Merge pull request #3453 from Menshin/Sun_and_solars

Sun and solars
This commit is contained in:
Cheridan
2014-04-20 09:11:50 -05:00
3 changed files with 89 additions and 65 deletions

View File

@@ -1,40 +1,43 @@
#define SOLAR_UPDATE_TIME 600 //duration between two updates of the whole sun/solars positions
/datum/sun
var/angle
var/dx
var/dy
var/counter = 50 // to make the vars update during 1st call
var/rate
var/list/solars // for debugging purposes, references solars_list at the constructor
var/solar_next_update // last time the sun position was checked and adjusted
/datum/sun/New()
solars = solars_list
rate = rand(75,125)/100 // 75% - 125% of standard rotation
if(prob(50))
rate = rand(50,200)/100 // 50% - 200% of standard rotation
if(prob(50)) // same chance to rotate clockwise than counter-clockwise
rate = -rate
solar_next_update = world.time // init the timer
angle = rand (0,360) // the station position to the sun is randomised at round start
// calculate the sun's position given the time of day
// at the standard rate (100%) the angle is increase/decreased by 6 degrees every minute.
// a full rotation thus take a game hour in that case
/datum/sun/proc/calc_position()
counter++
if(counter<50) // count 50 pticks (50 seconds, roughly - about a 5deg change)
return
counter = 0
if(world.time < solar_next_update) //if less than 60 game secondes have passed, do nothing
return;
angle = (360 + angle + rate * 6) % 360 // increase/decrease the angle to the sun, adjusted by the rate
solar_next_update += SOLAR_UPDATE_TIME // since we updated the angle, set the proper time for the next loop
angle = ((rate*world.realtime/100)%360 + 360)%360 // gives about a 60 minute rotation time
// now 45 - 75 minutes, depending on rate
// now calculate and cache the (dx,dy) increments for line drawing
var/s = sin(angle)
var/c = cos(angle)
if(c == 0)
// Either "abs(s) < abs(c)" or "abs(s) >= abs(c)"
// In both cases, the greater is greater than 0, so, no "if 0" check is needed for the divisions
dx = 0
dy = s
else if( abs(s) < abs(c))
if( abs(s) < abs(c))
dx = s / abs(c)
dy = c / abs(c)
@@ -55,6 +58,11 @@
var/obj/machinery/power/tracker/T = M
T.set_angle(angle)
// Solar Control
else if(istype(M, /obj/machinery/power/solar_control))
var/obj/machinery/power/solar_control/C = M
C.tracker_update() //update manual tracker
// Solar Panel
else if(istype(M, /obj/machinery/power/solar))
var/obj/machinery/power/solar/S = M
@@ -62,19 +70,18 @@
occlusion(S)
// for a solar panel, trace towards sun to see if we're in shadow
/datum/sun/proc/occlusion(var/obj/machinery/power/solar/S)
var/ax = S.x // start at the solar panel
var/ay = S.y
var/turf/T = null
for(var/i = 1 to 20) // 20 steps is enough
ax += dx // do step
ay += dy
var/turf/T = locate( round(ax,0.5),round(ay,0.5),S.z)
T = locate( round(ax,0.5),round(ay,0.5),S.z)
if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy) // not obscured if we reach the edge
break

View File

