diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm
index e104916d2d..aad0440423 100644
--- a/code/modules/admin/admin_verb_lists_vr.dm
+++ b/code/modules/admin/admin_verb_lists_vr.dm
@@ -194,7 +194,8 @@ var/list/admin_verbs_spawn = list(
/client/proc/map_template_upload,
/client/proc/map_template_load_on_new_z,
/client/proc/eventkit_open_mob_spawner,
- /client/proc/generic_structure //VOREStation Add
+ /client/proc/generic_structure, //VOREStation Add
+ /client/proc/generic_item //VOREStation Add
)
var/list/admin_verbs_server = list(
diff --git a/code/modules/eventkit/generic_objects/generic_item.dm b/code/modules/eventkit/generic_objects/generic_item.dm
new file mode 100644
index 0000000000..aba094ce3c
--- /dev/null
+++ b/code/modules/eventkit/generic_objects/generic_item.dm
@@ -0,0 +1,241 @@
+/obj/item/generic_item
+ name = "unusual object"
+ desc = "An unusual object of some sort."
+ icon = 'icons/obj/props/items.dmi'
+ icon_state = "old_handheld"
+ var/on = 0
+ var/icon_state_off = "old_handheld"
+ var/icon_state_on = "old_handheld_on"
+ var/activatable_hand = 1
+ var/togglable = 1
+ var/text_activated = "The item turns on."
+ var/text_deactivated = "The item turns off."
+ var/effect = 0
+ var/object = 0
+ var/sound_activated = 0
+ var/delay_time = 0
+ var/icon_off = 0
+ var/icon_on = 0
+
+/obj/item/generic_item/attack_self(mob/user)
+ if(activatable_hand)
+ if(!on)
+ if(delay_time)
+ if(!do_after(user, delay_time, src, exclusive = TASK_USER_EXCLUSIVE))
+ return 0
+ on = 1
+ if(icon_on)
+ icon = icon_on
+ else
+ icon = 'icons/obj/props/items.dmi'
+ icon_state = icon_state_on
+ src.visible_message("[text_activated]")
+ update_icon()
+ if(effect == 1)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(3, 1, src)
+ s.start()
+ if(effect == 2)
+ for(var/obj/machinery/light/L in machines)
+ if(L.z != user.z || get_dist(user,L) > 10)
+ continue
+ else
+ L.flicker(10)
+ if(effect == 3)
+ for (var/mob/O in viewers(user, null))
+ if(get_dist(user, O) > 3)
+ continue
+
+ var/flash_time = 10
+ if(istype(O, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = O
+ //VOREStation Edit Start
+ if(H.nif && H.nif.flag_check(NIF_V_FLASHPROT,NIF_FLAGS_VISION))
+ H.nif.notify("High intensity light detected, and blocked!",TRUE)
+ continue
+ //VOREStation Edit End
+ if(!H.eyecheck() <= 0)
+ continue
+ flash_time *= H.species.flash_mod
+ var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ if(!E)
+ return
+ if(E.is_bruised() && prob(E.damage + 50))
+ H.flash_eyes()
+ E.damage += rand(1, 5)
+ else
+ if(!O.blinded && isliving(O))
+ var/mob/living/L = O
+ L.flash_eyes()
+ O.Weaken(flash_time)
+ if(effect == 4)
+ var/atom/o = new object(get_turf(user))
+ src.visible_message("[src] has produced [o]!")
+ if(sound_activated)
+ playsound(src, sound_activated, 50, 1)
+ else if(togglable)
+ if(delay_time)
+ if(!do_after(user, delay_time, src, exclusive = TASK_USER_EXCLUSIVE))
+ return 0
+ on = 0
+ icon_state = icon_state_off
+ if(icon_off)
+ icon = icon_off
+ else
+ icon = 'icons/obj/props/items.dmi'
+ src.visible_message("[text_deactivated]")
+ update_icon()
+ return ..()
+
+/client/proc/generic_item()
+ set category = "EventKit"
+ set name = "Spawn Generic Item"
+ set desc = "Spawn a customisable item with a range of different options."
+
+ var/s_activatable = 0
+ var/s_togglable = 0
+ var/s_icon_state_on = 0
+ var/s_icon = 0
+ var/s_icon2 = 0
+ var/s_delay = 0
+ var/s_text_activated = 0
+ var/s_text_deactivated = 0
+ var/s_effect = 0
+ var/s_sound = 0
+ var/s_object = 0
+ var/list/icon_state_options = list("old_handheld",
+ "old_handheld_on",
+ "switch",
+ "switch_on",
+ "chalice",
+ "staffofnothing",
+ "staffofchange",
+ "staffofanimation",
+ "staffofchaos",
+ "scroll_rolledup",
+ "scroll_blank",
+ "scroll_text",
+ "scroll_textseal",
+ "scroll_rolledupseal",
+ "revolver",
+ "universal_id",
+ "universal_id_glow",
+ "partypopper",
+ "partypopper_e",
+ "screwdriver",
+ "screwdriver_glow",
+ "crystal",
+ "crystal_red",
+ "old_phone",
+ "old_phone_on",
+ "flash",
+ "flash_red",
+ "flash_burnt",
+ "techball_green",
+ "techball_yellow",
+ "techball_red",
+ "techball_blue",
+ "fleshorb",
+ "fleshorb_moving",
+ "Upload Own Sprite")
+ var/list/sound_options = list('sound/effects/alert.ogg',
+ 'sound/effects/bamf.ogg',
+ 'sound/effects/bang.ogg',
+ 'sound/effects/blobattack.ogg',
+ 'sound/effects/cascade.ogg',
+ 'sound/effects/clockcult_gateway_disrupted.ogg',
+ 'sound/effects/closet_close.ogg',
+ 'sound/effects/confetti_ball.ogg',
+ 'sound/effects/deskbell.ogg',
+ 'sound/effects/EMPulse.ogg',
+ 'sound/effects/Explosion1.ogg',
+ 'sound/effects/ghost.ogg',
+ 'sound/effects/Glassbr1.ogg',
+ 'sound/effects/lightningshock.ogg',
+ 'sound/effects/lighton.ogg',
+ 'sound/effects/magnetclamp.ogg',
+ 'sound/effects/pai_boot.ogg',
+ 'sound/effects/pai_login.ogg',
+ 'sound/effects/pai-restore.ogg',
+ 'sound/effects/radio_common.ogg',
+ 'sound/effects/refill.ogg',
+ 'sound/effects/siren.ogg',
+ 'sound/effects/smoke.ogg',
+ 'sound/effects/sparks1.ogg',
+ 'sound/effects/spray.ogg',
+ 'sound/effects/squelch1.ogg',
+ 'sound/effects/supermatter.ogg',
+ 'sound/effects/Whipcrack.ogg',
+ 'sound/effects/woodcutting.ogg')
+
+ var/check_togglable
+
+
+ if(!holder)
+ return
+
+ var/s_name = tgui_input_text(src, "Item Name:", "Name")
+ var/s_desc = tgui_input_text(src, "Item Description:", "Description")
+ var/s_icon_state_off = tgui_input_list(src, "Choose starting icon state:", "icon_state_off", icon_state_options)
+ if(s_icon_state_off == "Upload Own Sprite")
+ s_icon = input(usr, "Choose an image file to upload. Images that are not 32x32 will need to have their positions offset.","Upload Icon") as null|file
+ var/check_activatable = tgui_alert(src, "Allow it to be turned on?", "activatable", list("Yes", "No", "Cancel"))
+ if(check_activatable == "Cancel")
+ return
+ if(check_activatable == "No")
+ s_activatable = 0
+ if(check_activatable == "Yes")
+ s_activatable = 1
+ s_text_activated = tgui_input_text(src, "Activation text:", "Activation Text")
+ check_togglable = tgui_alert(src, "Allow it to be turned back off again?", "togglable", list("Yes", "No", "Cancel"))
+ if(check_togglable == "Cancel")
+ return
+ if(check_togglable == "No")
+ s_togglable = 0
+ if(check_togglable == "Yes")
+ s_text_deactivated = tgui_input_text(src, "Deactivation text:", "Deactivation Text")
+ s_togglable = 1
+ s_icon_state_on = tgui_input_list(src, "Choose activated icon state:", "icon_state_on", icon_state_options)
+ if(s_icon_state_on == "Upload Own Sprite")
+ s_icon2 = input(usr, "Choose an image file to upload. Images that are not 32x32 will need to have their positions offset.","Upload Icon") as null|file
+ s_delay = tgui_input_number(src, "Do you want it to take time to put turn on? Choose a number of deciseconds to activate, or 0 for instant.", "Delay")
+ var/check_effect = tgui_alert(src, "Produce an effect on activation?", "Effect?", list("No", "Spark", "Flicker Lights", "Flash", "Spawn Item", "Cancel"))
+ if(check_effect == "Cancel")
+ return
+ if(check_effect == "No")
+ s_effect = 0
+ if(check_effect == "Spark")
+ s_effect = 1
+ if(check_effect == "Flicker Lights")
+ s_effect = 2
+ if(check_effect == "Flash")
+ s_effect = 3
+ if(check_effect == "Spawn Item")
+ s_effect = 4
+ s_object = get_path_from_partial_text()
+ var/check_sound = tgui_alert(src, "Play a sound when turning on?", "Sound", list("Yes", "No", "Cancel"))
+ if(check_sound == "Cancel")
+ return
+ if(check_sound == "Yes")
+ s_sound = tgui_input_list(src, "Choose a sound to play on activation:", "Sound", sound_options)
+
+ var/spawnloc = get_turf(src.mob)
+ var/obj/item/generic_item/P = new(spawnloc)
+ P.name = s_name
+ P.desc = s_desc
+ P.icon_state_off = s_icon_state_off
+ P.icon_state_on = s_icon_state_on
+ P.activatable_hand = s_activatable
+ P.togglable = s_togglable
+ P.text_activated = s_text_activated
+ P.text_deactivated = s_text_deactivated
+ P.effect = s_effect
+ P.sound_activated = s_sound
+ P.delay_time = s_delay
+ P.object = s_object
+ P.icon_state = s_icon_state_off
+ P.icon_off = s_icon
+ P.icon_on = s_icon2
+ if(s_icon)
+ P.icon = s_icon
+ P.update_icon()
diff --git a/code/modules/eventkit/generic_objects/generic_structure.dm b/code/modules/eventkit/generic_objects/generic_structure.dm
index d7be876bdb..5334111cc3 100644
--- a/code/modules/eventkit/generic_objects/generic_structure.dm
+++ b/code/modules/eventkit/generic_objects/generic_structure.dm
@@ -16,8 +16,11 @@
var/text_activated = "The strucutre turns on."
var/text_deactivated = "The structure turns off."
var/effect = 0
+ var/object = 0
var/sound_activated = 0
var/delay_time = 0
+ var/icon_on = 0
+ var/icon_off = 0
/obj/structure/generic_structure/attack_hand(mob/user)
if(activatable_hand)
@@ -27,12 +30,53 @@
return 0
on = 1
icon_state = icon_state_on
+ if(icon_on)
+ icon = icon_on
+ else
+ icon = 'icons/obj/props/decor.dmi'
+ icon_state = icon_state_on
src.visible_message("[text_activated]")
update_icon()
- if(effect)
+ if(effect == 1)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
+ if(effect == 2)
+ for(var/obj/machinery/light/L in machines)
+ if(L.z != src.z || get_dist(src,L) > 10)
+ continue
+ else
+ L.flicker(10)
+ if(effect == 3)
+ for (var/mob/O in viewers(src, null))
+ if(get_dist(src, O) > 3)
+ continue
+
+ var/flash_time = 10
+ if(istype(O, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = O
+ //VOREStation Edit Start
+ if(H.nif && H.nif.flag_check(NIF_V_FLASHPROT,NIF_FLAGS_VISION))
+ H.nif.notify("High intensity light detected, and blocked!",TRUE)
+ continue
+ //VOREStation Edit End
+ if(!H.eyecheck() <= 0)
+ continue
+ flash_time *= H.species.flash_mod
+ var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ if(!E)
+ return
+ if(E.is_bruised() && prob(E.damage + 50))
+ H.flash_eyes()
+ E.damage += rand(1, 5)
+ else
+ if(!O.blinded && isliving(O))
+ var/mob/living/L = O
+ L.flash_eyes()
+ O.Weaken(flash_time)
+ if(effect == 4)
+ var/atom/o = new object(get_turf(src))
+ src.visible_message("[src] has produced [o]!")
if(sound_activated)
playsound(src, sound_activated, 50, 1)
else if(togglable)
@@ -41,6 +85,10 @@
return 0
on = 0
icon_state = icon_state_off
+ if(icon_off)
+ icon = icon_off
+ else
+ icon = 'icons/obj/props/decor.dmi'
src.visible_message("[text_deactivated]")
update_icon()
return ..()
@@ -67,6 +115,9 @@
var/s_text_deactivated = 0
var/s_effect = 0
var/s_sound = 0
+ var/s_object = 0
+ var/s_icon = 0
+ var/s_icon2 = 0
var/list/icon_state_options = list("bsb_off",
"bsb_on",
"bsc",
@@ -133,7 +184,8 @@
"ob_warhead_2",
"ob_warhead_3",
"ob_warhead_4",
- "angel")
+ "angel",
+ "Upload Own Sprite")
var/list/sound_options = list('sound/effects/alert.ogg',
'sound/effects/bamf.ogg',
'sound/effects/bang.ogg',
@@ -194,6 +246,8 @@
if(check_wrenchable == "Yes")
s_wrenchable = 1
var/s_icon_state_off = tgui_input_list(src, "Choose starting icon state:", "icon_state_off", icon_state_options)
+ if(s_icon_state_off == "Upload Own Sprite")
+ s_icon = input(usr, "Choose an image file to upload. Images that are not 32x32 will need to have their positions offset.","Upload Icon") as null|file
var/check_activatable = tgui_alert(src, "Allow it to be turned on?", "activatable", list("Yes", "No", "Cancel"))
if(check_activatable == "Cancel")
return
@@ -211,14 +265,23 @@
s_text_deactivated = tgui_input_text(src, "Deactivation text:", "Deactivation Text")
s_togglable = 1
s_icon_state_on = tgui_input_list(src, "Choose activated icon state:", "icon_state_on", icon_state_options)
+ if(s_icon_state_on == "Upload Own Sprite")
+ s_icon2 = input(usr, "Choose an image file to upload. Images that are not 32x32 will need to have their positions offset.","Upload Icon") as null|file
s_delay = tgui_input_number(src, "Do you want it to take time to put turn on? Choose a number of deciseconds to activate, or 0 for instant.", "Delay")
- var/check_effect = tgui_alert(src, "Spark when turning on?", "Spark?", list("Yes", "No", "Cancel"))
+ var/check_effect = tgui_alert(src, "Produce an effect on activation?", "Effect?", list("No", "Spark", "Flicker Lights", "Flash", "Spawn Item", "Cancel"))
if(check_effect == "Cancel")
return
if(check_effect == "No")
s_effect = 0
- if(check_effect == "Yes")
+ if(check_effect == "Spark")
s_effect = 1
+ if(check_effect == "Flicker Lights")
+ s_effect = 2
+ if(check_effect == "Flash")
+ s_effect = 3
+ if(check_effect == "Spawn Item")
+ s_effect = 4
+ s_object = get_path_from_partial_text()
var/check_sound = tgui_alert(src, "Play a sound when turning on?", "Sound", list("Yes", "No", "Cancel"))
if(check_sound == "Cancel")
return
@@ -241,5 +304,36 @@
P.effect = s_effect
P.sound_activated = s_sound
P.delay_time = s_delay
+ P.object = s_object
+ P.icon_state = s_icon_state_off
+ P.icon_off = s_icon
+ P.icon_on = s_icon2
+ if(s_icon)
+ P.icon = s_icon
P.update_icon()
+/client/proc/get_path_from_partial_text(default_path)
+ var/desired_path = tgui_input_text(usr, "Enter full or partial typepath.","Typepath","[default_path]")
+
+ if(!desired_path) //VOREStation Add - If you don't give it anything it builds a list of every possible thing in the game and crashes your client.
+ return //VOREStation Add - And the main way for it to do that is to push the cancel button, which should just do nothing. :U
+
+ var/list/types = typesof(/atom)
+ var/list/matches = list()
+
+ for(var/path in types)
+ if(findtext("[path]", desired_path))
+ matches += path
+
+ if(matches.len==0)
+ tgui_alert_async(usr, "No results found. Sorry.")
+ return
+
+ var/result = null
+
+ if(matches.len==1)
+ result = matches[1]
+ else
+ result = tgui_input_list(usr, "Select an atom type", "Spawn Atom", matches, strict_modern = TRUE)
+ return result
+
diff --git a/icons/obj/props/items.dmi b/icons/obj/props/items.dmi
new file mode 100644
index 0000000000..98a5538c79
Binary files /dev/null and b/icons/obj/props/items.dmi differ
diff --git a/vorestation.dme b/vorestation.dme
index 6ebe54698e..cd057eceee 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2266,6 +2266,7 @@
#include "code\modules\error_handler\error_viewer.dm"
#include "code\modules\error_handler\~defines.dm"
#include "code\modules\eventkit\event_machinery.dm"
+#include "code\modules\eventkit\generic_objects\generic_item.dm"
#include "code\modules\eventkit\generic_objects\generic_structure.dm"
#include "code\modules\eventkit\gm_interfaces\fake_pda_conversations.dm"
#include "code\modules\eventkit\gm_interfaces\mob_spawner.dm"