diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 8e0886a30d..42e630a75e 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -323,6 +323,7 @@ #define ABDUCTOR_ANTAGONIST "abductor-antagonist" #define MADE_UNCLONEABLE "made-uncloneable" #define TIMESTOP_TRAIT "timestop" +#define DOMAIN_TRAIT "domain" #define NUKEOP_TRAIT "nuke-op" #define CLOWNOP_TRAIT "clown-op" #define MEGAFAUNA_TRAIT "megafauna" diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index bb39da381b..1c25cde286 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -511,9 +511,25 @@ /datum/status_effect/eldritch/void/on_effect() var/turf/open/turfie = get_turf(owner) turfie.TakeTemperature(-40) - owner.adjust_bodytemperature(-20) + owner.adjust_bodytemperature(-60) return ..() +/datum/status_effect/domain + id = "domain" + alert_type = null + var/movespeed_mod = /datum/movespeed_modifier/status_effect/domain + +/datum/status_effect/domain/on_creation(mob/living/new_owner, set_duration) + if(isliving(owner)) + var/mob/living/carbon/C = owner + C.add_movespeed_modifier(movespeed_mod) + +/datum/status_effect/electrode/on_remove() + if(isliving(owner)) + var/mob/living/carbon/C = owner + C.remove_movespeed_modifier(movespeed_mod) + . = ..() + /datum/status_effect/corrosion_curse id = "corrosion_curse" status_type = STATUS_EFFECT_REPLACE diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm index ce118c1cc9..ca65fd9afb 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm @@ -250,7 +250,8 @@ var/obj/item/bodypart/bodypart = pick(target.bodyparts) var/datum/wound/slash/critical/crit_wound = new crit_wound.apply_wound(bodypart) - target.adjustFireLoss(20) + crit_wound.apply_wound(bodypart) + target.adjustBruteLoss(20) new /obj/effect/temp_visual/cleave(target.drop_location()) /obj/effect/proc_holder/spell/pointed/cleave/can_target(atom/target, mob/user, silent) @@ -897,7 +898,7 @@ /obj/effect/proc_holder/spell/pointed/boogie_woogie/cast(list/targets, mob/user) . = ..() var/target = targets[1] - playsound(user, 'sound/magic/voidclap.ogg', 75, TRUE) + user.emote("clap1") playsound(user, 'sound/magic/voidblink.ogg', 75, TRUE) var/turf/targeted_turf = get_turf(target) var/turf/user_turf = get_turf(user) @@ -936,3 +937,31 @@ /obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch/cast(list/targets,mob/user = usr) user.emote("snap") ..(targets, user, 60) + +/obj/effect/proc_holder/spell/aoe_turf/domain_expansion + name = "Infinite Void" + desc = "Create a domain that will slow down and mark all opponents with a void mark." + charge_max = 1200 + clothes_req = FALSE + invocation = "RYO'IKI TEN'KAI" + invocation_type = "none" + range = 0 + action_icon_state = "time" + action_background_icon_state = "bg_ecult" + var/timestop_range = 7 + var/timestop_duration = 200 + var/static/mutable_appearance/halo + var/sound/Snd // shamelessly ripped from lightning. + +/obj/effect/proc_holder/spell/aoe_turf/domain_expansion/cast(list/targets, mob/user = usr) + user.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/domain) + Snd = new/sound('sound/magic/clockwork/ratvar_attack.ogg',channel = 7) + halo = halo || mutable_appearance('icons/effects/effects.dmi', "shield-flash", EFFECTS_LAYER) + user.add_overlay(halo) + playsound(get_turf(user), Snd, 50, 0) + if(do_mob(user,user,50,1)) + playsound(user, 'sound/magic/domain.ogg', 125, TRUE) + user.say("DOM'ENO ISPLET'IMAS") + user.emote("clap1") + user.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/domain) + new /obj/effect/domain_expansion(get_turf(user), timestop_range, timestop_duration, list(user)) \ No newline at end of file diff --git a/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm index 3be4908b01..5450caf10c 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm @@ -127,8 +127,6 @@ /datum/eldritch_knowledge/void_blade_upgrade/on_ranged_attack_eldritch_blade(atom/target, mob/user, click_parameters) . = ..() - if(!ishuman(target) || !iscarbon(user)) - return var/mob/living/carbon/carbon_human = user var/mob/living/carbon/human/human_target = target var/datum/status_effect/eldritch/effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh) || human_target.has_status_effect(/datum/status_effect/eldritch/void) @@ -137,7 +135,7 @@ var/dir = angle2dir(dir2angle(get_dir(user,human_target))+180) carbon_human.forceMove(get_step(human_target,dir)) var/obj/item/melee/sickly_blade/blade = carbon_human.get_active_held_item() - blade.melee_attack_chain(carbon_human,human_target) + blade.melee_attack_chain(carbon_human,human_target,attackchain_flags = ATTACK_IGNORE_CLICKDELAY) /datum/eldritch_knowledge/spell/voidpull name = "Void Pull" @@ -154,15 +152,15 @@ desc = "With the clap of your hands, you can swap your position with someone within your vision." cost = 2 spell_to_add = /obj/effect/proc_holder/spell/pointed/boogie_woogie - next_knowledge = list(/datum/eldritch_knowledge/spell/infinity) + next_knowledge = list(/datum/eldritch_knowledge/spell/domain_expansion) route = PATH_VOID -/datum/eldritch_knowledge/spell/infinity - name = "Void's Push" - gain_text = "With the snap of my fingers, they do as I please." - desc = "With the snap of your fingers, send your enemies away." +/datum/eldritch_knowledge/spell/domain_expansion + name = "Infinite Void" + gain_text = "This world will be my stage, and nothing will be out of my reach." + desc = "Gain the ability to mark a 7x7 area as your domain after a short delay. Creatures in your domain are slowed and branded with a void mark, allowing you to quickly teleport to them and slash them, further inhibiting their ability to move." cost = 2 - spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch + spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/domain_expansion next_knowledge = list(/datum/eldritch_knowledge/final/void_final) route = PATH_VOID @@ -180,6 +178,7 @@ /datum/eldritch_knowledge/final/void_final/on_finished_recipe(mob/living/user, list/atoms, loc) var/mob/living/carbon/human/H = user + user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch) H.physiology.brute_mod *= 0.5 H.physiology.burn_mod *= 0.5 ADD_TRAIT(H, TRAIT_RESISTLOWPRESSURE, MAGIC_TRAIT) diff --git a/code/modules/fields/infinite_void.dm b/code/modules/fields/infinite_void.dm new file mode 100644 index 0000000000..8a60976b43 --- /dev/null +++ b/code/modules/fields/infinite_void.dm @@ -0,0 +1,169 @@ + +/obj/effect/domain_expansion + anchored = TRUE + name = "infinite void" + desc = "Once inside, the user's cursed techniques are improved and cannot be avoided." + layer = FLY_LAYER + pixel_x = -64 + pixel_y = -64 + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + var/list/immune = list() // the one who creates the domain_expansion is immune, which includes wizards and the dead slime you murdered to make this chronofield + var/turf/target + var/freezerange = 2 + var/duration = 140 + var/datum/proximity_monitor/advanced/domain_expansion/chronofield + alpha = 125 + var/check_anti_magic = FALSE + var/check_holy = FALSE + +/obj/effect/domain_expansion/Initialize(mapload, radius, time, list/immune_atoms, start = TRUE) //Immune atoms assoc list atom = TRUE + . = ..() + if(!isnull(time)) + duration = time + if(!isnull(radius)) + freezerange = radius + for(var/A in immune_atoms) + immune[A] = TRUE + for(var/mob/living/L in GLOB.player_list) + if(locate(/obj/effect/proc_holder/spell/aoe_turf/domain_expansion) in L.mind.spell_list) //People who can stop time are immune to its effects + immune[L] = TRUE + for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.parasites) + if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/domain_expansion) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune. + immune[G] = TRUE + if(start) + INVOKE_ASYNC(src, .proc/domain_expansion) + +/obj/effect/domain_expansion/Destroy() + qdel(chronofield) + return ..() + +/obj/effect/domain_expansion/proc/domain_expansion() + target = get_turf(src) + chronofield = make_field(/datum/proximity_monitor/advanced/domain_expansion, list("current_range" = freezerange, "host" = src, "immune" = immune, "check_anti_magic" = check_anti_magic, "check_holy" = check_holy)) + QDEL_IN(src, duration) + +/obj/effect/domain_expansion/magic + check_anti_magic = TRUE + +/datum/proximity_monitor/advanced/domain_expansion + name = "chronofield" + setup_field_turfs = TRUE + field_shape = FIELD_SHAPE_RADIUS_SQUARE + requires_processing = TRUE + var/list/immune = list() + var/list/frozen_things = list() + var/list/frozen_mobs = list() //cached separately for processing + var/list/frozen_structures = list() //Also machinery, and only frozen aestethically + var/list/frozen_turfs = list() //Only aesthetically + var/check_anti_magic = FALSE + var/check_holy = FALSE + + var/static/list/global_frozen_atoms = list() + +/datum/proximity_monitor/advanced/domain_expansion/Destroy() + unfreeze_all() + return ..() + +/datum/proximity_monitor/advanced/domain_expansion/field_turf_crossed(atom/movable/AM) + freeze_atom(AM) + +/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_atom(atom/movable/A) + if(immune[A] || global_frozen_atoms[A] || !istype(A)) + return FALSE + if(ismob(A)) + var/mob/M = A + if(M.anti_magic_check(check_anti_magic, check_holy)) + immune[A] = TRUE + return + var/frozen = TRUE + if(isliving(A)) + freeze_mob(A) + else if((ismachinery(A) && !istype(A, /obj/machinery/light)) || isstructure(A)) //Special exception for light fixtures since recoloring causes them to change light + freeze_structure(A) + else + frozen = FALSE + if(A.throwing) + freeze_throwing(A) + frozen = TRUE + if(!frozen) + return + + frozen_things[A] = A.move_resist + A.move_resist = INFINITY + global_frozen_atoms[A] = src + into_the_negative_zone(A) + RegisterSignal(A, COMSIG_MOVABLE_PRE_MOVE, .proc/unfreeze_atom) + RegisterSignal(A, COMSIG_ITEM_PICKUP, .proc/unfreeze_atom) + + return TRUE + +/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_all() + for(var/i in frozen_things) + unfreeze_atom(i) + for(var/T in frozen_turfs) + unfreeze_turf(T) + +/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_atom(atom/movable/A) + SIGNAL_HANDLER + + if(A.throwing) + unfreeze_throwing(A) + if(isliving(A)) + unfreeze_mob(A) + + UnregisterSignal(A, COMSIG_MOVABLE_PRE_MOVE) + UnregisterSignal(A, COMSIG_ITEM_PICKUP) + escape_the_negative_zone(A) + A.move_resist = frozen_things[A] + frozen_things -= A + global_frozen_atoms -= A + +/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_throwing(atom/movable/AM) + var/datum/thrownthing/T = AM.throwing + T.paused = TRUE + +/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_throwing(atom/movable/AM) + var/datum/thrownthing/T = AM.throwing + if(T) + T.paused = FALSE + +/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_turf(turf/T) + into_the_negative_zone(T) + frozen_turfs += T + +/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_turf(turf/T) + escape_the_negative_zone(T) + +/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_structure(obj/O) + into_the_negative_zone(O) + frozen_structures += O + +/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_structure(obj/O) + escape_the_negative_zone(O) + +/datum/proximity_monitor/advanced/domain_expansion/process() + for(var/i in frozen_mobs) + var/mob/living/m = i + m.apply_status_effect(/datum/status_effect/eldritch/void) + +/datum/proximity_monitor/advanced/domain_expansion/setup_field_turf(turf/T) + for(var/i in T.contents) + freeze_atom(i) + freeze_turf(T) + return ..() + +/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_mob(mob/living/L) + frozen_mobs += L + L.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/domain) + +/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_mob(mob/living/L) + L.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/domain) + frozen_mobs -= L + +//you don't look quite right, is something the matter? +/datum/proximity_monitor/advanced/domain_expansion/proc/into_the_negative_zone(atom/A) + A.add_atom_colour(list(-0.6,0,0,0, 0,-0.6,0,0, 0,0,-1,0, 0,0,0,1, 0.5,0.5,1,0), TEMPORARY_COLOUR_PRIORITY) + +//let's put some colour back into your cheeks +/datum/proximity_monitor/advanced/domain_expansion/proc/escape_the_negative_zone(atom/A) + A.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm index 4c710cb483..e0afce13ed 100644 --- a/code/modules/movespeed/modifiers/status_effects.dm +++ b/code/modules/movespeed/modifiers/status_effects.dm @@ -21,6 +21,9 @@ multiplicative_slowdown = 1.5 priority = 50 +/datum/movespeed_modifier/status_effect/domain + multiplicative_slowdown = 1.5 + /datum/movespeed_modifier/status_effect/tased/no_combat_mode multiplicative_slowdown = 8 priority = 100 diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm index a9334ca923..318dd027b1 100644 --- a/modular_citadel/code/modules/mob/cit_emotes.dm +++ b/modular_citadel/code/modules/mob/cit_emotes.dm @@ -321,3 +321,16 @@ else sound = pick('modular_citadel/sound/voice/human_female_pain_1.ogg', 'modular_citadel/sound/voice/human_female_pain_2.ogg', 'modular_citadel/sound/voice/human_female_pain_3.ogg', 'modular_citadel/sound/voice/human_female_scream_2.ogg', 'modular_citadel/sound/voice/human_female_scream_3.ogg', 'modular_citadel/sound/voice/human_female_scream_4.ogg') playsound(user, sound, 50, 0, 0) + +/datum/emote/living/clap1 + key = "clap1" + key_third_person = "claps" + message = "claps their hands together." + emote_type = EMOTE_AUDIBLE + muzzle_ignore = TRUE + restraint_check = TRUE + +/datum/emote/living/clap1/run_emote(mob/living/user, params) + if(!(. = ..())) + return + playsound(user, 'modular_citadel/sound/voice/clap.ogg', 50, 1, -1) \ No newline at end of file diff --git a/modular_citadel/sound/voice/clap.ogg b/modular_citadel/sound/voice/clap.ogg new file mode 100644 index 0000000000..03c4bdd392 Binary files /dev/null and b/modular_citadel/sound/voice/clap.ogg differ diff --git a/sound/magic/domain.ogg b/sound/magic/domain.ogg new file mode 100644 index 0000000000..d9398790cf Binary files /dev/null and b/sound/magic/domain.ogg differ diff --git a/tgstation.dme b/tgstation.dme index d8ad93d90c..ef83dd4a47 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2099,6 +2099,7 @@ #include "code\modules\events\wizard\summons.dm" #include "code\modules\fields\fields.dm" #include "code\modules\fields\gravity.dm" +#include "code\modules\fields\infinite_void.dm" #include "code\modules\fields\peaceborg_dampener.dm" #include "code\modules\fields\timestop.dm" #include "code\modules\fields\turf_objects.dm"