Merge branch 'master' into QM-as-Head
@@ -54,7 +54,7 @@
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
GLOB.crewmonitor.show(AI)
|
||||
GLOB.crewmonitor.show(AI,AI)
|
||||
|
||||
/obj/screen/ai/crew_manifest
|
||||
name = "Crew Manifest"
|
||||
|
||||
@@ -57,8 +57,6 @@ GLOBAL_LIST_EMPTY(cinematics)
|
||||
|
||||
//Close all open windows if global
|
||||
if(is_global)
|
||||
for (var/datum/html_interface/hi in GLOB.html_interfaces)
|
||||
hi.closeAll()
|
||||
SStgui.close_all_uis()
|
||||
|
||||
|
||||
|
||||
@@ -143,10 +143,6 @@
|
||||
var/datum/atom_hud/data/human/medical/basic/B = GLOB.huds[DATA_HUD_MEDICAL_BASIC]
|
||||
B.update_suit_sensors(src)
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if (T)
|
||||
GLOB.crewmonitor.queueUpdate(T.z)
|
||||
|
||||
//called when a living mob changes health
|
||||
/mob/living/proc/med_hud_set_health()
|
||||
var/image/holder = hud_list[HEALTH_HUD]
|
||||
@@ -158,10 +154,6 @@
|
||||
/mob/living/carbon/med_hud_set_health()
|
||||
..()
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
GLOB.crewmonitor.queueUpdate(T.z)
|
||||
|
||||
//called when a carbon changes stat, virus or XENO_HOST
|
||||
/mob/living/proc/med_hud_set_status()
|
||||
var/image/holder = hud_list[STATUS_HUD]
|
||||
@@ -216,10 +208,6 @@
|
||||
holder.icon_state = "hud[ckey(wear_id.GetJobName())]"
|
||||
sec_hud_set_security_status()
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if (T)
|
||||
GLOB.crewmonitor.queueUpdate(T.z)
|
||||
|
||||
/mob/living/carbon/human/proc/sec_hud_set_implants()
|
||||
var/image/holder
|
||||
for(var/i in list(IMPTRACK_HUD, IMPLOYAL_HUD, IMPCHEM_HUD))
|
||||
|
||||
@@ -456,21 +456,6 @@ Class Procs:
|
||||
/obj/machinery/proc/on_deconstruction()
|
||||
return
|
||||
|
||||
// Hook for html_interface module to prevent updates to clients who don't have this as their active machine.
|
||||
/obj/machinery/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi)
|
||||
if (hclient.client.mob && (hclient.client.mob.stat == 0 || IsAdminGhost(hclient.client.mob)))
|
||||
if (isAI(hclient.client.mob) || IsAdminGhost(hclient.client.mob))
|
||||
return TRUE
|
||||
else
|
||||
return hclient.client.mob.machine == src && Adjacent(hclient.client.mob)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
// Hook for html_interface module to unset the active machine when the window is closed by the player.
|
||||
/obj/machinery/proc/hiOnHide(datum/html_interface_client/hclient)
|
||||
if (hclient.client.mob && hclient.client.mob.machine == src)
|
||||
hclient.client.mob.unset_machine()
|
||||
|
||||
/obj/machinery/proc/can_be_overridden()
|
||||
. = 1
|
||||
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
switchCamera(cameras[camera])
|
||||
|
||||
/datum/trackable
|
||||
var/initialized = FALSE
|
||||
var/list/names = list()
|
||||
var/list/namecounts = list()
|
||||
var/list/humans = list()
|
||||
var/list/others = list()
|
||||
|
||||
/mob/living/silicon/ai/proc/trackable_mobs()
|
||||
|
||||
track.initialized = TRUE
|
||||
track.names.Cut()
|
||||
track.namecounts.Cut()
|
||||
track.humans.Cut()
|
||||
@@ -63,6 +64,9 @@
|
||||
if(!target_name)
|
||||
return
|
||||
|
||||
if(!track.initialized)
|
||||
trackable_mobs()
|
||||
|
||||
var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name])
|
||||
|
||||
ai_actual_track(target)
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
body
|
||||
{
|
||||
padding-left: 53%;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#ntbgcenter
|
||||
{
|
||||
background-position: 550px 0px !important;
|
||||
}
|
||||
|
||||
#minimap
|
||||
{
|
||||
position: fixed;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
border: 2px inset #888;
|
||||
overflow: hidden;
|
||||
min-width: 480px;
|
||||
min-height: 480px;
|
||||
width: 53%;
|
||||
height: 100%;
|
||||
max-width: 480px;
|
||||
max-height: 480px;
|
||||
}
|
||||
|
||||
#textbased
|
||||
{
|
||||
width: 100%;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
#textbased table
|
||||
{
|
||||
min-width: 380px;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
#textbased td
|
||||
{
|
||||
vertical-align: top;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#textbased tbody td
|
||||
{
|
||||
transition: .2s all;
|
||||
}
|
||||
|
||||
#textbased tbody tr:hover td, #textbased tbody tr.hover td
|
||||
{
|
||||
background-color: #515151;
|
||||
}
|
||||
|
||||
#textarea:after
|
||||
{
|
||||
content: "";
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.health
|
||||
{
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: #FFF;
|
||||
border: 1px solid #434343;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.health-5 { background-color: #17d568; }
|
||||
.health-4 { background-color: #2ecc71; }
|
||||
.health-3 { background-color: #e67e22; }
|
||||
.health-2 { background-color: #ed5100; }
|
||||
.health-1 { background-color: #e74c3c; }
|
||||
.health-0 { background-color: #ed2814; }
|
||||
|
||||
.health > div
|
||||
{
|
||||
margin-left: 20px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.tt
|
||||
{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.tt > div
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tt:hover > div
|
||||
{
|
||||
position: absolute;
|
||||
bottom: -30px;
|
||||
left: 50%;
|
||||
margin-left: -64px;
|
||||
|
||||
display: block;
|
||||
width: 128px;
|
||||
height: 24px;
|
||||
border: 1px solid #313131;
|
||||
background-color: #434343;
|
||||
padding: 4px;
|
||||
z-index: 999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tt > div > span
|
||||
{
|
||||
position: relative;
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.dot
|
||||
{
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
margin-top: 0px;
|
||||
margin-left: 0px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.dot.active
|
||||
{
|
||||
z-index: 9999 !important;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-top: -2px;
|
||||
margin-left: -3px;
|
||||
}
|
||||
|
||||
.zoom
|
||||
{
|
||||
position: fixed;
|
||||
left: 53%;
|
||||
top: 10px;
|
||||
display: block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
margin-left: 20px !important;
|
||||
}
|
||||
|
||||
.zoom.in
|
||||
{
|
||||
margin-left: -3px !important;
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
#define SENSORS_UPDATE_PERIOD 100 //How often the sensor data updates.
|
||||
|
||||
/obj/machinery/computer/crew
|
||||
name = "crew monitoring console"
|
||||
desc = "Used to monitor active health sensors built into most of the crew's uniforms."
|
||||
@@ -16,21 +18,22 @@
|
||||
/obj/machinery/computer/crew/attack_ai(mob/user)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
GLOB.crewmonitor.show(user)
|
||||
GLOB.crewmonitor.show(user,src)
|
||||
|
||||
/obj/machinery/computer/crew/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
GLOB.crewmonitor.show(user)
|
||||
GLOB.crewmonitor.show(user,src)
|
||||
|
||||
GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
|
||||
/datum/crewmonitor
|
||||
var/list/ui_sources = list() //List of user -> ui source
|
||||
var/list/jobs
|
||||
var/list/interfaces
|
||||
var/list/data
|
||||
var/list/data_by_z = list()
|
||||
var/list/last_update = list()
|
||||
|
||||
/datum/crewmonitor/New()
|
||||
. = ..()
|
||||
@@ -77,196 +80,119 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
jobs["Assistant"] = 999 //Unknowns/custom jobs should appear after civilians, and before assistants
|
||||
|
||||
src.jobs = jobs
|
||||
src.interfaces = list()
|
||||
src.data = list()
|
||||
register_asset("crewmonitor.js",'crew.js')
|
||||
register_asset("crewmonitor.css",'crew.css')
|
||||
|
||||
/datum/crewmonitor/Destroy()
|
||||
if (src.interfaces)
|
||||
for (var/datum/html_interface/hi in interfaces)
|
||||
qdel(hi)
|
||||
src.interfaces = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/crewmonitor/proc/show(mob/mob, z)
|
||||
if (mob.client)
|
||||
sendResources(mob.client)
|
||||
if (!z)
|
||||
z = mob.z
|
||||
/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "crew", "crew monitor", 800, 600 , master_ui, state)
|
||||
ui.open()
|
||||
|
||||
if (z > 0 && src.interfaces)
|
||||
var/datum/html_interface/hi
|
||||
/datum/crewmonitor/proc/show(mob/M, source)
|
||||
ui_sources[M] = source
|
||||
ui_interact(M)
|
||||
|
||||
if (!src.interfaces["[z]"])
|
||||
src.interfaces["[z]"] = new/datum/html_interface/nanotrasen(src, "Crew Monitoring", 900, 540, "<link rel=\"stylesheet\" type=\"text/css\" href=\"crewmonitor.css\" /><script type=\"text/javascript\">var z = [z]; var tile_size = [world.icon_size]; var maxx = [world.maxx]; var maxy = [world.maxy];</script><script type=\"text/javascript\" src=\"crewmonitor.js\"></script>")
|
||||
/datum/crewmonitor/ui_host(mob/user)
|
||||
return ui_sources[user]
|
||||
|
||||
hi = src.interfaces["[z]"]
|
||||
/datum/crewmonitor/ui_data(mob/user)
|
||||
var/z = user.z
|
||||
if(!z)
|
||||
var/turf/T = get_turf(user)
|
||||
z = T.z
|
||||
var/list/zdata = update_data(z)
|
||||
. = list()
|
||||
.["sensors"] = zdata
|
||||
.["link_allowed"] = isAI(user)
|
||||
|
||||
hi.updateContent("content", "<div id=\"minimap\"><a href=\"javascript:zoomIn();\" class=\"zoom in\">+</a><a href=\"javascript:zoomOut();\" class=\"zoom\">-</a></div><div id=\"textbased\"></div>")
|
||||
/datum/crewmonitor/proc/update_data(z)
|
||||
if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD)
|
||||
return data_by_z["[z]"]
|
||||
|
||||
src.update(z, TRUE)
|
||||
else
|
||||
hi = src.interfaces["[z]"]
|
||||
src.update(z,TRUE)
|
||||
var/list/results = list()
|
||||
var/obj/item/clothing/under/U
|
||||
var/obj/item/card/id/I
|
||||
var/turf/pos
|
||||
var/ijob
|
||||
var/name
|
||||
var/assignment
|
||||
var/oxydam
|
||||
var/toxdam
|
||||
var/burndam
|
||||
var/brutedam
|
||||
var/area
|
||||
var/pos_x
|
||||
var/pos_y
|
||||
var/life_status
|
||||
|
||||
// Debugging purposes
|
||||
mob << browse_rsc(file("code/game/machinery/computer/crew.js"), "crew.js")
|
||||
mob << browse_rsc(file("code/game/machinery/computer/crew.css"), "crew.css")
|
||||
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
|
||||
// Check if their z-level is correct and if they are wearing a uniform.
|
||||
// Accept H.z==0 as well in case the mob is inside an object.
|
||||
if ((H.z == 0 || H.z == z) && istype(H.w_uniform, /obj/item/clothing/under))
|
||||
U = H.w_uniform
|
||||
|
||||
hi = src.interfaces["[z]"]
|
||||
hi.show(mob)
|
||||
src.updateFor(mob, hi, z)
|
||||
// Are the suit sensors on?
|
||||
if ((U.has_sensor > 0) && U.sensor_mode)
|
||||
pos = H.z == 0 || U.sensor_mode == SENSOR_COORDS ? get_turf(H) : null
|
||||
|
||||
/datum/crewmonitor/proc/updateFor(hclient_or_mob, datum/html_interface/hi, z)
|
||||
// This check will succeed if updateFor is called after showing to the player, but will fail
|
||||
// on regular updates. Since we only really need this once we don't care if it fails.
|
||||
hi.callJavaScript("clearAll", null, hclient_or_mob)
|
||||
// Special case: If the mob is inside an object confirm the z-level on turf level.
|
||||
if (H.z == 0 && (!pos || pos.z != z))
|
||||
continue
|
||||
|
||||
for (var/list/L in data)
|
||||
hi.callJavaScript("add", L, hclient_or_mob)
|
||||
I = H.wear_id ? H.wear_id.GetID() : null
|
||||
|
||||
hi.callJavaScript("onAfterUpdate", null, hclient_or_mob)
|
||||
if (I)
|
||||
name = I.registered_name
|
||||
assignment = I.assignment
|
||||
ijob = jobs[I.assignment]
|
||||
else
|
||||
name = "Unknown"
|
||||
assignment = ""
|
||||
ijob = 80
|
||||
|
||||
/datum/crewmonitor/proc/update(z, ignore_unused = FALSE)
|
||||
if (src.interfaces["[z]"])
|
||||
var/datum/html_interface/hi = src.interfaces["[z]"]
|
||||
if (U.sensor_mode >= SENSOR_LIVING)
|
||||
life_status = (!H.stat ? TRUE : FALSE)
|
||||
else
|
||||
life_status = null
|
||||
|
||||
if (ignore_unused || hi.isUsed())
|
||||
var/list/results = list()
|
||||
var/obj/item/clothing/under/U
|
||||
var/obj/item/card/id/I
|
||||
var/turf/pos
|
||||
var/ijob
|
||||
var/name
|
||||
var/assignment
|
||||
var/dam1
|
||||
var/dam2
|
||||
var/dam3
|
||||
var/dam4
|
||||
var/area
|
||||
var/pos_x
|
||||
var/pos_y
|
||||
var/life_status
|
||||
if (U.sensor_mode >= SENSOR_VITALS)
|
||||
oxydam = round(H.getOxyLoss(),1)
|
||||
toxdam = round(H.getToxLoss(),1)
|
||||
burndam = round(H.getFireLoss(),1)
|
||||
brutedam = round(H.getBruteLoss(),1)
|
||||
else
|
||||
oxydam = null
|
||||
toxdam = null
|
||||
burndam = null
|
||||
brutedam = null
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
|
||||
// Check if their z-level is correct and if they are wearing a uniform.
|
||||
// Accept H.z==0 as well in case the mob is inside an object.
|
||||
if ((H.z == 0 || H.z == z) && istype(H.w_uniform, /obj/item/clothing/under))
|
||||
U = H.w_uniform
|
||||
if (U.sensor_mode >= SENSOR_COORDS)
|
||||
if (!pos)
|
||||
pos = get_turf(H)
|
||||
area = get_area_name(H, TRUE)
|
||||
pos_x = pos.x
|
||||
pos_y = pos.y
|
||||
else
|
||||
area = null
|
||||
pos_x = null
|
||||
pos_y = null
|
||||
|
||||
// Are the suit sensors on?
|
||||
if ((U.has_sensor > 0) && U.sensor_mode)
|
||||
pos = H.z == 0 || U.sensor_mode == SENSOR_COORDS ? get_turf(H) : null
|
||||
results[++results.len] = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null))
|
||||
|
||||
data_by_z["[z]"] = results
|
||||
last_update["[z]"] = world.time
|
||||
|
||||
return results
|
||||
|
||||
// Special case: If the mob is inside an object confirm the z-level on turf level.
|
||||
if (H.z == 0 && (!pos || pos.z != z))
|
||||
continue
|
||||
/datum/crewmonitor/ui_act(action,params)
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
if(!istype(AI))
|
||||
return
|
||||
switch (action)
|
||||
if ("select_person")
|
||||
AI.ai_camera_track(params["name"])
|
||||
|
||||
I = H.wear_id ? H.wear_id.GetID() : null
|
||||
|
||||
if (I)
|
||||
name = I.registered_name
|
||||
assignment = I.assignment
|
||||
ijob = jobs[I.assignment]
|
||||
else
|
||||
name = "<i>Unknown</i>"
|
||||
assignment = ""
|
||||
ijob = 80
|
||||
|
||||
if (U.sensor_mode >= SENSOR_LIVING)
|
||||
life_status = (!H.stat ? "true" : "false")
|
||||
else
|
||||
life_status = null
|
||||
|
||||
if (U.sensor_mode >= SENSOR_VITALS)
|
||||
dam1 = round(H.getOxyLoss(),1)
|
||||
dam2 = round(H.getToxLoss(),1)
|
||||
dam3 = round(H.getFireLoss(),1)
|
||||
dam4 = round(H.getBruteLoss(),1)
|
||||
else
|
||||
dam1 = null
|
||||
dam2 = null
|
||||
dam3 = null
|
||||
dam4 = null
|
||||
|
||||
if (U.sensor_mode >= SENSOR_COORDS)
|
||||
if (!pos)
|
||||
pos = get_turf(H)
|
||||
area = get_area_name(H, TRUE)
|
||||
pos_x = pos.x
|
||||
pos_y = pos.y
|
||||
else
|
||||
area = null
|
||||
pos_x = null
|
||||
pos_y = null
|
||||
|
||||
results[++results.len] = list(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area, pos_x, pos_y, H.can_track(null))
|
||||
|
||||
src.data = results
|
||||
src.updateFor(null, hi, z) // updates for everyone
|
||||
|
||||
/datum/crewmonitor/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi)
|
||||
var/z = ""
|
||||
|
||||
for (z in src.interfaces)
|
||||
if (src.interfaces[z] == hi)
|
||||
break
|
||||
|
||||
if(hclient.client.mob && IsAdminGhost(hclient.client.mob))
|
||||
return TRUE
|
||||
|
||||
if (hclient.client.mob && hclient.client.mob.stat == 0 && hclient.client.mob.z == text2num(z))
|
||||
if (isAI(hclient.client.mob))
|
||||
return TRUE
|
||||
else if (iscyborg(hclient.client.mob))
|
||||
return (locate(/obj/machinery/computer/crew, range(world.view, hclient.client.mob))) || (locate(/obj/item/device/sensor_device, hclient.client.mob.contents))
|
||||
else
|
||||
return (locate(/obj/machinery/computer/crew, range(1, hclient.client.mob))) || (locate(/obj/item/device/sensor_device, hclient.client.mob.contents))
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/datum/crewmonitor/Topic(href, href_list[], datum/html_interface_client/hclient)
|
||||
if (istype(hclient))
|
||||
if (hclient && hclient.client && hclient.client.mob && isAI(hclient.client.mob))
|
||||
var/mob/living/silicon/ai/AI = hclient.client.mob
|
||||
|
||||
switch (href_list["action"])
|
||||
if ("select_person")
|
||||
AI.ai_camera_track(href_list["name"])
|
||||
|
||||
if ("select_position")
|
||||
var/x = text2num(href_list["x"])
|
||||
var/y = text2num(href_list["y"])
|
||||
var/turf/tile = locate(x, y, AI.z)
|
||||
|
||||
var/obj/machinery/camera/C = locate(/obj/machinery/camera) in range(5, tile)
|
||||
|
||||
if (!C)
|
||||
C = locate(/obj/machinery/camera) in urange(10, tile)
|
||||
if (!C)
|
||||
C = locate(/obj/machinery/camera) in urange(15, tile)
|
||||
|
||||
if (C)
|
||||
addtimer(CALLBACK(src, .proc/update_ai, AI, C, AI.eyeobj.loc), min(30, get_dist(get_turf(C), AI.eyeobj) / 4))
|
||||
|
||||
/datum/crewmonitor/proc/update_ai(mob/living/silicon/ai/AI, obj/machinery/camera/C, turf/current_loc)
|
||||
if (AI && AI.eyeobj && current_loc == AI.eyeobj.loc)
|
||||
AI.switchCamera(C)
|
||||
|
||||
/mob/living/carbon/human/Move()
|
||||
var/old_z = src.z
|
||||
. = ..()
|
||||
if (src.w_uniform)
|
||||
if (old_z != src.z)
|
||||
GLOB.crewmonitor.queueUpdate(old_z)
|
||||
GLOB.crewmonitor.queueUpdate(src.z)
|
||||
|
||||
/datum/crewmonitor/proc/queueUpdate(z)
|
||||
addtimer(CALLBACK(src, .proc/update, z), 5, TIMER_UNIQUE)
|
||||
|
||||
/datum/crewmonitor/proc/sendResources(var/client/client)
|
||||
send_asset(client, "crewmonitor.js")
|
||||
send_asset(client, "crewmonitor.css")
|
||||
SSminimap.send(client)
|
||||
#undef SENSORS_UPDATE_PERIOD
|
||||
@@ -1,588 +0,0 @@
|
||||
/*!
|
||||
* jQuery scrollintoview() plugin and :scrollable selector filter
|
||||
*
|
||||
* Version 1.8 (14 Jul 2011)
|
||||
* Requires jQuery 1.4 or newer
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var converter = {
|
||||
vertical: { x: false, y: true },
|
||||
horizontal: { x: true, y: false },
|
||||
both: { x: true, y: true },
|
||||
x: { x: true, y: false },
|
||||
y: { x: false, y: true }
|
||||
};
|
||||
|
||||
var settings = {
|
||||
duration: "fast",
|
||||
direction: "both"
|
||||
};
|
||||
|
||||
var rootrx = /^(?:html)$/i;
|
||||
|
||||
// gets border dimensions
|
||||
var borders = function (domElement, styles) {
|
||||
styles = styles || (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(domElement, null) : domElement.currentStyle);
|
||||
var px = document.defaultView && document.defaultView.getComputedStyle ? true : false;
|
||||
var b = {
|
||||
top: (parseFloat(px ? styles.borderTopWidth : $.css(domElement, "borderTopWidth")) || 0),
|
||||
left: (parseFloat(px ? styles.borderLeftWidth : $.css(domElement, "borderLeftWidth")) || 0),
|
||||
bottom: (parseFloat(px ? styles.borderBottomWidth : $.css(domElement, "borderBottomWidth")) || 0),
|
||||
right: (parseFloat(px ? styles.borderRightWidth : $.css(domElement, "borderRightWidth")) || 0)
|
||||
};
|
||||
return {
|
||||
top: b.top,
|
||||
left: b.left,
|
||||
bottom: b.bottom,
|
||||
right: b.right,
|
||||
vertical: b.top + b.bottom,
|
||||
horizontal: b.left + b.right
|
||||
};
|
||||
};
|
||||
|
||||
var dimensions = function ($element) {
|
||||
var win = $(window);
|
||||
var isRoot = rootrx.test($element[0].nodeName);
|
||||
return {
|
||||
border: isRoot ? { top: 0, left: 0, bottom: 0, right: 0} : borders($element[0]),
|
||||
scroll: {
|
||||
top: (isRoot ? win : $element).scrollTop(),
|
||||
left: (isRoot ? win : $element).scrollLeft()
|
||||
},
|
||||
scrollbar: {
|
||||
right: isRoot ? 0 : $element.innerWidth() - $element[0].clientWidth,
|
||||
bottom: isRoot ? 0 : $element.innerHeight() - $element[0].clientHeight
|
||||
},
|
||||
rect: (function () {
|
||||
var r = $element[0].getBoundingClientRect();
|
||||
return {
|
||||
top: isRoot ? 0 : r.top,
|
||||
left: isRoot ? 0 : r.left,
|
||||
bottom: isRoot ? $element[0].clientHeight : r.bottom,
|
||||
right: isRoot ? $element[0].clientWidth : r.right
|
||||
};
|
||||
})()
|
||||
};
|
||||
};
|
||||
|
||||
$.fn.extend({
|
||||
scrollintoview: function (options) {
|
||||
/// <summary>Scrolls the first element in the set into view by scrolling its closest scrollable parent.</summary>
|
||||
/// <param name="options" type="Object">Additional options that can configure scrolling:
|
||||
/// duration (default: "fast") - jQuery animation speed (can be a duration string or number of milliseconds)
|
||||
/// direction (default: "both") - select possible scrollings ("vertical" or "y", "horizontal" or "x", "both")
|
||||
/// complete (default: none) - a function to call when scrolling completes (called in context of the DOM element being scrolled)
|
||||
/// </param>
|
||||
/// <return type="jQuery">Returns the same jQuery set that this function was run on.</return>
|
||||
|
||||
options = $.extend({}, settings, options);
|
||||
options.direction = converter[typeof (options.direction) === "string" && options.direction.toLowerCase()] || converter.both;
|
||||
|
||||
var dirStr = "";
|
||||
if (options.direction.x === true) dirStr = "horizontal";
|
||||
if (options.direction.y === true) dirStr = dirStr ? "both" : "vertical";
|
||||
|
||||
var el = this.eq(0);
|
||||
var scroller = el.closest(":scrollable(" + dirStr + ")");
|
||||
|
||||
// check if there's anything to scroll in the first place
|
||||
if (scroller.length > 0)
|
||||
{
|
||||
scroller = scroller.eq(0);
|
||||
|
||||
var dim = {
|
||||
e: dimensions(el),
|
||||
s: dimensions(scroller)
|
||||
};
|
||||
|
||||
var rel = {
|
||||
top: dim.e.rect.top - (dim.s.rect.top + dim.s.border.top),
|
||||
bottom: dim.s.rect.bottom - dim.s.border.bottom - dim.s.scrollbar.bottom - dim.e.rect.bottom,
|
||||
left: dim.e.rect.left - (dim.s.rect.left + dim.s.border.left),
|
||||
right: dim.s.rect.right - dim.s.border.right - dim.s.scrollbar.right - dim.e.rect.right
|
||||
};
|
||||
|
||||
var animOptions = {};
|
||||
|
||||
// vertical scroll
|
||||
if (options.direction.y === true)
|
||||
{
|
||||
if (rel.top < 0)
|
||||
{
|
||||
animOptions.scrollTop = dim.s.scroll.top + rel.top;
|
||||
}
|
||||
else if (rel.top > 0 && rel.bottom < 0)
|
||||
{
|
||||
animOptions.scrollTop = dim.s.scroll.top + Math.min(rel.top, -rel.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
// horizontal scroll
|
||||
if (options.direction.x === true)
|
||||
{
|
||||
if (rel.left < 0)
|
||||
{
|
||||
animOptions.scrollLeft = dim.s.scroll.left + rel.left;
|
||||
}
|
||||
else if (rel.left > 0 && rel.right < 0)
|
||||
{
|
||||
animOptions.scrollLeft = dim.s.scroll.left + Math.min(rel.left, -rel.right);
|
||||
}
|
||||
}
|
||||
|
||||
// scroll if needed
|
||||
if (!$.isEmptyObject(animOptions))
|
||||
{
|
||||
if (rootrx.test(scroller[0].nodeName))
|
||||
{
|
||||
scroller = $("html,body");
|
||||
}
|
||||
scroller
|
||||
.animate(animOptions, options.duration)
|
||||
.eq(0) // we want function to be called just once (ref. "html,body")
|
||||
.queue(function (next) {
|
||||
$.isFunction(options.complete) && options.complete.call(scroller[0]);
|
||||
next();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// when there's nothing to scroll, just call the "complete" function
|
||||
$.isFunction(options.complete) && options.complete.call(scroller[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// return set back
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
var scrollValue = {
|
||||
auto: true,
|
||||
scroll: true,
|
||||
visible: false,
|
||||
hidden: false
|
||||
};
|
||||
|
||||
$.extend($.expr[":"], {
|
||||
scrollable: function (element, index, meta, stack) {
|
||||
var direction = converter[typeof (meta[3]) === "string" && meta[3].toLowerCase()] || converter.both;
|
||||
var styles = (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(element, null) : element.currentStyle);
|
||||
var overflow = {
|
||||
x: scrollValue[styles.overflowX.toLowerCase()] || false,
|
||||
y: scrollValue[styles.overflowY.toLowerCase()] || false,
|
||||
isRoot: rootrx.test(element.nodeName)
|
||||
};
|
||||
|
||||
// check if completely unscrollable (exclude HTML element because it's special)
|
||||
if (!overflow.x && !overflow.y && !overflow.isRoot)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var size = {
|
||||
height: {
|
||||
scroll: element.scrollHeight,
|
||||
client: element.clientHeight
|
||||
},
|
||||
width: {
|
||||
scroll: element.scrollWidth,
|
||||
client: element.clientWidth
|
||||
},
|
||||
// check overflow.x/y because iPad (and possibly other tablets) don't dislay scrollbars
|
||||
scrollableX: function () {
|
||||
return (overflow.x || overflow.isRoot) && this.width.scroll > this.width.client;
|
||||
},
|
||||
scrollableY: function () {
|
||||
return (overflow.y || overflow.isRoot) && this.height.scroll > this.height.client;
|
||||
}
|
||||
};
|
||||
return direction.y && size.scrollableY() || direction.x && size.scrollableX();
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
/*!
|
||||
* Crew manifest script
|
||||
*/
|
||||
|
||||
var minimap_height = 480;
|
||||
var scale_x;
|
||||
var scale_y;
|
||||
var zoom_factor = null;
|
||||
var minimap_mousedown = false;
|
||||
var minimap_mousedown_scrollLeft;
|
||||
var minimap_mousedown_scrollTop;
|
||||
var minimap_mousedown_clientX;
|
||||
var minimap_mousedown_clientY;
|
||||
var minimap_mousedown_counter = 0;
|
||||
|
||||
function disableSelection(){ return false; };
|
||||
|
||||
$(window).on("onUpdateContent", function()
|
||||
{
|
||||
$("#textbased").html("<table><colgroup><col /><col style=\"width: 24px;\" class=\"colhealth\" /><col style=\"width: 180px;\" /></colgroup><thead><tr><td><h3>Name</h3></td><td><h3> </h3></td><td><h3>Position</h3></td></tr></thead><tbody id=\"textbased-tbody\"></tbody></table>");
|
||||
|
||||
$("#minimap").append("<img src=\"minimap_" + z + ".png\" id=\"map\" style=\"width: auto; height: " + minimap_height + "px;\" />");
|
||||
|
||||
$("body")[0].onselectstart = disableSelection;
|
||||
|
||||
$("#minimap").on("click", function(e)
|
||||
{
|
||||
if (!$(e.target).is(".zoom,.dot"))
|
||||
{
|
||||
var x = ((((e.clientX + this.scrollLeft - 8) / scale_x) / tile_size) + 1).toFixed(0);
|
||||
var y = ((maxy - (((e.clientY + this.scrollTop - 8) / scale_y) / tile_size)) + 1).toFixed(0);
|
||||
|
||||
window.location.href = "byond://?src=" + hSrc + "&action=select_position&x=" + x + "&y=" + y;
|
||||
}
|
||||
}).on("mousedown", function(e)
|
||||
{
|
||||
minimap_mousedown_scrollLeft = this.scrollLeft;
|
||||
minimap_mousedown_scrollTop = this.scrollTop;
|
||||
minimap_mousedown_clientX = e.clientX;
|
||||
minimap_mousedown_clientY = e.clientY;
|
||||
|
||||
var c = ++minimap_mousedown_counter;
|
||||
setTimeout(function()
|
||||
{
|
||||
if (c == minimap_mousedown_counter)
|
||||
{
|
||||
minimap_mousedown = true;
|
||||
$("#minimap").css("cursor", "move");
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
$(document).on("mousemove", function(e)
|
||||
{
|
||||
if (minimap_mousedown)
|
||||
{
|
||||
var offsetX = minimap_mousedown_clientX - e.clientX;
|
||||
var offsetY = minimap_mousedown_clientY - e.clientY;
|
||||
|
||||
var minimap = document.getElementById("minimap");
|
||||
minimap.scrollLeft = minimap_mousedown_scrollLeft + offsetX;
|
||||
minimap.scrollTop = minimap_mousedown_scrollTop + offsetY;
|
||||
}
|
||||
}).on("mouseup", function()
|
||||
{
|
||||
++minimap_mousedown_counter;
|
||||
if (minimap_mousedown)
|
||||
{
|
||||
document.body.focus();
|
||||
minimap_mousedown = false;
|
||||
$("#minimap").css("cursor", "");
|
||||
}
|
||||
});
|
||||
|
||||
$(window).on("resize", onResize);
|
||||
|
||||
scaleMinimap(1.00);
|
||||
});
|
||||
|
||||
function zoomIn()
|
||||
{
|
||||
scaleMinimap(Math.min(6.00, zoom_factor + 1.00));
|
||||
}
|
||||
|
||||
function zoomOut()
|
||||
{
|
||||
scaleMinimap(Math.max(1.00, zoom_factor - 1.00));
|
||||
}
|
||||
|
||||
function scaleMinimap(factor)
|
||||
{
|
||||
var $minimap = $("#minimap");
|
||||
|
||||
if (factor != zoom_factor)
|
||||
{
|
||||
zoom_factor = factor;
|
||||
|
||||
var old_map_width = $minimap.width();
|
||||
var old_map_height = $minimap.height();
|
||||
var old_canvas_size = $("#minimap > img").height(); // height is assumed to be the same
|
||||
var new_canvas_size = minimap_height * factor; // ditto
|
||||
|
||||
var old_scrollLeft = $minimap[0].scrollLeft;
|
||||
var old_scrollTop = $minimap[0].scrollTop;
|
||||
|
||||
var old_factor = old_canvas_size / minimap_height;
|
||||
var diff_factor = factor - old_factor;
|
||||
|
||||
var old_centerX = ((old_map_width / 2) * diff_factor) + old_scrollLeft;
|
||||
var old_centerY = ((old_map_height / 2) * diff_factor) + old_scrollTop;
|
||||
|
||||
$("#minimap > img").css("height", new_canvas_size + "px");
|
||||
$minimap.css("max-width", new_canvas_size + "px");
|
||||
|
||||
var new_map_width = $minimap.width();
|
||||
var new_map_height = $minimap.height();
|
||||
|
||||
var new_centerX = (new_map_width / 2) + old_centerX;
|
||||
var new_centerY = (new_map_height / 2) + old_centerY;
|
||||
|
||||
var scrollLeft = new_centerX - (new_map_width / 2);
|
||||
var scrollTop = new_centerY - (new_map_height / 2);
|
||||
|
||||
scale_x = new_canvas_size / (maxx * tile_size);
|
||||
scale_y = new_canvas_size / (maxy * tile_size);
|
||||
|
||||
onResize();
|
||||
|
||||
$minimap[0].scrollLeft = scrollLeft;
|
||||
$minimap[0].scrollTop = scrollTop;
|
||||
|
||||
$(".dot").each(function()
|
||||
{
|
||||
var $this = $(this);
|
||||
var tx = translateX(parseInt($this.attr("data-x")));
|
||||
var ty = translateY(parseInt($this.attr("data-y")));
|
||||
|
||||
// Workaround for IE bug where it doesn't modify the positions.
|
||||
setTimeout(function(){ $this.css({ "top": ty + "px", "left": tx + "px" });}, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onResize()
|
||||
{
|
||||
if (zoom_factor == 1.00)
|
||||
{
|
||||
$(".zoom").css("left", "442px");
|
||||
$("#minimap").css("max-height", Math.min($(window).height() - 16, 480) + "px");
|
||||
}
|
||||
else
|
||||
{
|
||||
$(".zoom").css("left", ($("#minimap").width() - 34) + "px");
|
||||
$("#minimap").css("max-height", Math.min($(window).height() - 16, $("#minimap > img").height()) + "px");
|
||||
}
|
||||
|
||||
if (expandHealth())
|
||||
{
|
||||
$(".colhealth").css("width", "150px");
|
||||
$(".health").removeClass("tt");
|
||||
}
|
||||
else
|
||||
{
|
||||
$(".colhealth").css("width", "24px");
|
||||
$(".health").addClass("tt");
|
||||
}
|
||||
|
||||
$("body").css("padding-left", Math.min($(window).width() - 400, $("#minimap").width() - 10) + "px");
|
||||
}
|
||||
|
||||
function expandHealth()
|
||||
{
|
||||
return $("#textbased").width() > 510;
|
||||
}
|
||||
|
||||
var updateMap = true;
|
||||
|
||||
function switchTo(i)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
$("#minimap").hide();
|
||||
$("#textbased").show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#textbased").hide();
|
||||
$("#minimap").show();
|
||||
}
|
||||
}
|
||||
|
||||
var orig_scrollTop = 0;
|
||||
|
||||
function clearAll()
|
||||
{
|
||||
orig_scrollTop = $(window).scrollTop();
|
||||
$("#textbased-tbody").empty();
|
||||
$("#minimap .dot").remove();
|
||||
}
|
||||
|
||||
function onAfterUpdate()
|
||||
{
|
||||
$(window).scrollTop(orig_scrollTop);
|
||||
}
|
||||
|
||||
function isHead(ijob)
|
||||
{
|
||||
return (ijob % 10 == 0); // head roles always end in 0
|
||||
}
|
||||
|
||||
function getColor(ijob)
|
||||
{
|
||||
if (ijob == 0) { return "#C06616"; } // captain
|
||||
else if (ijob >= 10 && ijob < 20) { return "#E74C3C"; } // security
|
||||
else if (ijob >= 20 && ijob < 30) { return "#3498DB"; } // medical
|
||||
else if (ijob >= 30 && ijob < 40) { return "#9B59B6"; } // science
|
||||
else if (ijob >= 40 && ijob < 50) { return "#F1C40F"; } // engineering
|
||||
else if (ijob >= 50 && ijob < 60) { return "#F39C12"; } // cargo
|
||||
else if (ijob >= 200 && ijob < 230) { return "#00C100"; } // CentCom
|
||||
else { return "#C38312"; } // other / unknown
|
||||
}
|
||||
|
||||
function add(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area, pos_x, pos_y, in_range)
|
||||
{
|
||||
try { ijob = parseInt(ijob); }
|
||||
catch (ex) { ijob = 0; }
|
||||
|
||||
var ls = "";
|
||||
|
||||
if (life_status === null) { ls = (life_status ? "<span class=\"bad\">Deceased</span>" : "<span class=\"good\">Living</span>"); }
|
||||
|
||||
var healthHTML = "";
|
||||
|
||||
if (dam1 != "" || dam2 != "" || dam3 != "" || dam4 != "")
|
||||
{
|
||||
var avg_dam = parseInt(dam1) + parseInt(dam2) + parseInt(dam3) + parseInt(dam4);
|
||||
var i;
|
||||
|
||||
if (avg_dam <= 0) { i = 5; }
|
||||
else if (avg_dam <= 25) { i = 4; }
|
||||
else if (avg_dam <= 50) { i = 3; }
|
||||
else if (avg_dam <= 75) { i = 2; }
|
||||
else { i = 0; }
|
||||
|
||||
healthHTML = "<div class=\"health health-" + i + (expandHealth() ? "" : " tt") + "\"><div><span>(<font color=\"#3498db\">" + dam1 + "</font>/<font color=\"#2ecc71\">" + dam2 + "</font>/<font color=\"#e67e22\">" + dam3 + "</font>/<font color=\"#e74c3c\">" + dam4 + "</font>)</span></div></div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
healthHTML = "<div class=\"health health-" + (life_status == "" ? -1 : (life_status == "true" ? 4 : 0)) + (expandHealth() ? "" : " tt") + "\"><div><span>Not Available</span></div></div>";
|
||||
}
|
||||
|
||||
var trElem = $("<tr></tr>").attr("data-ijob", ijob);
|
||||
var tdElem;
|
||||
var spanElem;
|
||||
|
||||
tdElem = $("<td></td>");
|
||||
|
||||
var italics = false;
|
||||
|
||||
if (name.length >= 7 && name.substring(0, 3) == "<i>")
|
||||
{
|
||||
name = name.substring(3, name.length - 4);
|
||||
italics = true;
|
||||
}
|
||||
|
||||
spanElem = $("<span></span>").text(name);
|
||||
|
||||
if (italics)
|
||||
{
|
||||
spanElem.css("font-style", "italic");
|
||||
}
|
||||
|
||||
if (isHead(ijob)) { spanElem.css("font-weight", "bold"); }
|
||||
|
||||
var color = getColor(ijob);
|
||||
|
||||
if (color) { spanElem.css("color", color); }
|
||||
|
||||
tdElem.append(spanElem);
|
||||
|
||||
if (assignment) { tdElem.append($("<span></span>").text(" (" + assignment + ")")); }
|
||||
|
||||
trElem.append(tdElem);
|
||||
|
||||
tdElem = $("<td style=\"vertical-align: top; cursor: default;\"></td>");
|
||||
tdElem.html(healthHTML);
|
||||
|
||||
trElem.append(tdElem);
|
||||
|
||||
tdElem = $("<td style=\"cursor: default;\"></td>");
|
||||
|
||||
if (area && pos_x && pos_y)
|
||||
{
|
||||
tdElem.append($("<div></div>").text(area).addClass("tt").append($("<div></div>").append($("<span></span>").text("(" + pos_x + ", " + pos_y + ")"))));
|
||||
tdElem.css("cursor", "pointer").on("click", function()
|
||||
{
|
||||
window.clipboardData.setData("Text", pos_x + ", " + pos_y);
|
||||
});
|
||||
}
|
||||
else { tdElem.text("Not Available"); }
|
||||
|
||||
trElem.append(tdElem);
|
||||
|
||||
var item = $("#textbased-tbody > tr").filter(function(){ return parseInt($(this).attr("data-ijob")) >= ijob; }).eq(0);
|
||||
|
||||
if (item.length > 0) { trElem.insertBefore(item); }
|
||||
else { $("#textbased-tbody").append(trElem); }
|
||||
|
||||
if (updateMap && pos_x && pos_y && (in_range == "1"))
|
||||
{
|
||||
var x = parseInt(pos_x);
|
||||
var y = maxy - parseInt(pos_y);
|
||||
|
||||
var tx = translateX(x);
|
||||
var ty = translateY(y);
|
||||
|
||||
var dotElem = $("<div class=\"dot\" style=\"top: " + ty + "px; left: " + tx + "px; background-color: " + color + "; z-index: " + ijob + ";\" data-x=\"" + x + "\" data-y=\"" + y + "\"></div>");
|
||||
|
||||
$("#minimap").append(dotElem);
|
||||
|
||||
var counter = 0;
|
||||
|
||||
function enable()
|
||||
{
|
||||
++counter;
|
||||
dotElem.addClass("active").css({ "border-color": color });
|
||||
}
|
||||
|
||||
function disable()
|
||||
{
|
||||
++counter;
|
||||
dotElem.removeClass("active").css({ "border-color": "transparent" });
|
||||
}
|
||||
|
||||
function click(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
window.location.href = "byond://?src=" + hSrc + "&action=select_person&name=" + encodeURIComponent(name);
|
||||
}
|
||||
|
||||
trElem.on("mouseover", function()
|
||||
{
|
||||
enable();
|
||||
|
||||
if (zoom_factor > 1.00)
|
||||
{
|
||||
var c = counter;
|
||||
setTimeout(function()
|
||||
{
|
||||
if (c == counter)
|
||||
{
|
||||
var minimap = document.getElementById("minimap");
|
||||
var half = $(minimap).height() / 2;
|
||||
var offset = $(dotElem).offset();
|
||||
|
||||
minimap.scrollLeft = offset.left + minimap.scrollLeft - half;
|
||||
minimap.scrollTop = offset.top + minimap.scrollTop - half;
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}).on("mouseout", disable).on("click", click);
|
||||
dotElem.on("mouseover", function()
|
||||
{
|
||||
trElem.addClass("hover");
|
||||
enable();
|
||||
trElem.scrollintoview();
|
||||
}).on("mouseout", function()
|
||||
{
|
||||
trElem.removeClass("hover");
|
||||
disable();
|
||||
}).on("click", click);
|
||||
}
|
||||
}
|
||||
|
||||
function translateX(n) { return (translate(n - 1.5, scale_x) ).toFixed(0); }
|
||||
function translateY(n) { return (translate(n + 0.75, scale_y) ).toFixed(0); }
|
||||
|
||||
function translate(n, scale)
|
||||
{
|
||||
return (n * tile_size) * scale;
|
||||
}
|
||||
@@ -34,19 +34,7 @@
|
||||
charges--
|
||||
insisting = 0
|
||||
|
||||
user.dna.add_mutation(HULK)
|
||||
user.dna.add_mutation(XRAY)
|
||||
user.dna.add_mutation(COLDRES)
|
||||
user.dna.add_mutation(TK)
|
||||
|
||||
user.mind.special_role = "Avatar of the Wish Granter"
|
||||
|
||||
var/datum/objective/hijack/hijack = new
|
||||
hijack.owner = user.mind
|
||||
user.mind.objectives += hijack
|
||||
user.mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
|
||||
user.mind.announce_objectives()
|
||||
user.mind.add_antag_datum(/datum/antagonist/wishgranter)
|
||||
|
||||
to_chat(user, "You have a very bad feeling about this.")
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
var/ghetto = FALSE
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
var/datum/component/mobhook
|
||||
|
||||
/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
@@ -84,7 +85,7 @@
|
||||
/obj/item/twohanded/rcl/Destroy()
|
||||
QDEL_NULL(loaded)
|
||||
last = null
|
||||
active = FALSE
|
||||
setActive(FALSE, null) // setactive(FALSE) removes mobhook
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/rcl/update_icon()
|
||||
@@ -115,18 +116,19 @@
|
||||
QDEL_NULL(loaded)
|
||||
loaded = null
|
||||
unwield(user)
|
||||
active = wielded
|
||||
setActive(wielded, user)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/twohanded/rcl/dropped(mob/wearer)
|
||||
..()
|
||||
active = FALSE
|
||||
if(mobhook)
|
||||
setActive(FALSE, mobhook.parent)
|
||||
last = null
|
||||
|
||||
/obj/item/twohanded/rcl/attack_self(mob/user)
|
||||
..()
|
||||
active = wielded
|
||||
setActive(wielded, user)
|
||||
if(!active)
|
||||
last = null
|
||||
else if(!last)
|
||||
@@ -135,9 +137,15 @@
|
||||
last = C
|
||||
break
|
||||
|
||||
/obj/item/twohanded/rcl/on_mob_move(direct, mob/user)
|
||||
if(active)
|
||||
trigger(user)
|
||||
/obj/item/twohanded/rcl/proc/setActive(toggle, mob/user)
|
||||
active = toggle
|
||||
if (active && user)
|
||||
if (mobhook && mobhook.parent != user)
|
||||
QDEL_NULL(mobhook)
|
||||
if (!mobhook)
|
||||
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/trigger, user))
|
||||
else
|
||||
QDEL_NULL(mobhook)
|
||||
|
||||
/obj/item/twohanded/rcl/proc/trigger(mob/user)
|
||||
if(!isturf(user.loc))
|
||||
@@ -148,7 +156,7 @@
|
||||
|
||||
if(prob(2) && ghetto) //Give ghetto RCLs a 2% chance to jam, requiring it to be reactviated manually.
|
||||
to_chat(user, "<span class='warning'>[src]'s wires jam!</span>")
|
||||
active = FALSE
|
||||
setActive(FALSE, user)
|
||||
return
|
||||
else
|
||||
if(last)
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
slot_flags = SLOT_BELT
|
||||
|
||||
/obj/item/device/sensor_device/attack_self(mob/user)
|
||||
GLOB.crewmonitor.show(user) //Proc already exists, just had to call it
|
||||
GLOB.crewmonitor.show(user,src) //Proc already exists, just had to call it
|
||||
|
||||
@@ -202,15 +202,6 @@
|
||||
/obj/proc/check_uplink_validity()
|
||||
return 1
|
||||
|
||||
/obj/proc/on_mob_move(dir, mob, oldLoc, forced)
|
||||
return
|
||||
|
||||
/obj/proc/on_mob_turn(dir, mob)
|
||||
return
|
||||
|
||||
/obj/proc/intercept_user_move(dir, mob, newLoc, oldLoc)
|
||||
return
|
||||
|
||||
/obj/vv_get_dropdown()
|
||||
. = ..()
|
||||
.["Delete all of type"] = "?_src_=vars;[HrefToken()];delall=[REF(src)]"
|
||||
|
||||
@@ -139,12 +139,13 @@
|
||||
return 1
|
||||
if(..())
|
||||
return 1
|
||||
if(intact && istype(C, /obj/item/crowbar))
|
||||
return pry_tile(C, user)
|
||||
if(intact && istype(C, /obj/item/stack/tile))
|
||||
try_replace_tile(C, user, params)
|
||||
return 0
|
||||
|
||||
/turf/open/floor/crowbar_act(mob/living/user, obj/item/I)
|
||||
return intact ? pry_tile(I, user) : FALSE
|
||||
|
||||
/turf/open/floor/proc/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
if(T.turf_type == type)
|
||||
return
|
||||
|
||||
@@ -17,12 +17,8 @@
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>There's a few <b>screws</b> and a <b>small crack</b> visible.</span>")
|
||||
|
||||
/turf/open/floor/wood/attackby(obj/item/C, mob/user, params)
|
||||
if(..())
|
||||
return
|
||||
if(istype(C, /obj/item/screwdriver))
|
||||
pry_tile(C, user)
|
||||
return
|
||||
/turf/open/floor/wood/screwdriver_act(mob/living/user, obj/item/I)
|
||||
return pry_tile(I, user)
|
||||
|
||||
/turf/open/floor/wood/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
if(T.turf_type == type)
|
||||
@@ -38,9 +34,8 @@
|
||||
P.attackby(T, user, params)
|
||||
|
||||
/turf/open/floor/wood/pry_tile(obj/item/C, mob/user, silent = FALSE)
|
||||
var/is_screwdriver = istype(C, /obj/item/screwdriver)
|
||||
C.play_tool_sound(src, 80)
|
||||
return remove_tile(user, silent, make_tile = is_screwdriver)
|
||||
return remove_tile(user, silent, (C.tool_behaviour == TOOL_SCREWDRIVER))
|
||||
|
||||
/turf/open/floor/wood/remove_tile(mob/user, silent = FALSE, make_tile = TRUE)
|
||||
if(broken || burnt)
|
||||
@@ -80,7 +75,7 @@
|
||||
update_icon()
|
||||
|
||||
/turf/open/floor/grass/attackby(obj/item/C, mob/user, params)
|
||||
if(istype(C, /obj/item/shovel) && params)
|
||||
if((C.tool_behaviour == TOOL_SHOVEL) && params)
|
||||
new ore_type(src, 2)
|
||||
user.visible_message("[user] digs up [src].", "<span class='notice'>You [turfverb] [src].</span>")
|
||||
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
|
||||
@@ -99,10 +94,11 @@
|
||||
initial_gas_mix = "o2=22;n2=82;TEMP=180"
|
||||
slowdown = 2
|
||||
|
||||
/turf/open/floor/grass/snow/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/crowbar))//You need to dig this turf out instead of crowbarring it
|
||||
return
|
||||
..()
|
||||
/turf/open/floor/grass/snow/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/grass/snow/crowbar_act(mob/living/user, obj/item/I)
|
||||
return
|
||||
|
||||
/turf/open/floor/grass/snow/basalt //By your powers combined, I am captain planet
|
||||
name = "volcanic floor"
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
if(exposed_temperature > 300)
|
||||
PlasmaBurn(exposed_temperature)
|
||||
|
||||
/turf/open/floor/mineral/plasma/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
/turf/open/floor/mineral/plasma/attackby(obj/item/W, mob/user, params)
|
||||
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
|
||||
message_admins("Plasma flooring was ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
|
||||
log_game("Plasma flooring was ignited by [key_name(user)] in [COORD(src)]")
|
||||
|
||||
@@ -196,6 +196,9 @@
|
||||
flick_overlay(I, viewing, 8)
|
||||
L.adjustToxLoss(-3, TRUE, TRUE)
|
||||
|
||||
/turf/open/floor/clockwork/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/clockwork/crowbar_act(mob/living/user, obj/item/I)
|
||||
if(baseturfs == type)
|
||||
return TRUE
|
||||
|
||||
@@ -123,3 +123,6 @@
|
||||
/turf/open/floor/plating/foam/ex_act()
|
||||
..()
|
||||
ScrapeAway()
|
||||
|
||||
/turf/open/floor/plating/foam/tool_act(mob/living/user, obj/tool/I, tool_type)
|
||||
return
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
if(LAZYLEN(archdrops))
|
||||
AddComponent(/datum/component/archaeology, 100, archdrops)
|
||||
|
||||
|
||||
/turf/open/floor/plating/asteroid/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/plating/asteroid/burn_tile()
|
||||
return
|
||||
|
||||
|
||||
@@ -10,3 +10,6 @@
|
||||
|
||||
/turf/open/floor/plating/dirt/dark
|
||||
icon_state = "greenerdirt"
|
||||
|
||||
/turf/open/floor/plating/dirt/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
/turf/open/floor/plating/abductor2/burn_tile()
|
||||
return //unburnable
|
||||
|
||||
/turf/open/floor/plating/abductor2/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/plating/astplate
|
||||
icon_state = "asteroidplating"
|
||||
@@ -49,6 +51,9 @@
|
||||
icon = smooth_icon
|
||||
. = ..()
|
||||
|
||||
/turf/open/floor/plating/ashplanet/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/plating/ashplanet/break_tile()
|
||||
return
|
||||
|
||||
@@ -84,6 +89,9 @@
|
||||
flags_1 = NONE
|
||||
attachment_holes = FALSE
|
||||
|
||||
/turf/open/floor/plating/beach/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/plating/beach/ex_act(severity, target)
|
||||
contents_explosion(severity, target)
|
||||
|
||||
@@ -122,6 +130,9 @@
|
||||
/turf/open/floor/plating/ironsand/burn_tile()
|
||||
return
|
||||
|
||||
/turf/open/floor/plating/ironsand/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/plating/ice
|
||||
name = "ice sheet"
|
||||
desc = "A sheet of solid ice. Looks slippery."
|
||||
@@ -135,6 +146,9 @@
|
||||
wet = TURF_WET_PERMAFROST
|
||||
attachment_holes = FALSE
|
||||
|
||||
/turf/open/floor/plating/ice/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/plating/ice/HandleWet()
|
||||
if(wet == TURF_WET_ICE)
|
||||
return
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
..()
|
||||
return //unplateable
|
||||
|
||||
/turf/open/floor/engine/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
|
||||
/turf/open/floor/engine/crowbar_act(mob/living/user, obj/item/I)
|
||||
return
|
||||
|
||||
/turf/open/floor/engine/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You begin removing rods...</span>")
|
||||
if(I.use_tool(src, user, 30, volume=80))
|
||||
|
||||
@@ -286,26 +286,22 @@
|
||||
newmob.real_name = newmob.dna.species.random_name(newmob.gender,1)
|
||||
newmob.dna.update_dna_identity()
|
||||
newmob.key = chosen_candidate.key
|
||||
newmob.mind.assigned_role = "CentCom Official"
|
||||
newmob.equipOutfit(/datum/outfit/centcom_official)
|
||||
|
||||
|
||||
//Assign antag status and the mission
|
||||
//Job
|
||||
newmob.mind.assigned_role = "CentCom Official"
|
||||
newmob.mind.special_role = "official"
|
||||
|
||||
//Mission
|
||||
var/datum/objective/missionobj = new
|
||||
missionobj.owner = newmob.mind
|
||||
missionobj.explanation_text = mission
|
||||
missionobj.completed = 1
|
||||
newmob.mind.objectives += missionobj
|
||||
|
||||
newmob.mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
var/datum/antagonist/official/O = new
|
||||
O.mission = missionobj
|
||||
|
||||
if(CONFIG_GET(flag/enforce_human_authority))
|
||||
newmob.set_species(/datum/species/human)
|
||||
|
||||
//Greet the official
|
||||
to_chat(newmob, "<B><font size=3 color=red>You are a CentCom Official.</font></B>")
|
||||
to_chat(newmob, "<BR>Central Command is sending you to [station_name()] with the task: [mission]")
|
||||
newmob.mind.add_antag_datum(O)
|
||||
|
||||
//Logging and cleanup
|
||||
message_admins("CentCom Official [key_name_admin(newmob)] has spawned with the task: [mission]")
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
/datum/antagonist/ert/proc/forge_objectives()
|
||||
if(ert_team)
|
||||
objectives |= ert_team.objectives
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/ert/proc/equipERT()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/antagonist/nightmare
|
||||
name = "Nightmare"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
@@ -0,0 +1,33 @@
|
||||
/datum/antagonist/official
|
||||
name = "CentCom Official"
|
||||
show_name_in_check_antagonists = TRUE
|
||||
show_in_antagpanel = FALSE
|
||||
var/datum/objective/mission
|
||||
|
||||
/datum/antagonist/official/greet()
|
||||
to_chat(owner, "<B><font size=3 color=red>You are a CentCom Official.</font></B>")
|
||||
to_chat(owner, "Central Command is sending you to [station_name()] with the task: [mission.explanation_text]")
|
||||
|
||||
/datum/antagonist/official/proc/equip_official()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
H.equipOutfit(/datum/outfit/centcom_official)
|
||||
|
||||
if(CONFIG_GET(flag/enforce_human_authority))
|
||||
H.set_species(/datum/species/human)
|
||||
|
||||
/datum/antagonist/official/proc/forge_objectives()
|
||||
if(!mission)
|
||||
var/datum/objective/missionobj = new
|
||||
missionobj.owner = owner
|
||||
missionobj.explanation_text = "Conduct a routine preformance review of [station_name()] and its Captain."
|
||||
missionobj.completed = 1
|
||||
mission = missionobj
|
||||
objectives |= mission
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/official/on_gain()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
equip_official()
|
||||
@@ -62,6 +62,15 @@
|
||||
var/perfectsouls = 0 //How many perfect, regen-cap increasing souls the revenant has. //TODO, add objective for getting a perfect soul(s?)
|
||||
var/generated_objectives_and_spells = FALSE
|
||||
|
||||
/mob/living/simple_animal/revenant/Initialize(mapload)
|
||||
. = ..()
|
||||
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/malfunction(null))
|
||||
|
||||
/mob/living/simple_animal/revenant/Login()
|
||||
..()
|
||||
to_chat(src, "<span class='deadsay'><span class='big bold'>You are a revenant.</span></span>")
|
||||
@@ -73,26 +82,10 @@
|
||||
to_chat(src, "<b>Be sure to read the wiki page at https://tgstation13.org/wiki/Revenant to learn more.</b>")
|
||||
if(!generated_objectives_and_spells)
|
||||
generated_objectives_and_spells = TRUE
|
||||
mind.remove_all_antag()
|
||||
mind.wipe_memory()
|
||||
SEND_SOUND(src, sound('sound/effects/ghost.ogg'))
|
||||
var/datum/objective/revenant/objective = new
|
||||
objective.owner = mind
|
||||
mind.objectives += objective
|
||||
to_chat(src, "<b>Objective #1</b>: [objective.explanation_text]")
|
||||
var/datum/objective/revenantFluff/objective2 = new
|
||||
objective2.owner = mind
|
||||
mind.objectives += objective2
|
||||
to_chat(src, "<b>Objective #2</b>: [objective2.explanation_text]")
|
||||
mind.assigned_role = ROLE_REVENANT
|
||||
mind.special_role = ROLE_REVENANT
|
||||
mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/malfunction(null))
|
||||
SEND_SOUND(src, sound('sound/effects/ghost.ogg'))
|
||||
mind.add_antag_datum(/datum/antagonist/revenant)
|
||||
|
||||
//Life, Stat, Hud Updates, and Say
|
||||
/mob/living/simple_animal/revenant/Life()
|
||||
@@ -219,7 +212,7 @@
|
||||
var/reforming_essence = essence_regen_cap //retain the gained essence capacity
|
||||
var/obj/item/ectoplasm/revenant/R = new(get_turf(src))
|
||||
R.essence = max(reforming_essence - 15 * perfectsouls, 75) //minus any perfect souls
|
||||
R.client_to_revive = client //If the essence reforms, the old revenant is put back in the body
|
||||
R.old_key = client.key //If the essence reforms, the old revenant is put back in the body
|
||||
R.revenant = src
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
revealed = FALSE
|
||||
@@ -328,7 +321,7 @@
|
||||
var/essence = 75 //the maximum essence of the reforming revenant
|
||||
var/reforming = TRUE
|
||||
var/inert = FALSE
|
||||
var/client/client_to_revive
|
||||
var/old_key //key of the previous revenant, will have first pick on reform.
|
||||
var/mob/living/simple_animal/revenant/revenant
|
||||
|
||||
/obj/item/ectoplasm/revenant/New()
|
||||
@@ -375,11 +368,11 @@
|
||||
message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.")
|
||||
forceMove(drop_location()) //In case it's in a backpack or someone's hand
|
||||
revenant.forceMove(loc)
|
||||
if(client_to_revive)
|
||||
if(old_key)
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(M.client == client_to_revive) //Only recreates the mob if the mob the client is in is dead
|
||||
revenant.client = client_to_revive
|
||||
key_of_revenant = client_to_revive.key
|
||||
if(M.client && M.client.key == old_key) //Only recreates the mob if the mob the client is in is dead
|
||||
key_of_revenant = old_key
|
||||
break
|
||||
if(!key_of_revenant)
|
||||
message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...")
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to be [revenant.name] (reforming)?", ROLE_REVENANT, null, ROLE_REVENANT, 50, revenant)
|
||||
@@ -390,7 +383,6 @@
|
||||
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
|
||||
return
|
||||
var/client/C = pick(candidates)
|
||||
revenant.client = C
|
||||
key_of_revenant = C.key
|
||||
if(!key_of_revenant)
|
||||
qdel(revenant)
|
||||
@@ -399,8 +391,8 @@
|
||||
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
|
||||
return
|
||||
|
||||
message_admins("[key_of_revenant] has been [client_to_revive ? "re":""]made into a revenant by reforming ectoplasm.")
|
||||
log_game("[key_of_revenant] was [client_to_revive ? "re":""]made as a revenant by reforming ectoplasm.")
|
||||
message_admins("[key_of_revenant] has been [old_key == key_of_revenant ? "re":""]made into a revenant by reforming ectoplasm.")
|
||||
log_game("[key_of_revenant] was [old_key == key_of_revenant ? "re":""]made as a revenant by reforming ectoplasm.")
|
||||
visible_message("<span class='revenboldnotice'>[src] suddenly rises into the air before fading away.</span>")
|
||||
|
||||
revenant.essence = essence
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/datum/antagonist/revenant
|
||||
name = "Revenant"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
|
||||
/datum/antagonist/revenant/greet()
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/revenant/proc/forge_objectives()
|
||||
var/datum/objective/revenant/objective = new
|
||||
objective.owner = owner
|
||||
objectives += objective
|
||||
var/datum/objective/revenantFluff/objective2 = new
|
||||
objective2.owner = owner
|
||||
objectives += objective2
|
||||
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/revenant/on_gain()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/team/nation
|
||||
name = "Nation"
|
||||
|
||||
/datum/antagonist/separatist
|
||||
name = "Separatists"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
var/datum/team/nation/nation
|
||||
|
||||
/datum/antagonist/separatist/create_team(datum/team/nation/new_team)
|
||||
if(!new_team)
|
||||
return
|
||||
nation = new_team
|
||||
|
||||
/datum/antagonist/separatist/get_team()
|
||||
return nation
|
||||
|
||||
/datum/antagonist/separatist/greet()
|
||||
to_chat(owner, "<B>You are a separatist! [nation.name] forever! Protect the sovereignty of your newfound land with your comrades in arms!</B>")
|
||||
@@ -26,6 +26,8 @@
|
||||
new_objective2.explanation_text = "[objective_verb] everyone[summoner ? " else while you're at it":""]."
|
||||
objectives += new_objective2
|
||||
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/slaughter/laughter
|
||||
name = "Laughter demon"
|
||||
objective_verb = "Hug and Tickle"
|
||||
@@ -0,0 +1,39 @@
|
||||
/datum/antagonist/survivalist
|
||||
name = "Survivalist"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
var/greet_message = ""
|
||||
|
||||
/datum/antagonist/survivalist/proc/forge_objectives()
|
||||
var/datum/objective/survive/survive = new
|
||||
survive.owner = owner
|
||||
objectives += survive
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/survivalist/on_gain()
|
||||
owner.special_role = "survivalist"
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/survivalist/greet()
|
||||
to_chat(owner, "<B>You are the survivalist![greet_message]</B>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/survivalist/guns
|
||||
greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way."
|
||||
|
||||
/datum/antagonist/survivalist/guns/forge_objectives()
|
||||
var/datum/objective/steal_five_of_type/summon_guns/guns = new
|
||||
guns.owner = owner
|
||||
objectives += guns
|
||||
..()
|
||||
|
||||
/datum/antagonist/survivalist/magic
|
||||
name = "Amateur Magician"
|
||||
greet_message = "Grow your newfound talent! Grab as many magical artefacts as possible, by any means necessary. Kill anyone who gets in your way."
|
||||
|
||||
/datum/antagonist/survivalist/magic/forge_objectives()
|
||||
var/datum/objective/steal_five_of_type/summon_magic/magic = new
|
||||
magic.owner = owner
|
||||
objectives += magic
|
||||
..()
|
||||
@@ -0,0 +1,24 @@
|
||||
/datum/antagonist/heartbreaker
|
||||
name = "heartbreaker"
|
||||
roundend_category = "valentines"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
|
||||
|
||||
/datum/antagonist/heartbreaker/proc/forge_objectives()
|
||||
var/datum/objective/martyr/normiesgetout = new
|
||||
normiesgetout.owner = owner
|
||||
objectives += normiesgetout
|
||||
owner.objectives += objectives
|
||||
|
||||
/datum/antagonist/heartbreaker/on_gain()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/heartbreaker/on_removal()
|
||||
owner.objectives -= objectives
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/heartbreaker/greet()
|
||||
to_chat(owner, "<span class='warning'><B>You didn't get a date! They're all having fun without you! you'll show them though...</B></span>")
|
||||
owner.announce_objectives()
|
||||
@@ -0,0 +1,37 @@
|
||||
/datum/antagonist/valentine
|
||||
name = "valentine"
|
||||
roundend_category = "valentines" //there's going to be a ton of them so put them in separate category
|
||||
show_in_antagpanel = FALSE
|
||||
var/datum/mind/date
|
||||
|
||||
/datum/antagonist/valentine/proc/forge_objectives()
|
||||
var/datum/objective/protect/protect_objective = new /datum/objective/protect
|
||||
protect_objective.owner = owner
|
||||
protect_objective.target = date
|
||||
protect_objective.explanation_text = "Protect [date.name], your date."
|
||||
objectives += protect_objective
|
||||
owner.objectives += objectives
|
||||
|
||||
/datum/antagonist/valentine/on_gain()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/valentine/on_removal()
|
||||
owner.objectives -= objectives
|
||||
|
||||
/datum/antagonist/valentine/greet()
|
||||
to_chat(owner, "<span class='warning'><B>You're on a date with [date.name]! Protect them at all costs. This takes priority over all other loyalties.</B></span>")
|
||||
|
||||
//Squashed up a bit
|
||||
/datum/antagonist/valentine/roundend_report()
|
||||
var/objectives_complete = TRUE
|
||||
if(owner.objectives.len)
|
||||
for(var/datum/objective/objective in owner.objectives)
|
||||
if(!objective.check_completion())
|
||||
objectives_complete = FALSE
|
||||
break
|
||||
|
||||
if(objectives_complete)
|
||||
return "<span class='greentext big'>[owner.name] protected their date</span>"
|
||||
else
|
||||
return "<span class='redtext big'>[owner.name] date failed!</span>"
|
||||
@@ -0,0 +1,29 @@
|
||||
/datum/antagonist/wishgranter
|
||||
name = "Wishgranter Avatar"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
|
||||
/datum/antagonist/wishgranter/proc/forge_objectives()
|
||||
var/datum/objective/hijack/hijack = new
|
||||
hijack.owner = owner
|
||||
objectives += hijack
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/wishgranter/on_gain()
|
||||
owner.special_role = "Avatar of the Wish Granter"
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
give_powers()
|
||||
|
||||
/datum/antagonist/wishgranter/greet()
|
||||
to_chat(owner, "<B>Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!</B>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/wishgranter/proc/give_powers()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
H.dna.add_mutation(HULK)
|
||||
H.dna.add_mutation(XRAY)
|
||||
H.dna.add_mutation(COLDRES)
|
||||
H.dna.add_mutation(TK)
|
||||
@@ -113,14 +113,7 @@
|
||||
if("To Kill")
|
||||
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.")
|
||||
user.mind.special_role = ROLE_TRAITOR
|
||||
|
||||
var/datum/objective/hijack/hijack = new
|
||||
hijack.owner = user.mind
|
||||
user.mind.objectives += hijack
|
||||
user.mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
to_chat(user, "<B>Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!</B>")
|
||||
user.mind.announce_objectives()
|
||||
user.mind.add_antag_datum(/datum/antagonist/wishgranter)
|
||||
user.set_species(/datum/species/shadow)
|
||||
if("Peace")
|
||||
to_chat(user, "<B>Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.</B>")
|
||||
|
||||
@@ -338,7 +338,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
/datum/asset/simple/goonchat
|
||||
verify = FALSE
|
||||
assets = list(
|
||||
"jquery.min.js" = 'code/modules/html_interface/js/jquery.min.js',
|
||||
"jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js',
|
||||
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
|
||||
"errorHandler.js" = 'code/modules/goonchat/browserassets/js/errorHandler.js',
|
||||
"browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
|
||||
@@ -350,12 +350,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
|
||||
)
|
||||
|
||||
//Registers HTML Interface assets.
|
||||
/datum/asset/HTML_interface/register()
|
||||
for(var/path in typesof(/datum/html_interface))
|
||||
var/datum/html_interface/hi = new path()
|
||||
hi.registerResources()
|
||||
|
||||
//this exists purely to avoid meta by pre-loading all language icons.
|
||||
/datum/asset/language/register()
|
||||
for(var/path in typesof(/datum/language))
|
||||
|
||||
@@ -49,9 +49,6 @@
|
||||
|
||||
var/obj/screen/click_catcher/void
|
||||
|
||||
// Used by html_interface module.
|
||||
var/hi_last_pos
|
||||
|
||||
var/ip_intel = "Disabled"
|
||||
|
||||
//datum that controls the displaying and hiding of tooltips
|
||||
|
||||
@@ -97,16 +97,19 @@
|
||||
|
||||
var/atom/movable/cached_pull //recipe for disaster again.
|
||||
var/afterForceMove = FALSE
|
||||
var/datum/component/mobhook
|
||||
|
||||
/obj/item/device/flightpack/proc/changeWearer(mob/changeto)
|
||||
if(wearer)
|
||||
LAZYREMOVE(wearer.user_movement_hooks, src)
|
||||
wearer = null
|
||||
QDEL_NULL(mobhook)
|
||||
cached_pull = null
|
||||
if(istype(changeto))
|
||||
wearer = changeto
|
||||
LAZYADD(wearer.user_movement_hooks, src)
|
||||
cached_pull = changeto.pulling
|
||||
mobhook = changeto.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/on_mob_move, changeto))
|
||||
|
||||
/obj/item/device/flightpack/Initialize()
|
||||
ion_trail = new
|
||||
@@ -180,6 +183,7 @@
|
||||
QDEL_NULL(part_laser)
|
||||
QDEL_NULL(part_bin)
|
||||
QDEL_NULL(ion_trail)
|
||||
QDEL_NULL(mobhook)
|
||||
STOP_PROCESSING(SSflightpacks, src)
|
||||
. = ..()
|
||||
|
||||
@@ -205,27 +209,6 @@
|
||||
momentum_y = CLAMP(momentum_y + amounty, -momentum_max, momentum_max)
|
||||
calculate_momentum_speed()
|
||||
|
||||
/obj/item/device/flightpack/intercept_user_move(dir, mob, newLoc, oldLoc)
|
||||
if(!flight)
|
||||
return
|
||||
var/momentum_increment = momentum_gain
|
||||
if(boost)
|
||||
momentum_increment = boost_power
|
||||
if(brake)
|
||||
momentum_increment = 0
|
||||
if(!gravity && !pressure)
|
||||
momentum_increment -= 10
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
adjust_momentum(0, momentum_increment)
|
||||
if(SOUTH)
|
||||
adjust_momentum(0, -momentum_increment)
|
||||
if(EAST)
|
||||
adjust_momentum(momentum_increment, 0)
|
||||
if(WEST)
|
||||
adjust_momentum(-momentum_increment, 0)
|
||||
return ..()
|
||||
|
||||
//The wearer has momentum left. Move them and take some away, while negating the momentum that moving the wearer would gain. Or force the wearer to lose control if they are incapacitated.
|
||||
/obj/item/device/flightpack/proc/momentum_drift()
|
||||
if(!flight || !wearer || (momentum_speed == 0))
|
||||
@@ -252,7 +235,7 @@
|
||||
if(prob(emp_damage * 15))
|
||||
step(wearer, pick(GLOB.alldirs))
|
||||
|
||||
/obj/item/device/flightpack/on_mob_move(dir, mob/mob, turf/oldLoc, forced)
|
||||
/obj/item/device/flightpack/proc/on_mob_move(mob/mob, turf/oldLoc, dir, forced)
|
||||
if(forced)
|
||||
if(cached_pull && istype(oldLoc) && (get_dist(oldLoc, loc) <= 1) && !oldLoc.density)
|
||||
cached_pull.forceMove(oldLoc)
|
||||
@@ -270,7 +253,22 @@
|
||||
afterForceMove = FALSE
|
||||
if(flight)
|
||||
ion_trail.generate_effect()
|
||||
. = ..()
|
||||
var/momentum_increment = momentum_gain
|
||||
if(boost)
|
||||
momentum_increment = boost_power
|
||||
if(brake)
|
||||
momentum_increment = 0
|
||||
if(!gravity && !pressure)
|
||||
momentum_increment -= 10
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
adjust_momentum(0, momentum_increment)
|
||||
if(SOUTH)
|
||||
adjust_momentum(0, -momentum_increment)
|
||||
if(EAST)
|
||||
adjust_momentum(momentum_increment, 0)
|
||||
if(WEST)
|
||||
adjust_momentum(-momentum_increment, 0)
|
||||
|
||||
//Make the wearer lose some momentum.
|
||||
/obj/item/device/flightpack/proc/momentum_decay()
|
||||
|
||||
@@ -585,6 +585,7 @@
|
||||
armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75)
|
||||
item_color = "ancient"
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/datum/component/mobhook
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ancient
|
||||
name = "prototype RIG hardsuit"
|
||||
@@ -596,8 +597,9 @@
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/footstep = 1
|
||||
var/datum/component/mobhook
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ancient/on_mob_move()
|
||||
/obj/item/clothing/suit/space/hardsuit/ancient/proc/on_mob_move()
|
||||
var/mob/living/carbon/human/H = loc
|
||||
if(!istype(H) || H.wear_suit != src)
|
||||
return
|
||||
@@ -607,6 +609,24 @@
|
||||
else
|
||||
footstep++
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ancient/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if (slot == slot_wear_suit)
|
||||
if (mobhook && mobhook.parent != user)
|
||||
QDEL_NULL(mobhook)
|
||||
if (!mobhook)
|
||||
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/on_mob_move))
|
||||
else
|
||||
QDEL_NULL(mobhook)
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ancient/dropped()
|
||||
. = ..()
|
||||
QDEL_NULL(mobhook)
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ancient/Destroy()
|
||||
QDEL_NULL(mobhook) // mobhook is not our component
|
||||
return ..()
|
||||
|
||||
/////////////SHIELDED//////////////////////////////////
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/shielded
|
||||
|
||||
@@ -33,34 +33,19 @@
|
||||
|
||||
|
||||
forge_valentines_objective(L, date)
|
||||
|
||||
forge_valentines_objective(date, L)
|
||||
|
||||
if(valentines.len && prob(4))
|
||||
var/mob/living/notgoodenough = pick_n_take(valentines)
|
||||
forge_valentines_objective(notgoodenough, date)
|
||||
|
||||
|
||||
else
|
||||
to_chat(L, "<span class='warning'><B>You didn't get a date! They're all having fun without you! you'll show them though...</B></span>")
|
||||
var/datum/objective/martyr/normiesgetout = new
|
||||
normiesgetout.owner = L.mind
|
||||
L.mind.special_role = "heartbreaker"
|
||||
L.mind.objectives += normiesgetout
|
||||
L.mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
L.mind.add_antag_datum(/datum/antagonist/heartbreaker)
|
||||
|
||||
/proc/forge_valentines_objective(mob/living/lover,mob/living/date)
|
||||
lover.mind.special_role = "valentine"
|
||||
var/datum/objective/protect/protect_objective = new /datum/objective/protect
|
||||
protect_objective.owner = lover.mind
|
||||
protect_objective.target = date.mind
|
||||
protect_objective.explanation_text = "Protect [date.real_name], your date."
|
||||
lover.mind.objectives += protect_objective
|
||||
|
||||
lover.mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
|
||||
to_chat(lover, "<span class='warning'><B>You're on a date with [date]! Protect them at all costs. This takes priority over all other loyalties.</B></span>")
|
||||
|
||||
var/datum/antagonist/valentine/V = new
|
||||
V.date = date.mind
|
||||
lover.mind.add_antag_datum(V) //These really should be teams but i can't be assed to incorporate third wheels right now
|
||||
|
||||
/datum/round_event/valentines/announce(fake)
|
||||
priority_announce("It's Valentine's Day! Give a valentine to that special someone!")
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
player_mind.transfer_to(S)
|
||||
player_mind.assigned_role = "Nightmare"
|
||||
player_mind.special_role = "Nightmare"
|
||||
player_mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
player_mind.add_antag_datum(/datum/antagonist/nightmare)
|
||||
S.set_species(/datum/species/shadow/nightmare)
|
||||
playsound(S, 'sound/magic/ethereal_exit.ogg', 50, 1, -1)
|
||||
message_admins("[key_name_admin(S)] has been made into a Nightmare by an event.")
|
||||
|
||||
@@ -9,31 +9,34 @@
|
||||
|
||||
var/list/tidecolor
|
||||
var/list/jobs_to_revolt = list()
|
||||
var/nation
|
||||
var/nation_name
|
||||
var/list/citizens = list()
|
||||
|
||||
tidecolor = pick("grey", "white", "yellow", "purple", "brown", "whatevercolorrepresentstheservicepeople")
|
||||
switch(tidecolor)
|
||||
if("grey") //God help you
|
||||
jobs_to_revolt = list("Assistant")
|
||||
nation = pick("Assa", "Mainte", "Tunnel", "Gris", "Grey", "Liath", "Grigio", "Ass", "Assi")
|
||||
nation_name = pick("Assa", "Mainte", "Tunnel", "Gris", "Grey", "Liath", "Grigio", "Ass", "Assi")
|
||||
if("white")
|
||||
jobs_to_revolt = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist")
|
||||
nation = pick("Mede", "Healtha", "Recova", "Chemi", "Geneti", "Viro", "Psych")
|
||||
nation_name = pick("Mede", "Healtha", "Recova", "Chemi", "Geneti", "Viro", "Psych")
|
||||
if("yellow")
|
||||
jobs_to_revolt = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
|
||||
nation = pick("Atomo", "Engino", "Power", "Teleco")
|
||||
nation_name = pick("Atomo", "Engino", "Power", "Teleco")
|
||||
if("purple")
|
||||
jobs_to_revolt = list("Research Director","Scientist", "Roboticist")
|
||||
nation = pick("Sci", "Griffa", "Explosi", "Mecha", "Xeno")
|
||||
nation_name = pick("Sci", "Griffa", "Explosi", "Mecha", "Xeno")
|
||||
if("brown")
|
||||
jobs_to_revolt = list("Quartermaster", "Cargo Technician", "Shaft Miner")
|
||||
nation = pick("Cargo", "Guna", "Suppli", "Mule", "Crate", "Ore", "Mini", "Shaf")
|
||||
nation_name = pick("Cargo", "Guna", "Suppli", "Mule", "Crate", "Ore", "Mini", "Shaf")
|
||||
if("whatevercolorrepresentstheservicepeople") //the few, the proud, the technically aligned
|
||||
jobs_to_revolt = list("Bartender", "Cook", "Botanist", "Clown", "Mime", "Janitor", "Chaplain")
|
||||
nation = pick("Honka", "Boozo", "Fatu", "Danka", "Mimi", "Libra", "Jani", "Religi")
|
||||
nation_name = pick("Honka", "Boozo", "Fatu", "Danka", "Mimi", "Libra", "Jani", "Religi")
|
||||
|
||||
nation += pick("stan", "topia", "land", "nia", "ca", "tova", "dor", "ador", "tia", "sia", "ano", "tica", "tide", "cis", "marea", "co", "taoide", "slavia", "stotzka")
|
||||
nation_name += pick("stan", "topia", "land", "nia", "ca", "tova", "dor", "ador", "tia", "sia", "ano", "tica", "tide", "cis", "marea", "co", "taoide", "slavia", "stotzka")
|
||||
|
||||
var/datum/team/nation/nation = new
|
||||
nation.name = nation_name
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
|
||||
if(H.mind)
|
||||
@@ -42,12 +45,11 @@
|
||||
for(var/job in jobs_to_revolt)
|
||||
if(M.assigned_role == job)
|
||||
citizens += H
|
||||
M.special_role = "separatist"
|
||||
M.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
H.log_message("<font color='red'>Was made into a separatist, long live [nation]!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
to_chat(H, "<B>You are a separatist! [nation] forever! Protect the sovereignty of your newfound land with your comrades in arms!</B>")
|
||||
M.add_antag_datum(/datum/antagonist/separatist,nation)
|
||||
H.log_message("<font color='red'>Was made into a separatist, long live [nation_name]!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
|
||||
if(citizens.len)
|
||||
var/message
|
||||
for(var/job in jobs_to_revolt)
|
||||
message += "[job],"
|
||||
message_admins("The nation of [nation] has been formed. Affected jobs are [message]")
|
||||
message_admins("The nation of [nation_name] has been formed. Affected jobs are [message]")
|
||||
|
||||
@@ -283,15 +283,17 @@
|
||||
var/field_type = /datum/proximity_monitor/advanced/debug
|
||||
var/operating = FALSE
|
||||
var/datum/proximity_monitor/advanced/current = null
|
||||
var/datum/component/mobhook
|
||||
|
||||
/obj/item/device/multitool/field_debug/New()
|
||||
/obj/item/device/multitool/field_debug/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
..()
|
||||
|
||||
/obj/item/device/multitool/field_debug/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
QDEL_NULL(current)
|
||||
..()
|
||||
QDEL_NULL(mobhook)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/multitool/field_debug/proc/setup_debug_field()
|
||||
var/list/new_params = field_params.Copy()
|
||||
@@ -301,12 +303,18 @@
|
||||
/obj/item/device/multitool/field_debug/attack_self(mob/user)
|
||||
operating = !operating
|
||||
to_chat(user, "You turn [src] [operating? "on":"off"].")
|
||||
QDEL_NULL(mobhook)
|
||||
if(!istype(current) && operating)
|
||||
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/on_mob_move))
|
||||
setup_debug_field()
|
||||
else if(!operating)
|
||||
QDEL_NULL(current)
|
||||
|
||||
/obj/item/device/multitool/field_debug/on_mob_move()
|
||||
/obj/item/device/multitool/field_debug/dropped()
|
||||
. = ..()
|
||||
QDEL_NULL(mobhook)
|
||||
|
||||
/obj/item/device/multitool/field_debug/proc/on_mob_move()
|
||||
check_turf(get_turf(src))
|
||||
|
||||
/obj/item/device/multitool/field_debug/process()
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
/datum/playingcard
|
||||
var/name = "playing card"
|
||||
var/card_icon = "card_back"
|
||||
var/suit
|
||||
var/number
|
||||
|
||||
/* Deck */
|
||||
|
||||
/obj/item/deck
|
||||
name = "deck of cards"
|
||||
desc = "A simple deck of playing cards."
|
||||
icon = 'icons/obj/playing_cards.dmi'
|
||||
icon_state = "deck"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
flags_1 = NOBLUDGEON_1
|
||||
|
||||
var/list/cards = list()
|
||||
|
||||
/obj/item/deck/Initialize()
|
||||
. = ..()
|
||||
|
||||
var/cardcolor
|
||||
var/datum/playingcard/card
|
||||
|
||||
for (var/suit in list("spades", "clubs", "diamonds", "hearts"))
|
||||
if (suit == "spades" || suit == "clubs")
|
||||
cardcolor = "black_"
|
||||
else
|
||||
cardcolor = "red_"
|
||||
|
||||
for (var/number in list("ace", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"))
|
||||
card = new()
|
||||
card.name = "[number] of [suit]"
|
||||
card.card_icon = "[cardcolor]num"
|
||||
card.suit = suit
|
||||
card.number = number
|
||||
|
||||
src.cards.Add(card)
|
||||
|
||||
for (var/number in list("jack", "queen", "king"))
|
||||
card = new()
|
||||
card.name = "[number] of [suit]"
|
||||
card.card_icon = "[cardcolor]col"
|
||||
card.suit = suit
|
||||
card.number = number
|
||||
|
||||
src.cards.Add(card)
|
||||
|
||||
for (var/i = 0, i < 2, i++)
|
||||
card = new()
|
||||
card.name = "joker"
|
||||
card.card_icon = "joker"
|
||||
card.suit = "joker"
|
||||
card.number = ""
|
||||
|
||||
src.cards.Add(card)
|
||||
|
||||
/obj/item/deck/attackby(obj/O, mob/user)
|
||||
if (istype(O, /obj/item/hand))
|
||||
var/obj/item/hand/H = O
|
||||
|
||||
for (var/datum/playingcard/P in H.cards)
|
||||
src.cards.Add(P)
|
||||
|
||||
qdel (O)
|
||||
|
||||
user.show_message("You place your cards on the bottom of the deck.")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/deck/attack_self(mob/user)
|
||||
var/list/newcards = list()
|
||||
var/datum/playingcard/card
|
||||
|
||||
while (cards.len)
|
||||
card = pick(cards)
|
||||
newcards.Add(card)
|
||||
src.cards.Remove(card)
|
||||
|
||||
src.cards = newcards
|
||||
|
||||
user.visible_message("\The [user] shuffles [src].")
|
||||
|
||||
/obj/item/deck/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
|
||||
if(flag)
|
||||
return //It's adjacent, is the user, or is on the user's person
|
||||
|
||||
if(isliving(A))
|
||||
src.dealTo(A, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/deck/attack(mob/living/M, mob/living/user, def_zone)
|
||||
if (istype(M))
|
||||
src.dealTo(M, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/deck/proc/dealTo(mob/living/target, mob/living/source)
|
||||
if (!cards.len)
|
||||
source.show_message("There are no cards in the deck.")
|
||||
return
|
||||
|
||||
var/datum/playingcard/card = src.cards[1]
|
||||
|
||||
src.cards.Remove(card)
|
||||
|
||||
var/obj/item/hand/H = new(get_turf(src))
|
||||
|
||||
H.concealed = 1
|
||||
H.update_conceal()
|
||||
|
||||
H.cards.Add(card)
|
||||
H.update_icon()
|
||||
|
||||
source.visible_message("\The [source] deals a card to \the [target].")
|
||||
H.throw_at(get_step(target, target.dir), 10, 1, source)
|
||||
|
||||
/* Hand */
|
||||
|
||||
/obj/item/hand
|
||||
name = "hand of cards"
|
||||
desc = "Some playing cards."
|
||||
icon = 'icons/obj/playing_cards.dmi'
|
||||
icon_state = "empty"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
var/concealed = 0
|
||||
var/blank = 0
|
||||
var/list/cards = list()
|
||||
var/datum/html_interface/hi
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/hand/New(loc)
|
||||
. = ..()
|
||||
|
||||
src.hi = new/datum/html_interface/cards(src, "Your hand", 540, 302)
|
||||
src.update_conceal()
|
||||
|
||||
/obj/item/hand/Destroy()
|
||||
if (src.hi)
|
||||
qdel(src.hi)
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/hand/attackby(obj/O, mob/user)
|
||||
if(cards.len == 1 && istype(O, /obj/item/pen))
|
||||
var/datum/playingcard/P = cards[1]
|
||||
if(!blank)
|
||||
to_chat(user, "You cannot write on that card.")
|
||||
return
|
||||
var/cardtext = sanitize(input(user, "What do you wish to write on the card?", "Card Writing") as text|null, 50)
|
||||
if(!cardtext)
|
||||
return
|
||||
P.name = cardtext
|
||||
blank = 0
|
||||
else if(istype(O, /obj/item/hand))
|
||||
var/obj/item/hand/H = O
|
||||
|
||||
for(var/datum/playingcard/P in src.cards)
|
||||
H.cards.Add(P)
|
||||
|
||||
H.update_icon()
|
||||
|
||||
qdel(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/hand/verb/discard(datum/playingcard/card in cards)
|
||||
set category = "Object"
|
||||
set name = "Discard"
|
||||
set desc = "Place a card from your hand in front of you."
|
||||
|
||||
if (!card)
|
||||
return
|
||||
|
||||
var/obj/item/hand/H = new(src.loc)
|
||||
|
||||
H.concealed = 0
|
||||
H.update_conceal()
|
||||
|
||||
H.cards.Add(card)
|
||||
src.cards.Remove(card)
|
||||
|
||||
H.update_icon()
|
||||
|
||||
ASSERT(H)
|
||||
|
||||
usr.visible_message("\The [usr] plays \the [card.name].")
|
||||
H.forceMove(get_step(usr,usr.dir))
|
||||
|
||||
src.update_icon()
|
||||
|
||||
/obj/item/hand/verb/toggle_conceal()
|
||||
set category = "Object"
|
||||
set name = "Toggle conceal"
|
||||
set desc = "Toggle concealment of your hand"
|
||||
|
||||
src.concealed = !src.concealed
|
||||
|
||||
src.update_conceal()
|
||||
|
||||
usr.visible_message("\The [usr] [concealed ? "conceals" : "reveals"] their hand.")
|
||||
|
||||
src.update_icon()
|
||||
|
||||
/obj/item/hand/attack_self(mob/user)
|
||||
src.hi.show(user)
|
||||
|
||||
/obj/item/hand/examine()
|
||||
. = ..()
|
||||
|
||||
if((!concealed || src.loc == usr) && cards.len)
|
||||
usr.show_message("It contains: ", 1)
|
||||
|
||||
for (var/datum/playingcard/card in cards)
|
||||
usr.show_message("The [card.name].", 1)
|
||||
|
||||
/obj/item/hand/proc/update_conceal()
|
||||
if (src.concealed)
|
||||
src.hi.updateContent("headbar", "You are currently concealing your hand. <a href=\"byond://?src=[REF(hi)]&action=toggle_conceal\">Reveal your hand.</a>")
|
||||
else
|
||||
src.hi.updateContent("headbar", "You are currently revealing your hand. <a href=\"byond://?src=[REF(hi)]&action=toggle_conceal\">Conceal your hand.</a>")
|
||||
|
||||
/obj/item/hand/update_icon()
|
||||
if (!cards.len)
|
||||
qdel (src)
|
||||
else
|
||||
if(cards.len > 1)
|
||||
name = "hand of cards"
|
||||
desc = "Some playing cards."
|
||||
else
|
||||
name = "a playing card"
|
||||
desc = "A playing card."
|
||||
|
||||
cut_overlays()
|
||||
|
||||
if (cards.len == 1)
|
||||
var/datum/playingcard/P = cards[1]
|
||||
var/mutable_appearance/card_overlay = mutable_appearance(icon, (concealed ? "card_back" : "[P.card_icon]") )
|
||||
|
||||
card_overlay.pixel_x = card_overlay.pixel_x + (-5 + rand(10))
|
||||
card_overlay.pixel_y = card_overlay.pixel_y + (-5 + rand(10))
|
||||
|
||||
add_overlay(card_overlay)
|
||||
else
|
||||
var/origin = -12
|
||||
var/offset = round(32 / cards.len)
|
||||
|
||||
var/i = 0
|
||||
var/mutable_appearance/card_overlay
|
||||
|
||||
for(var/datum/playingcard/P in cards)
|
||||
card_overlay = mutable_appearance(icon, (concealed ? "card_back" : P.card_icon))
|
||||
card_overlay.pixel_x = origin + (offset * i)
|
||||
|
||||
add_overlay(card_overlay)
|
||||
i = i + 1
|
||||
|
||||
var/html = ""
|
||||
|
||||
for(var/datum/playingcard/card in cards)
|
||||
html = html + "<a href=\"byond://?src=[REF(src.hi)]&action=play_card&card=[REF(card)]\" class=\"card [card.suit] [card.number]\"></a>"
|
||||
|
||||
src.hi.updateContent("hand", html)
|
||||
|
||||
/obj/item/hand/Topic(href, href_list[], datum/html_interface_client/hclient)
|
||||
if (istype(hclient))
|
||||
switch (href_list["action"])
|
||||
if ("play_card")
|
||||
var/datum/playingcard/card = locate(href_list["card"]) in cards
|
||||
if (card && istype(card))
|
||||
src.discard(card)
|
||||
if ("toggle_conceal")
|
||||
src.toggle_conceal()
|
||||
|
||||
// Hook for html_interface module to prevent updates to clients who don't have this in their inventory.
|
||||
/obj/item/hand/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi)
|
||||
return (hclient.client.mob && hclient.client.mob.stat == 0 && (src in hclient.client.mob.contents))
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
// which is licensed under CC BY-NC-SA 2.0, the full text of which can be found at the following URL:
|
||||
// https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode
|
||||
// Original code by Zuhayr, Polaris Station, ported with modifications
|
||||
|
||||
/datum/playingcard
|
||||
var/name = "playing card"
|
||||
var/card_icon = "card_back"
|
||||
var/suit
|
||||
var/number
|
||||
|
||||
/obj/item/toy/cards/deck/cas
|
||||
name = "\improper CAS deck (white)"
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
/turf/open/floor/holofloor/attackby(obj/item/I, mob/living/user)
|
||||
return // HOLOFLOOR DOES NOT GIVE A FUCK
|
||||
|
||||
/turf/open/floor/holofloor/tool_act(mob/living/user, obj/item/I, tool_type)
|
||||
return
|
||||
|
||||
/turf/open/floor/holofloor/burn_tile()
|
||||
return //you can't burn a hologram!
|
||||
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
html, body, div.wrapper > table
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
background-color: #EAEAEA;
|
||||
font-family: verdana,Geneva,sans-serif;
|
||||
font-size: 12px;
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
color: #5353B1;
|
||||
}
|
||||
|
||||
div.wrapper
|
||||
{
|
||||
position: absolute; top: 24px; left: 0px; right: 0px; bottom: 0px;
|
||||
}
|
||||
|
||||
div#headbar
|
||||
{
|
||||
background-color: #B2B2B2;
|
||||
border-bottom: 1px solid #C2C2C2;
|
||||
height: 24px;
|
||||
padding: 4px 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div#hand
|
||||
{
|
||||
padding: 8px 8px;
|
||||
padding-bottom: 4px;
|
||||
background-color: #EAEAEA;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a.card
|
||||
{
|
||||
display: inline-block;
|
||||
margin: 0px 2px;
|
||||
|
||||
background-image: url(cards.png);
|
||||
background-repeat: no-repeat;
|
||||
width: 94px;
|
||||
height: 129px;
|
||||
|
||||
box-sizing: border-box;
|
||||
background-position: 0px 0px;
|
||||
background-origin: border-box;
|
||||
|
||||
text-decoration: none;
|
||||
font-size: 0px;
|
||||
}
|
||||
|
||||
a.card.clubs.ten { background-position: -5px -5px; }
|
||||
a.card.diamonds.ten { background-position: -109px -5px; }
|
||||
a.card.hearts.ten { background-position: -213px -5px; }
|
||||
a.card.spades.ten { background-position: -317px -5px; }
|
||||
a.card.clubs.two { background-position: -421px -5px; }
|
||||
a.card.diamonds.two { background-position: -525px -5px; }
|
||||
a.card.hearts.two { background-position: -629px -5px; }
|
||||
a.card.spades.two { background-position: -733px -5px; }
|
||||
a.card.clubs.three { background-position: -5px -144px; }
|
||||
a.card.diamonds.three { background-position: -109px -144px; }
|
||||
a.card.hearts.three { background-position: -213px -144px; }
|
||||
a.card.spades.three { background-position: -317px -144px; }
|
||||
a.card.clubs.four { background-position: -421px -144px; }
|
||||
a.card.diamonds.four { background-position: -525px -144px; }
|
||||
a.card.hearts.four { background-position: -629px -144px; }
|
||||
a.card.spades.four { background-position: -733px -144px; }
|
||||
a.card.clubs.five { background-position: -5px -283px; }
|
||||
a.card.diamonds.five { background-position: -109px -283px; }
|
||||
a.card.hearts.five { background-position: -213px -283px; }
|
||||
a.card.spades.five { background-position: -317px -283px; }
|
||||
a.card.clubs.six { background-position: -421px -283px; }
|
||||
a.card.diamonds.six { background-position: -525px -283px; }
|
||||
a.card.hearts.six { background-position: -629px -283px; }
|
||||
a.card.spades.six { background-position: -733px -283px; }
|
||||
a.card.clubs.seven { background-position: -5px -422px; }
|
||||
a.card.diamonds.seven { background-position: -109px -422px; }
|
||||
a.card.hearts.seven { background-position: -213px -422px; }
|
||||
a.card.spades.seven { background-position: -317px -422px; }
|
||||
a.card.clubs.eight { background-position: -421px -422px; }
|
||||
a.card.diamonds.eight { background-position: -525px -422px; }
|
||||
a.card.hearts.eight { background-position: -629px -422px; }
|
||||
a.card.spades.eight { background-position: -733px -422px; }
|
||||
a.card.clubs.nine { background-position: -5px -561px; }
|
||||
a.card.diamonds.nine { background-position: -109px -561px; }
|
||||
a.card.hearts.nine { background-position: -213px -561px; }
|
||||
a.card.spades.nine { background-position: -317px -561px; }
|
||||
a.card.clubs.ace { background-position: -421px -561px; }
|
||||
a.card.diamonds.ace { background-position: -525px -561px; }
|
||||
a.card.hearts.ace { background-position: -629px -561px; }
|
||||
a.card.spades.ace { background-position: -733px -561px; }
|
||||
a.card.clubs.jack { background-position: -5px -700px; }
|
||||
a.card.diamonds.jack { background-position: -109px -700px; }
|
||||
a.card.hearts.jack { background-position: -213px -700px; }
|
||||
a.card.spades.jack { background-position: -317px -700px; }
|
||||
a.card.clubs.king { background-position: -421px -700px; }
|
||||
a.card.diamonds.king { background-position: -525px -700px; }
|
||||
a.card.hearts.king { background-position: -629px -700px; }
|
||||
a.card.spades.king { background-position: -733px -700px; }
|
||||
a.card.clubs.queen { background-position: -837px -5px; }
|
||||
a.card.diamonds.queen { background-position: -837px -144px; }
|
||||
a.card.hearts.queen { background-position: -837px -283px; }
|
||||
a.card.spades.queen { background-position: -837px -422px; }
|
||||
a.card.joker { background-position: -837px -561px; }
|
||||
@@ -1,13 +0,0 @@
|
||||
// Used by playing cards; /obj/item/hand
|
||||
// Subtype exists because of sendResources; these must be sent when the client connects.
|
||||
|
||||
/datum/html_interface/cards/New()
|
||||
. = ..()
|
||||
|
||||
src.head = src.head + "<link rel=\"stylesheet\" type=\"text/css\" href=\"cards.css\" />"
|
||||
src.updateLayout("<div id=\"headbar\"></div><div class=\"wrapper\"><table><tr><td style=\"vertical-align: middle;\"><div id=\"hand\"></div></td></tr></table></div>")
|
||||
|
||||
/datum/html_interface/cards/registerResources(var/list/resources = list())
|
||||
resources["cards.css"] = 'cards.css'
|
||||
resources["cards.png"] = 'cards.png'
|
||||
..(resources)
|
||||
|
Before Width: | Height: | Size: 277 KiB |
@@ -1,11 +0,0 @@
|
||||
html
|
||||
{
|
||||
-ms-overflow-style: scrollbar;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
font-family: Arial;
|
||||
overflow-y: scroll;
|
||||
overflow-x: auto;
|
||||
}
|
||||
@@ -1,391 +0,0 @@
|
||||
/*
|
||||
Author: NullQuery
|
||||
Created on: 2014-09-24
|
||||
|
||||
** CAUTION - A WORD OF WARNING **
|
||||
|
||||
If there is no getter or setter available and you aren't extending my code with a sub-type, DO NOT ACCESS VARIABLES DIRECTLY!
|
||||
|
||||
Add a getter/setter instead, even if it does nothing but return or set the variable. Thank you for your patience with me. -NQ
|
||||
|
||||
** Public API **
|
||||
|
||||
var/datum/html_interface/hi = new/datum/html_interface(ref, title, width = 700, height = 480, head = "")
|
||||
|
||||
Creates a new HTML interface object with [ref] as the object and [title] as the initial title of the page. [width] and [height] is the initial width and height
|
||||
of the window. The text in [head] is added just before the end </head> tag.
|
||||
|
||||
hi.setTitle(title)
|
||||
|
||||
Changes the title of the page.
|
||||
|
||||
hi.getTitle()
|
||||
|
||||
Returns the current title of the page.
|
||||
|
||||
hi.updateLayout(layout)
|
||||
|
||||
Updates the overall layout of the page (the HTML code between the body tags).
|
||||
|
||||
This should be used sparingly.
|
||||
|
||||
hi.updateContent(id, content, ignore_cache = FALSE)
|
||||
|
||||
Updates a portion of the page, i.e., the DOM element with the appropriate ID. The contents of the element are replaced with the provided HTML.
|
||||
|
||||
The content is cached on the server-side to minimize network traffic when the client "should have" the same HTML. The client may not have
|
||||
the same HTML if scripts cause the content to change. In this case set the ignore_cache parameter.
|
||||
|
||||
hi.executeJavaScript(jscript, client = null)
|
||||
|
||||
Executes Javascript on the browser.
|
||||
|
||||
The client is optional and may be a /mob, /client or /html_interface_client object. If not specified the code is executed on all clients.
|
||||
|
||||
hi.show(client)
|
||||
|
||||
Shows the HTML interface to the provided client. This will create a window, apply the current layout and contents. It will then wait for events.
|
||||
|
||||
hi.hide(client)
|
||||
|
||||
Hides the HTML interface from the provided client. This will close the browser window.
|
||||
|
||||
hi.isUsed()
|
||||
|
||||
Returns TRUE if the interface is being used (has an active client) or FALSE if not.
|
||||
|
||||
hi.closeAll()
|
||||
|
||||
Closes the interface on all clients.
|
||||
|
||||
** Additional notes **
|
||||
|
||||
When working with byond:// links make sure to reference the HTML interface object and NOT the original object. Topic() will still be called on
|
||||
your object, but it will pass through the HTML interface first allowing interception at a higher level.
|
||||
|
||||
If you want to use custom resources(images/css/js) with an existing interface:
|
||||
You have to use modules/client/asset_cache to ensure they get sent BEFORE the interface opens
|
||||
|
||||
** Sample code **
|
||||
|
||||
/mob/var/datum/html_interface/hi
|
||||
|
||||
/mob/verb/test()
|
||||
if (!hi)
|
||||
hi = new/datum/html_interface(src, "[src.key]")
|
||||
|
||||
hi.updateLayout("<div id=\"content\"></div>")
|
||||
hi.updateContent("content", "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>")
|
||||
|
||||
hi.show(src)
|
||||
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_EMPTY(html_interfaces)
|
||||
|
||||
/datum/html_interface
|
||||
// The atom we should report to.
|
||||
var/atom/ref
|
||||
|
||||
// The current title of the browser window.
|
||||
var/title
|
||||
|
||||
// A list of content elements that have been changed. This is necessary when showing the browser control to new clients.
|
||||
var/list/content_elements = new/list()
|
||||
|
||||
// The HTML layout, typically what's in-between the <body></body> tag. May be overridden by extensions.
|
||||
var/layout
|
||||
|
||||
// An associative list of clients currently viewing this screen. The key is the /client object, the value is the /datum/html_interface_client object.
|
||||
var/list/clients
|
||||
|
||||
// This goes just before the closing HEAD tag. I haven't exposed any getters/setters for it because it's only being used by extensions.
|
||||
var/head = ""
|
||||
|
||||
// The initial width of the browser control, used when the window is first shown to a client.
|
||||
var/width
|
||||
|
||||
// The initial height of the browser control, used when the window is first shown to a client.
|
||||
var/height
|
||||
|
||||
// A type associated list of assets the interface needs.
|
||||
//Sent to the client when the interface opens on the client for the first time.
|
||||
var/static/list/asset_list
|
||||
|
||||
/datum/html_interface/New(atom/ref, title, width = 700, height = 480, head = "")
|
||||
GLOB.html_interfaces.Add(src)
|
||||
|
||||
. = ..()
|
||||
|
||||
src.ref = ref
|
||||
src.title = title
|
||||
src.width = width
|
||||
src.height = height
|
||||
src.head = head
|
||||
|
||||
/datum/html_interface/Destroy()
|
||||
src.closeAll()
|
||||
|
||||
GLOB.html_interfaces.Remove(src)
|
||||
|
||||
return ..()
|
||||
|
||||
/* * Hooks */
|
||||
/datum/html_interface/proc/specificRenderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE)
|
||||
|
||||
//if you need to override this, either call ..() or add your resources to asset_list
|
||||
/datum/html_interface/proc/registerResources(var/list/resources = list())
|
||||
resources["jquery.min.js"] = 'js/jquery.min.js'
|
||||
resources["bootstrap.min.js"] = 'js/bootstrap.min.js'
|
||||
resources["bootstrap.min.css"] = 'css/bootstrap.min.css'
|
||||
resources["html_interface.css"] = 'css/html_interface.css'
|
||||
resources["html_interface.js"] = 'js/html_interface.js'
|
||||
var/assetlist = list()
|
||||
for (var/R in resources)
|
||||
register_asset(R,resources[R])
|
||||
assetlist += R
|
||||
if (!asset_list)
|
||||
asset_list = list()
|
||||
asset_list[type] = assetlist
|
||||
|
||||
/datum/html_interface/proc/createWindow(datum/html_interface_client/hclient)
|
||||
winclone(hclient.client, "window", "browser_[REF(src)]")
|
||||
|
||||
var/list/params = list(
|
||||
"size" = "[width]x[height]",
|
||||
"statusbar" = "false",
|
||||
"on-close" = "byond://?src=[REF(src)]&html_interface_action=onclose"
|
||||
)
|
||||
|
||||
if (hclient.client.hi_last_pos)
|
||||
params["pos"] = "[hclient.client.hi_last_pos]"
|
||||
|
||||
winset(hclient.client, "browser_[REF(src)]", list2params(params))
|
||||
|
||||
winset(hclient.client, "browser_[REF(src)].browser", list2params(list("parent" = "browser_[REF(src)]", "type" = "browser", "pos" = "0,0", "size" = "[width]x[height]", "anchor1" = "0,0", "anchor2" = "100,100", "use-title" = "true", "auto-format" = "false")))
|
||||
|
||||
/* * Public API */
|
||||
/datum/html_interface/proc/getTitle()
|
||||
return src.title
|
||||
|
||||
/datum/html_interface/proc/setTitle(title, ignore_cache = FALSE)
|
||||
src.title = title
|
||||
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/client in src.clients)
|
||||
hclient = src._getClient(src.clients[client])
|
||||
|
||||
if (hclient && hclient.active)
|
||||
src._renderTitle(src.clients[client], ignore_cache)
|
||||
|
||||
/datum/html_interface/proc/executeJavaScript(jscript, datum/html_interface_client/hclient = null)
|
||||
if (hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
if (hclient.is_loaded)
|
||||
hclient.client << output(list2params(list(jscript)), "browser_[REF(src)].browser:eval")
|
||||
else
|
||||
for (var/client in src.clients)
|
||||
if(src.clients[client])
|
||||
src.executeJavaScript(jscript, src.clients[client])
|
||||
|
||||
/datum/html_interface/proc/callJavaScript(func, list/arguments, datum/html_interface_client/hclient = null)
|
||||
if (!arguments)
|
||||
arguments = new/list()
|
||||
|
||||
if (hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
if (hclient.is_loaded)
|
||||
hclient.client << output(list2params(arguments), "browser_[REF(src)].browser:[func]")
|
||||
else
|
||||
for (var/client in src.clients)
|
||||
if (src.clients[client])
|
||||
src.callJavaScript(func, arguments, src.clients[client])
|
||||
|
||||
/datum/html_interface/proc/updateLayout(layout)
|
||||
src.layout = layout
|
||||
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/client in src.clients)
|
||||
hclient = src._getClient(src.clients[client])
|
||||
|
||||
if (hclient && hclient.active)
|
||||
src._renderLayout(hclient)
|
||||
|
||||
/datum/html_interface/proc/updateContent(id, content, ignore_cache = FALSE)
|
||||
src.content_elements[id] = content
|
||||
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/client in src.clients)
|
||||
hclient = src._getClient(src.clients[client])
|
||||
|
||||
if (hclient && hclient.active)
|
||||
spawn (-1) src._renderContent(id, hclient, ignore_cache)
|
||||
|
||||
/datum/html_interface/proc/show(datum/html_interface_client/hclient)
|
||||
hclient = getClient(hclient, TRUE)
|
||||
|
||||
if (istype(hclient))
|
||||
if ((type in asset_list) && islist(asset_list[type]))
|
||||
send_asset_list(hclient.client, asset_list[type], TRUE)
|
||||
|
||||
if (!winexists(hclient.client, "browser_[REF(src)]"))
|
||||
src.createWindow(hclient)
|
||||
//src._renderTitle(hclient, TRUE)
|
||||
//src._renderLayout(hclient)
|
||||
|
||||
hclient.is_loaded = FALSE
|
||||
hclient.client << output(replacetextEx(replacetextEx(file2text('html_interface.html'), "\[hsrc\]", "[REF(src)]"), "</head>", "[head]</head>"), "browser_[REF(src)].browser")
|
||||
|
||||
winshow(hclient.client, "browser_[REF(src)]", TRUE)
|
||||
|
||||
while (hclient.client && hclient.active && !hclient.is_loaded)
|
||||
sleep(2)
|
||||
|
||||
/datum/html_interface/proc/hide(datum/html_interface_client/hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
if (src.clients)
|
||||
src.clients.Remove(hclient.client)
|
||||
|
||||
if (!src.clients.len)
|
||||
src.clients = null
|
||||
|
||||
hclient.client.hi_last_pos = winget(hclient.client, "browser_[REF(src)]" ,"pos")
|
||||
|
||||
winshow(hclient.client, "browser_[REF(src)]", FALSE)
|
||||
winset(hclient.client, "browser_[REF(src)]", "parent=none")
|
||||
|
||||
if (hascall(src.ref, "hiOnHide"))
|
||||
call(src.ref, "hiOnHide")(hclient)
|
||||
|
||||
// Convert a /mob to /client, and /client to /datum/html_interface_client
|
||||
/datum/html_interface/proc/getClient(client, create_if_not_exist = FALSE)
|
||||
if (istype(client, /datum/html_interface_client))
|
||||
return src._getClient(client)
|
||||
else if (ismob(client))
|
||||
var/mob/mob = client
|
||||
client = mob.client
|
||||
|
||||
if (istype(client, /client))
|
||||
if (create_if_not_exist && (!src.clients || !(client in src.clients)))
|
||||
if (!src.clients)
|
||||
src.clients = new/list()
|
||||
if (!(client in src.clients))
|
||||
src.clients[client] = new/datum/html_interface_client(client)
|
||||
|
||||
if (src.clients && (client in src.clients))
|
||||
return src._getClient(src.clients[client])
|
||||
else
|
||||
return null
|
||||
else
|
||||
return null
|
||||
|
||||
/datum/html_interface/proc/enableFor(datum/html_interface_client/hclient)
|
||||
hclient.active = TRUE
|
||||
|
||||
src.show(hclient)
|
||||
|
||||
/datum/html_interface/proc/disableFor(datum/html_interface_client/hclient)
|
||||
hclient.active = FALSE
|
||||
|
||||
/datum/html_interface/proc/isUsed()
|
||||
if (src.clients && src.clients.len > 0)
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/key in clients)
|
||||
hclient = _getClient(clients[key])
|
||||
|
||||
if (hclient)
|
||||
if (hclient.active)
|
||||
return TRUE
|
||||
else
|
||||
clients.Remove(key)
|
||||
|
||||
return FALSE
|
||||
|
||||
/datum/html_interface/proc/closeAll()
|
||||
if (src.clients)
|
||||
for (var/client in src.clients)
|
||||
src.hide(src.clients[client])
|
||||
|
||||
/* * Danger Zone */
|
||||
|
||||
/datum/html_interface/proc/_getClient(datum/html_interface_client/hclient)
|
||||
if (hclient)
|
||||
if (hclient.client)
|
||||
// res = if the client has been active in the past 10 minutes and the client is allowed to view the object (context-sensitive).
|
||||
var/res = hclient.client.inactivity <= 6000 && (hascall(src.ref, "hiIsValidClient") ? call(src.ref, "hiIsValidClient")(hclient, src) : TRUE)
|
||||
|
||||
if (res)
|
||||
if (!hclient.active) src.enableFor(hclient)
|
||||
else
|
||||
if (hclient.active) src.disableFor(hclient)
|
||||
|
||||
return hclient
|
||||
else
|
||||
return null
|
||||
else
|
||||
return null
|
||||
|
||||
/datum/html_interface/proc/_renderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE, ignore_loaded = FALSE)
|
||||
if (hclient && (ignore_loaded || hclient.is_loaded))
|
||||
// Only render if we have new content.
|
||||
|
||||
if (ignore_cache || src.title != hclient.title)
|
||||
hclient.title = title
|
||||
|
||||
src.specificRenderTitle(hclient)
|
||||
|
||||
hclient.client << output(list2params(list(title)), "browser_[REF(src)].browser:setTitle")
|
||||
|
||||
/datum/html_interface/proc/_renderLayout(datum/html_interface_client/hclient, ignore_loaded = FALSE)
|
||||
if (hclient && (ignore_loaded || hclient.is_loaded))
|
||||
var/html = src.layout
|
||||
|
||||
// Only render if we have new content.
|
||||
if (html != hclient.layout)
|
||||
hclient.layout = html
|
||||
|
||||
hclient.client << output(list2params(list(html)), "browser_[REF(src)].browser:updateLayout")
|
||||
|
||||
for (var/id in src.content_elements)
|
||||
src._renderContent(id, hclient, ignore_loaded = ignore_loaded)
|
||||
|
||||
/datum/html_interface/proc/_renderContent(id, datum/html_interface_client/hclient, ignore_cache = FALSE, ignore_loaded = FALSE)
|
||||
if (hclient && (ignore_loaded || hclient.is_loaded))
|
||||
var/html = src.content_elements[id]
|
||||
|
||||
// Only render if we have new content.
|
||||
if (ignore_cache || !(id in hclient.content_elements) || html != hclient.content_elements[id])
|
||||
hclient.content_elements[id] = html
|
||||
|
||||
hclient.client << output(list2params(list(id, html)), "browser_[REF(src)].browser:updateContent")
|
||||
|
||||
/datum/html_interface/Topic(href, href_list[])
|
||||
var/datum/html_interface_client/hclient = getClient(usr.client)
|
||||
|
||||
if (istype(hclient))
|
||||
if ("html_interface_action" in href_list)
|
||||
switch (href_list["html_interface_action"])
|
||||
|
||||
if ("onload")
|
||||
hclient.layout = null
|
||||
hclient.content_elements.len = 0
|
||||
|
||||
src._renderTitle(hclient, TRUE, TRUE)
|
||||
src._renderLayout(hclient, TRUE)
|
||||
|
||||
hclient.is_loaded = TRUE
|
||||
|
||||
if ("onclose")
|
||||
src.hide(hclient)
|
||||
else if (src.ref && hclient.active)
|
||||
src.ref.Topic(href, href_list, hclient)
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta charset="UTF-8" />
|
||||
<title></title>
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
|
||||
<link rel="stylesheet" type="text/css" href="html_interface.css" />
|
||||
<script type="text/javascript">var hSrc = "[hsrc]";</script>
|
||||
<script type="text/javascript" src="jquery.min.js"></script>
|
||||
<script type="text/javascript" src="jquery.mousewheel.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="html_interface.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,46 +0,0 @@
|
||||
/datum/html_interface_client
|
||||
// The /client object represented by this model.
|
||||
var/client/client
|
||||
|
||||
// The layout currently visible to the client.
|
||||
var/layout
|
||||
|
||||
// The content elements (mirrored from /datum/html_interface) currently visible to the client.
|
||||
var/list/content_elements = new/list()
|
||||
|
||||
// The current title for this client
|
||||
var/title
|
||||
|
||||
// TRUE if the browser control has loaded and will accept input, FALSE if not.
|
||||
var/is_loaded = FALSE
|
||||
|
||||
// TRUE if this client should receive updates, FALSE if not.
|
||||
var/active = TRUE
|
||||
|
||||
// A list of extra variables, for use by extensions.
|
||||
var/list/extra_vars
|
||||
|
||||
/datum/html_interface_client/New(client/client)
|
||||
. = ..()
|
||||
|
||||
src.client = client
|
||||
|
||||
/datum/html_interface_client/proc/putExtraVar(key, value)
|
||||
if (!src.extra_vars)
|
||||
src.extra_vars = new/list()
|
||||
src.extra_vars[key] = value
|
||||
|
||||
/datum/html_interface_client/proc/removeExtraVar(key)
|
||||
if (src.extra_vars)
|
||||
. = src.extra_vars[key]
|
||||
|
||||
src.extra_vars.Remove(key)
|
||||
|
||||
if (!src.extra_vars.len)
|
||||
src.extra_vars = null
|
||||
|
||||
return .
|
||||
|
||||
/datum/html_interface_client/proc/getExtraVar(key)
|
||||
if (src.extra_vars)
|
||||
return src.extra_vars[key]
|
||||
@@ -1,45 +0,0 @@
|
||||
var is_loading = false;
|
||||
var load_count = 0;
|
||||
|
||||
function onload()
|
||||
{
|
||||
if (!is_loading)
|
||||
{
|
||||
var count = ++load_count;
|
||||
is_loading = true;
|
||||
$("body").html("");
|
||||
|
||||
window.location.href = "byond://?src=" + hSrc + "&html_interface_action=onload";
|
||||
|
||||
// The request may fail which would prevent the player from refreshing the screen again. Try to detect this retry.
|
||||
setTimeout(function()
|
||||
{
|
||||
if (count == load_count && is_loading && $("body").html() == "")
|
||||
{
|
||||
is_loading = false;
|
||||
onload();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
$(document).on("keydown", function(e)
|
||||
{
|
||||
if (!e.ctrlKey && e.which == 116)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
onload();
|
||||
}
|
||||
});
|
||||
|
||||
onload();
|
||||
});
|
||||
|
||||
function fixText(text) { return text.replace(/ÿ/g, ""); }
|
||||
|
||||
function setTitle(new_title) { $("title").html(fixText(new_title)); $(window).trigger("onUpdateTitle"); }
|
||||
function updateLayout(new_html) { $("body").html(fixText(new_html)); $(window).trigger("onUpdateLayout"); setTimeout(function(){ is_loading = false; }, 200); }
|
||||
function updateContent(id, new_html) { $("#" + id).html(fixText(new_html)); $(window).trigger("onUpdateContent"); }
|
||||
@@ -1,321 +0,0 @@
|
||||
body
|
||||
{
|
||||
background-color: #272727;
|
||||
background-image: url(uiBg.png);
|
||||
background-repeat: repeat-x;
|
||||
background-position: center top;
|
||||
|
||||
font-family: verdana,Geneva,sans-serif;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
line-height: 170%; /* NullQuery: 170% of what? */
|
||||
}
|
||||
|
||||
/* Fix for IE8 */
|
||||
body
|
||||
{
|
||||
background-color: #1F1F1F\9 !important;
|
||||
}
|
||||
|
||||
#ntbgcenter
|
||||
{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 246px;
|
||||
|
||||
background-image: url(uiBgcenter.png);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#content
|
||||
{
|
||||
padding: 8px;
|
||||
font-family: Verdana, Geneva, sans-serif;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
background-color: #40628a;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
a, a:link, a:visited, a:active, .linkOn, .linkOff
|
||||
{
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background: #40628a;
|
||||
border: 1px solid #161616;
|
||||
padding: 1px 4px 1px 4px;
|
||||
margin: 0 2px 0 0;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
a.nobg, a.nobg:link, a.nobg:visited, a.nobg:active
|
||||
{
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
cursor:default;
|
||||
font-weight:bold;
|
||||
}
|
||||
a.nobg:hover
|
||||
{
|
||||
color:#40628a;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
color: #40628a;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
a.white, a.white:link, a.white:visited, a.white:active
|
||||
{
|
||||
color: #40628a;
|
||||
text-decoration: none;
|
||||
background: #ffffff;
|
||||
border: 1px solid #161616;
|
||||
padding: 1px 4px 1px 4px;
|
||||
margin: 0 2px 0 0;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
a.white:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #40628a;
|
||||
}
|
||||
|
||||
.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
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #999999;
|
||||
border-color: #666666;
|
||||
}
|
||||
|
||||
a.icon, .linkOn.icon, .linkOff.icon
|
||||
{
|
||||
position: relative;
|
||||
padding: 1px 4px 2px 20px;
|
||||
}
|
||||
|
||||
a.icon img, .linkOn.icon img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
padding: 4px 0 0 10px;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li
|
||||
{
|
||||
padding: 0 0 2px 0;
|
||||
}
|
||||
|
||||
img, a img
|
||||
{
|
||||
border-style:none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
margin: 0;
|
||||
padding: 16px 0 8px 0;
|
||||
color: #517087;
|
||||
}
|
||||
|
||||
h1
|
||||
{
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
h2
|
||||
{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h3
|
||||
{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
h4
|
||||
{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.good
|
||||
{
|
||||
color: #00ff00;
|
||||
}
|
||||
|
||||
.average
|
||||
{
|
||||
color: #d09000;
|
||||
}
|
||||
|
||||
.bad
|
||||
{
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.highlight
|
||||
{
|
||||
color: #8BA5C4;
|
||||
}
|
||||
|
||||
.dark
|
||||
{
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
.notice
|
||||
{
|
||||
position: relative;
|
||||
background: #E9C183;
|
||||
color: #15345A;
|
||||
font-size: 10px;
|
||||
font-style: italic;
|
||||
padding: 2px 4px 0 4px;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.notice.icon
|
||||
{
|
||||
padding: 2px 4px 0 20px;
|
||||
}
|
||||
|
||||
.notice img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
div.notice
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.statusDisplay
|
||||
{
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
border: 1px solid #40628a;
|
||||
padding: 4px;
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.statusLabel
|
||||
{
|
||||
width: 138px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
color: #98B0C3;
|
||||
}
|
||||
|
||||
.statusValue
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
.block
|
||||
{
|
||||
padding: 8px;
|
||||
margin: 10px 4px 4px 4px;
|
||||
border: 1px solid #40628a;
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
.block h3
|
||||
{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.progressBar
|
||||
{
|
||||
width: 240px;
|
||||
height: 14px;
|
||||
border: 1px solid #666666;
|
||||
float: left;
|
||||
margin: 0 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progressFill
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #40628a;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progressFill.good
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #00ff00;
|
||||
}
|
||||
|
||||
.progressFill.average
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #d09000;
|
||||
}
|
||||
|
||||
.progressFill.bad
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #ff0000;
|
||||
}
|
||||
|
||||
.progressFill.highlight
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #8BA5C4;
|
||||
}
|
||||
|
||||
.clearBoth
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.clearLeft
|
||||
{
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.clearRight
|
||||
{
|
||||
clear: right;
|
||||
}
|
||||
|
||||
.line
|
||||
{
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
Author: NullQuery
|
||||
Created on: 2014-09-25
|
||||
|
||||
Extension to implement Nanotrasen styled windows.
|
||||
|
||||
Additional procs:
|
||||
|
||||
hi.setEyeColor(color, client)
|
||||
|
||||
Use this to set the color of the 'eye' in the top-left corner of the window.
|
||||
|
||||
The client is optional and may be a /mob, /client or /html_interface_client object. It must be specified, since the eye icon is specific to a client.
|
||||
|
||||
*/
|
||||
|
||||
/datum/html_interface/nanotrasen/New()
|
||||
. = ..()
|
||||
|
||||
// Add appropriate CSS and set the default layout.
|
||||
src.head = src.head + "<link rel=\"stylesheet\" type=\"text/css\" href=\"hi-nanotrasen.css\" />"
|
||||
src.updateLayout("")
|
||||
|
||||
/datum/html_interface/nanotrasen/updateLayout(layout)
|
||||
// Wrap the layout in our custom HTML
|
||||
return ..("<div id=\"ntbgcenter\"></div><div id=\"content\">[layout]</div>")
|
||||
|
||||
/datum/html_interface/specificRenderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE)
|
||||
// Update the title in our custom header (in addition to default functionality)
|
||||
winset(hclient.client, "browser_[REF(src)].uiTitle", list2params(list("text" = "[src.title]")))
|
||||
|
||||
/datum/html_interface/nanotrasen/registerResources(var/list/resources = list())
|
||||
resources["uiBg.png"] = 'uiBg.png'
|
||||
resources["uiBgcenter.png"] = 'uiBgcenter.png'
|
||||
resources["hi-nanotrasen.css"] = 'hi-nanotrasen.css'
|
||||
..(resources)
|
||||
|
||||
/datum/html_interface/nanotrasen/createWindow(datum/html_interface_client/hclient)
|
||||
. = ..() // we want the default window
|
||||
|
||||
// Remove the titlebar
|
||||
winset(hclient.client, "browser_[REF(src)]", list2params(list(
|
||||
"titlebar" = "false"
|
||||
)))
|
||||
|
||||
// Reposition the browser
|
||||
winset(hclient.client, "browser_[REF(src)].browser", list2params(list(
|
||||
"pos" = "0,35",
|
||||
"size" = "[width]x[height - 35]"
|
||||
)))
|
||||
|
||||
// Add top background image
|
||||
winset(hclient.client, "browser_[REF(src)].topbg", list2params(list(
|
||||
"parent" = "browser_[REF(src)]",
|
||||
"type" = "label",
|
||||
"pos" = "0,0",
|
||||
"size" = "[width]x35",
|
||||
"anchor1" = "0,0",
|
||||
"anchor2" = "100,0",
|
||||
"image" = "['uiBgtop.png']",
|
||||
"image-mode" = "tile",
|
||||
"is-disabled" = "true"
|
||||
)))
|
||||
|
||||
// Add Nanotrasen logo
|
||||
winset(hclient.client, "browser_[REF(src)].uiTitleFluff", list2params(list(
|
||||
"parent" = "browser_[REF(src)]",
|
||||
"type" = "label",
|
||||
"pos" = "[width - 42 - 4 - 24 - 4 - 24 - 4],5",
|
||||
"size" = "42x24",
|
||||
"anchor1" = "100,0",
|
||||
"anchor2" = "100,0",
|
||||
"image" = "['uiTitleFluff.png']",
|
||||
"image-mode" = "tile",
|
||||
"is-disabled" = "true"
|
||||
)))
|
||||
|
||||
// Add Eye picture
|
||||
winset(hclient.client, "browser_[REF(src)].uiTitleEye", list2params(list(
|
||||
"parent" = "browser_[REF(src)]",
|
||||
"type" = "label",
|
||||
"pos" = "8,5",
|
||||
"size" = "42x24",
|
||||
"anchor1" = "0,0",
|
||||
"anchor2" = "0,0",
|
||||
"image" = "['uiEyeGreen.png']",
|
||||
"image-mode" = "tile",
|
||||
"is-disabled" = "true"
|
||||
)))
|
||||
|
||||
// Add title text
|
||||
winset(hclient.client, "browser_[REF(src)].uiTitle", list2params(list(
|
||||
"parent" = "browser_[REF(src)]",
|
||||
"type" = "label",
|
||||
"is-transparent" = "true",
|
||||
"pos" = "64,0",
|
||||
"size" = "580x35",
|
||||
"anchor1" = "0,0",
|
||||
"anchor2" = "100,0",
|
||||
"is-disabled" = "true",
|
||||
"text" = "[src.title]",
|
||||
"align" = "left",
|
||||
"font-family" = "verdana,Geneva,sans-serif",
|
||||
"font-size" = "12", // ~ 16px
|
||||
"text-color" = "#E9C183"
|
||||
)))
|
||||
|
||||
// Add minimize button
|
||||
// TODO: Style the button (add image)
|
||||
winset(hclient.client, "browser_[REF(src)].uiTitleMinimize", list2params(list(
|
||||
"parent" = "browser_[REF(src)]",
|
||||
"type" = "button",
|
||||
"is-flat" = "true",
|
||||
"background-color"="#383838", // should be unnecessary if image is used
|
||||
"text-color" = "#FFFFFF", // should be unnecessary if image is used
|
||||
"is-transparent" = "true",
|
||||
"pos" = "[width - 24 - 4 - 24 - 4],5",
|
||||
"size" = "24x24",
|
||||
"anchor1" = "100,0",
|
||||
"anchor2" = "100,0",
|
||||
"text" = "-",
|
||||
"font-family" = "verdana,Geneva,sans-serif", // should be unnecessary if image is used
|
||||
"font-size" = "12", // ~ 16px - should be unnecessary if image is used
|
||||
|
||||
// Disable resizing (disables maximizing), minimize window, bind window.on-size to catch 'restore window' button to enable resizing if restored.
|
||||
"command" = ".winset \"browser_[REF(src)].can-resize=false;browser_[REF(src)].is-minimized=true;browser_[REF(src)].on-size=\".swinset \\\"browser_[REF(src)].can-resize=true;browser_[REF(src)].on-size=\\\"\"\""
|
||||
)))
|
||||
|
||||
// Add close button
|
||||
// TODO: Style the button (add image)
|
||||
winset(hclient.client, "browser_[REF(src)].uiTitleClose", list2params(list(
|
||||
"parent" = "browser_[REF(src)]",
|
||||
"type" = "button",
|
||||
"is-flat" = "true",
|
||||
"background-color"="#383838", // should be unnecessary if image is used
|
||||
"text-color" = "#FFFFFF", // should be unnecessary if image is used
|
||||
"command" = "byond://?src=[REF(src)];html_interface_action=onclose",
|
||||
"is-transparent" = "true",
|
||||
"pos" = "[width - 24 - 4],5",
|
||||
"size" = "24x24",
|
||||
"anchor1" = "100,0",
|
||||
"anchor2" = "100,0",
|
||||
"text" = "X",
|
||||
"font-family" = "verdana,Geneva,sans-serif", // should be unnecessary if image is used
|
||||
"font-size" = "12" // ~ 16px - should be unnecessary if image is used
|
||||
)))
|
||||
|
||||
/datum/html_interface/nanotrasen/enableFor(datum/html_interface_client/hclient)
|
||||
. = ..()
|
||||
|
||||
src.setEyeColor("green", hclient)
|
||||
|
||||
/datum/html_interface/nanotrasen/disableFor(datum/html_interface_client/hclient)
|
||||
hclient.active = FALSE
|
||||
|
||||
src.setEyeColor("red", hclient)
|
||||
|
||||
/datum/html_interface/nanotrasen/proc/setEyeColor(color, datum/html_interface_client/hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
var/resource
|
||||
switch (color)
|
||||
if ("green")
|
||||
resource = 'uiEyeGreen.png'
|
||||
if ("orange")
|
||||
resource = 'uiEyeOrange.png'
|
||||
if ("red")
|
||||
resource = 'uiEyeRed.png'
|
||||
else
|
||||
CRASH("Invalid color: [color]")
|
||||
|
||||
if (hclient.getExtraVar("eye_color") != color)
|
||||
hclient.putExtraVar("eye_color", color)
|
||||
|
||||
winset(hclient.client, "browser_[REF(src)].uiTitleEye", list2params(list("image" = "[resource]")))
|
||||
else
|
||||
WARNING("Invalid object passed to /datum/html_interface/nanotrasen/proc/setEyeColor")
|
||||
|
Before Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 912 B |
|
Before Width: | Height: | Size: 985 B |
|
Before Width: | Height: | Size: 946 B |
|
Before Width: | Height: | Size: 946 B |
@@ -362,7 +362,7 @@
|
||||
pocell.desc = "A rechargeable plant-based power cell. This one has a rating of [DisplayEnergy(pocell.maxcharge)], and you should not swallow it."
|
||||
|
||||
if(G.reagents.has_reagent("plasma", 2))
|
||||
pocell.rigged = 1
|
||||
pocell.rigged = TRUE
|
||||
|
||||
qdel(G)
|
||||
else
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
// The list is converted to JSON down the line.
|
||||
/obj/item/integrated_circuit/proc/save()
|
||||
var/list/component_params = list()
|
||||
var/init_name = initial(name)
|
||||
|
||||
// Save initial name used for differentiating assemblies
|
||||
component_params["type"] = name
|
||||
component_params["type"] = init_name
|
||||
|
||||
// Save the modified name.
|
||||
if(name != displayed_name)
|
||||
if(init_name != displayed_name)
|
||||
component_params["name"] = displayed_name
|
||||
|
||||
// Saving input values
|
||||
@@ -43,25 +44,26 @@
|
||||
// Verifies a list of component parameters
|
||||
// Returns null on success, error name on failure
|
||||
/obj/item/integrated_circuit/proc/verify_save(list/component_params)
|
||||
var/init_name = initial(name)
|
||||
// Validate name
|
||||
if(component_params["name"] && !reject_bad_name(component_params["name"], TRUE))
|
||||
return "Bad component name at [name]."
|
||||
return "Bad component name at [init_name]."
|
||||
|
||||
// Validate input values
|
||||
if(component_params["inputs"])
|
||||
var/list/loaded_inputs = component_params["inputs"]
|
||||
if(!islist(loaded_inputs))
|
||||
return "Malformed input values list at [name]."
|
||||
return "Malformed input values list at [init_name]."
|
||||
|
||||
var/inputs_amt = length(inputs)
|
||||
|
||||
// Too many inputs? Inputs for input-less component? This is not good.
|
||||
if(!inputs_amt || inputs_amt < length(loaded_inputs))
|
||||
return "Input values list out of bounds at [name]."
|
||||
return "Input values list out of bounds at [init_name]."
|
||||
|
||||
for(var/list/input in loaded_inputs)
|
||||
if(input.len != 3)
|
||||
return "Malformed input data at [name]."
|
||||
return "Malformed input data at [init_name]."
|
||||
|
||||
var/input_id = input[1]
|
||||
var/input_type = input[2]
|
||||
@@ -69,12 +71,12 @@
|
||||
|
||||
// No special type support yet.
|
||||
if(input_type)
|
||||
return "Unidentified input type at [name]!"
|
||||
return "Unidentified input type at [init_name]!"
|
||||
// TODO: support for special input types, such as typepaths and internal refs
|
||||
|
||||
// Input ID is a list index, make sure it's sane.
|
||||
if(!isnum(input_id) || input_id % 1 || input_id > inputs_amt || input_id < 1)
|
||||
return "Invalid input index at [name]."
|
||||
return "Invalid input index at [init_name]."
|
||||
|
||||
|
||||
// Loads component parameters from a list
|
||||
|
||||
@@ -851,8 +851,8 @@
|
||||
return
|
||||
|
||||
/obj/item/integrated_circuit/input/ntnetsc
|
||||
name = "NTnet scanner"
|
||||
desc = "This can return NTnet IDs of a component inside the given object, if there are any."
|
||||
name = "NTNet scanner"
|
||||
desc = "This can return NTNet IDs of a component inside the given object, if there are any."
|
||||
icon_state = "signalsc"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
complexity = 2
|
||||
@@ -865,22 +865,24 @@
|
||||
power_draw_per_use = 1
|
||||
|
||||
/obj/item/integrated_circuit/input/ntnetsc/do_work()
|
||||
|
||||
var/atom/AM = get_pin_data_as_type(IC_INPUT, 1, /atom)
|
||||
var/list/processing_list = list(AM)
|
||||
var/datum/component/ntnet_interface/net = null
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
while(processing_list.len && !net)
|
||||
var/atom/A = processing_list[1]
|
||||
processing_list.Cut(1, 2)
|
||||
//Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed
|
||||
//This is also why we don't need to check against assembled as we go along
|
||||
processing_list += A.contents
|
||||
net = A.GetComponent(/datum/component/ntnet_interface)
|
||||
var/datum/component/ntnet_interface/net
|
||||
|
||||
if(AM)
|
||||
var/list/processing_list = list(AM)
|
||||
while(processing_list.len && !net)
|
||||
var/atom/A = processing_list[1]
|
||||
processing_list.Cut(1, 2)
|
||||
//Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed
|
||||
//This is also why we don't need to check against assembled as we go along
|
||||
processing_list += A.contents
|
||||
net = A.GetComponent(/datum/component/ntnet_interface)
|
||||
|
||||
if(net)
|
||||
set_pin_data(IC_OUTPUT, 1, net.hardware_id)
|
||||
activate_pin(2)
|
||||
else
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
activate_pin(3)
|
||||
push_data()
|
||||
return
|
||||
|
||||
@@ -56,13 +56,3 @@
|
||||
nutrition -= HUNGER_FACTOR/10
|
||||
if(m_intent == MOVE_INTENT_RUN)
|
||||
nutrition -= HUNGER_FACTOR/10
|
||||
|
||||
/mob/living/carbon/Moved(oldLoc, Dir)
|
||||
. = ..()
|
||||
for(var/obj/O in internal_organs)
|
||||
O.on_mob_move(dir, src, oldLoc)
|
||||
|
||||
/mob/living/carbon/setDir(newdir)
|
||||
. = ..()
|
||||
for(var/obj/O in internal_organs)
|
||||
O.on_mob_turn(newdir, src)
|
||||
|
||||
@@ -111,25 +111,10 @@
|
||||
if(mob.throwing)
|
||||
mob.throwing.finalize(FALSE)
|
||||
|
||||
if(LAZYLEN(mob.user_movement_hooks))
|
||||
for(var/obj/O in mob.user_movement_hooks)
|
||||
O.intercept_user_move(direct, mob, n, oldloc)
|
||||
|
||||
var/atom/movable/P = mob.pulling
|
||||
if(P && !ismob(P) && P.density)
|
||||
mob.dir = turn(mob.dir, 180)
|
||||
|
||||
/mob/Moved(oldLoc, dir, Forced = FALSE)
|
||||
. = ..()
|
||||
for(var/obj/O in contents)
|
||||
O.on_mob_move(dir, src, oldLoc, Forced)
|
||||
|
||||
/mob/setDir(newDir)
|
||||
. = ..()
|
||||
for(var/obj/O in contents)
|
||||
O.on_mob_turn(newDir, src)
|
||||
|
||||
|
||||
///Process_Grab()
|
||||
///Called by client/Move()
|
||||
///Checks to see if you are being grabbed and if so attemps to break it
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var/maxcharge = 1000
|
||||
materials = list(MAT_METAL=700, MAT_GLASS=50)
|
||||
grind_results = list("lithium" = 15, "iron" = 5, "silicon" = 5)
|
||||
var/rigged = 0 // true if rigged to explode
|
||||
var/rigged = FALSE // true if rigged to explode
|
||||
var/chargerate = 100 //how much power is given every tick in a recharger
|
||||
var/self_recharge = 0 //does it self recharge, over time, or not?
|
||||
var/ratingdesc = TRUE
|
||||
@@ -104,7 +104,7 @@
|
||||
return (FIRELOSS)
|
||||
|
||||
/obj/item/stock_parts/cell/on_reagent_change(changetype)
|
||||
rigged = reagents.has_reagent("plasma", 5)
|
||||
rigged = !isnull(reagents.has_reagent("plasma", 5)) //has_reagent returns the reagent datum
|
||||
..()
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
var/light_impact_range = round(sqrt(charge)/30)
|
||||
var/flash_range = light_impact_range
|
||||
if (light_impact_range==0)
|
||||
rigged = 0
|
||||
rigged = FALSE
|
||||
corrupt()
|
||||
return
|
||||
//explosion(T, 0, 1, 2, 2)
|
||||
@@ -128,7 +128,7 @@
|
||||
charge /= 2
|
||||
maxcharge = max(maxcharge/2, chargerate)
|
||||
if (prob(10))
|
||||
rigged = 1 //broken batterys are dangerous
|
||||
rigged = TRUE //broken batterys are dangerous
|
||||
|
||||
/obj/item/stock_parts/cell/emp_act(severity)
|
||||
charge -= 1000 / severity
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty")
|
||||
|
||||
var/datum/action/item_action/zoom_lock_action/zoom_lock_action
|
||||
var/datum/component/mobhook
|
||||
|
||||
/obj/item/gun/energy/beam_rifle/debug
|
||||
delay = 0
|
||||
@@ -189,6 +190,7 @@
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
set_user(null)
|
||||
QDEL_LIST(current_tracers)
|
||||
QDEL_NULL(mobhook)
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/energy/beam_rifle/emp_act(severity)
|
||||
@@ -258,7 +260,7 @@
|
||||
delay_penalty(difference * aiming_time_increase_angle_multiplier)
|
||||
lastangle = angle
|
||||
|
||||
/obj/item/gun/energy/beam_rifle/on_mob_move()
|
||||
/obj/item/gun/energy/beam_rifle/proc/on_mob_move()
|
||||
check_user()
|
||||
if(aiming)
|
||||
delay_penalty(aiming_time_increase_user_movement)
|
||||
@@ -284,12 +286,14 @@
|
||||
if(user == current_user)
|
||||
return
|
||||
stop_aiming(current_user)
|
||||
QDEL_NULL(mobhook)
|
||||
if(istype(current_user))
|
||||
LAZYREMOVE(current_user.mousemove_intercept_objects, src)
|
||||
current_user = null
|
||||
if(istype(user))
|
||||
current_user = user
|
||||
LAZYADD(current_user.mousemove_intercept_objects, src)
|
||||
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/on_mob_move))
|
||||
|
||||
/obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
|
||||
if(aiming)
|
||||
|
||||
@@ -167,4 +167,4 @@
|
||||
return
|
||||
playsound(src, "sparks", 75, 1)
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='notice'>You you disable the security protocols.</span>")
|
||||
to_chat(user, "<span class='notice'>You disable the security protocols.</span>")
|
||||
|
||||
@@ -90,24 +90,14 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
|
||||
if(H.stat == DEAD || !(H.client))
|
||||
return
|
||||
if(H.mind)
|
||||
if(iswizard(H) || H.mind.special_role == "survivalist")
|
||||
if(iswizard(H) || H.mind.has_antag_datum(/datum/antagonist/survivalist/guns))
|
||||
return
|
||||
|
||||
if(prob(GLOB.summon_guns_triggered) && !(H.mind.has_antag_datum(/datum/antagonist)))
|
||||
SSticker.mode.traitors += H.mind
|
||||
|
||||
var/datum/objective/steal_five_of_type/summon_guns/guns = new
|
||||
guns.owner = H.mind
|
||||
H.mind.objectives += guns
|
||||
H.mind.special_role = "survivalist"
|
||||
H.mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
to_chat(H, "<B>You are the survivalist! Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way.</B>")
|
||||
|
||||
var/datum/objective/survive/survive = new
|
||||
survive.owner = H.mind
|
||||
H.mind.objectives += survive
|
||||
H.mind.add_antag_datum(/datum/antagonist/survivalist/guns)
|
||||
H.log_message("<font color='red'>Was made into a survivalist, and trusts no one!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
H.mind.announce_objectives()
|
||||
|
||||
var/gun_type = pick(GLOB.summoned_guns)
|
||||
var/obj/item/gun/G = new gun_type(get_turf(H))
|
||||
@@ -122,22 +112,12 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
|
||||
if(H.stat == DEAD || !(H.client))
|
||||
return
|
||||
if(H.mind)
|
||||
if(iswizard(H) || H.mind.special_role == "survivalist")
|
||||
if(iswizard(H) || H.mind.has_antag_datum(/datum/antagonist/survivalist/magic))
|
||||
return
|
||||
|
||||
if(prob(GLOB.summon_magic_triggered) && !(H.mind.has_antag_datum(/datum/antagonist)))
|
||||
var/datum/objective/steal_five_of_type/summon_magic/magic = new
|
||||
magic.owner = H.mind
|
||||
H.mind.objectives += magic
|
||||
H.mind.special_role = "amateur magician"
|
||||
H.mind.add_antag_datum(/datum/antagonist/auto_custom)
|
||||
to_chat(H, "<B>You are the amateur magician! Grow your newfound talent! Grab as many magical artefacts as possible, by any means necessary. Kill anyone who gets in your way.</B>")
|
||||
|
||||
var/datum/objective/survive/survive = new
|
||||
survive.owner = H.mind
|
||||
H.mind.objectives += survive
|
||||
H.mind.add_antag_datum(/datum/antagonist/survivalist/magic)
|
||||
H.log_message("<font color='red'>Was made into a survivalist, and trusts no one!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
H.mind.announce_objectives()
|
||||
|
||||
var/magic_type = pick(GLOB.summoned_magic)
|
||||
var/lucky = FALSE
|
||||
|
||||
@@ -170,9 +170,10 @@
|
||||
if(active && (obj_flags & EMAGGED))
|
||||
change_meteor_chance(0.5)
|
||||
|
||||
/obj/machinery/satellite/meteor_shield/emag_act()
|
||||
/obj/machinery/satellite/meteor_shield/emag_act(mob/user)
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='notice'>You scramble the satellite's controller, increasing the chance of meteor strikes.</span>")
|
||||
if(active)
|
||||
change_meteor_chance(2)
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
var/list/obj/effect/abstract/eye_lighting/eye_lighting
|
||||
var/obj/effect/abstract/eye_lighting/on_mob
|
||||
var/image/mob_overlay
|
||||
var/datum/component/mobhook
|
||||
|
||||
/obj/item/organ/eyes/robotic/glow/Initialize()
|
||||
. = ..()
|
||||
@@ -227,15 +228,20 @@
|
||||
if(active)
|
||||
deactivate(silent = TRUE)
|
||||
|
||||
/obj/item/organ/eyes/robotic/glow/on_mob_move()
|
||||
if(QDELETED(owner) || !active)
|
||||
return
|
||||
update_visuals()
|
||||
/obj/item/organ/eyes/robotic/glow/Insert(var/mob/living/carbon/M)
|
||||
. = ..()
|
||||
if (mobhook && mobhook.parent != M)
|
||||
QDEL_NULL(mobhook)
|
||||
if (!mobhook)
|
||||
mobhook = M.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_DIR_CHANGE), CALLBACK(src, .proc/update_visuals))
|
||||
|
||||
/obj/item/organ/eyes/robotic/glow/on_mob_turn()
|
||||
if(QDELETED(owner) || !active)
|
||||
return
|
||||
update_visuals()
|
||||
/obj/item/organ/eyes/robotic/glow/Remove(mob/living/carbon/M)
|
||||
. = ..()
|
||||
QDEL_NULL(mobhook)
|
||||
|
||||
/obj/item/organ/eyes/robotic/glow/Destroy()
|
||||
QDEL_NULL(mobhook) // mobhook is not our component
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/eyes/robotic/glow/proc/activate(silent = FALSE)
|
||||
start_visuals()
|
||||
@@ -251,11 +257,13 @@
|
||||
active = FALSE
|
||||
remove_mob_overlay()
|
||||
|
||||
/obj/item/organ/eyes/robotic/glow/proc/update_visuals()
|
||||
/obj/item/organ/eyes/robotic/glow/proc/update_visuals(olddir, newdir)
|
||||
if((LAZYLEN(eye_lighting) < light_beam_distance) || !on_mob)
|
||||
regenerate_light_effects()
|
||||
var/turf/scanfrom = get_turf(owner)
|
||||
var/scandir = owner.dir
|
||||
if (newdir && scandir != newdir) // COMSIG_ATOM_DIR_CHANGE happens before the dir change, but with a reference to the new direction.
|
||||
scandir = newdir
|
||||
if(!istype(scanfrom))
|
||||
clear_visuals()
|
||||
var/turf/scanning = scanfrom
|
||||
@@ -320,4 +328,4 @@
|
||||
/obj/item/organ/eyes/moth
|
||||
name = "moth eyes"
|
||||
desc = "These eyes seem to have increased sensitivity to bright light, with no improvement to low light vision."
|
||||
flash_protect = -1
|
||||
flash_protect = -1
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
* This allows modules/datums to have the UI attached to them,
|
||||
* and be a part of another object.
|
||||
**/
|
||||
/datum/proc/ui_host()
|
||||
/datum/proc/ui_host(mob/user)
|
||||
return src // Default src.
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* return UI_state The state of the UI.
|
||||
**/
|
||||
/datum/proc/ui_status(mob/user, datum/ui_state/state)
|
||||
var/src_object = ui_host()
|
||||
var/src_object = ui_host(user)
|
||||
. = UI_CLOSE
|
||||
if(!state)
|
||||
return
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
var/update_count = 0
|
||||
for(var/ui_key in open_uis[src_object_key])
|
||||
for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host()) // Check the UI is valid.
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) // Check the UI is valid.
|
||||
ui.process(force = 1) // Update the UI.
|
||||
update_count++ // Count each UI we update.
|
||||
return update_count
|
||||
@@ -94,7 +94,7 @@
|
||||
var/close_count = 0
|
||||
for(var/ui_key in open_uis[src_object_key])
|
||||
for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host()) // Check the UI is valid.
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) // Check the UI is valid.
|
||||
ui.close() // Close the UI.
|
||||
close_count++ // Count each UI we close.
|
||||
return close_count
|
||||
@@ -111,7 +111,7 @@
|
||||
for(var/src_object_key in open_uis)
|
||||
for(var/ui_key in open_uis[src_object_key])
|
||||
for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host()) // Check the UI is valid.
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) // Check the UI is valid.
|
||||
ui.close() // Close the UI.
|
||||
close_count++ // Count each UI we close.
|
||||
return close_count
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
* optional force bool If the UI should be forced to update.
|
||||
**/
|
||||
/datum/tgui/process(force = 0)
|
||||
var/datum/host = src_object.ui_host()
|
||||
var/datum/host = src_object.ui_host(user)
|
||||
if(!src_object || !host || !user) // If the object or user died (or something else), abort.
|
||||
close()
|
||||
return
|
||||
|
||||