mirror of
https://github.com/open-goal/jak-project
synced 2026-08-06 18:03:30 -04:00
481 lines
25 KiB
Common Lisp
481 lines
25 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
(bundles "GAME.CGO")
|
|
(require "engine/collide/collide-cache.gc")
|
|
(require "engine/common-obs/process-drawable.gc")
|
|
|
|
;; DECOMP BEGINS
|
|
|
|
;; Each selected skeleton joint becomes an independently moving fragment. The tuning storage is
|
|
;; overlaid because fountain launches use component-wise velocity ranges, while radial launches use
|
|
;; the same 32 bytes as a focal point plus horizontal and vertical speed ranges.
|
|
(deftype joint-exploder-tuning (structure)
|
|
((explosion uint64)
|
|
(duration time-frame)
|
|
(gravity float)
|
|
(rot-speed float)
|
|
(fountain-rand-transv-lo vector :inline)
|
|
(fountain-rand-transv-hi vector :inline)
|
|
(away-from-focal-pt vector :inline :overlay-at fountain-rand-transv-lo)
|
|
(away-from-rand-transv-xz-lo float :overlay-at (-> fountain-rand-transv-hi x))
|
|
(away-from-rand-transv-xz-hi float :overlay-at (-> fountain-rand-transv-hi y))
|
|
(away-from-rand-transv-y-lo float :overlay-at (-> fountain-rand-transv-hi z))
|
|
(away-from-rand-transv-y-hi float :overlay-at (-> fountain-rand-transv-hi w)))
|
|
(:methods
|
|
(new (symbol type int) _type_)))
|
|
|
|
(deftype joint-exploder-static-joint-params (structure)
|
|
((joint-index int16)
|
|
(parent-joint-index int16)))
|
|
|
|
(deftype joint-exploder-static-params (basic)
|
|
((joints (array joint-exploder-static-joint-params))))
|
|
|
|
(deftype joint-exploder-joint (structure)
|
|
((next int16)
|
|
(prev int16)
|
|
(joint-index int16)
|
|
(rspeed float)
|
|
(mat matrix :inline)
|
|
(rmat matrix :inline)
|
|
(transv vector :inline)
|
|
(prev-pos vector :inline)))
|
|
|
|
(deftype joint-exploder-joints (basic)
|
|
((num-joints int32)
|
|
(joint joint-exploder-joint :inline :dynamic :offset 16))
|
|
(:methods
|
|
(new (symbol type joint-exploder-static-params) _type_)))
|
|
|
|
(deftype joint-exploder-list (structure)
|
|
((head int32)
|
|
(pre-moved? symbol)
|
|
(bbox-valid? symbol)
|
|
(bbox bounding-box :inline)))
|
|
|
|
;; Lists 1 through 4 are spatial buckets for background collision. List 1 starts with every
|
|
;; fragment, and oversized bounds split at their midpoint into any empty bucket in that range.
|
|
;; When all four are occupied, the upper half spills into list 0: it still moves, draws, and
|
|
;; contributes to the overall bounds, but it is not subdivided or tested against the background.
|
|
(deftype joint-exploder (process-drawable)
|
|
((parent-override (pointer process-drawable) :overlay-at parent)
|
|
(die-if-below-y float)
|
|
(die-if-beyond-xz-dist-sqrd float)
|
|
(joints joint-exploder-joints)
|
|
(static-params joint-exploder-static-params)
|
|
(anim art-joint-anim)
|
|
(scale-vector vector :inline)
|
|
(tuning joint-exploder-tuning :inline)
|
|
(lists joint-exploder-list 5 :inline))
|
|
(:methods
|
|
(add-joint! (_type_ joint-exploder-list int) int)
|
|
(grow-bbox! (_type_ joint-exploder-list joint-exploder-joint) none)
|
|
(collide-joints! (_type_ joint-exploder-list) symbol)
|
|
(init-joints! (_type_) symbol)
|
|
(kill-joint! (_type_ joint-exploder-list int) int)
|
|
(integrate-joints! (_type_ joint-exploder-list) symbol)
|
|
(remove-joint! (_type_ joint-exploder-list int) int)
|
|
(split-list! (_type_ joint-exploder-list int) joint-exploder-list)
|
|
(subdivide-list! (_type_ joint-exploder-list) none))
|
|
(:states
|
|
joint-exploder-shatter))
|
|
|
|
(defmethod asize-of ((this joint-exploder-joints))
|
|
"Return the dynamic allocation size: the sixteen-byte header plus 176 bytes per joint."
|
|
(the-as int (+ (-> this type size) (* 176 (-> this num-joints)))))
|
|
|
|
(defmethod new joint-exploder-joints ((allocation symbol) (type-to-make type) (static-params joint-exploder-static-params))
|
|
"Allocate the dynamic joint array sized from static-params."
|
|
(let* ((joint-count (-> static-params joints length))
|
|
(result (object-new allocation type-to-make (the-as int (+ (-> type-to-make size) (* 176 joint-count))))))
|
|
(set! (-> result num-joints) joint-count)
|
|
result))
|
|
|
|
(defun joint-exploder-joint-callback ((exploder joint-exploder))
|
|
"Compose each fragment's spin and simulated base transform into its skeleton joint, then apply
|
|
the current disappearance scale to every skeleton transform."
|
|
(let* ((skeleton-nodes (-> exploder node-list))
|
|
(joint-array (-> exploder joints))
|
|
(i (-> joint-array num-joints)))
|
|
(while (nonzero? i)
|
|
(+! i -1)
|
|
(let* ((joint-data (-> joint-array joint i))
|
|
(bone-transform (-> skeleton-nodes data (-> joint-data joint-index) bone transform)))
|
|
(matrix*! bone-transform (-> joint-data rmat) (-> joint-data mat))))
|
|
(let ((exploder-scale (-> exploder scale-vector)))
|
|
(set! i (-> skeleton-nodes length))
|
|
(while (nonzero? i)
|
|
(+! i -1)
|
|
(let ((scaled-transform (-> skeleton-nodes data i bone transform)))
|
|
(scale-matrix! scaled-transform exploder-scale scaled-transform)))))
|
|
0
|
|
(none))
|
|
|
|
(defmethod kill-joint! ((this joint-exploder) (joint-list joint-exploder-list) (joint-index int))
|
|
"Remove joint-index from joint-list, zero its transform basis, and place it at the exploder
|
|
root so its fragment collapses out of view. Return the following list index."
|
|
(let ((next-index (remove-joint! this joint-list joint-index)))
|
|
(let* ((joint-array (-> this joints))
|
|
(joint-data (-> joint-array joint joint-index)))
|
|
(set! (-> joint-data mat vector 0 quad) (the-as uint128 0))
|
|
(set! (-> joint-data mat vector 1 quad) (the-as uint128 0))
|
|
(set! (-> joint-data mat vector 2 quad) (the-as uint128 0))
|
|
(set! (-> joint-data mat vector 3 quad) (-> this root trans quad)))
|
|
next-index))
|
|
|
|
(defmethod remove-joint! ((this joint-exploder) (joint-list joint-exploder-list) (joint-index int))
|
|
"Unlink joint-index from joint-list's doubly linked index chain and return its former next
|
|
index. Invalidate the bounds when the list becomes empty."
|
|
(let* ((joint-array (-> this joints))
|
|
(joint-data (-> joint-array joint joint-index))
|
|
(previous-index (-> joint-data prev))
|
|
(next-index (-> joint-data next)))
|
|
(cond
|
|
((>= previous-index 0)
|
|
(set! (-> joint-array joint previous-index next) next-index)
|
|
(if (>= next-index 0) (set! (-> (the-as joint-exploder-joint (-> joint-array joint next-index)) prev) previous-index)))
|
|
(else
|
|
(set! (-> joint-list head) next-index)
|
|
(cond
|
|
((>= next-index 0) (let ((next-joint-data (-> joint-array joint next-index))) (set! (-> next-joint-data prev) -1)))
|
|
(else (set! (-> joint-list bbox-valid?) #f)))))
|
|
next-index))
|
|
|
|
(defmethod add-joint! ((this joint-exploder) (joint-list joint-exploder-list) (joint-index int))
|
|
"Insert joint-index at the head of joint-list's doubly linked index chain."
|
|
(let* ((joint-array (-> this joints))
|
|
(joint-data (-> joint-array joint joint-index))
|
|
(old-head-index (-> joint-list head)))
|
|
(set! (-> joint-list head) joint-index)
|
|
(set! (-> joint-data prev) -1)
|
|
(set! (-> joint-data next) old-head-index)
|
|
(when (>= old-head-index 0)
|
|
(set! (-> (the-as joint-exploder-joint (-> joint-array joint old-head-index)) prev) joint-index)
|
|
joint-index)))
|
|
|
|
(defmethod grow-bbox! ((this joint-exploder) (joint-list joint-exploder-list) (joint-data joint-exploder-joint))
|
|
"Expand joint-list's bounds to include joint-data's current and previous positions, so the
|
|
box encloses its complete swept segment for this frame."
|
|
(let ((joint-position (-> joint-data mat vector 3)))
|
|
(cond
|
|
((-> joint-list bbox-valid?) (add-point! (-> joint-list bbox) (the-as vector3s joint-position)))
|
|
(else
|
|
(set! (-> joint-list bbox-valid?) #t)
|
|
(vector-copy! (-> joint-list bbox min) joint-position)
|
|
(vector-copy! (-> joint-list bbox max) joint-position))))
|
|
(add-point! (-> joint-list bbox) (the-as vector3s (-> joint-data prev-pos)))
|
|
(none))
|
|
|
|
(defmethod split-list! ((this joint-exploder) (joint-list joint-exploder-list) (split-axis int))
|
|
"Try to acquire an empty collision bucket from lists 1 through 4, split joint-list at its
|
|
bounding-box midpoint on axis, and move members on the upper side into that bucket. When all
|
|
four are occupied, spill into non-colliding list 0 and return false to stop recursion."
|
|
(local-vars (current-joint joint-exploder-joint) (split-position float) (next-index int))
|
|
(let ((available-list (the-as joint-exploder-list #f)))
|
|
(let ((list-index 1))
|
|
(until (= list-index 5)
|
|
(let ((candidate-list (-> this lists list-index)))
|
|
(when (< (-> candidate-list head) 0)
|
|
(set! available-list candidate-list)
|
|
(goto cfg-6)))
|
|
(+! list-index 1)))
|
|
(label cfg-6)
|
|
(let ((destination-list (the-as object available-list)))
|
|
(cond
|
|
((the-as joint-exploder-list destination-list)
|
|
(set! (-> (the-as joint-exploder-list destination-list) pre-moved?) #t)
|
|
(set! (-> (the-as joint-exploder-list destination-list) bbox-valid?) #f))
|
|
(else (set! destination-list (-> this lists))))
|
|
(set! (-> joint-list bbox-valid?) #f)
|
|
(let ((joint-array (-> this joints))
|
|
(current-index (-> joint-list head)))
|
|
(cond
|
|
((zero? split-axis)
|
|
(set! split-position (* 0.5 (+ (-> joint-list bbox min x) (-> joint-list bbox max x))))
|
|
(while (>= current-index 0)
|
|
(set! current-joint (-> joint-array joint current-index))
|
|
(cond
|
|
((>= (-> current-joint mat vector 3 x) split-position)
|
|
(set! next-index (remove-joint! this joint-list current-index))
|
|
(add-joint! this (the-as joint-exploder-list destination-list) current-index)
|
|
(set! current-index next-index)
|
|
(grow-bbox! this (the-as joint-exploder-list destination-list) current-joint))
|
|
(else (grow-bbox! this joint-list current-joint) (set! current-index (-> current-joint next))))))
|
|
((= split-axis 1)
|
|
(set! split-position (* 0.5 (+ (-> joint-list bbox min y) (-> joint-list bbox max y))))
|
|
(while (>= current-index 0)
|
|
(set! current-joint (-> joint-array joint current-index))
|
|
(cond
|
|
((>= (-> current-joint mat vector 3 y) split-position)
|
|
(set! next-index (remove-joint! this joint-list current-index))
|
|
(add-joint! this (the-as joint-exploder-list destination-list) current-index)
|
|
(set! current-index next-index)
|
|
(grow-bbox! this (the-as joint-exploder-list destination-list) current-joint))
|
|
(else (grow-bbox! this joint-list current-joint) (set! current-index (-> current-joint next))))))
|
|
((= split-axis 2)
|
|
(set! split-position (* 0.5 (+ (-> joint-list bbox min z) (-> joint-list bbox max z))))
|
|
(while (>= current-index 0)
|
|
(set! current-joint (-> joint-array joint current-index))
|
|
(cond
|
|
((>= (-> current-joint mat vector 3 z) split-position)
|
|
(set! next-index (remove-joint! this joint-list current-index))
|
|
(add-joint! this (the-as joint-exploder-list destination-list) current-index)
|
|
(set! current-index next-index)
|
|
(grow-bbox! this (the-as joint-exploder-list destination-list) current-joint))
|
|
(else (grow-bbox! this joint-list current-joint) (set! current-index (-> current-joint next)))))))))
|
|
available-list))
|
|
|
|
(defmethod subdivide-list! ((this joint-exploder) (joint-list joint-exploder-list))
|
|
"Recursively split valid nonempty lists whose X, Y, or Z extent exceeds five metres,
|
|
prioritizing axes in that order. The small boxes limit the background collision-cache work."
|
|
(when (and (-> joint-list bbox-valid?) (>= (-> joint-list head) 0))
|
|
(cond
|
|
((< 20480.0 (- (-> joint-list bbox max x) (-> joint-list bbox min x)))
|
|
(let ((x-split-list (split-list! this joint-list 0))) (if x-split-list (subdivide-list! this x-split-list)))
|
|
(subdivide-list! this joint-list))
|
|
((< 20480.0 (- (-> joint-list bbox max y) (-> joint-list bbox min y)))
|
|
(let ((y-split-list (split-list! this joint-list 1))) (if y-split-list (subdivide-list! this y-split-list)))
|
|
(subdivide-list! this joint-list))
|
|
((< 20480.0 (- (-> joint-list bbox max z) (-> joint-list bbox min z)))
|
|
(let ((z-split-list (split-list! this joint-list 2))) (if z-split-list (subdivide-list! this z-split-list)))
|
|
(subdivide-list! this joint-list))))
|
|
(none))
|
|
|
|
(defmethod integrate-joints! ((this joint-exploder) (joint-list joint-exploder-list))
|
|
"Advance every member of joint-list by one frame of gravity, linear velocity, and local-Z
|
|
spin. Kill fragments outside the vertical or radial limits and rebuild swept bounds for the
|
|
survivors."
|
|
(set! (-> joint-list bbox-valid?) #f)
|
|
(set! (-> joint-list pre-moved?) #t)
|
|
(let ((joint-array (-> this joints))
|
|
(gravity-step (* (-> this tuning gravity) (seconds-per-frame)))
|
|
(current-index (-> joint-list head)))
|
|
(while (>= current-index 0)
|
|
(let* ((joint-data (-> joint-array joint current-index))
|
|
(position (-> joint-data mat vector 3)))
|
|
(set! (-> joint-data prev-pos quad) (-> position quad))
|
|
(+! (-> joint-data transv y) gravity-step)
|
|
(vector-v+! position position (-> joint-data transv))
|
|
(let ((cos-step 0.99)
|
|
(sin-step (* (-> joint-data rspeed) (seconds-per-frame)))
|
|
(r00 (-> joint-data rmat vector 0 x))
|
|
(r01 (-> joint-data rmat vector 0 y))
|
|
(r10 (-> joint-data rmat vector 1 x))
|
|
(r11 (-> joint-data rmat vector 1 y)))
|
|
(set! (-> joint-data rmat vector 0 x) (- (* r00 cos-step) (* r01 sin-step)))
|
|
(set! (-> joint-data rmat vector 0 y) (+ (* r00 sin-step) (* r01 cos-step)))
|
|
(set! (-> joint-data rmat vector 1 x) (- (* r10 cos-step) (* r11 sin-step)))
|
|
(set! (-> joint-data rmat vector 1 y) (+ (* r10 sin-step) (* r11 cos-step))))
|
|
(cond
|
|
((or (< (-> position y) (-> this die-if-below-y))
|
|
(< (-> this die-if-beyond-xz-dist-sqrd) (vector-vector-xz-distance position (-> this root trans))))
|
|
(set! current-index (kill-joint! this joint-list current-index)))
|
|
(else (grow-bbox! this joint-list joint-data) (set! current-index (-> joint-data next)))))))
|
|
#f)
|
|
|
|
(defmethod collide-joints! ((this joint-exploder) (joint-list joint-exploder-list))
|
|
"Fill the shared background collision cache for joint-list, sweep a 0.01-metre sphere along
|
|
each joint's frame motion, and bounce hits with 75 percent horizontal and 70 percent
|
|
vertical speed retention while halving spin."
|
|
(fill-using-bounding-box *collide-cache*
|
|
(-> joint-list bbox)
|
|
(collide-kind background)
|
|
this
|
|
(new 'static 'pat-surface :noentity #x1))
|
|
(let ((joint-array (-> this joints))
|
|
(current-index (-> joint-list head)))
|
|
(while (>= current-index 0)
|
|
(let ((joint-data (-> joint-array joint current-index)))
|
|
(let ((position (-> joint-data mat vector 3))
|
|
(frame-motion (new 'stack-no-clear 'vector))
|
|
(probe-result (new 'stack-no-clear 'collide-tri-result)))
|
|
(vector-! frame-motion position (-> joint-data prev-pos))
|
|
(when (>= (probe-using-line-sphere *collide-cache*
|
|
(-> joint-data prev-pos)
|
|
frame-motion
|
|
40.96
|
|
(collide-kind background)
|
|
probe-result
|
|
(new 'static 'pat-surface :noentity #x1))
|
|
0.0)
|
|
(set! (-> position quad) (-> probe-result intersect quad))
|
|
(let ((horizontal-speed (vector-xz-length (-> joint-data transv))))
|
|
(vector-reflect! (-> joint-data transv) (-> joint-data transv) (-> probe-result normal))
|
|
(let ((vertical-speed (-> joint-data transv y)))
|
|
(set! (-> joint-data transv y) 0.0)
|
|
(vector-normalize! (-> joint-data transv) (* 0.75 horizontal-speed))
|
|
(set! (-> joint-data transv y) (* 0.7 vertical-speed))))
|
|
(+! (-> position y) (* 40.96 (-> probe-result normal y)))
|
|
(set! (-> position w) 1.0)
|
|
(set! (-> joint-data rspeed) (/ (-> joint-data rspeed) 2))))
|
|
(set! current-index (-> joint-data next)))))
|
|
#f)
|
|
|
|
(defstate joint-exploder-shatter (joint-exploder)
|
|
:enter
|
|
(behavior ()
|
|
(set-time! (-> self state-time)))
|
|
:trans
|
|
(behavior ()
|
|
;; Shrink Y to zero after three quarters of the lifetime, then finish collapsing X/Z. Lists
|
|
;; are marked as they move because subdivision can transfer joints into a later list.
|
|
(local-vars (joint-list joint-exploder-list))
|
|
(let* ((elapsed-frames (the float (- (current-time) (-> self state-time))))
|
|
(horizontal-scale (- 1.0 (/ elapsed-frames (the float (-> self tuning duration)))))
|
|
(vertical-scale (- 1.0 (/ elapsed-frames (* 0.75 (the float (-> self tuning duration)))))))
|
|
(if (< vertical-scale 0.0) (set! vertical-scale 0.0))
|
|
(set-vector! (-> self scale-vector) horizontal-scale vertical-scale horizontal-scale 1.0))
|
|
(let ((i 0))
|
|
(while (< i 5)
|
|
(set! (-> self lists i pre-moved?) #f)
|
|
(+! i 1))
|
|
(set! i 0)
|
|
(while (< i 5)
|
|
(set! joint-list (-> self lists i))
|
|
(when (>= (-> joint-list head) 0)
|
|
(when (not (-> joint-list pre-moved?))
|
|
(integrate-joints! self joint-list)
|
|
(if (nonzero? i) (subdivide-list! self joint-list))))
|
|
(+! i 1))
|
|
(let ((combined-bounds (new 'stack-no-clear 'bounding-box)))
|
|
(let ((root-position (-> self root trans)))
|
|
(vector-copy! (-> combined-bounds min) root-position)
|
|
(vector-copy! (-> combined-bounds max) root-position))
|
|
(set! i 0)
|
|
(while (< i 5)
|
|
(set! joint-list (-> self lists i))
|
|
(if (-> joint-list bbox-valid?) (add-box! combined-bounds (-> joint-list bbox)))
|
|
(if (nonzero? i) (collide-joints! self joint-list))
|
|
(+! i 1))
|
|
(let ((draw-bounds (-> self draw bounds)))
|
|
(set-vector! draw-bounds
|
|
(* 0.5 (+ (-> combined-bounds min x) (-> combined-bounds max x)))
|
|
(* 0.5 (+ (-> combined-bounds min y) (-> combined-bounds max y)))
|
|
(* 0.5 (+ (-> combined-bounds min z) (-> combined-bounds max z)))
|
|
1.0)
|
|
(let ((bound-radius (+ 16384.0 (vector-vector-distance draw-bounds (-> combined-bounds max)))))
|
|
(vector-! draw-bounds draw-bounds (-> self root trans))
|
|
(set! (-> draw-bounds w) bound-radius)))))
|
|
0)
|
|
:code
|
|
(behavior ()
|
|
(set-time! (-> self state-time))
|
|
(until (time-elapsed? (-> self state-time) (-> self tuning duration))
|
|
(suspend)
|
|
(ja :num! (loop!))))
|
|
:post ja-post)
|
|
|
|
(defmethod init-joints! ((this joint-exploder))
|
|
"Build each fragment's base transform, spin matrix, linked-list indices, and launch velocity
|
|
from the static joint table and selected explosion style, then seed the main list and bounds."
|
|
(let ((joint-array (-> this joints))
|
|
(i 0))
|
|
(while (< i (-> joint-array num-joints))
|
|
(let ((static-joint (-> this static-params joints i))
|
|
(joint-data (-> joint-array joint i)))
|
|
(let ((parent-index (-> static-joint parent-joint-index)))
|
|
(set! (-> joint-data prev) (+ i -1))
|
|
(set! (-> joint-data next) (+ i 1))
|
|
(set! (-> joint-data joint-index) (-> static-joint joint-index))
|
|
(set! (-> joint-data rspeed) (-> this tuning rot-speed))
|
|
(cond
|
|
((>= parent-index 0)
|
|
(if (zero? parent-index) (set! parent-index (-> static-joint joint-index)))
|
|
(matrix-copy! (-> joint-data mat) (-> this parent-override 0 node-list data parent-index bone transform))
|
|
(matrix-identity! (-> joint-data rmat)))
|
|
(else
|
|
(matrix-copy! (-> joint-data mat) (-> this node-list data (-> static-joint joint-index) bone transform))
|
|
(matrix-identity! (-> joint-data rmat)))))
|
|
(case (-> this tuning explosion)
|
|
((1)
|
|
(vector-! (-> joint-data transv) (-> joint-data mat vector 3) (-> this tuning fountain-rand-transv-lo))
|
|
(vector-normalize! (-> joint-data transv)
|
|
(rand-vu-float-range (-> this tuning fountain-rand-transv-hi x) (-> this tuning fountain-rand-transv-hi y)))
|
|
(+! (-> joint-data transv y)
|
|
(rand-vu-float-range (-> this tuning fountain-rand-transv-hi z) (-> this tuning fountain-rand-transv-hi w)))
|
|
(set! (-> joint-data transv w) 1.0))
|
|
(else
|
|
(let ((velocity-low (-> this tuning fountain-rand-transv-lo))
|
|
(velocity-high (-> this tuning fountain-rand-transv-hi)))
|
|
(set-vector! (-> joint-data transv)
|
|
(rand-vu-float-range (-> velocity-low x) (-> velocity-high x))
|
|
(rand-vu-float-range (-> velocity-low y) (-> velocity-high y))
|
|
(rand-vu-float-range (-> velocity-low z) (-> velocity-high z))
|
|
1.0)))))
|
|
(+! i 1))
|
|
(when (nonzero? (-> joint-array num-joints))
|
|
(let ((last-joint (-> joint-array joint (+ (-> joint-array num-joints) -1)))) (set! (-> last-joint next) -1))
|
|
(let ((main-list (-> this lists 1)))
|
|
(set! (-> main-list head) 0)
|
|
(let ((main-bounds (-> main-list bbox)))
|
|
(let ((first-position (-> joint-array joint 0 mat vector 3)))
|
|
(set! (-> main-bounds min quad) (-> first-position quad))
|
|
(set! (-> main-bounds max quad) (-> first-position quad)))
|
|
(set! i 0)
|
|
(while (< i (-> joint-array num-joints))
|
|
(add-point! main-bounds (the-as vector3s (-> joint-array joint i mat vector 3)))
|
|
(+! i 1))))
|
|
#f)))
|
|
|
|
(defmethod relocate ((this joint-exploder) (offset int))
|
|
"Relocate the separately allocated dynamic joint array, then relocate the drawable."
|
|
(if (nonzero? (-> this joints)) (&+! (-> this joints) offset))
|
|
(the-as joint-exploder ((method-of-type process-drawable relocate) this offset)))
|
|
|
|
(defbehavior joint-exploder-init-by-other joint-exploder ((exploder-sg skeleton-group)
|
|
(animation-index int)
|
|
(tuning joint-exploder-tuning)
|
|
(static-params joint-exploder-static-params))
|
|
"Spawn fragments from parent using exploder-sg and animation-index. Copy tuning, allocate the
|
|
static joint selection, inherit the parent's root transform, pose the animation, initialize the
|
|
fragments, install the post-bind callback, and enter the shatter state."
|
|
(set! (-> self static-params) static-params)
|
|
(set! (-> self die-if-beyond-xz-dist-sqrd) 10485760000.0)
|
|
(mem-copy! (the-as pointer (-> self tuning)) (the-as pointer tuning) 64)
|
|
(set! (-> self joints) (new 'process 'joint-exploder-joints static-params))
|
|
(dotimes (i 5)
|
|
(let ((joint-list (-> self lists i)))
|
|
(set! (-> joint-list head) -1)
|
|
(set! (-> joint-list bbox-valid?) #f)
|
|
(set! (-> joint-list pre-moved?) #f)))
|
|
(logior! (-> self mask) (process-mask enemy))
|
|
(set! (-> self root) (new 'process 'trsqv))
|
|
(vector-copy! (-> self root trans) (-> self parent-override 0 root trans))
|
|
(quaternion-copy! (-> self root quat) (-> self parent-override 0 root quat))
|
|
(vector-copy! (-> self root scale) (-> self parent-override 0 root scale))
|
|
(initialize-skeleton self exploder-sg '())
|
|
(logior! (-> self skel status) (janim-status inited))
|
|
(set! (-> self anim) (the-as art-joint-anim (-> self draw art-group data animation-index)))
|
|
(ja-channel-set! 1)
|
|
(ja :group! (-> self anim) :num! min)
|
|
(ja-post)
|
|
(init-joints! self)
|
|
(set! (-> self die-if-below-y) (+ -102400.0 (-> self root trans y)))
|
|
(set! (-> self skel postbind-function) joint-exploder-joint-callback)
|
|
(go joint-exploder-shatter)
|
|
(none))
|
|
|
|
(defmethod new joint-exploder-tuning ((allocation symbol) (type-to-make type) (explosion-style int))
|
|
"Allocate default tuning for explosion-style. Style 0 uses component-wise random fountain
|
|
velocity; style 1 launches away from a focal point with randomized horizontal and vertical
|
|
speeds."
|
|
(let ((parent-new (method-of-type structure new))
|
|
(requested-type type-to-make))
|
|
(-> type-to-make size)
|
|
(let ((result (the-as joint-exploder-tuning (parent-new allocation requested-type))))
|
|
(set! (-> result explosion) (the-as uint explosion-style))
|
|
(set! (-> result duration) (seconds 2))
|
|
(set! (-> result gravity) -286720.0)
|
|
(set! (-> result rot-speed) 8.4)
|
|
(cond
|
|
((zero? explosion-style)
|
|
(set-vector! (-> result fountain-rand-transv-lo) -81920.0 20480.0 -81920.0 1.0)
|
|
(set-vector! (-> result fountain-rand-transv-hi) 81920.0 61440.0 81920.0 1.0))
|
|
((= explosion-style 1)
|
|
(vector-reset! (-> result fountain-rand-transv-lo))
|
|
(set! (-> result fountain-rand-transv-hi x) 49152.0)
|
|
(set! (-> result fountain-rand-transv-hi y) 163840.0)
|
|
(set! (-> result fountain-rand-transv-hi z) 20480.0)
|
|
(set! (-> result fountain-rand-transv-hi w) 61440.0)))
|
|
result)))
|