Merge pull request #2537 from yogstation13/upstream-merge-40105

[MIRROR] Ports paradise's modular buildmode
This commit is contained in:
1fbff5f83b23d39d38b1dfcb4cac8d9b
2018-09-15 20:20:52 +02:00
committed by GitHub
25 changed files with 1076 additions and 420 deletions

View File

@@ -460,3 +460,6 @@ GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE))
#define CAMERA_SEE_GHOSTS_ORBIT 2
#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (istype(I, /client) ? I : (istype(I, /datum/mind) ? I:current?:client : null)))
#define AREASELECT_CORNERA "corner A"
#define AREASELECT_CORNERB "corner B"

View File

@@ -10,9 +10,6 @@
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(check_click_intercept(params,A))
return
if(control_disabled || incapacitated())
return

View File

@@ -1,7 +1,4 @@
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
if(check_click_intercept(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)

View File

@@ -1,394 +0,0 @@
#define BASIC_BUILDMODE 1
#define ADV_BUILDMODE 2
#define VAR_BUILDMODE 3
#define THROW_BUILDMODE 4
#define AREA_BUILDMODE 5
#define COPY_BUILDMODE 6
#define NUM_BUILDMODES 6
//Buildmode Shuttle
//Builmode Move
/obj/screen/buildmode
icon = 'icons/misc/buildmode.dmi'
var/datum/buildmode/bd
/obj/screen/buildmode/New(bd)
..()
src.bd = bd
/obj/screen/buildmode/Destroy()
bd.buttons -= src
bd = null
return ..()
/obj/screen/buildmode/mode
icon_state = "buildmode1"
name = "Toggle Mode"
screen_loc = "NORTH,WEST"
/obj/screen/buildmode/mode/Click(location, control, params)
var/list/pa = params2list(params)
if(pa.Find("left"))
bd.toggle_modes()
else if(pa.Find("right"))
bd.change_settings(usr)
update_icon()
return 1
/obj/screen/buildmode/mode/update_icon()
icon_state = "buildmode[bd.mode]"
return
/obj/screen/buildmode/help
icon_state = "buildhelp"
screen_loc = "NORTH,WEST+1"
name = "Buildmode Help"
/obj/screen/buildmode/help/Click()
bd.show_help(usr)
return 1
/obj/screen/buildmode/bdir
icon_state = "build"
screen_loc = "NORTH,WEST+2"
name = "Change Dir"
/obj/screen/buildmode/bdir/update_icon()
setDir(bd.build_dir)
return
/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/bdir/Click()
bd.change_dir()
update_icon()
return 1
/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/turf/cornerA = null
var/turf/cornerB = null
var/generator_path = null
var/varholder = "name"
var/valueholder = "derp"
var/objholder = /obj/structure/closet
var/atom/movable/stored = null
var/list/preview = list()
/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
usr.client.images -= preview
preview.Cut()
qdel(src)
return
/datum/buildmode/Destroy()
stored = null
QDEL_LIST(buttons)
throw_atom = null
holder = null
preview.Cut()
cornerA = null
cornerB = null
return ..()
/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)
var/list/dat = list()
switch(mode)
if(BASIC_BUILDMODE)
dat += "***********************************************************"
dat += "Left Mouse Button = Construct / Upgrade"
dat += "Right Mouse Button = Deconstruct / Delete / Downgrade"
dat += "Left Mouse Button + ctrl = R-Window"
dat += "Left Mouse Button + alt = Airlock"
dat += ""
dat += "Use the button in the upper left corner to"
dat += "change the direction of built objects."
dat += "***********************************************************"
if(ADV_BUILDMODE)
dat += "***********************************************************"
dat += "Right Mouse Button on buildmode button = Set object type"
dat += "Left Mouse Button + alt on turf/obj = Copy object type"
dat += "Left Mouse Button on turf/obj = Place objects"
dat += "Right Mouse Button = Delete objects"
dat += ""
dat += "Use the button in the upper left corner to"
dat += "change the direction of built objects."
dat += "***********************************************************"
if(VAR_BUILDMODE)
dat += "***********************************************************"
dat += "Right Mouse Button on buildmode button = Select var(type) & value"
dat += "Left Mouse Button on turf/obj/mob = Set var(type) & value"
dat += "Right Mouse Button on turf/obj/mob = Reset var's value"
dat += "***********************************************************"
if(THROW_BUILDMODE)
dat += "***********************************************************"
dat += "Left Mouse Button on turf/obj/mob = Select"
dat += "Right Mouse Button on turf/obj/mob = Throw"
dat += "***********************************************************"
if(AREA_BUILDMODE)
dat += "***********************************************************"
dat += "Left Mouse Button on turf/obj/mob = Select corner"
dat += "Right Mouse Button on turf/obj/mob = Reset corner selection"
dat += "Right Mouse Button on buildmode button = Select generator"
dat += "***********************************************************"
if(COPY_BUILDMODE)
dat += "***********************************************************"
dat += "Left Mouse Button on obj/turf/mob = Spawn a Copy of selected target"
dat += "Right Mouse Button on obj/mob = Select target to copy"
dat += "***********************************************************"
to_chat(user, "<font color='blue'>[dat.Join("\n")]</font>")
/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 GLOB.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/list/options = list()
for(var/path in gen_paths)
var/datum/mapGenerator/MP = path
options[initial(MP.buildmode_name)] = path
var/type = input(user,"Select Generator Type","Type") as null|anything in options
if(!type)
return
generator_path = options[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/Reset()//Reset temporary variables
cornerA = null
cornerB = null
/proc/togglebuildmode(mob/M in GLOB.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")
//Clicking on UI elements shouldn't try to build things in nullspace.
if(istype(object,/obj/screen))
return FALSE
. = TRUE
switch(mode)
if(BASIC_BUILDMODE)
if(isturf(object) && left_click && !alt_click && !ctrl_click)
var/turf/T = object
if(isspaceturf(object))
T.PlaceOnTop(/turf/open/floor/plating)
else if(isplatingturf(object))
T.PlaceOnTop(/turf/open/floor/plasteel)
else if(isfloorturf(object))
T.PlaceOnTop(/turf/closed/wall)
else if(iswallturf(object))
T.PlaceOnTop(/turf/closed/wall/r_wall)
log_admin("Build Mode: [key_name(user)] built [T] at [AREACOORD(T)]")
return
else if(right_click)
log_admin("Build Mode: [key_name(user)] deleted [object] at [AREACOORD(object)]")
if(isturf(object))
var/turf/T = object
T.ScrapeAway()
else if(isobj(object))
qdel(object)
return
else if(isturf(object) && alt_click && left_click)
log_admin("Build Mode: [key_name(user)] built an airlock at [AREACOORD(object)]")
new/obj/machinery/door/airlock(get_turf(object))
else if(isturf(object) && ctrl_click && left_click)
var/obj/structure/window/reinforced/window
if(build_dir == NORTHWEST)
window = new /obj/structure/window/reinforced/fulltile(get_turf(object))
else
window = new /obj/structure/window/reinforced(get_turf(object))
window.setDir(build_dir)
log_admin("Build Mode: [key_name(user)] built a window at [AREACOORD(object)]")
if(ADV_BUILDMODE)
if(left_click && alt_click)
objholder = object.type
to_chat(user, "<span class='notice'>[initial(object.name)] ([object.type]) selected.</span>")
else if(left_click)
if(ispath(objholder, /turf))
var/turf/T = get_turf(object)
log_admin("Build Mode: [key_name(user)] modified [T] in [AREACOORD(object)] to [objholder]")
T.PlaceOnTop(objholder)
else
var/obj/A = new objholder (get_turf(object))
A.setDir(build_dir)
log_admin("Build Mode: [key_name(user)] modified [A]'s [COORD(A)] dir to [build_dir]")
else if(right_click)
if(isobj(object))
log_admin("Build Mode: [key_name(user)] deleted [object] at [AREACOORD(object)]")
qdel(object)
if(VAR_BUILDMODE)
if(left_click) //I cant believe this shit actually compiles.
if(object.vars.Find(varholder))
if(object.vv_edit_var(varholder, valueholder))
log_admin("Build Mode: [key_name(user)] modified [object.name]'s [varholder] to [valueholder]")
else
to_chat(user, "<span class='warning'>Varedit rejected</span>")
else
to_chat(user, "<span class='warning'>[initial(object.name)] does not have a var called '[varholder]'</span>")
if(right_click)
if(object.vars.Find(varholder))
if(object.vv_edit_var(varholder, initial(object.vars[varholder])))
log_admin("Build Mode: [key_name(user)] modified [object.name]'s [varholder] to [valueholder]")
else
to_chat(user, "<span class='warning'>Varedit rejected</span>")
else
to_chat(user, "<span class='warning'>[initial(object.name)] does not have a var called '[varholder]'</span>")
if(THROW_BUILDMODE)
if(left_click)
if(isturf(object))
return
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] in [AREACOORD(object)]")
if(AREA_BUILDMODE)
if(left_click) //rectangular
if(!cornerA)
cornerA = get_turf(object)
preview += image('icons/turf/overlays.dmi',cornerA,"greenOverlay")
usr.client.images -= preview
usr.client.images += preview
return
if(cornerA && !cornerB)
cornerB = get_turf(object)
preview += image('icons/turf/overlays.dmi',cornerB,"blueOverlay")
usr.client.images -= preview
usr.client.images += preview
to_chat(user, "<span class='boldwarning'>Region selected, if you're happy with your selection left click again, otherwise right click.</span>")
return
if(cornerA && cornerB)
if(!generator_path)
to_chat(user, "<span class='warning'>Select generator type first.</span>")
return
var/datum/mapGenerator/G = new generator_path
if(istype(G, /datum/mapGenerator/repair/reload_station_map))
if(GLOB.reloading_map)
to_chat(user, "<span class='boldwarning'>You are already reloading an area! Please wait for it to fully finish loading before trying to load another!</span>")
return
G.defineRegion(cornerA, cornerB, 1)
for(var/t in G.map)
preview += image('icons/turf/overlays.dmi', t ,"redOverlay")
usr.client.images -= preview
usr.client.images += preview
var/confirm = alert("Are you sure you want run the map generator?", "Run generator", "Yes", "No")
if(confirm == "Yes")
G.generate()
cornerA = null
cornerB = null
usr.client.images -= preview
preview.Cut()
return
//Something wrong - Reset
cornerA = null
cornerB = null
if(COPY_BUILDMODE)
if(left_click)
var/turf/T = get_turf(object)
if(stored)
DuplicateObject(stored,perfectcopy=1,newloc=T)
else if(right_click)
if(ismovableatom(object)) // No copying turfs for now.
stored = object

View File

@@ -517,6 +517,25 @@ GLOBAL_PROTECT(VVpixelmovement)
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]")
message_admins("[key_name_admin(src)] modified [original_name]'s varlist [objectvar]: [original_var]=[new_var]")
/proc/vv_varname_lockcheck(param_var_name)
if(param_var_name in GLOB.VVlocked)
if(!check_rights(R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVckey_edit)
if(!check_rights(R_SPAWN|R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVicon_edit_lock)
if(!check_rights(R_FUN|R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVpixelmovement)
if(!check_rights(R_DEBUG))
return FALSE
var/prompt = alert(usr, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT")
if (prompt != "Continue")
return FALSE
return TRUE
/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0)
if(!check_rights(R_VAREDIT))
return
@@ -546,26 +565,12 @@ GLOBAL_PROTECT(VVpixelmovement)
return
var_value = O.vars[variable]
if(variable in GLOB.VVlocked)
if(!check_rights(R_DEBUG))
return
if(variable in GLOB.VVckey_edit)
if(!check_rights(R_SPAWN|R_DEBUG))
return
if(variable in GLOB.VVicon_edit_lock)
if(!check_rights(R_FUN|R_DEBUG))
return
if(!vv_varname_lockcheck(variable))
return
if(istype(O, /datum/armor))
var/prompt = alert(src, "Editing this var changes this value on potentially thousands of items that share the same combination of armor values. If you want to edit the armor of just one item, use the \"Modify armor values\" dropdown item", "DANGER", "ABORT ", "Continue", " ABORT")
if (prompt != "Continue")
return
if(variable in GLOB.VVpixelmovement)
if(!check_rights(R_DEBUG))
return
var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT")
if (prompt != "Continue")
return
var/default = vv_get_class(variable, var_value)

View File

@@ -0,0 +1,215 @@
# Buildmode
## Code layout
### Buildmode
Manager for buildmode modes. Contains logic to manage switching between each mode, and presenting a suitable user interface.
### Effects
Special graphics used by buildmode modes for user interface purposes.
### Buildmode Mode
Implementer of buildmode behaviors.
Existing varieties:
+ Basic
**Description**:
Allows creation of simple structures consisting of floors, walls, windows, and airlocks.
**Controls**:
+ *Left click a turf*:
"Upgrades" the turf based on the following rules below:
+ Space -> Tiled floor
+ Simulated floor -> Regular wall
+ Wall -> Reinforced wall
+ *Right click a turf*:
"Downgrades" the turf based on the following rules below:
+ Reinforced wall -> Regular wall
+ Wall -> Tiled floor
+ Simulated floor -> Space
+ *Right click an object*:
Deletes the clicked object.
+ *Alt+Left click a location*:
Places an airlock at the clicked location.
+ *Ctrl+Left click a location*:
Places a window at the clicked location.
+ Advanced
**Description**:
Creates an instance of a configurable atom path where you click.
**Controls**:
+ *Right click on the mode selector*:
Choose a path to spawn.
+ *Left click a location* (requires chosen path):
Place an instance of the chosen path at the location.
+ *Right click an object*:
Delete the object.
+ Fill
**Description**:
Creates an instance of an atom path on every tile in a chosen region.
With a special control input, instead deletes everything within the region.
**Controls**:
+ *Right click on the mode selector*:
Choose a path to spawn.
+ *Left click on a region* (requires chosen path):
Fill the region with the chosen path.
+ *Alt+Left click on a region*:
Deletes everything within the region.
+ *Right click during region selection*:
Cancel region selection.
+ Copy
**Description**:
Take an existing object in the world, and place duplicates with identical attributes where you click.
May not always work nicely - "deep" variables such as lists or datums may malfunction.
**Controls**:
+ *Right click an existing object*:
Select the clicked object as a template.
+ *Left click a location* (Requires a selected object as template):
Place a duplicate of the template at the clicked location.
+ Area Edit
**Description**:
Modifies and creates areas.
The active area will be highlighted in yellow.
**Controls**:
+ *Right click the mode selector*:
Create a new area, and make it active.
+ *Right click an existing area*:
Make the clicked area active.
+ *Left click a turf*:
When an area is active, adds the turf to the active area.
+ Var Edit
**Description**:
Allows for setting and resetting variables of objects with a click.
If the object does not have the var, will do nothing and print a warning message.
**Controls**:
+ *Right click the mode selector*:
Choose which variable to set, and what to set it to.
+ *Left click an atom*:
Change the clicked atom's variables as configured.
+ *Right click an atom*:
Reset the targeted variable to its original value in the code.
+ Map Generator
**Description**:
Fills rectangular regions with algorithmically generated content. Right click during region selection to cancel.
See the `procedural_mapping` module for the generators themselves.
**Controls**:
+ *Right-click on the mode selector*:
Select a map generator from all the generators present in the codebase.
+ *Left click two corners of an area*:
Use the generator to populate the region.
+ *Right click during region selection*:
Cancel region selection.
+ Throwing
**Description**:
Select an object with left click, and right click to throw it towards where you clicked.
**Controls**:
+ *Left click on a movable atom*:
Select the atom for throwing.
+ *Right click on a location*:
Throw the selected atom towards that location.
+ Boom
**Description**:
Make explosions where you click.
**Controls**:
+ *Right click the mode selector*:
Configure the explosion size.
+ *Left click a location*:
Cause an explosion where you clicked.

View File

@@ -0,0 +1,91 @@
/datum/buildmode_mode
var/key = "oops"
var/datum/buildmode/BM
// would corner selection work better as a component?
var/use_corner_selection = FALSE
var/list/preview
var/turf/cornerA
var/turf/cornerB
/datum/buildmode_mode/New(datum/buildmode/BM)
src.BM = BM
preview = list()
return ..()
/datum/buildmode_mode/Destroy()
cornerA = null
cornerB = null
QDEL_LIST(preview)
preview = null
return ..()
/datum/buildmode_mode/proc/enter_mode(datum/buildmode/BM)
return
/datum/buildmode_mode/proc/exit_mode(datum/buildmode/BM)
return
/datum/buildmode_mode/proc/get_button_iconstate()
return "buildmode_[key]"
/datum/buildmode_mode/proc/show_help(client/c)
CRASH("No help defined, yell at a coder")
/datum/buildmode_mode/proc/change_settings(client/c)
to_chat(c, "<span class='warning'>There is no configuration available for this mode</span>")
return
/datum/buildmode_mode/proc/Reset()
deselect_region()
/datum/buildmode_mode/proc/select_tile(turf/T, corner_to_select)
var/overlaystate
BM.holder.images -= preview
switch(corner_to_select)
if(AREASELECT_CORNERA)
overlaystate = "greenOverlay"
if(AREASELECT_CORNERB)
overlaystate = "blueOverlay"
var/image/I = image('icons/turf/overlays.dmi', T, overlaystate)
I.plane = ABOVE_LIGHTING_PLANE
preview += I
BM.holder.images += preview
return T
/datum/buildmode_mode/proc/highlight_region(region)
BM.holder.images -= preview
for(var/t in region)
var/image/I = image('icons/turf/overlays.dmi', t, "redOverlay")
I.plane = ABOVE_LIGHTING_PLANE
preview += I
BM.holder.images += preview
/datum/buildmode_mode/proc/deselect_region()
BM.holder.images -= preview
preview.Cut()
cornerA = null
cornerB = null
/datum/buildmode_mode/proc/handle_click(client/c, params, object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
if(use_corner_selection)
if(left_click)
if(!cornerA)
cornerA = select_tile(get_turf(object), AREASELECT_CORNERA)
return
if(cornerA && !cornerB)
cornerB = select_tile(get_turf(object), AREASELECT_CORNERB)
to_chat(c, "<span class='boldwarning'>Region selected, if you're happy with your selection left click again, otherwise right click.</span>")
return
handle_selected_area(c, params)
deselect_region()
else
to_chat(c, "<span class='notice'>Region selection canceled!</span>")
deselect_region()
return
/datum/buildmode_mode/proc/handle_selected_area(client/c, params)

View File

@@ -0,0 +1,161 @@
#define BM_SWITCHSTATE_NONE 0
#define BM_SWITCHSTATE_MODE 1
#define BM_SWITCHSTATE_DIR 2
/datum/buildmode
var/build_dir = SOUTH
var/datum/buildmode_mode/mode
var/client/holder
// login callback
var/li_cb
// SECTION UI
var/list/buttons
// Switching management
var/switch_state = BM_SWITCHSTATE_NONE
var/switch_width = 5
// modeswitch UI
var/obj/screen/buildmode/mode/modebutton
var/list/modeswitch_buttons = list()
// dirswitch UI
var/obj/screen/buildmode/bdir/dirbutton
var/list/dirswitch_buttons = list()
/datum/buildmode/New(client/c)
mode = new /datum/buildmode_mode/basic(src)
holder = c
buttons = list()
li_cb = CALLBACK(src, .proc/post_login)
holder.player_details.post_login_callbacks += li_cb
holder.show_popup_menus = FALSE
create_buttons()
holder.screen += buttons
holder.click_intercept = src
mode.enter_mode(src)
/datum/buildmode/proc/quit()
mode.exit_mode(src)
holder.screen -= buttons
holder.click_intercept = null
holder.show_popup_menus = TRUE
qdel(src)
/datum/buildmode/Destroy()
close_switchstates()
holder.player_details.post_login_callbacks -= li_cb
holder = null
QDEL_NULL(mode)
QDEL_LIST(modeswitch_buttons)
QDEL_LIST(dirswitch_buttons)
return ..()
/datum/buildmode/proc/post_login()
// since these will get wiped upon login
holder.screen += buttons
// re-open the according switch mode
switch(switch_state)
if(BM_SWITCHSTATE_MODE)
open_modeswitch()
if(BM_SWITCHSTATE_DIR)
open_dirswitch()
/datum/buildmode/proc/create_buttons()
// keep a reference so we can update it upon mode switch
modebutton = new /obj/screen/buildmode/mode(src)
buttons += modebutton
buttons += new /obj/screen/buildmode/help(src)
// keep a reference so we can update it upon dir switch
dirbutton = new /obj/screen/buildmode/bdir(src)
buttons += dirbutton
buttons += new /obj/screen/buildmode/quit(src)
// build the lists of switching buttons
build_options_grid(subtypesof(/datum/buildmode_mode), modeswitch_buttons, /obj/screen/buildmode/modeswitch)
build_options_grid(list(SOUTH,EAST,WEST,NORTH,NORTHWEST), dirswitch_buttons, /obj/screen/buildmode/dirswitch)
// this creates a nice offset grid for choosing between buildmode options,
// because going "click click click ah hell" sucks.
/datum/buildmode/proc/build_options_grid(list/elements, list/buttonslist, buttontype)
var/pos_idx = 0
for(var/thing in elements)
var/x = pos_idx % switch_width
var/y = FLOOR(pos_idx / switch_width, 1)
var/obj/screen/buildmode/B = new buttontype(src, thing)
// extra .5 for a nice offset look
B.screen_loc = "NORTH-[(1 + 0.5 + y*1.5)],WEST+[0.5 + x*1.5]"
buttonslist += B
pos_idx++
/datum/buildmode/proc/close_switchstates()
switch(switch_state)
if(BM_SWITCHSTATE_MODE)
close_modeswitch()
if(BM_SWITCHSTATE_DIR)
close_dirswitch()
/datum/buildmode/proc/toggle_modeswitch()
if(switch_state == BM_SWITCHSTATE_MODE)
close_modeswitch()
else
close_switchstates()
open_modeswitch()
/datum/buildmode/proc/open_modeswitch()
switch_state = BM_SWITCHSTATE_MODE
holder.screen += modeswitch_buttons
/datum/buildmode/proc/close_modeswitch()
switch_state = BM_SWITCHSTATE_NONE
holder.screen -= modeswitch_buttons
/datum/buildmode/proc/toggle_dirswitch()
if(switch_state == BM_SWITCHSTATE_DIR)
close_dirswitch()
else
close_switchstates()
open_dirswitch()
/datum/buildmode/proc/open_dirswitch()
switch_state = BM_SWITCHSTATE_DIR
holder.screen += dirswitch_buttons
/datum/buildmode/proc/close_dirswitch()
switch_state = BM_SWITCHSTATE_NONE
holder.screen -= dirswitch_buttons
/datum/buildmode/proc/change_mode(newmode)
mode.exit_mode(src)
QDEL_NULL(mode)
close_switchstates()
mode = new newmode(src)
mode.enter_mode(src)
modebutton.update_icon()
/datum/buildmode/proc/change_dir(newdir)
build_dir = newdir
close_dirswitch()
dirbutton.update_icon()
return 1
/datum/buildmode/proc/InterceptClickOn(mob/user, params, atom/object)
mode.handle_click(user.client, params, object)
return TRUE // no doing underlying actions
/proc/togglebuildmode(mob/M as mob in GLOB.player_list)
set name = "Toggle Build Mode"
set category = "Event"
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_admin(usr)] has entered build mode.")
log_admin("[key_name(usr)] has entered build mode.")
#undef BM_SWITCHSTATE_NONE
#undef BM_SWITCHSTATE_MODE
#undef BM_SWITCHSTATE_DIR

View File

@@ -0,0 +1,90 @@
/obj/screen/buildmode
icon = 'icons/misc/buildmode.dmi'
var/datum/buildmode/bd
// If we don't do this, we get occluded by item action buttons
layer = ABOVE_HUD_LAYER
/obj/screen/buildmode/New(bld)
bd = bld
return ..()
/obj/screen/buildmode/Destroy()
bd = null
return ..()
/obj/screen/buildmode/mode
name = "Toggle Mode"
icon_state = "buildmode_basic"
screen_loc = "NORTH,WEST"
/obj/screen/buildmode/mode/Click(location, control, params)
var/list/pa = params2list(params)
if(pa.Find("left"))
bd.toggle_modeswitch()
else if(pa.Find("right"))
bd.mode.change_settings(usr.client)
update_icon()
return 1
/obj/screen/buildmode/mode/update_icon()
icon_state = bd.mode.get_button_iconstate()
/obj/screen/buildmode/help
icon_state = "buildhelp"
screen_loc = "NORTH,WEST+1"
name = "Buildmode Help"
/obj/screen/buildmode/help/Click(location, control, params)
bd.mode.show_help(usr.client)
return 1
/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.toggle_dirswitch()
update_icon()
return 1
// used to switch between modes
/obj/screen/buildmode/modeswitch
var/datum/buildmode_mode/modetype
/obj/screen/buildmode/modeswitch/New(bld, mt)
modetype = mt
icon_state = "buildmode_[initial(modetype.key)]"
name = initial(modetype.key)
return ..(bld)
/obj/screen/buildmode/modeswitch/Click()
bd.change_mode(modetype)
return 1
// used to switch between dirs
/obj/screen/buildmode/dirswitch
icon_state = "build"
/obj/screen/buildmode/dirswitch/New(bld, dir)
src.dir = dir
name = dir2text(dir)
return ..(bld)
/obj/screen/buildmode/dirswitch/Click()
bd.change_dir(dir)
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

View File

@@ -0,0 +1,28 @@
/obj/effect/buildmode_line
var/image/I
var/client/cl
/obj/effect/buildmode_line/New(client/C, atom/atom_a, atom/atom_b, linename)
name = linename
loc = get_turf(atom_a)
I = image('icons/misc/mark.dmi', src, "line", 19.0)
var/x_offset = ((atom_b.x * 32) + atom_b.pixel_x) - ((atom_a.x * 32) + atom_a.pixel_x)
var/y_offset = ((atom_b.y * 32) + atom_b.pixel_y) - ((atom_a.y * 32) + atom_a.pixel_y)
var/matrix/mat = matrix()
mat.Translate(0, 16)
mat.Scale(1, sqrt((x_offset * x_offset) + (y_offset * y_offset)) / 32)
mat.Turn(90 - ATAN2(x_offset, y_offset)) // So... You pass coords in order x,y to this version of atan2. It should be called acsc2.
mat.Translate(atom_a.pixel_x, atom_a.pixel_y)
transform = mat
cl = C
cl.images += I
/obj/effect/buildmode_line/Destroy()
if(I)
if(istype(cl))
cl.images -= I
cl = null
QDEL_NULL(I)
return ..()

View File

@@ -0,0 +1,50 @@
/datum/buildmode_mode/advanced
key = "advanced"
var/objholder = null
// FIXME: add logic which adds a button displaying the icon
// of the currently selected path
/datum/buildmode_mode/advanced/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on buildmode button = Set object type</span>")
to_chat(c, "<span class='notice'>Left Mouse Button on turf/obj = Place objects</span>")
to_chat(c, "<span class='notice'>Right Mouse Button = Delete objects</span>")
to_chat(c, "")
to_chat(c, "<span class='notice'>Use the button in the upper left corner to</span>")
to_chat(c, "<span class='notice'>change the direction of built objects.</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/advanced/change_settings(client/c)
var/target_path = input(c, "Enter typepath:", "Typepath", "/obj/structure/closet")
objholder = text2path(target_path)
if(!ispath(objholder))
objholder = pick_closest_path(target_path)
if(!objholder)
alert("No path was selected")
return
else if(ispath(objholder, /area))
objholder = null
alert("That path is not allowed.")
return
/datum/buildmode_mode/advanced/handle_click(client/c, params, obj/object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
var/right_click = pa.Find("right")
if(left_click)
if(ispath(objholder,/turf))
var/turf/T = get_turf(object)
log_admin("Build Mode: [key_name(c)] modified [T] in [AREACOORD(object)] to [objholder]")
T.ChangeTurf(objholder)
else if(!isnull(objholder))
var/obj/A = new objholder (get_turf(object))
A.setDir(BM.build_dir)
log_admin("Build Mode: [key_name(c)] modified [A]'s [COORD(A)] dir to [BM.build_dir]")
else
to_chat(c, "<span class='warning'>Select object type first.</span>")
else if(right_click)
if(isobj(object))
log_admin("Build Mode: [key_name(c)] deleted [object] at [AREACOORD(object)]")
qdel(object)

View File

@@ -0,0 +1,61 @@
/datum/buildmode_mode/area_edit
key = "areaedit"
var/area/storedarea
var/image/areaimage
/datum/buildmode_mode/area_edit/New()
areaimage = image('icons/turf/areas.dmi', null, "yellow")
..()
/datum/buildmode_mode/area_edit/enter_mode(datum/buildmode/BM)
BM.holder.images += areaimage
/datum/buildmode_mode/area_edit/exit_mode(datum/buildmode/BM)
areaimage.loc = null // de-color the area
BM.holder.images -= areaimage
return ..()
/datum/buildmode_mode/area_edit/Destroy()
QDEL_NULL(areaimage)
storedarea = null
return ..()
/datum/buildmode_mode/area_edit/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Left Mouse Button on obj/turf/mob = Paint area</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on obj/turf/mob = Select area to paint</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on buildmode button = Create new area</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/area_edit/change_settings(client/c)
var/target_path = input(c, "Enter typepath:", "Typepath", "/area")
var/areatype = text2path(target_path)
if(ispath(areatype,/area))
var/areaname = input(c, "Enter area name:", "Area name", "Area")
if(!areaname || !length(areaname))
return
storedarea = new areatype
storedarea.power_equip = 0
storedarea.power_light = 0
storedarea.power_environ = 0
storedarea.always_unpowered = 0
storedarea.name = areaname
areaimage.loc = storedarea // color our area
/datum/buildmode_mode/area_edit/handle_click(client/c, params, object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
var/right_click = pa.Find("right")
if(left_click)
if(!storedarea)
to_chat(c, "<span class='warning'>Configure or select the area you want to paint first!</span>")
return
var/turf/T = get_turf(object)
if(get_area(T) != storedarea)
log_admin("Build Mode: [key_name(c)] added [AREACOORD(T)] to [storedarea]")
storedarea.contents.Add(T)
else if(right_click)
var/turf/T = get_turf(object)
storedarea = get_area(T)
areaimage.loc = storedarea // color our area

View File

@@ -0,0 +1,52 @@
/datum/buildmode_mode/basic
key = "basic"
/datum/buildmode_mode/basic/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Left Mouse Button = Construct / Upgrade</span>")
to_chat(c, "<span class='notice'>Right Mouse Button = Deconstruct / Delete / Downgrade</span>")
to_chat(c, "<span class='notice'>Left Mouse Button + ctrl = R-Window</span>")
to_chat(c, "<span class='notice'>Left Mouse Button + alt = Airlock</span>")
to_chat(c, "")
to_chat(c, "<span class='notice'>Use the button in the upper left corner to</span>")
to_chat(c, "<span class='notice'>change the direction of built objects.</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/basic/handle_click(client/c, params, obj/object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
var/right_click = pa.Find("right")
var/ctrl_click = pa.Find("ctrl")
var/alt_click = pa.Find("alt")
if(istype(object,/turf) && left_click && !alt_click && !ctrl_click)
var/turf/T = object
if(isspaceturf(object))
T.PlaceOnTop(/turf/open/floor/plating)
else if(isplatingturf(object))
T.PlaceOnTop(/turf/open/floor/plasteel)
else if(isfloorturf(object))
T.PlaceOnTop(/turf/closed/wall)
else if(iswallturf(object))
T.PlaceOnTop(/turf/closed/wall/r_wall)
log_admin("Build Mode: [key_name(c)] built [T] at [AREACOORD(T)]")
return
else if(right_click)
log_admin("Build Mode: [key_name(c)] deleted [object] at [AREACOORD(object)]")
if(isturf(object))
var/turf/T = object
T.ScrapeAway()
else if(isobj(object))
qdel(object)
return
else if(istype(object,/turf) && alt_click && left_click)
log_admin("Build Mode: [key_name(c)] built an airlock at [AREACOORD(object)]")
new/obj/machinery/door/airlock(get_turf(object))
else if(istype(object,/turf) && ctrl_click && left_click)
var/obj/structure/window/reinforced/window
if(BM.build_dir == NORTHWEST)
window = new /obj/structure/window/reinforced/fulltile(get_turf(object))
else
window = new /obj/structure/window/reinforced(get_turf(object))
window.setDir(BM.build_dir)
log_admin("Build Mode: [key_name(c)] built a window at [AREACOORD(object)]")

View File

@@ -0,0 +1,38 @@
/datum/buildmode_mode/boom
key = "boom"
var/devastation = -1
var/heavy = -1
var/light = -1
var/flash = -1
var/flames = -1
/datum/buildmode_mode/boom/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Mouse Button on obj = Kaboom</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/boom/change_settings(client/c)
devastation = input(c, "Range of total devastation. -1 to none", text("Input")) as num|null
if(devastation == null)
devastation = -1
heavy = input(c, "Range of heavy impact. -1 to none", text("Input")) as num|null
if(heavy == null)
heavy = -1
light = input(c, "Range of light impact. -1 to none", text("Input")) as num|null
if(light == null)
light = -1
flash = input(c, "Range of flash. -1 to none", text("Input")) as num|null
if(flash == null)
flash = -1
flames = input(c, "Range of flames. -1 to none", text("Input")) as num|null
if(flames == null)
flames = -1
/datum/buildmode_mode/boom/handle_click(client/c, params, obj/object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
if(left_click)
explosion(object, devastation, heavy, light, flash, FALSE, TRUE, flames)
log_admin("Build Mode: [key_name(c)] caused an explosion(dev=[devastation], hvy=[heavy], lgt=[light], flash=[flash], flames=[flames]) at [AREACOORD(object)]")

View File

@@ -0,0 +1,28 @@
/datum/buildmode_mode/copy
key = "copy"
var/atom/movable/stored = null
/datum/buildmode_mode/copy/Destroy()
stored = null
return ..()
/datum/buildmode_mode/copy/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Left Mouse Button on obj/turf/mob = Spawn a Copy of selected target</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on obj/mob = Select target to copy</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/copy/handle_click(client/c, params, obj/object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
var/right_click = pa.Find("right")
if(left_click)
var/turf/T = get_turf(object)
if(stored)
DuplicateObject(stored, perfectcopy=1, sameloc=0,newloc=T)
log_admin("Build Mode: [key_name(c)] copied [stored] to [AREACOORD(object)]")
else if(right_click)
if(ismovableatom(object)) // No copying turfs for now.
to_chat(c, "<span class='notice'>[object] set as template.</span>")
stored = object

View File

@@ -0,0 +1,62 @@
/datum/buildmode_mode/fill
key = "fill"
use_corner_selection = TRUE
var/objholder = null
/datum/buildmode_mode/fill/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Left Mouse Button on turf/obj/mob = Select corner</span>")
to_chat(c, "<span class='notice'>Left Mouse Button + Alt on turf/obj/mob = Delete region</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on buildmode button = Select object type</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/fill/change_settings(client/c)
var/target_path = input(c, "Enter typepath:" ,"Typepath","/obj/structure/closet")
objholder = text2path(target_path)
if(!ispath(objholder))
objholder = pick_closest_path(target_path)
if(!objholder)
alert("No path has been selected.")
return
else if(ispath(objholder, /area))
objholder = null
alert("Area paths are not supported for this mode, use the area edit mode instead.")
return
deselect_region()
/datum/buildmode_mode/fill/handle_click(client/c, params, obj/object)
if(isnull(objholder))
to_chat(c, "<span class='warning'>Select an object type first.</span>")
deselect_region()
return
..()
/datum/buildmode_mode/fill/handle_selected_area(client/c, params)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
var/alt_click = pa.Find("alt")
if(left_click) //rectangular
if(alt_click)
var/list/deletion_area = block(get_turf(cornerA),get_turf(cornerB))
for(var/beep in deletion_area)
var/turf/T = beep
for(var/atom/movable/AM in T)
qdel(AM)
// extreme haircut
T.ScrapeAway(INFINITY, CHANGETURF_DEFER_CHANGE)
for(var/beep in deletion_area)
var/turf/T = beep
T.AfterChange()
log_admin("Build Mode: [key_name(c)] deleted turfs from [AREACOORD(cornerA)] through [AREACOORD(cornerB)]")
// if there's an analogous proc for this on tg lmk
// empty_region(block(get_turf(cornerA),get_turf(cornerB)))
else
for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
if(ispath(objholder,/turf))
T.PlaceOnTop(objholder)
else
var/obj/A = new objholder(T)
A.setDir(BM.build_dir)
log_admin("Build Mode: [key_name(c)] with path [objholder], filled the region from [AREACOORD(cornerA)] through [AREACOORD(cornerB)]")

View File

@@ -0,0 +1,48 @@
/datum/buildmode_mode/mapgen
key = "mapgen"
use_corner_selection = TRUE
var/generator_path
/datum/buildmode_mode/mapgen/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Left Mouse Button on turf/obj/mob = Select corner</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on buildmode button = Select generator</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/mapgen/change_settings(client/c)
var/list/gen_paths = subtypesof(/datum/mapGenerator)
var/list/options = list()
for(var/path in gen_paths)
var/datum/mapGenerator/MP = path
options[initial(MP.buildmode_name)] = path
var/type = input(c,"Select Generator Type","Type") as null|anything in options
if(!type)
return
generator_path = options[type]
deselect_region()
/datum/buildmode_mode/mapgen/handle_click(client/c, params, obj/object)
if(isnull(generator_path))
to_chat(c, "<span class='warning'>Select generator type first.</span>")
deselect_region()
return
..()
/datum/buildmode_mode/mapgen/handle_selected_area(client/c, params)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
if(left_click)
var/datum/mapGenerator/G = new generator_path
if(istype(G, /datum/mapGenerator/repair/reload_station_map))
if(GLOB.reloading_map)
to_chat(c, "<span class='boldwarning'>You are already reloading an area! Please wait for it to fully finish loading before trying to load another!</span>")
deselect_region()
return
G.defineRegion(cornerA, cornerB, 1)
highlight_region(G.map)
var/confirm = alert("Are you sure you want run the map generator?", "Run generator", "Yes", "No")
if(confirm == "Yes")
G.generate()
log_admin("Build Mode: [key_name(c)] ran the map generator '[G.buildmode_name]' in the region from [AREACOORD(cornerA)] to [AREACOORD(cornerB)]")

View File

@@ -0,0 +1,29 @@
/datum/buildmode_mode/throwing
key = "throw"
var/atom/movable/throw_atom = null
/datum/buildmode_mode/throwing/Destroy()
throw_atom = null
return ..()
/datum/buildmode_mode/throwing/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Left Mouse Button on turf/obj/mob = Select</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on turf/obj/mob = Throw</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/throwing/handle_click(client/c, params, obj/object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
var/right_click = pa.Find("right")
if(left_click)
if(isturf(object))
return
throw_atom = object
to_chat(c, "Selected object '[throw_atom]'")
if(right_click)
if(throw_atom)
throw_atom.throw_at(object, 10, 1, c.mob)
log_admin("Build Mode: [key_name(c)] threw [throw_atom] at [object] ([AREACOORD(object)])")

View File

@@ -0,0 +1,62 @@
/datum/buildmode_mode/varedit
key = "edit"
// Varedit mode
var/varholder = null
var/valueholder = null
/datum/buildmode_mode/varedit/Destroy()
varholder = null
valueholder = null
return ..()
/datum/buildmode_mode/varedit/show_help(client/c)
to_chat(c, "<span class='notice'>***********************************************************</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on buildmode button = Select var(type) & value</span>")
to_chat(c, "<span class='notice'>Left Mouse Button on turf/obj/mob = Set var(type) & value</span>")
to_chat(c, "<span class='notice'>Right Mouse Button on turf/obj/mob = Reset var's value</span>")
to_chat(c, "<span class='notice'>***********************************************************</span>")
/datum/buildmode_mode/varedit/Reset()
. = ..()
varholder = null
valueholder = null
/datum/buildmode_mode/varedit/change_settings(client/c)
varholder = input(c, "Enter variable name:" ,"Name", "name")
if(!vv_varname_lockcheck(varholder))
return
var/temp_value = c.vv_get_value()
if(isnull(temp_value["class"]))
Reset()
to_chat(c, "<span class='notice'>Variable unset.</span>")
return
valueholder = temp_value["value"]
/datum/buildmode_mode/varedit/handle_click(client/c, params, obj/object)
var/list/pa = params2list(params)
var/left_click = pa.Find("left")
var/right_click = pa.Find("right")
if(isnull(varholder))
to_chat(c, "<span class='warning'>Choose a variable to modify first.</span>")
return
if(left_click)
if(object.vars.Find(varholder))
if(object.vv_edit_var(varholder, valueholder) == FALSE)
to_chat(c, "<span class='warning'>Your edit was rejected by the object.</span>")
return
log_admin("Build Mode: [key_name(c)] modified [object.name]'s [varholder] to [valueholder]")
else
to_chat(c, "<span class='warning'>[initial(object.name)] does not have a var called '[varholder]'</span>")
if(right_click)
if(object.vars.Find(varholder))
var/reset_value = initial(object.vars[varholder])
if(object.vv_edit_var(varholder, reset_value) == FALSE)
to_chat(c, "<span class='warning'>Your edit was rejected by the object.</span>")
return
log_admin("Build Mode: [key_name(c)] modified [object.name]'s [varholder] to [reset_value]")
else
to_chat(c, "<span class='warning'>[initial(object.name)] does not have a var called '[varholder]'</span>")

View File

@@ -1,4 +1,6 @@
/datum/player_details
var/list/player_actions = list()
var/list/logging = list()
var/list/post_login_callbacks = list()
var/list/post_logout_callbacks = list()
var/byond_version = "Unknown"

View File

@@ -41,12 +41,14 @@
update_client_colour()
update_mouse_pointer()
if(client)
client.click_intercept = null
client.change_view(CONFIG_GET(string/default_view)) // Resets the client.view in case it was changed.
if(client.player_details.player_actions.len)
for(var/datum/action/A in client.player_details.player_actions)
A.Grant(src)
for(var/foo in client.player_details.post_login_callbacks)
var/datum/callback/CB = foo
CB.Invoke()
log_message("Client [key_name(src)] has taken ownership of mob [src]", LOG_OWNERSHIP)

View File

@@ -8,5 +8,10 @@
if(loc)
loc.on_log(FALSE)
if(client)
for(var/foo in client.player_details.post_logout_callbacks)
var/datum/callback/CB = foo
CB.Invoke()
return TRUE

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1004 B

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1087,7 +1087,6 @@
#include "code\modules\admin\verbs\bluespacearty.dm"
#include "code\modules\admin\verbs\borgpanel.dm"
#include "code\modules\admin\verbs\BrokenInhands.dm"
#include "code\modules\admin\verbs\buildmode.dm"
#include "code\modules\admin\verbs\cinematic.dm"
#include "code\modules\admin\verbs\deadsay.dm"
#include "code\modules\admin\verbs\debug.dm"
@@ -1370,6 +1369,19 @@
#include "code\modules\awaymissions\mission_code\undergroundoutpost45.dm"
#include "code\modules\awaymissions\mission_code\wildwest.dm"
#include "code\modules\bsql\includes.dm"
#include "code\modules\buildmode\bm_mode.dm"
#include "code\modules\buildmode\buildmode.dm"
#include "code\modules\buildmode\buttons.dm"
#include "code\modules\buildmode\effects\line.dm"
#include "code\modules\buildmode\submodes\advanced.dm"
#include "code\modules\buildmode\submodes\area_edit.dm"
#include "code\modules\buildmode\submodes\basic.dm"
#include "code\modules\buildmode\submodes\boom.dm"
#include "code\modules\buildmode\submodes\copy.dm"
#include "code\modules\buildmode\submodes\fill.dm"
#include "code\modules\buildmode\submodes\mapgen.dm"
#include "code\modules\buildmode\submodes\throwing.dm"
#include "code\modules\buildmode\submodes\variable_edit.dm"
#include "code\modules\cargo\bounty.dm"
#include "code\modules\cargo\bounty_console.dm"
#include "code\modules\cargo\console.dm"

View File

@@ -1091,7 +1091,6 @@
#include "code\modules\admin\verbs\bluespacearty.dm"
#include "code\modules\admin\verbs\borgpanel.dm"
#include "code\modules\admin\verbs\BrokenInhands.dm"
#include "code\modules\admin\verbs\buildmode.dm"
#include "code\modules\admin\verbs\cinematic.dm"
#include "code\modules\admin\verbs\deadsay.dm"
#include "code\modules\admin\verbs\debug.dm"
@@ -1372,6 +1371,19 @@
#include "code\modules\awaymissions\mission_code\undergroundoutpost45.dm"
#include "code\modules\awaymissions\mission_code\wildwest.dm"
#include "code\modules\bsql\includes.dm"
#include "code\modules\buildmode\bm_mode.dm"
#include "code\modules\buildmode\buildmode.dm"
#include "code\modules\buildmode\buttons.dm"
#include "code\modules\buildmode\effects\line.dm"
#include "code\modules\buildmode\submodes\advanced.dm"
#include "code\modules\buildmode\submodes\area_edit.dm"
#include "code\modules\buildmode\submodes\basic.dm"
#include "code\modules\buildmode\submodes\boom.dm"
#include "code\modules\buildmode\submodes\copy.dm"
#include "code\modules\buildmode\submodes\fill.dm"
#include "code\modules\buildmode\submodes\mapgen.dm"
#include "code\modules\buildmode\submodes\throwing.dm"
#include "code\modules\buildmode\submodes\variable_edit.dm"
#include "code\modules\cargo\bounty.dm"
#include "code\modules\cargo\bounty_console.dm"
#include "code\modules\cargo\console.dm"