Files
CHOMPStation2/code/game/atoms_movable.dm
Neerti 0315b18185 Makes Icon Scaling Great
Scaling wasn't great before so no Again.
Makes most icons not get blurry when scaled.
Makes all /atom/movable s able to be scaled with the adjust_scale() proc.
Adds ability for species to get scaled automatically.  Currently no species does this, but it is an option in the future.
Adds four traits to adjust your mob scale.  It is purely cosmetic at this time.
2017-11-14 19:32:49 -05:00

308 lines
8.9 KiB
Plaintext

/atom/movable
layer = 3
appearance_flags = TILE_BOUND|PIXEL_SCALE
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 // Used to specify the item state for the on-mob overlays.
var/icon_scale = 1 // Used to scale icons up or down in update_transform().
var/auto_init = 1
/atom/movable/New()
..()
if(auto_init && ticker && ticker.current_state == GAME_STATE_PLAYING)
if(SScreation && SScreation.map_loading) // If a map is being loaded, newly created objects need to wait for it to finish.
SScreation.atoms_needing_initialize += src
else
initialize()
/atom/movable/Destroy()
. = ..()
if(reagents)
qdel(reagents)
reagents = null
for(var/atom/movable/AM in contents)
qdel(AM)
var/turf/un_opaque
if(opacity && isturf(loc))
un_opaque = loc
loc = null
if(un_opaque)
un_opaque.recalc_atom_opacity()
if (pulledby)
if (pulledby.pulling == src)
pulledby.pulling = null
pulledby = null
/atom/movable/proc/initialize()
if(QDELETED(src))
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(loc == destination)
return 0
var/is_origin_turf = isturf(loc)
var/is_destination_turf = isturf(destination)
// It is a new area if:
// Both the origin and destination are turfs with different areas.
// When either origin or destination is a turf and the other is not.
var/is_new_area = (is_origin_turf ^ is_destination_turf) || (is_origin_turf && is_destination_turf && loc.loc != destination.loc)
var/atom/origin = loc
loc = destination
if(origin)
origin.Exited(src, destination)
if(is_origin_turf)
for(var/atom/movable/AM in origin)
AM.Uncrossed(src)
if(is_new_area && is_origin_turf)
origin.loc.Exited(src, destination)
if(destination)
destination.Entered(src, origin)
if(is_destination_turf) // If we're entering a turf, cross all movable atoms
for(var/atom/movable/AM in loc)
if(AM != src)
AM.Crossed(src)
if(is_new_area && is_destination_turf)
destination.loc.Entered(src, origin)
return 1
//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
if(M.buckled == src)
return // Don't hit the thing we're buckled to.
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
T.hitby(src,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)
continue
// Special handling of windows, which are dense but block only from some directions
if(istype(A, /obj/structure/window))
var/obj/structure/window/W = A
if (!W.is_full_window() && !(turn(src.last_move, 180) & A.dir))
continue
// Same thing for (closed) windoors, which have the same problem
else if(istype(A, /obj/machinery/door/window) && !(turn(src.last_move, 180) & A.dir))
continue
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 using_map.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)
//by default, transition randomly to another zlevel
/atom/movable/proc/get_transit_zlevel()
var/list/candidates = using_map.accessible_z_levels.Copy()
candidates.Remove("[src.z]")
if(!candidates.len)
return null
return text2num(pickweight(candidates))
/atom/movable/proc/update_transform()
var/matrix/M = matrix()
M.Scale(icon_scale)
src.transform = M
// Use this to set the object's scale.
/atom/movable/proc/adjust_scale(new_scale)
icon_scale = new_scale
update_transform()