mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Implements the Tesla engine and supporting features (#4539)
* Adds "typecache" utility functions. A fast way to filter lists by type. Ported from TG * Ports the "orbit" feature and subsystem from TG * Adds a feature that allows mobs and objs to "orbit" around some atom. They literally are moved around in circles. See the `orbit` proc in orbit.dm. * Adds a subsystem that processes the actual movement of orbiting items. * Adds utility methods for common machinery behavior. * Adds default_unfasten_wrench which handles the standard anchor/unanchor behavior of wrenches being used on machines. Together with the other default_x_tool machinery procs we can eliminate having that code duplicated in dozens of places! * Adds is_wire_tool proc to easily detect when a machine is hit with a tool that should open its wires UI (if it has one). Based on ideas from Paradise, with improvements for us. * Implements the Tesla Engine Ported from a mixture of TG and Paradise code and assets: Edison's Bane Includes the tesla energy ball itself, the generator that makes it, tesla coils, grounding rods, the circuits and frames to build them. * Switch dusting to zapping on impact and spin better Ported /tg SpinAnimation which supports more than triangles.
This commit is contained in:
132
code/datums/orbit.dm
Normal file
132
code/datums/orbit.dm
Normal file
@@ -0,0 +1,132 @@
|
||||
/datum/orbit
|
||||
var/atom/movable/orbiter
|
||||
var/atom/orbiting
|
||||
var/lock = TRUE
|
||||
var/turf/lastloc
|
||||
var/lastprocess
|
||||
|
||||
/datum/orbit/New(_orbiter, _orbiting, _lock)
|
||||
orbiter = _orbiter
|
||||
orbiting = _orbiting
|
||||
SSorbit.processing += src
|
||||
if (!orbiting.orbiters)
|
||||
orbiting.orbiters = list()
|
||||
orbiting.orbiters += src
|
||||
|
||||
if (orbiter.orbiting)
|
||||
orbiter.stop_orbit()
|
||||
orbiter.orbiting = src
|
||||
Check()
|
||||
lock = _lock
|
||||
|
||||
//do not qdel directly, use stop_orbit on the orbiter. (This way the orbiter can bind to the orbit stopping)
|
||||
/datum/orbit/Destroy(force = FALSE)
|
||||
SSorbit.processing -= src
|
||||
if (orbiter)
|
||||
orbiter.orbiting = null
|
||||
orbiter = null
|
||||
if (orbiting)
|
||||
if (orbiting.orbiters)
|
||||
orbiting.orbiters -= src
|
||||
if (!orbiting.orbiters.len)//we are the last orbit, delete the list
|
||||
orbiting.orbiters = null
|
||||
orbiting = null
|
||||
return ..()
|
||||
|
||||
/datum/orbit/proc/Check(turf/targetloc, list/checked_already = list())
|
||||
//Avoid infinite loops for people who end up orbiting themself through another orbiter
|
||||
checked_already[src] = TRUE
|
||||
if (!orbiter)
|
||||
qdel(src)
|
||||
return
|
||||
if (!orbiting)
|
||||
orbiter.stop_orbit()
|
||||
return
|
||||
if (!orbiter.orbiting) //admin wants to stop the orbit.
|
||||
orbiter.orbiting = src //set it back to us first
|
||||
orbiter.stop_orbit()
|
||||
var/atom/movable/AM = orbiting
|
||||
if(istype(AM) && AM.orbiting && AM.orbiting.orbiting == orbiter)
|
||||
orbiter.stop_orbit()
|
||||
return
|
||||
lastprocess = world.time
|
||||
if (!targetloc)
|
||||
targetloc = get_turf(orbiting)
|
||||
if (!targetloc || (!lock && orbiter.loc != lastloc && orbiter.loc != targetloc))
|
||||
orbiter.stop_orbit()
|
||||
return
|
||||
orbiter.loc = targetloc
|
||||
//TODO-LESH-DEL orbiter.update_parallax_contents()
|
||||
orbiter.update_light()
|
||||
lastloc = orbiter.loc
|
||||
for(var/other_orbit in orbiter.orbiters)
|
||||
var/datum/orbit/OO = other_orbit
|
||||
//Skip if checked already
|
||||
if(checked_already[OO])
|
||||
continue
|
||||
OO.Check(targetloc, checked_already)
|
||||
|
||||
/atom/movable/var/datum/orbit/orbiting = null
|
||||
/atom/var/list/orbiters = null
|
||||
|
||||
//A: atom to orbit
|
||||
//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
|
||||
//clockwise: whether you orbit clockwise or anti clockwise
|
||||
//rotation_speed: how fast to rotate (how many ds should it take for a rotation to complete)
|
||||
//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
|
||||
//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
|
||||
//lockinorbit: Forces src to always be on A's turf, otherwise the orbit cancels when src gets too far away (eg: ghosts)
|
||||
|
||||
/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE, lockinorbit = FALSE)
|
||||
if (!istype(A))
|
||||
return
|
||||
|
||||
new/datum/orbit(src, A, lockinorbit)
|
||||
if (!orbiting) //something failed, and our orbit datum deleted itself
|
||||
return
|
||||
var/matrix/initial_transform = matrix(transform)
|
||||
|
||||
//Head first!
|
||||
if (pre_rotation)
|
||||
var/matrix/M = matrix(transform)
|
||||
var/pre_rot = 90
|
||||
if(!clockwise)
|
||||
pre_rot = -90
|
||||
M.Turn(pre_rot)
|
||||
transform = M
|
||||
|
||||
var/matrix/shift = matrix(transform)
|
||||
shift.Translate(0,radius)
|
||||
transform = shift
|
||||
|
||||
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
|
||||
|
||||
//we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
|
||||
transform = initial_transform
|
||||
|
||||
/atom/movable/proc/stop_orbit()
|
||||
SpinAnimation(0,0)
|
||||
qdel(orbiting)
|
||||
|
||||
/atom/Destroy(force = FALSE)
|
||||
. = ..()
|
||||
if (orbiters)
|
||||
for (var/thing in orbiters)
|
||||
var/datum/orbit/O = thing
|
||||
if (O.orbiter)
|
||||
O.orbiter.stop_orbit()
|
||||
|
||||
/atom/movable/Destroy(force = FALSE)
|
||||
. = ..()
|
||||
if (orbiting)
|
||||
stop_orbit()
|
||||
|
||||
/*
|
||||
/atom/movable/proc/transfer_observers_to(atom/movable/target)
|
||||
if(orbiters)
|
||||
for(var/thing in orbiters)
|
||||
var/datum/orbit/O = thing
|
||||
if(O.orbiter && isobserver(O.orbiter))
|
||||
var/mob/dead/observer/D = O.orbiter
|
||||
D.ManualFollow(target)
|
||||
*/
|
||||
18
code/datums/wires/tesla_coil.dm
Normal file
18
code/datums/wires/tesla_coil.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
/datum/wires/tesla_coil
|
||||
wire_count = 1
|
||||
holder_type = /obj/machinery/power/tesla_coil
|
||||
|
||||
var/const/WIRE_ZAP = 1
|
||||
|
||||
/datum/wires/tesla_coil/CanUse(mob/living/L)
|
||||
var/obj/machinery/power/tesla_coil/T = holder
|
||||
if(T && T.panel_open)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/wires/tesla_coil/UpdatePulsed(index)
|
||||
var/obj/machinery/power/tesla_coil/T = holder
|
||||
switch(index)
|
||||
if(WIRE_ZAP)
|
||||
T.zap()
|
||||
..()
|
||||
Reference in New Issue
Block a user