diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index a127e7608f..15b0bd95df 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -46,6 +46,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/preferred_map = null
var/uses_glasses_colour = 0
+
+ var/screenshake = 100
+ var/damagescreenshake = 2
//character preferences
var/real_name //our character's name
@@ -363,6 +366,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "High"
dat += "
"
+ dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]
"
+
+ if (!user.client.prefs.screenshake==0)
+ dat += "Damage Screen Shake: [(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]
"
+
dat += "
"
dat += "Special Role Settings"
@@ -1486,6 +1494,20 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["exhibitionist"] = TRUE
else
features["exhibitionist"] = FALSE
+ if ("screenshake")
+ var/desiredshake = input(user, "Set the amount of screenshake you want. \n(0 = disabled, 100 = full, 200 = maximum.)", "Character Preference", screenshake) as null|num
+ if (!isnull(desiredshake))
+ screenshake = desiredshake
+ if("damagescreenshake")
+ switch(damagescreenshake)
+ if(0)
+ damagescreenshake = 1
+ if(1)
+ damagescreenshake = 2
+ if(2)
+ damagescreenshake = 0
+ else
+ damagescreenshake = 1
if("publicity")
if(unlock_content)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 947372bfcb..9daad5cae7 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -191,6 +191,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["menuoptions"] >> menuoptions
//citadel code
S["arousable"] >> arousable
+ S["screenshake"] >> screenshake
+ S["damagescreenshake"] >> damagescreenshake
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -215,6 +217,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION)
menuoptions = SANITIZE_LIST(menuoptions)
be_special = SANITIZE_LIST(be_special)
+ screenshake = sanitize_integer(screenshake, 0, 200, initial(screenshake))
+ damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
return 1
@@ -256,6 +260,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["enable_tips"], enable_tips)
WRITE_FILE(S["tip_delay"], tip_delay)
//citadel code
+ WRITE_FILE(S["screenshake"], screenshake)
+ WRITE_FILE(S["damagescreenshake"], damagescreenshake)
WRITE_FILE(S["arousable"], arousable)
return 1
diff --git a/modular_citadel/README.md b/modular_citadel/README.md
new file mode 100644
index 0000000000..dfae177607
--- /dev/null
+++ b/modular_citadel/README.md
@@ -0,0 +1,3 @@
+Hooray modularity!
+Things that modify core files without directly touching said core files go here. This is similar to how Hippie handles things.
+This stops dreammaker from throwing errors and warnings if you try to compile these files while they're inside code/citadel/.
diff --git a/modular_citadel/cit_screenshake.dm b/modular_citadel/cit_screenshake.dm
new file mode 100644
index 0000000000..2d0110c4e7
--- /dev/null
+++ b/modular_citadel/cit_screenshake.dm
@@ -0,0 +1,69 @@
+//we vlambeer now
+
+/obj/proc/shake_camera(mob/M, duration, strength=1)//byond's wonky with this shit
+ if(!M || !M.client || duration <= 0)
+ return
+ var/client/C = M.client
+ if (C.prefs.screenshake==0)
+ return
+ var/oldx = C.pixel_x
+ var/oldy = C.pixel_y
+ var/clientscreenshake = (C.prefs.screenshake * 0.01)
+ var/max = (strength*clientscreenshake) * world.icon_size
+ var/min = -((strength*clientscreenshake) * world.icon_size)
+
+ for(var/i in 0 to duration-1)
+ if (i == 0)
+ animate(C, pixel_x=rand(min,max), pixel_y=rand(min,max), time=1)
+ else
+ animate(pixel_x=rand(min,max), pixel_y=rand(min,max), time=1)
+ animate(pixel_x=oldx, pixel_y=oldy, time=1)
+
+/obj/item/gun/energy
+ ..()
+ recoil = 0.1
+
+/obj/item/gun/energy/kinetic_accelerator
+ ..()
+ recoil = 0.5
+
+/obj/item/gun/ballistic
+ ..()
+ recoil = 0.25
+
+/obj/item/gun/ballistic/shotgun
+ ..()
+ recoil = 1
+
+/obj/item/gun/ballistic/revolver
+ ..()
+ recoil = 0.5
+
+/obj/item/gun/ballistic/revolver/doublebarrel
+ ..()
+ recoil = 1
+
+/obj/item/gun/syringe
+ ..()
+ recoil = 0.1
+
+/obj/item/pneumatic_cannon/fire_items(turf/target, mob/user)
+ . = ..()
+ shake_camera(user, (pressureSetting * 0.75 + 1), (pressureSetting * 0.75))
+
+/obj/item/attack(mob/living/M, mob/living/user)
+ . = ..()
+ if(force && force >=15)
+ shake_camera(user, ((force - 10) * 0.01 + 1), ((force - 10) * 0.01))
+ if(M.client)
+ switch (M.client.prefs.damagescreenshake)
+ if (1)
+ shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015))
+ if (2)
+ if (M.IsKnockdown())
+ shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015))
+
+/obj/item/attack_obj(obj/O, mob/living/user)
+ . = ..()
+ if(force && force >= 20)
+ shake_camera(user, ((force - 15) * 0.01 + 1), ((force - 15) * 0.01))
diff --git a/tgstation.dme b/tgstation.dme
index 0d142f7973..eb1bfd6c11 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2274,6 +2274,7 @@
#include "code\modules\VR\vr_sleeper.dm"
#include "code\modules\zombie\items.dm"
#include "code\modules\zombie\organs.dm"
+#include "modular_citadel\cit_screenshake.dm"
#include "interface\interface.dm"
#include "interface\menu.dm"
#include "interface\stylesheet.dm"
|