Merge branch 'Bleeding-Edge' of gitlab.com:vgstation/vgstation into Bleeding-Edge

This commit is contained in:
Rob Nelson
2015-08-25 13:28:37 -07:00
20 changed files with 3783 additions and 507 deletions

View File

@@ -116,7 +116,7 @@
/datum/theft_objective/traitor/corgi
name = "a piece of corgi meat"
typepath = /obj/item/weapon/reagent_containers/food/snacks/meat/corgi
typepath = /obj/item/weapon/reagent_containers/food/snacks/meat/animal/corgi
/datum/theft_objective/traitor/rd_jumpsuit
name = "the research director's jumpsuit"

View File

@@ -41,6 +41,13 @@
other_amounts=list(5)
result=/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh
/datum/biogen_recipe/food/monkeycube
id="monkeycube"
name="monkey cube"
cost=250
other_amounts=list(5)
result=/obj/item/weapon/reagent_containers/food/snacks/monkeycube
/datum/biogen_recipe/nutrient
category="Nutrients"

View File

@@ -245,7 +245,11 @@ obj/machinery/gibber/New()
var/sourcename = src.occupant.real_name
var/sourcejob = src.occupant.job
var/sourcenutriment = src.occupant.nutrition / 15
var/sourcetotalreagents = src.occupant.reagents.total_volume
var/sourcetotalreagents
if(src.occupant.reagents)
sourcetotalreagents = src.occupant.reagents.total_volume
var/totalslabs = src.occupant.size
var/obj/item/weapon/reagent_containers/food/snacks/meat/human/allmeat[totalslabs]
@@ -255,7 +259,10 @@ obj/machinery/gibber/New()
newmeat.subjectname = sourcename
newmeat.subjectjob = sourcejob
newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first
if(src.occupant.reagents)
src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the
allmeat[i] = newmeat
src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by <B>[key_name(user)]</B>" //One shall not simply gib a mob unnoticed!
@@ -299,7 +306,10 @@ obj/machinery/gibber/New()
var/sourcename = victim.real_name
var/sourcejob = victim.job
var/sourcenutriment = victim.nutrition / 15
var/sourcetotalreagents = victim.reagents.total_volume
var/sourcetotalreagents
if(victim.reagents)
sourcetotalreagents = victim.reagents.total_volume
var/totalslabs = victim.size
var/obj/item/weapon/reagent_containers/food/snacks/meat/allmeat[totalslabs]
@@ -318,7 +328,10 @@ obj/machinery/gibber/New()
if(newmeat==null)
return
newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first
if(victim.reagents)
victim.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the
allmeat[i] = newmeat
victim.attack_log += "\[[time_stamp()]\] Was auto-gibbed by <B>[src]</B>" //One shall not simply gib a mob unnoticed!
@@ -336,7 +349,7 @@ obj/machinery/gibber/New()
else
var/obj/effect/decal/cleanable/blood/gibs/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs, Tx)
O.New(Tx,2)
del(victim)
qdel(victim)
spawn(src.gibtime)
playsound(get_turf(src), 'sound/effects/gib2.ogg', 50, 1)
operating = 0

View File

@@ -1831,17 +1831,17 @@ client/proc/check_convertables()
var/dat = ""
for(var/mob/M in player_list)
if(!M.mind)
dat += "[M.real_name]/([ckey(src.key)]): <font color=grey><b>NO MIND</b></font></br>"
dat += "[M.real_name]/([ckey(M.key)]): <font color=grey><b>NO MIND</b></font></br>"
else if(!istype(M,/mob/living/carbon/human))
dat += "[M.real_name]/([ckey(src.key)]): <b>NOT HUMAN</b></br>"
dat += "[M.real_name]/([ckey(M.key)]): <b>NOT HUMAN</b></br>"
else if(!is_convertable_to_cult(M.mind))
dat += "[M.real_name]/([ckey(src.key)]): <font color=red><b>UNCONVERTABLE</b></font></br>"
dat += "[M.real_name]/([ckey(M.key)]): <font color=red><b>UNCONVERTABLE</b></font></br>"
else if(jobban_isbanned(M, "cultist"))
dat += "[M.real_name]/([ckey(src.key)]): <font color=red><b>JOBBANNED</b></font></br>"
dat += "[M.real_name]/([ckey(M.key)]): <font color=red><b>JOBBANNED</b></font></br>"
else if(M.mind in ticker.mode.cult)
dat += "[M.real_name]/([ckey(src.key)]): <font color=blue><b>CULTIST</b></font></br>"
dat += "[M.real_name]/([ckey(M.key)]): <font color=blue><b>CULTIST</b></font></br>"
else
dat += "[M.real_name]/([ckey(src.key)]): <font color=green><b>CONVERTABLE</b></font></br>"
dat += "[M.real_name]/([ckey(M.key)]): <font color=green><b>CONVERTABLE</b></font></br>"
usr << dat

