diff --git a/code/game/objects/effects/temporary_visuals/clockcult.dm b/code/game/objects/effects/temporary_visuals/clockcult.dm index 59c4e23283..9a236c00c3 100644 --- a/code/game/objects/effects/temporary_visuals/clockcult.dm +++ b/code/game/objects/effects/temporary_visuals/clockcult.dm @@ -95,6 +95,56 @@ icon_state = "warden_gaze" duration = 3 +/obj/effect/temp_visual/ratvar/volt_hit + name = "volt blast" + layer = ABOVE_MOB_LAYER + duration = 8 + icon_state = "volt_hit" + light_range = 1.5 + light_power = 2 + light_color = LIGHT_COLOR_ORANGE + var/mob/user + var/damage = 20 + +/obj/effect/temp_visual/ratvar/volt_hit/Initialize(mapload, caster) + . = ..() + user = caster + if(user) + var/matrix/M = new + M.Turn(Get_Angle(src, user)) + transform = M + INVOKE_ASYNC(src, .proc/volthit) + +/obj/effect/temp_visual/ratvar/volt_hit/proc/volthit() + if(user) + Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray) + var/hit_amount = 0 + var/turf/T = get_turf(src) + for(var/mob/living/L in T) + if(is_servant_of_ratvar(L)) + continue + var/obj/item/I = L.anti_magic_check() + if(I) + L.visible_message("Strange energy flows into [L]'s [I.name]!", \ + "Your [I.name] shields you from [src]!") + continue + L.visible_message("[L] is struck by a [name]!", "You're struck by a [name]!") + L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!")) + log_combat(user, L, "struck with a volt blast") + hit_amount++ + for(var/obj/mecha/M in T) + if(M.occupant) + if(is_servant_of_ratvar(M.occupant)) + continue + to_chat(M.occupant, "Your [M.name] is struck by a [name]!") + M.visible_message("[M] is struck by a [name]!") + M.take_damage(damage, BURN, 0, 0) + hit_amount++ + if(hit_amount) + playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1) + else + playsound(src, "sparks", 50, 1) + /obj/effect/temp_visual/ratvar/ocular_warden/Initialize() . = ..() pixel_x = rand(-8, 8) diff --git a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm index de2e85a501..81ad7ddc26 100644 --- a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm +++ b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm @@ -135,6 +135,29 @@ return TRUE +//For the Volt Void scripture, fires a ray of energy at a target location +/obj/effect/proc_holder/slab/volt + ranged_mousepointer = 'icons/effects/volt_target.dmi' + +/obj/effect/proc_holder/slab/volt/InterceptClickOn(mob/living/caller, params, atom/target) + if(target == slab || ..()) //we can't cancel + return TRUE + + var/turf/T = ranged_ability_user.loc + if(!isturf(T)) + return TRUE + + if(target in view(7, get_turf(ranged_ability_user))) + successful = TRUE + ranged_ability_user.visible_message("[ranged_ability_user] fires a ray of energy at [target]!", "You fire a volt ray at [target].") + playsound(ranged_ability_user, 'sound/effects/light_flicker.ogg', 50, 1) + T = get_turf(target) + new/obj/effect/temp_visual/ratvar/volt_hit(T, ranged_ability_user) + log_combat(ranged_ability_user, T, "fired a volt ray") + remove_ranged_ability() + + return TRUE + //For the Kindle scripture; stuns and mutes a target non-servant. /obj/effect/proc_holder/slab/kindle ranged_mousepointer = 'icons/effects/volt_target.dmi' diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm index c40168a986..9d5118e393 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm @@ -263,3 +263,160 @@ duration = max(duration, 100) return slab.procure_gateway(invoker, duration, portal_uses) + +//Mending Mantra: Channeled for up to ten times over twenty seconds to repair structures and heal allies +/datum/clockwork_scripture/channeled/mending_mantra + descname = "Channeled, Area Healing and Repair" + name = "Mending Mantra" + desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed. Channeled every two seconds for a maximum of twenty seconds." + chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!") + chant_amount = 10 + chant_interval = 20 + power_cost = 400 + usage_tip = "This is a very effective way to rapidly reinforce a base after an attack." + tier = SCRIPTURE_SCRIPT + primary_component = VANGUARD_COGWHEEL + sort_priority = 7 + quickbind = TRUE + quickbind_desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed.
Maximum 10 chants." + var/heal_attempts = 4 + var/heal_amount = 2.5 + var/static/list/damage_heal_order = list(BRUTE, BURN, OXY) + var/static/list/heal_finish_messages = list("There, all mended!", "Try not to get too damaged.", "No more dents and scratches for you!", "Champions never die.", "All patched up.", \ + "Ah, child, it's okay now.", "Pain is temporary.", "What you do for the Justiciar is eternal.", "Bear this for me.", "Be strong, child.", "Please, be careful!", \ + "If you die, you will be remembered.") + var/static/list/heal_target_typecache = typecacheof(list( + /obj/structure/destructible/clockwork, + /obj/machinery/door/airlock/clockwork, + /obj/machinery/door/window/clockwork, + /obj/structure/window/reinforced/clockwork, + /obj/structure/table/reinforced/brass)) + var/static/list/ratvarian_armor_typecache = typecacheof(list( + /obj/item/clothing/suit/armor/clockwork, + /obj/item/clothing/head/helmet/clockwork, + /obj/item/clothing/gloves/clockwork, + /obj/item/clothing/shoes/clockwork)) + +/datum/clockwork_scripture/channeled/mending_mantra/chant_effects(chant_number) + var/turf/T + for(var/atom/movable/M in range(7, invoker)) + if(isliving(M)) + if(isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab)) + var/mob/living/simple_animal/S = M + if(S.health == S.maxHealth || S.stat == DEAD) + continue + T = get_turf(M) + for(var/i in 1 to heal_attempts) + if(S.health < S.maxHealth) + S.adjustHealth(-heal_amount) + new /obj/effect/temp_visual/heal(T, "#1E8CE1") + if(i == heal_attempts && S.health >= S.maxHealth) //we finished healing on the last tick, give them the message + to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"") + break + else + to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"") + break + else if(issilicon(M)) + var/mob/living/silicon/S = M + if(S.health == S.maxHealth || S.stat == DEAD || !is_servant_of_ratvar(S)) + continue + T = get_turf(M) + for(var/i in 1 to heal_attempts) + if(S.health < S.maxHealth) + S.heal_ordered_damage(heal_amount, damage_heal_order) + new /obj/effect/temp_visual/heal(T, "#1E8CE1") + if(i == heal_attempts && S.health >= S.maxHealth) + to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"") + break + else + to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"") + break + else if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.health == H.maxHealth || H.stat == DEAD || !is_servant_of_ratvar(H)) + continue + T = get_turf(M) + var/heal_ticks = 0 //one heal tick for each piece of ratvarian armor worn + var/obj/item/I = H.get_item_by_slot(SLOT_WEAR_SUIT) + if(is_type_in_typecache(I, ratvarian_armor_typecache)) + heal_ticks++ + I = H.get_item_by_slot(SLOT_HEAD) + if(is_type_in_typecache(I, ratvarian_armor_typecache)) + heal_ticks++ + I = H.get_item_by_slot(SLOT_GLOVES) + if(is_type_in_typecache(I, ratvarian_armor_typecache)) + heal_ticks++ + I = H.get_item_by_slot(SLOT_SHOES) + if(is_type_in_typecache(I, ratvarian_armor_typecache)) + heal_ticks++ + if(heal_ticks) + for(var/i in 1 to heal_ticks) + if(H.health < H.maxHealth) + H.heal_ordered_damage(heal_amount, damage_heal_order) + new /obj/effect/temp_visual/heal(T, "#1E8CE1") + if(i == heal_ticks && H.health >= H.maxHealth) + to_chat(H, "\"[text2ratvar(pick(heal_finish_messages))]\"") + break + else + to_chat(H, "\"[text2ratvar(pick(heal_finish_messages))]\"") + break + else if(is_type_in_typecache(M, heal_target_typecache)) + var/obj/structure/destructible/clockwork/C = M + if(C.obj_integrity == C.max_integrity || (istype(C) && !C.can_be_repaired)) + continue + T = get_turf(M) + for(var/i in 1 to heal_attempts) + if(C.obj_integrity < C.max_integrity) + C.obj_integrity = min(C.obj_integrity + 5, C.max_integrity) + C.update_icon() + new /obj/effect/temp_visual/heal(T, "#1E8CE1") + else + break + new /obj/effect/temp_visual/ratvar/mending_mantra(get_turf(invoker)) + return TRUE + +//Volt Blaster: Channeled for up to five times over ten seconds to fire up to five rays of energy at target locations. +/datum/clockwork_scripture/channeled/volt_blaster + descname = "Channeled, Targeted Energy Blasts" + name = "Volt Blaster" + desc = "Allows you to fire five energy rays at target locations. Channeled every fourth of a second for a maximum of ten seconds." + channel_time = 30 + invocations = list("Amperage...", "...grant me your power!") + chant_invocations = list("Use charge to kill!", "Slay with power!", "Hunt with energy!") + chant_amount = 5 + chant_interval = 4 + power_cost = 500 + usage_tip = "Though it requires you to stand still, this scripture can do massive damage." + tier = SCRIPTURE_SCRIPT + primary_component = HIEROPHANT_ANSIBLE + sort_priority = 10 + quickbind = TRUE + quickbind_desc = "Allows you to fire energy rays at target locations.
Maximum 5 chants." + var/static/list/nzcrentr_insults = list("You're not very good at aiming.", "You hunt badly.", "What a waste of energy.", "Almost funny to watch.", + "Boss says \"Click something, you idiot!\".", "Stop wasting power if you can't aim.") + +/datum/clockwork_scripture/channeled/volt_blaster/chant_effects(chant_number) + slab.busy = null + var/datum/clockwork_scripture/ranged_ability/volt_ray/ray = new + ray.slab = slab + ray.invoker = invoker + var/turf/T = get_turf(invoker) + if(!ray.run_scripture() && slab && invoker) + if(can_recite() && T == get_turf(invoker)) + to_chat(invoker, "\"[text2ratvar(pick(nzcrentr_insults))]\"") + else + return FALSE + return TRUE + +/obj/effect/ebeam/volt_ray + name = "volt_ray" + layer = LYING_MOB_LAYER + +/datum/clockwork_scripture/ranged_ability/volt_ray + name = "Volt Ray" + slab_overlay = "volt" + allow_mobility = FALSE + ranged_type = /obj/effect/proc_holder/slab/volt + ranged_message = "You charge the clockwork slab with shocking might.\n\ + Left-click a target to fire, quickly!" + timeout_time = 20