Revert "Merge branch 'master' of https://github.com/PolarisSS13/Polaris into NanoGrade"
This reverts commit6bb5409349, reversing changes made tof6a83d5ee0.
@@ -6,11 +6,9 @@ env:
|
||||
BYOND_MAJOR="510"
|
||||
BYOND_MINOR="1346"
|
||||
MACRO_COUNT=986
|
||||
NODE_VERSION="4"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- tgui/node_modules
|
||||
- $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}
|
||||
|
||||
addons:
|
||||
@@ -21,13 +19,10 @@ addons:
|
||||
- libstdc++6:i386
|
||||
|
||||
before_script:
|
||||
- cd tgui && npm install && cd ..
|
||||
- chmod +x ./install-byond.sh
|
||||
- ./install-byond.sh
|
||||
|
||||
install:
|
||||
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $NODE_VERSION
|
||||
- npm install -g gulp-cli
|
||||
- pip install --user PyYaml -q
|
||||
- pip install --user beautifulsoup4 -q
|
||||
|
||||
@@ -39,8 +34,6 @@ script:
|
||||
- awk -f tools/indentation.awk **/*.dm
|
||||
- md5sum -c - <<< "88490b460c26947f5ec1ab1bb9fa9f17 *html/changelogs/example.yml"
|
||||
- (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ])
|
||||
- cd tgui && gulp
|
||||
- cd ..
|
||||
- source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup
|
||||
- python tools/TagMatcher/tag-matcher.py ../..
|
||||
- echo "#define UNIT_TEST 1" > code/_unit_tests.dm
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#define UI_INTERACTIVE 2 // Green/Interactive
|
||||
#define UI_UPDATE 1 // Orange/Updates Only
|
||||
#define UI_DISABLED 0 // Red/Disabled
|
||||
#define UI_CLOSE -1 // Closed
|
||||
@@ -1,5 +0,0 @@
|
||||
#define TICK_LIMIT_RUNNING 90
|
||||
#define TICK_LIMIT_TO_RUN 85
|
||||
|
||||
#define TICK_CHECK ( world.tick_usage > TICK_LIMIT_RUNNING ? stoplag() : 0 )
|
||||
#define CHECK_TICK if(world.tick_usage > TICK_LIMIT_RUNNING) stoplag()
|
||||
@@ -1,22 +1,6 @@
|
||||
#if DM_VERSION < 510
|
||||
|
||||
//Case Sensitive!
|
||||
/proc/text2listEx(text, delimiter="\n")
|
||||
var/delim_len = length(delimiter)
|
||||
if(delim_len < 1) return list(text)
|
||||
. = list()
|
||||
var/last_found = 1
|
||||
var/found
|
||||
do
|
||||
found = findtextEx(text, delimiter, last_found, 0)
|
||||
. += copytext(text, last_found, found)
|
||||
last_found = found + delim_len
|
||||
while(found)
|
||||
|
||||
/proc/replacetext(text, find, replacement)
|
||||
return jointext(splittext(text, find), replacement)
|
||||
|
||||
/proc/replacetextEx(text, find, replacement)
|
||||
return jointext(text2listEx(text, find), replacement)
|
||||
|
||||
#endif
|
||||
@@ -1,28 +0,0 @@
|
||||
/proc/get_turf_pixel(atom/movable/AM)
|
||||
if(!istype(AM))
|
||||
return
|
||||
|
||||
//Find AM's matrix so we can use it's X/Y pixel shifts
|
||||
var/matrix/M = matrix(AM.transform)
|
||||
|
||||
var/pixel_x_offset = AM.pixel_x + M.get_x_shift()
|
||||
var/pixel_y_offset = AM.pixel_y + M.get_y_shift()
|
||||
|
||||
//Irregular objects
|
||||
if(AM.bound_height != world.icon_size || AM.bound_width != world.icon_size)
|
||||
var/icon/AMicon = icon(AM.icon, AM.icon_state)
|
||||
pixel_x_offset += ((AMicon.Width()/world.icon_size)-1)*(world.icon_size*0.5)
|
||||
pixel_y_offset += ((AMicon.Height()/world.icon_size)-1)*(world.icon_size*0.5)
|
||||
qdel(AMicon)
|
||||
|
||||
//DY and DX
|
||||
var/rough_x = round(round(pixel_x_offset,world.icon_size)/world.icon_size)
|
||||
var/rough_y = round(round(pixel_y_offset,world.icon_size)/world.icon_size)
|
||||
|
||||
//Find coordinates
|
||||
var/turf/T = get_turf(AM) //use AM's turfs, as it's coords are the same as AM's AND AM's coords are lost if it is inside another atom
|
||||
var/final_x = T.x + rough_x
|
||||
var/final_y = T.y + rough_y
|
||||
|
||||
if(final_x || final_y)
|
||||
return locate(final_x, final_y, T.z)
|
||||
@@ -323,30 +323,6 @@ proc/listclearnulls(list/list)
|
||||
return (result + L.Copy(Li, 0))
|
||||
return (result + R.Copy(Ri, 0))
|
||||
|
||||
/proc/sortByVar(var/list/L, var/key)
|
||||
if(L.len < 2)
|
||||
return L
|
||||
var/middle = L.len / 2 + 1
|
||||
return mergeVaredLists(sortByVar(L.Copy(0, middle), key), sortByVar(L.Copy(middle), key), key)
|
||||
|
||||
/proc/mergeVaredLists(var/list/L, var/list/R, var/key)
|
||||
var/Li=1
|
||||
var/Ri=1
|
||||
var/list/result = new()
|
||||
while(Li <= L.len && Ri <= R.len)
|
||||
var/datum/LO = L[Li]
|
||||
var/datum/RO = R[Ri]
|
||||
if(LO.vars[key] > RO.vars[key])
|
||||
// Works around list += list2 merging lists; it's not pretty but it works
|
||||
result += "temp item"
|
||||
result[result.len] = R[Ri++]
|
||||
else
|
||||
result += "temp item"
|
||||
result[result.len] = L[Li++]
|
||||
|
||||
if(Li <= L.len)
|
||||
return (result + L.Copy(Li, 0))
|
||||
return (result + R.Copy(Ri, 0))
|
||||
|
||||
//Mergesort: any value in a list, preserves key=value structure
|
||||
/proc/sortAssoc(var/list/L)
|
||||
|
||||
@@ -82,13 +82,6 @@
|
||||
if(config.log_world_output)
|
||||
diary << "\[[time_stamp()]]DD_OUTPUT: [text][log_end]"
|
||||
|
||||
/*
|
||||
Standardized method for tracking startup times.
|
||||
*/
|
||||
/proc/log_startup_progress(var/message)
|
||||
admin_notice("<span class='danger'>[message]</span>", R_DEBUG)
|
||||
log_to_dd(message)
|
||||
|
||||
/proc/log_misc(text)
|
||||
diary << "\[[time_stamp()]]MISC: [text][log_end]"
|
||||
|
||||
|
||||
@@ -15,11 +15,3 @@
|
||||
animate(src, transform = m120, time = speed, loops)
|
||||
animate(transform = m240, time = speed)
|
||||
animate(transform = m360, time = speed)
|
||||
|
||||
//The X pixel offset of this matrix
|
||||
/matrix/proc/get_x_shift()
|
||||
. = c
|
||||
|
||||
//The Y pixel offset of this matrix
|
||||
/matrix/proc/get_y_shift()
|
||||
. = f
|
||||
@@ -100,16 +100,4 @@ var/round_start_time = 0
|
||||
|
||||
/hook/startup/proc/set_roundstart_hour()
|
||||
roundstart_hour = pick(2,7,12,17)
|
||||
return 1
|
||||
/*
|
||||
Returns "watch handle" (really just a timestamp)
|
||||
*/
|
||||
/proc/start_watch()
|
||||
return world.timeofday
|
||||
|
||||
/*
|
||||
Returns number of seconds elapsed.
|
||||
@param wh number The "Watch Handle" from start_watch(). (timestamp)
|
||||
*/
|
||||
/proc/stop_watch(wh)
|
||||
return round(0.1*(world.timeofday-wh),0.1)
|
||||
return 1
|
||||
@@ -1315,15 +1315,3 @@ var/mob/dview/dview_mob = new
|
||||
tY = max(1, min(world.maxy, origin.y + (text2num(tY) - (world.view + 1))))
|
||||
return locate(tX, tY, tZ)
|
||||
|
||||
//Key thing that stops lag. Cornerstone of performance in ss13, Just sitting here, in unsorted.dm.
|
||||
/proc/stoplag()
|
||||
. = 1
|
||||
sleep(world.tick_lag)
|
||||
if(world.tick_usage > TICK_LIMIT_TO_RUN) //woke up, still not enough tick, sleep for more.
|
||||
. += 2
|
||||
sleep(world.tick_lag*2)
|
||||
if(world.tick_usage > TICK_LIMIT_TO_RUN) //woke up, STILL not enough tick, sleep for more.
|
||||
. += 4
|
||||
sleep(world.tick_lag*4)
|
||||
//you might be thinking of adding more steps to this, or making it use a loop and a counter var
|
||||
// not worth it.
|
||||
@@ -66,9 +66,6 @@ world/loop_checks = 0
|
||||
testing("GC: [refID] old enough to test: GCd_at_time: [GCd_at_time] time_to_kill: [time_to_kill] current: [world.time]")
|
||||
#endif
|
||||
if(A && A.gcDestroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
|
||||
#ifdef GC_FINDREF
|
||||
LocateReferences(A)
|
||||
#endif
|
||||
// Something's still referring to the qdel'd object. Kill it.
|
||||
testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --")
|
||||
logging["[A.type]"]++
|
||||
@@ -91,47 +88,29 @@ world/loop_checks = 0
|
||||
#undef GC_COLLECTIONS_PER_TICK
|
||||
|
||||
#ifdef GC_FINDREF
|
||||
|
||||
/datum/controller/process/garbage_collector/proc/LocateReferences(var/atom/A)
|
||||
testing("GC: Attempting to locate references to [A] | [A.type]. This is a potentially long-running operation.")
|
||||
if(istype(A))
|
||||
if(A.loc != null)
|
||||
testing("GC: [A] | [A.type] is located in [A.loc] instead of null")
|
||||
if(A.contents.len)
|
||||
testing("GC: [A] | [A.type] has contents: [jointext(A.contents)]")
|
||||
var/ref_count = 0
|
||||
for(var/atom/atom)
|
||||
ref_count += LookForRefs(atom, A)
|
||||
for(var/datum/datum) // This is strictly /datum, not subtypes.
|
||||
ref_count += LookForRefs(datum, A)
|
||||
for(var/client/client)
|
||||
ref_count += LookForRefs(client, A)
|
||||
var/message = "GC: References found to [A] | [A.type]: [ref_count]."
|
||||
if(!ref_count)
|
||||
message += " Has likely been supplied as an 'in list' argment to a proc."
|
||||
testing(message)
|
||||
|
||||
/datum/controller/process/garbage_collector/proc/LookForRefs(var/datum/D, var/datum/A)
|
||||
/datum/controller/process/garbage_collector/proc/LookForRefs(var/datum/D, var/list/targ)
|
||||
. = 0
|
||||
for(var/V in D.vars)
|
||||
if(V == "contents")
|
||||
continue
|
||||
if(!islist(D.vars[V]))
|
||||
if(D.vars[V] == A)
|
||||
if(istype(D.vars[V], /atom))
|
||||
var/atom/A = D.vars[V]
|
||||
if(A in targ)
|
||||
testing("GC: [A] | [A.type] referenced by [D] | [D.type], var [V]")
|
||||
. += 1
|
||||
else
|
||||
. += LookForListRefs(D.vars[V], A, D, V)
|
||||
else if(islist(D.vars[V]))
|
||||
. += LookForListRefs(D.vars[V], targ, D, V)
|
||||
|
||||
/datum/controller/process/garbage_collector/proc/LookForListRefs(var/list/L, var/datum/A, var/datum/D, var/V)
|
||||
/datum/controller/process/garbage_collector/proc/LookForListRefs(var/list/L, var/list/targ, var/datum/D, var/V)
|
||||
. = 0
|
||||
for(var/F in L)
|
||||
if(!islist(F))
|
||||
if(F == A || L[F] == A)
|
||||
if(istype(F, /atom))
|
||||
var/atom/A = F
|
||||
if(A in targ)
|
||||
testing("GC: [A] | [A.type] referenced by [D] | [D.type], list [V]")
|
||||
. += 1
|
||||
else
|
||||
. += LookForListRefs(F, A, D, "[F] in list [V]")
|
||||
if(islist(F))
|
||||
. += LookForListRefs(F, targ, D, "[F] in list [V]")
|
||||
#endif
|
||||
|
||||
/datum/controller/process/garbage_collector/proc/AddTrash(datum/A)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
var/global/datum/controller/process/tgui/tgui_process
|
||||
|
||||
/datum/controller/process/tgui
|
||||
var/list/tg_open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
|
||||
var/list/processing_uis = list() // A list of processing UIs, ungrouped.
|
||||
var/basehtml // The HTML base used for all UIs.
|
||||
|
||||
/datum/controller/process/tgui/setup()
|
||||
name = "tgui"
|
||||
schedule_interval = 10 // every 2 seconds
|
||||
start_delay = 23
|
||||
|
||||
basehtml = file2text('tgui/tgui.html') // Read the HTML from disk.
|
||||
tgui_process = src
|
||||
|
||||
/datum/controller/process/tgui/doWork()
|
||||
for(var/gui in processing_uis)
|
||||
var/datum/tgui/ui = gui
|
||||
if(ui && ui.user && ui.src_object)
|
||||
ui.process()
|
||||
SCHECK
|
||||
continue
|
||||
processing_uis.Remove(ui)
|
||||
SCHECK
|
||||
|
||||
/datum/controller/process/tgui/statProcess()
|
||||
..()
|
||||
stat(null, "[tgui_process.processing_uis.len] UI\s")
|
||||
@@ -21,13 +21,11 @@ datum/controller/game_controller/New()
|
||||
qdel(master_controller)
|
||||
master_controller = src
|
||||
|
||||
var/watch = 0
|
||||
if(!job_master)
|
||||
watch = start_watch()
|
||||
job_master = new /datum/controller/occupations()
|
||||
job_master.SetupOccupations()
|
||||
job_master.LoadJobs("config/jobs.txt")
|
||||
log_startup_progress("Job setup complete in [stop_watch(watch)]s.")
|
||||
admin_notice("<span class='danger'>Job setup complete</span>", R_DEBUG)
|
||||
|
||||
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
|
||||
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
|
||||
@@ -46,56 +44,31 @@ datum/controller/game_controller/proc/setup()
|
||||
|
||||
|
||||
datum/controller/game_controller/proc/setup_objects()
|
||||
var/watch = start_watch()
|
||||
var/count = 0
|
||||
var/overwatch = start_watch() //Overall.
|
||||
|
||||
log_startup_progress("Populating asset cache...")
|
||||
populate_asset_cache()
|
||||
log_startup_progress(" Populated [asset_cache.len] assets in [stop_watch(watch)]s.")
|
||||
|
||||
watch = start_watch()
|
||||
log_startup_progress("Initializing objects")
|
||||
// sleep(-1)
|
||||
admin_notice("<span class='danger'>Initializing objects</span>", R_DEBUG)
|
||||
sleep(-1)
|
||||
for(var/atom/movable/object in world)
|
||||
if(isnull(object.gcDestroyed))
|
||||
object.initialize()
|
||||
count++
|
||||
log_startup_progress(" Initialized [count] objects in [stop_watch(watch)]s.")
|
||||
|
||||
watch = start_watch()
|
||||
count = 0
|
||||
log_startup_progress("Initializing areas")
|
||||
// sleep(-1)
|
||||
admin_notice("<span class='danger'>Initializing areas</span>", R_DEBUG)
|
||||
sleep(-1)
|
||||
for(var/area/area in all_areas)
|
||||
area.initialize()
|
||||
count++
|
||||
log_startup_progress(" Initialized [count] areas in [stop_watch(watch)]s.")
|
||||
|
||||
watch = start_watch()
|
||||
count = 0
|
||||
log_startup_progress("Initializing pipe networks")
|
||||
// sleep(-1)
|
||||
admin_notice("<span class='danger'>Initializing pipe networks</span>", R_DEBUG)
|
||||
sleep(-1)
|
||||
for(var/obj/machinery/atmospherics/machine in machines)
|
||||
machine.build_network()
|
||||
count++
|
||||
log_startup_progress(" Initialized [count] pipe networks in [stop_watch(watch)]s.")
|
||||
|
||||
watch = start_watch()
|
||||
count = 0
|
||||
log_startup_progress("Initializing atmos machinery.")
|
||||
// sleep(-1)
|
||||
admin_notice("<span class='danger'>Initializing atmos machinery.</span>", R_DEBUG)
|
||||
sleep(-1)
|
||||
for(var/obj/machinery/atmospherics/unary/U in machines)
|
||||
if(istype(U, /obj/machinery/atmospherics/unary/vent_pump))
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/T = U
|
||||
T.broadcast_status()
|
||||
count++
|
||||
else if(istype(U, /obj/machinery/atmospherics/unary/vent_scrubber))
|
||||
var/obj/machinery/atmospherics/unary/vent_scrubber/T = U
|
||||
T.broadcast_status()
|
||||
count++
|
||||
log_startup_progress(" Initialized [count] atmospherics devices in [stop_watch(watch)]s.")
|
||||
log_startup_progress("Finished object initializations in [stop_watch(overwatch)]s.")
|
||||
|
||||
// Set up antagonists.
|
||||
populate_antag_type_list()
|
||||
@@ -103,5 +76,5 @@ datum/controller/game_controller/proc/setup_objects()
|
||||
//Set up spawn points.
|
||||
populate_spawn_points()
|
||||
|
||||
log_startup_progress("Initializations complete.")
|
||||
// sleep(-1)
|
||||
admin_notice("<span class='danger'>Initializations complete.</span>", R_DEBUG)
|
||||
sleep(-1)
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/datum
|
||||
var/weakref
|
||||
|
||||
/datum/Destroy()
|
||||
weakref = null // Clear this reference to ensure it's kept for as brief duration as possible.
|
||||
. = ..()
|
||||
|
||||
//obtain a weak reference to a datum
|
||||
/proc/weakref(datum/D)
|
||||
if(D.gcDestroyed)
|
||||
return
|
||||
if(!D.weakref)
|
||||
D.weakref = new /datum/weakref(D)
|
||||
return D.weakref
|
||||
|
||||
/datum/weakref
|
||||
var/ref
|
||||
|
||||
/datum/weakref/New(datum/D)
|
||||
ref = "\ref[D]"
|
||||
|
||||
/datum/weakref/Destroy()
|
||||
// A weakref datum should not be manually destroyed as it is a shared resource,
|
||||
// rather it should be automatically collected by the BYOND GC when all references are gone.
|
||||
return 0
|
||||
|
||||
/datum/weakref/proc/resolve()
|
||||
var/datum/D = locate(ref)
|
||||
if(D && D.weakref == src)
|
||||
return D
|
||||
return null
|
||||
@@ -286,7 +286,6 @@
|
||||
occupantData["name"] = H.name
|
||||
occupantData["stat"] = H.stat
|
||||
occupantData["health"] = H.health
|
||||
occupantData["maxHealth"] = H.maxHealth
|
||||
|
||||
occupantData["hasVirus"] = H.virus2.len
|
||||
|
||||
@@ -310,7 +309,6 @@
|
||||
var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
|
||||
bloodData["volume"] = blood_volume
|
||||
bloodData["percent"] = round(((blood_volume / 560)*100))
|
||||
bloodData["bloodLevel"] = round(H.vessel.get_reagent_amount("blood"))
|
||||
|
||||
occupantData["blood"] = bloodData
|
||||
|
||||
@@ -331,10 +329,6 @@
|
||||
organData["germ_level"] = E.germ_level
|
||||
organData["bruteLoss"] = E.brute_dam
|
||||
organData["fireLoss"] = E.burn_dam
|
||||
organData["totalLoss"] = E.brute_dam + E.burn_dam
|
||||
organData["maxHealth"] = E.max_damage
|
||||
organData["bruised"] = E.min_bruised_damage
|
||||
organData["broken"] = E.min_broken_damage
|
||||
|
||||
var/implantData[0]
|
||||
for(var/obj/I in E.implants)
|
||||
@@ -379,16 +373,13 @@
|
||||
var/organData[0]
|
||||
organData["name"] = I.name
|
||||
if(I.status & ORGAN_ASSISTED)
|
||||
organData["robotic"] = 1
|
||||
organData["desc"] = "Assisted"
|
||||
else if(I.robotic >= ORGAN_ROBOT)
|
||||
organData["robotic"] = 2
|
||||
organData["desc"] = "Mechanical"
|
||||
else
|
||||
organData["robotic"] = null
|
||||
organData["desc"] = null
|
||||
organData["germ_level"] = I.germ_level
|
||||
organData["damage"] = I.damage
|
||||
organData["maxHealth"] = I.max_damage
|
||||
organData["bruised"] = I.min_broken_damage
|
||||
organData["broken"] = I.min_bruised_damage
|
||||
|
||||
intOrganData.Add(list(organData))
|
||||
|
||||
@@ -426,9 +417,6 @@
|
||||
printing = null
|
||||
printing_text = null
|
||||
|
||||
if (href_list["ejectify"])
|
||||
src.connected.eject()
|
||||
|
||||
/obj/machinery/body_scanconsole/proc/generate_printing_text()
|
||||
var/dat = ""
|
||||
|
||||
|
||||
@@ -265,17 +265,20 @@ update_flag
|
||||
return src.attack_hand(user)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob)
|
||||
return src.tg_ui_interact(user)
|
||||
return src.ui_interact(user)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if (src.destroyed)
|
||||
return
|
||||
|
||||
// this is the data which will be sent to the ui
|
||||
var/data[0]
|
||||
data["name"] = name
|
||||
data["canLabel"] = can_label ? 1 : 0
|
||||
data["portConnected"] = connected_port ? 1 : 0
|
||||
data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
|
||||
data["releasePressure"] = round(release_pressure ? release_pressure : 0)
|
||||
data["minReleasePressure"] = round(ONE_ATMOSPHERE/10)
|
||||
data["defaultReleasePressure"] = ONE_ATMOSPHERE
|
||||
data["maxReleasePressure"] = round(10*ONE_ATMOSPHERE)
|
||||
data["valveOpen"] = valve_open ? 1 : 0
|
||||
|
||||
@@ -283,70 +286,83 @@ update_flag
|
||||
if (holding)
|
||||
data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure()))
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/tg_ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = tg_physical_state)
|
||||
if (src.destroyed)
|
||||
return
|
||||
ui = tgui_process.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "canister", name, 400, 400, master_ui, state)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "canister.tmpl", "Canister", 480, 400)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/ui_status(mob/user, datum/ui_state/state)
|
||||
if(!istype(src.loc, /turf))
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
/obj/machinery/portable_atmospherics/canister/Topic(href, href_list)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/ui_act(action, params)
|
||||
switch(action)
|
||||
if("relabel")
|
||||
if (can_label)
|
||||
var/list/colors = list(\
|
||||
"\[N2O\]" = "redws", \
|
||||
"\[N2\]" = "red", \
|
||||
"\[O2\]" = "blue", \
|
||||
"\[Phoron\]" = "orange", \
|
||||
"\[CO2\]" = "black", \
|
||||
"\[Air\]" = "grey", \
|
||||
"\[CAUTION\]" = "yellow", \
|
||||
)
|
||||
var/label = input("Choose canister label", "Gas canister") as null|anything in colors
|
||||
if (label)
|
||||
src.canister_color = colors[label]
|
||||
src.icon_state = colors[label]
|
||||
src.name = "\improper Canister: [label]"
|
||||
if("pressure")
|
||||
var/diff = text2num(params["adjust"])
|
||||
if(diff > 0)
|
||||
release_pressure = min(10*ONE_ATMOSPHERE, release_pressure+diff)
|
||||
//Do not use "if(..()) return" here, canisters will stop working in unpowered areas like space or on the derelict. // yeah but without SOME sort of Topic check any dick can mess with them via exploits as he pleases -walter0o
|
||||
//First comment might be outdated.
|
||||
if (!istype(src.loc, /turf))
|
||||
return 0
|
||||
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) // exploit protection -walter0o
|
||||
usr << browse(null, "window=canister")
|
||||
onclose(usr, "canister")
|
||||
return
|
||||
|
||||
if(href_list["toggle"])
|
||||
if (valve_open)
|
||||
if (holding)
|
||||
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the [holding]<br>"
|
||||
else
|
||||
release_pressure = max(ONE_ATMOSPHERE/10, release_pressure+diff)
|
||||
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the <font color='red'><b>air</b></font><br>"
|
||||
else
|
||||
if (holding)
|
||||
release_log += "Valve was <b>opened</b> by [usr] ([usr.ckey]), starting the transfer into the [holding]<br>"
|
||||
else
|
||||
release_log += "Valve was <b>opened</b> by [usr] ([usr.ckey]), starting the transfer into the <font color='red'><b>air</b></font><br>"
|
||||
log_open()
|
||||
valve_open = !valve_open
|
||||
|
||||
if("valve")
|
||||
if (href_list["remove_tank"])
|
||||
if(holding)
|
||||
if (valve_open)
|
||||
if (holding)
|
||||
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the [holding]<br>"
|
||||
else
|
||||
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the <font color='red'><b>air</b></font><br>"
|
||||
else
|
||||
if (holding)
|
||||
release_log += "Valve was <b>opened</b> by [usr] ([usr.ckey]), starting the transfer into the [holding]<br>"
|
||||
else
|
||||
release_log += "Valve was <b>opened</b> by [usr] ([usr.ckey]), starting the transfer into the <font color='red'><b>air</b></font><br>"
|
||||
log_open()
|
||||
valve_open = !valve_open
|
||||
valve_open = 0
|
||||
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the [holding]<br>"
|
||||
if(istype(holding, /obj/item/weapon/tank))
|
||||
holding.manipulated_by = usr.real_name
|
||||
holding.loc = loc
|
||||
holding = null
|
||||
|
||||
if("eject")
|
||||
if(holding)
|
||||
if (valve_open)
|
||||
valve_open = 0
|
||||
release_log += "Valve was <b>closed</b> by [usr] ([usr.ckey]), stopping the transfer into the [holding]<br>"
|
||||
if(istype(holding, /obj/item/weapon/tank))
|
||||
holding.manipulated_by = usr.real_name
|
||||
holding.loc = loc
|
||||
holding = null
|
||||
return TRUE
|
||||
if (href_list["pressure_adj"])
|
||||
var/diff = text2num(href_list["pressure_adj"])
|
||||
if(diff > 0)
|
||||
release_pressure = min(10*ONE_ATMOSPHERE, release_pressure+diff)
|
||||
else
|
||||
release_pressure = max(ONE_ATMOSPHERE/10, release_pressure+diff)
|
||||
|
||||
if (href_list["relabel"])
|
||||
if (can_label)
|
||||
var/list/colors = list(\
|
||||
"\[N2O\]" = "redws", \
|
||||
"\[N2\]" = "red", \
|
||||
"\[O2\]" = "blue", \
|
||||
"\[Phoron\]" = "orange", \
|
||||
"\[CO2\]" = "black", \
|
||||
"\[Air\]" = "grey", \
|
||||
"\[CAUTION\]" = "yellow", \
|
||||
)
|
||||
var/label = input("Choose canister label", "Gas canister") as null|anything in colors
|
||||
if (label)
|
||||
src.canister_color = colors[label]
|
||||
src.icon_state = colors[label]
|
||||
src.name = "Canister: [label]"
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/phoron/New()
|
||||
..()
|
||||
|
||||
@@ -11,91 +11,103 @@
|
||||
req_access = list(access_engine)
|
||||
|
||||
var/secure = 0 //if set, then wires will be randomized and bolts will drop if the door is broken
|
||||
var/list/conf_access = list()
|
||||
var/list/conf_access = null
|
||||
var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access
|
||||
var/last_configurator = null
|
||||
var/locked = 1
|
||||
|
||||
/obj/item/weapon/airlock_electronics/attack_self(mob/user as mob)
|
||||
if (!ishuman(user) && !istype(user,/mob/living/silicon/robot))
|
||||
return ..(user)
|
||||
attack_self(mob/user as mob)
|
||||
if (!ishuman(user) && !istype(user,/mob/living/silicon/robot))
|
||||
return ..(user)
|
||||
|
||||
tg_ui_interact(user)
|
||||
var/t1 = text("<B>Access control</B><br>\n")
|
||||
|
||||
//tgui interact code generously lifted from tgstation.
|
||||
/obj/item/weapon/airlock_electronics/tg_ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = hands_state)
|
||||
if (last_configurator)
|
||||
t1 += "Operator: [last_configurator]<br>"
|
||||
|
||||
tgui_process.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "airlock_electronics", src.name, 1000, 500, master_ui, state)
|
||||
ui.open()
|
||||
if (locked)
|
||||
t1 += "<a href='?src=\ref[src];login=1'>Swipe ID</a><hr>"
|
||||
else
|
||||
t1 += "<a href='?src=\ref[src];logout=1'>Block</a><hr>"
|
||||
|
||||
/obj/item/weapon/airlock_electronics/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/regions = list()
|
||||
t1 += "Access requirement is set to "
|
||||
t1 += one_access ? "<a style='color: green' href='?src=\ref[src];one_access=1'>ONE</a><hr>" : "<a style='color: red' href='?src=\ref[src];one_access=1'>ALL</a><hr>"
|
||||
|
||||
for(var/i in ACCESS_REGION_SECURITY to ACCESS_REGION_SUPPLY) //code/game/jobs/_access_defs.dm
|
||||
var/list/region = list()
|
||||
var/list/accesses = list()
|
||||
for(var/j in get_region_accesses(i))
|
||||
var/list/access = list()
|
||||
access["name"] = get_access_desc(j)
|
||||
access["id"] = j
|
||||
access["req"] = (j in src.conf_access)
|
||||
accesses[++accesses.len] = access
|
||||
region["name"] = get_region_accesses_name(i)
|
||||
region["accesses"] = accesses
|
||||
regions[++regions.len] = region
|
||||
data["regions"] = regions
|
||||
data["oneAccess"] = one_access
|
||||
data["locked"] = locked
|
||||
t1 += conf_access == null ? "<font color=red>All</font><br>" : "<a href='?src=\ref[src];access=all'>All</a><br>"
|
||||
|
||||
return data
|
||||
t1 += "<br>"
|
||||
|
||||
/obj/item/weapon/airlock_electronics/ui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
switch(action)
|
||||
if("clear")
|
||||
conf_access = list()
|
||||
one_access = 0
|
||||
return TRUE
|
||||
if("one_access")
|
||||
one_access = !one_access
|
||||
return TRUE
|
||||
if("set")
|
||||
var/access = text2num(params["access"])
|
||||
if (!(access in conf_access))
|
||||
conf_access += access
|
||||
else
|
||||
conf_access -= access
|
||||
return TRUE
|
||||
if("unlock")
|
||||
var/list/accesses = get_all_station_access()
|
||||
for (var/acc in accesses)
|
||||
var/aname = get_access_desc(acc)
|
||||
|
||||
if (!conf_access || !conf_access.len || !(acc in conf_access))
|
||||
t1 += "<a href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
|
||||
else if(one_access)
|
||||
t1 += "<a style='color: green' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
|
||||
else
|
||||
t1 += "<a style='color: red' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
|
||||
|
||||
t1 += text("<p><a href='?src=\ref[];close=1'>Close</a></p>\n", src)
|
||||
|
||||
user << browse(t1, "window=airlock_electronics")
|
||||
onclose(user, "airlock")
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon)))
|
||||
return
|
||||
if (href_list["close"])
|
||||
usr << browse(null, "window=airlock")
|
||||
return
|
||||
|
||||
if (href_list["login"])
|
||||
if(istype(usr,/mob/living/silicon))
|
||||
locked = 0
|
||||
last_configurator = usr.name
|
||||
return TRUE
|
||||
src.locked = 0
|
||||
src.last_configurator = usr.name
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/device/pda))
|
||||
var/obj/item/device/pda/pda = I
|
||||
I = pda.id
|
||||
if(!istype(I, /obj/item/weapon/card/id))
|
||||
usr << "<span class='warning'>[\src] flashes a yellow LED near the ID scanner. Did you remember to scan your ID or PDA?</span>"
|
||||
return TRUE
|
||||
if (I && src.check_access(I))
|
||||
locked = 0
|
||||
last_configurator = I:registered_name
|
||||
else
|
||||
usr << "<span class='warning'>[\src] flashes a red LED near the ID scanner, indicating your access has been denied.</span>"
|
||||
return TRUE
|
||||
if("lock")
|
||||
src.locked = 0
|
||||
src.last_configurator = I:registered_name
|
||||
|
||||
if (locked)
|
||||
return
|
||||
|
||||
if (href_list["logout"])
|
||||
locked = 1
|
||||
. = TRUE
|
||||
|
||||
if (href_list["one_access"])
|
||||
one_access = !one_access
|
||||
|
||||
if (href_list["access"])
|
||||
toggle_access(href_list["access"])
|
||||
|
||||
attack_self(usr)
|
||||
|
||||
proc
|
||||
toggle_access(var/acc)
|
||||
if (acc == "all")
|
||||
conf_access = null
|
||||
else
|
||||
var/req = text2num(acc)
|
||||
|
||||
if (conf_access == null)
|
||||
conf_access = list()
|
||||
|
||||
if (!(req in conf_access))
|
||||
conf_access += req
|
||||
else
|
||||
conf_access -= req
|
||||
if (!conf_access.len)
|
||||
conf_access = null
|
||||
|
||||
|
||||
/obj/item/weapon/airlock_electronics/secure
|
||||
name = "secure airlock electronics"
|
||||
desc = "designed to be somewhat more resistant to hacking than standard electronics."
|
||||
origin_tech = list(TECH_DATA = 2)
|
||||
secure = 1
|
||||
secure = 1
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
//Main door timer loop, if it's timing and time is >0 reduce time by 1.
|
||||
// if it's less than 0, open door, reset timer
|
||||
// update the door_timer window and the icon
|
||||
@@ -67,10 +68,12 @@
|
||||
if(timeleft > 1e5)
|
||||
src.releasetime = 0
|
||||
|
||||
|
||||
if(world.timeofday > src.releasetime)
|
||||
src.timer_end() // open doors, reset timer, clear status screen
|
||||
src.timing = 0
|
||||
|
||||
src.updateUsrDialog()
|
||||
src.update_icon()
|
||||
|
||||
else
|
||||
@@ -78,12 +81,14 @@
|
||||
|
||||
return
|
||||
|
||||
|
||||
// has the door power situation changed, if so update icon.
|
||||
/obj/machinery/door_timer/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
// open/closedoor checks if door_timer has power, if so it checks if the
|
||||
// linked door is open/closed (by density) then opens it/closes it.
|
||||
|
||||
@@ -94,9 +99,6 @@
|
||||
// Set releasetime
|
||||
releasetime = world.timeofday + timetoset
|
||||
|
||||
//set timing
|
||||
timing = 1
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(door.density) continue
|
||||
spawn(0)
|
||||
@@ -109,6 +111,7 @@
|
||||
C.icon_state = C.icon_locked
|
||||
return 1
|
||||
|
||||
|
||||
// Opens and unlocks doors, power check
|
||||
/obj/machinery/door_timer/proc/timer_end()
|
||||
if(stat & (NOPOWER|BROKEN)) return 0
|
||||
@@ -116,9 +119,6 @@
|
||||
// Reset releasetime
|
||||
releasetime = 0
|
||||
|
||||
//reset timing
|
||||
timing = 0
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(!door.density) continue
|
||||
spawn(0)
|
||||
@@ -132,6 +132,7 @@
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
// Check for releasetime timeleft
|
||||
/obj/machinery/door_timer/proc/timeleft()
|
||||
. = (releasetime - world.timeofday)/10
|
||||
@@ -151,62 +152,116 @@
|
||||
/obj/machinery/door_timer/attack_ai(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
//Allows humans to use door_timer
|
||||
//Opens dialog window when someone clicks on door timer
|
||||
// Allows altering timer and the timing boolean.
|
||||
// Flasher activation limited to 150 seconds
|
||||
/obj/machinery/door_timer/attack_hand(var/mob/user as mob)
|
||||
tg_ui_interact(user)
|
||||
|
||||
/obj/machinery/door_timer/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["timing"] = timing
|
||||
data["releasetime"] = releasetime
|
||||
data["timetoset"] = timetoset
|
||||
data["timeleft"] = timeleft()
|
||||
|
||||
var/list/flashes = list()
|
||||
|
||||
for(var/obj/machinery/flasher/flash in targets)
|
||||
var/list/flashdata = list()
|
||||
if(flash.last_flash && (flash.last_flash + 150) > world.time)
|
||||
flashdata["status"] = 0
|
||||
else
|
||||
flashdata["status"] = 1
|
||||
flashes[++flashes.len] = flashdata
|
||||
|
||||
data["flashes"] = flashes
|
||||
return data
|
||||
|
||||
/obj/machinery/door_timer/ui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
// Used for the 'time left' display
|
||||
var/second = round(timeleft() % 60)
|
||||
var/minute = round((timeleft() - second) / 60)
|
||||
|
||||
// Used for 'set timer'
|
||||
var/setsecond = round((timetoset / 10) % 60)
|
||||
var/setminute = round(((timetoset / 10) - setsecond) / 60)
|
||||
|
||||
user.set_machine(src)
|
||||
|
||||
// dat
|
||||
var/dat = "<HTML><BODY><TT>"
|
||||
|
||||
dat += "<HR>Timer System:</hr>"
|
||||
dat += " <b>Door [src.id] controls</b><br/>"
|
||||
|
||||
// Start/Stop timer
|
||||
if (src.timing)
|
||||
dat += "<a href='?src=\ref[src];timing=0'>Stop Timer and open door</a><br/>"
|
||||
else
|
||||
dat += "<a href='?src=\ref[src];timing=1'>Activate Timer and close door</a><br/>"
|
||||
|
||||
// Time Left display (uses releasetime)
|
||||
dat += "Time Left: [(minute ? text("[minute]:") : null)][second] <br/>"
|
||||
dat += "<br/>"
|
||||
|
||||
// Set Timer display (uses timetoset)
|
||||
if(src.timing)
|
||||
dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] <a href='?src=\ref[src];change=1'>Set</a><br/>"
|
||||
else
|
||||
dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond]<br/>"
|
||||
|
||||
// Controls
|
||||
dat += "<a href='?src=\ref[src];tp=-60'>-</a> <a href='?src=\ref[src];tp=-1'>-</a> <a href='?src=\ref[src];tp=1'>+</a> <A href='?src=\ref[src];tp=60'>+</a><br/>"
|
||||
|
||||
// Mounted flash controls
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
if(F.last_flash && (F.last_flash + 150) > world.time)
|
||||
dat += "<br/><A href='?src=\ref[src];fc=1'>Flash Charging</A>"
|
||||
else
|
||||
dat += "<br/><A href='?src=\ref[src];fc=1'>Activate Flash</A>"
|
||||
|
||||
dat += "<br/><br/><a href='?src=\ref[user];mach_close=computer'>Close</a>"
|
||||
dat += "</TT></BODY></HTML>"
|
||||
|
||||
user << browse(dat, "window=computer;size=400x500")
|
||||
onclose(user, "computer")
|
||||
return
|
||||
|
||||
|
||||
//Function for using door_timer dialog input, checks if user has permission
|
||||
// href_list to
|
||||
// "timing" turns on timer
|
||||
// "tp" value to modify timer
|
||||
// "fc" activates flasher
|
||||
// "change" resets the timer to the timetoset amount while the timer is counting down
|
||||
// Also updates dialog window and timer icon
|
||||
/obj/machinery/door_timer/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(!src.allowed(usr))
|
||||
return TRUE
|
||||
return
|
||||
|
||||
switch (action)
|
||||
if("start")
|
||||
if(timetoset > 18000)
|
||||
log_admin("[key_name(usr)] has started a brig timer over 30 minutes in length!")
|
||||
message_admins("[key_name_admin(usr)] has started a brig timer over 30 minutes in length!")
|
||||
timer_start()
|
||||
if("stop")
|
||||
timer_end()
|
||||
if("flash")
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["timing"])
|
||||
src.timing = text2num(href_list["timing"])
|
||||
|
||||
if(src.timing)
|
||||
src.timer_start()
|
||||
else
|
||||
src.timer_end()
|
||||
|
||||
else
|
||||
if(href_list["tp"]) //adjust timer, close door if not already closed
|
||||
var/tp = text2num(href_list["tp"])
|
||||
var/addtime = (timetoset / 10)
|
||||
addtime += tp
|
||||
addtime = min(max(round(addtime), 0), 3600)
|
||||
|
||||
timeset(addtime)
|
||||
|
||||
if(href_list["fc"])
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
F.flash()
|
||||
if("time")
|
||||
timetoset += text2num(params["adjust"])
|
||||
timetoset = Clamp(timetoset, 0, 36000)
|
||||
|
||||
if(href_list["change"])
|
||||
src.timer_start()
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
src.update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door_timer/tg_ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
ui = tgui_process.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "brig_timer", name , 300, 150, master_ui, state)
|
||||
ui.open()
|
||||
/* if(src.timing)
|
||||
src.timer_start()
|
||||
|
||||
else
|
||||
src.timer_end() */
|
||||
|
||||
return
|
||||
|
||||
|
||||
//icon update function
|
||||
// if NOPOWER, display blank
|
||||
@@ -227,9 +282,7 @@
|
||||
disp2 = "Error"
|
||||
update_display(disp1, disp2)
|
||||
else
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
update_display("Set","Time") // would be nice to have some default printed text
|
||||
if(maptext) maptext = ""
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
var/close_door_at = 0 //When to automatically close the door, if possible
|
||||
|
||||
//Multi-tile doors
|
||||
dir = EAST
|
||||
var/width = 1
|
||||
|
||||
// turf animation
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//Terribly sorry for the code doubling, but things go derpy otherwise.
|
||||
/obj/machinery/door/airlock/multi_tile
|
||||
width = 2
|
||||
dir = EAST
|
||||
|
||||
/obj/machinery/door/airlock/multi_tile/New()
|
||||
..()
|
||||
|
||||
@@ -8,7 +8,7 @@ datum/track/New(var/title_name, var/audio)
|
||||
title = title_name
|
||||
sound = audio
|
||||
|
||||
/obj/machinery/media/jukebox
|
||||
/obj/machinery/media/jukebox/
|
||||
name = "space jukebox"
|
||||
icon = 'icons/obj/jukebox.dmi'
|
||||
icon_state = "jukebox2-nopower"
|
||||
@@ -44,11 +44,10 @@ datum/track/New(var/title_name, var/audio)
|
||||
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
|
||||
component_parts += new /obj/item/stack/cable_coil(src, 5)
|
||||
RefreshParts()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/media/jukebox/Destroy()
|
||||
StopPlaying()
|
||||
. = ..()
|
||||
..()
|
||||
|
||||
/obj/machinery/media/jukebox/power_change()
|
||||
if(!powered(power_channel) || !anchored)
|
||||
@@ -75,7 +74,10 @@ datum/track/New(var/title_name, var/audio)
|
||||
else
|
||||
overlays += "[state_base]-running"
|
||||
|
||||
/obj/machinery/media/jukebox/interact(mob/user)
|
||||
/obj/machinery/media/jukebox/Topic(href, href_list)
|
||||
if(..() || !(Adjacent(usr) || istype(usr, /mob/living/silicon)))
|
||||
return
|
||||
|
||||
if(!anchored)
|
||||
usr << "<span class='warning'>You must secure \the [src] first.</span>"
|
||||
return
|
||||
@@ -84,73 +86,69 @@ datum/track/New(var/title_name, var/audio)
|
||||
usr << "\The [src] doesn't appear to function."
|
||||
return
|
||||
|
||||
tg_ui_interact(user)
|
||||
|
||||
/obj/machinery/media/jukebox/ui_status(mob/user, datum/ui_state/state)
|
||||
if(!anchored || inoperable())
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/media/jukebox/tg_ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = tg_default_state)
|
||||
ui = tgui_process.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "jukebox", "RetroBox - Space Style", 340, 440, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/media/jukebox/ui_data()
|
||||
var/list/juke_tracks = new
|
||||
for(var/datum/track/T in tracks)
|
||||
juke_tracks.Add(T.title)
|
||||
|
||||
var/list/data = list(
|
||||
"current_track" = current_track != null ? current_track.title : "No track selected",
|
||||
"playing" = playing,
|
||||
"tracks" = juke_tracks
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/media/jukebox/ui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
switch(action)
|
||||
if("change_track")
|
||||
for(var/datum/track/T in tracks)
|
||||
if(T.title == params["title"])
|
||||
current_track = T
|
||||
StartPlaying()
|
||||
break
|
||||
. = TRUE
|
||||
if("stop")
|
||||
StopPlaying()
|
||||
. = TRUE
|
||||
if("play")
|
||||
if(emagged)
|
||||
emag_play()
|
||||
else if(!current_track)
|
||||
usr << "No track selected."
|
||||
else
|
||||
if(href_list["change_track"])
|
||||
for(var/datum/track/T in tracks)
|
||||
if(T.title == href_list["title"])
|
||||
current_track = T
|
||||
StartPlaying()
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/media/jukebox/proc/emag_play()
|
||||
playsound(loc, 'sound/items/AirHorn.ogg', 100, 1)
|
||||
for(var/mob/living/carbon/M in ohearers(6, src))
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs))
|
||||
continue
|
||||
M.sleeping = 0
|
||||
M.stuttering += 20
|
||||
M.ear_deaf += 30
|
||||
M.Weaken(3)
|
||||
if(prob(30))
|
||||
M.Stun(10)
|
||||
M.Paralyse(4)
|
||||
break
|
||||
else if(href_list["stop"])
|
||||
StopPlaying()
|
||||
else if(href_list["play"])
|
||||
if(emagged)
|
||||
playsound(src.loc, 'sound/items/AirHorn.ogg', 100, 1)
|
||||
for(var/mob/living/carbon/M in ohearers(6, src))
|
||||
if(M.get_ear_protection() >= 2)
|
||||
continue
|
||||
M.sleeping = 0
|
||||
M.stuttering += 20
|
||||
M.ear_deaf += 30
|
||||
M.Weaken(3)
|
||||
if(prob(30))
|
||||
M.Stun(10)
|
||||
M.Paralyse(4)
|
||||
else
|
||||
M.make_jittery(500)
|
||||
spawn(15)
|
||||
explode()
|
||||
else if(current_track == null)
|
||||
usr << "No track selected."
|
||||
else
|
||||
M.make_jittery(500)
|
||||
spawn(15)
|
||||
explode()
|
||||
StartPlaying()
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/media/jukebox/interact(mob/user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
usr << "\The [src] doesn't appear to function."
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/media/jukebox/ui_interact(mob/user, ui_key = "jukebox", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/title = "RetroBox - Space Style"
|
||||
var/data[0]
|
||||
|
||||
if(!(stat & (NOPOWER|BROKEN)))
|
||||
data["current_track"] = current_track != null ? current_track.title : ""
|
||||
data["playing"] = playing
|
||||
|
||||
var/list/nano_tracks = new
|
||||
for(var/datum/track/T in tracks)
|
||||
nano_tracks[++nano_tracks.len] = list("track" = T.title)
|
||||
|
||||
data["tracks"] = nano_tracks
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "jukebox.tmpl", title, 450, 600)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/media/jukebox/attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
@@ -174,6 +172,10 @@ datum/track/New(var/title_name, var/audio)
|
||||
/obj/machinery/media/jukebox/attackby(obj/item/W as obj, mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
|
||||
if(default_deconstruction_screwdriver(user, W))
|
||||
return
|
||||
if(default_deconstruction_crowbar(user, W))
|
||||
return
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
if(playing)
|
||||
StopPlaying()
|
||||
@@ -198,6 +200,7 @@ datum/track/New(var/title_name, var/audio)
|
||||
// Always kill the current sound
|
||||
for(var/mob/living/M in mobs_in_area(main_area))
|
||||
M << sound(null, channel = 1)
|
||||
|
||||
main_area.forced_ambience = null
|
||||
playing = 0
|
||||
update_use_power(1)
|
||||
@@ -217,4 +220,4 @@ datum/track/New(var/title_name, var/audio)
|
||||
|
||||
playing = 1
|
||||
update_use_power(2)
|
||||
update_icon()
|
||||
update_icon()
|
||||
|
||||
@@ -90,8 +90,6 @@
|
||||
|
||||
/datum/feed_network/proc/insert_message_in_channel(var/datum/feed_channel/FC, var/datum/feed_message/newMsg)
|
||||
FC.messages += newMsg
|
||||
if(newMsg.img)
|
||||
register_asset("newscaster_photo_[sanitize(FC.channel_name)]_[FC.messages.len].png", newMsg.img)
|
||||
newMsg.parent_channel = FC
|
||||
FC.update()
|
||||
alert_readers(FC.announcement)
|
||||
@@ -379,12 +377,11 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
|
||||
else
|
||||
var/i = 0
|
||||
for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
|
||||
++i
|
||||
i++
|
||||
dat+="-[MESSAGE.body] <BR>"
|
||||
if(MESSAGE.img)
|
||||
var/resourc_name = "newscaster_photo_[sanitize(viewing_channel.channel_name)]_[i].png"
|
||||
send_asset(usr.client, resourc_name)
|
||||
dat+="<img src='[resourc_name]' width = '180'><BR>"
|
||||
usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
|
||||
dat+="<img src='tmp_photo[i].png' width = '180'><BR>"
|
||||
if(MESSAGE.caption)
|
||||
dat+="<FONT SIZE=1><B>[MESSAGE.caption]</B></FONT><BR>"
|
||||
dat+="<BR>"
|
||||
@@ -877,12 +874,11 @@ obj/item/weapon/newspaper/attack_self(mob/user as mob)
|
||||
dat+="<ul>"
|
||||
var/i = 0
|
||||
for(var/datum/feed_message/MESSAGE in C.messages)
|
||||
++i
|
||||
i++
|
||||
dat+="-[MESSAGE.body] <BR>"
|
||||
if(MESSAGE.img)
|
||||
var/resourc_name = "newscaster_photo_[sanitize(C.channel_name)]_[i].png"
|
||||
send_asset(user.client, resourc_name)
|
||||
dat+="<img src='[resourc_name]' width = '180'><BR>"
|
||||
user << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
|
||||
dat+="<img src='tmp_photo[i].png' width = '180'><BR>"
|
||||
dat+="<FONT SIZE=1>\[[MESSAGE.message_type] by <FONT COLOR='maroon'>[MESSAGE.author]</FONT>\]</FONT><BR><BR>"
|
||||
dat+="</ul>"
|
||||
if(scribble_page==curr_page)
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
var/set_temperature = T0C + 20 //K
|
||||
var/heating_power = 40000
|
||||
|
||||
|
||||
/obj/machinery/space_heater/New()
|
||||
..()
|
||||
if (cell_type)
|
||||
cell = new cell_type(src)
|
||||
src.cell = new cell_type(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/space_heater/update_icon()
|
||||
@@ -78,7 +79,7 @@
|
||||
return
|
||||
|
||||
/obj/machinery/space_heater/attack_hand(mob/user as mob)
|
||||
add_fingerprint(user)
|
||||
src.add_fingerprint(user)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/space_heater/interact(mob/user as mob)
|
||||
@@ -110,6 +111,7 @@
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/space_heater/Topic(href, href_list)
|
||||
if (usr.stat)
|
||||
return
|
||||
@@ -133,6 +135,7 @@
|
||||
cell = null
|
||||
power_change()
|
||||
|
||||
|
||||
if("cellinstall")
|
||||
if(panel_open && !cell)
|
||||
var/obj/item/weapon/cell/C = usr.get_active_hand()
|
||||
@@ -150,6 +153,8 @@
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
|
||||
|
||||
/obj/machinery/space_heater/process()
|
||||
if(on)
|
||||
if(cell && cell.charge)
|
||||
@@ -181,4 +186,4 @@
|
||||
else
|
||||
on = 0
|
||||
power_change()
|
||||
update_icon()
|
||||
update_icon()
|
||||
|
||||
@@ -620,9 +620,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
if(!FC.censored)
|
||||
var/index = 0
|
||||
for(var/datum/feed_message/FM in FC.messages)
|
||||
++index
|
||||
index++
|
||||
if(FM.img)
|
||||
send_asset(usr.client, "newscaster_photo_[sanitize(FC.channel_name)]_[index].png")
|
||||
usr << browse_rsc(FM.img, "pda_news_tmp_photo_[feed["channel"]]_[index].png")
|
||||
// News stories are HTML-stripped but require newline replacement to be properly displayed in NanoUI
|
||||
var/body = replacetext(FM.body, "\n", "<br>")
|
||||
messages[++messages.len] = list("author" = FM.author, "body" = body, "message_type" = FM.message_type, "time_stamp" = FM.time_stamp, "has_image" = (FM.img != null), "caption" = FM.caption, "index" = index)
|
||||
@@ -651,8 +651,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
|
||||
//NOTE: graphic resources are loaded on client login
|
||||
/obj/item/device/pda/attack_self(mob/user as mob)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/pda)
|
||||
assets.send(user)
|
||||
|
||||
user.set_machine(src)
|
||||
|
||||
|
||||
@@ -33,12 +33,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
|
||||
var/obj/item/weapon/cartridge/cartridge = null //current cartridge
|
||||
var/list/modules = list(
|
||||
list("module" = "Phone", "icon" = "mobile", "number" = 2),
|
||||
list("module" = "Contacts", "icon" = "users", "number" = 3),
|
||||
list("module" = "Messaging", "icon" = "envelope", "number" = 4),
|
||||
list("module" = "Note", "icon" = "file-text", "number" = 5),
|
||||
list("module" = "Settings", "icon" = "gear", "number" = 6)
|
||||
) //list("module" = "Name of Module", "icon" = "icon name", "number" = "what tab is the module")
|
||||
list("module" = "Phone", "icon" = "phone64", "number" = 2),
|
||||
list("module" = "Contacts", "icon" = "person64", "number" = 3),
|
||||
list("module" = "Messaging", "icon" = "comment64", "number" = 4),
|
||||
list("module" = "Note", "icon" = "note64", "number" = 5),
|
||||
list("module" = "Settings", "icon" = "gear64", "number" = 6)
|
||||
) //list("module" = "Name of Module", "icon" = "icon name64", "number" = "what tab is the module")
|
||||
|
||||
var/selected_tab = 1
|
||||
var/owner = ""
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
dat += {"
|
||||
<b><font size='3px'>pAI Request Module</font></b><br><br>
|
||||
<p>Requesting AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>
|
||||
Searching for personalities, please wait...<br><br>
|
||||
<img src='loading.gif' /> Searching for personalities<br><br>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
|
||||
@@ -143,9 +143,6 @@
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/card/id/proc/show(mob/user as mob)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/paper)
|
||||
assets.send(user)
|
||||
|
||||
if(front && side)
|
||||
user << browse_rsc(front, "front.png")
|
||||
user << browse_rsc(side, "side.png")
|
||||
@@ -365,4 +362,4 @@
|
||||
desc = "An identification card of some sort. It does not look like it is issued by NT."
|
||||
icon_state = "permit"
|
||||
primary_color = rgb(142,94,0)
|
||||
secondary_color = rgb(191,159,95)
|
||||
secondary_color = rgb(191,159,95)
|
||||
@@ -115,7 +115,6 @@
|
||||
|
||||
/obj/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tg_ui_interact(user)
|
||||
..()
|
||||
|
||||
/obj/proc/interact(mob/user)
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
return
|
||||
|
||||
if("marked datum")
|
||||
current = holder.marked_datum()
|
||||
current = holder.marked_datum
|
||||
if(!current)
|
||||
switch(alert("You do not currently have a marked datum; do you want to pass null instead?",, "Yes", "Cancel"))
|
||||
if("Yes")
|
||||
|
||||
@@ -6,16 +6,13 @@ var/list/admin_datums = list()
|
||||
var/rights = 0
|
||||
var/fakekey = null
|
||||
|
||||
var/datum/weakref/marked_datum_weak
|
||||
var/datum/marked_datum
|
||||
|
||||
var/admincaster_screen = 0 //See newscaster.dm under machinery for a full description
|
||||
var/datum/feed_message/admincaster_feed_message = new /datum/feed_message //These two will act as holders.
|
||||
var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel
|
||||
var/admincaster_signature //What you'll sign the newsfeeds as
|
||||
|
||||
/datum/admins/proc/marked_datum()
|
||||
if(marked_datum_weak)
|
||||
return marked_datum_weak.resolve()
|
||||
|
||||
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
|
||||
if(!ckey)
|
||||
|
||||
@@ -1538,7 +1538,6 @@
|
||||
where = "onfloor"
|
||||
|
||||
if ( where == "inmarked" )
|
||||
var/marked_datum = marked_datum()
|
||||
if ( !marked_datum )
|
||||
usr << "You don't have any object marked. Abandoning spawn."
|
||||
return
|
||||
@@ -1556,7 +1555,7 @@
|
||||
if ("relative")
|
||||
target = locate(loc.x + X,loc.y + Y,loc.z + Z)
|
||||
if ( "inmarked" )
|
||||
target = marked_datum()
|
||||
target = marked_datum
|
||||
|
||||
if(target)
|
||||
for (var/path in paths)
|
||||
|
||||
@@ -959,18 +959,3 @@
|
||||
log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!")
|
||||
else
|
||||
alert("Invalid mob")
|
||||
|
||||
/client/proc/reload_nanoui_resources()
|
||||
set category = "Debug"
|
||||
set name = "Reload NanoUI Resources"
|
||||
set desc = "Force the client to redownload NanoUI Resources"
|
||||
|
||||
// Close open NanoUIs.
|
||||
nanomanager.close_user_uis(usr)
|
||||
|
||||
// Re-load the assets.
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui)
|
||||
assets.register()
|
||||
|
||||
// Clear the user's cache so they get resent.
|
||||
usr.client.cache = list()
|
||||
@@ -162,7 +162,6 @@ var/list/debug_verbs = list (
|
||||
,/client/proc/setup_supermatter_engine
|
||||
,/client/proc/atmos_toggle_debug
|
||||
,/client/proc/spawn_tanktransferbomb
|
||||
,/client/proc/reload_nanoui_resources
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -27,20 +27,20 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
src.modify_variables(ticker)
|
||||
feedback_add_details("admin_verb","ETV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/mod_list_add_ass()
|
||||
var/class = "text"
|
||||
var/list/class_input = list("text","num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
|
||||
if(src.holder)
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum)
|
||||
class_input += "marked datum ([marked_datum.type])"
|
||||
/client/proc/mod_list_add_ass() //haha
|
||||
|
||||
var/class = "text"
|
||||
if(src.holder && src.holder.marked_datum)
|
||||
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
|
||||
else
|
||||
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
|
||||
|
||||
class = input("What kind of variable?","Variable Type") as null|anything in class_input
|
||||
if(!class)
|
||||
return
|
||||
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum && class == "marked datum ([marked_datum.type])")
|
||||
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
|
||||
class = "marked datum"
|
||||
|
||||
var/var_value = null
|
||||
@@ -69,7 +69,7 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
var_value = input("Pick icon:","Icon") as null|icon
|
||||
|
||||
if("marked datum")
|
||||
var_value = holder.marked_datum()
|
||||
var_value = holder.marked_datum
|
||||
|
||||
if(!var_value) return
|
||||
|
||||
@@ -79,18 +79,17 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
/client/proc/mod_list_add(var/list/L, atom/O, original_name, objectvar)
|
||||
|
||||
var/class = "text"
|
||||
var/list/class_input = list("text","num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
|
||||
if(src.holder)
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum)
|
||||
class_input += "marked datum ([marked_datum.type])"
|
||||
if(src.holder && src.holder.marked_datum)
|
||||
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
|
||||
else
|
||||
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
|
||||
|
||||
class = input("What kind of variable?","Variable Type") as null|anything in class_input
|
||||
if(!class)
|
||||
return
|
||||
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum && class == "marked datum ([marked_datum.type])")
|
||||
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
|
||||
class = "marked datum"
|
||||
|
||||
var/var_value = null
|
||||
@@ -119,7 +118,7 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
var_value = input("Pick icon:","Icon") as icon
|
||||
|
||||
if("marked datum")
|
||||
var_value = holder.marked_datum()
|
||||
var_value = holder.marked_datum
|
||||
|
||||
if(!var_value) return
|
||||
|
||||
@@ -245,21 +244,17 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
usr << "If a direction, direction is: [dir]"
|
||||
|
||||
var/class = "text"
|
||||
var/list/class_input = list("text","num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
|
||||
|
||||
if(src.holder)
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum)
|
||||
class_input += "marked datum ([marked_datum.type])"
|
||||
|
||||
class_input += "DELETE FROM LIST"
|
||||
class = input("What kind of variable?","Variable Type",default) as null|anything in class_input
|
||||
if(src.holder && src.holder.marked_datum)
|
||||
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST")
|
||||
else
|
||||
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "DELETE FROM LIST")
|
||||
|
||||
if(!class)
|
||||
return
|
||||
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum && class == "marked datum ([marked_datum.type])")
|
||||
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
|
||||
class = "marked datum"
|
||||
|
||||
var/original_var
|
||||
@@ -341,9 +336,7 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
L[L.Find(variable)] = new_var
|
||||
|
||||
if("marked datum")
|
||||
new_var = holder.marked_datum()
|
||||
if(!new_var)
|
||||
return
|
||||
new_var = holder.marked_datum
|
||||
if(assoc)
|
||||
L[assoc_key] = new_var
|
||||
else
|
||||
@@ -508,12 +501,12 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
if(dir)
|
||||
usr << "If a direction, direction is: [dir]"
|
||||
|
||||
var/list/class_input = list("text","num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
|
||||
if(src.holder)
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum)
|
||||
class_input += "marked datum ([marked_datum.type])"
|
||||
class = input("What kind of variable?","Variable Type",default) as null|anything in class_input
|
||||
if(src.holder && src.holder.marked_datum)
|
||||
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
|
||||
else
|
||||
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
|
||||
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
|
||||
|
||||
if(!class)
|
||||
return
|
||||
@@ -525,8 +518,7 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
else
|
||||
original_name = O:name
|
||||
|
||||
var/datum/marked_datum = holder.marked_datum()
|
||||
if(marked_datum && class == "marked datum ([marked_datum.type])")
|
||||
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
|
||||
class = "marked datum"
|
||||
|
||||
switch(class)
|
||||
@@ -592,7 +584,7 @@ var/list/VVckey_edit = list("key", "ckey")
|
||||
O.vars[variable] = var_new
|
||||
|
||||
if("marked datum")
|
||||
O.vars[variable] = holder.marked_datum()
|
||||
O.vars[variable] = holder.marked_datum
|
||||
|
||||
world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]"
|
||||
log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]")
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
usr << "This can only be done to instances of type /datum"
|
||||
return
|
||||
|
||||
src.holder.marked_datum_weak = weakref(D)
|
||||
src.holder.marked_datum = D
|
||||
href_list["datumrefresh"] = href_list["mark_object"]
|
||||
|
||||
else if(href_list["rotatedatum"])
|
||||
@@ -476,10 +476,7 @@
|
||||
usr << "This can only be done on mobs with clients"
|
||||
return
|
||||
|
||||
nanomanager.close_uis(H)
|
||||
H.client.cache.Cut()
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui)
|
||||
assets.send(H)
|
||||
nanomanager.send_resources(H.client)
|
||||
|
||||
usr << "Resource files sent"
|
||||
H << "Your NanoUI Resource files have been refreshed"
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</tr></table>
|
||||
<div align='center'>
|
||||
<b><font size='1'>[replacetext("[D.type]", "/", "/<wbr>")]</font></b>
|
||||
[holder.marked_datum() == D ? "<br/><font size='1' color='red'><b>Marked Object</b></font>" : ""]
|
||||
[holder.marked_datum == D ? "<br/><font size='1' color='red'><b>Marked Object</b></font>" : ""]
|
||||
</div>
|
||||
</td>
|
||||
<td width='50%'>
|
||||
|
||||
@@ -3,7 +3,7 @@ proc/createRandomZlevel()
|
||||
return
|
||||
|
||||
var/list/potentialRandomZlevels = list()
|
||||
log_startup_progress("Searching for away missions...")
|
||||
admin_notice("\red \b Searching for away missions...", R_DEBUG)
|
||||
var/list/Lines = file2list("maps/RandomZLevels/fileList.txt")
|
||||
if(!Lines.len) return
|
||||
for (var/t in Lines)
|
||||
@@ -35,7 +35,7 @@ proc/createRandomZlevel()
|
||||
|
||||
|
||||
if(potentialRandomZlevels.len)
|
||||
log_startup_progress("Loading away mission...")
|
||||
admin_notice("\red \b Loading away mission...", R_DEBUG)
|
||||
|
||||
var/map = pick(potentialRandomZlevels)
|
||||
var/file = file(map)
|
||||
@@ -48,8 +48,8 @@ proc/createRandomZlevel()
|
||||
continue
|
||||
awaydestinations.Add(L)
|
||||
|
||||
log_startup_progress("Away mission loaded.")
|
||||
admin_notice("\red \b Away mission loaded.", R_DEBUG)
|
||||
|
||||
else
|
||||
log_startup_progress("No away missions found.")
|
||||
admin_notice("\red \b No away missions found.", R_DEBUG)
|
||||
return
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
Asset cache quick users guide:
|
||||
|
||||
Make a datum at the bottom of this file with your assets for your thing.
|
||||
The simple subsystem will most like be of use for most cases.
|
||||
Then call get_asset_datum() with the type of the datum you created and store the return
|
||||
Then call .send(client) on that stored return value.
|
||||
|
||||
You can set verify to TRUE if you want send() to sleep until the client has the assets.
|
||||
*/
|
||||
|
||||
|
||||
// Amount of time(ds) MAX to send per asset, if this get exceeded we cancel the sleeping.
|
||||
// This is doubled for the first asset, then added per asset after
|
||||
#define ASSET_CACHE_SEND_TIMEOUT 7
|
||||
|
||||
//When sending mutiple assets, how many before we give the client a quaint little sending resources message
|
||||
#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8
|
||||
|
||||
//List of ALL assets for the above, format is list(filename = asset).
|
||||
/var/global/list/asset_cache = list()
|
||||
|
||||
/client
|
||||
var/list/cache = list() // List of all assets sent to this client by the asset cache.
|
||||
var/list/completed_asset_jobs = list() // List of all completed jobs, awaiting acknowledgement.
|
||||
var/list/sending = list()
|
||||
var/last_asset_job = 0 // Last job done.
|
||||
|
||||
//This proc sends the asset to the client, but only if it needs it.
|
||||
//This proc blocks(sleeps) unless verify is set to false
|
||||
/proc/send_asset(var/client/client, var/asset_name, var/verify = TRUE)
|
||||
if(!istype(client))
|
||||
if(ismob(client))
|
||||
var/mob/M = client
|
||||
if(M.client)
|
||||
client = M.client
|
||||
|
||||
else
|
||||
return 0
|
||||
|
||||
else
|
||||
return 0
|
||||
|
||||
if(client.cache.Find(asset_name) || client.sending.Find(asset_name))
|
||||
return 0
|
||||
|
||||
client << browse_rsc(asset_cache[asset_name], asset_name)
|
||||
if(!verify || !winexists(client, "asset_cache_browser")) // Can't access the asset cache browser, rip.
|
||||
if (client)
|
||||
client.cache += asset_name
|
||||
return 1
|
||||
if (!client)
|
||||
return 0
|
||||
|
||||
client.sending |= asset_name
|
||||
var/job = ++client.last_asset_job
|
||||
|
||||
client << browse({"
|
||||
<script>
|
||||
window.location.href="?asset_cache_confirm_arrival=[job]"
|
||||
</script>
|
||||
"}, "window=asset_cache_browser")
|
||||
|
||||
var/t = 0
|
||||
var/timeout_time = (ASSET_CACHE_SEND_TIMEOUT * client.sending.len) + ASSET_CACHE_SEND_TIMEOUT
|
||||
while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
|
||||
sleep(1) // Lock up the caller until this is received.
|
||||
t++
|
||||
|
||||
if(client)
|
||||
client.sending -= asset_name
|
||||
client.cache |= asset_name
|
||||
client.completed_asset_jobs -= job
|
||||
|
||||
return 1
|
||||
|
||||
//This proc blocks(sleeps) unless verify is set to false
|
||||
/proc/send_asset_list(var/client/client, var/list/asset_list, var/verify = TRUE)
|
||||
if(!istype(client))
|
||||
if(ismob(client))
|
||||
var/mob/M = client
|
||||
if(M.client)
|
||||
client = M.client
|
||||
|
||||
else
|
||||
return 0
|
||||
|
||||
else
|
||||
return 0
|
||||
|
||||
var/list/unreceived = asset_list - (client.cache + client.sending)
|
||||
if(!unreceived || !unreceived.len)
|
||||
return 0
|
||||
if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT)
|
||||
client << "Sending Resources..."
|
||||
for(var/asset in unreceived)
|
||||
if (asset in asset_cache)
|
||||
client << browse_rsc(asset_cache[asset], asset)
|
||||
|
||||
if(!verify || !winexists(client, "asset_cache_browser")) // Can't access the asset cache browser, rip.
|
||||
if (client)
|
||||
client.cache += unreceived
|
||||
return 1
|
||||
if (!client)
|
||||
return 0
|
||||
client.sending |= unreceived
|
||||
var/job = ++client.last_asset_job
|
||||
|
||||
client << browse({"
|
||||
<script>
|
||||
window.location.href="?asset_cache_confirm_arrival=[job]"
|
||||
</script>
|
||||
"}, "window=asset_cache_browser")
|
||||
|
||||
var/t = 0
|
||||
var/timeout_time = ASSET_CACHE_SEND_TIMEOUT * client.sending.len
|
||||
while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
|
||||
sleep(1) // Lock up the caller until this is received.
|
||||
t++
|
||||
|
||||
if(client)
|
||||
client.sending -= unreceived
|
||||
client.cache |= unreceived
|
||||
client.completed_asset_jobs -= job
|
||||
|
||||
return 1
|
||||
|
||||
//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start.
|
||||
//The proc calls procs that sleep for long times.
|
||||
proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE)
|
||||
for(var/file in files)
|
||||
if (!client)
|
||||
break
|
||||
if (register_asset)
|
||||
register_asset(file,files[file])
|
||||
send_asset(client,file)
|
||||
sleep(-1) //queuing calls like this too quickly can cause issues in some client versions
|
||||
|
||||
//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up.
|
||||
//if it's an icon or something be careful, you'll have to copy it before further use.
|
||||
/proc/register_asset(var/asset_name, var/asset)
|
||||
asset_cache[asset_name] = asset
|
||||
|
||||
//From here on out it's populating the asset cache.
|
||||
/proc/populate_asset_cache()
|
||||
for(var/type in typesof(/datum/asset) - list(/datum/asset, /datum/asset/simple))
|
||||
var/datum/asset/A = new type()
|
||||
A.register()
|
||||
|
||||
for(var/client/C in clients)
|
||||
//doing this to a client too soon after they've connected can cause issues, also the proc we call sleeps
|
||||
spawn(10)
|
||||
getFilesSlow(C, asset_cache, FALSE)
|
||||
|
||||
//These datums are used to populate the asset cache, the proc "register()" does this.
|
||||
|
||||
//all of our asset datums, used for referring to these later
|
||||
/var/global/list/asset_datums = list()
|
||||
|
||||
//get a assetdatum or make a new one
|
||||
/proc/get_asset_datum(var/type)
|
||||
if (!(type in asset_datums))
|
||||
return new type()
|
||||
return asset_datums[type]
|
||||
|
||||
/datum/asset/New()
|
||||
asset_datums[type] = src
|
||||
|
||||
/datum/asset/proc/register()
|
||||
return
|
||||
|
||||
/datum/asset/proc/send(client)
|
||||
return
|
||||
|
||||
//If you don't need anything complicated.
|
||||
/datum/asset/simple
|
||||
var/assets = list()
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/simple/register()
|
||||
for(var/asset_name in assets)
|
||||
register_asset(asset_name, assets[asset_name])
|
||||
/datum/asset/simple/send(client)
|
||||
send_asset_list(client,assets,verify)
|
||||
|
||||
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
/datum/asset/simple/paper
|
||||
assets = list(
|
||||
"large_stamp-clown.png" = 'icons/paper_icons/large_stamp-clown.png',
|
||||
"large_stamp-deny.png" = 'icons/paper_icons/large_stamp-deny.png',
|
||||
"large_stamp-ok.png" = 'icons/paper_icons/large_stamp-ok.png',
|
||||
"large_stamp-hop.png" = 'icons/paper_icons/large_stamp-hop.png',
|
||||
"large_stamp-cmo.png" = 'icons/paper_icons/large_stamp-cmo.png',
|
||||
"large_stamp-ce.png" = 'icons/paper_icons/large_stamp-ce.png',
|
||||
"large_stamp-hos.png" = 'icons/paper_icons/large_stamp-hos.png',
|
||||
"large_stamp-rd.png" = 'icons/paper_icons/large_stamp-rd.png',
|
||||
"large_stamp-cap.png" = 'icons/paper_icons/large_stamp-cap.png',
|
||||
"large_stamp-qm.png" = 'icons/paper_icons/large_stamp-qm.png',
|
||||
"large_stamp-law.png" = 'icons/paper_icons/large_stamp-law.png',
|
||||
"large_stamp-cent.png" = 'icons/paper_icons/large_stamp-cent.png',
|
||||
"talisman.png" = 'icons/paper_icons/talisman.png',
|
||||
"ntlogo.png" = 'icons/paper_icons/ntlogo.png',
|
||||
"sglogo.png" = 'icons/paper_icons/sglogo.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/tgui
|
||||
assets = list(
|
||||
"tgui.css" = 'tgui/assets/tgui.css',
|
||||
"tgui.js" = 'tgui/assets/tgui.js'
|
||||
)
|
||||
|
||||
/datum/asset/simple/pda
|
||||
assets = list(
|
||||
"pda_atmos.png" = 'icons/pda_icons/pda_atmos.png',
|
||||
"pda_back.png" = 'icons/pda_icons/pda_back.png',
|
||||
"pda_bell.png" = 'icons/pda_icons/pda_bell.png',
|
||||
"pda_blank.png" = 'icons/pda_icons/pda_blank.png',
|
||||
"pda_boom.png" = 'icons/pda_icons/pda_boom.png',
|
||||
"pda_bucket.png" = 'icons/pda_icons/pda_bucket.png',
|
||||
"pda_chatroom.png" = 'icons/pda_icons/pda_chatroom.png',
|
||||
"pda_crate.png" = 'icons/pda_icons/pda_crate.png',
|
||||
"pda_cuffs.png" = 'icons/pda_icons/pda_cuffs.png',
|
||||
"pda_eject.png" = 'icons/pda_icons/pda_eject.png',
|
||||
"pda_exit.png" = 'icons/pda_icons/pda_exit.png',
|
||||
"pda_honk.png" = 'icons/pda_icons/pda_honk.png',
|
||||
"pda_locked.png" = 'icons/pda_icons/pda_locked.png',
|
||||
"pda_mail.png" = 'icons/pda_icons/pda_mail.png',
|
||||
"pda_medical.png" = 'icons/pda_icons/pda_medical.png',
|
||||
"pda_menu.png" = 'icons/pda_icons/pda_menu.png',
|
||||
"pda_mule.png" = 'icons/pda_icons/pda_mule.png',
|
||||
"pda_notes.png" = 'icons/pda_icons/pda_notes.png',
|
||||
"pda_power.png" = 'icons/pda_icons/pda_power.png',
|
||||
"pda_rdoor.png" = 'icons/pda_icons/pda_rdoor.png',
|
||||
"pda_reagent.png" = 'icons/pda_icons/pda_reagent.png',
|
||||
"pda_refresh.png" = 'icons/pda_icons/pda_refresh.png',
|
||||
"pda_scanner.png" = 'icons/pda_icons/pda_scanner.png',
|
||||
"pda_signaler.png" = 'icons/pda_icons/pda_signaler.png',
|
||||
"pda_status.png" = 'icons/pda_icons/pda_status.png'
|
||||
)
|
||||
|
||||
/datum/asset/nanoui
|
||||
var/list/common = list()
|
||||
|
||||
var/list/common_dirs = list(
|
||||
"nano/assets/",
|
||||
"nano/css/",
|
||||
"nano/js/",
|
||||
"nano/images/",
|
||||
"nano/layouts/"
|
||||
)
|
||||
var/list/uncommon_dirs = list(
|
||||
"nano/templates/"
|
||||
)
|
||||
|
||||
/datum/asset/nanoui/register()
|
||||
// Crawl the directories to find files.
|
||||
for (var/path in common_dirs)
|
||||
var/list/filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // Ignore directories.
|
||||
if(fexists(path + filename))
|
||||
common[filename] = fcopy_rsc(path + filename)
|
||||
register_asset(filename, common[filename])
|
||||
for (var/path in uncommon_dirs)
|
||||
var/list/filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // Ignore directories.
|
||||
if(fexists(path + filename))
|
||||
register_asset(filename, fcopy_rsc(path + filename))
|
||||
|
||||
/datum/asset/nanoui/send(client, uncommon)
|
||||
if(!islist(uncommon))
|
||||
uncommon = list(uncommon)
|
||||
|
||||
send_asset_list(client, uncommon)
|
||||
send_asset_list(client, common)
|
||||
@@ -47,6 +47,4 @@
|
||||
|
||||
preload_rsc = 0 // This is 0 so we can set it to an URL once the player logs in and have them download the resources from a different server.
|
||||
var/global/obj/screen/click_catcher/void
|
||||
|
||||
//NanoUI//
|
||||
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
|
||||
|
||||
|
||||
@@ -28,17 +28,11 @@
|
||||
|
||||
#if defined(TOPIC_DEBUGGING)
|
||||
world << "[src]'s Topic: [href] destined for [hsrc]."
|
||||
#endif
|
||||
|
||||
if(href_list["nano_err"]) //nano throwing errors
|
||||
if(topic_debugging)
|
||||
src << "## NanoUI: " + html_decode(href_list["nano_err"]) //NANO DEBUG HOOK
|
||||
world << "## NanoUI, Subject [src]: " + html_decode(href_list["nano_err"]) //NANO DEBUG HOOK
|
||||
|
||||
if(href_list["asset_cache_confirm_arrival"])
|
||||
//src << "ASSET JOB [href_list["asset_cache_confirm_arrival"]] ARRIVED."
|
||||
var/job = text2num(href_list["asset_cache_confirm_arrival"])
|
||||
completed_asset_jobs += job
|
||||
return
|
||||
#endif
|
||||
|
||||
//search the href for script injection
|
||||
if( findtext(href,"<script",1,0) )
|
||||
@@ -161,15 +155,13 @@
|
||||
log_client_to_db()
|
||||
|
||||
send_resources()
|
||||
nanomanager.send_resources(src)
|
||||
|
||||
if(!void)
|
||||
void = new()
|
||||
void.MakeGreed()
|
||||
screen += void
|
||||
|
||||
if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them.
|
||||
src << "<span class='warning'>Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.</span>"
|
||||
|
||||
if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates.
|
||||
src << "<span class='info'>You have unread updates in the changelog.</span>"
|
||||
winset(src, "rpane.changelog", "background-color=#eaeaea;font-style=bold")
|
||||
@@ -288,18 +280,56 @@
|
||||
/client/proc/last_activity_seconds()
|
||||
return inactivity / 10
|
||||
|
||||
//Send resources to the client.
|
||||
//send resources to the client. It's here in its own proc so we can move it around easiliy if need be
|
||||
/client/proc/send_resources()
|
||||
|
||||
// Most assets are now handled through global_cache.dm
|
||||
getFiles(
|
||||
'html/search.js', // Used in various non-NanoUI HTML windows for search functionality
|
||||
'html/panels.css' // Used for styling certain panels, such as in the new player panel
|
||||
'html/search.js',
|
||||
'html/panels.css',
|
||||
'html/images/loading.gif',
|
||||
'html/images/ntlogo.png',
|
||||
'html/images/sglogo.png',
|
||||
'html/images/talisman.png',
|
||||
'icons/pda_icons/pda_atmos.png',
|
||||
'icons/pda_icons/pda_back.png',
|
||||
'icons/pda_icons/pda_bell.png',
|
||||
'icons/pda_icons/pda_blank.png',
|
||||
'icons/pda_icons/pda_boom.png',
|
||||
'icons/pda_icons/pda_bucket.png',
|
||||
'icons/pda_icons/pda_crate.png',
|
||||
'icons/pda_icons/pda_cuffs.png',
|
||||
'icons/pda_icons/pda_eject.png',
|
||||
'icons/pda_icons/pda_exit.png',
|
||||
'icons/pda_icons/pda_flashlight.png',
|
||||
'icons/pda_icons/pda_honk.png',
|
||||
'icons/pda_icons/pda_mail.png',
|
||||
'icons/pda_icons/pda_medical.png',
|
||||
'icons/pda_icons/pda_menu.png',
|
||||
'icons/pda_icons/pda_mule.png',
|
||||
'icons/pda_icons/pda_notes.png',
|
||||
'icons/pda_icons/pda_power.png',
|
||||
'icons/pda_icons/pda_rdoor.png',
|
||||
'icons/pda_icons/pda_reagent.png',
|
||||
'icons/pda_icons/pda_refresh.png',
|
||||
'icons/pda_icons/pda_scanner.png',
|
||||
'icons/pda_icons/pda_signaler.png',
|
||||
'icons/pda_icons/pda_status.png',
|
||||
'icons/spideros_icons/sos_1.png',
|
||||
'icons/spideros_icons/sos_2.png',
|
||||
'icons/spideros_icons/sos_3.png',
|
||||
'icons/spideros_icons/sos_4.png',
|
||||
'icons/spideros_icons/sos_5.png',
|
||||
'icons/spideros_icons/sos_6.png',
|
||||
'icons/spideros_icons/sos_7.png',
|
||||
'icons/spideros_icons/sos_8.png',
|
||||
'icons/spideros_icons/sos_9.png',
|
||||
'icons/spideros_icons/sos_10.png',
|
||||
'icons/spideros_icons/sos_11.png',
|
||||
'icons/spideros_icons/sos_12.png',
|
||||
'icons/spideros_icons/sos_13.png',
|
||||
'icons/spideros_icons/sos_14.png'
|
||||
)
|
||||
|
||||
spawn (10)
|
||||
//Precache the client with all other assets slowly, so as to not block other browse() calls
|
||||
getFilesSlow(src, asset_cache, register_asset = FALSE)
|
||||
|
||||
mob/proc/MayRespawn()
|
||||
return 0
|
||||
|
||||
@@ -144,24 +144,6 @@ var/list/_client_preferences_by_type
|
||||
enabled_description = "Fancy"
|
||||
disabled_description = "Plain"
|
||||
|
||||
/datum/client_preference/nanoui_style
|
||||
description = "Fancy NanoUI style"
|
||||
key = "NANO_STYLED"
|
||||
enabled_description = "Fancy"
|
||||
disabled_description = "Plain"
|
||||
|
||||
/datum/client_preference/tgui_style
|
||||
description ="tgui Style"
|
||||
key = "TGUI_FANCY"
|
||||
enabled_description = "Fancy"
|
||||
disabled_description = "Plain"
|
||||
|
||||
/datum/client_preference/tgui_monitor
|
||||
description ="tgui Monitor"
|
||||
key = "TGUI_MONITOR"
|
||||
enabled_description = "Primary"
|
||||
disabled_description = "All"
|
||||
|
||||
/********************
|
||||
* Staff Preferences *
|
||||
********************/
|
||||
|
||||
@@ -262,7 +262,7 @@ datum/preferences
|
||||
if(be_random_name)
|
||||
real_name = random_name(identifying_gender,species)
|
||||
|
||||
// Ask the preferences datums to apply their own settings to the new mob
|
||||
// Ask the preferences datums to apply their own settings to the new mob
|
||||
player_setup.copy_to_mob(character)
|
||||
|
||||
if(icon_updates)
|
||||
|
||||
@@ -798,9 +798,6 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/rig/check_access(obj/item/I)
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/rig/proc/force_rest(var/mob/user)
|
||||
if(!ai_can_move_suit(user, check_user_module = 1))
|
||||
return
|
||||
|
||||
@@ -6,6 +6,12 @@ send money to people (might be worth attaching money to custom database thing fo
|
||||
log transactions
|
||||
|
||||
*/
|
||||
|
||||
#define NO_SCREEN 0
|
||||
#define CHANGE_SECURITY_LEVEL 1
|
||||
#define TRANSFER_FUNDS 2
|
||||
#define VIEW_TRANSACTION_LOGS 3
|
||||
|
||||
/obj/item/weapon/card/id/var/money = 2000
|
||||
|
||||
/obj/machinery/atm
|
||||
@@ -20,20 +26,13 @@ log transactions
|
||||
var/datum/money_account/authenticated_account
|
||||
var/number_incorrect_tries = 0
|
||||
var/previous_account_number = 0
|
||||
var/account_num = 0
|
||||
var/pin_num = 0
|
||||
var/max_pin_attempts = 3
|
||||
var/ticks_left_locked_down = 0
|
||||
var/ticks_left_timeout = 0
|
||||
var/machine_id = ""
|
||||
var/obj/item/weapon/card/held_card
|
||||
var/editing_security_level = 0
|
||||
var/withdrawal_type = 1
|
||||
var/withdrawal = 0
|
||||
var/target_account_num = 0
|
||||
var/transaction_amount = 0
|
||||
var/transaction_purpose = 0
|
||||
var/view_screen = 0
|
||||
var/view_screen = NO_SCREEN
|
||||
var/datum/effect/effect/system/spark_spread/spark_system
|
||||
|
||||
/obj/machinery/atm/New()
|
||||
@@ -103,7 +102,7 @@ log transactions
|
||||
if(istype(I, /obj/item/weapon/card))
|
||||
if(emagged > 0)
|
||||
//prevent inserting id into an emagged ATM
|
||||
user << "\icon[src]<span class='warning'>CARD READER ERROR. This system has been compromised!</span>"
|
||||
user << "\red \icon[src] CARD READER ERROR. This system has been compromised!"
|
||||
return
|
||||
else if(istype(I,/obj/item/weapon/card/emag))
|
||||
I.resolve_attackby(src, user)
|
||||
@@ -143,67 +142,268 @@ log transactions
|
||||
|
||||
/obj/machinery/atm/attack_hand(mob/user as mob)
|
||||
if(istype(user, /mob/living/silicon))
|
||||
user << "\icon[src]<span class='warning'>Artificial unit recognized. Artificial units do not currently receive monetary compensation, as per system banking regulation #1005.</span>"
|
||||
user << "\red \icon[src] Artificial unit recognized. Artificial units do not currently receive monetary compensation, as per system banking regulation #1005."
|
||||
return
|
||||
tg_ui_interact(user)
|
||||
if(get_dist(src,user) <= 1)
|
||||
|
||||
/obj/machinery/atm/tg_ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
ui = tgui_process.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atm", "[name] [machine_id]", 550, 650, master_ui, state)
|
||||
ui.open()
|
||||
//js replicated from obj/machinery/computer/card
|
||||
var/dat = "<h1>Automatic Teller Machine</h1>"
|
||||
dat += "For all your monetary needs!<br>"
|
||||
dat += "<i>This terminal is</i> [machine_id]. <i>Report this code when contacting IT Support</i><br/>"
|
||||
|
||||
/obj/machinery/atm/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
if(authenticated_account)
|
||||
var/list/authAccount = list()
|
||||
var/list/transactions = list()
|
||||
authAccount["suspended"] = authenticated_account.suspended
|
||||
authAccount["securityLevel"] = authenticated_account.security_level
|
||||
for(var/datum/transaction/T in authenticated_account.transaction_log)
|
||||
var/list/log_list = list()
|
||||
log_list["date"] = T.date
|
||||
log_list["time"] = T.time
|
||||
log_list["target_name"] = T.target_name
|
||||
log_list["purpose"] = T.purpose
|
||||
log_list["amount"] = T.amount
|
||||
log_list["source_terminal"] = T.source_terminal
|
||||
transactions[++transactions.len] = log_list
|
||||
authAccount["transactionLog"] = transactions
|
||||
authAccount["money"] = authenticated_account.money
|
||||
authAccount["name"] = authenticated_account.owner_name
|
||||
data["authAccount"] = authAccount
|
||||
if(emagged > 0)
|
||||
dat += "Card: <span style='color: red;'>LOCKED</span><br><br><span style='color: red;'>Unauthorized terminal access detected! This ATM has been locked. Please contact IT Support.</span>"
|
||||
else
|
||||
dat += "Card: <a href='?src=\ref[src];choice=insert_card'>[held_card ? held_card.name : "------"]</a><br><br>"
|
||||
|
||||
if(ticks_left_locked_down > 0)
|
||||
dat += "<span class='alert'>Maximum number of pin attempts exceeded! Access to this ATM has been temporarily disabled.</span>"
|
||||
else if(authenticated_account)
|
||||
if(authenticated_account.suspended)
|
||||
dat += "\red<b>Access to this account has been suspended, and the funds within frozen.</b>"
|
||||
else
|
||||
switch(view_screen)
|
||||
if(CHANGE_SECURITY_LEVEL)
|
||||
dat += "Select a new security level for this account:<br><hr>"
|
||||
var/text = "Zero - Either the account number or card is required to access this account. EFTPOS transactions will require a card and ask for a pin, but not verify the pin is correct."
|
||||
if(authenticated_account.security_level != 0)
|
||||
text = "<A href='?src=\ref[src];choice=change_security_level;new_security_level=0'>[text]</a>"
|
||||
dat += "[text]<hr>"
|
||||
text = "One - An account number and pin must be manually entered to access this account and process transactions."
|
||||
if(authenticated_account.security_level != 1)
|
||||
text = "<A href='?src=\ref[src];choice=change_security_level;new_security_level=1'>[text]</a>"
|
||||
dat += "[text]<hr>"
|
||||
text = "Two - In addition to account number and pin, a card is required to access this account and process transactions."
|
||||
if(authenticated_account.security_level != 2)
|
||||
text = "<A href='?src=\ref[src];choice=change_security_level;new_security_level=2'>[text]</a>"
|
||||
dat += "[text]<hr><br>"
|
||||
dat += "<A href='?src=\ref[src];choice=view_screen;view_screen=0'>Back</a>"
|
||||
if(VIEW_TRANSACTION_LOGS)
|
||||
dat += "<b>Transaction logs</b><br>"
|
||||
dat += "<A href='?src=\ref[src];choice=view_screen;view_screen=0'>Back</a>"
|
||||
dat += "<table border=1 style='width:100%'>"
|
||||
dat += "<tr>"
|
||||
dat += "<td><b>Date</b></td>"
|
||||
dat += "<td><b>Time</b></td>"
|
||||
dat += "<td><b>Target</b></td>"
|
||||
dat += "<td><b>Purpose</b></td>"
|
||||
dat += "<td><b>Value</b></td>"
|
||||
dat += "<td><b>Source terminal ID</b></td>"
|
||||
dat += "</tr>"
|
||||
for(var/datum/transaction/T in authenticated_account.transaction_log)
|
||||
dat += "<tr>"
|
||||
dat += "<td>[T.date]</td>"
|
||||
dat += "<td>[T.time]</td>"
|
||||
dat += "<td>[T.target_name]</td>"
|
||||
dat += "<td>[T.purpose]</td>"
|
||||
dat += "<td>$[T.amount]</td>"
|
||||
dat += "<td>[T.source_terminal]</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<A href='?src=\ref[src];choice=print_transaction'>Print</a><br>"
|
||||
if(TRANSFER_FUNDS)
|
||||
dat += "<b>Account balance:</b> $[authenticated_account.money]<br>"
|
||||
dat += "<A href='?src=\ref[src];choice=view_screen;view_screen=0'>Back</a><br><br>"
|
||||
dat += "<form name='transfer' action='?src=\ref[src]' method='get'>"
|
||||
dat += "<input type='hidden' name='src' value='\ref[src]'>"
|
||||
dat += "<input type='hidden' name='choice' value='transfer'>"
|
||||
dat += "Target account number: <input type='text' name='target_acc_number' value='' style='width:200px; background-color:white;'><br>"
|
||||
dat += "Funds to transfer: <input type='text' name='funds_amount' value='' style='width:200px; background-color:white;'><br>"
|
||||
dat += "Transaction purpose: <input type='text' name='purpose' value='Funds transfer' style='width:200px; background-color:white;'><br>"
|
||||
dat += "<input type='submit' value='Transfer funds'><br>"
|
||||
dat += "</form>"
|
||||
else
|
||||
dat += "Welcome, <b>[authenticated_account.owner_name].</b><br/>"
|
||||
dat += "<b>Account balance:</b> $[authenticated_account.money]"
|
||||
dat += "<form name='withdrawal' action='?src=\ref[src]' method='get'>"
|
||||
dat += "<input type='hidden' name='src' value='\ref[src]'>"
|
||||
dat += "<input type='radio' name='choice' value='withdrawal' checked> Cash <input type='radio' name='choice' value='e_withdrawal'> Chargecard<br>"
|
||||
dat += "<input type='text' name='funds_amount' value='' style='width:200px; background-color:white;'><input type='submit' value='Withdraw'>"
|
||||
dat += "</form>"
|
||||
dat += "<A href='?src=\ref[src];choice=view_screen;view_screen=1'>Change account security level</a><br>"
|
||||
dat += "<A href='?src=\ref[src];choice=view_screen;view_screen=2'>Make transfer</a><br>"
|
||||
dat += "<A href='?src=\ref[src];choice=view_screen;view_screen=3'>View transaction log</a><br>"
|
||||
dat += "<A href='?src=\ref[src];choice=balance_statement'>Print balance statement</a><br>"
|
||||
dat += "<A href='?src=\ref[src];choice=logout'>Logout</a><br>"
|
||||
else
|
||||
dat += "<form name='atm_auth' action='?src=\ref[src]' method='get'>"
|
||||
dat += "<input type='hidden' name='src' value='\ref[src]'>"
|
||||
dat += "<input type='hidden' name='choice' value='attempt_auth'>"
|
||||
dat += "<b>Account:</b> <input type='text' id='account_num' name='account_num' style='width:250px; background-color:white;'><br>"
|
||||
dat += "<b>PIN:</b> <input type='text' id='account_pin' name='account_pin' style='width:250px; background-color:white;'><br>"
|
||||
dat += "<input type='submit' value='Submit'><br>"
|
||||
dat += "</form>"
|
||||
|
||||
user << browse(dat,"window=atm;size=550x650")
|
||||
else
|
||||
data["authAccount"] = null
|
||||
data["emagged"] = emagged
|
||||
data["lockdown"] = ticks_left_locked_down > 0 ? TRUE : null
|
||||
data["screen"] = view_screen
|
||||
data["transactionTargetNumber"] = target_account_num
|
||||
data["transactionTargetAmount"] = transaction_amount
|
||||
data["transactionPurpose"] = transaction_purpose
|
||||
data["card"] = held_card
|
||||
data["cardName"] = held_card ? held_card.name : "Insert Card"
|
||||
data["account"] = account_num
|
||||
data["pin"] = pin_num
|
||||
data["withdrawal"] = withdrawal
|
||||
data["withdrawalType"] = withdrawal_type
|
||||
user << browse(null,"window=atm")
|
||||
|
||||
return data
|
||||
/obj/machinery/atm/Topic(var/href, var/href_list)
|
||||
if(href_list["choice"])
|
||||
switch(href_list["choice"])
|
||||
if("transfer")
|
||||
if(authenticated_account)
|
||||
var/transfer_amount = text2num(href_list["funds_amount"])
|
||||
transfer_amount = round(transfer_amount, 0.01)
|
||||
if(transfer_amount <= 0)
|
||||
alert("That is not a valid amount.")
|
||||
else if(transfer_amount <= authenticated_account.money)
|
||||
var/target_account_number = text2num(href_list["target_acc_number"])
|
||||
var/transfer_purpose = href_list["purpose"]
|
||||
if(charge_to_account(target_account_number, authenticated_account.owner_name, transfer_purpose, machine_id, transfer_amount))
|
||||
usr << "\icon[src]<span class='info'>Funds transfer successful.</span>"
|
||||
authenticated_account.money -= transfer_amount
|
||||
|
||||
/obj/machinery/atm/ui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
switch(action)
|
||||
if("screen")
|
||||
view_screen = text2num(params["new_screen"])
|
||||
//create an entry in the account transaction log
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "Account #[target_account_number]"
|
||||
T.purpose = transfer_purpose
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
T.amount = "([transfer_amount])"
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Funds transfer failed.</span>"
|
||||
|
||||
if("security_level")
|
||||
if(authenticated_account)
|
||||
var/new_sec_level = max(min(text2num(params["new_security_level"]), 2), 0)
|
||||
authenticated_account.security_level = new_sec_level
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have enough funds to do that!</span>"
|
||||
if("view_screen")
|
||||
view_screen = text2num(href_list["view_screen"])
|
||||
if("change_security_level")
|
||||
if(authenticated_account)
|
||||
var/new_sec_level = max( min(text2num(href_list["new_security_level"]), 2), 0)
|
||||
authenticated_account.security_level = new_sec_level
|
||||
if("attempt_auth")
|
||||
|
||||
if("print")
|
||||
if(params["print_type"] == "transaction")
|
||||
// check if they have low security enabled
|
||||
scan_user(usr)
|
||||
|
||||
if(!ticks_left_locked_down && held_card)
|
||||
var/tried_account_num = text2num(href_list["account_num"])
|
||||
if(!tried_account_num)
|
||||
tried_account_num = held_card.associated_account_number
|
||||
var/tried_pin = text2num(href_list["account_pin"])
|
||||
|
||||
authenticated_account = attempt_account_access(tried_account_num, tried_pin, held_card && held_card.associated_account_number == tried_account_num ? 2 : 1)
|
||||
if(!authenticated_account)
|
||||
number_incorrect_tries++
|
||||
if(previous_account_number == tried_account_num)
|
||||
if(number_incorrect_tries > max_pin_attempts)
|
||||
//lock down the atm
|
||||
ticks_left_locked_down = 30
|
||||
playsound(src, 'sound/machines/buzz-two.ogg', 50, 1)
|
||||
|
||||
//create an entry in the account transaction log
|
||||
var/datum/money_account/failed_account = get_account(tried_account_num)
|
||||
if(failed_account)
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = failed_account.owner_name
|
||||
T.purpose = "Unauthorised login attempt"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
failed_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\red \icon[src] Incorrect pin/account combination entered, [max_pin_attempts - number_incorrect_tries] attempts remaining."
|
||||
previous_account_number = tried_account_num
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1)
|
||||
else
|
||||
usr << "\red \icon[src] incorrect pin/account combination entered."
|
||||
number_incorrect_tries = 0
|
||||
else
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
ticks_left_timeout = 120
|
||||
view_screen = NO_SCREEN
|
||||
|
||||
//create a transaction log entry
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = authenticated_account.owner_name
|
||||
T.purpose = "Remote terminal access"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
|
||||
usr << "\blue \icon[src] Access granted. Welcome user '[authenticated_account.owner_name].'"
|
||||
|
||||
previous_account_number = tried_account_num
|
||||
if("e_withdrawal")
|
||||
var/amount = max(text2num(href_list["funds_amount"]),0)
|
||||
amount = round(amount, 0.01)
|
||||
if(amount <= 0)
|
||||
alert("That is not a valid amount.")
|
||||
else if(authenticated_account && amount > 0)
|
||||
if(amount <= authenticated_account.money)
|
||||
playsound(src, 'sound/machines/chime.ogg', 50, 1)
|
||||
|
||||
//remove the money
|
||||
authenticated_account.money -= amount
|
||||
|
||||
// spawn_money(amount,src.loc)
|
||||
spawn_ewallet(amount,src.loc,usr)
|
||||
|
||||
//create an entry in the account transaction log
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = authenticated_account.owner_name
|
||||
T.purpose = "Credit withdrawal"
|
||||
T.amount = "([amount])"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have enough funds to do that!</span>"
|
||||
if("withdrawal")
|
||||
var/amount = max(text2num(href_list["funds_amount"]),0)
|
||||
amount = round(amount, 0.01)
|
||||
if(amount <= 0)
|
||||
alert("That is not a valid amount.")
|
||||
else if(authenticated_account && amount > 0)
|
||||
if(amount <= authenticated_account.money)
|
||||
playsound(src, 'sound/machines/chime.ogg', 50, 1)
|
||||
|
||||
//remove the money
|
||||
authenticated_account.money -= amount
|
||||
|
||||
spawn_money(amount,src.loc,usr)
|
||||
|
||||
//create an entry in the account transaction log
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = authenticated_account.owner_name
|
||||
T.purpose = "Credit withdrawal"
|
||||
T.amount = "([amount])"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have enough funds to do that!</span>"
|
||||
if("balance_statement")
|
||||
if(authenticated_account)
|
||||
var/obj/item/weapon/paper/R = new(src.loc)
|
||||
R.name = "Account balance: [authenticated_account.owner_name]"
|
||||
R.info = "<b>NT Automated Teller Account Statement</b><br><br>"
|
||||
R.info += "<i>Account holder:</i> [authenticated_account.owner_name]<br>"
|
||||
R.info += "<i>Account number:</i> [authenticated_account.account_number]<br>"
|
||||
R.info += "<i>Balance:</i> $[authenticated_account.money]<br>"
|
||||
R.info += "<i>Date and time:</i> [stationtime2text()], [current_date_string]<br><br>"
|
||||
R.info += "<i>Service terminal ID:</i> [machine_id]<br>"
|
||||
|
||||
//stamp the paper
|
||||
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
|
||||
stampoverlay.icon_state = "paper_stamp-cent"
|
||||
if(!R.stamped)
|
||||
R.stamped = new
|
||||
R.stamped += /obj/item/weapon/stamp
|
||||
R.overlays += stampoverlay
|
||||
R.stamps += "<HR><i>This paper has been stamped by the Automatic Teller Machine.</i>"
|
||||
|
||||
if(prob(50))
|
||||
playsound(loc, 'sound/items/polaroid1.ogg', 50, 1)
|
||||
else
|
||||
playsound(loc, 'sound/items/polaroid2.ogg', 50, 1)
|
||||
if ("print_transaction")
|
||||
if(authenticated_account)
|
||||
var/obj/item/weapon/paper/R = new(src.loc)
|
||||
R.name = "Transaction logs: [authenticated_account.owner_name]"
|
||||
@@ -241,221 +441,29 @@ log transactions
|
||||
R.overlays += stampoverlay
|
||||
R.stamps += "<HR><i>This paper has been stamped by the Automatic Teller Machine.</i>"
|
||||
|
||||
if(prob(50))
|
||||
playsound(loc, 'sound/items/polaroid1.ogg', 50, 1)
|
||||
else
|
||||
playsound(loc, 'sound/items/polaroid2.ogg', 50, 1)
|
||||
|
||||
if(params["print_type"] == "balance")
|
||||
if(authenticated_account)
|
||||
var/obj/item/weapon/paper/R = new(src.loc)
|
||||
R.name = "Account balance: [authenticated_account.owner_name]"
|
||||
R.info = "<b>NT Automated Teller Account Statement</b><br><br>"
|
||||
R.info += "<i>Account holder:</i> [authenticated_account.owner_name]<br>"
|
||||
R.info += "<i>Account number:</i> [authenticated_account.account_number]<br>"
|
||||
R.info += "<i>Balance:</i> $[authenticated_account.money]<br>"
|
||||
R.info += "<i>Date and time:</i> [stationtime2text()], [current_date_string]<br><br>"
|
||||
R.info += "<i>Service terminal ID:</i> [machine_id]<br>"
|
||||
|
||||
//stamp the paper
|
||||
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
|
||||
stampoverlay.icon_state = "paper_stamp-cent"
|
||||
if(!R.stamped)
|
||||
R.stamped = new
|
||||
R.stamped += /obj/item/weapon/stamp
|
||||
R.overlays += stampoverlay
|
||||
R.stamps += "<HR><i>This paper has been stamped by the Automatic Teller Machine.</i>"
|
||||
|
||||
if(prob(50))
|
||||
playsound(loc, 'sound/items/polaroid1.ogg', 50, 1)
|
||||
else
|
||||
playsound(loc, 'sound/items/polaroid2.ogg', 50, 1)
|
||||
|
||||
if("input")
|
||||
var/response = input("ATM input.", "ATM input.", params["input_current"])
|
||||
switch(params["input_name"])
|
||||
if("transactiontarget")
|
||||
target_account_num = text2num(response)
|
||||
if("transactionamount")
|
||||
transaction_amount = text2num(response)
|
||||
if("transactionpurpose")
|
||||
transaction_purpose = response
|
||||
if("account")
|
||||
account_num = text2num(response)
|
||||
if("pin")
|
||||
pin_num = text2num(response)
|
||||
if("withdrawalamount")
|
||||
withdrawal = text2num(response)
|
||||
|
||||
if("submit")
|
||||
if(params["submit_type"] == "transaction")
|
||||
if(authenticated_account)
|
||||
var/transfer_amount = transaction_amount
|
||||
transfer_amount = round(transfer_amount, 0.01)
|
||||
if(transfer_amount <= 0)
|
||||
alert("That is not a valid amount.")
|
||||
else if(transfer_amount <= authenticated_account.money)
|
||||
var/target_account_number = target_account_num
|
||||
var/transfer_purpose = transaction_purpose
|
||||
if(charge_to_account(target_account_number, authenticated_account.owner_name, transfer_purpose, machine_id, transfer_amount))
|
||||
usr << "\icon[src]<span class='info'>Funds transfer successful.</span>"
|
||||
authenticated_account.money -= transfer_amount
|
||||
|
||||
//create an entry in the account transaction log
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "Account #[target_account_number]"
|
||||
T.purpose = transfer_purpose
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
T.amount = "([transfer_amount])"
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Funds transfer failed.</span>"
|
||||
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have enough funds to do that!</span>"
|
||||
|
||||
if(params["submit_type"] == "login")
|
||||
// check if they have low security enabled
|
||||
scan_user(usr)
|
||||
|
||||
if(!ticks_left_locked_down && held_card)
|
||||
var/tried_account_num = account_num
|
||||
if(!tried_account_num)
|
||||
tried_account_num = held_card.associated_account_number
|
||||
var/tried_pin = pin_num
|
||||
|
||||
authenticated_account = attempt_account_access(tried_account_num, tried_pin, held_card && held_card.associated_account_number == tried_account_num ? 2 : 1)
|
||||
if(!authenticated_account)
|
||||
number_incorrect_tries++
|
||||
if(previous_account_number == tried_account_num)
|
||||
if(number_incorrect_tries > max_pin_attempts)
|
||||
//lock down the atm
|
||||
ticks_left_locked_down = 30
|
||||
playsound(src, 'sound/machines/buzz-two.ogg', 50, 1)
|
||||
|
||||
//create an entry in the account transaction log
|
||||
var/datum/money_account/failed_account = get_account(tried_account_num)
|
||||
if(failed_account)
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = failed_account.owner_name
|
||||
T.purpose = "Unauthorised login attempt"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
failed_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Incorrect pin/account combination entered, [max_pin_attempts - number_incorrect_tries] attempts remaining.</span>"
|
||||
previous_account_number = tried_account_num
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>incorrect pin/account combination entered.</span>"
|
||||
number_incorrect_tries = 0
|
||||
else
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
ticks_left_timeout = 120
|
||||
view_screen = "home"
|
||||
|
||||
//create a transaction log entry
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = authenticated_account.owner_name
|
||||
T.purpose = "Remote terminal access"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
|
||||
usr << "\icon[src]<span class='info'>Access granted. Welcome user '[authenticated_account.owner_name].'</span>"
|
||||
|
||||
previous_account_number = tried_account_num
|
||||
|
||||
if("withdrawal_type")
|
||||
withdrawal_type = text2num(params["type"])
|
||||
|
||||
if("withdraw")
|
||||
if(withdrawal_type == 1)
|
||||
var/amount = max(withdrawal,0)
|
||||
amount = round(amount, 0.01)
|
||||
if(amount <= 0)
|
||||
alert("That is not a valid amount.")
|
||||
else if(authenticated_account && amount > 0)
|
||||
if(amount <= authenticated_account.money)
|
||||
playsound(src, 'sound/machines/chime.ogg', 50, 1)
|
||||
|
||||
//remove the money
|
||||
authenticated_account.money -= amount
|
||||
|
||||
spawn_money(amount,src.loc,usr)
|
||||
|
||||
//create an entry in the account transaction log
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = authenticated_account.owner_name
|
||||
T.purpose = "Credit withdrawal"
|
||||
T.amount = "([amount])"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have enough funds to do that!</span>"
|
||||
|
||||
else if(withdrawal_type == 2)
|
||||
var/amount = max(withdrawal,0)
|
||||
amount = round(amount, 0.01)
|
||||
if(amount <= 0)
|
||||
alert("That is not a valid amount.")
|
||||
else if(authenticated_account && amount > 0)
|
||||
if(amount <= authenticated_account.money)
|
||||
playsound(src, 'sound/machines/chime.ogg', 50, 1)
|
||||
|
||||
//remove the money
|
||||
authenticated_account.money -= amount
|
||||
|
||||
// spawn_money(amount,src.loc)
|
||||
spawn_ewallet(amount,src.loc,usr)
|
||||
|
||||
//create an entry in the account transaction log
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = authenticated_account.owner_name
|
||||
T.purpose = "Credit withdrawal"
|
||||
T.amount = "([amount])"
|
||||
T.source_terminal = machine_id
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have enough funds to do that!</span>"
|
||||
else
|
||||
usr << "<span class='warning'>Error! Select a withdrawal method!</span>"
|
||||
|
||||
withdrawal = 0
|
||||
|
||||
if("insert_card")
|
||||
if(!held_card)
|
||||
//this might happen if the user had the browser window open when somebody emagged it
|
||||
if(emagged > 0)
|
||||
usr << "\icon[src]<span class='warning'>The ATM card reader rejected your ID because this machine has been sabotaged!</span>"
|
||||
if(prob(50))
|
||||
playsound(loc, 'sound/items/polaroid1.ogg', 50, 1)
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
held_card = I
|
||||
else
|
||||
release_held_id(usr)
|
||||
playsound(loc, 'sound/items/polaroid2.ogg', 50, 1)
|
||||
|
||||
if("logout")
|
||||
authenticated_account = null
|
||||
account_num = 0
|
||||
pin_num = 0
|
||||
view_screen = 0
|
||||
target_account_num = 0
|
||||
transaction_purpose = 0
|
||||
transaction_amount = 0
|
||||
withdrawal = 0
|
||||
if("insert_card")
|
||||
if(!held_card)
|
||||
//this might happen if the user had the browser window open when somebody emagged it
|
||||
if(emagged > 0)
|
||||
usr << "\red \icon[src] The ATM card reader rejected your ID because this machine has been sabotaged!"
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
held_card = I
|
||||
else
|
||||
release_held_id(usr)
|
||||
if("logout")
|
||||
authenticated_account = null
|
||||
//usr << browse(null,"window=atm")
|
||||
|
||||
return TRUE
|
||||
src.attack_hand(usr)
|
||||
|
||||
//stolen wholesale and then edited a bit from newscasters, which are awesome and by Agouri
|
||||
/obj/machinery/atm/proc/scan_user(mob/living/carbon/human/human_user as mob)
|
||||
@@ -470,7 +478,7 @@ log transactions
|
||||
if(I)
|
||||
authenticated_account = attempt_account_access(I.associated_account_number)
|
||||
if(authenticated_account)
|
||||
human_user << "\icon[src]<span class='info'>Access granted. Welcome user '[authenticated_account.owner_name].'</span>"
|
||||
human_user << "\blue \icon[src] Access granted. Welcome user '[authenticated_account.owner_name].'"
|
||||
|
||||
//create a transaction log entry
|
||||
var/datum/transaction/T = new()
|
||||
@@ -481,7 +489,7 @@ log transactions
|
||||
T.time = stationtime2text()
|
||||
authenticated_account.transaction_log.Add(T)
|
||||
|
||||
view_screen = 0
|
||||
view_screen = NO_SCREEN
|
||||
|
||||
// put the currently held id on the ground or in the hand of the user
|
||||
/obj/machinery/atm/proc/release_held_id(mob/living/carbon/human/human_user as mob)
|
||||
|
||||
@@ -720,10 +720,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
/mob/observer/dead/canface()
|
||||
return 1
|
||||
|
||||
/mob/proc/can_admin_interact()
|
||||
return 0
|
||||
|
||||
/mob/observer/dead/can_admin_interact()
|
||||
/mob/observer/dead/proc/can_admin_interact()
|
||||
return check_rights(R_ADMIN, 0, src)
|
||||
|
||||
/mob/observer/dead/verb/toggle_ghostsee()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/mob/Logout()
|
||||
nanomanager.user_logout(src) // this is used to clean up (remove) this user's Nano UIs
|
||||
tgui_process.on_logout(src)
|
||||
player_list -= src
|
||||
log_access("Logout: [key_name(src)]")
|
||||
if(admin_datums[src.ckey])
|
||||
|
||||
@@ -576,10 +576,4 @@ var/list/global/organ_rel_size = list(
|
||||
)
|
||||
|
||||
/mob/proc/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash)
|
||||
return
|
||||
|
||||
/proc/get_both_hands(mob/living/carbon/M)
|
||||
if(!istype(M))
|
||||
return
|
||||
var/list/hands = list(M.l_hand, M.r_hand)
|
||||
return hands
|
||||
return
|
||||
@@ -1,9 +0,0 @@
|
||||
/*
|
||||
This state only checks if user is conscious.
|
||||
*/
|
||||
/var/global/datum/topic_state/hands/hands_state = new()
|
||||
|
||||
/datum/topic_state/hands/can_use_topic(var/src_object, var/mob/user)
|
||||
. = user.shared_ui_interaction(src_object)
|
||||
if(. > STATUS_CLOSE)
|
||||
. = min(., user.hands_can_use_topic(src_object))
|
||||
@@ -1,6 +1,6 @@
|
||||
/datum/nano_module
|
||||
var/name
|
||||
var/datum/host
|
||||
var/host
|
||||
|
||||
/datum/nano_module/New(var/host)
|
||||
src.host = host
|
||||
|
||||
@@ -5,6 +5,32 @@
|
||||
var/open_uis[0]
|
||||
// a list of current open /nanoui UIs, not grouped, for use in processing
|
||||
var/list/processing_uis = list()
|
||||
// a list of asset filenames which are to be sent to the client on user logon
|
||||
var/list/asset_files = list()
|
||||
|
||||
/**
|
||||
* Create a new nanomanager instance.
|
||||
* This proc generates a list of assets which are to be sent to each client on connect
|
||||
*
|
||||
* @return /nanomanager new nanomanager object
|
||||
*/
|
||||
/datum/nanomanager/New()
|
||||
var/list/nano_asset_dirs = list(\
|
||||
"nano/css/",\
|
||||
"nano/images/",\
|
||||
"nano/js/",\
|
||||
"nano/templates/"\
|
||||
)
|
||||
|
||||
var/list/filenames = null
|
||||
for (var/path in nano_asset_dirs)
|
||||
filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
|
||||
if(fexists(path + filename))
|
||||
asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
|
||||
|
||||
return
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
|
||||
@@ -228,4 +254,18 @@
|
||||
|
||||
oldMob.open_uis.Cut()
|
||||
|
||||
return 1 // success
|
||||
return 1 // success
|
||||
|
||||
/**
|
||||
* Sends all nano assets to the client
|
||||
* This is called on user login
|
||||
*
|
||||
* @param client /client The user's client
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
/datum/nanomanager/proc/send_resources(client)
|
||||
for(var/file in asset_files)
|
||||
client << browse_rsc(file) // send the file to the client
|
||||
|
||||
|
||||
@@ -57,21 +57,22 @@
|
||||
world.log << "NanoMapGen: <B>GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])</B>"
|
||||
usr << "NanoMapGen: <B>GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])</B>"
|
||||
|
||||
var/count = 0;
|
||||
for(var/WorldX = startX, WorldX <= endX, WorldX++)
|
||||
for(var/WorldY = startY, WorldY <= endY, WorldY++)
|
||||
var/turf/T = locate(WorldX, WorldY, currentZ)
|
||||
var/list/atoms = T.contents + T
|
||||
atoms = sortByVar(atoms, "layer")
|
||||
for(var/atom/A in atoms)
|
||||
if(A.type == /turf/space|| istype(A, /mob) || A.invisibility > 0)
|
||||
continue
|
||||
|
||||
var/icon/TurfIcon = new(A.icon, A.icon_state, A.dir, 1, 0)
|
||||
TurfIcon.Scale(NANOMAP_ICON_SIZE, NANOMAP_ICON_SIZE)
|
||||
var/atom/Turf = locate(WorldX, WorldY, currentZ)
|
||||
|
||||
Tile.Blend(TurfIcon, ICON_OVERLAY, ((WorldX - 1) * NANOMAP_ICON_SIZE) + (A.pixel_x * NANOMAP_ICON_SIZE / 32), ((WorldY - 1) * NANOMAP_ICON_SIZE) + (A.pixel_y * NANOMAP_ICON_SIZE / 32))
|
||||
var/icon/TurfIcon = new(Turf.icon, Turf.icon_state)
|
||||
TurfIcon.Scale(NANOMAP_ICON_SIZE, NANOMAP_ICON_SIZE)
|
||||
|
||||
CHECK_TICK
|
||||
Tile.Blend(TurfIcon, ICON_OVERLAY, ((WorldX - 1) * NANOMAP_ICON_SIZE), ((WorldY - 1) * NANOMAP_ICON_SIZE))
|
||||
|
||||
count++
|
||||
|
||||
if (count % 8000 == 0)
|
||||
world.log << "NanoMapGen: <B>[count] tiles done</B>"
|
||||
sleep(1)
|
||||
|
||||
var/mapFilename = "nanomap_z[currentZ]-new.png"
|
||||
|
||||
|
||||
@@ -96,9 +96,6 @@ nanoui is used to open and update nano browser uis
|
||||
|
||||
add_common_assets()
|
||||
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui)
|
||||
assets.send(user, ntemplate_filename)
|
||||
|
||||
/**
|
||||
* Use this proc to add assets which are common to (and required by) all nano uis
|
||||
*
|
||||
@@ -106,13 +103,15 @@ nanoui is used to open and update nano browser uis
|
||||
*/
|
||||
/datum/nanoui/proc/add_common_assets()
|
||||
add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together)
|
||||
add_script("nano.js") // A JS file of the NanoUI JavaScript compressed into one file.
|
||||
add_stylesheet("nanoui.css") // Concatenated CSS sheet common to all UIs, contains all of the standard NanoUI styling.
|
||||
|
||||
// CodeMirror
|
||||
add_script("codemirror-compressed.js") // A custom minified JavaScript file of CodeMirror, with the following plugins: CSS Mode, NTSL Mode, CSS-hint addon, Search addon, Sublime Keymap.
|
||||
add_stylesheet("codemirror.css") // A CSS sheet containing the basic stylings and formatting information for CodeMirror.
|
||||
add_stylesheet("cm_lesser-dark.css") // A theme for CodeMirror to use, which closely resembles the rest of the NanoUI style.
|
||||
add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions.
|
||||
add_script("nano_template.js") // The NanoTemplate JS, this is used to render templates.
|
||||
add_script("nano_state_manager.js") // The NanoStateManager JS, it handles updates from the server and passes data to the current state
|
||||
add_script("nano_state.js") // The NanoState JS, this is the base state which all states must inherit from
|
||||
add_script("nano_state_default.js") // The NanoStateDefault JS, this is the "default" state (used by all UIs by default), which inherits from NanoState
|
||||
add_script("nano_base_callbacks.js") // The NanoBaseCallbacks JS, this is used to set up (before and after update) callbacks which are common to all UIs
|
||||
add_script("nano_base_helpers.js") // The NanoBaseHelpers JS, this is used to set up template helpers which are common to all UIs
|
||||
add_stylesheet("shared.css") // this CSS sheet is common to all UIs
|
||||
add_stylesheet("icons.css") // this CSS sheet is common to all UIs
|
||||
|
||||
/**
|
||||
* Set the current status (also known as visibility) of this ui.
|
||||
@@ -187,15 +186,7 @@ nanoui is used to open and update nano browser uis
|
||||
"autoUpdateContent" = auto_update_content,
|
||||
"showMap" = show_map,
|
||||
"mapZLevel" = map_z_level,
|
||||
"user" = list(
|
||||
"name" = user.name,
|
||||
"fancy" = user.client.is_preference_enabled(/datum/client_preference/browser_style)
|
||||
),
|
||||
"window" = list(
|
||||
"width" = width,
|
||||
"height" = height,
|
||||
"ref" = window_id
|
||||
)
|
||||
"user" = list("name" = user.name)
|
||||
)
|
||||
return config_data
|
||||
|
||||
@@ -343,7 +334,7 @@ nanoui is used to open and update nano browser uis
|
||||
/datum/nanoui/proc/get_html()
|
||||
|
||||
// before the UI opens, add the layout files based on the layout key
|
||||
//add_stylesheet("layout_[layout_key].css")
|
||||
add_stylesheet("layout_[layout_key].css")
|
||||
add_template("layout", "layout_[layout_key].tmpl")
|
||||
|
||||
var/head_content = ""
|
||||
@@ -392,9 +383,9 @@ nanoui is used to open and update nano browser uis
|
||||
</div>
|
||||
<noscript>
|
||||
<div id='uiNoScript'>
|
||||
<h1>Javascript Required</h1>
|
||||
<p>Javascript is required in order to use this NanoUI interface.</p>
|
||||
<p>Please enable Javascript in Internet Explorer, and restart your game.</p>
|
||||
<h2>JAVASCRIPT REQUIRED</h2>
|
||||
<p>Your Internet Explorer's Javascript is disabled (or broken).<br/>
|
||||
Enable Javascript and then open this UI again.</p>
|
||||
</div>
|
||||
</noscript>
|
||||
</body>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
return
|
||||
|
||||
/obj/item/weapon/clipboard/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
|
||||
|
||||
if(istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/weapon/photo))
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
@@ -106,20 +106,20 @@
|
||||
|
||||
else if(href_list["write"])
|
||||
var/obj/item/weapon/P = locate(href_list["write"])
|
||||
|
||||
|
||||
if(P && (P.loc == src) && istype(P, /obj/item/weapon/paper) && (P == toppaper) )
|
||||
|
||||
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
|
||||
|
||||
if(istype(I, /obj/item/weapon/pen))
|
||||
|
||||
|
||||
P.attackby(I, usr)
|
||||
|
||||
else if(href_list["remove"])
|
||||
var/obj/item/P = locate(href_list["remove"])
|
||||
|
||||
|
||||
if(P && (P.loc == src) && (istype(P, /obj/item/weapon/paper) || istype(P, /obj/item/weapon/photo)) )
|
||||
|
||||
|
||||
P.loc = usr.loc
|
||||
usr.put_in_hands(P)
|
||||
if(P == toppaper)
|
||||
@@ -129,25 +129,30 @@
|
||||
toppaper = newtop
|
||||
else
|
||||
toppaper = null
|
||||
|
||||
|
||||
else if(href_list["rename"])
|
||||
var/obj/item/weapon/O = locate(href_list["rename"])
|
||||
|
||||
|
||||
if(O && (O.loc == src))
|
||||
if(istype(O, /obj/item/weapon/paper))
|
||||
var/obj/item/weapon/paper/to_rename = O
|
||||
to_rename.rename()
|
||||
|
||||
|
||||
else if(istype(O, /obj/item/weapon/photo))
|
||||
var/obj/item/weapon/photo/to_rename = O
|
||||
to_rename.rename()
|
||||
|
||||
else if(href_list["read"])
|
||||
var/obj/item/weapon/paper/P = locate(href_list["read"])
|
||||
|
||||
|
||||
if(P && (P.loc == src) && istype(P, /obj/item/weapon/paper) )
|
||||
|
||||
P.show_content(usr)
|
||||
|
||||
if(!(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/observer/dead) || istype(usr, /mob/living/silicon)))
|
||||
usr << browse("<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[stars(P.info)][P.stamps]</BODY></HTML>", "window=[P.name]")
|
||||
onclose(usr, "[P.name]")
|
||||
else
|
||||
usr << browse("<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[P.info][P.stamps]</BODY></HTML>", "window=[P.name]")
|
||||
onclose(usr, "[P.name]")
|
||||
|
||||
else if(href_list["look"])
|
||||
var/obj/item/weapon/photo/P = locate(href_list["look"])
|
||||
|
||||
@@ -102,7 +102,12 @@
|
||||
else if(href_list["read"])
|
||||
var/obj/item/weapon/paper/P = locate(href_list["read"])
|
||||
if(P && (P.loc == src) && istype(P))
|
||||
P.show_content(usr)
|
||||
if(!(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/observer/dead) || istype(usr, /mob/living/silicon)))
|
||||
usr << browse("<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[stars(P.info)][P.stamps]</BODY></HTML>", "window=[P.name]")
|
||||
onclose(usr, "[P.name]")
|
||||
else
|
||||
usr << browse("<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[P.info][P.stamps]</BODY></HTML>", "window=[P.name]")
|
||||
onclose(usr, "[P.name]")
|
||||
else if(href_list["look"])
|
||||
var/obj/item/weapon/photo/P = locate(href_list["look"])
|
||||
if(P && (P.loc == src) && istype(P))
|
||||
|
||||
@@ -79,22 +79,13 @@
|
||||
user << "<span class='notice'>You have to go closer if you want to read it.</span>"
|
||||
return
|
||||
|
||||
/obj/item/weapon/paper/proc/show_content(var/mob/user, var/forceshow = 0, var/forcestars = 0, var/infolinks = 0, var/view = 1)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/paper)
|
||||
assets.send(user)
|
||||
|
||||
var/data
|
||||
if((!(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/observer/dead) || istype(usr, /mob/living/silicon)) && !forceshow) || forcestars)
|
||||
data = "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)][stamps]</BODY></HTML>"
|
||||
if(view)
|
||||
usr << browse(data, "window=[name]")
|
||||
onclose(usr, "[name]")
|
||||
/obj/item/weapon/paper/proc/show_content(var/mob/user, var/forceshow=0)
|
||||
if(!(istype(user, /mob/living/carbon/human) || istype(user, /mob/observer/dead) || istype(user, /mob/living/silicon)) && !forceshow)
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)][stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(user, "[name]")
|
||||
else
|
||||
data = "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[infolinks ? info_links : info][stamps]</BODY></HTML>"
|
||||
if(view)
|
||||
usr << browse(data, "window=[name]")
|
||||
onclose(usr, "[name]")
|
||||
return data
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info][stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(user, "[name]")
|
||||
|
||||
/obj/item/weapon/paper/verb/rename()
|
||||
set name = "Rename paper"
|
||||
@@ -141,9 +132,11 @@
|
||||
else //cyborg or AI not seeing through a camera
|
||||
dist = get_dist(src, user)
|
||||
if(dist < 2)
|
||||
show_content(user, forceshow = 1)
|
||||
usr << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info][stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(usr, "[name]")
|
||||
else
|
||||
show_content(user, forcestars = 1)
|
||||
usr << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)][stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(usr, "[name]")
|
||||
return
|
||||
|
||||
/obj/item/weapon/paper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
|
||||
|
||||
@@ -122,7 +122,10 @@
|
||||
|
||||
if(istype(pages[page], /obj/item/weapon/paper))
|
||||
var/obj/item/weapon/paper/P = W
|
||||
dat += P.show_content(usr, view = 0)
|
||||
if(!(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/observer/dead) || istype(usr, /mob/living/silicon)))
|
||||
dat+= "<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[stars(P.info)][P.stamps]</BODY></HTML>"
|
||||
else
|
||||
dat+= "<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[P.info][P.stamps]</BODY></HTML>"
|
||||
user << browse(dat, "window=[name]")
|
||||
else if(istype(pages[page], /obj/item/weapon/photo))
|
||||
var/obj/item/weapon/photo/P = W
|
||||
|
||||
@@ -726,22 +726,26 @@
|
||||
if(wiresexposed && !istype(user, /mob/living/silicon/ai))
|
||||
wires.Interact(user)
|
||||
|
||||
return tg_ui_interact(user)
|
||||
return ui_interact(user)
|
||||
|
||||
|
||||
/obj/machinery/power/apc/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["locked"] = (locked && !emagged) ? 1 : 0
|
||||
data["isOperating"] = operating
|
||||
data["externalPower"] = main_status
|
||||
data["powerCellStatus"] = cell ? cell.percent() : null
|
||||
data["chargeMode"] = chargemode
|
||||
data["chargingStatus"] = charging
|
||||
data["totalLoad"] = round(lastused_total)
|
||||
data["totalCharging"] = round(lastused_charging)
|
||||
data["coverLocked"] = coverlocked
|
||||
data["siliconUser"] = issilicon(user) || isobserver(user) //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate.
|
||||
data["powerChannels"] = list(
|
||||
/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(!user)
|
||||
return
|
||||
|
||||
var/list/data = list(
|
||||
"locked" = (locked && !emagged) ? 1 : 0,
|
||||
"isOperating" = operating,
|
||||
"externalPower" = main_status,
|
||||
"powerCellStatus" = cell ? cell.percent() : null,
|
||||
"chargeMode" = chargemode,
|
||||
"chargingStatus" = charging,
|
||||
"totalLoad" = round(lastused_total),
|
||||
"totalCharging" = round(lastused_charging),
|
||||
"coverLocked" = coverlocked,
|
||||
"siliconUser" = issilicon(user) || isobserver(user), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate.
|
||||
|
||||
"powerChannels" = list(
|
||||
list(
|
||||
"title" = "Equipment",
|
||||
"powerLoad" = lastused_equip,
|
||||
@@ -773,14 +777,20 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/power/apc/tg_ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
ui = tgui_process.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "apc", "[area.name] - APC" , 520, issilicon(user) ? 535 : 460, master_ui, state)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 520, data["siliconUser"] ? 465 : 440)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/power/apc/proc/report()
|
||||
return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
|
||||
@@ -847,59 +857,66 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/power/apc/ui_act(action, params)
|
||||
/obj/machinery/power/apc/Topic(href, href_list)
|
||||
if(..())
|
||||
return TRUE
|
||||
return 1
|
||||
|
||||
if(!can_use(usr, 1))
|
||||
return TRUE
|
||||
return 1
|
||||
|
||||
if(locked && !issilicon(usr) )
|
||||
if(isobserver(usr) )
|
||||
var/mob/observer/dead/O = usr //Added to allow admin nanoUI interactions.
|
||||
if(!O.can_admin_interact() ) //NanoUI /should/ make this not needed, but better safe than sorry.
|
||||
usr << "Try as you might, your ghostly fingers can't press the buttons."
|
||||
return TRUE
|
||||
return 1
|
||||
else
|
||||
usr << "You must unlock the panel to use this!"
|
||||
return TRUE
|
||||
return 1
|
||||
|
||||
switch(action)
|
||||
if("cover")
|
||||
coverlocked = !coverlocked
|
||||
if (href_list["lock"])
|
||||
coverlocked = !coverlocked
|
||||
|
||||
if("breaker")
|
||||
toggle_breaker()
|
||||
else if (href_list["breaker"])
|
||||
toggle_breaker()
|
||||
|
||||
if("charge")
|
||||
chargemode = !chargemode
|
||||
if(!chargemode)
|
||||
charging = 0
|
||||
else if (href_list["cmode"])
|
||||
chargemode = !chargemode
|
||||
if(!chargemode)
|
||||
charging = 0
|
||||
update_icon()
|
||||
|
||||
if("channel")
|
||||
if(params["eqp"])
|
||||
equipment = setsubsystem(text2num(params["eqp"]))
|
||||
update()
|
||||
else if(params["lgt"])
|
||||
lighting = setsubsystem(text2num(params["lgt"]))
|
||||
update()
|
||||
else if(params["env"])
|
||||
environ = setsubsystem(text2num(params["env"]))
|
||||
update()
|
||||
else if (href_list["eqp"])
|
||||
var/val = text2num(href_list["eqp"])
|
||||
equipment = setsubsystem(val)
|
||||
update_icon()
|
||||
update()
|
||||
|
||||
if("overload")
|
||||
if(istype(usr, /mob/living/silicon))
|
||||
src.overload_lighting()
|
||||
else if (href_list["lgt"])
|
||||
var/val = text2num(href_list["lgt"])
|
||||
lighting = setsubsystem(val)
|
||||
update_icon()
|
||||
update()
|
||||
|
||||
if("lock")
|
||||
if(istype(usr, /mob/living/silicon))
|
||||
if(emagged || (stat & (BROKEN|MAINT)))
|
||||
usr << "The APC does not respond to the command."
|
||||
else
|
||||
locked = !locked
|
||||
else if (href_list["env"])
|
||||
var/val = text2num(href_list["env"])
|
||||
environ = setsubsystem(val)
|
||||
update_icon()
|
||||
update()
|
||||
|
||||
src.update_icon()
|
||||
return TRUE
|
||||
else if (href_list["overload"])
|
||||
if(istype(usr, /mob/living/silicon))
|
||||
src.overload_lighting()
|
||||
|
||||
else if (href_list["toggleaccess"])
|
||||
if(istype(usr, /mob/living/silicon))
|
||||
if(emagged || (stat & (BROKEN|MAINT)))
|
||||
usr << "The APC does not respond to the command."
|
||||
else
|
||||
locked = !locked
|
||||
update_icon()
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/power/apc/proc/toggle_breaker()
|
||||
operating = !operating
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/**
|
||||
* tgui external
|
||||
*
|
||||
* Contains all external tgui declarations.
|
||||
**/
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Used to open and update UIs.
|
||||
* If this proc is not implemented properly, the UI will not update correctly.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional ui_key string The ui_key of the UI.
|
||||
* optional ui datum/tgui The UI to be updated, if it exists.
|
||||
* optional force_open bool If the UI should be re-opened instead of updated.
|
||||
* optional master_ui datum/tgui The parent UI.
|
||||
* optional state datum/ui_state The state used to determine status.
|
||||
**/
|
||||
/datum/proc/tg_ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = tg_default_state)
|
||||
return -1 // Not implemented.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Data to be sent to the UI.
|
||||
* This must be implemented for a UI to work.
|
||||
*
|
||||
* required user mob The mob interacting with the UI.
|
||||
*
|
||||
* return list Data to be sent to the UI.
|
||||
**/
|
||||
/datum/proc/ui_data(mob/user, ui_key = "main")
|
||||
return list() // Not implemented.
|
||||
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Called on a UI when the UI receieves a href.
|
||||
* Think of this as Topic().
|
||||
*
|
||||
* required action string The action/button that has been invoked by the user.
|
||||
* required params list A list of parameters attached to the button.
|
||||
*
|
||||
* return bool If the UI should be updated or not.
|
||||
**/
|
||||
/datum/proc/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(!ui || ui.status != UI_INTERACTIVE)
|
||||
return 1 // If UI is not interactive or usr calling Topic is not the UI user, bail.
|
||||
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* The UI's host object (usually src_object).
|
||||
* This allows modules/datums to have the UI attached to them,
|
||||
* and be a part of another object.
|
||||
**/
|
||||
/datum/proc/ui_host()
|
||||
return src // Default src.
|
||||
|
||||
/**
|
||||
* global
|
||||
*
|
||||
* Used to track the current screen.
|
||||
**/
|
||||
/datum/var/ui_screen = "home"
|
||||
|
||||
/**
|
||||
* global
|
||||
*
|
||||
* Used to track UIs for a mob.
|
||||
**/
|
||||
/mob/var/list/tg_open_uis = list()
|
||||
|
||||
/**
|
||||
* verb
|
||||
*
|
||||
* Called by UIs when they are closed.
|
||||
* Must be a verb so winset() can call it.
|
||||
*
|
||||
* required uiref ref The UI that was closed.
|
||||
**/
|
||||
/client/verb/uiclose(ref as text)
|
||||
// Name the verb, and hide it from the user panel.
|
||||
set name = "uiclose"
|
||||
set hidden = 1
|
||||
|
||||
// Get the UI based on the ref.
|
||||
var/datum/tgui/ui = locate(ref)
|
||||
|
||||
// If we found the UI, close it.
|
||||
if(istype(ui))
|
||||
ui.close()
|
||||
// Unset machine just to be sure.
|
||||
if(src && src.mob)
|
||||
src.mob.unset_machine()
|
||||
@@ -1,223 +0,0 @@
|
||||
/**
|
||||
* tgui process
|
||||
*
|
||||
* Contains all tgui state and process code.
|
||||
**/
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Get a open UI given a user, src_object, and ui_key and try to update it with data.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required src_object datum The object/datum which owns the UI.
|
||||
* required ui_key string The ui_key of the UI.
|
||||
* optional ui datum/tgui The UI to be updated, if it exists.
|
||||
* optional force_open bool If the UI should be re-opened instead of updated.
|
||||
*
|
||||
* return datum/tgui The found UI.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/try_update_ui(mob/user, datum/src_object, ui_key, datum/tgui/ui, force_open = 0)
|
||||
if(isnull(ui)) // No UI was passed, so look for one.
|
||||
ui = get_open_ui(user, src_object, ui_key)
|
||||
|
||||
if(!isnull(ui))
|
||||
var/data = src_object.ui_data(user) // Get data from the src_object.
|
||||
if(!force_open) // UI is already open; update it.
|
||||
ui.push_data(data)
|
||||
else // Re-open it anyways.
|
||||
ui.reinitialize(null, data)
|
||||
return ui // We found the UI, return it.
|
||||
else
|
||||
return null // We couldn't find a UI.
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Get a open UI given a user, src_object, and ui_key.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required src_object datum The object/datum which owns the UI.
|
||||
* required ui_key string The ui_key of the UI.
|
||||
*
|
||||
* return datum/tgui The found UI.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/get_open_ui(mob/user, datum/src_object, ui_key)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if(isnull(tg_open_uis[src_object_key]) || !istype(tg_open_uis[src_object_key], /list))
|
||||
return null // No UIs open.
|
||||
else if(isnull(tg_open_uis[src_object_key][ui_key]) || !istype(tg_open_uis[src_object_key][ui_key], /list))
|
||||
return null // No UIs open for this object.
|
||||
|
||||
for(var/datum/tgui/ui in tg_open_uis[src_object_key][ui_key]) // Find UIs for this object.
|
||||
if(ui.user == user) // Make sure we have the right user
|
||||
return ui
|
||||
|
||||
return null // Couldn't find a UI!
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Update all UIs attached to src_object.
|
||||
*
|
||||
* required src_object datum The object/datum which owns the UIs.
|
||||
*
|
||||
* return int The number of UIs updated.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/update_uis(datum/src_object)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if(isnull(tg_open_uis[src_object_key]) || !istype(tg_open_uis[src_object_key], /list))
|
||||
return 0 // Couldn't find any UIs for this object.
|
||||
|
||||
var/update_count = 0
|
||||
for(var/ui_key in tg_open_uis[src_object_key])
|
||||
for(var/datum/tgui/ui in tg_open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host()) // Check the UI is valid.
|
||||
ui.process(force = 1) // Update the UI.
|
||||
update_count++ // Count each UI we update.
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Close all UIs attached to src_object.
|
||||
*
|
||||
* required src_object datum The object/datum which owns the UIs.
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/close_uis(datum/src_object)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if(isnull(tg_open_uis[src_object_key]) || !istype(tg_open_uis[src_object_key], /list))
|
||||
return 0 // Couldn't find any UIs for this object.
|
||||
|
||||
var/close_count = 0
|
||||
for(var/ui_key in tg_open_uis[src_object_key])
|
||||
for(var/datum/tgui/ui in tg_open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host()) // Check the UI is valid.
|
||||
ui.close() // Close the UI.
|
||||
close_count++ // Count each UI we close.
|
||||
return close_count
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Update all UIs belonging to a user.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional src_object datum If provided, only update UIs belonging this src_object.
|
||||
* optional ui_key string If provided, only update UIs with this UI key.
|
||||
*
|
||||
* return int The number of UIs updated.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/update_user_uis(mob/user, datum/src_object = null, ui_key = null)
|
||||
if(isnull(user.tg_open_uis) || !istype(user.tg_open_uis, /list) || tg_open_uis.len == 0)
|
||||
return 0 // Couldn't find any UIs for this user.
|
||||
|
||||
var/update_count = 0
|
||||
for(var/datum/tgui/ui in user.tg_open_uis)
|
||||
if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.process(force = 1) // Update the UI.
|
||||
update_count++ // Count each UI we upadte.
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Close all UIs belonging to a user.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional src_object datum If provided, only close UIs belonging this src_object.
|
||||
* optional ui_key string If provided, only close UIs with this UI key.
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/close_user_uis(mob/user, datum/src_object = null, ui_key = null)
|
||||
if(isnull(user.tg_open_uis) || !istype(user.tg_open_uis, /list) || tg_open_uis.len == 0)
|
||||
return 0 // Couldn't find any UIs for this user.
|
||||
|
||||
var/close_count = 0
|
||||
for(var/datum/tgui/ui in user.tg_open_uis)
|
||||
if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.close() // Close the UI.
|
||||
close_count++ // Count each UI we close.
|
||||
return close_count
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Add a UI to the list of open UIs.
|
||||
*
|
||||
* required ui datum/tgui The UI to be added.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/on_open(datum/tgui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if(isnull(tg_open_uis[src_object_key]) || !istype(tg_open_uis[src_object_key], /list))
|
||||
tg_open_uis[src_object_key] = list(ui.ui_key = list()) // Make a list for the ui_key and src_object.
|
||||
else if(isnull(tg_open_uis[src_object_key][ui.ui_key]) || !istype(tg_open_uis[src_object_key][ui.ui_key], /list))
|
||||
tg_open_uis[src_object_key][ui.ui_key] = list() // Make a list for the ui_key.
|
||||
|
||||
// Append the UI to all the lists.
|
||||
ui.user.tg_open_uis |= ui
|
||||
var/list/uis = tg_open_uis[src_object_key][ui.ui_key]
|
||||
uis |= ui
|
||||
processing_uis |= ui
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Remove a UI from the list of open UIs.
|
||||
*
|
||||
* required ui datum/tgui The UI to be removed.
|
||||
*
|
||||
* return bool If the UI was removed or not.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/on_close(datum/tgui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if(isnull(tg_open_uis[src_object_key]) || !istype(tg_open_uis[src_object_key], /list))
|
||||
return 0 // It wasn't open.
|
||||
else if(isnull(tg_open_uis[src_object_key][ui.ui_key]) || !istype(tg_open_uis[src_object_key][ui.ui_key], /list))
|
||||
return 0 // It wasn't open.
|
||||
|
||||
processing_uis.Remove(ui) // Remove it from the list of processing UIs.
|
||||
if(ui.user) // If the user exists, remove it from them too.
|
||||
ui.user.tg_open_uis.Remove(ui)
|
||||
var/list/uis = tg_open_uis[src_object_key][ui.ui_key] // Remove it from the list of open UIs.
|
||||
uis.Remove(ui)
|
||||
return 1 // Let the caller know we did it.
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Handle client logout, by closing all their UIs.
|
||||
*
|
||||
* required user mob The mob which logged out.
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/on_logout(mob/user)
|
||||
return close_user_uis(user)
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Handle clients switching mobs, by transfering their UIs.
|
||||
*
|
||||
* required user source The client's original mob.
|
||||
* required user target The client's new mob.
|
||||
*
|
||||
* return bool If the UIs were transferred.
|
||||
**/
|
||||
/datum/controller/process/tgui/proc/on_transfer(mob/source, mob/target)
|
||||
if(!source || isnull(source.tg_open_uis) || !istype(source.tg_open_uis, /list) || tg_open_uis.len == 0)
|
||||
return 0 // The old mob had no open UIs.
|
||||
|
||||
if(isnull(target.tg_open_uis) || !istype(target.tg_open_uis, /list))
|
||||
target.tg_open_uis = list() // Create a list for the new mob if needed.
|
||||
|
||||
for(var/datum/tgui/ui in source.tg_open_uis)
|
||||
ui.user = target // Inform the UIs of their new owner.
|
||||
target.tg_open_uis.Add(ui) // Transfer all the UIs.
|
||||
|
||||
source.tg_open_uis.Cut() // Clear the old list.
|
||||
return 1 // Let the caller know we did it.
|
||||
@@ -1,110 +0,0 @@
|
||||
/**
|
||||
* tgui states
|
||||
*
|
||||
* Base state and helpers for states. Just does some sanity checks, implement a state for in-depth checks.
|
||||
**/
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Checks the UI state for a mob.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required state datum/ui_state The state to check.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
**/
|
||||
/datum/proc/ui_status(mob/user, datum/ui_state/state)
|
||||
var/datum/src_object = ui_host()
|
||||
if(src_object != src)
|
||||
return src_object.ui_status(user, state)
|
||||
|
||||
if(isobserver(user)) // Special-case ghosts.
|
||||
if(user.can_admin_interact())
|
||||
return UI_INTERACTIVE // If they turn it on, admins can interact.
|
||||
if(get_dist(src_object, src) < user.client.view)
|
||||
return UI_UPDATE // Regular ghosts can only view.
|
||||
return UI_CLOSE // To keep too many UIs from being opened.
|
||||
return state.can_use_topic(src_object, user) // Check if the state allows interaction.
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Checks if a user can use src_object's UI, and returns the state.
|
||||
* Can call a mob proc, which allows overrides for each mob.
|
||||
*
|
||||
* required src_object datum The object/datum which owns the UI.
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
**/
|
||||
/datum/ui_state/proc/can_use_topic(src_object, mob/user)
|
||||
return UI_CLOSE // Don't allow interaction by default.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Standard interaction/sanity checks. Different mob types may have overrides.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
**/
|
||||
/mob/proc/shared_ui_interaction(src_object)
|
||||
if(!client) // Close UIs if mindless.
|
||||
return UI_CLOSE
|
||||
else if(stat) // Disable UIs if unconcious.
|
||||
return UI_DISABLED
|
||||
else if(incapacitated() || lying) // Update UIs if incapicitated but concious.
|
||||
return UI_UPDATE
|
||||
return UI_INTERACTIVE
|
||||
|
||||
/mob/living/silicon/ai/shared_ui_interaction(src_object)
|
||||
if(lacks_power()) // Disable UIs if the AI is unpowered.
|
||||
return UI_DISABLED
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/shared_ui_interaction(src_object)
|
||||
if(cell.charge <= 0 || lockcharge) // Disable UIs if the Borg is unpowered or locked.
|
||||
return UI_DISABLED
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Check the distance for a living mob.
|
||||
* Really only used for checks outside the context of a mob.
|
||||
* Otherwise, use shared_living_ui_distance().
|
||||
*
|
||||
* required src_object The object which owns the UI.
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
**/
|
||||
/atom/proc/contents_ui_distance(src_object, mob/living/user)
|
||||
return user.shared_living_ui_distance(src_object) // Just call this mob's check.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Distance versus interaction check.
|
||||
*
|
||||
* required src_object atom/movable The object which owns the UI.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
**/
|
||||
/mob/living/proc/shared_living_ui_distance(atom/movable/src_object)
|
||||
if(!(src_object in view(src))) // If the object is obscured, close it.
|
||||
return UI_CLOSE
|
||||
|
||||
var/dist = get_dist(src_object, src)
|
||||
if(dist <= 1) // Open and interact if 1-0 tiles away.
|
||||
return UI_INTERACTIVE
|
||||
else if(dist <= 2) // View only if 2-3 tiles away.
|
||||
return UI_UPDATE
|
||||
else if(dist <= 5) // Disable if 5 tiles away.
|
||||
return UI_DISABLED
|
||||
return UI_CLOSE // Otherwise, we got nothing.
|
||||
|
||||
/mob/living/carbon/human/shared_living_ui_distance(atom/movable/src_object)
|
||||
if((TK in mutations))
|
||||
return UI_INTERACTIVE
|
||||
return ..()
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* tgui state: admin_state
|
||||
*
|
||||
* Checks that the user is an admin, end-of-story.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/admin_state/tg_admin_state = new()
|
||||
|
||||
/datum/ui_state/admin_state/can_use_topic(src_object, mob/user)
|
||||
if(check_rights(R_ADMIN, 0, user))
|
||||
return UI_INTERACTIVE
|
||||
return UI_CLOSE
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* tgui state: conscious_state
|
||||
*
|
||||
* Only checks if the user is conscious.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/conscious_state/tg_conscious_state = new()
|
||||
|
||||
/datum/ui_state/conscious_state/can_use_topic(src_object, mob/user)
|
||||
if(user.stat == CONSCIOUS)
|
||||
return UI_INTERACTIVE
|
||||
return UI_CLOSE
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* tgui state: contained_state
|
||||
*
|
||||
* Checks that the user is inside the src_object.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/contained_state/tg_contained_state = new()
|
||||
|
||||
/datum/ui_state/contained_state/can_use_topic(atom/src_object, mob/user)
|
||||
if(!src_object.contains(user))
|
||||
return UI_CLOSE
|
||||
return user.shared_ui_interaction(src_object)
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* tgui state: deep_inventory_state
|
||||
*
|
||||
* Checks that the src_object is in the user's deep (backpack, box, toolbox, etc) inventory.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/deep_inventory_state/tg_deep_inventory_state = new()
|
||||
|
||||
/datum/ui_state/deep_inventory_state/can_use_topic(src_object, mob/user)
|
||||
if(!user.contains(src_object))
|
||||
return UI_CLOSE
|
||||
return user.shared_ui_interaction(src_object)
|
||||
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
* tgui state: default_state
|
||||
*
|
||||
* Checks a number of things -- mostly physical distance for humans and view for robots.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/default/tg_default_state = new()
|
||||
|
||||
/datum/ui_state/default/can_use_topic(src_object, mob/user)
|
||||
return user.tg_default_can_use_topic(src_object) // Call the individual mob-overriden procs.
|
||||
|
||||
/mob/proc/tg_default_can_use_topic(src_object)
|
||||
return UI_CLOSE // Don't allow interaction by default.
|
||||
|
||||
/mob/living/tg_default_can_use_topic(src_object)
|
||||
. = shared_ui_interaction(src_object)
|
||||
if(. > UI_CLOSE && loc)
|
||||
. = min(., loc.contents_ui_distance(src_object, src)) // Check the distance...
|
||||
if(. == UI_INTERACTIVE) // Non-human living mobs can only look, not touch.
|
||||
return UI_UPDATE
|
||||
|
||||
/mob/living/carbon/human/tg_default_can_use_topic(src_object)
|
||||
. = shared_ui_interaction(src_object)
|
||||
if(. > UI_CLOSE)
|
||||
. = min(., shared_living_ui_distance(src_object)) // Check the distance...
|
||||
// Derp a bit if we have brain loss.
|
||||
if(prob(getBrainLoss()))
|
||||
return UI_UPDATE
|
||||
|
||||
/mob/living/silicon/robot/tg_default_can_use_topic(src_object)
|
||||
. = shared_ui_interaction(src_object)
|
||||
if(. <= UI_DISABLED)
|
||||
return
|
||||
|
||||
// Robots can interact with anything they can see.
|
||||
if(get_dist(src, src_object) <= client.view)
|
||||
return UI_INTERACTIVE
|
||||
return UI_DISABLED // Otherwise they can keep the UI open.
|
||||
|
||||
/mob/living/silicon/ai/tg_default_can_use_topic(src_object)
|
||||
. = shared_ui_interaction(src_object)
|
||||
if(. < UI_INTERACTIVE)
|
||||
return
|
||||
|
||||
// The AI can interact with anything it can see nearby, or with cameras.
|
||||
if((get_dist(src, src_object) <= client.view) || cameranet.checkTurfVis(get_turf_pixel(src_object)))
|
||||
return UI_INTERACTIVE
|
||||
return UI_CLOSE
|
||||
|
||||
/mob/living/silicon/pai/tg_default_can_use_topic(src_object)
|
||||
// pAIs can only use themselves and the owner's radio.
|
||||
if((src_object == src || src_object == radio) && !stat)
|
||||
return UI_INTERACTIVE
|
||||
else
|
||||
return ..()
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* tgui state: hands_state
|
||||
*
|
||||
* Checks that the src_object is in the user's hands.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/hands_state/tg_hands_state = new()
|
||||
|
||||
/datum/ui_state/hands_state/can_use_topic(src_object, mob/user)
|
||||
. = user.shared_ui_interaction(src_object)
|
||||
if(. > UI_CLOSE)
|
||||
return min(., user.hands_can_use_topic(src_object))
|
||||
|
||||
/mob/proc/hands_can_use_topic(src_object)
|
||||
return UI_CLOSE
|
||||
|
||||
/mob/living/hands_can_use_topic(src_object)
|
||||
if(src_object in get_both_hands(src))
|
||||
return UI_INTERACTIVE
|
||||
return UI_CLOSE
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* tgui state: inventory_state
|
||||
*
|
||||
* Checks that the src_object is in the user's top-level (hand, ear, pocket, belt, etc) inventory.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/inventory_state/tg_inventory_state = new()
|
||||
|
||||
/datum/ui_state/inventory_state/can_use_topic(src_object, mob/user)
|
||||
if(!(src_object in user))
|
||||
return UI_CLOSE
|
||||
return user.shared_ui_interaction(src_object)
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* tgui state: notcontained_state
|
||||
*
|
||||
* Checks that the user is not inside src_object, and then makes the default checks.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/notcontained_state/tg_notcontained_state = new()
|
||||
|
||||
/datum/ui_state/notcontained_state/can_use_topic(atom/src_object, mob/user)
|
||||
. = user.shared_ui_interaction(src_object)
|
||||
if(. > UI_CLOSE)
|
||||
return min(., user.notcontained_can_use_topic(src_object))
|
||||
|
||||
/mob/proc/notcontained_can_use_topic(src_object)
|
||||
return UI_CLOSE
|
||||
|
||||
/mob/living/notcontained_can_use_topic(atom/src_object)
|
||||
if(src_object.contains(src))
|
||||
return UI_CLOSE // Close if we're inside it.
|
||||
return tg_default_can_use_topic(src_object)
|
||||
|
||||
/mob/living/silicon/notcontained_can_use_topic(src_object)
|
||||
return tg_default_can_use_topic(src_object) // Silicons use default bevhavior.
|
||||
|
||||
/mob/living/simple_animal/drone/notcontained_can_use_topic(src_object)
|
||||
return tg_default_can_use_topic(src_object) // Drones use default bevhavior.
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* tgui state: physical_state
|
||||
*
|
||||
* Short-circuits the default state to only check physical distance.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/physical/tg_physical_state = new()
|
||||
|
||||
/datum/ui_state/physical/can_use_topic(src_object, mob/user)
|
||||
. = user.shared_ui_interaction(src_object)
|
||||
if(. > UI_CLOSE)
|
||||
return min(., user.physical_can_use_topic(src_object))
|
||||
|
||||
/mob/proc/physical_can_use_topic(src_object)
|
||||
return UI_CLOSE
|
||||
|
||||
/mob/living/physical_can_use_topic(src_object)
|
||||
return shared_living_ui_distance(src_object)
|
||||
|
||||
/mob/living/silicon/physical_can_use_topic(src_object)
|
||||
return max(UI_UPDATE, shared_living_ui_distance(src_object)) // Silicons can always see.
|
||||
|
||||
/mob/living/silicon/ai/physical_can_use_topic(src_object)
|
||||
return UI_UPDATE // AIs are not physical.
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* tgui state: self_state
|
||||
*
|
||||
* Only checks that the user and src_object are the same.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/self_state/tg_self_state = new()
|
||||
|
||||
/datum/ui_state/self_state/can_use_topic(src_object, mob/user)
|
||||
if(src_object != user)
|
||||
return UI_CLOSE
|
||||
return user.shared_ui_interaction(src_object)
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* tgui state: z_state
|
||||
*
|
||||
* Only checks that the Z-level of the user and src_object are the same.
|
||||
**/
|
||||
|
||||
/var/global/datum/ui_state/z_state/tg_z_state = new()
|
||||
|
||||
/datum/ui_state/z_state/can_use_topic(src_object, mob/user)
|
||||
var/turf/turf_obj = get_turf(src_object)
|
||||
var/turf/turf_usr = get_turf(user)
|
||||
if(turf_obj && turf_usr && turf_obj.z == turf_usr.z)
|
||||
return UI_INTERACTIVE
|
||||
return UI_CLOSE
|
||||
@@ -1,369 +0,0 @@
|
||||
/**
|
||||
* tgui
|
||||
*
|
||||
* /tg/station user interface library
|
||||
**/
|
||||
|
||||
/**
|
||||
* tgui datum (represents a UI).
|
||||
**/
|
||||
/datum/tgui
|
||||
var/mob/user // The mob who opened/is using the UI.
|
||||
var/datum/src_object // The object which owns the UI.
|
||||
var/title // The title of te UI.
|
||||
var/ui_key // The ui_key of the UI. This allows multiple UIs for one src_object.
|
||||
var/window_id // The window_id for browse() and onclose().
|
||||
var/width = 0 // The window width.
|
||||
var/height = 0 // The window height
|
||||
var/window_options = list( // Extra options to winset().
|
||||
"focus" = FALSE,
|
||||
"titlebar" = TRUE,
|
||||
"can_resize" = TRUE,
|
||||
"can_minimize" = TRUE,
|
||||
"can_maximize" = FALSE,
|
||||
"can_close" = TRUE,
|
||||
"auto_format" = FALSE
|
||||
)
|
||||
var/style = "nanotrasen" // The style to be used for this UI.
|
||||
var/interface // The interface (template) to be used for this UI.
|
||||
var/autoupdate = TRUE // Update the UI every MC tick.
|
||||
var/initialized = FALSE // If the UI has been initialized yet.
|
||||
var/list/initial_data // The data (and datastructure) used to initialize the UI.
|
||||
var/status = UI_INTERACTIVE // The status/visibility of the UI.
|
||||
var/datum/ui_state/state = null // Topic state used to determine status/interactability.
|
||||
var/datum/tgui/master_ui // The parent UI.
|
||||
var/list/datum/tgui/children = list() // Children of this UI.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Create a new UI.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required src_object datum The object or datum which owns the UI.
|
||||
* required ui_key string The ui_key of the UI.
|
||||
* required interface string The interface used to render the UI.
|
||||
* optional title string The title of the UI.
|
||||
* optional width int The window width.
|
||||
* optional height int The window height.
|
||||
* optional master_ui datum/tgui The parent UI.
|
||||
* optional state datum/ui_state The state used to determine status.
|
||||
*
|
||||
* return datum/tgui The requested UI.
|
||||
**/
|
||||
/datum/tgui/New(mob/user, datum/src_object, ui_key, interface, title, width = 0, height = 0, datum/tgui/master_ui = null, datum/ui_state/state = tg_default_state)
|
||||
src.user = user
|
||||
src.src_object = src_object
|
||||
src.ui_key = ui_key
|
||||
src.window_id = "\ref[src_object]-[ui_key]"
|
||||
|
||||
set_interface(interface)
|
||||
|
||||
if(title)
|
||||
src.title = sanitize(title)
|
||||
if(width)
|
||||
src.width = width
|
||||
if(height)
|
||||
src.height = height
|
||||
|
||||
src.master_ui = master_ui
|
||||
if(master_ui)
|
||||
master_ui.children += src
|
||||
src.state = state
|
||||
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/tgui)
|
||||
assets.send(user)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Open this UI (and initialize it with data).
|
||||
**/
|
||||
/datum/tgui/proc/open()
|
||||
if(!user.client)
|
||||
return // Bail if there is no client.
|
||||
|
||||
update_status(push = 0) // Update the window status.
|
||||
if(status < UI_UPDATE)
|
||||
return // Bail if we're not supposed to open.
|
||||
|
||||
if(!initial_data)
|
||||
set_initial_data(src_object.ui_data(user)) // Get the UI data.
|
||||
|
||||
var/window_size = ""
|
||||
if(width && height) // If we have a width and height, use them.
|
||||
window_size = "size=[width]x[height];"
|
||||
|
||||
var/debugable = check_rights(R_DEBUG, 0, user)
|
||||
user << browse(get_html(debugable), "window=[window_id];[window_size][list2params(window_options)]") // Open the window.
|
||||
winset(user, window_id, "on-close=\"uiclose \ref[src]\"") // Instruct the client to signal UI when the window is closed.
|
||||
tgui_process.on_open(src)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Reinitialize the UI.
|
||||
* (Possibly with a new interface and/or data).
|
||||
*
|
||||
* optional template string The name of the new interface.
|
||||
* optional data list The new initial data.
|
||||
**/
|
||||
/datum/tgui/proc/reinitialize(interface, list/data)
|
||||
if(interface)
|
||||
set_interface(interface) // Set a new interface.
|
||||
if(data)
|
||||
set_initial_data(data) // Replace the initial_data.
|
||||
open()
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Close the UI, and all its children.
|
||||
**/
|
||||
/datum/tgui/proc/close()
|
||||
user << browse(null, "window=[window_id]") // Close the window.
|
||||
tgui_process.on_close(src)
|
||||
for(var/datum/tgui/child in children) // Loop through and close all children.
|
||||
child.close()
|
||||
children.Cut()
|
||||
state = null
|
||||
master_ui = null
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Sets the browse() window options for this UI.
|
||||
*
|
||||
* required window_options list The window options to set.
|
||||
**/
|
||||
/datum/tgui/proc/set_window_options(list/window_options)
|
||||
src.window_options = window_options
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Set the style for this UI.
|
||||
*
|
||||
* required style string The new UI style.
|
||||
**/
|
||||
/datum/tgui/proc/set_style(style)
|
||||
src.style = lowertext(style)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Set the interface (template) for this UI.
|
||||
*
|
||||
* required interface string The new UI interface.
|
||||
**/
|
||||
/datum/tgui/proc/set_interface(interface)
|
||||
src.interface = lowertext(interface)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Enable/disable auto-updating of the UI.
|
||||
*
|
||||
* required state bool Enable/disable auto-updating.
|
||||
**/
|
||||
/datum/tgui/proc/set_autoupdate(state = 1)
|
||||
autoupdate = state
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Set the data to initialize the UI with.
|
||||
* The datastructure cannot be changed by subsequent updates.
|
||||
*
|
||||
* optional data list The data/datastructure to initialize the UI with.
|
||||
**/
|
||||
/datum/tgui/proc/set_initial_data(list/data)
|
||||
initial_data = data
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Generate HTML for this UI.
|
||||
*
|
||||
* optional bool inline If the JSON should be inlined into the HTML (for debugging).
|
||||
*
|
||||
* return string UI HTML output.
|
||||
**/
|
||||
/datum/tgui/proc/get_html(var/inline)
|
||||
var/html
|
||||
// Poplate HTML with JSON if we're supposed to inline.
|
||||
if(inline)
|
||||
html = replacetextEx(tgui_process.basehtml, "{}", get_json(initial_data))
|
||||
else
|
||||
html = tgui_process.basehtml
|
||||
html = replacetextEx(html, "\[ref]", "\ref[src]")
|
||||
html = replacetextEx(html, "\[style]", style)
|
||||
return html
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Get the config data/datastructure to initialize the UI with.
|
||||
*
|
||||
* return list The config data.
|
||||
**/
|
||||
/datum/tgui/proc/get_config_data()
|
||||
var/list/config_data = list(
|
||||
"title" = title,
|
||||
"status" = status,
|
||||
"screen" = src_object.ui_screen,
|
||||
"style" = style,
|
||||
"interface" = interface,
|
||||
"fancy" = user.is_preference_enabled(/datum/client_preference/tgui_style),
|
||||
"locked" = user.is_preference_enabled(/datum/client_preference/tgui_monitor),
|
||||
"window" = window_id,
|
||||
"ref" = "\ref[src]",
|
||||
"user" = list(
|
||||
"name" = user.name,
|
||||
"ref" = "\ref[user]"
|
||||
),
|
||||
"srcObject" = list(
|
||||
"name" = "[src_object]",
|
||||
"ref" = "\ref[src_object]"
|
||||
)
|
||||
)
|
||||
return config_data
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Package the data to send to the UI, as JSON.
|
||||
* This includes the UI data and config_data.
|
||||
*
|
||||
* return string The packaged JSON.
|
||||
**/
|
||||
/datum/tgui/proc/get_json(list/data)
|
||||
var/list/json_data = list()
|
||||
|
||||
json_data["config"] = get_config_data()
|
||||
if(!isnull(data))
|
||||
json_data["data"] = data
|
||||
|
||||
// Generate the JSON.
|
||||
var/json = json_encode(json_data)
|
||||
// Strip #255/improper.
|
||||
json = replacetext(json, "\proper", "")
|
||||
json = replacetext(json, "\improper", "")
|
||||
return json
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Handle clicks from the UI.
|
||||
* Call the src_object's ui_act() if status is UI_INTERACTIVE.
|
||||
* If the src_object's ui_act() returns 1, update all UIs attacked to it.
|
||||
**/
|
||||
/datum/tgui/Topic(href, href_list)
|
||||
if(user != usr)
|
||||
return // Something is not right here.
|
||||
|
||||
var/action = href_list["action"]
|
||||
var/params = href_list; params -= "action"
|
||||
|
||||
switch(action)
|
||||
if("tgui:initialize")
|
||||
user << output(url_encode(get_json(initial_data)), "[window_id].browser:initialize")
|
||||
initialized = TRUE
|
||||
if("tgui:view")
|
||||
if(params["screen"])
|
||||
src_object.ui_screen = params["screen"]
|
||||
tgui_process.update_uis(src_object)
|
||||
if("tgui:link")
|
||||
user << link(params["url"])
|
||||
if("tgui:fancy")
|
||||
user.set_preference(/datum/client_preference/tgui_style, TRUE)
|
||||
if("tgui:nofrills")
|
||||
user.set_preference(/datum/client_preference/tgui_style, FALSE)
|
||||
else
|
||||
update_status(push = 0) // Update the window state.
|
||||
if(src_object.ui_act(action, params, src, state)) // Call ui_act() on the src_object.
|
||||
tgui_process.update_uis(src_object) // Update if the object requested it.
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Update the UI.
|
||||
* Only updates the data if update is true, otherwise only updates the status.
|
||||
*
|
||||
* optional force bool If the UI should be forced to update.
|
||||
**/
|
||||
/datum/tgui/proc/process(force = 0)
|
||||
var/datum/host = src_object.ui_host()
|
||||
if(!src_object || !host || !user) // If the object or user died (or something else), abort.
|
||||
close()
|
||||
return
|
||||
|
||||
if(status && (force || autoupdate))
|
||||
update() // Update the UI if the status and update settings allow it.
|
||||
else
|
||||
update_status(push = 1) // Otherwise only update status.
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Push data to an already open UI.
|
||||
*
|
||||
* required data list The data to send.
|
||||
* optional force bool If the update should be sent regardless of state.
|
||||
**/
|
||||
/datum/tgui/proc/push_data(data, force = 0)
|
||||
update_status(push = 0) // Update the window state.
|
||||
if(!initialized)
|
||||
return // Cannot update UI if it is not set up yet.
|
||||
if(status <= UI_DISABLED && !force)
|
||||
return // Cannot update UI, we have no visibility.
|
||||
|
||||
// Send the new JSON to the update() Javascript function.
|
||||
user << output(url_encode(get_json(data)), "[window_id].browser:update")
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Updates the UI by interacting with the src_object again, which will hopefully
|
||||
* call try_ui_update on it.
|
||||
*
|
||||
* optional force_open bool If force_open should be passed to ui_interact.
|
||||
**/
|
||||
/datum/tgui/proc/update(force_open = 0)
|
||||
src_object.tg_ui_interact(user, ui_key, src, force_open, master_ui, state)
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Update the status/visibility of the UI for its user.
|
||||
*
|
||||
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
|
||||
**/
|
||||
/datum/tgui/proc/update_status(push = 0)
|
||||
var/status = src_object.ui_status(user, state)
|
||||
if(master_ui)
|
||||
status = min(status, master_ui.status)
|
||||
|
||||
set_status(status, push)
|
||||
if(status == UI_CLOSE)
|
||||
close()
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Set the status/visibility of the UI.
|
||||
*
|
||||
* required status int The status to set (UI_CLOSE/UI_DISABLED/UI_UPDATE/UI_INTERACTIVE).
|
||||
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
|
||||
**/
|
||||
/datum/tgui/proc/set_status(status, push = 0)
|
||||
if(src.status != status) // Only update if status has changed.
|
||||
if(src.status == UI_DISABLED)
|
||||
src.status = status
|
||||
if(push)
|
||||
update()
|
||||
else
|
||||
src.status = status
|
||||
if(status == UI_DISABLED || push) // Update if the UI just because disabled, or a push is requested.
|
||||
push_data(null, force = 1)
|
||||
@@ -1,4 +1,5 @@
|
||||
body {
|
||||
body
|
||||
{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #272727;
|
||||
@@ -7,12 +8,14 @@ body {
|
||||
line-height: 170%;
|
||||
}
|
||||
|
||||
hr {
|
||||
hr
|
||||
{
|
||||
background-color: #40628a;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
a, a:link, a:visited, a:active, .linkOn, .linkOff {
|
||||
a, a:link, a:visited, a:active, .linkOn, .linkOff
|
||||
{
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background: #40628a;
|
||||
@@ -23,12 +26,14 @@ a, a:link, a:visited, a:active, .linkOn, .linkOff {
|
||||
white-space:nowrap;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
a:hover
|
||||
{
|
||||
color: #40628a;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
a.white, a.white:link, a.white:visited, a.white:active {
|
||||
a.white, a.white:link, a.white:visited, a.white:active
|
||||
{
|
||||
color: #40628a;
|
||||
text-decoration: none;
|
||||
background: #ffffff;
|
||||
@@ -38,29 +43,34 @@ a.white, a.white:link, a.white:visited, a.white:active {
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
a.white:hover {
|
||||
a.white:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #40628a;
|
||||
}
|
||||
|
||||
.linkOn, a.linkOn:link, a.linkOn:visited, a.linkOn:active, a.linkOn:hover {
|
||||
.linkOn, a.linkOn:link, a.linkOn:visited, a.linkOn:active, a.linkOn:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #2f943c;
|
||||
border-color: #24722e;
|
||||
}
|
||||
|
||||
.linkOff, a.linkOff:link, a.linkOff:visited, a.linkOff:active, a.linkOff:hover {
|
||||
.linkOff, a.linkOff:link, a.linkOff:visited, a.linkOff:active, a.linkOff:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #999999;
|
||||
border-color: #666666;
|
||||
}
|
||||
|
||||
a.icon, .linkOn.icon, .linkOff.icon {
|
||||
a.icon, .linkOn.icon, .linkOff.icon
|
||||
{
|
||||
position: relative;
|
||||
padding: 1px 4px 2px 20px;
|
||||
}
|
||||
|
||||
a.icon img, .linkOn.icon img {
|
||||
a.icon img, .linkOn.icon img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -68,13 +78,15 @@ a.icon img, .linkOn.icon img {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
a.icon64, .linkOn.icon64, .linkOff.icon64 {
|
||||
a.icon64, .linkOn.icon64, .linkOff.icon64
|
||||
{
|
||||
position: relative;
|
||||
padding: 1px 4px 2px 68px;
|
||||
font-size: 55px;
|
||||
}
|
||||
|
||||
a.icon64 img, .linkOn.icon64 img {
|
||||
a.icon64 img, .linkOn.icon64 img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -82,49 +94,60 @@ a.icon64 img, .linkOn.icon64 img {
|
||||
height: 66px;
|
||||
}
|
||||
|
||||
ul {
|
||||
ul
|
||||
{
|
||||
padding: 4px 0 0 10px;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li {
|
||||
li
|
||||
{
|
||||
padding: 0 0 2px 0;
|
||||
}
|
||||
|
||||
img, a img {
|
||||
img, a img
|
||||
{
|
||||
border-style:none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
margin: 0;
|
||||
padding: 16px 0 8px 0;
|
||||
color: #517087;
|
||||
}
|
||||
|
||||
h1 {
|
||||
h1
|
||||
{
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
h2
|
||||
{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
h3
|
||||
{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
h4
|
||||
{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.uiWrapper {
|
||||
.uiWrapper
|
||||
{
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-top:32px;
|
||||
}
|
||||
|
||||
.uiTitle {
|
||||
.uiTitle
|
||||
{
|
||||
clear: both;
|
||||
padding: 6px 8px 6px 8px;
|
||||
border-bottom: 2px solid #161616;
|
||||
@@ -133,7 +156,8 @@ h4 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.uiTitleWrapper {
|
||||
.uiTitleWrapper
|
||||
{
|
||||
position:fixed;
|
||||
top:0px;
|
||||
left:0px;
|
||||
@@ -141,7 +165,8 @@ h4 {
|
||||
z-index: 10
|
||||
}
|
||||
|
||||
.uiTitleButtons {
|
||||
.uiTitleButtons
|
||||
{
|
||||
position:fixed;
|
||||
top:0px;
|
||||
right:0px;
|
||||
@@ -150,39 +175,47 @@ h4 {
|
||||
}
|
||||
|
||||
|
||||
.uiTitle.icon {
|
||||
.uiTitle.icon
|
||||
{
|
||||
padding: 6px 8px 6px 42px;
|
||||
background-position: 2px 50%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.uiContent {
|
||||
.uiContent
|
||||
{
|
||||
clear: both;
|
||||
padding: 8px;
|
||||
font-family: Verdana, Geneva, sans-serif;
|
||||
}
|
||||
|
||||
.good {
|
||||
.good
|
||||
{
|
||||
color: #00ff00;
|
||||
}
|
||||
|
||||
.average {
|
||||
.average
|
||||
{
|
||||
color: #d09000;
|
||||
}
|
||||
|
||||
.bad {
|
||||
.bad
|
||||
{
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
.highlight
|
||||
{
|
||||
color: #8BA5C4;
|
||||
}
|
||||
|
||||
.dark {
|
||||
.dark
|
||||
{
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
.notice {
|
||||
.notice
|
||||
{
|
||||
position: relative;
|
||||
background: #E9C183;
|
||||
color: #15345A;
|
||||
@@ -192,11 +225,13 @@ h4 {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.notice.icon {
|
||||
.notice.icon
|
||||
{
|
||||
padding: 2px 4px 0 20px;
|
||||
}
|
||||
|
||||
.notice img {
|
||||
.notice img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -204,11 +239,13 @@ h4 {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
div.notice {
|
||||
div.notice
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.statusDisplay {
|
||||
.statusDisplay
|
||||
{
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
border: 1px solid #40628a;
|
||||
@@ -216,18 +253,21 @@ div.notice {
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.block {
|
||||
.block
|
||||
{
|
||||
padding: 8px;
|
||||
margin: 10px 4px 4px 4px;
|
||||
border: 1px solid #40628a;
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
.block h3 {
|
||||
.block h3
|
||||
{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.progressBar {
|
||||
.progressBar
|
||||
{
|
||||
width: 240px;
|
||||
height: 14px;
|
||||
border: 1px solid #666666;
|
||||
@@ -236,46 +276,55 @@ div.notice {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progressFill {
|
||||
.progressFill
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #40628a;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progressFill.good {
|
||||
.progressFill.good
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #00ff00;
|
||||
}
|
||||
|
||||
.progressFill.average {
|
||||
.progressFill.average
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #d09000;
|
||||
}
|
||||
|
||||
.progressFill.bad {
|
||||
.progressFill.bad
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #ff0000;
|
||||
}
|
||||
|
||||
.progressFill.highlight {
|
||||
.progressFill.highlight
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #8BA5C4;
|
||||
}
|
||||
|
||||
.clearBoth {
|
||||
.clearBoth
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.clearLeft {
|
||||
.clearLeft
|
||||
{
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.clearRight {
|
||||
.clearRight
|
||||
{
|
||||
clear: right;
|
||||
}
|
||||
|
||||
.line {
|
||||
.line
|
||||
{
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
.statusLabel {
|
||||
.statusLabel
|
||||
{
|
||||
width: 128px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.statusValue {
|
||||
.statusValue
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
.getblockstring {
|
||||
.getblockstring
|
||||
{
|
||||
font-family: Fixed, monospace;
|
||||
}
|
||||
|
||||
.blockString {
|
||||
.blockString
|
||||
{
|
||||
width: 55px;
|
||||
height: 19px;
|
||||
padding: 0 8px 8px 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.statusLabel {
|
||||
.statusLabel
|
||||
{
|
||||
width: 128px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.statusValue {
|
||||
.statusValue
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
.statusLabel {
|
||||
.statusLabel
|
||||
{
|
||||
width: 128px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.statusValue {
|
||||
.statusValue
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
################################
|
||||
# Example Changelog File
|
||||
#
|
||||
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
|
||||
#
|
||||
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
|
||||
# When it is, any changes listed below will disappear.
|
||||
#
|
||||
# Valid Prefixes:
|
||||
# bugfix
|
||||
# wip (For works in progress)
|
||||
# tweak
|
||||
# soundadd
|
||||
# sounddel
|
||||
# rscadd (general adding of nice things)
|
||||
# rscdel (general deleting of nice things)
|
||||
# imageadd
|
||||
# imagedel
|
||||
# maptweak
|
||||
# spellcheck (typo fixes)
|
||||
# experiment
|
||||
#################################
|
||||
|
||||
# Your name.
|
||||
author: Sin4
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- rscadd: "Upgrades NanoUI to version used by Paradise."
|
||||
- rscadd: "Ports tgui from Baystation."
|
||||
- rscadd: "Airlock electronics, APC, ATM, Brig Door Timers, Space Heaters, and Canisters now use tgui."
|
||||
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
@@ -1718,32 +1718,6 @@ window "mainwindow"
|
||||
macro = "macro"
|
||||
menu = "menu"
|
||||
on-close = ""
|
||||
elem "asset_cache_browser"
|
||||
type = BROWSER
|
||||
pos = 424,208
|
||||
size = 1x1
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #000000
|
||||
background-color = none
|
||||
is-visible = false
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = false
|
||||
border = none
|
||||
drop-zone = false
|
||||
right-click = false
|
||||
saved-params = ""
|
||||
on-size = ""
|
||||
show-history = false
|
||||
show-url = false
|
||||
auto-format = true
|
||||
use-title = false
|
||||
on-show = ""
|
||||
on-hide = ""
|
||||
elem "hotkey_toggle"
|
||||
type = BUTTON
|
||||
pos = 560,420
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
node_modules/
|
||||
bower_components/
|
||||
@@ -1,108 +0,0 @@
|
||||
### Settings ###
|
||||
util = require("gulp-util")
|
||||
s =
|
||||
min: util.env.min
|
||||
|
||||
# Project Paths
|
||||
input =
|
||||
fonts: "**/*.{eot,woff2}"
|
||||
images: "images"
|
||||
layouts: "layouts/"
|
||||
scripts:
|
||||
lib: "scripts/libraries"
|
||||
main: "scripts/nano"
|
||||
styles: "styles"
|
||||
templates: "templates/"
|
||||
|
||||
output =
|
||||
dir: "assets"
|
||||
scripts:
|
||||
lib: "libraries.min.js"
|
||||
main: "nano.js"
|
||||
css: "nanoui.css"
|
||||
|
||||
### Pacakages ###
|
||||
bower = require "main-bower-files"
|
||||
child_process = require "child_process"
|
||||
del = require "del"
|
||||
gulp = require "gulp"
|
||||
merge = require "merge-stream"
|
||||
|
||||
### Plugins ###
|
||||
g = require("gulp-load-plugins")({replaceString: /^gulp(-|\.)|-/g})
|
||||
p =
|
||||
autoprefixer: require "autoprefixer"
|
||||
gradient: require "postcss-filter-gradient"
|
||||
opacity: require "postcss-opacity"
|
||||
rgba: require "postcss-color-rgba-fallback"
|
||||
plsfilters: require "pleeease-filters"
|
||||
|
||||
|
||||
### Helpers ###
|
||||
|
||||
glob = (path) ->
|
||||
"#{path}/*"
|
||||
|
||||
### Tasks ###
|
||||
gulp.task "default", ["fonts", "scripts", "styles"]
|
||||
|
||||
gulp.task "clean", ->
|
||||
del glob output.dir
|
||||
|
||||
gulp.task "watch", ->
|
||||
gulp.watch [glob input.images], ["reload"]
|
||||
gulp.watch [glob input.layouts], ["reload"]
|
||||
gulp.watch [glob input.scripts.lib], ["reload"]
|
||||
gulp.watch [glob input.scripts.main], ["reload"]
|
||||
gulp.watch [glob input.styles], ["reload"]
|
||||
gulp.watch [glob input.templates], ["reload"]
|
||||
|
||||
gulp.task "reload", ["default"], ->
|
||||
child_process.exec "reload.bat", (err, stdout, stderr) ->
|
||||
return console.log err if err
|
||||
|
||||
|
||||
gulp.task "fonts", ["clean"], ->
|
||||
gulp.src bower input.fonts
|
||||
.pipe gulp.dest output.dir
|
||||
|
||||
gulp.task "scripts", ["clean"], ->
|
||||
lib = gulp.src glob input.scripts.lib
|
||||
etc = gulp.src bower "**/*.js"
|
||||
|
||||
merged = merge lib, etc
|
||||
.pipe g.order(["jquery.js",
|
||||
"jquery*.js",
|
||||
"*.js"])
|
||||
.pipe g.concat(output.scripts.lib)
|
||||
.pipe g.if(s.min, g.uglify().on('error', util.log))
|
||||
.pipe gulp.dest output.dir
|
||||
|
||||
main = gulp.src glob input.scripts.main
|
||||
.pipe g.order(["nano_utility.js",
|
||||
"nano_state_manager.js"
|
||||
"*.js"])
|
||||
.pipe g.concat(output.scripts.main)
|
||||
.pipe g.if(s.min, g.uglify().on('error', util.log))
|
||||
.pipe gulp.dest output.dir
|
||||
|
||||
gulp.task "styles", ["clean"], ->
|
||||
lib = gulp.src bower "**/*.css"
|
||||
.pipe g.replace("../fonts/", "")
|
||||
|
||||
main = gulp.src glob input.styles
|
||||
.pipe g.filter(["*.less", "!_*.less"])
|
||||
.pipe g.less({paths: [input.images]})
|
||||
.pipe g.postcss([
|
||||
p.autoprefixer({browsers: ["last 2 versions", "ie >= 8"]}),
|
||||
p.gradient,
|
||||
p.opacity,
|
||||
p.rgba({oldie: true}),
|
||||
p.plsfilters({oldIE: true})
|
||||
])
|
||||
|
||||
combined = merge lib, main
|
||||
combined
|
||||
.pipe g.if(s.min, g.cssnano({discardComments: {removeAll: true}}), g.csscomb())
|
||||
.pipe g.concat(output.css)
|
||||
.pipe gulp.dest output.dir
|
||||
@@ -1,2 +0,0 @@
|
||||
require('coffee-script/register');
|
||||
require('./Gulpfile.coffee');
|
||||
@@ -1,107 +0,0 @@
|
||||
# NanoUI
|
||||
|
||||
NanoUI is a user interface library, used for over 100 different interfaces, and rising.
|
||||
It is more complicated than the other two UI systems in use, the `/datum/browser` and
|
||||
`browse()` systems, but offers pre-made libraries, JavaScript, and a modified doT
|
||||
template engine.
|
||||
|
||||
This README is not yet complete, but gives a basic rundown of how the folder structure
|
||||
works. I'll get around to finishing it one day.
|
||||
|
||||
## Contributors
|
||||
|
||||
This section is for listing the contributors to NanoUI.
|
||||
|
||||
- -tg-station/Neersighted
|
||||
- Special thanks goes to Neersighted for creating most of the newest and best features
|
||||
of NanoUI. Everything between using the Gulp build system to switching to LESS styles
|
||||
has been directly adapated and/or copied from his original work for -tg-station and
|
||||
their UI system, tgui.
|
||||
|
||||
Systems ported/adapted from -tg-station and Neersighted include, but are not limited
|
||||
to:
|
||||
|
||||
- NanoUI's JavaScript controlling the "fancy" borderless window mode.
|
||||
- The NanoTrasen.svg logo (Licensed under CC 3.0 BY-SA).
|
||||
- The Gulp buildscript concept, as well as a large amount of the actual
|
||||
Gulpfile.coffee.
|
||||
- The packages in bower.json and packages.json files were hand-picked by Neersighted
|
||||
for usage in compiling NanoUI.
|
||||
- A considerable amount of this README is adapated from Neersighted's documentation.
|
||||
- The concepts following: Using FontAwesome instead of icon16, Using LESS to expand
|
||||
NanoUI's CSS style.
|
||||
|
||||
NanoUI is licensed under AGPLv3. This applies to it's serverside `DM` code as well as it's
|
||||
clientside `JavaScript` and `LESS` code. The file `nano/images/nanotrasen.svg` is licensed
|
||||
under CC 3.0 BY-SA, and was created by Neersighted. All other image files in the
|
||||
`nano/images/` directory are subject to the standard image license applied to the Paradise
|
||||
repository icons.
|
||||
|
||||
## Folder Rundown
|
||||
|
||||
### /assets
|
||||
The assets folder is used by the Gulp compiling system, and stores the minified version of
|
||||
the NanoUI JavaScript Library and prerequisites. Everything within this folder is sent to
|
||||
the client as-is.
|
||||
|
||||
### /codemirror
|
||||
This folder contains all of the JavaScript and CSS for CodeMirror. It is sent to the
|
||||
client as-is. CodeMirror only has it's own folder due to the fact that it can't be
|
||||
directly compiled into the NanoUI files.
|
||||
|
||||
### /images
|
||||
This folder is used to store any image files. It is sent to the client as-is.
|
||||
|
||||
### /layouts
|
||||
This folder is used for the central "layout" template files, which is loaded before the
|
||||
UI's actual template file. It is sent to the client as-is.
|
||||
|
||||
### /scripts
|
||||
This folder is used for anything that will be compiled by the Gulp compilation system.
|
||||
Currently, it is split into two folders. The file names must start with a number, as this
|
||||
is how Gulp decides what order to put the concatenated and possibly minified files in.
|
||||
Anything within this folder is not sent to the client directly.
|
||||
|
||||
#### /scripts/libraries
|
||||
This folder is used to store the source code of the prerequisites of NanoUI. Currently,
|
||||
it contains jQuery, jQuery UI, jQuery timers, and the doT template system.
|
||||
|
||||
#### /scripts/nano
|
||||
This folder contains the primary JavaScript for NanoUI.
|
||||
|
||||
### /styles
|
||||
This folder is used for NanoUI's LESS styles. These are compiled via gulp into the file
|
||||
`nanoui.css`. LESS is a system that expands upon CSS in order to make it better, as well
|
||||
as less complicated.
|
||||
|
||||
Any LESS file that is prefixed with the `_` character will be ignored during compilation.
|
||||
These files are still included, however, via `@import`, view the file
|
||||
[`nanoui.less`](http://github.com/ParadiseSS13/Paradise/blob/master/nano/styles/nanoui.less) to see how this works.
|
||||
|
||||
|
||||
### /templates
|
||||
This folder is used to store the .tmpl files which are later compiled by the NanoUtility
|
||||
JavaScript, using a modified version of the doT template engine. It is sent to the client
|
||||
as-is.
|
||||
|
||||
## Compiling
|
||||
To compile any changes to the NanoUI JavaScript, you must first setup the building
|
||||
environment.
|
||||
|
||||
### Prerequisites
|
||||
You will first need to install the primary prerequisite of NanoUI, [Node.js](https://nodejs.org).
|
||||
|
||||
Node.js is used to obtain all of the remaining prerequisites to compile NanoUI. This is
|
||||
done by running the following commands.
|
||||
- `npm install -g gulp bower`
|
||||
- `npm install`
|
||||
- `bower install`
|
||||
|
||||
### Running Gulp
|
||||
NanoUI is built using the `gulp` task automation system. This system uses the contents
|
||||
of the `Gulpfile.js` and `Gulpfile.coffee` files to perform compilation tasks.
|
||||
|
||||
In order to build an un-minified version of NanoUI, you may simply run `gulp` in the
|
||||
`nanoui` directory. However, this should only be used while testing, and you should run
|
||||
the command `gulp --min` before commiting changes, in order to produce minified
|
||||
JavaScript.
|
||||
@@ -0,0 +1,4 @@
|
||||
copy css\* "%USERPROFILE%\Documents\BYOND\cache" /y
|
||||
copy images\* "%USERPROFILE%\Documents\BYOND\cache" /y
|
||||
copy js\* "%USERPROFILE%\Documents\BYOND\cache" /y
|
||||
copy templates\* "%USERPROFILE%\Documents\BYOND\cache" /y
|
||||