diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
new file mode 100644
index 00000000000..14161a5775f
--- /dev/null
+++ b/code/__DEFINES/is_helpers.dm
@@ -0,0 +1 @@
+#define ismovableatom(A) istype(A, /atom/movable)
\ No newline at end of file
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 773572cc0fc..899e8caa98a 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -896,7 +896,7 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
-proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
+/proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0, var/atom/newloc = null)
if(!original)
return null
@@ -905,15 +905,23 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
if(sameloc)
O=new original.type(original.loc)
else
- O=new original.type(locate(0,0,0))
+ O=new original.type(newloc)
if(perfectcopy)
if((O) && (original))
- for(var/V in original.vars)
- if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key")))
- O.vars[V] = original.vars[V]
- return O
+ var/static/list/forbidden_vars = list("type","loc","locs","vars", "parent","parent_type", "verbs","ckey","key","power_supply","contents","reagents","stat","x","y","z","group")
+ for(var/V in original.vars - forbidden_vars)
+ if(istype(original.vars[V],/list))
+ var/list/L = original.vars[V]
+ O.vars[V] = L.Copy()
+ else if(istype(original.vars[V],/datum))
+ continue // this would reference the original's object, that will break when it is used or deleted.
+ else
+ O.vars[V] = original.vars[V]
+ if(istype(O))
+ O.update_icon()
+ return O
/area/proc/copy_contents_to(var/area/A , var/platingRequired = 0 )
//Takes: Area. Optional: If it should copy to areas that don't have plating
@@ -1019,7 +1027,7 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
for(var/V in T.vars)
- if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key","x","y","z","contents", "luminosity")))
+ if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key","x","y","z","contents", "luminosity", "group")))
X.vars[V] = T.vars[V]
// var/area/AR = X.loc
@@ -1673,3 +1681,58 @@ var/mob/dview/dview_mob = new
tY = max(1, min(world.maxy, origin.y + (text2num(tY) - (world.view + 1))))
return locate(tX, tY, tZ)
+/proc/pick_closest_path(value)
+ var/list/matches = get_fancy_list_of_types()
+ if (!isnull(value) && value!="")
+ matches = filter_fancy_list(matches, value)
+
+ if(matches.len==0)
+ return
+
+ var/chosen
+ if(matches.len==1)
+ chosen = matches[1]
+ else
+ chosen = input("Select an atom type", "Spawn Atom", matches[1]) as null|anything in matches
+ if(!chosen)
+ return
+ chosen = matches[chosen]
+ return chosen
+
+
+var/list/TYPES_SHORTCUTS = list(
+ /obj/effect/decal/cleanable = "CLEANABLE",
+ /obj/item/device/radio/headset = "HEADSET",
+ /obj/item/clothing/head/helmet/space = "SPESSHELMET",
+ /obj/item/weapon/book/manual = "MANUAL",
+ /obj/item/weapon/reagent_containers/food/drinks = "DRINK", //longest paths comes first
+ /obj/item/weapon/reagent_containers/food = "FOOD",
+ /obj/item/weapon/reagent_containers = "REAGENT_CONTAINERS",
+ /obj/machinery/atmospherics = "ATMOS",
+ /obj/machinery/portable_atmospherics = "PORT_ATMOS",
+// /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/missile_rack = "MECHA_MISSILE_RACK",
+ /obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP",
+// /obj/item/organ/internal = "ORGAN_INT",
+)
+
+var/global/list/g_fancy_list_of_types = null
+/proc/get_fancy_list_of_types()
+ if (isnull(g_fancy_list_of_types)) //init
+ var/list/temp = sortList(subtypesof(/atom) - typesof(/area) - /atom/movable)
+ g_fancy_list_of_types = new(temp.len)
+ for(var/type in temp)
+ var/typename = "[type]"
+ for (var/tn in TYPES_SHORTCUTS)
+ if (copytext(typename,1, length("[tn]/")+1)=="[tn]/" /*findtextEx(typename,"[tn]/",1,2)*/ )
+ typename = TYPES_SHORTCUTS[tn]+copytext(typename,length("[tn]/"))
+ break
+ g_fancy_list_of_types[typename] = type
+ return g_fancy_list_of_types
+
+/proc/filter_fancy_list(list/L, filter as text)
+ var/list/matches = new
+ for(var/key in L)
+ var/value = L[key]
+ if(findtext("[key]", filter) || findtext("[value]", filter))
+ matches[key] = value
+ return matches
\ No newline at end of file
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 5b9dd3bc6c7..6e21012259b 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -10,9 +10,9 @@
Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner.
*/
/mob/living/silicon/ai/DblClickOn(var/atom/A, params)
- if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
- build_click(src, client.buildmode, params, A)
- return
+ if(client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return
if(control_disabled || stat) return
@@ -27,9 +27,9 @@
return
next_click = world.time + 1
- if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
- build_click(src, client.buildmode, params, A)
- return
+ if(client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return
if(control_disabled || stat)
return
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 5c13314833c..e16fc5af6c1 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -38,9 +38,11 @@
return
next_click = world.time + 1
- if(client && client.buildmode)
- build_click(src, client.buildmode, params, A)
- return
+ if(client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return
+ else
+ log_to_dd("Some twerp set a click_intercept without a viable \"InterceptClickOn\" variable, go yell at them. Mob: [src]")
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index fd54407f19e..bc46ae1b514 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -11,9 +11,9 @@
return
next_click = world.time + 1
- if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
- build_click(src, client.buildmode, params, A)
- return
+ if(client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 09e205a3316..e4f9fef933a 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -1,7 +1,7 @@
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
- if(client.buildmode)
- build_click(src, client.buildmode, params, A)
- return
+ if(client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return
if(can_reenter_corpse && mind && mind.current)
if(A == mind.current || (mind.current in A)) // double click your corpse or whatever holds it
reenter_corpse() // (cloning scanner, body bag, closet, mech, etc)
@@ -17,9 +17,9 @@
forceMove(get_turf(A))
/mob/dead/observer/ClickOn(var/atom/A, var/params)
- if(client.buildmode)
- build_click(src, client.buildmode, params, A)
- return
+ if(client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return
if(world.time <= next_move)
return
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index eea1bfcc586..4c7277cfdaf 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -86,10 +86,10 @@
if(essence == 0)
src << "You feel your essence fraying!"
-/mob/living/simple_animal/revenant/ClickOn(var/atom/A, var/params) //Copypaste from ghost code - revenants can't interact with the world directly.
- if(client.buildmode)
- build_click(src, client.buildmode, params, A)
- return
+/mob/living/simple_animal/revenant/ClickOn(var/atom/A, var/params) //Copypaste from ghost code - revenants can't interact with the world directly.if(client.click_intercept)
+ if(client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return
var/list/modifiers = params2list(params)
if(modifiers["middle"])
diff --git a/code/modules/admin/buildmode.dm b/code/modules/admin/buildmode.dm
index 31e1842186e..c7a2e331c44 100644
--- a/code/modules/admin/buildmode.dm
+++ b/code/modules/admin/buildmode.dm
@@ -3,225 +3,274 @@
#define VAR_BUILDMODE 3
#define THROW_BUILDMODE 4
#define AREA_BUILDMODE 5
-#define NUM_BUILDMODES 5
+#define COPY_BUILDMODE 6
+#define NUM_BUILDMODES 6
-/proc/togglebuildmode(mob/M as mob in player_list)
- set name = "Toggle Build Mode"
- set category = "Special Verbs"
- if(M.client)
- if(M.client.buildmode)
- log_admin("[key_name(usr)] has left build mode.")
- M.client.buildmode = 0
- M.client.show_popup_menus = 1
- for(var/obj/effect/bmode/buildholder/H)
- if(H.cl == M.client)
- qdel(H)
- else
- message_admins("[key_name_admin(usr)] has entered build mode.")
- log_admin("[key_name(usr)] has entered build mode.")
- M.client.buildmode = 1
- M.client.show_popup_menus = 0
-
- var/obj/effect/bmode/buildholder/H = new/obj/effect/bmode/buildholder()
- var/obj/effect/bmode/builddir/A = new/obj/effect/bmode/builddir(H)
- A.master = H
- var/obj/effect/bmode/buildhelp/B = new/obj/effect/bmode/buildhelp(H)
- B.master = H
- var/obj/effect/bmode/buildmode/C = new/obj/effect/bmode/buildmode(H)
- C.master = H
- var/obj/effect/bmode/buildquit/D = new/obj/effect/bmode/buildquit(H)
- D.master = H
-
- H.builddir = A
- H.buildhelp = B
- H.buildmode = C
- H.buildquit = D
- M.client.screen += A
- M.client.screen += B
- M.client.screen += C
- M.client.screen += D
- H.cl = M.client
-
-/obj/effect/bmode //Cleaning up the tree a bit
- density = 1
- anchored = 1
- layer = 20
- dir = NORTH
+/obj/screen/buildmode
icon = 'icons/misc/buildmode.dmi'
- var/obj/effect/bmode/buildholder/master = null
+ var/datum/buildmode/bd
-/obj/effect/bmode/Destroy()
- if(master && master.cl)
- master.cl.screen -= src
- master = null
- return ..()
+/obj/screen/buildmode/New(bld)
+ ..()
+ bd = bld
-/obj/effect/bmode/builddir
- icon_state = "build"
+/obj/screen/buildmode/mode
+ name = "Toggle Mode"
+ icon_state = "buildmode1"
screen_loc = "NORTH,WEST"
-/obj/effect/bmode/Click()
- switch(dir)
- if(NORTH)
- dir = EAST
- if(EAST)
- dir = SOUTH
- if(SOUTH)
- dir = WEST
- if(WEST)
- dir = SOUTHWEST
- if(SOUTHWEST)
- dir = NORTH
- return 1
-
-/obj/effect/bmode/buildhelp
- icon = 'icons/misc/buildmode.dmi'
- icon_state = "buildhelp"
- screen_loc = "NORTH,WEST+1"
-
-/obj/effect/bmode/buildhelp/Click()
- switch(master.cl.buildmode)
- if(BASIC_BUILDMODE)
- usr << "\blue ***********************************************************"
- usr << "\blue Left Mouse Button = Construct / Upgrade"
- usr << "\blue Right Mouse Button = Deconstruct / Delete / Downgrade"
- usr << "\blue Left Mouse Button + ctrl = R-Window"
- usr << "\blue Left Mouse Button + alt = Airlock"
- usr << ""
- usr << "\blue Use the button in the upper left corner to"
- usr << "\blue change the direction of built objects."
- usr << "\blue ***********************************************************"
- if(ADV_BUILDMODE)
- usr << "\blue ***********************************************************"
- usr << "\blue Right Mouse Button on buildmode button = Set object type"
- usr << "\blue Left Mouse Button on turf/obj = Place objects"
- usr << "\blue Right Mouse Button = Delete objects"
- usr << ""
- usr << "\blue Use the button in the upper left corner to"
- usr << "\blue change the direction of built objects."
- usr << "\blue ***********************************************************"
- if(VAR_BUILDMODE)
- usr << "\blue ***********************************************************"
- usr << "\blue Right Mouse Button on buildmode button = Select var(type) & value"
- usr << "\blue Left Mouse Button on turf/obj/mob = Set var(type) & value"
- usr << "\blue Right Mouse Button on turf/obj/mob = Reset var's value"
- usr << "\blue ***********************************************************"
- if(THROW_BUILDMODE)
- usr << "\blue ***********************************************************"
- usr << "\blue Left Mouse Button on turf/obj/mob = Select"
- usr << "\blue Right Mouse Button on turf/obj/mob = Throw"
- usr << "\blue ***********************************************************"
- if(AREA_BUILDMODE)
- usr << "\blue ***********************************************************"
- usr << "\blue Left Mouse Button on turf/obj/mob = Select corner"
- usr << "\blue Right Mouse Button on buildmode button = Select generator"
- usr << "\blue ***********************************************************"
- return 1
-
-/obj/effect/bmode/buildquit
- icon_state = "buildquit"
- screen_loc = "NORTH,WEST+3"
-
-/obj/effect/bmode/buildquit/Click()
- togglebuildmode(master.cl.mob)
- return 1
-
-/obj/effect/bmode/buildholder
- density = 0
- anchored = 1
- var/client/cl = null
- var/obj/effect/bmode/builddir/builddir = null
- var/obj/effect/bmode/buildhelp/buildhelp = null
- var/obj/effect/bmode/buildmode/buildmode = null
- var/obj/effect/bmode/buildquit/buildquit = null
- var/atom/movable/throw_atom = null
- var/turf/cornerA = null
- var/turf/cornerB = null
- var/generator_path = null
-
-/obj/effect/bmode/buildholder/Destroy()
- qdel(builddir)
- builddir = null
- qdel(buildhelp)
- buildhelp = null
- qdel(buildmode)
- buildmode = null
- qdel(buildquit)
- buildquit = null
- throw_atom = null
- cl = null
- return ..()
-
-/obj/effect/bmode/buildmode
- icon_state = "buildmode1"
- screen_loc = "NORTH,WEST+2"
- var/varholder = "name"
- var/valueholder = "derp"
- var/objholder = /obj/structure/closet
-
-/obj/effect/bmode/buildmode/Click(location, control, params)
+/obj/screen/buildmode/mode/Click(location, control, params)
var/list/pa = params2list(params)
if(pa.Find("left"))
- master.cl.buildmode = (master.cl.buildmode % NUM_BUILDMODES) +1
- src.icon_state = "buildmode[master.cl.buildmode]"
-
+ bd.toggle_modes()
else if(pa.Find("right"))
- switch(master.cl.buildmode)
- if(BASIC_BUILDMODE)
- return 1
- if(ADV_BUILDMODE)
- objholder = text2path(input(usr,"Enter typepath:" ,"Typepath","/obj/structure/closet"))
- if(!ispath(objholder))
- objholder = /obj/structure/closet
- alert("That path is not allowed.")
- else
- if(ispath(objholder,/mob) && !check_rights(R_DEBUG,0))
- objholder = /obj/structure/closet
- if(VAR_BUILDMODE)
- var/list/locked = list("vars", "key", "ckey", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "viruses", "cuffed", "ka", "last_eaten", "urine")
-
- master.buildmode.varholder = input(usr,"Enter variable name:" ,"Name", "name")
- if(master.buildmode.varholder in locked && !check_rights(R_DEBUG,0))
- return 1
- var/thetype = input(usr,"Select variable type:" ,"Type") in list("text","number","mob-reference","obj-reference","turf-reference")
- if(!thetype) return 1
- switch(thetype)
- if("text")
- master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value", "value") as text
- if("number")
- master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value", 123) as num
- if("mob-reference")
- master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as mob in mob_list
- if("obj-reference")
- master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as obj in world
- if("turf-reference")
- master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as turf in world
- if(AREA_BUILDMODE)
- var/list/gen_paths = subtypesof(/datum/mapGenerator)
-
- var/type = input(usr,"Select Generator Type","Type") as null|anything in gen_paths
- if(!type) return
-
- master.generator_path = type
+ bd.change_settings(usr)
+ update_icon()
return 1
+/obj/screen/buildmode/mode/update_icon()
+ icon_state = "buildmode[bd.mode]"
+ return
-/proc/build_click(var/mob/user, buildmode, params, var/obj/object)
- var/obj/effect/bmode/buildholder/holder = null
- for(var/obj/effect/bmode/buildholder/H)
- if(H.cl == user.client)
- holder = H
- break
- if(!holder) return
- var/list/pa = params2list(params)
+/obj/screen/buildmode/help
+ icon_state = "buildhelp"
+ screen_loc = "NORTH,WEST+1"
+ name = "Buildmode Help"
- if(istype(object,/obj/effect/bmode))
- return
+/obj/screen/buildmode/help/Click()
+ bd.show_help(usr)
+ return 1
- switch(buildmode)
+/obj/screen/buildmode/bdir
+ icon_state = "build"
+ screen_loc = "NORTH,WEST+2"
+ name = "Change Dir"
+
+/obj/screen/buildmode/bdir/update_icon()
+ dir = bd.build_dir
+ return
+
+/obj/screen/buildmode/bdir/Click()
+ bd.change_dir()
+ update_icon()
+ return 1
+
+/obj/screen/buildmode/quit
+ icon_state = "buildquit"
+ screen_loc = "NORTH,WEST+3"
+ name = "Quit Buildmode"
+
+/obj/screen/buildmode/quit/Click()
+ bd.quit()
+ return 1
+
+/obj/screen/buildmode/dir/Click()
+ bd.change_dir()
+ update_icon()
+ return 1
+
+/obj/effect/buildmode_reticule
+ var/image/I
+ var/client/cl
+
+/obj/effect/buildmode_reticule/New(var/turf/t, var/client/c)
+ loc = t
+ I = image('icons/mob/blob.dmi', t, "marker",19.0,2) // Sprite reuse wooo
+ cl = c
+ cl.images += I
+
+/obj/effect/buildmode_reticule/proc/deselect()
+ qdel(src)
+
+/obj/effect/buildmode_reticule/Destroy()
+ cl.images -= I
+ cl = null
+ qdel(I)
+
+/datum/buildmode
+ var/mode = BASIC_BUILDMODE
+ var/client/holder = null
+ var/list/obj/screen/buttons = list()
+ var/build_dir = SOUTH
+ var/atom/movable/throw_atom = null
+ var/obj/effect/buildmode_reticule/cornerA = null
+ var/obj/effect/buildmode_reticule/cornerB = null
+ var/generator_path = null
+ var/varholder = "name"
+ var/valueholder = "derp"
+ var/objholder = /obj/structure/closet
+ var/atom/movable/stored = null
+
+/datum/buildmode/New(client/c)
+ create_buttons()
+ holder = c
+ holder.click_intercept = src
+ holder.show_popup_menus = 0
+ holder.screen += buttons
+
+/datum/buildmode/proc/quit()
+ holder.screen -= buttons
+ holder.click_intercept = null
+ holder.show_popup_menus = 1
+ qdel(src)
+
+/datum/buildmode/Destroy()
+ stored = null
+ Reset()
+ for(var/button in buttons)
+ qdel(button)
+
+/datum/buildmode/proc/create_buttons()
+ buttons += new /obj/screen/buildmode/mode(src)
+ buttons += new /obj/screen/buildmode/help(src)
+ buttons += new /obj/screen/buildmode/bdir(src)
+ buttons += new /obj/screen/buildmode/quit(src)
+
+/datum/buildmode/proc/toggle_modes()
+ mode = (mode % NUM_BUILDMODES) +1
+ Reset()
+ return
+
+/datum/buildmode/proc/show_help(mob/user)
+ switch(mode)
if(BASIC_BUILDMODE)
- if(istype(object,/turf) && pa.Find("left") && !pa.Find("alt") && !pa.Find("ctrl") )
+ user << "***********************************************************"
+ user << "Left Mouse Button = Construct / Upgrade"
+ user << "Right Mouse Button = Deconstruct / Delete / Downgrade"
+ user << "Left Mouse Button + ctrl = R-Window"
+ user << "Left Mouse Button + alt = Airlock"
+ user << ""
+ user << "Use the button in the upper left corner to"
+ user << "change the direction of built objects."
+ user << "***********************************************************"
+ if(ADV_BUILDMODE)
+ user << "***********************************************************"
+ user << "Right Mouse Button on buildmode button = Set object type"
+ user << "Left Mouse Button on turf/obj = Place objects"
+ user << "Right Mouse Button = Delete objects"
+ user << ""
+ user << "Use the button in the upper left corner to"
+ user << "change the direction of built objects."
+ user << "***********************************************************"
+ if(VAR_BUILDMODE)
+ user << "***********************************************************"
+ user << "Right Mouse Button on buildmode button = Select var(type) & value"
+ user << "Left Mouse Button on turf/obj/mob = Set var(type) & value"
+ user << "Right Mouse Button on turf/obj/mob = Reset var's value"
+ user << "***********************************************************"
+ if(THROW_BUILDMODE)
+ user << "***********************************************************"
+ user << "Left Mouse Button on turf/obj/mob = Select"
+ user << "Right Mouse Button on turf/obj/mob = Throw"
+ user << "***********************************************************"
+ if(AREA_BUILDMODE)
+ user << "***********************************************************"
+ user << "Left Mouse Button on turf/obj/mob = Select corner"
+ user << "Right Mouse Button on buildmode button = Select generator"
+ user << "***********************************************************"
+ if(COPY_BUILDMODE)
+ user << "***********************************************************"
+ user << "Left Mouse Button on obj/turf/mob = Spawn a Copy of selected target"
+ user << "Right Mouse Button on obj/mob = Select target to copy"
+ user << "***********************************************************"
+
+/datum/buildmode/proc/change_settings(mob/user)
+ switch(mode)
+ if(BASIC_BUILDMODE)
+
+ return 1
+ if(ADV_BUILDMODE)
+ var/target_path = input(user,"Enter typepath:" ,"Typepath","/obj/structure/closet")
+ objholder = text2path(target_path)
+ if(!ispath(objholder))
+ objholder = pick_closest_path(target_path)
+ if(!objholder)
+ objholder = /obj/structure/closet
+ alert("That path is not allowed.")
+ else
+ if(ispath(objholder,/mob) && !check_rights(R_DEBUG,0))
+ objholder = /obj/structure/closet
+ if(VAR_BUILDMODE)
+ var/list/locked = list("vars", "key", "ckey", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "viruses", "cuffed", "ka", "last_eaten", "urine")
+
+ varholder = input(user,"Enter variable name:" ,"Name", "name")
+ if(varholder in locked && !check_rights(R_DEBUG,0))
+
+ return 1
+ var/thetype = input(user,"Select variable type:" ,"Type") in list("text","number","mob-reference","obj-reference","turf-reference")
+ if(!thetype) return 1
+ switch(thetype)
+ if("text")
+ valueholder = input(user,"Enter variable value:" ,"Value", "value") as text
+ if("number")
+ valueholder = input(user,"Enter variable value:" ,"Value", 123) as num
+ if("mob-reference")
+ valueholder = input(user,"Enter variable value:" ,"Value") as mob in mob_list
+ if("obj-reference")
+ valueholder = input(user,"Enter variable value:" ,"Value") as obj in world
+ if("turf-reference")
+ valueholder = input(user,"Enter variable value:" ,"Value") as turf in world
+ if(AREA_BUILDMODE)
+ var/list/gen_paths = subtypesof(/datum/mapGenerator)
+
+ var/type = input(user,"Select Generator Type","Type") as null|anything in gen_paths
+ if(!type) return
+
+ generator_path = type
+ cornerA = null
+ cornerB = null
+
+/datum/buildmode/proc/change_dir()
+ switch(build_dir)
+ if(NORTH)
+ build_dir = EAST
+ if(EAST)
+ build_dir = SOUTH
+ if(SOUTH)
+ build_dir = WEST
+ if(WEST)
+ build_dir = NORTHWEST
+ if(NORTHWEST)
+ build_dir = NORTH
+ return 1
+
+/datum/buildmode/proc/deselect_region()
+ qdel(cornerA)
+ cornerA = null
+ qdel(cornerB)
+ cornerB = null
+
+/datum/buildmode/proc/Reset()//Reset temporary variables
+ deselect_region()
+
+/datum/buildmode/proc/select_tile(var/turf/T)
+ return new /obj/effect/buildmode_reticule(T, holder)
+
+/proc/togglebuildmode(mob/M in player_list)
+ set name = "Toggle Build Mode"
+ set category = "Special Verbs"
+ if(M.client)
+ if(istype(M.client.click_intercept,/datum/buildmode))
+ var/datum/buildmode/B = M.client.click_intercept
+ B.quit()
+ log_admin("[key_name(usr)] has left build mode.")
+ else
+ new/datum/buildmode(M.client)
+ message_admins("[key_name(usr)] has entered build mode.")
+ log_admin("[key_name(usr)] has entered build mode.")
+
+/datum/buildmode/proc/InterceptClickOn(user,params,atom/object) //Click Intercept
+ var/list/pa = params2list(params)
+ var/right_click = pa.Find("right")
+ var/left_click = pa.Find("left")
+ var/alt_click = pa.Find("alt")
+ var/ctrl_click = pa.Find("ctrl")
+
+ . = 1
+ switch(mode)
+ if(BASIC_BUILDMODE)
+ if(istype(object,/turf) && left_click && !alt_click && !ctrl_click)
var/turf/T = object
if(istype(object,/turf/space))
T.ChangeTurf(/turf/simulated/floor/plasteel)
@@ -229,10 +278,10 @@
T.ChangeTurf(/turf/simulated/wall)
else if(istype(object,/turf/simulated/wall))
T.ChangeTurf(/turf/simulated/wall/r_wall)
- log_admin("Build Mode: [key_name(usr)] built [T] at ([T.x],[T.y],[T.z])")
+ log_admin("Build Mode: [key_name(user)] built [T] at ([T.x],[T.y],[T.z])")
return
- else if(pa.Find("right"))
- log_admin("Build Mode: [key_name(usr)] deleted [object] at ([object.x],[object.y],[object.z])")
+ else if(right_click)
+ log_admin("Build Mode: [key_name(user)] deleted [object] at ([object.x],[object.y],[object.z])")
if(istype(object,/turf/simulated/wall))
var/turf/T = object
T.ChangeTurf(/turf/simulated/floor/plasteel)
@@ -245,11 +294,11 @@
else if(istype(object,/obj))
qdel(object)
return
- else if(istype(object,/turf) && pa.Find("alt") && pa.Find("left"))
- log_admin("Build Mode: [key_name(usr)] built an airlock at ([object.x],[object.y],[object.z])")
+ else if(istype(object,/turf) && alt_click && left_click)
+ log_admin("Build Mode: [key_name(user)] built an airlock at ([object.x],[object.y],[object.z])")
new/obj/machinery/door/airlock(get_turf(object))
- else if(istype(object,/turf) && pa.Find("ctrl") && pa.Find("left"))
- switch(holder.builddir.dir)
+ else if(istype(object,/turf) && ctrl_click && left_click)
+ switch(build_dir)
if(NORTH)
var/obj/structure/window/reinforced/WIN = new/obj/structure/window/reinforced(get_turf(object))
WIN.dir = NORTH
@@ -262,76 +311,74 @@
if(WEST)
var/obj/structure/window/reinforced/WIN = new/obj/structure/window/reinforced(get_turf(object))
WIN.dir = WEST
- if(SOUTHWEST)
- new/obj/structure/window/full/reinforced(get_turf(object))
- log_admin("Build Mode: [key_name(usr)] built a window at ([object.x],[object.y],[object.z])")
+ if(NORTHWEST)
+ var/obj/structure/window/reinforced/WIN = new/obj/structure/window/reinforced(get_turf(object))
+ WIN.dir = NORTHWEST
+ log_admin("Build Mode: [key_name(user)] built a window at ([object.x],[object.y],[object.z])")
+
if(ADV_BUILDMODE)
- if(pa.Find("left"))
- if(ispath(holder.buildmode.objholder,/turf))
+ if(left_click)
+ if(ispath(objholder,/turf))
var/turf/T = get_turf(object)
- log_admin("Build Mode: [key_name(usr)] modified [T] ([T.x],[T.y],[T.z]) to [holder.buildmode.objholder]")
- T.ChangeTurf(holder.buildmode.objholder)
+ log_admin("Build Mode: [key_name(user)] modified [T] ([T.x],[T.y],[T.z]) to [objholder]")
+ T.ChangeTurf(objholder)
else
- var/obj/A = new holder.buildmode.objholder (get_turf(object))
- A.dir = holder.builddir.dir
- log_admin("Build Mode: [key_name(usr)] modified [A]'s ([A.x],[A.y],[A.z]) dir to [holder.builddir.dir]")
- else if(pa.Find("right"))
+ var/obj/A = new objholder (get_turf(object))
+ A.dir = build_dir
+ log_admin("Build Mode: [key_name(user)] modified [A]'s ([A.x],[A.y],[A.z]) dir to [build_dir]")
+ else if(right_click)
if(isobj(object))
- log_admin("Build Mode: [key_name(usr)] deleted [object] at ([object.x],[object.y],[object.z])")
+ log_admin("Build Mode: [key_name(user)] deleted [object] at ([object.x],[object.y],[object.z])")
qdel(object)
if(VAR_BUILDMODE)
- if(pa.Find("left")) //I cant believe this shit actually compiles.
- if(object.vars.Find(holder.buildmode.varholder))
- log_admin("[key_name(usr)] modified [object.name]'s [holder.buildmode.varholder] to [holder.buildmode.valueholder]")
- object.vars[holder.buildmode.varholder] = holder.buildmode.valueholder
+ if(left_click) //I cant believe this shit actually compiles.
+ if(object.vars.Find(varholder))
+ log_admin("Build Mode: [key_name(user)] modified [object.name]'s [varholder] to [valueholder]")
+ object.vars[varholder] = valueholder
else
- usr << "[initial(object.name)] does not have a var called '[holder.buildmode.varholder]'"
- if(pa.Find("right"))
- if(object.vars.Find(holder.buildmode.varholder))
- log_admin("[key_name(usr)] modified [object.name]'s [holder.buildmode.varholder] to [holder.buildmode.valueholder]")
- object.vars[holder.buildmode.varholder] = initial(object.vars[holder.buildmode.varholder])
+ user << "[initial(object.name)] does not have a var called '[varholder]'"
+ if(right_click)
+ if(object.vars.Find(varholder))
+ log_admin("Build Mode: [key_name(user)] modified [object.name]'s [varholder] to [valueholder]")
+ object.vars[varholder] = initial(object.vars[varholder])
else
- usr << "[initial(object.name)] does not have a var called '[holder.buildmode.varholder]'"
+ user << "[initial(object.name)] does not have a var called '[varholder]'"
if(THROW_BUILDMODE)
- if(pa.Find("left"))
+ if(left_click)
if(isturf(object))
return
- holder.throw_atom = object
- if(pa.Find("right"))
- if(holder.throw_atom)
- holder.throw_atom.throw_at(object, 10, 1)
- log_admin("Build Mode: [key_name(usr)] threw [holder.throw_atom] at [object] ([object.x],[object.y],[object.z])")
+ throw_atom = object
+ if(right_click)
+ if(throw_atom)
+ throw_atom.throw_at(object, 10, 1,user)
+ log_admin("Build Mode: [key_name(user)] threw [throw_atom] at [object] ([object.x],[object.y],[object.z])")
if(AREA_BUILDMODE)
- if(!holder.cornerA)
- holder.cornerA = get_turf(object)
+ if(!cornerA)
+ cornerA = select_tile(get_turf(object))
return
- if(holder.cornerA && !holder.cornerB)
- holder.cornerB = get_turf(object)
+ if(cornerA && !cornerB)
+ cornerB = select_tile(get_turf(object))
+ if(left_click) //rectangular
+ if(cornerA && cornerB)
+ if(!generator_path)
+ user << "Select generator type first."
+ else
+ var/datum/mapGenerator/G = new generator_path
+ G.defineRegion(cornerA.loc,cornerB.loc,1)
+ G.generate()
+ deselect_region()
+ return
- if(pa.Find("left")) //rectangular
- if(holder.cornerA && holder.cornerB)
- if(!holder.generator_path)
- usr << "Select generator type first."
- var/datum/mapGenerator/G = new holder.generator_path
- G.defineRegion(holder.cornerA,holder.cornerB,1)
- G.generate()
- holder.cornerA = null
- holder.cornerB = null
- return
- /* Something wrong with this, will check later
- if(pa.Find("right")) // circular
- if(holder.cornerA && holder.cornerB)
- if(!holder.generator_path)
- usr << "Select generator type first."
- var/datum/mapGenerator/G = new holder.generator_path
- G.defineCircularRegion(holder.cornerA,holder.cornerB,1)
- G.generate()
- holder.cornerA = null
- holder.cornerB = null
- return
- */
//Something wrong - Reset
- holder.cornerA = null
- holder.cornerB = null
\ No newline at end of file
+ deselect_region()
+ if(COPY_BUILDMODE)
+ if(left_click)
+ var/turf/T = get_turf(object)
+ if(stored)
+ DuplicateObject(stored, perfectcopy=1, sameloc=0,newloc=T)
+ else if(right_click)
+ if(ismovableatom(object)) // No copying turfs for now.
+ user << "[object] set as template."
+ stored = object
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index 4d9237bd11c..3f19442f94b 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -3,7 +3,6 @@
//ADMIN THINGS//
////////////////
var/datum/admins/holder = null
- var/buildmode = 0
var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent.
@@ -80,4 +79,6 @@
var/topic_debugging = 0 //if set to true, allows client to see nanoUI errors -- yes i realize this is messy but it'll make live testing infinitely easier
- control_freak = CONTROL_FREAK_ALL | CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
\ No newline at end of file
+ control_freak = CONTROL_FREAK_ALL | CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
+
+ var/datum/click_intercept = null // To use this, implement "InterceptClickOn" in your datum, then set your desired client's click_intercept to that datum
\ No newline at end of file
diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi
index beed381e391..ca9d1fd05cc 100644
Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ
diff --git a/paradise.dme b/paradise.dme
index c30ca7e5c0f..454d119d863 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -10,6 +10,7 @@
#define DEBUG
// END_PREFERENCES
// BEGIN_INCLUDE
+#include "stddef.dm"
#include "_maps\cyberiad.dm"
#include "code\_compile_options.dm"
#include "code\hub.dm"
@@ -25,6 +26,7 @@
#include "code\__DEFINES\genetics.dm"
#include "code\__DEFINES\hud.dm"
#include "code\__DEFINES\hydroponics.dm"
+#include "code\__DEFINES\is_helpers.dm"
#include "code\__DEFINES\language.dm"
#include "code\__DEFINES\lighting.dm"
#include "code\__DEFINES\machines.dm"