@@ -1,5 +1,3 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
#define SOLAR_MAX_DIST 40
#define SOLARGENRATE 1500
@@ -25,20 +23,19 @@ var/list/solars_list = list()
var/turn_angle = 0
var/obj/machinery/power/solar_control/control = null
/obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S, var/process = 1)
/obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
Make(S)
connect_to_network(process)
connect_to_network()
/obj/machinery/power/solar/disconnect_from_network()
..()
solars_list.Remove(src)
/obj/machinery/power/solar/connect_to_network(var/process)
/obj/machinery/power/solar/connect_to_network()
..()
if(process)
solars_list.Add(src)
if(powernet) //if connected and not already in solar_list...
solars_list |= src //... add it
/obj/machinery/power/solar/proc/Make(var/obj/item/solar_assembly/S)
@@ -47,6 +44,8 @@ var/list/solars_list = list()
S.glass_type = /obj/item/stack/sheet/glass
S.anchored = 1
S.loc = src
if(S.glass_type == /obj/item/stack/sheet/rglass) //if the panel is in reinforced glass
health *= 2 //this need to be placed here, because panels already on the map don't have an assembly linked to
update_icon()
@@ -55,6 +54,7 @@ var/list/solars_list = list()
if(istype(W, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
user << "<span class='notice'>You begin to take the glass off the solar panel...</span>"
if(do_after(user, 50))
var/obj/item/solar_assembly/S = locate() in src
if(S)
@@ -106,21 +106,22 @@ var/list/solars_list = list()
if(obscured)
sunfrac = 0
return
var/p_angle = abs((360+adir)%360 - (360+sun.angle)%360)
//find the smaller angle between the direction the panel is facing and the direction of the sun (the sign is not important here)
var/p_angle = min(abs(adir - sun.angle), 360 - abs(adir - sun.angle))
if(p_angle > 90) // if facing more than 90deg from sun, zero output
sunfrac = 0
return
sunfrac = cos(p_angle) ** 2
sunfrac = cos(p_angle) ** 2
//isn't the power recieved from the incoming light proportionnal to cos(p_angle) (Lambert's cosine law) rather than cos(p_angle)^2 ?
/obj/machinery/power/solar/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
if(stat & BROKEN) return
if(!control) return
if(adir != ndir)
adir = (360+adir+dd_range(-10,10,ndir-adir))%360
update_icon()
update_solar_exposure()
if(stat & BROKEN)
return
if(!sun || !control) //if there's no sun or the panel is not linked to a solar control computer, no need to proceed
return
if(obscured) return
@@ -147,17 +148,20 @@ var/list/solars_list = list()
/obj/machinery/power/solar/ex_act(severity)
switch(severity)
if(1.0)
qdel(src)
if(prob(15))
new /obj/item/weapon/shard( src.loc )
qdel(src)
return
if(2.0)
if (prob(25))
new /obj/item/weapon/shard( src.loc )
qdel(src)
return
if (prob(50))
broken()
if(3.0)
if (prob(25))
broken()
@@ -264,12 +268,12 @@ var/list/solars_list = list()
idle_power_usage = 250
var/id = 0
var/cdir = 0
var/targetdir = 0 // target angle in manual tracking (since it updates every game minute)
var/gen = 0
var/lastgen = 0
var/track = 0 // 0= off 1=timed 2=auto (tracker)
var/trackrate = 600 // 300-900 seconds
var/trackdir = 1 // 0 =CCW, 1=CW
var/nexttime = 0
var/nexttime = 0 // time for a panel to rotate of 1<> in manual tracking
/obj/machinery/power/solar_control/New()
@@ -284,8 +288,8 @@ var/list/solars_list = list()
/obj/machinery/power/solar_control/connect_to_network()
..()
if(powernet)
solars_list.Add(src)
if(powernet) //if connected and not already in solar_list...
solars_list |= src //... add it
/obj/machinery/power/solar_control/initialize()
..()
@@ -324,7 +328,7 @@ var/list/solars_list = list()
if(2)
t += "<A href='?src=\ref[src];track=0'>Off</A> <A href='?src=\ref[src];track=1'>Timed</A> <span class='linkOn'>Auto</span><BR>"
t += "Tracking Rate: [rate_control(src,"tdir","[trackrate] deg/h ([trackrate<0 ? "CCW" : "CW"])",5,30,180)]</div><BR>"
t += "Tracking Rate: [rate_control(src,"tdir","[trackrate] deg/h ([trackrate<0 ? "CCW" : "CW"])",1,30,180)]</div><BR>"
t += "<A href='?src=\ref[src];close=1'>Close</A>"
var/datum/browser/popup = new(user, "solar", name)
@@ -364,7 +368,6 @@ var/list/solars_list = list()
src.attack_hand(user)
return
/obj/machinery/power/solar_control/process()
lastgen = gen
gen = 0
@@ -372,19 +375,23 @@ var/list/solars_list = list()
if(stat & (NOPOWER | BROKEN))
return
if(track==1 && nexttime < world.timeofday && trackrate)
nexttime = world.timeofday + 3600/abs(trackrate)
cdir = (cdir+trackrate/abs(trackrate)+360)%360
set_panels(cdir)
if(track==1 && trackrate)
if(nexttime <= world.time) //every time we need to increase/decrease the angle by 1<>...
targetdir = (targetdir + trackrate/abs(trackrate) + 360) % 360 //... do it
nexttime += 36000/abs(trackrate) //reset the counter for the next 1<>
src.updateDialog()
// called by solar tracker when sun position changes
// or called by the sun controller for manual tracking updates
/obj/machinery/power/solar_control/proc/tracker_update(var/angle)
if(track != 2 || stat & (NOPOWER | BROKEN))
if(stat & (NOPOWER | BROKEN) || track == 0)
return
if (track == 2)
cdir = angle
else if (track == 1 && trackrate) //if manual tracking...
cdir = targetdir //...the current direction is the targetted one (and rotates panels to it)
set_panels(cdir)
src.updateDialog()
@@ -399,29 +406,30 @@ var/list/solars_list = list()
usr.unset_machine()
return
if(href_list["dir"])
cdir = text2num(href_list["dir"])
set_panels(cdir)
if(href_list["rate control"])
if(href_list["cdir"])
src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360)
src.targetdir = src.cdir
if(track == 2) //manual update, so losing auto-tracking
track = 0
spawn(1)
set_panels(cdir)
if(href_list["tdir"])
src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"]))
if(src.trackrate) nexttime = world.timeofday + 3600/abs(trackrate)
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
if(href_list["track"])
if(src.trackrate) nexttime = world.timeofday + 3600/abs(trackrate)
track = text2num(href_list["track"])
if(powernet && (track == 2))
for(var/obj/machinery/power/tracker/T in powernet.nodes)
if(powernet.nodes[T])
cdir = T.sun_angle
T.set_angle(sun.angle)
break
else if (track == 1) //begin manual tracking
src.targetdir = src.cdir
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
set_panels(targetdir)
set_panels(cdir)
src.updateUsrDialog()
return
@@ -433,7 +441,10 @@ var/list/solars_list = list()
if(get_dist(S, src) < SOLAR_MAX_DIST)
if(!S.control)
S.control = src
S.ndir = cdir
S.adir = cdir //instantly rotates the panel
S.update_icon() //and
S.update_solar_exposure() //update it
update_icon()

View File

@@ -13,16 +13,12 @@
directwired = 1
use_power = 0
var/id = 0
var/sun_angle = 0 // sun angle as set by sun datum
/obj/machinery/power/tracker/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
if(!S)
S = new /obj/item/solar_assembly(src)
S.glass_type = /obj/item/stack/sheet/glass
S.tracker = 1
S.anchored = 1
S.loc = src
Make(S)
connect_to_network()
/obj/machinery/power/tracker/disconnect_from_network()
@@ -31,7 +27,17 @@
/obj/machinery/power/tracker/connect_to_network()
..()
solars_list.Add(src)
if(powernet) //if connected and not already in solar_list...
solars_list |= src //... add it
/obj/machinery/power/tracker/proc/Make(var/obj/item/solar_assembly/S)
if(!S)
S = new /obj/item/solar_assembly(src)
S.glass_type = /obj/item/stack/sheet/glass
S.tracker = 1
S.anchored = 1
S.loc = src
update_icon()
// called by datum/sun/calc_position() as sun's angle changes
/obj/machinery/power/tracker/proc/set_angle(var/angle)
@@ -49,11 +55,11 @@
if(get_dist(C, src) < SOLAR_MAX_DIST)
C.tracker_update(angle)
/obj/machinery/power/tracker/attackby(var/obj/item/weapon/W, var/mob/user)
if(istype(W, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
user << "<span class='notice'>You begin to take the glass off the solar tracker...</span>"
if(do_after(user, 50))
var/obj/item/solar_assembly/S = locate() in src
if(S)