diff --git a/code/__DEFINES/resonator_defines.dm b/code/__DEFINES/resonator_defines.dm
new file mode 100644
index 00000000000..b6a4b897d26
--- /dev/null
+++ b/code/__DEFINES/resonator_defines.dm
@@ -0,0 +1,3 @@
+#define RESONATOR_MODE_AUTO 1
+#define RESONATOR_MODE_MANUAL 2
+#define RESONATOR_MODE_MATRIX 3
diff --git a/code/modules/mining/equipment/resonator.dm b/code/modules/mining/equipment/resonator.dm
index 6c94015d9a5..ba80370b261 100644
--- a/code/modules/mining/equipment/resonator.dm
+++ b/code/modules/mining/equipment/resonator.dm
@@ -9,42 +9,60 @@
w_class = WEIGHT_CLASS_NORMAL
force = 15
throwforce = 10
- var/burst_time = 30
- var/fieldlimit = 4
- var/list/fields = list()
+
+ /// the mode of the resonator; has three modes: auto (1), manual (2), and matrix (3)
+ var/mode = RESONATOR_MODE_AUTO
+ /// How efficient it is in manual mode. Yes, we lower the damage cuz it's gonna be used for mobhunt
var/quick_burst_mod = 0.8
+ /// the number of fields the resonator is allowed to have at once
+ var/fieldlimit = 4
+ /// the list of currently active fields from this resonator
+ var/list/fields = list()
+ /// the number that is added to the failure_prob, which is the probability of whether it will spread or not
+ var/adding_failure = 50
+
+/obj/item/resonator/attack_self(mob/user)
+ if(mode == RESONATOR_MODE_AUTO)
+ to_chat(user, "You set the [name]'s fields to detonate only after you hit it with [src].")
+ mode = RESONATOR_MODE_MANUAL
+ else
+ to_chat(user, "You set [src]'s fields to detonate after 2 seconds.")
+ mode = RESONATOR_MODE_AUTO
/obj/item/resonator/upgraded
name = "upgraded resonator"
- desc = "An upgraded version of the resonator that can produce more fields at once."
+ desc = "An upgraded version of the resonator that can produce more fields at once, as well as having no damage penalty for bursting a resonance field early. It also allows you to set 'Resonance matrixes', that detonate after someone (or something) walks over it."
icon_state = "resonator_u"
origin_tech = "materials=4;powerstorage=3;engineering=3;magnets=3"
fieldlimit = 6
quick_burst_mod = 1
-/obj/item/resonator/attack_self(mob/user)
- if(burst_time == 50)
- burst_time = 30
- to_chat(user, "You set the resonator's fields to detonate after 3 seconds.")
+/obj/item/resonator/upgraded/attack_self(mob/user)
+ if(mode == RESONATOR_MODE_AUTO)
+ to_chat(user, "You set [src]'s fields to detonate only after being attacked by [src].")
+ mode = RESONATOR_MODE_MANUAL
+ else if(mode == RESONATOR_MODE_MANUAL)
+ to_chat(user, "You set [src]'s fields to work as matrix traps.")
+ mode = RESONATOR_MODE_MATRIX
else
- burst_time = 50
- to_chat(user, "You set the resonator's fields to detonate after 5 seconds.")
+ to_chat(user, "You set [src]'s fields to detonate automatically after 2 seconds.")
+ mode = RESONATOR_MODE_AUTO
-/obj/item/resonator/proc/CreateResonance(target, mob/user)
- var/turf/T = get_turf(target)
- var/obj/effect/temp_visual/resonance/R = locate(/obj/effect/temp_visual/resonance) in T
- if(R)
- R.damage_multiplier = quick_burst_mod
- R.burst()
+/obj/item/resonator/proc/create_resonance(target, mob/user)
+ var/turf/target_turf = get_turf(target)
+ var/obj/effect/temp_visual/resonance/resonance_field = locate(/obj/effect/temp_visual/resonance) in target_turf
+ if(resonance_field)
+ resonance_field.damage_multiplier = quick_burst_mod
+ resonance_field.burst()
return
if(LAZYLEN(fields) < fieldlimit)
- new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
+ new /obj/effect/temp_visual/resonance(target_turf, user, src, mode, adding_failure)
user.changeNext_move(CLICK_CD_MELEE)
/obj/item/resonator/pre_attack(atom/target, mob/user, params)
- if(check_allowed_items(target, 1))
- CreateResonance(target, user)
- return TRUE
+ if(check_allowed_items(target, not_inside = TRUE))
+ create_resonance(target, user)
+ return ..()
//resonance field, crushes rock, damages mobs
/obj/effect/temp_visual/resonance
@@ -53,31 +71,48 @@
icon = 'icons/effects/effects.dmi'
icon_state = "shield1"
layer = ABOVE_ALL_MOB_LAYER
- duration = 50
+ duration = 60 SECONDS
+ /// the amount of damage living beings will take whilst inside the field during its burst
var/resonance_damage = 20
+ /// the modifier to resonance_damage; affected by the quick_burst_mod from the resonator
var/damage_multiplier = 1
- var/creator
- var/obj/item/resonator/res
+ /// the parent creator (user) of this field
+ var/mob/creator
+ /// the parent resonator of this field
+ var/obj/item/resonator/parent_resonator
+ /// whether the field is rupturing currently or not (to prevent recursion)
+ var/rupturing = FALSE
+ /// the probability that the field will not be able to spread
+ var/failure_prob = 0
+ /// the number that is added to the failure_prob. Will default to 50
+ var/adding_failure
-/obj/effect/temp_visual/resonance/New(loc, set_creator, set_resonator, set_duration)
- duration = set_duration
+/obj/effect/temp_visual/resonance/Initialize(mapload, set_creator, set_resonator, mode, set_failure = 50)
+ if(mode == RESONATOR_MODE_AUTO)
+ duration = 2 SECONDS
+ if(mode == RESONATOR_MODE_MATRIX)
+ icon_state = "shield2"
+ name = "resonance matrix"
+ RegisterSignal(src, COMSIG_MOVABLE_CROSSED, PROC_REF(burst))
. = ..()
creator = set_creator
- res = set_resonator
- if(res)
- res.fields += src
- playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
- transform = matrix() * 0.75
- animate(src, transform = matrix() * 1.5, time = duration)
+ parent_resonator = set_resonator
+ if(parent_resonator)
+ parent_resonator.fields += src
+ adding_failure = set_failure
+ playsound(src, 'sound/weapons/resonator_blast.ogg', 50, TRUE)
+ if(mode == RESONATOR_MODE_AUTO)
+ transform = matrix() * 0.75
+ animate(src, transform = matrix() * 1.5, time = duration)
deltimer(timerid)
timerid = addtimer(CALLBACK(src, PROC_REF(burst)), duration, TIMER_STOPPABLE)
/obj/effect/temp_visual/resonance/Destroy()
- if(res)
- res.fields -= src
- res = null
+ if(parent_resonator)
+ parent_resonator.fields -= src
+ parent_resonator = null
creator = null
- return ..()
+ . = ..()
/obj/effect/temp_visual/resonance/proc/check_pressure(turf/proj_turf)
if(!proj_turf)
@@ -91,21 +126,33 @@
resonance_damage *= damage_multiplier
/obj/effect/temp_visual/resonance/proc/burst()
- var/turf/T = get_turf(src)
- new /obj/effect/temp_visual/resonance_crush(T)
- if(ismineralturf(T))
- if(is_ancient_rock(T))
- visible_message("This rock appears to be resistant to all mining tools except pickaxes!")
- else
- var/turf/simulated/mineral/M = T
- M.gets_drilled(creator)
- check_pressure(T)
- playsound(T,'sound/weapons/resonator_blast.ogg',50,1)
- for(var/mob/living/L in T)
+ SIGNAL_HANDLER // COMSIG_MOVABLE_CROSSED
+ if(rupturing)
+ return
+ rupturing = TRUE
+ var/turf/src_turf = get_turf(src)
+ new /obj/effect/temp_visual/resonance_crush(src_turf)
+ if(ismineralturf(src_turf))
+ var/turf/simulated/mineral/mineral_turf = src_turf
+ mineral_turf.gets_drilled(creator)
+ check_pressure(src_turf)
+ playsound(src_turf, 'sound/weapons/resonator_blast.ogg', 50, TRUE)
+ for(var/mob/living/attacked_living in src_turf)
if(creator)
- add_attack_logs(creator, L, "Resonance field'ed")
- to_chat(L, "[src] ruptured with you in it!")
- L.apply_damage(resonance_damage, BRUTE)
+ log_attack(creator, attacked_living, "used a resonator field on", "resonator")
+ to_chat(attacked_living, "[src] ruptured with you in it!")
+ attacked_living.apply_damage(resonance_damage, BRUTE)
+ for(var/obj/effect/temp_visual/resonance/field in orange(1, src))
+ if(field.rupturing)
+ continue
+ if(parent_resonator.mode == RESONATOR_MODE_AUTO || parent_resonator.mode == RESONATOR_MODE_MANUAL)
+ field.burst()
+ if(!prob(failure_prob) && parent_resonator)
+ for(var/turf/simulated/mineral/mineral_spread in orange(1, src))
+ if(locate(/obj/effect/temp_visual/resonance) in mineral_spread)
+ continue
+ var/obj/effect/temp_visual/resonance/new_field = new(mineral_spread, creator, parent_resonator, parent_resonator.mode)
+ new_field.failure_prob = failure_prob + adding_failure
qdel(src)
/obj/effect/temp_visual/resonance_crush
@@ -113,7 +160,7 @@
layer = ABOVE_ALL_MOB_LAYER
duration = 4
-/obj/effect/temp_visual/resonance_crush/New()
- ..()
- transform = matrix()*1.5
+/obj/effect/temp_visual/resonance_crush/Initialize(mapload)
+ . = ..()
+ transform = matrix() * 1.5
animate(src, transform = matrix() * 0.1, alpha = 50, time = 4)
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 5b22c551ca5..a5a8f66f953 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -538,7 +538,7 @@
R.damage_multiplier = modifier
R.burst()
return
- new /obj/effect/temp_visual/resonance(target_turf, K.firer, null, 30)
+ new /obj/effect/temp_visual/resonance(target_turf, K.firer, null, RESONATOR_MODE_MANUAL, 100) //manual detonate mode and will NOT spread
/obj/item/borg/upgrade/modkit/bounty
name = "death syphon"
diff --git a/paradise.dme b/paradise.dme
index a20ea022411..ddaee141df4 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -109,6 +109,7 @@
#include "code\__DEFINES\reagents_defines.dm"
#include "code\__DEFINES\regex.dm"
#include "code\__DEFINES\revolution_defines.dm"
+#include "code\__DEFINES\resonator_defines.dm"
#include "code\__DEFINES\role_preferences.dm"
#include "code\__DEFINES\rolebans.dm"
#include "code\__DEFINES\rust.dm"