View File

@@ -10,11 +10,12 @@
ASSERT(client_list)
if(asset_name in client_list)
return
return 0
// world << "sending a client the asset '[asset_name]'"
client << browse_rsc(asset_cache[asset_name], asset_name)
client_list += asset_name
. = 1
/proc/send_asset_list(var/client/client, var/list/asset_list)
for(var/asset_name in asset_list)
@@ -268,3 +269,8 @@
var/datum/html_interface/hi = new path()
hi.registerResources()
/datum/asset/simple/chartJS
assets = list("Chart.js" = 'code/modules/html_interface/Chart.js')
/datum/asset/simple/power_chart
assets = list("powerChart.js" = 'code/modules/power/powerChart.js')

View File

@@ -195,9 +195,8 @@
var/s_tone = 0.0
var/created_name = "Buttbot"
proc
transfer_buttdentity(var/mob/living/carbon/H)
name = "[H]'s butt"
/obj/item/clothing/head/butt/proc/transfer_buttdentity(var/mob/living/carbon/H)
name = "[H.real_name]'s butt"
return
/obj/item/clothing/head/tinfoil

View File

@@ -817,8 +817,8 @@
/datum/recipe/corgikabob
items = list(
/obj/item/stack/rods,
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi,
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi,
/obj/item/weapon/reagent_containers/food/snacks/meat/animal/corgi,
/obj/item/weapon/reagent_containers/food/snacks/meat/animal/corgi,
)
result = /obj/item/weapon/reagent_containers/food/snacks/corgikabob
@@ -1527,7 +1527,7 @@
/datum/recipe/cornydog
items = list(
/obj/item/weapon/reagent_containers/food/snacks/grown/corn,
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi,
/obj/item/weapon/reagent_containers/food/snacks/meat/animal/corgi,
/obj/item/stack/rods)
result = /obj/item/weapon/reagent_containers/food/snacks/cornydog

