Files
Aurora.3/code/game/atoms_movable.dm
Lohikar 0cba68911d Lighting Overhaul & General process improvements (#1612)
This is it. The big one.
Risk: Very large. This modifies or rewrites several important systems.
Some things still need balancing, but that's probably better done if/when this hits dev.

changes:

New smooth lighting system.
Machinery split into three processes: machinery, powernet, pipenet Removed due to breakage. Refactored into multi-step process.
Mob process rewritten.
NanoUI process rewritten.
Objects process rewritten.
Tweaked color output of station lights.
Slime core lights now emit colored light.
Fixed light update frequency issue with fire alarms, hydroponics trays, and airlocks.
Increased light emission from bolted airlocks.
Miscellaneous performance improvements.
New datum pool implementation.
New lighting usage profiler.
Lighting system now tracks UV light, which is not visible to players.
Space now has a parallax effect.
Disabled Spin View verbs due to incompatibility with the new lighting system.
Disabled hallucination view spin due to incompatibility with the new lighting system.
Lighting system now initializes in the lobby before the round starts to reduce BoR deadtime.
Added UV light tracking to lighting engine; dionae now gain energy exclusively from UV light.
Added colored lighting to a few consoles that used default (white) light.
2017-01-29 01:13:54 +02:00

295 lines
8.5 KiB
Plaintext

/atom/movable
layer = 3
var/last_move = null
var/anchored = 0
// var/elevation = 2 - not used anywhere
var/move_speed = 10
var/l_move_time = 1
var/m_flag = 1
var/throwing = 0
var/thrower
var/turf/throw_source = null
var/throw_speed = 2
var/throw_range = 7
var/moved_recently = 0
var/mob/pulledby = null
var/item_state = null // Base name of the image used for when the item is worn. Suffixes are added to this.
//Also used on holdable mobs for the same info related to their held version
var/auto_init = 1
/atom/movable/New()
..()
if (objects_initialized)
if (auto_init)
initialize()
else
objects_init_list += src
/atom/movable/Del()
if(isnull(gcDestroyed) && loc)
testing("GC: -- [type] was deleted via del() rather than qdel() --")
crash_with("GC: -- [type] was deleted via del() rather than qdel() --") // stick a stack trace in the runtime logs
// else if(isnull(gcDestroyed))
// testing("GC: [type] was deleted via GC without qdel()") //Not really a huge issue but from now on, please qdel()
// else
// testing("GC: [type] was deleted via GC with qdel()")
..()
/atom/movable/Destroy()
. = ..()
if(reagents)
qdel(reagents)
reagents = null
for(var/atom/movable/AM in contents)
qdel(AM)
loc = null
if (pulledby)
if (pulledby.pulling == src)
pulledby.pulling = null
pulledby = null
/atom/movable/proc/initialize()
if(!isnull(gcDestroyed))
crash_with("GC: -- [type] had initialize() called after qdel() --")
/atom/movable/Bump(var/atom/A, yes)
if(src.throwing)
src.throw_impact(A)
src.throwing = 0
spawn(0)
if ((A && yes))
A.last_bumped = world.time
A.Bumped(src)
return
..()
return
/atom/movable/proc/forceMove(atom/destination)
if(destination)
if(loc)
loc.Exited(src)
loc = destination
loc.Entered(src)
update_client_hook(loc)
return 1
update_client_hook(loc)
return 0
//called when src is thrown into hit_atom
/atom/movable/proc/throw_impact(atom/hit_atom, var/speed)
if(istype(hit_atom,/mob/living))
var/mob/living/M = hit_atom
M.hitby(src,speed)
else if(isobj(hit_atom))
var/obj/O = hit_atom
if(!O.anchored)
step(O, src.last_move)
O.hitby(src,speed)
else if(isturf(hit_atom))
src.throwing = 0
var/turf/T = hit_atom
if(T.density)
spawn(2)
step(src, turn(src.last_move, 180))
if(istype(src,/mob/living))
var/mob/living/M = src
M.turf_collision(T, speed)
//decided whether a movable atom being thrown can pass through the turf it is in.
/atom/movable/proc/hit_check(var/speed)
if(src.throwing)
for(var/atom/A in get_turf(src))
if(A == src) continue
if(istype(A,/mob/living))
if(A:lying) continue
src.throw_impact(A,speed)
if(isobj(A))
if(A.density && !A.throwpass) // **TODO: Better behaviour for windows which are dense, but shouldn't always stop movement
src.throw_impact(A,speed)
/atom/movable/proc/throw_at(atom/target, range, speed, thrower)
if(!target || !src) return 0
//use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target
src.throwing = 1
src.thrower = thrower
src.throw_source = get_turf(src) //store the origin turf
if(usr)
if(HULK in usr.mutations)
src.throwing = 2 // really strong throw!
var/dist_x = abs(target.x - src.x)
var/dist_y = abs(target.y - src.y)
var/dx
if (target.x > src.x)
dx = EAST
else
dx = WEST
var/dy
if (target.y > src.y)
dy = NORTH
else
dy = SOUTH
var/dist_travelled = 0
var/dist_since_sleep = 0
var/area/a = get_area(src.loc)
if(dist_x > dist_y)
var/error = dist_x/2 - dist_y
while(src && target &&((((src.x < target.x && dx == EAST) || (src.x > target.x && dx == WEST)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf))
// only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up
if(error < 0)
var/atom/step = get_step(src, dy)
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
break
src.Move(step)
hit_check(speed)
error += dist_x
dist_travelled++
dist_since_sleep++
if(dist_since_sleep >= speed)
dist_since_sleep = 0
sleep(1)
else
var/atom/step = get_step(src, dx)
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
break
src.Move(step)
hit_check(speed)
error -= dist_y
dist_travelled++
dist_since_sleep++
if(dist_since_sleep >= speed)
dist_since_sleep = 0
sleep(1)
a = get_area(src.loc)
else
var/error = dist_y/2 - dist_x
while(src && target &&((((src.y < target.y && dy == NORTH) || (src.y > target.y && dy == SOUTH)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf))
// only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up
if(error < 0)
var/atom/step = get_step(src, dx)
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
break
src.Move(step)
hit_check(speed)
error += dist_y
dist_travelled++
dist_since_sleep++
if(dist_since_sleep >= speed)
dist_since_sleep = 0
sleep(1)
else
var/atom/step = get_step(src, dy)
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
break
src.Move(step)
hit_check(speed)
error -= dist_x
dist_travelled++
dist_since_sleep++
if(dist_since_sleep >= speed)
dist_since_sleep = 0
sleep(1)
a = get_area(src.loc)
//done throwing, either because it hit something or it finished moving
if(isobj(src)) src.throw_impact(get_turf(src),speed)
src.throwing = 0
src.thrower = null
src.throw_source = null
//Overlays
/atom/movable/overlay
var/atom/master = null
anchored = 1
/atom/movable/overlay/New()
for(var/x in src.verbs)
src.verbs -= x
..()
/atom/movable/overlay/attackby(a, b)
if (src.master)
return src.master.attackby(a, b)
return
/atom/movable/overlay/attack_hand(a, b, c)
if (src.master)
return src.master.attack_hand(a, b, c)
return
/atom/movable/proc/touch_map_edge()
if(z in config.sealed_levels)
return
if(config.use_overmap)
overmap_spacetravel(get_turf(src), src)
return
var/move_to_z = src.get_transit_zlevel()
if(move_to_z)
z = move_to_z
if(x <= TRANSITIONEDGE)
x = world.maxx - TRANSITIONEDGE - 2
y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
else if (x >= (world.maxx - TRANSITIONEDGE + 1))
x = TRANSITIONEDGE + 1
y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
else if (y <= TRANSITIONEDGE)
y = world.maxy - TRANSITIONEDGE -2
x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
else if (y >= (world.maxy - TRANSITIONEDGE + 1))
y = TRANSITIONEDGE + 1
x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
if(ticker && istype(ticker.mode, /datum/game_mode/nuclear)) //only really care if the game mode is nuclear
var/datum/game_mode/nuclear/G = ticker.mode
G.check_nuke_disks()
spawn(0)
if(loc) loc.Entered(src)
//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there.
var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "6" = 60)
//by default, transition randomly to another zlevel
/atom/movable/proc/get_transit_zlevel()
var/list/candidates = accessible_z_levels.Copy()
candidates.Remove("[src.z]")
if(!candidates.len)
return null
return text2num(pickweight(candidates))
// Parallax stuff.
/atom/movable/proc/update_client_hook(atom/destination)
if(locate(/mob) in src)
for(var/client/C in parallax_on_clients)
if((get_turf(C.eye) == destination) && (C.mob.hud_used))
C.mob.hud_used.update_parallax_values()
/mob/update_client_hook(atom/destination)
if(locate(/mob) in src)
for(var/client/C in parallax_on_clients)
if((get_turf(C.eye) == destination) && (C.mob.hud_used))
C.mob.hud_used.update_parallax_values()
else if(client && hud_used)
hud_used.update_parallax_values()