diff --git a/code/__defines/misc_ch.dm b/code/__defines/misc_ch.dm
index 20f63270a8..58f0f9ac4d 100644
--- a/code/__defines/misc_ch.dm
+++ b/code/__defines/misc_ch.dm
@@ -22,4 +22,13 @@
#define RCD_FRAME "Frame" // Build a Machine or Computer frame
#define RCD_WALLFRAME "WallFrame" // Build a selection of wall frames
#define RCD_CONVEYOR "Conveyor" // Build direction conveyors
-#define RCD_TURRET "Turret" // Build turrets when emagged
\ No newline at end of file
+#define RCD_TURRET "Turret" // Build turrets when emagged
+
+
+#define VANTAG_VORE_YE "vantag_vore_ye"
+#define VANTAG_VORE_YD "vantag_vore_yd"
+#define VANTAG_VORE_YA "vantag_vore_ya"
+#define VANTAG_VORE_D "vantag_vore_d"
+#define VANTAG_VORE_DE "vantag_vore_de"
+#define VANTAG_VORE_DD "vantag_vore_dd"
+#define VANTAG_VORE_DA "vantag_vore_da"
\ No newline at end of file
diff --git a/code/_helpers/_lists.dm b/code/_helpers/_lists.dm
index 76299d4879..ba29d57b8b 100644
--- a/code/_helpers/_lists.dm
+++ b/code/_helpers/_lists.dm
@@ -881,3 +881,21 @@ var/global/list/json_cache = list()
else
used_key_list[input_key] = 1
return input_key
+
+//CHOMPAdd start
+/proc/pick_weight(list/list_to_pick)
+ var/total = 0
+ var/item
+ for(item in list_to_pick)
+ if(!list_to_pick[item])
+ list_to_pick[item] = 0
+ total += list_to_pick[item]
+
+ total = rand(1, total)
+ for(item in list_to_pick)
+ total -= list_to_pick[item]
+ if(total <= 0 && list_to_pick[item])
+ return item
+
+ return null
+//CHOMPAdd end
\ No newline at end of file
diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm
index f47b384b97..0b3c134537 100644
--- a/code/_helpers/global_lists_vr.dm
+++ b/code/_helpers/global_lists_vr.dm
@@ -34,11 +34,20 @@ var/global/list/player_sizes_list = list(
"Tiny" = RESIZE_TINY)
//stores vantag settings indexed by name
+//CHOMPEdit start - expanding the vore hud list
var/global/list/vantag_choices_list = list(
VANTAG_NONE = "No Involvement",
- VANTAG_VORE = "Be Prey",
+ VANTAG_VORE = "Be Prey (Any)",
+ VANTAG_VORE_YE = "Be Prey (Endo)",
+ VANTAG_VORE_YD = "Be Prey (Digestion)",
+ VANTAG_VORE_YA = "Be Prey (Absorption)",
+ VANTAG_VORE_D = "Be Pred (Any)",
+ VANTAG_VORE_DE = "Be Pred (Endo)",
+ VANTAG_VORE_DD = "Be Pred (Digestion)",
+ VANTAG_VORE_DA = "Be Pred (Absorption)",
VANTAG_KIDNAP = "Be Kidnapped",
VANTAG_KILL = "Be Killed")
+//CHOMPEdit end
//Blacklist to exclude items from object ingestion. Digestion blacklist located in digest_act_vr.dm
var/global/list/item_vore_blacklist = list(
diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm
index 781a76f20f..559a6a65d3 100644
--- a/code/datums/components/_component.dm
+++ b/code/datums/components/_component.dm
@@ -208,6 +208,13 @@
signal_enabled = TRUE
+//CHOMPAdd start
+/// Registers multiple signals to the same proc.
+/datum/proc/RegisterSignals(datum/target, list/signal_types, proctype, override = FALSE)
+ for (var/signal_type in signal_types)
+ RegisterSignal(target, signal_type, proctype, override)
+//CHOMPAdd end
+
/**
* Stop listening to a given signal from target
*
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 25806f9e0c..a4d450f67f 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -238,7 +238,7 @@
for (var/datum/light_source/light as anything in light_sources) // Cycle through the light sources on this atom and tell them to update.
light.source_atom.update_light()
- SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, old_loc, direction)
+ //SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, old_loc, direction) CHOMPEdit - Why was this comsig here twice?
return TRUE
diff --git a/code/game/objects/items/devices/radio/headset_ch.dm b/code/game/objects/items/devices/radio/headset_ch.dm
deleted file mode 100644
index b659ae7381..0000000000
--- a/code/game/objects/items/devices/radio/headset_ch.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/obj/item/device/radio/headset/casino
- name = "radio headset"
- desc = "An updated, modular intercom that fits over the head with extra comfortable for the hardworking casino luxury crew. Has encryption key for scamm-... Kind casino staff channel."
- icon = 'icons/obj/casino_ch.dmi'
- icon_state = "headset"
- origin_tech = list(TECH_ILLEGAL = 2)
- ks1type = /obj/item/device/encryptionkey/raider
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/melee/shock_maul.dm b/code/game/objects/items/weapons/melee/shock_maul.dm
index 69896c885d..a692713ea7 100644
--- a/code/game/objects/items/weapons/melee/shock_maul.dm
+++ b/code/game/objects/items/weapons/melee/shock_maul.dm
@@ -217,12 +217,8 @@
/obj/item/weapon/melee/shock_maul/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity)
if(!proximity) return
..()
+ //CHOMPEdit start - maul changes
if(A && wielded && status)
- deductcharge()
- status = 0
- user.visible_message("\The [src] discharges with a thunderous, hair-raising crackle!")
- playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
- update_held_icon()
if(istype(A,/obj/structure/window))
var/obj/structure/window/W = A
visible_message("\The [W] crumples under the force of the impact!")
@@ -232,7 +228,22 @@
B.dismantle()
else if(istype(A,/obj/structure/grille))
qdel(A)
+ else if(istype(A, /turf/simulated/wall))
+ var/turf/simulated/wall/W = A
+ if(W.density)
+ W.take_damage(force*3) //One hit for regular walls, 3 hits for r_wall
+ else if(istype(A, /obj/structure/girder))
+ var/obj/structure/girder/G = A
+ G.dismantle()
+ else
+ return ..() //Don't do anything if we don't resolve anything on our target
+ deductcharge()
+ status = 0
+ user.visible_message("\The [src] discharges with a thunderous, hair-raising crackle!")
+ playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
+ update_held_icon()
powercheck(hitcost)
+ //CHOMPEdit end
/obj/item/weapon/melee/shock_maul/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
. = ..()
diff --git a/code/modules/ai/ai_holder_cooperation.dm b/code/modules/ai/ai_holder_cooperation.dm
index dd6228f460..517f35b168 100644
--- a/code/modules/ai/ai_holder_cooperation.dm
+++ b/code/modules/ai/ai_holder_cooperation.dm
@@ -1,7 +1,7 @@
// Involves cooperating with other ai_holders.
/datum/ai_holder
var/cooperative = FALSE // If true, asks allies to help when fighting something.
- var/call_distance = 14 // How far away calls for help will go for.
+ var/call_distance = 5 //CHOMPEdit - 14 is way too egreigous // How far away calls for help will go for.
var/last_helpask_time = 0 // world.time when a mob asked for help.
var/list/faction_friends = list() // List of all mobs inside the faction with ai_holders that have cooperate on, to call for help without using range().
// Note that this is only used for sending calls out. Receiving calls doesn't care about this list, only if the mob is in the faction.
diff --git a/code/modules/awaymissions/trigger.dm b/code/modules/awaymissions/trigger.dm
index d34763ab02..8c1de51c83 100644
--- a/code/modules/awaymissions/trigger.dm
+++ b/code/modules/awaymissions/trigger.dm
@@ -1,16 +1,23 @@
/obj/effect/step_trigger/message
var/message //the message to give to the mob
var/once = 1
+ var/list/mobs = list() //CHOMPEdit - mobs we've sent our message to
/obj/effect/step_trigger/message/Trigger(mob/M as mob)
+ //CHOMPEdit start - tweaked message trigger to be more sane
if(M.client)
- to_chat(M, "[message]")
if(once)
- qdel(src)
+ if(M in mobs)
+ return
+ else
+ mobs += M
+ to_chat(M, "[message]")
+ //CHOMPEdit end
/obj/effect/step_trigger/teleport_fancy
var/locationx
var/locationy
+ var/locationz //CHOMPEdit - Why wasn't there a z for this
var/uses = 1 //0 for infinite uses
var/entersparks = 0
var/exitsparks = 0
@@ -18,8 +25,10 @@
var/exitsmoke = 0
/obj/effect/step_trigger/teleport_fancy/Trigger(mob/M as mob)
- var/dest = locate(locationx, locationy, z)
- M.Move(dest)
+ if(!locationz)
+ locationz = src.z //CHOMPEdit - Safety net to not break existing teleport triggers
+ var/dest = locate(locationx, locationy, locationz) //CHOMPEdit - added locationz
+ M.forceMove(dest) //CHOMPEdit - Teleports should be forceMove, not Move
if(entersparks)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 4b1a6be816..e9b56a1288 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -92,9 +92,10 @@
icon_state = "clown"
slowdown = SHOES_SLOWDOWN+0.5
force = 0
- var/footstep = 1 //used for squeeks whilst walking
+ //CHOMPRemove - removed built in squeak sounds
species_restricted = null
+/* CHOMPEdit - Replaced with squeak component
/obj/item/clothing/shoes/clown_shoes/handle_movement(var/turf/walking, var/running)
if(running)
if(footstep >= 2)
@@ -104,6 +105,7 @@
footstep++
else
playsound(src, "clownstep", 20, 1)
+*/
/obj/item/clothing/shoes/cult
name = "boots"
@@ -249,40 +251,6 @@
icon_state = "sneakersred"
item_state = "sneakersred"
-// CHOMPedit start - Mech boots with hijacked clown shoes code.
-
-/obj/item/clothing/shoes/mech_shoes
- name = "mech shoes"
- desc = "Thud thud."
- icon_state = "nothing"
- armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0) // Same as loadout jackboots.
- siemens_coefficient = 0.7 // Same as loadout jackboots.
- force = 2
- var/footstep = 1 // Used for thuds while walking.
- species_restricted = null
-
-/obj/item/clothing/shoes/mech_shoes/handle_movement(var/turf/walking, var/running)
- if(running)
- if(footstep >= 2)
- footstep = 0
- playsound(src, "mechstep", 15, 1) // Hopefully this won't be too annoying.
- else
- footstep++
-
-/obj/item/clothing/shoes/mech_shoes/light
- name = "light mech shoes"
- desc = "Thud thud, but quieter."
-
-/obj/item/clothing/shoes/mech_shoes/light/handle_movement(var/turf/walking, var/running)
- if(running)
- if(footstep >= 2)
- footstep = 0
- playsound(src, "powerloaderstep", 15, 1) // Hopefully this won't be too annoying.
- else
- footstep++
-
-// CHOMPedit end.
-
/obj/item/clothing/shoes/ballet
name = "pointe shoes"
desc = "These shoes feature long lace straps and flattened off toes. Great for the most elegant of dances!"
diff --git a/code/modules/mining/mine_outcrops.dm b/code/modules/mining/mine_outcrops.dm
index fb570af547..218dec9d6c 100644
--- a/code/modules/mining/mine_outcrops.dm
+++ b/code/modules/mining/mine_outcrops.dm
@@ -100,7 +100,7 @@
if (istype(W, /obj/item/weapon/melee/shock_maul))
var/obj/item/weapon/melee/shock_maul/S = W
if(!S.wielded || !S.status)
- to_chat(user, "\The [src] must be wielded in two hands and powered on to be used for mining!")
+ to_chat(user, "\The [W] must be wielded in two hands and powered on to be used to mine this!") //CHOMPEdit - fix improper name
return
to_chat(user, "You pulverize \the [src]!")
for(var/i=0;i<(rand(mindrop,upperdrop));i++)
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index ec0bcb9b75..69a860e516 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -455,8 +455,8 @@ var/list/mining_overlay_cache = list()
return
var/obj/item/weapon/melee/shock_maul/S = W
- if(!S.wielded || !S.status) //if we're not wielded OR not powered up, do nothing
- to_chat(user, "\The [src] must be wielded in two hands and powered on to be used for mining!")
+ if(!S.wielded) //CHOMPEdit - slight maul buff
+ to_chat(user, "\The [W] must be wielded in two hands to be used for mining!") //CHOMPEdit - fixed improper name
return
var/newDepth = excavation_level + S.excavation_amount // Used commonly below
@@ -470,6 +470,9 @@ var/list/mining_overlay_cache = list()
wreckfinds(S.destroy_artefacts)
to_chat(user, "You smash through \the [src][fail_message].")
+ //CHOMPEdit start - Moved the maul sounds up here and made it not cost energy to mine
+ user.visible_message("\The [src] discharges with a thunderous, hair-raising crackle!")
+ playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
if(newDepth >= 200) // This means the rock is mined out fully
if(S.destroy_artefacts)
@@ -488,12 +491,7 @@ var/list/mining_overlay_cache = list()
var/obj/item/weapon/ore/O = new(src)
geologic_data.UpdateNearbyArtifactInfo(src)
O.geologic_data = geologic_data
-
- user.visible_message("\The [src] discharges with a thunderous, hair-raising crackle!")
- playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
- S.deductcharge()
- S.status = 0
- S.update_held_icon()
+ //CHOMPEdit end
if (istype(W, /obj/item/weapon/pickaxe))
if(!istype(user.loc, /turf))
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 87d498fad4..de2dc6a12c 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -240,7 +240,7 @@ emp_act
return null
/mob/living/carbon/human/proc/check_shields(var/damage = 0, var/atom/damage_source = null, var/mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
- for(var/obj/item/shield in list(l_hand, r_hand, wear_suit))
+ for(var/obj/item/shield in list(l_hand, r_hand, wear_suit, l_ear, r_ear)) //CHOMPEdit - included ears for the headset/event item
if(!shield) continue
. = shield.handle_shield(src, damage, damage_source, attacker, def_zone, attack_text)
if(.) return
diff --git a/code/modules/mob/living/carbon/human/human_helpers_vr.dm b/code/modules/mob/living/carbon/human/human_helpers_vr.dm
index 7d02ca95a0..ddd1363d57 100644
--- a/code/modules/mob/living/carbon/human/human_helpers_vr.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers_vr.dm
@@ -1,4 +1,4 @@
-var/static/icon/ingame_hud_vr = icon('icons/mob/hud_vr.dmi')
+var/static/icon/ingame_hud_vr = icon('modular_chomp/icons/mob/hud_vore.dmi') //CHOMPEdit - expanded vore huds
var/static/icon/ingame_hud_med_vr = icon('icons/mob/hud_med_vr.dmi')
/mob/living/carbon/human/make_hud_overlays()
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index d661b5bc0b..021e335e3e 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -256,17 +256,12 @@
// Handle footstep sounds
/mob/living/carbon/human/handle_footstep(var/turf/T)
- if(!istype(T))
- return
- if(is_incorporeal())
- return
- if(!config.footstep_volume || !T.footstep_sounds || !T.footstep_sounds.len)
- return
+ if(!istype(T) || is_incorporeal() || !config.footstep_volume || !T.footstep_sounds || !T.footstep_sounds.len)
+ return //CHOMPEdit - Condensed some return checks
// Future Upgrades - Multi species support
var/list/footstep_sounds = T.footstep_sounds["human"]
if(!footstep_sounds)
return
-
var/S = pick(footstep_sounds)
GLOB.step_taken_shift_roundstat++
if(!S) return
@@ -274,11 +269,13 @@
// Play every 20 steps while walking, for the sneak
if(m_intent == "walk" && step_count++ % 20 != 0)
check_vorefootstep(m_intent, T) //CHOMPstation edit: sloshing reagent belly walk system
- return
-
// Play every other step while running
if(m_intent == "run" && step_count++ % 2 != 0)
check_vorefootstep(m_intent, T) //CHOMPstation edit: sloshing reagent belly walk system
+ if(shoes && loc == T && has_gravity(loc) && !flying)
+ if(SEND_SIGNAL(shoes, COMSIG_SHOES_STEP_ACTION, m_intent)) //CHOMPEdit - Shoe step comsig
+ return
+ if(step_count % 2 == 0) //CHOMPAdd, since I removed the returns up above, need this to track each odd step.
return
var/volume = config.footstep_volume
diff --git a/modular_chomp/code/datums/components/squeak.dm b/modular_chomp/code/datums/components/squeak.dm
new file mode 100644
index 0000000000..26d5bb12d7
--- /dev/null
+++ b/modular_chomp/code/datums/components/squeak.dm
@@ -0,0 +1,180 @@
+//You know, with some intelligent coding.. you could add onto this code to handle the turf based footstep sounds, and be away with those turf lists all together
+//Partial squeak port from tg. Commented out stuff we don't have.
+/datum/component/squeak
+ var/static/list/default_squeak_sounds = list('sound/items/bikehorn.ogg'=1, 'sound/voice/quack.ogg'=1)
+ var/list/override_squeak_sounds
+ var/mob/holder
+
+ var/squeak_chance = 100
+ var/volume = 30
+
+ // This is so shoes don't squeak every step
+ var/steps = 0
+ var/step_delay = 1
+
+ // This is to stop squeak spam from inhand usage
+ var/last_use = 0
+ var/use_delay = 20
+
+ ///extra-range for this component's sound
+ var/sound_extra_range = -1
+ /*
+ ///when sounds start falling off for the squeak
+ var/sound_falloff_distance = 1
+ ///sound exponent for squeak. Defaults to 10 as squeaking is loud and annoying enough.
+ var/sound_falloff_exponent = 10
+ */
+
+ /* Disposals stuff we don't have
+ ///what we set connect_loc to if parent is an item
+ var/static/list/item_connections = list(
+ COMSIG_ATOM_ENTERED = PROC_REF(play_squeak_crossed),
+ )
+ */
+
+
+/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override, extrarange)
+ if(!isatom(parent))
+ return COMPONENT_INCOMPATIBLE
+ RegisterSignals(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK), PROC_REF(play_squeak))
+ if(ismovable(parent))
+ RegisterSignals(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT, COMSIG_PROJECTILE_BEFORE_FIRE), PROC_REF(play_squeak))
+
+ //Disposals stuff we don't have
+ //AddComponent(/datum/component/connect_loc_behalf, parent, item_connections)
+ //RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, PROC_REF(disposing_react))
+ if(isitem(parent))
+ //RegisterSignals(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_ATOM, COMSIG_ITEM_HIT_REACT), PROC_REF(play_squeak))
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(use_squeak))
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip))
+ RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
+ if(istype(parent, /obj/item/clothing/shoes))
+ RegisterSignal(parent, COMSIG_SHOES_STEP_ACTION, PROC_REF(step_squeak))
+ else if(isstructure(parent))
+ RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(use_squeak))
+ else if(ismob(parent) || ismecha(parent))
+ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(step_squeak))
+ /*
+ if(istype(parent, /obj/item/organ/internal/liver))
+ // Liver squeaking is depending on them functioning like a clown's liver
+ RegisterSignal(parent, SIGNAL_REMOVETRAIT(TRAIT_COMEDY_METABOLISM), PROC_REF(on_comedy_metabolism_removal))
+ */
+
+ override_squeak_sounds = custom_sounds
+ if(chance_override)
+ squeak_chance = chance_override
+ if(volume_override)
+ volume = volume_override
+ if(isnum(step_delay_override))
+ step_delay = step_delay_override
+ if(isnum(use_delay_override))
+ use_delay = use_delay_override
+ if(isnum(extrarange))
+ sound_extra_range = extrarange
+ /*
+ if(isnum(falloff_exponent))
+ sound_falloff_exponent = falloff_exponent
+ if(isnum(fallof_distance))
+ sound_falloff_distance = fallof_distance
+ */
+
+/*
+/datum/component/squeak/UnregisterFromParent()
+ . = ..()
+ qdel(GetComponent(/datum/component/connect_loc_behalf))
+*/
+
+/datum/component/squeak/proc/play_squeak(var/volume_mod = 1)
+ SIGNAL_HANDLER
+
+ if(prob(squeak_chance))
+ if(!override_squeak_sounds)
+ playsound(parent, pick_weight(default_squeak_sounds), volume * volume_mod, TRUE, sound_extra_range)
+ else
+ playsound(parent, pick_weight(override_squeak_sounds), volume * volume_mod, TRUE, sound_extra_range)
+
+/datum/component/squeak/proc/step_squeak(obj/item/clothing/shoes/source, var/running)
+ SIGNAL_HANDLER
+
+ /*
+ var/mob/living/carbon/human/owner = source.loc
+ if(CHECK_MOVE_LOOP_FLAGS(owner, MOVEMENT_LOOP_OUTSIDE_CONTROL))
+ return
+ */
+ if(running == "walk")
+ running = 0.25
+ else
+ running = 1
+ if(steps > step_delay)
+ play_squeak(running)
+ steps = 0
+ else
+ steps++
+ return 1
+
+/datum/component/squeak/proc/play_squeak_crossed(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
+ SIGNAL_HANDLER
+ /* We don't have abstract items yet
+ if(isitem(arrived))
+ var/obj/item/I = arrived
+ if(I.item_flags & ABSTRACT)
+ return
+ //Annoyingly, our flight code doesn't set the movement_type, nor do we have a define for it. So I'm not adding it yet.
+ //if(arrived.movement_type & (FLYING|FLOATING) || !arrived.has_gravity())
+ */
+ if(!arrived.has_gravity())
+ return
+ if(ismob(arrived) && !arrived.density) // Prevents 10 overlapping mice from making an unholy sound while moving
+ return
+ var/atom/current_parent = parent
+ if(isturf(current_parent?.loc))
+ play_squeak()
+
+/datum/component/squeak/proc/use_squeak()
+ SIGNAL_HANDLER
+
+ if(last_use + use_delay < world.time)
+ last_use = world.time
+ play_squeak()
+
+/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot)
+ SIGNAL_HANDLER
+ holder = equipper
+ //RegisterSignal(holder, COMSIG_MOVABLE_DISPOSING, PROC_REF(disposing_react), override=TRUE)
+ RegisterSignal(holder, COMSIG_PARENT_QDELETING, PROC_REF(holder_deleted), override=TRUE)
+ //override for the preqdeleted is necessary because putting parent in hands sends the signal that this proc is registered towards,
+ //so putting an object in hands and then equipping the item on a clothing slot (without dropping it first)
+ //will always runtime without override = TRUE
+
+/datum/component/squeak/proc/on_drop(datum/source, mob/user)
+ SIGNAL_HANDLER
+ //UnregisterSignal(user, COMSIG_MOVABLE_DISPOSING)
+ UnregisterSignal(user, COMSIG_PARENT_QDELETING)
+ holder = null
+
+///just gets rid of the reference to holder in the case that theyre qdeleted
+/datum/component/squeak/proc/holder_deleted(datum/source, datum/possible_holder)
+ SIGNAL_HANDLER
+ if(possible_holder == holder)
+ holder = null
+
+/* We don't have comsigs set up for these
+// Disposal pipes related shits
+/datum/component/squeak/proc/disposing_react(datum/source, obj/structure/disposalholder/disposal_holder, obj/machinery/disposal/disposal_source)
+ SIGNAL_HANDLER
+
+ //We don't need to worry about unregistering this signal as it will happen for us automaticaly when the holder is qdeleted
+ RegisterSignal(disposal_holder, COMSIG_ATOM_DIR_CHANGE, PROC_REF(holder_dir_change))
+
+/datum/component/squeak/proc/holder_dir_change(datum/source, old_dir, new_dir)
+ SIGNAL_HANDLER
+
+ //If the dir changes it means we're going through a bend in the pipes, let's pretend we bumped the wall
+ if(old_dir != new_dir)
+ play_squeak()
+
+/datum/component/squeak/proc/on_comedy_metabolism_removal(datum/source, trait)
+ SIGNAL_HANDLER
+
+ qdel(src)
+*/
\ No newline at end of file
diff --git a/modular_chomp/code/game/objects/effects/step_triggers.dm b/modular_chomp/code/game/objects/effects/step_triggers.dm
new file mode 100644
index 0000000000..24ce748321
--- /dev/null
+++ b/modular_chomp/code/game/objects/effects/step_triggers.dm
@@ -0,0 +1,103 @@
+var/static/list/mapped_autostrips = list()
+var/static/list/mapped_autostrips_mob = list()
+
+/*
+This should actually be refactored if it ever needs to be used again into just being
+an event controller with more graceful solutions.
+Creating lockers was not graceful, in practice, and creates clutter, for example.
+Repurpose this idea into a self contained machine in the future that stores and auto-equips someones gear.
+
+But for now, for what it's been used for, it works.
+
+*/
+
+//Admin tool to automatically strip a human victim of all their equipment and genetics powers, and store them in a closet.
+//Equips Vox/Zaddat survival gear, and a few basic pieces of clothing
+/obj/effect/step_trigger/autostrip
+ name = "Autostrip trigger. Set the targetid to match the effect/autostriptarget"
+ var/targetid = "Default"
+ var/obj/effect/autostriptarget/target
+ var/obj/effect/autostriptarget/mob/Mtarget
+ var/remove_implants = 0 //Havn't bothered to implement this yet
+ var/remove_mutations = 0
+
+/obj/effect/step_trigger/autostrip/Initialize(mapload)
+ . = ..()
+ initMappedLink()
+
+/obj/effect/step_trigger/autostrip/Trigger(mob/living/carbon/human/H as mob)
+ if(!istype(H))
+ return
+ if(!target)
+ if(!initMappedLink())
+ return
+ if(Mtarget)
+ H.forceMove(Mtarget.loc)
+ var/obj/locker = new /obj/structure/closet/secure_closet/mind(target.loc, mind_target = H.mind)
+ for(var/obj/item/W in H)
+ if(istype(W, /obj/item/weapon/implant/backup) || istype(W, /obj/item/device/nif))
+ continue //VOREStation Edit
+ if(H.drop_from_inventory(W))
+ W.forceMove(locker)
+
+ if(remove_mutations)
+ var/needs_update = H.mutations.len > 0
+ for(var/entry in H.mutations)
+ var/mut
+ switch(entry)
+ if(TK)
+ mut = TELEBLOCK
+ if(XRAY)
+ mut = XRAYBLOCK
+ if(HULK)
+ mut = HULKBLOCK
+ if(mRemotetalk)
+ mut = REMOTETALKBLOCK
+ if(COLD_RESISTANCE)
+ mut = FIREBLOCK
+ if(mut)
+ new /obj/item/weapon/dnainjector/safe(locker, block_type = mut)
+ H.dna.SetSEState(mut,0)
+ H.mutations = list()
+ H.disabilities = 0
+ H.sdisabilities = 0
+ if(needs_update)
+ domutcheck(H,null,MUTCHK_FORCED)
+ H.update_mutations()
+ if(H.species.name == SPECIES_VOX || SPECIES_ZADDAT) //Species that 'actually' require survival gear to live. The rest don't.
+ H.species.equip_survival_gear(H)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/chameleon(H), slot_w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes)
+ H.equip_to_slot_or_del(new /obj/item/device/radio/headset(H),slot_l_ear)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/permit(H), slot_l_hand)
+
+
+/obj/effect/step_trigger/autostrip/proc/initMappedLink()
+ . = FALSE
+ target = mapped_autostrips[targetid]
+ Mtarget = mapped_autostrips_mob[targetid]
+ if(target)
+ . = TRUE
+
+/obj/effect/autostriptarget
+ name = "Autostrip target. Link me via targetid to an autostrip trigger."
+ icon = 'icons/mob/screen1.dmi'
+ icon_state = "no_item1"
+ var/targetid = "Default"
+ unacidable = 1
+ layer = 99
+ anchored = 1
+ invisibility = 99
+
+
+/obj/effect/autostriptarget/Initialize(mapload)
+ . = ..()
+ if(targetid)
+ mapped_autostrips[targetid] = src
+
+/obj/effect/autostriptarget/mob
+ name = "Autostrip target to send mobs to."
+
+/obj/effect/autostriptarget/mob/Initialize(mapload)
+ if(targetid)
+ mapped_autostrips_mob[targetid] = src
\ No newline at end of file
diff --git a/modular_chomp/code/game/objects/items/devices/radio/headset.dm b/modular_chomp/code/game/objects/items/devices/radio/headset.dm
new file mode 100644
index 0000000000..d9652aa568
--- /dev/null
+++ b/modular_chomp/code/game/objects/items/devices/radio/headset.dm
@@ -0,0 +1,85 @@
+/obj/item/device/radio/headset/casino
+ name = "radio headset"
+ desc = "An updated, modular intercom that fits over the head with extra comfortable for the hardworking casino luxury crew. Has encryption key for scamm-... Kind casino staff channel."
+ icon = 'icons/obj/casino_ch.dmi'
+ icon_state = "headset"
+ origin_tech = list(TECH_ILLEGAL = 2)
+ ks1type = /obj/item/device/encryptionkey/raider
+
+//Badmin piece of clothing that applies a few effects to a mob, used specifically for events with "hunters"
+//This just helps me equip the hunters a little easier
+/obj/item/device/radio/headset/event
+ name = "totally normal headset"
+ desc = "A headset with numerous toolkits appended to it, applying a wide variety of effects to its wearer set as per its manufacturer."
+ icon_state = "cent_headset_alt"
+ item_state = "headset"
+ var/mob/living/carbon/human/wearer
+ var/effect_icon = 'modular_chomp/icons/effects/effects.dmi' //Cosmetic Effect that will be applied to the mob as an overlay
+ var/effect_icon_state = "arrow2"
+ var/image/effect_overlay = null //Reference to an overlay so we can remove it on unequip
+ var/overlay_offset_y = 32
+ //Spells that will be added on equip
+ var/list/spells = list("/spell/targeted/unrestricted/mend", "/spell/targeted/unrestricted/plasmastun")
+ var/list/remove_spells = list() //Reference to spells that'll get removed
+ var/slowdown_to_set = 0.5
+ var/item_slowdown_reset = 0 //Vars to copy and reset later
+ var/slowdown_reset = 0
+ light_range = 6
+ light_power = 0 //Set this to 0 if you don't want a light
+ light_color = "#ffaaaa"
+ var/tele_threshold = 50
+ var/telex = 16
+ var/teley = 16
+ var/telez = 0 //Set this in-round if you want a return point with fake health
+
+/obj/item/device/radio/headset/event/equipped(var/mob/living/carbon/human/H)
+ if(H && ((H.l_ear == src) || (H.r_ear == src)))
+ wearer = H
+ if(light_power)
+ set_light(light_range,light_power,light_color,1)
+ if(effect_icon)
+ effect_overlay = image(effect_icon, effect_icon_state, pixel_y = overlay_offset_y*H.size_multiplier)
+ effect_overlay.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
+ effect_overlay.plane = PLANE_LIGHTING_ABOVE
+ effect_overlay.layer = MOB_LAYER
+ H.add_overlay(effect_overlay)
+ if(spells.len)
+ for(var/thing in spells)
+ var/spell/SP = new thing(H)
+ H.add_spell(SP)
+ remove_spells += SP
+ if(slowdown_to_set != 0)
+ slowdown_reset = H.species.slowdown
+ item_slowdown_reset = H.species.item_slowdown_mod
+ H.species.slowdown = slowdown_to_set
+ H.species.item_slowdown_mod = 0
+
+/obj/item/device/radio/headset/event/dropped(var/mob/living/carbon/human/H)
+ ..()
+ if(wearer)
+ wearer = null
+ if(light_power)
+ light_on = 0
+ if(effect_icon)
+ H.cut_overlay(effect_overlay)
+ if(remove_spells.len)
+ for(var/spell/SP in remove_spells)
+ H.remove_spell(SP)
+ qdel(SP)
+ if(slowdown_to_set != 0)
+ H.species.slowdown = slowdown_reset
+ H.species.item_slowdown_mod = item_slowdown_reset
+
+/obj/item/device/radio/headset/event/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(!telez)
+ return FALSE
+ tele_threshold -= damage
+ if(tele_threshold <= 0)
+ var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
+ spark_system.set_up(5, 0, user.loc)
+ spark_system.start()
+ playsound(src, "sparks", 50, 1)
+ user.visible_message("[user] is abruptly flung somewhere else in response to the damage!")
+ do_teleport(user, locate(telex,teley,telez), local = 0, bohsafe = 1)
+ tele_threshold = initial(tele_threshold)
+ return TRUE
\ No newline at end of file
diff --git a/modular_chomp/code/game/objects/items/weapons/dna_injector.dm b/modular_chomp/code/game/objects/items/weapons/dna_injector.dm
new file mode 100644
index 0000000000..8e811d2df8
--- /dev/null
+++ b/modular_chomp/code/game/objects/items/weapons/dna_injector.dm
@@ -0,0 +1,46 @@
+//Same as regular injector, but without the radiation
+//Using for events, set the block to the desired gene
+//Note, genetics code is incredibly scuffed, sometimes blocks just won't activate unless you do it multiple times????
+/obj/item/weapon/dnainjector/safe
+ desc = "A slightly safer DNA injector"
+ datatype = DNA2_BUF_SE
+ value = 0xFFF
+
+/obj/item/weapon/dnainjector/safe/New(var/block_type)
+ block = block_type
+ ..()
+
+/obj/item/weapon/dnainjector/safe/inject(mob/M as mob, mob/user as mob)
+ /*
+ if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed
+ if (buf.types & DNA2_BUF_UI)
+ if (!block) //isolated block?
+ M.UpdateAppearance(buf.dna.UI.Copy())
+ if (buf.types & DNA2_BUF_UE) //unique enzymes? yes
+ M.real_name = buf.dna.real_name
+ M.name = buf.dna.real_name
+ uses--
+ else
+ M.dna.SetUIValue(block,src.GetValue())
+ M.UpdateAppearance()
+ uses--
+ if (buf.types & DNA2_BUF_SE)
+ if (!block) //isolated block?
+ M.dna.SE = buf.dna.SE.Copy()
+ M.dna.UpdateSE()
+ else
+ M.dna.SetSEValue(block,src.GetValue())
+ domutcheck(M, null, block!=null)
+ uses--
+ if(prob(5))
+ trigger_side_effect(M)
+ */
+ M.dna.SetSEState(block,1)
+ domutcheck(M,null,MUTCHK_FORCED)
+ M.update_mutations()
+
+ spawn(0)//this prevents the collapse of space-time continuum
+ if (user)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return uses
\ No newline at end of file
diff --git a/modular_chomp/code/game/objects/items/weapons/melee/shock_maul.dm b/modular_chomp/code/game/objects/items/weapons/melee/shock_maul.dm
new file mode 100644
index 0000000000..d7a396e5d2
--- /dev/null
+++ b/modular_chomp/code/game/objects/items/weapons/melee/shock_maul.dm
@@ -0,0 +1,5 @@
+/obj/item/weapon/melee/shock_maul/harmless
+ name = "rubber concussion maul"
+ desc = "A variant of the concussion maul that staggers and weakens victims. Despite their screams, does no real damage."
+ damtype = HALLOSS
+ launch_force = 0
\ No newline at end of file
diff --git a/modular_chomp/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/modular_chomp/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
new file mode 100644
index 0000000000..d2cafb2e2f
--- /dev/null
+++ b/modular_chomp/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
@@ -0,0 +1,42 @@
+/obj/structure/closet/secure_closet/mind
+ name = "mind secured locker"
+ var/datum/mind/owner
+ var/self_del = 1
+ anchored = 0
+
+/obj/structure/closet/secure_closet/mind/New(var/datum/mind/mind_target, var/del_self = 1)
+ .=..()
+ self_del = del_self
+ if(mind_target)
+ owner = mind_target
+ name = "Owned by [owner.name]"
+ if(owner.current)
+ var/icon/I = get_flat_icon(owner.current, dir=SOUTH, no_anim=TRUE)
+ var/image/IM = image(I, pixel_x = (32 - I.Width()))
+ //icon2base64(get_flat_icon(owner.current,dir=SOUTH,no_anim=TRUE))
+ /*
+ I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
+ I.plane = MOB_PLANE
+ I.layer = MOB_LAYER
+ */
+ add_overlay(IM)
+ qdel(I)
+
+/obj/structure/closet/secure_closet/mind/allowed(mob/user)
+ if(user.mind == owner)
+ return TRUE
+ else
+ return FALSE
+
+/obj/structure/closet/secure_closet/mind/open()
+ .=..()
+ if(self_del)
+ qdel(src)
+
+/obj/structure/closet/secure_closet/mind/LateInitialize()
+ if(ispath(closet_appearance))
+ closet_appearance = GLOB.closet_appearances[closet_appearance]
+ if(istype(closet_appearance))
+ icon = closet_appearance.icon
+ color = null
+ update_icon()
\ No newline at end of file
diff --git a/modular_chomp/code/game/objects/structures/watercloset_ch.dm b/modular_chomp/code/game/objects/structures/watercloset_ch.dm
index c1fa9b7162..003f5e8017 100644
--- a/modular_chomp/code/game/objects/structures/watercloset_ch.dm
+++ b/modular_chomp/code/game/objects/structures/watercloset_ch.dm
@@ -216,3 +216,14 @@
B.digest_brute = 20
B.special_entrance_sound = 'sound/machines/blender.ogg'
B.recycling = TRUE
+
+/obj/structure/toilet/item/Initialize(mapload)
+ ..()
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/structure/toilet/item/LateInitialize()
+ if(istype(loc, /mob/living)) return
+ var/obj/item/I
+ for(I in loc)
+ if(I.density || I.anchored || I == src) continue
+ I.forceMove(src)
\ No newline at end of file
diff --git a/modular_chomp/code/modules/clothing/shoes/miscellaneous.dm b/modular_chomp/code/modules/clothing/shoes/miscellaneous.dm
new file mode 100644
index 0000000000..8aa8c53d0b
--- /dev/null
+++ b/modular_chomp/code/modules/clothing/shoes/miscellaneous.dm
@@ -0,0 +1,31 @@
+/obj/item/clothing/shoes/mech_shoes
+ name = "mech shoes"
+ desc = "Thud thud."
+ icon_state = "nothing"
+ armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0) // Same as loadout jackboots.
+ siemens_coefficient = 0.7 // Same as loadout jackboots.
+ force = 2
+ species_restricted = null
+ var/list/squeak_sound = list("mechstep"=1) //Squeak sound list. Necessary so our subtypes can have different sounds loaded into their component
+
+/obj/item/clothing/shoes/mech_shoes/Initialize(mapload)
+ .=..()
+ LoadComponent(/datum/component/squeak, squeak_sound, 15*step_volume_mod)
+
+/obj/item/clothing/shoes/mech_shoes/light
+ name = "light mech shoes"
+ desc = "Thud thud, but quieter."
+ squeak_sound = list("powerloaderstep"=1)
+
+/obj/item/clothing/shoes/mech_shoes/heavy
+ name = "heavy mech shoes"
+ desc = "Thud thud, but heavy."
+ squeak_sound = list('modular_chomp/sound/mob/footstep_large.ogg'=1,'modular_chomp/sound/mob/footstep_large2.ogg'=1)
+ step_volume_mod = 4
+
+/obj/item/clothing/shoes/clown_shoes
+ var/list/squeak_sound = list("clownstep"=1)
+
+/obj/item/clothing/shoes/clown_shoes/Initialize(mapload)
+ .=..()
+ LoadComponent(/datum/component/squeak, squeak_sound, 20*step_volume_mod)
\ No newline at end of file
diff --git a/modular_chomp/code/modules/paperwork/pen.dm b/modular_chomp/code/modules/paperwork/pen.dm
new file mode 100644
index 0000000000..9a2c7703c6
--- /dev/null
+++ b/modular_chomp/code/modules/paperwork/pen.dm
@@ -0,0 +1,30 @@
+//Adminspawn item for hunters who're doing kidnaps during events
+/obj/item/weapon/pen/autostun
+ desc = "A well made and expensive fountain pen. This one has gold accents."
+ icon_state = "blueg_fountain"
+ var/stun_duration = 10
+
+/obj/item/weapon/pen/autostun/attack(mob/living/M as mob, mob/user as mob)
+
+ if(!istype(M))
+ return
+ M.Stun(stun_duration)
+
+/obj/item/weapon/pen/autostun/paralyse
+ desc = "A well made and expensive fountain pen. This one has gold accents."
+
+/obj/item/weapon/pen/autostun/paralyse/attack(mob/living/M as mob, mob/user as mob)
+
+ if(!istype(M))
+ return
+ M.Paralyse(stun_duration)
+
+
+/obj/item/weapon/pen/autostun/weaken
+ desc = "A well made and expensive fountain pen. This one has gold accents."
+
+/obj/item/weapon/pen/autostun/weaken/attack(mob/living/M as mob, mob/user as mob)
+
+ if(!istype(M))
+ return
+ M.Weaken(stun_duration)
\ No newline at end of file
diff --git a/modular_chomp/code/modules/projectiles/guns/energy/special.dm b/modular_chomp/code/modules/projectiles/guns/energy/special.dm
new file mode 100644
index 0000000000..6ee7234a28
--- /dev/null
+++ b/modular_chomp/code/modules/projectiles/guns/energy/special.dm
@@ -0,0 +1,24 @@
+/obj/item/weapon/gun/energy/taser/disabler/slow
+ name = "plasma snare device"
+ desc = "A modified disabler adjusted to impulse a target with a restrictive slowdown."
+ icon_state = "disabler"
+ projectile_type = /obj/item/projectile/energy/plasmastun/slow
+ charge_cost = 480
+ self_recharge = 1
+ recharge_time = 3
+
+/obj/item/projectile/energy/plasmastun/slow
+ name = "plasma pulse"
+ icon_state = "plasma_stun"
+ fire_sound = 'sound/weapons/weaponsounds_laserstrong.ogg'
+ armor_penetration = 10
+ range = 9
+ damage = 0
+ agony = 0
+ vacuum_traversal = 1
+ hud_state = "plasma_rifle_blast"
+
+/obj/item/projectile/energy/plasmastun/slow/on_hit(var/atom/target)
+ if(isliving(target))
+ var/mob/living/L = target
+ L.add_modifier(/datum/modifier/entangled, 10 SECONDS)
\ No newline at end of file
diff --git a/modular_chomp/code/modules/spells/spells.dm b/modular_chomp/code/modules/spells/spells.dm
new file mode 100644
index 0000000000..aed9f20477
--- /dev/null
+++ b/modular_chomp/code/modules/spells/spells.dm
@@ -0,0 +1,169 @@
+//This is pretty much just copied from construct_spells but adjusted so anyone can use them
+
+/spell/targeted/unrestricted
+ name = "Base Unrestricted Spell"
+ desc = "If you see this, you should probably remind coders to refactor spell code."
+
+ range = -1
+ school = "evocation"
+ charge_type = Sp_RECHARGE
+ invocation_type = SpI_NONE
+
+ spell_flags = INCLUDEUSER
+
+ hud_state = "const_rune"
+ smoke_amt = 0
+
+ charge_max = 10
+
+ var/obj/item/weapon/spell/unrestricted/spell_obj = null //This is the var that determines what Technomancer-style spell is put into their hands.
+
+/spell/targeted/unrestricted/cast(list/targets, mob/living/user)
+ user.place_spell_in_hand(spell_obj)
+
+/obj/item/weapon/spell/unrestricted
+ name = "a spell"
+ desc = "Remind the devs to refactor spell code."
+ icon = 'icons/obj/spells.dmi'
+ icon_state = "generic"
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/items/lefthand_spells.dmi',
+ slot_r_hand_str = 'icons/mob/items/righthand_spells.dmi',
+ )
+ throwforce = 0
+ force = 0
+ show_examine = FALSE
+ owner = null
+ core = null
+ cast_methods = null // Controls how the spell is casted.
+ aspect = ASPECT_UNHOLY // Not used for everything we do
+ toggled = 0 // Mainly used for overlays.
+ cooldown = 0 // If set, will add a cooldown overlay and adjust click delay. Must be a multiple of 5 for overlays.
+ cast_sound = null // Sound file played when this is used.
+ var/last_castcheck = null // The last time this spell was cast.
+
+/obj/item/weapon/spell/unrestricted/New()
+ if(isliving(loc))
+ owner = loc
+ if(!owner)
+ qdel(src)
+ update_icon()
+
+/obj/item/weapon/spell/unrestricted/run_checks()
+ if(owner)
+ if(world.time >= (last_castcheck + cooldown)) //Are they a cultist or a construct, and has the cooldown time passed?
+ last_castcheck = world.time
+ return 1
+ return 0
+
+/obj/item/weapon/spell/unrestricted/pay_energy(var/amount)
+ if(owner)
+ return 1
+
+/obj/item/weapon/spell/unrestricted/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ if(!run_checks())
+ return
+ if(!proximity_flag)
+ if(cast_methods & CAST_RANGED)
+ on_ranged_cast(target, user)
+ else
+ if(istype(target, /obj/item/weapon/spell))
+ var/obj/item/weapon/spell/spell = target
+ if(spell.cast_methods & CAST_COMBINE)
+ spell.on_combine_cast(src, user)
+ return
+ if(cast_methods & CAST_MELEE)
+ on_melee_cast(target, user)
+ else if(cast_methods & CAST_RANGED) //Try to use a ranged method if a melee one doesn't exist.
+ on_ranged_cast(target, user)
+ if(cooldown)
+ var/effective_cooldown = round(cooldown, 5)
+ user.setClickCooldown(effective_cooldown)
+ flick("cooldown_[effective_cooldown]",src)
+
+/obj/item/weapon/spell/unrestricted/projectile //This makes me angry, but we need the template, and we can't use it because special check overrides on the base.
+ name = "construct projectile template"
+ icon_state = "generic"
+ desc = "This is a generic template that shoots projectiles. If you can read this, the game broke!"
+ cast_methods = CAST_RANGED
+ var/obj/item/projectile/spell_projectile = null
+ var/pre_shot_delay = 0
+ var/fire_sound = null
+ var/energy_cost_per_shot = 5
+
+/obj/item/weapon/spell/unrestricted/projectile/on_ranged_cast(atom/hit_atom, mob/living/user)
+ if(set_up(hit_atom, user))
+ var/obj/item/projectile/new_projectile = make_projectile(spell_projectile, user)
+ new_projectile.old_style_target(hit_atom)
+ new_projectile.firer = user //Don't shoot yourself while moving
+ new_projectile.fire()
+ log_attack("has casted [src] at \the [hit_atom].")
+ if(fire_sound)
+ playsound(src, fire_sound, 75, 1)
+ return 1
+ return 0
+
+/obj/item/weapon/spell/unrestricted/projectile/proc/make_projectile(obj/item/projectile/projectile_type, mob/living/user)
+ var/obj/item/projectile/P = new projectile_type(get_turf(user))
+ return P
+
+/obj/item/weapon/spell/unrestricted/projectile/proc/set_up(atom/hit_atom, mob/living/user)
+ if(spell_projectile)
+ if(pay_energy(energy_cost_per_shot))
+ if(pre_shot_delay)
+ var/image/target_image = image(icon = 'icons/obj/spells.dmi', loc = get_turf(hit_atom), icon_state = "target")
+ user << target_image
+ user.Stun(pre_shot_delay / 10)
+ sleep(pre_shot_delay)
+ qdel(target_image)
+ if(owner)
+ return TRUE
+ return FALSE // We got dropped before the firing occured.
+ return TRUE // No delay, no need to check.
+ return FALSE
+
+//
+// The actual spells
+//
+
+/spell/targeted/unrestricted/plasmastun
+ name = "Plasma Snare"
+ desc = "Fire a debillitating slowing projectile."
+
+ hud_state = "const_beam"
+ spell_obj = /obj/item/weapon/spell/unrestricted/projectile/plasmastun
+
+/obj/item/weapon/spell/unrestricted/projectile/plasmastun
+ name = "plasma snare"
+ icon_state = "generic"
+ desc = "Your hands fire a debillitating slowing projectile."
+ cast_methods = CAST_RANGED
+ spell_projectile = /obj/item/projectile/energy/plasmastun/slow
+ pre_shot_delay = 0
+ cooldown = 5
+ fire_sound = 'sound/weapons/weaponsounds_laserstrong.ogg'
+
+/spell/targeted/unrestricted/mend
+ name = "Mend Target"
+ desc = "Mend a target over time."
+
+ charge_max = 100
+
+ hud_state = "const_mend"
+ spell_obj = /obj/item/weapon/spell/unrestricted/mend
+
+/obj/item/weapon/spell/unrestricted/mend
+ name = "mend target"
+ desc = "Mend the wounds of a target over time"
+ icon_state = "mend_wounds"
+ cast_methods = CAST_MELEE
+ aspect = ASPECT_UNHOLY
+ light_color = "#FF5C5C"
+ light_power = -2
+ light_on = TRUE
+
+/obj/item/weapon/spell/unrestricted/mend/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
+ if(isliving(hit_atom))
+ var/mob/living/L = hit_atom
+ L.add_modifier(/datum/modifier/mend_occult, 150) //No need to change this, it does the job
+ qdel(src)
\ No newline at end of file
diff --git a/modular_chomp/icons/effects/effects.dmi b/modular_chomp/icons/effects/effects.dmi
new file mode 100644
index 0000000000..eca4771b5e
Binary files /dev/null and b/modular_chomp/icons/effects/effects.dmi differ
diff --git a/modular_chomp/icons/mob/hud_vore.dmi b/modular_chomp/icons/mob/hud_vore.dmi
new file mode 100644
index 0000000000..c597e57c23
Binary files /dev/null and b/modular_chomp/icons/mob/hud_vore.dmi differ
diff --git a/modular_chomp/maps/submaps/surface_submaps/wilderness/wilderness_areas.dm b/modular_chomp/maps/submaps/surface_submaps/wilderness/wilderness_areas.dm
index 5d2ff78256..eba81b4ce4 100644
--- a/modular_chomp/maps/submaps/surface_submaps/wilderness/wilderness_areas.dm
+++ b/modular_chomp/maps/submaps/surface_submaps/wilderness/wilderness_areas.dm
@@ -2,11 +2,10 @@
/area/submap
name = "Submap Area"
icon_state = "submap"
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | AREA_FLAG_IS_NOT_PERSISTENT
ambience = AMBIENCE_RUINS
secret_name = TRUE
forbid_events = TRUE
- flags = AREA_FLAG_IS_NOT_PERSISTENT
/area/submap/event //To be used for Events not for regular PoIs
name = "Unknown"
diff --git a/modular_chomp/sound/mob/footstep_large.ogg b/modular_chomp/sound/mob/footstep_large.ogg
new file mode 100644
index 0000000000..7eaef41e15
Binary files /dev/null and b/modular_chomp/sound/mob/footstep_large.ogg differ
diff --git a/modular_chomp/sound/mob/footstep_large2.ogg b/modular_chomp/sound/mob/footstep_large2.ogg
new file mode 100644
index 0000000000..065fca4dcd
Binary files /dev/null and b/modular_chomp/sound/mob/footstep_large2.ogg differ
diff --git a/vorestation.dme b/vorestation.dme
index 5c71ed65f3..adfc0303f3 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -1319,7 +1319,6 @@
#include "code\game\objects\items\devices\radio\encryptionkey.dm"
#include "code\game\objects\items\devices\radio\encryptionkey_vr.dm"
#include "code\game\objects\items\devices\radio\headset.dm"
-#include "code\game\objects\items\devices\radio\headset_ch.dm"
#include "code\game\objects\items\devices\radio\headset_vr.dm"
#include "code\game\objects\items\devices\radio\intercom.dm"
#include "code\game\objects\items\devices\radio\jammer.dm"
@@ -4610,6 +4609,7 @@
#include "modular_chomp\code\datums\browser\color_matrix_picker.dm"
#include "modular_chomp\code\datums\changelog\changelog.dm"
#include "modular_chomp\code\datums\components\gargoyle.dm"
+#include "modular_chomp\code\datums\components\squeak.dm"
#include "modular_chomp\code\datums\components\xenoqueen.dm"
#include "modular_chomp\code\datums\crafting\recipes.dm"
#include "modular_chomp\code\datums\interfaces\appearance.dm"
@@ -4637,14 +4637,18 @@
#include "modular_chomp\code\game\machinery\virtual_reality\vr_console.dm"
#include "modular_chomp\code\game\objects\items.dm"
#include "modular_chomp\code\game\objects\mob_spawner.dm"
+#include "modular_chomp\code\game\objects\effects\step_triggers.dm"
#include "modular_chomp\code\game\objects\items\holosign_creator.dm"
#include "modular_chomp\code\game\objects\items\petrifier.dm"
#include "modular_chomp\code\game\objects\items\clockwork\ratvarian_spear.dm"
#include "modular_chomp\code\game\objects\items\devices\flipper.dm"
#include "modular_chomp\code\game\objects\items\devices\vacpack.dm"
+#include "modular_chomp\code\game\objects\items\devices\radio\headset.dm"
#include "modular_chomp\code\game\objects\items\weapons\capture_crystal.dm"
#include "modular_chomp\code\game\objects\items\weapons\cigs_lighters.dm"
+#include "modular_chomp\code\game\objects\items\weapons\dna_injector.dm"
#include "modular_chomp\code\game\objects\items\weapons\RCD.dm"
+#include "modular_chomp\code\game\objects\items\weapons\melee\shock_maul.dm"
#include "modular_chomp\code\game\objects\items\weapons\storage\backpack.dm"
#include "modular_chomp\code\game\objects\items\weapons\storage\firstaid.dm"
#include "modular_chomp\code\game\objects\random\mapping.dm"
@@ -4654,6 +4658,7 @@
#include "modular_chomp\code\game\objects\structures\loot_pile.dm"
#include "modular_chomp\code\game\objects\structures\watercloset_ch.dm"
#include "modular_chomp\code\game\objects\structures\crate_lockers\largecrate.dm"
+#include "modular_chomp\code\game\objects\structures\crates_lockers\closets\secure\secure_closets.dm"
#include "modular_chomp\code\game\turfs\turf.dm"
#include "modular_chomp\code\game\turfs\simulated\outdoors\desert_planet.dm"
#include "modular_chomp\code\game\turfs\simulated\outdoors\lava_land.dm"
@@ -4677,6 +4682,7 @@
#include "modular_chomp\code\modules\clothing\head\jobs.dm"
#include "modular_chomp\code\modules\clothing\masks\hailer.dm"
#include "modular_chomp\code\modules\clothing\rings\rings_ch.dm"
+#include "modular_chomp\code\modules\clothing\shoes\miscellaneous.dm"
#include "modular_chomp\code\modules\clothing\spacesuits\rig\.behemoth.dm"
#include "modular_chomp\code\modules\clothing\spacesuits\rig\clockwork_ch.dm"
#include "modular_chomp\code\modules\clothing\spacesuits\rig\other.dm"
@@ -4833,6 +4839,7 @@
#include "modular_chomp\code\modules\organs\organ_icon.dm"
#include "modular_chomp\code\modules\overmap\dynamic_sector.dm"
#include "modular_chomp\code\modules\paperwork\filingcabinet.dm"
+#include "modular_chomp\code\modules\paperwork\pen.dm"
#include "modular_chomp\code\modules\planet\sif.dm"
#include "modular_chomp\code\modules\planet\smokestar\turf.dm"
#include "modular_chomp\code\modules\player_tips\player_tips_list.dm"
@@ -4853,6 +4860,7 @@
#include "modular_chomp\code\modules\projectiles\guns\special.dm"
#include "modular_chomp\code\modules\projectiles\guns\staffs.dm"
#include "modular_chomp\code\modules\projectiles\guns\energy\laser.dm"
+#include "modular_chomp\code\modules\projectiles\guns\energy\special.dm"
#include "modular_chomp\code\modules\projectiles\guns\projectile\revolver.dm"
#include "modular_chomp\code\modules\projectiles\precursor\freezegun.dm"
#include "modular_chomp\code\modules\reagents\machinery\dispenser\chem_synthesizer_ch.dm"
@@ -4873,6 +4881,7 @@
#include "modular_chomp\code\modules\research\designs\weapons.dm"
#include "modular_chomp\code\modules\shieldgen\shield_capacitor.dm"
#include "modular_chomp\code\modules\shieldgen\shield_gen.dm"
+#include "modular_chomp\code\modules\spells\spells.dm"
#include "modular_chomp\code\modules\tgui\feedback.dm"
#include "modular_chomp\code\modules\tgui\states\ticket.dm"
#include "modular_chomp\code\modules\tickets\procs.dm"