3477
code/modules/html_interface/Chart.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,418 +0,0 @@
/datum/biogen_recipe
var/id=""
var/cost=0
var/category=""
var/name=""
var/amount_per_unit=1
var/list/other_amounts=list()
var/reagent=null
var/result=null
/datum/biogen_recipe/proc/Render(var/context)
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/biogen_recipe/proc/Render() called tick#: [world.time]")
var/html = "<li><a href='?src=\ref[context];action=create;item=[id];num=1'>[amount_per_unit==1?"":"[amount_per_unit] "][name]</a> <FONT COLOR=blue>([cost])</FONT>"
if(other_amounts.len)
var/first=1
html += " ("
for(var/amount in other_amounts)
if(!first)
html +=" "
html +="<A href='?src=\ref[context];action=create;item=[id];num=[amount]'>x[amount*amount_per_unit]</A>"
first=0
html += ")"
html += "</li>"
return html
/datum/biogen_recipe/food
category="Food"
/datum/biogen_recipe/food/milk
id="milk"
name="milk"
reagent="milk"
cost=20
amount_per_unit=10
other_amounts=list(5)
/datum/biogen_recipe/food/meat
id="meat"
name="Slab of meat"
cost=50
other_amounts=list(5)
result=/obj/item/weapon/reagent_containers/food/snacks/meat
/datum/biogen_recipe/food/monkeycube
id="monkeycube"
cost=250
name="monkey cube"
other_amounts=list(5)
result=/obj/item/weapon/reagent_containers/food/snacks/monkeycube
/datum/biogen_recipe/nutrient
category="Nutrients"
/datum/biogen_recipe/nutrient/ez
id="ez"
cost=10
name="E-Z-Nutrient"
other_amounts=list(5)
result=/obj/item/nutrient/ez
/datum/biogen_recipe/nutrient/l4z
id="l4z"
cost=20
name="Left 4 Zed"
other_amounts=list(5)
result=/obj/item/nutrient/l4z
/datum/biogen_recipe/nutrient/rh
id="rh"
cost=25
name="Robust Harvest"
other_amounts=list(5)
result=/obj/item/nutrient/rh
/datum/biogen_recipe/leather
category="Leather"
/datum/biogen_recipe/leather/wallet
cost=100
id="wallet"
name="Wallet"
result=/obj/item/weapon/storage/wallet
/datum/biogen_recipe/leather/gloves
cost=250
id="gloves"
name="Botanical Gloves"
result=/obj/item/clothing/gloves/botanic_leather
/datum/biogen_recipe/leather/belt
cost=300
id="belt"
name="Utility Belt"
result=/obj/item/weapon/storage/belt/utility
/datum/biogen_recipe/leather/plants
cost=350
id="plants"
name="Plant Bag"
result=/obj/item/weapon/storage/bag/plants
/datum/biogen_recipe/leather/satchel
cost=400
id="satchel"
name="Leather Satchel"
result=/obj/item/weapon/storage/backpack/satchel
/datum/biogen_recipe/misc
category="Misc."
/datum/biogen_recipe/misc/pest
cost=40
id="pest"
name="Pest Spray"
other_amounts=list(5)
result=/obj/item/weapon/pestspray
/datum/biogen_recipe/misc/beez
cost=40
id="beez"
name="BeezEez"
other_amounts=list(5)
result=/obj/item/beezeez
/datum/biogen_recipe/misc/cardboard
cost=200
id="cardboard"
name="Cardboard Sheet"
other_amounts=list(5,10)
result=/obj/item/stack/sheet/cardboard
/datum/biogen_recipe/misc/charcoal
cost=100
id="charcoal"
name="Charcoal Sheet"
other_amounts=list(5,10)
result=/obj/item/stack/sheet/charcoal
/datum/biogen_recipe/misc/paper
cost=75
id="paper"
name="Sheet of Paper"
other_amounts=list(5,10)
result=/obj/item/weapon/paper
/obj/machinery/biogenerator
name = "Biogenerator"
desc = ""
icon = 'icons/obj/biogenerator.dmi'
icon_state = "biogen-stand"
density = 1
anchored = 1
use_power = 1
idle_power_usage = 40
var/opened = 0.0
var/processing = 0
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/points = 0
var/menustat = "menu"
var/list/recipes[0]
var/list/recipe_categories[0]
l_color = "#7BF9FF"
power_change()
..()
if(!(stat & (BROKEN|NOPOWER)))
SetLuminosity(2)
else
SetLuminosity(0)
on_reagent_change() //When the reagents change, change the icon as well.
update_icon()
update_icon()
if(!src.beaker)
icon_state = "biogen-empty"
else if(!src.processing)
icon_state = "biogen-stand"
else
icon_state = "biogen-work"
return
/obj/machinery/biogenerator/New()
. = ..()
create_reagents(1000)
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
component_parts = newlist(\
/obj/item/weapon/circuitboard/biogenerator,\
/obj/item/weapon/stock_parts/manipulator,\
/obj/item/weapon/stock_parts/manipulator,\
/obj/item/weapon/stock_parts/matter_bin,\
/obj/item/weapon/stock_parts/matter_bin,\
/obj/item/weapon/stock_parts/micro_laser,\
/obj/item/weapon/stock_parts/micro_laser,\
/obj/item/weapon/stock_parts/micro_laser,\
/obj/item/weapon/stock_parts/scanning_module,\
/obj/item/weapon/stock_parts/scanning_module,\
/obj/item/weapon/stock_parts/console_screen,\
/obj/item/weapon/stock_parts/console_screen\
)
RefreshParts()
for(var/biotype in typesof(/datum/biogen_recipe))
var/datum/biogen_recipe/recipe = new biotype
if(recipe.id=="") continue
if(!(recipe.category in recipe_categories))
recipe_categories[recipe.category]=list()
recipe_categories[recipe.category] += recipe.id
recipes[recipe.id]=recipe
/obj/machinery/biogenerator/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(istype(O, /obj/item/weapon/reagent_containers/glass))
if(beaker)
user << "<span class='warning'>The biogenerator already occuped.</span>"
else
user.before_take_item(O)
O.loc = src
beaker = O
updateUsrDialog()
else if(processing)
user << "<span class='warning'>The biogenerator is currently processing.</span>"
else if(istype(O, /obj/item/weapon/storage/bag/plants))
var/i = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents)
i++
if(i >= 20)
user << "<span class='warning'>The biogenerator is already full! Activate it.</span>"
else
var/obj/item/weapon/storage/bag/B = O
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in O.contents)
B.remove_from_storage(G,src)
i++
if(i >= 20)
user << "<span class='notice'>You fill the biogenerator to its capacity.</span>"
break
if(i<20)
user << "<span class='notice'>You empty the plant bag into the biogenerator.</span>"
else if (istype(O, /obj/item/weapon/screwdriver))
if (!opened)
src.opened = 1
user << "You open the maintenance hatch of [src]."
//src.icon_state = "autolathe_t"
else
src.opened = 0
user << "You close the maintenance hatch of [src]."
//src.icon_state = "autolathe"
return 1
else if(istype(O, /obj/item/weapon/crowbar))
if (opened)
if(beaker)
user << "<span class='warning'>A beaker is loaded, you cannot deconstruct [src].</span>"
return 1
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc)
M.state = 1
M.set_build_state(2)
for(var/obj/I in component_parts)
if(I.reliability != 100 && crit_fail)
I.crit_fail = 1
I.loc = src.loc
del(src)
return 1
else if(!istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown))
user << "<span class='warning'>You cannot put this in [src.name]</span>"
else
var/i = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents)
i++
if(i >= 10)
user << "<span class='warning'>The biogenerator is full! Activate it.</span>"
else
user.before_take_item(O)
O.loc = src
user << "<span class='notice'>You put [O.name] in [src.name]</span>"
update_icon()
return
/obj/machinery/biogenerator/interact(mob/user as mob)
if(stat & BROKEN)
return
user.set_machine(src)
var/dat = "<TITLE>Biogenerator</TITLE>Biogenerator:<BR>"
if (processing)
dat += "<FONT COLOR=red>Biogenerator is processing! Please wait...</FONT>"
else
dat += "Biomass: [points] points.<HR>"
switch(menustat)
if("menu")
if (beaker)
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\biogenerator.dm:89: dat += "<A href='?src=\ref[src];action=activate'>Activate Biogenerator!</A><BR>"
dat += {"<A href='?src=\ref[src];action=activate'>Activate Biogenerator!</A><BR>
<A href='?src=\ref[src];action=detach'>Detach Container</A><BR><BR>"}
for(var/cat in recipe_categories)
dat += "<h2>[cat]</h2><ul>"
for(var/rid in recipe_categories[cat])
var/datum/biogen_recipe/recipe = recipes[rid]
dat += recipe.Render(src)
dat += "</ul>"
else
dat += "<BR><FONT COLOR=red>No beaker inside. Please insert a beaker.</FONT><BR>"
if("nopoints")
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\biogenerator.dm:108: dat += "You do not have biomass to create products.<BR>Please, put growns into reactor and activate it.<BR>"
dat += {"You do not have biomass to create products.<BR>Please, put growns into reactor and activate it.<BR>
<A href='?src=\ref[src];action=menu'>Return to menu</A>"}
// END AUTOFIX
if("complete")
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\biogenerator.dm:111: dat += "Operation complete.<BR>"
dat += {"Operation complete.<BR>
<A href='?src=\ref[src];action=menu'>Return to menu</A>"}
// END AUTOFIX
if("void")
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\biogenerator.dm:114: dat += "<FONT COLOR=red>Error: No growns inside.</FONT><BR>Please, put growns into reactor.<BR>"
dat += {"<FONT COLOR=red>Error: No growns inside.</FONT><BR>Please, put growns into reactor.<BR>
<A href='?src=\ref[src];action=menu'>Return to menu</A>"}
// END AUTOFIX
user << browse(dat, "window=biogenerator")
onclose(user, "biogenerator")
return
/obj/machinery/biogenerator/attack_hand(mob/user as mob)
interact(user)
/obj/machinery/biogenerator/proc/activate()
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/biogenerator/proc/activate() called tick#: [world.time]")
if (usr.stat != 0)
return
if (src.stat != 0) //NOPOWER etc
return
if(src.processing)
usr << "<span class='warning'>The biogenerator is in the process of working.</span>"
return
var/S = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/I in contents)
S += 5
if(I.reagents.get_reagent_amount("nutriment") < 0.1)
points += 1
else points += I.reagents.get_reagent_amount("nutriment")*10
del(I)
if(S)
processing = 1
update_icon()
updateUsrDialog()
playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1)
use_power(S*30)
sleep(S+15)
processing = 0
update_icon()
else
menustat = "void"
return
/obj/machinery/biogenerator/proc/check_cost(var/cost)
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/biogenerator/proc/check_cost() called tick#: [world.time]")
if (cost > points)
menustat = "nopoints"
return 1
else
points -= cost
processing = 1
update_icon()
updateUsrDialog()
sleep(30)
return 0
/obj/machinery/biogenerator/proc/create_product(var/item, var/num)
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/biogenerator/proc/create_product() called tick#: [world.time]")
var/datum/biogen_recipe/recipe=recipes[item]
num=Clamp(num,1,10)
if(check_cost(recipe.cost*num))
return 0
if(recipe.reagent)
beaker.reagents.add_reagent(recipe.reagent,recipe.amount_per_unit*num)
else
if(istype(recipe.result,/obj/item/stack))
var/obj/item/stack/stack=new recipe.result(src.loc)
stack.amount=num*recipe.amount_per_unit
else
for(var/i=0;i<num;i++)
new recipe.result(src.loc)
processing = 0
menustat = "complete"
update_icon()
return 1
/obj/machinery/biogenerator/Topic(href, href_list)
if(..()) return 1
usr.set_machine(src)
//testing(href)
switch(href_list["action"])
if("activate")
activate()
if("detach")
if(beaker)
beaker.loc = src.loc
beaker = null
update_icon()
if("create")
create_product(href_list["item"],text2num(href_list["num"]))
if("menu")
menustat = "menu"
updateUsrDialog()

View File

@@ -414,10 +414,6 @@
icon_state = "bhole3"
desc = "A stable hole in the universe made by a wormhole jaunter. Turbulent doesn't even begin to describe how rough passage through one of these is, but at least it will always get you somewhere near a beacon."
/obj/effect/portal/jaunt_tunnel/New()
sleep(300) // 30s
qdel(src)
/*/obj/effect/portal/wormhole/jaunt_tunnel/teleport(atom/movable/M)
if(istype(M, /obj/effect))
return

View File

@@ -841,3 +841,6 @@ var/list/ai_list = list()
/mob/living/silicon/ai/html_mob_check()
return 1
/mob/living/silicon/ai/isTeleViewing(var/client_eye)
return 1

View File

@@ -441,11 +441,6 @@
else if(ishuman(movement_target.loc) )
if(prob(20))
emote("stares at [movement_target.loc]'s [movement_target] with a sad puppy-face")
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
name = "Corgi meat"
desc = "Tastes like the tears of the station. Gives off the faint aroma of a valid salad. Just like mom used to make. This revalation horrifies you greatly."
//PC stuff-Sieve
/mob/living/simple_animal/corgi/regenerate_icons()

View File

@@ -1459,6 +1459,7 @@ var/list/slot_equipment_priority = list( \
statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button)
if(Sp_HOLDVAR)
statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button)
sleep(world.tick_lag * 2)
// facing verbs
@@ -1779,7 +1780,7 @@ mob/proc/walking()
return
/mob/shuttle_rotate(angle)
src.dir = turn(src.dir, angle) //rotating pixel_x and pixel_y is bad
src.dir = turn(src.dir, -angle) //rotating pixel_x and pixel_y is bad
/mob/can_shuttle_move()
return 1

View File

@@ -1,3 +1,5 @@
#define POWER_MONITOR_HIST_SIZE 15
// the power monitoring computer
// for the moment, just report the status of all APCs in the same powernet
/obj/machinery/power/monitor
@@ -21,14 +23,35 @@
var/datum/html_interface/interface
var/tmp/next_process = 0
//Lists used for the charts.
var/list/demand_hist[0]
var/list/supply_hist[0]
var/list/load_hist[0]
/obj/machinery/power/monitor/New()
..()
var/const/head = "<style type=\"text/css\">span.area { display: block; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; width: auto; }</style>\
<script type=\"text/javascript\">function checkSize(){ $(\"span.area\").css(\"width\", \"auto\");\
if ($(window).width() < window.document.body.scrollWidth){ var width = 0; $(\"span.area\").each(function(){ width = Math.max(width, $(this).parent().outerWidth()); });\
width = Math.round($(window).width() - (window.document.body.scrollWidth - width + 16 + 8));$(\"span.area\").css(\"width\", width + \"px\"); } }\
$(window).on(\"resize\", checkSize); $(window).on(\"onUpdateContent\", checkSize); $(document).on(\"ready\", checkSize);</script>"
for(var/i = 1 to POWER_MONITOR_HIST_SIZE) //The chart doesn't like lists with null.
demand_hist.Add(list(0))
supply_hist.Add(list(0))
load_hist.Add(list(0))
var/head = {"
<style type="text/css">
span.area
{
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: auto;
}
</style>
<script src="Chart.js"></script>
<script>var chartSize = [POWER_MONITOR_HIST_SIZE];</script>
<script src="powerChart.js"></script>
"}
src.interface = new/datum/html_interface/nanotrasen(src, "Power Monitoring", 420, 600, head)
var/obj/structure/cable/attached = null
@@ -39,35 +62,68 @@
powernet = attached.get_powernet()
html_machines += src
/obj/machinery/power/monitor/attack_ai(mob/user)
add_fingerprint(user)
init_ui()
if(stat & (BROKEN|NOPOWER))
return
interact(user)
/obj/machinery/power/monitor/proc/init_ui()
var/dat = {"
<div id="operatable">
<canvas id="powerChart" style="width: 261px;"><!--261px is as much as possible.-->
</canvas>
<div id="legend" style="float: right;"></div>
<table class="table" width="100%; table-layout: fixed;">
<colgroup><col style="width: 180px;"/><col/></colgroup>
<tr><td><strong>Total power:</strong></td><td id="totPower">X W</td></tr>
<tr><td><strong>Total load:</strong></td><td id="totLoad">X W</td></tr>
<tr><td><strong>Total demand:</strong></td><td id="totDemand">X W</td></tr>
</table>
<table class="table" width="100%; table-layout: fixed;">
<colgroup><col/><col style="width: 60px;"/><col style="width: 60px;"/><col style="width: 60px;"/><col style="width: 80px;"/><col style="width: 80px;"/><col style="width: 20px;"/></colgroup>
<thead><tr><th>Area</th><th>Eqp.</th><th>Lgt.</th><th>Env.</th><th align="right">Load</th><th align="right">Cell</th><th></th></tr></thead>
<tbody id="APCTable">
</tbody>
</table>
</div>
<div id="n_operatable" style="display: none;">
<span class="error">No connection.</span>
</div>
"}
interface.updateContent("content", dat)
/obj/machinery/power/monitor/attack_ai(mob/user)
. = attack_hand(user)
/obj/machinery/power/monitor/Destroy()
..()
html_machines -= src
/obj/machinery/power/monitor/attack_hand(mob/user)
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
. = ..()
if(.)
interface.hide(user)
return
interact(user)
//Needs to be overriden because else it will use the shitty set_machine().
/obj/machinery/power/monitor/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi)
return hclient.client.mob.html_mob_check(src.type)
/obj/machinery/power/monitor/interact(mob/user)
var/delay = 0
delay += send_asset(user.client, "Chart.js")
delay += send_asset(user.client, "powerChart.js")
if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) )
if (!(issilicon(user) || isobserver(user)))
user.unset_machine()
src.interface.hide(user)
return
spawn(delay) //To prevent Jscript issues with resource sending.
interface.show(user)
interface.executeJavaScript("makeChart()", user) //Making the chart in something like $("document").ready() won't work so I do it here
user.set_machine(src)
src.interface.show(user)
for(var/i = 1 to POWER_MONITOR_HIST_SIZE)
interface.callJavaScript("pushPowerData", list(demand_hist[i], supply_hist[i], load_hist[i]), user)
/obj/machinery/power/monitor/power_change()
..()
@@ -101,57 +157,66 @@
A.state = 4
A.icon_state = "4"
del(src)
qdel(src)
else
src.attack_hand(user)
return
/obj/machinery/power/monitor/process()
if(stat & (BROKEN|NOPOWER))
if(stat & (BROKEN|NOPOWER) || !powernet)
interface.executeJavaScript("setDisabled()")
return
else
interface.executeJavaScript("setEnabled()")
demand_hist += load()
supply_hist += avail()
load_hist += powernet.viewload
if(demand_hist.len > POWER_MONITOR_HIST_SIZE) //Should always be true but eh.
demand_hist.Cut(1, 2)
supply_hist.Cut(1, 2)
load_hist.Cut(1,2)
interface.callJavaScript("pushPowerData", list(load(), avail(), powernet.viewload))
// src.next_process == 0 is in place to make it update the first time around, then wait until someone watches
if ((!src.next_process || src.interface.isUsed()) && world.time >= src.next_process)
src.next_process = world.time + 30
var/t
// t += "<BR><HR><A href='?src=\ref[src.interface];update=1'>Refresh</A>"
// t += "<BR><HR><A href='?src=\ref[src.interface];close=1'>Close</A>"
if(!powernet)
t += "<span class=\"error\">No connection.</span>"
else
interface.updateContent("totPower", "[avail()] W")
interface.updateContent("totLoad", "[num2text(powernet.viewload,10)] W")
interface.updateContent("totDemand", "[load()] W")
t = t + "<table class=\"table\" width=\"100%; table-layout: fixed;\">"
t = t + "<colgroup><col style=\"width: 180px;\"/><col/></colgroup>"
t = t + "<tr><td><strong>Total power:</strong></td><td>[powernet.avail] W</td></tr>"
t = t + "<tr><td><strong>Total load:</strong></td><td>[num2text(powernet.viewload,10)] W</td></tr>"
var/tbl = ""
var/tbl
var/total_demand = 0
var/list/S = list(" Off","AOff"," On", " AOn")
var/list/chg = list("N","C","F")
var/found = FALSE
var/list/S = list(" <span class='bad'>Off","<span class='bad'>AOff"," <span class='good'>On", " <span class='good'>AOn")
var/list/chg = list(" <span class='bad'>N","<span class='average'>C","<span class='good'>F")
for(var/obj/machinery/power/terminal/term in powernet.nodes)
if(istype(term.master, /obj/machinery/power/apc))
found = TRUE
var/obj/machinery/power/apc/A = term.master
tbl = tbl + "<tr>"
tbl = tbl + "<td><span class=\"area\">["\The [A.areaMaster]"]</span></td>"
tbl = tbl + "<td>[S[A.equipment+1]]</td><td>[S[A.lighting+1]]</td><td>[S[A.environ+1]]</td>"
tbl = tbl + "<td align=\"right\">[A.lastused_total]</td>"
tbl = tbl + "[A.cell ? "<td align=\"right\">[round(A.cell.percent())]%</td><td align=\"right\">[chg[A.charging+1]]" : "<td colspan=\"2\" align=\"right\">N/C</td>"]"
tbl = tbl + "</tr>"
total_demand = total_demand + A.lastused_total
tbl += "<tr>"
tbl += "<td><span class=\"area\">["\The [A.areaMaster]"]</span></td>"
tbl += "<td>[S[A.equipment+1]]</span></td><td>[S[A.lighting+1]]</span></td><td>[S[A.environ+1]]</span></td>"
tbl += "<td align=\"right\">[A.lastused_total]</td>"
if(A.cell)
var/class = "good"
if (found)
t += "<tr><td><strong>Total demand:</strong></td><td>[total_demand] W</td></tr>"
switch(A.cell.percent())
if(49 to 15)
class = "average"
if(15 to -INFINITY)
class = "bad"
t = t + "</table>"
tbl += "<td align='right' class='[class]'>[round(A.cell.percent())]%</td><td align='right'>[chg[A.charging+1]]</span>"
else
tbl += "<td colspan='2' align='right'>N/C</td>"
tbl += "</tr>"
t = t + "<table class=\"table\" width=\"100%; table-layout: fixed;\">"
t = t + "<colgroup><col /><col style=\"width: 60px;\"/><col style=\"width: 60px;\"/><col style=\"width: 60px;\"/><col style=\"width: 80px;\"/><col style=\"width: 80px;\"/><col style=\"width: 20px;\"/></colgroup>"
t = t + "<thead><tr><th>Area</th><th>Eqp.</th><th>Lgt.</th><th>Env.</th><th align=\"right\">Load</th><th align=\"right\">Cell</th><th></th></tr></thead>"
t = t + "<tbody>[tbl]</tbody></table>"
src.interface.updateContent("content", t)
src.interface.updateContent("APCTable", tbl)
#undef POWER_MONITOR_HIST_SIZE

View File

@@ -81,6 +81,12 @@
else
return 0
/obj/machinery/power/proc/load()
if(get_powernet())
return powernet.load
else
return 0
/obj/machinery/power/proc/get_powernet()
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/power/proc/get_powernet() called tick#: [world.time]")
check_rebuild()

View File

@@ -0,0 +1,109 @@
//Note: the var "chartSize" is defined in the power monitor code, in a seperate <script> tag.
var powerChart = null;
function makeChart()
{
var ctx = document.getElementById("powerChart").getContext("2d");
var data = {
labels: ["", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
datasets: [
{
label: "power production",
fillColor: "rgba(100,255,100,0.2)",
strokeColor: "rgba(100,255,100,1)",
pointColor: "rgba(0,255,0,1)",
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
{
label: "power load",
fillColor: "rgba(100,100,255,0.2)",
strokeColor: "rgba(100,100,255,1)",
pointColor: "rgba(0,0,255,1)",
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
{
label: "power usage",
fillColor: "rgba(255,100,100,0.2)",
strokeColor: "rgba(255,100,100,1)",
pointColor: "rgba(255,0,0,1)",
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
]
};
var options = {
scaleLineColor: "#e9c183",
scaleLabel: "<%=formatWatts(value)%>",
multiTooltipTemplate: "<%=formatWatts(value)%>",
scaleFontColor: "#BBBBBB",
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"color:<%=datasets[i].strokeColor%>\">&bull; </span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
};
powerChart = new Chart(ctx).Line(data, options);
$("#legend").html(powerChart.generateLegend());
}
function checkSize()
{
$("span.area").css("width", "auto");
if($(window).width() < window.document.body.scrollWidth)
{
var width = 0;
$("span.area").each(
function()
{
width = Math.max(width, $(this).parent().outerWidth());
}
);
width = Math.round($(window).width() - (window.document.body.scrollWidth - width + 16 + 8));
$("span.area").css("width", width + "px");
}
}
$(window).on("resize", checkSize);
$(window).on("onUpdateContent", checkSize);
$(document).on("ready", checkSize);
function setDisabled()
{
$("#operatable").hide();
$("#n_operatable").show();
}
function setEnabled()
{
$("#operatable").show();
$("#n_operatable").hide();
}
function pushPowerData(demand, supply, load)
{
//Thanks BYOND
if(typeof(demand) == "string")
{
load = parseFloat(load);
supply = parseFloat(supply);
demand = parseFloat(demand);
}
if(powerChart.datasets[0].points.length == 15)
{
powerChart.removeData();
}
powerChart.addData([supply, load, demand], "");
}
var watt_suffixes = ["W", "KW", "MW", "GW", "TW", "PW", "EW", "ZW", "YW"];
function formatWatts(wattage)
{
if(wattage == 0)
{
return "0 W";
}
var i = 0;
while(Math.abs(Math.round(wattage / 1000)) >= 1 && i < watt_suffixes.length)
{
wattage /= 1000;
i++;
}
return "" + wattage + " " + watt_suffixes[i];
}

View File

@@ -15,7 +15,7 @@
/obj/item/weapon/reagent_containers/food/snacks/meat/animal/monkey
/obj/item/weapon/reagent_containers/food/snacks/meat/animal/corgi
desc = "Tastes like... well you know..."
desc = "Tastes like the tears of the station. Gives off the faint aroma of a valid salad. Just like mom used to make. This revelation horrifies you greatly."
/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh
name = "synthetic meat"

View File

@@ -0,0 +1,12 @@
# Your name.
author: Intigracy
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
changes:
- bugfix: Fixed jaunters. They now delete when you spawn the portal, and the portal actually works.

View File

@@ -0,0 +1,5 @@
author: PJB3005
delete-after: true
changes:
- rscadd: The power monitor now has a fancy chart.
- tweak: The power monitor now has colour coding.

View File

@@ -25,7 +25,7 @@
author: N3X15
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
#delete-after: True
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.