diff --git a/code/__defines/admin.dm b/code/__defines/admin.dm
index 5f9ada5e98..d2afb7846e 100644
--- a/code/__defines/admin.dm
+++ b/code/__defines/admin.dm
@@ -39,4 +39,9 @@
#define R_EVENT 0x4000
#define R_HOST 0x8000 //higher than this will overflow
-#define R_MAXPERMISSION 0x8000 // This holds the maximum value for a permission. It is used in iteration, so keep it updated.
\ No newline at end of file
+#define R_MAXPERMISSION 0x8000 // This holds the maximum value for a permission. It is used in iteration, so keep it updated.
+
+#define SMITE_BREAKLEGS "Break Legs"
+#define SMITE_BLUESPACEARTILLERY "Bluespace Artillery"
+#define SMITE_SPONTANEOUSCOMBUSTION "Spontaneous Combustion"
+#define SMITE_LIGHTNINGBOLT "Lightning Bolt"
diff --git a/code/__defines/admin_vr.dm b/code/__defines/admin_vr.dm
new file mode 100644
index 0000000000..6e5e8c1a9b
--- /dev/null
+++ b/code/__defines/admin_vr.dm
@@ -0,0 +1,3 @@
+#define SMITE_SHADEKIN_ATTACK "Shadekin (Attack)"
+#define SMITE_SHADEKIN_NOMF "Shadekin (Devour)"
+#define SMITE_REDSPACE_ABDUCT "Redspace Abduction"
diff --git a/code/_onclick/adjacent.dm b/code/_onclick/adjacent.dm
index 47e7e99a92..25997f90ed 100644
--- a/code/_onclick/adjacent.dm
+++ b/code/_onclick/adjacent.dm
@@ -31,7 +31,7 @@
return 1
if(get_dist(src,T0) > 1)
return 0
-
+ if(T0.z != z) return 0 //VOREStation Add
if(T0.x == x || T0.y == y)
// Check for border blockages
return T0.ClickCross(get_dir(T0,src), border_only = 1) && src.ClickCross(get_dir(src,T0), border_only = 1, target_atom = target)
diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm
index cbf492b081..b4c1999b48 100644
--- a/code/game/turfs/unsimulated.dm
+++ b/code/game/turfs/unsimulated.dm
@@ -3,3 +3,15 @@
oxygen = MOLES_O2STANDARD
nitrogen = MOLES_N2STANDARD
initialized = TRUE // Don't call init on unsimulated turfs (at least not yet)
+
+//VOREStation Add
+/turf/unsimulated/fake_space
+ name = "\proper space"
+ icon = 'icons/turf/space.dmi'
+ icon_state = "0"
+ dynamic_lighting = FALSE
+
+/turf/unsimulated/fake_space/New()
+ ..()
+ icon_state = "[((x + y) ^ ~(x * y) + z) % 25]"
+//VOREStation Add End
\ No newline at end of file
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 59a787a2ae..9a0a0ce87d 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -134,7 +134,9 @@ var/list/admin_verbs_fun = list(
/client/proc/editappear,
/client/proc/roll_dices,
/datum/admins/proc/call_supply_drop,
- /datum/admins/proc/call_drop_pod
+ /datum/admins/proc/call_drop_pod,
+ /client/proc/smite_vr, //VOREStation Add,
+ /client/proc/smite
)
var/list/admin_verbs_spawn = list(
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 704be1e117..f92bae98fb 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1325,6 +1325,16 @@
feedback_inc("admin_cookies_spawned",1)
H << "Your prayers have been answered!! You received the best cookie!"
+ else if(href_list["adminsmite"])
+ if(!check_rights(R_ADMIN|R_FUN)) return
+
+ var/mob/living/carbon/human/H = locate(href_list["adminsmite"])
+ if(!ishuman(H))
+ usr << "This can only be used on instances of type /mob/living/carbon/human"
+ return
+
+ owner.smite(H)
+
else if(href_list["BlueSpaceArtillery"])
if(!check_rights(R_ADMIN|R_FUN)) return
@@ -1336,37 +1346,7 @@
if(alert(src.owner, "Are you sure you wish to hit [key_name(M)] with Blue Space Artillery?", "Confirm Firing?" , "Yes" , "No") != "Yes")
return
- if(BSACooldown)
- src.owner << "Standby! Reload cycle in progress! Gunnary crews ready in five seconds!"
- return
-
- BSACooldown = 1
- spawn(50)
- BSACooldown = 0
-
- M << "You've been hit by bluespace artillery!"
- log_admin("[key_name(M)] has been hit by Bluespace Artillery fired by [src.owner]")
- message_admins("[key_name(M)] has been hit by Bluespace Artillery fired by [src.owner]")
-
- var/obj/effect/stop/S
- S = new /obj/effect/stop
- S.victim = M
- S.loc = M.loc
- spawn(20)
- qdel(S)
-
- var/turf/simulated/floor/T = get_turf(M)
- if(istype(T))
- if(prob(80)) T.break_tile_to_plating()
- else T.break_tile()
-
- if(M.health == 1)
- M.gib()
- else
- M.adjustBruteLoss( min( 99 , (M.health - 1) ) )
- M.Stun(20)
- M.Weaken(20)
- M.stuttering = 20
+ bluespace_artillery(M,src)
else if(href_list["CentComReply"])
var/mob/living/L = locate(href_list["CentComReply"])
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index b8fbf77ed3..5469367beb 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -17,7 +17,7 @@
return
var/image/cross = image('icons/obj/storage.dmi',"bible")
- msg = "\icon[cross] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src, src)]) (CA) (SC): [msg]"
+ msg = "\icon[cross] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src, src)]) (CA) (SC) (SMITE): [msg]"
for(var/client/C in admins)
if(R_ADMIN & C.holder.rights)
diff --git a/code/modules/admin/verbs/smite.dm b/code/modules/admin/verbs/smite.dm
new file mode 100644
index 0000000000..e8183e3665
--- /dev/null
+++ b/code/modules/admin/verbs/smite.dm
@@ -0,0 +1,83 @@
+/client/proc/smite(var/mob/living/carbon/human/target in player_list)
+ set name = "Smite"
+ set desc = "Abuse a player with various 'special treatments' from a list."
+ set category = "Fun"
+ if(!check_rights(R_FUN))
+ return
+
+ if(!istype(target))
+ return
+
+ var/list/smite_types = list(SMITE_BREAKLEGS,SMITE_BLUESPACEARTILLERY,SMITE_SPONTANEOUSCOMBUSTION,SMITE_LIGHTNINGBOLT)
+
+ var/smite_choice = input("Select the type of SMITE for [target]","SMITE Type Choice") as null|anything in smite_types
+ if(!smite_choice)
+ return
+
+ switch(smite_choice)
+ if(SMITE_BREAKLEGS)
+ var/broken_legs = 0
+ var/obj/item/organ/external/left_leg = target.get_organ(BP_L_LEG)
+ if(left_leg && left_leg.fracture())
+ broken_legs++
+ var/obj/item/organ/external/right_leg = target.get_organ(BP_R_LEG)
+ if(right_leg && right_leg.fracture())
+ broken_legs++
+ if(!broken_legs)
+ to_chat(src,"[target] didn't have any breakable legs, sorry.")
+
+ if(SMITE_BLUESPACEARTILLERY)
+ bluespace_artillery(target,src)
+
+ if(SMITE_SPONTANEOUSCOMBUSTION)
+ target.adjust_fire_stacks(10)
+ target.IgniteMob()
+ target.visible_message("[target] bursts into flames!")
+
+ if(SMITE_LIGHTNINGBOLT)
+ var/turf/T = get_step(get_step(target, NORTH), NORTH)
+ T.Beam(target, icon_state="lightning[rand(1,12)]", time = 5)
+ target.electrocute_act(75,def_zone = BP_HEAD)
+ target.visible_message("[target] is struck by lightning!")
+
+ else
+ return //Injection? Don't print any messages.
+
+ log_and_message_admins("[key_name(src)] has used SMITE ([smite_choice]) on [key_name(target)].")
+ feedback_add_details("admin_verb","SMITE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/proc/bluespace_artillery(mob/living/target, user)
+ if(!istype(target))
+ return
+
+ if(BSACooldown)
+ if(user)
+ to_chat(user,"BSA is still cooling down, please wait!")
+ return
+
+ BSACooldown = 1
+ spawn(50)
+ BSACooldown = 0
+
+ to_chat(target,"You've been hit by bluespace artillery!")
+ log_and_message_admins("[key_name(target)] has been hit by Bluespace Artillery fired by [key_name(user ? user : usr)]")
+
+ var/obj/effect/stop/S
+ S = new /obj/effect/stop
+ S.victim = target
+ S.loc = target.loc
+ spawn(20)
+ qdel(S)
+
+ var/turf/simulated/floor/T = get_turf(target)
+ if(istype(T))
+ if(prob(80)) T.break_tile_to_plating()
+ else T.break_tile()
+
+ if(target.health == 1)
+ target.gib()
+ else
+ target.adjustBruteLoss( min( 99 , (target.health - 1) ) )
+ target.Stun(20)
+ target.Weaken(20)
+ target.stuttering = 20
diff --git a/code/modules/admin/verbs/smite_vr.dm b/code/modules/admin/verbs/smite_vr.dm
new file mode 100644
index 0000000000..6fccc23dfa
--- /dev/null
+++ b/code/modules/admin/verbs/smite_vr.dm
@@ -0,0 +1,211 @@
+/client/proc/smite_vr(var/mob/living/carbon/human/target in player_list)
+ set name = "Smite (Vore)"
+ set desc = "Abuse a player with various 'special Vore-brand treatments' from a list."
+ set category = "Fun"
+ if(!check_rights(R_ADMIN|R_FUN))
+ return
+
+ if(!istype(target))
+ return
+
+ var/list/smite_types = list(SMITE_SHADEKIN_ATTACK,SMITE_SHADEKIN_NOMF,SMITE_REDSPACE_ABDUCT)
+
+ var/smite_choice = input("Select the type of SMITE for [target]","SMITE Type Choice") as null|anything in smite_types
+ if(!smite_choice)
+ return
+
+ log_and_message_admins("[key_name(src)] has used SMITE (Vore) ([smite_choice]) on [key_name(target)].")
+ feedback_add_details("admin_verb","SMITEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+ switch(smite_choice)
+ if(SMITE_SHADEKIN_ATTACK)
+ var/turf/Tt = get_turf(target) //Turf for target
+
+ if(target.loc != Tt)
+ return //Too hard to attack someone in something
+
+ var/turf/Ts //Turf for shadekin
+
+ //Try to find nondense turf
+ for(var/direction in cardinal)
+ var/turf/T = get_step(target,direction)
+ if(T && !T.density)
+ Ts = T //Found shadekin spawn turf
+ if(!Ts)
+ return //Didn't find shadekin spawn turf
+
+ var/mob/living/simple_animal/shadekin/red/shadekin = new(Ts)
+ //Abuse of shadekin
+ shadekin.real_name = shadekin.name
+ shadekin.init_vore()
+ shadekin.ability_flags |= 0x1
+ shadekin.specific_targets = TRUE //Don't attack others
+ shadekin.phase_shift()
+ shadekin.target_mob = target
+ shadekin.stance = STANCE_ATTACK
+ shadekin.Life()
+ //Remove when done
+ spawn(10 SECONDS)
+ if(shadekin)
+ shadekin.death()
+
+ if(SMITE_SHADEKIN_NOMF)
+ var/list/kin_types = list(
+ "Red Eyes (Dark)" = /mob/living/simple_animal/shadekin/red/dark,
+ "Red Eyes (Light)" = /mob/living/simple_animal/shadekin/red/white,
+ "Red Eyes (Brown)" = /mob/living/simple_animal/shadekin/red/brown,
+ "Blue Eyes (Dark)" = /mob/living/simple_animal/shadekin/blue/dark,
+ "Blue Eyes (Light)" = /mob/living/simple_animal/shadekin/blue/white,
+ "Blue Eyes (Brown)" = /mob/living/simple_animal/shadekin/blue/brown,
+ "Purple Eyes (Dark)" = /mob/living/simple_animal/shadekin/purple/dark,
+ "Purple Eyes (Light)" = /mob/living/simple_animal/shadekin/purple/white,
+ "Purple Eyes (Brown)" = /mob/living/simple_animal/shadekin/purple/brown,
+ "Yellow Eyes (Dark)" = /mob/living/simple_animal/shadekin/yellow/dark,
+ "Yellow Eyes (Light)" = /mob/living/simple_animal/shadekin/yellow/white,
+ "Yellow Eyes (Brown)" = /mob/living/simple_animal/shadekin/yellow/brown,
+ "Green Eyes (Dark)" = /mob/living/simple_animal/shadekin/green/dark,
+ "Green Eyes (Light)" = /mob/living/simple_animal/shadekin/green/white,
+ "Green Eyes (Brown)" = /mob/living/simple_animal/shadekin/green/brown,
+ "Orange Eyes (Dark)" = /mob/living/simple_animal/shadekin/orange/dark,
+ "Orange Eyes (Light)" = /mob/living/simple_animal/shadekin/orange/white,
+ "Orange Eyes (Brown)" = /mob/living/simple_animal/shadekin/orange/brown,
+ "Rivyr (Unique)" = /mob/living/simple_animal/shadekin/blue/rivyr)
+ var/kin_type = input("Select the type of shadekin for [target] nomf","Shadekin Type Choice") as null|anything in kin_types
+ if(!kin_type || !target)
+ return
+
+ kin_type = kin_types[kin_type]
+
+ var/myself = alert("Control the shadekin yourself or delete pred and prey after?","Control Shadekin?","Control","Cancel","Delete")
+ if(myself == "Cancel" || !target)
+ return
+
+ var/turf/Tt = get_turf(target)
+
+ if(target.loc != Tt)
+ return //Can't nom when not exposed
+
+ //Begin abuse
+ target.transforming = TRUE //Cheap hack to stop them from moving
+ var/mob/living/simple_animal/shadekin/shadekin = new kin_type(Tt)
+ shadekin.real_name = shadekin.name
+ shadekin.init_vore()
+ shadekin.can_be_drop_pred = TRUE
+ shadekin.ai_inactive = TRUE
+ shadekin.dir = SOUTH
+ shadekin.ability_flags |= 0x1
+ shadekin.phase_shift() //Homf
+ shadekin.energy = initial(shadekin.energy)
+ //For fun
+ sleep(1 SECOND)
+ shadekin.dir = WEST
+ sleep(1 SECOND)
+ shadekin.dir = EAST
+ sleep(1 SECOND)
+ shadekin.dir = SOUTH
+ sleep(1 SECOND)
+ shadekin.audible_message("[shadekin] belches loudly!")
+ sleep(2 SECONDS)
+ shadekin.phase_shift()
+ target.transforming = FALSE //Undo cheap hack
+
+ if(myself == "Control") //Put admin in mob
+ shadekin.ckey = ckey
+
+ else //Permakin'd
+ to_chat(target,"You're carried off into The Dark by the [shadekin]. Who knows if you'll find your way back?")
+ target.ghostize()
+ qdel(target)
+ qdel(shadekin)
+
+ if(SMITE_REDSPACE_ABDUCT)
+ redspace_abduction(target, src)
+
+ else
+ return //Injection? Don't print any messages.
+
+var/redspace_abduction_z
+
+/area/redspace_abduction
+ name = "Another Time And Place"
+ requires_power = FALSE
+ dynamic_lighting = FALSE
+
+/proc/redspace_abduction(mob/living/target, user)
+ if(redspace_abduction_z < 0)
+ to_chat(user,"The abduction z-level is already being created. Please wait.")
+ return
+ if(!redspace_abduction_z)
+ redspace_abduction_z = -1
+ to_chat(user,"This is the first use of the verb this shift, it will take a minute to configure the abduction z-level. It will be z[world.maxz+1].")
+ var/z = ++world.maxz
+ for(var/x = 1 to world.maxx)
+ for(var/y = 1 to world.maxy)
+ var/turf/T = locate(x,y,z)
+ new /area/redspace_abduction(T)
+ T.ChangeTurf(/turf/unsimulated/fake_space)
+ CHECK_TICK
+ redspace_abduction_z = z
+
+ if(!target || !user)
+ return
+
+ var/size_of_square = 26
+ var/halfbox = round(size_of_square*0.5)
+ target.transforming = TRUE
+ to_chat(target,"You feel a strange tug, deep inside. You're frozen in momentarily...")
+ to_chat(user,"Beginning vis_contents copy to abduction site, player mob is frozen.")
+ sleep(1 SECOND)
+ //Lower left corner of a working box
+ var/llc_x = max(0,halfbox-target.x) + min(target.x+halfbox, world.maxx) - size_of_square
+ var/llc_y = max(0,halfbox-target.y) + min(target.y+halfbox, world.maxy) - size_of_square
+
+ //Copy them all
+ for(var/x = llc_x to llc_x+size_of_square)
+ for(var/y = llc_y to llc_y+size_of_square)
+ var/turf/T_src = locate(x,y,target.z)
+ var/turf/T_dest = locate(x,y,redspace_abduction_z)
+ T_dest.vis_contents.Cut()
+ T_dest.vis_contents += T_src
+ T_dest.density = T_src.density
+ T_dest.opacity = T_src.opacity
+ CHECK_TICK
+
+ //Feather the edges
+ for(var/x = llc_x to llc_x+1) //Left
+ for(var/y = llc_y to llc_y+size_of_square)
+ if(prob(50))
+ var/turf/T = locate(x,y,redspace_abduction_z)
+ T.density = FALSE
+ T.opacity = FALSE
+ T.vis_contents.Cut()
+
+ for(var/x = llc_x+size_of_square-1 to llc_x+size_of_square) //Right
+ for(var/y = llc_y to llc_y+size_of_square)
+ if(prob(50))
+ var/turf/T = locate(x,y,redspace_abduction_z)
+ T.density = FALSE
+ T.opacity = FALSE
+ T.vis_contents.Cut()
+
+ for(var/x = llc_x to llc_x+size_of_square) //Top
+ for(var/y = llc_y+size_of_square-1 to llc_y+size_of_square)
+ if(prob(50))
+ var/turf/T = locate(x,y,redspace_abduction_z)
+ T.density = FALSE
+ T.opacity = FALSE
+ T.vis_contents.Cut()
+
+ for(var/x = llc_x to llc_x+size_of_square) //Bottom
+ for(var/y = llc_y to llc_y+1)
+ if(prob(50))
+ var/turf/T = locate(x,y,redspace_abduction_z)
+ T.density = FALSE
+ T.opacity = FALSE
+ T.vis_contents.Cut()
+
+ target.forceMove(locate(target.x,target.y,redspace_abduction_z))
+ to_chat(target,"The tug relaxes, but everything around you looks... slightly off.")
+ to_chat(user,"The mob has been moved. ([admin_jump_link(target,usr.client.holder)])")
+
+ target.transforming = FALSE
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index 9d16617a67..5d176026f2 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -1050,6 +1050,8 @@ Note that amputating the affected organ does in fact remove the infection from t
var/obj/item/clothing/suit/space/suit = owner.wear_suit
suit.handle_fracture(owner, src)
+ return 1
+
/obj/item/organ/external/proc/mend_fracture()
if(robotic >= ORGAN_ROBOT)
return 0 //ORGAN_BROKEN doesn't have the same meaning for robot limbs
diff --git a/vorestation.dme b/vorestation.dme
index 4708e10d2c..b1c402130e 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -26,6 +26,7 @@
#include "code\__defines\_planes+layers_vr.dm"
#include "code\__defines\_tick.dm"
#include "code\__defines\admin.dm"
+#include "code\__defines\admin_vr.dm"
#include "code\__defines\appearance.dm"
#include "code\__defines\atmos.dm"
#include "code\__defines\belly_modes_vr.dm"
@@ -1381,6 +1382,8 @@
#include "code\modules\admin\verbs\SDQL.dm"
#include "code\modules\admin\verbs\SDQL_2.dm"
#include "code\modules\admin\verbs\SDQL_2_parser.dm"
+#include "code\modules\admin\verbs\smite.dm"
+#include "code\modules\admin\verbs\smite_vr.dm"
#include "code\modules\admin\verbs\striketeam.dm"
#include "code\modules\admin\verbs\ticklag.dm"
#include "code\modules\admin\verbs\tripAI.dm"