mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
798356802b
* make vis work * update comments
1284 lines
43 KiB
Common Lisp
1284 lines
43 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: sparticle-launcher.gc
|
|
;; name in dgo: sparticle-launcher
|
|
;; dgos: GAME, ENGINE
|
|
|
|
(define *particle-300hz-timer* 0)
|
|
|
|
(deftype sparticle-birthinfo (structure)
|
|
((sprite uint32 :offset-assert 0)
|
|
(anim int32 :offset-assert 4)
|
|
(anim-speed float :offset-assert 8)
|
|
(birth-func basic :offset-assert 12)
|
|
(joint-ppoint int32 :offset-assert 16)
|
|
(num-to-birth float :offset-assert 20)
|
|
(sound basic :offset-assert 24)
|
|
(dataf float 1 :offset 0)
|
|
(data uint32 1 :offset 0)
|
|
)
|
|
:method-count-assert 9
|
|
:size-assert #x1c
|
|
:flag-assert #x90000001c
|
|
)
|
|
|
|
|
|
(defmethod inspect sparticle-launcher ((obj sparticle-launcher))
|
|
"Print out a sparticle-laucher, including its fields"
|
|
(format #t "~X: sparticle-launcher~%" obj)
|
|
(let ((s5-0 0))
|
|
(while (!= (-> obj init-specs s5-0 field) (sp-field-id spt-end))
|
|
(let ((init-spec (-> obj init-specs s5-0)))
|
|
(format #t "~T~S : ~F / #x~X / ~D~%"
|
|
(enum->string sp-field-id (-> init-spec field))
|
|
(-> init-spec initial-valuef)
|
|
(-> init-spec initial-valuef)
|
|
(-> init-spec initial-valuef)
|
|
)
|
|
)
|
|
(+! s5-0 1)
|
|
)
|
|
)
|
|
(the-as sparticle-launcher 0)
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; particle tables
|
|
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; All particle effects (sparticle-launcher) and groups (sparticle-launch-groups) are statically defined
|
|
;; Code defining particle effects should add itself to the tables.
|
|
;; When a level heap is discarded, it should call (unlike-part-group-by-heap <heap>) to remove references to
|
|
;; particle effects that are going to be discarded.
|
|
|
|
;; All the particle launchers.
|
|
;; Particle effects will add themselves to this table when the code is loaded/linked
|
|
(define *part-id-table* (new 'global 'boxed-array sparticle-launcher 3584))
|
|
|
|
|
|
;; All the particle groups.
|
|
(define *part-group-id-table* (new 'global 'boxed-array sparticle-launch-group 1024))
|
|
|
|
(defun lookup-part-group-by-name ((arg0 string))
|
|
"Find a particle group with the given name. Checks all of them, not very efficient."
|
|
(let* ((s5-0 *part-group-id-table*)
|
|
(s4-0 (-> s5-0 length))
|
|
)
|
|
(dotimes (s3-0 s4-0)
|
|
(let ((s2-0 (-> s5-0 s3-0)))
|
|
(if (and (nonzero? s2-0) (string= arg0 (-> s2-0 name)))
|
|
(return (the-as basic s2-0))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(the-as sparticle-launch-group #f)
|
|
)
|
|
|
|
(defun lookup-part-group-pointer-by-name ((arg0 string))
|
|
"Get a (pointer sparticle-launch-group) for the given name. Checks all of them, not very efficient."
|
|
(let* ((s4-0 *part-group-id-table*)
|
|
(s3-0 (-> s4-0 length))
|
|
)
|
|
(dotimes (gp-0 s3-0)
|
|
(let ((v1-2 (-> s4-0 gp-0)))
|
|
(if (and (nonzero? v1-2) (string= arg0 (-> v1-2 name)))
|
|
;;(return (&+ (-> s4-0 data) (* gp-0 4)))
|
|
(return (&-> s4-0 gp-0))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(the-as (pointer sparticle-launch-group) #f)
|
|
)
|
|
|
|
(defun part-group-pointer? ((arg0 pointer))
|
|
"Is the given pointer a pointer that was returned by lookup-part-group-pointer-by-name?"
|
|
(let ((v1-0 *part-group-id-table*))
|
|
;; just check if we are inside the array.
|
|
(and (>= (the-as int arg0) (the-as int (-> v1-0 data)))
|
|
(< (the-as int arg0) (the-as int (&-> v1-0 1024)))
|
|
)
|
|
)
|
|
)
|
|
|
|
(defun unlink-part-group-by-heap ((arg0 kheap))
|
|
"Find all particle groups that are stored in the specified heap and set them to 0."
|
|
(let* ((v1-0 *part-group-id-table*)
|
|
(a2-0 (-> v1-0 length))
|
|
(a1-0 (-> arg0 base))
|
|
(a0-1 (-> arg0 top-base))
|
|
)
|
|
(while (nonzero? a2-0)
|
|
(+! a2-0 -1)
|
|
(let ((a3-2 (-> v1-0 a2-0)))
|
|
(when (and (>= (the-as int a3-2) (the-as int a1-0)) (< (the-as int a3-2) (the-as int a0-1)))
|
|
(set! (-> v1-0 a2-0) (the-as sparticle-launch-group 0))
|
|
0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; particle init
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define-extern sp-init-fields! (function object (inline-array sp-field-init-spec) sp-field-id sp-field-id symbol object))
|
|
(define sp-init-fields! (the (function object (inline-array sp-field-init-spec) sp-field-id sp-field-id symbol object)
|
|
(__pc-get-mips2c "sp-init-fields!")))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; launch queue
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(deftype sp-queued-launch-particles (structure)
|
|
((sp-system sparticle-system :offset-assert 0)
|
|
(sp-launcher sparticle-launcher :offset-assert 4)
|
|
(pos vector :inline :offset-assert 16)
|
|
)
|
|
:method-count-assert 9
|
|
:size-assert #x20
|
|
:flag-assert #x900000020
|
|
)
|
|
|
|
(deftype sp-launch-queue (basic)
|
|
((in-use int32 :offset-assert 4)
|
|
(queue sp-queued-launch-particles 32 :inline :offset-assert 16)
|
|
)
|
|
:method-count-assert 9
|
|
:size-assert #x410
|
|
:flag-assert #x900000410
|
|
)
|
|
|
|
(define *sp-launcher-lock* #f)
|
|
(define *sp-launch-queue* (new 'global 'sp-launch-queue))
|
|
(define *sp-launcher-enable* #t)
|
|
|
|
;;;;;;;;;;;;;;;;;;;
|
|
;; particle adgif
|
|
;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; the particle system can modify the adgif shader as part of particle effects.
|
|
;; it also is responsible for setting up the adgif.
|
|
|
|
(defun particle-setup-adgif ((arg0 adgif-shader) (arg1 texture-id))
|
|
"Set up the adgif for a particle and the given texture."
|
|
|
|
;; grab the texture
|
|
(let ((a1-1 (lookup-texture-by-id arg1)))
|
|
;; set up some texture stuff
|
|
(set! (-> arg0 tex1) (new 'static 'gs-tex1 :mmag #x1 :mmin #x1))
|
|
(set! (-> arg0 tex0 tfx) 0)
|
|
;; get the default adgif settings for this txture
|
|
(if a1-1
|
|
(adgif-shader<-texture! arg0 a1-1)
|
|
)
|
|
)
|
|
|
|
;; we'll use the usual tex0/tex1/miptbp1
|
|
(set! (-> arg0 prims 1) (gs-reg64 tex0-1))
|
|
(set! (-> arg0 prims 3) (gs-reg64 tex1-1))
|
|
(set! (-> arg0 prims 5) (gs-reg64 miptbp1-1))
|
|
|
|
;; clamp will use something weird
|
|
(set! (-> arg0 clamp-reg) (gs-reg64 zbuf-1))
|
|
;; this is sometimes "gs-miptbp" instead.
|
|
(set! (-> arg0 prims 9) (gs-reg64 alpha-1))
|
|
|
|
;; should probably fix this type eventually...
|
|
(set! (-> arg0 alpha) (the gs-miptbp (new 'static 'gs-alpha :b #x1 :d #x1)))
|
|
|
|
;; clamp is actually zbuf for sparticles, not gs-clamp.
|
|
(set! (-> arg0 clamp) (the gs-clamp (new 'static 'gs-zbuf :zbp #x1c0 :psm (gs-psm ct24) :zmsk #x1)))
|
|
0
|
|
(none)
|
|
)
|
|
|
|
;; this is where we'll store the actual adgifs
|
|
(deftype particle-adgif-cache (basic)
|
|
((used int32 :offset-assert 4)
|
|
(last uint16 :offset-assert 8)
|
|
(lastgif adgif-shader :offset-assert 12)
|
|
(tidhash uint16 80 :offset-assert 16)
|
|
(spadgif adgif-shader 80 :inline :offset-assert 176)
|
|
)
|
|
:method-count-assert 9
|
|
:size-assert #x19b0
|
|
:flag-assert #x9000019b0
|
|
)
|
|
|
|
(define *particle-adgif-cache* (new 'global 'particle-adgif-cache))
|
|
(set! (-> *particle-adgif-cache* used) 0)
|
|
|
|
(define-extern particle-adgif (function adgif-shader texture-id none))
|
|
(set! particle-adgif (the (function adgif-shader texture-id none) (__pc-get-mips2c "particle-adgif")))
|
|
|
|
;;;;;;;;;;;;;;;;;;;
|
|
;; launch
|
|
;;;;;;;;;;;;;;;;;;;
|
|
|
|
(defun sp-queue-launch ((arg0 sparticle-system) (arg1 sparticle-launcher) (arg2 vector))
|
|
"Queue a launch from the given launcher, at the given position."
|
|
(let ((v1-0 *sp-launch-queue*))
|
|
|
|
;; make sure we have room in the queue
|
|
(when (= (-> v1-0 in-use) 32)
|
|
(format 0 "ERROR: sp-launch-particles called during processing, and queue is full~%")
|
|
(return 0)
|
|
)
|
|
|
|
;; make a new entry in the queue
|
|
(let ((a3-5 (-> v1-0 queue (-> v1-0 in-use))))
|
|
(set! (-> a3-5 sp-system) arg0)
|
|
(set! (-> a3-5 sp-launcher) arg1)
|
|
(set! (-> a3-5 pos quad) (-> arg2 quad))
|
|
)
|
|
(let ((v0-1 (+ (-> v1-0 in-use) 1)))
|
|
(set! (-> v1-0 in-use) v0-1)
|
|
v0-1
|
|
)
|
|
)
|
|
)
|
|
|
|
(defun sp-adjust-launch ((arg0 sparticle-launchinfo) (arg1 sparticle-cpuinfo) (arg2 (inline-array sp-field-init-spec)))
|
|
"Adjust the fields based on the init-specs"
|
|
(let ((s5-0 (new 'stack-no-clear 'sparticle-launchinfo)))
|
|
(let ((s2-0 (new 'stack-no-clear 'matrix))
|
|
(s3-0 (new 'stack-no-clear 'vector))
|
|
)
|
|
|
|
;; use the field-init-spec to create a totally new launchinfo.
|
|
(sp-init-fields!
|
|
(-> s5-0 launchrot)
|
|
arg2
|
|
(sp-field-id launch-fields-start)
|
|
(sp-field-id launch-fields-end)
|
|
#t
|
|
)
|
|
|
|
;; rotate vel to include the launchrot and conerot
|
|
(matrix-rotate-xyz! s2-0 (-> s5-0 launchrot))
|
|
(vector3s-matrix*!
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
s2-0
|
|
)
|
|
(matrix-rotate-xyz! s2-0 (-> s5-0 conerot))
|
|
(vector3s-matrix*!
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
s2-0
|
|
)
|
|
|
|
;; cone axis (pre-rotation to local, y is default, but there's a flag for z)
|
|
(if (logtest? (sp-cpuinfo-flag launch-along-z) (-> arg1 flags))
|
|
(set-vector! s3-0 0.0 0.0 (-> s5-0 coneradius) 1.0)
|
|
(set-vector! s3-0 0.0 (-> s5-0 coneradius) 0.0 1.0)
|
|
)
|
|
;; rotate cone
|
|
(vector-matrix*! s3-0 s3-0 s2-0)
|
|
;; add to the launch info (this is approximate, but who cares.)
|
|
(+! (-> arg0 launchrot x) (-> s3-0 x))
|
|
(+! (-> arg0 launchrot y) (-> s3-0 y))
|
|
(+! (-> arg0 launchrot z) (-> s3-0 z))
|
|
)
|
|
|
|
|
|
;; if desired, apply addition y rotation.
|
|
(when (!= (-> s5-0 rotate-y) 0.0)
|
|
(let ((s3-1 (new 'stack-no-clear 'matrix)))
|
|
(matrix-rotate-y! s3-1 (-> s5-0 rotate-y))
|
|
(vector3s-rotate*!
|
|
(the-as vector3s (-> arg0 launchrot))
|
|
(the-as vector3s (-> arg0 launchrot))
|
|
s3-1
|
|
)
|
|
(vector3s-rotate*!
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
s3-1
|
|
)
|
|
;; optionally rotate acc.
|
|
(if (zero? (logand (sp-cpuinfo-flag use-global-acc) (-> arg1 flags)))
|
|
(vector3s-rotate*!
|
|
(the-as vector3s (-> arg1 acc))
|
|
(the-as vector3s (-> arg1 acc))
|
|
s3-1
|
|
)
|
|
)
|
|
)
|
|
;; optionally rotate the cone (it seems like this happens too late, but maybe it's okay.)
|
|
(if (logtest? (sp-cpuinfo-flag set-conerot) (-> arg1 flags))
|
|
(set! (-> arg0 conerot y) (+ 16384.0 (-> s5-0 rotate-y)))
|
|
)
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun sp-euler-convert ((arg0 sparticle-launchinfo) (arg1 sparticle-cpuinfo))
|
|
"Convert rotations from euler angles to quaternions."
|
|
(rlet ((vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf2 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(let ((a1-1 (new 'stack-no-clear 'vector))
|
|
(s5-0 (new 'stack-no-clear 'quaternion))
|
|
)
|
|
|
|
;; convert conerot to a quaternion
|
|
(set-vector!
|
|
a1-1
|
|
(-> arg0 conerot x)
|
|
(-> arg0 conerot y)
|
|
(-> arg0 conerot z)
|
|
1.0
|
|
)
|
|
(quaternion-zxy! s5-0 a1-1)
|
|
;; flip the sign of w if needed. the sprite renderer _requires_ that w be positive
|
|
;; because it doesn't actually store w!
|
|
;; this code also preserves w.
|
|
(cond
|
|
((< (-> s5-0 w) 0.0)
|
|
(.lvf vf1 (&-> arg0 conerot quad))
|
|
(.lvf vf2 (&-> s5-0 vec quad))
|
|
(.sub.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> arg0 conerot quad) vf1)
|
|
)
|
|
(else
|
|
(.lvf vf1 (&-> arg0 conerot quad))
|
|
(.lvf vf2 (&-> s5-0 vec quad))
|
|
(.add.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> arg0 conerot quad) vf1)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; scale the rate of rot-syvel (it's multiplied by a rate already)
|
|
(cond
|
|
(*sp-60-hz*
|
|
(set! (-> arg1 rot-syvel x) (* 5.0 (-> arg1 rot-syvel x)))
|
|
(set! (-> arg1 rot-syvel y) (* 5.0 (-> arg1 rot-syvel y)))
|
|
(set! (-> arg1 rot-syvel z) (* 5.0 (-> arg1 rot-syvel z)))
|
|
)
|
|
(else
|
|
(set! (-> arg1 rot-syvel x) (* 6.0 (-> arg1 rot-syvel x)))
|
|
(set! (-> arg1 rot-syvel y) (* 6.0 (-> arg1 rot-syvel y)))
|
|
(set! (-> arg1 rot-syvel z) (* 6.0 (-> arg1 rot-syvel z)))
|
|
)
|
|
)
|
|
;; this one gets stored in a separate rotvel3d.
|
|
(quaternion-zxy! (-> arg1 rotvel3d) (-> arg1 rot-syvel))
|
|
0
|
|
(none)
|
|
)
|
|
)
|
|
|
|
(defun sp-rotate-system ((arg0 sparticle-launchinfo) (arg1 sparticle-cpuinfo) (arg2 transformq))
|
|
"Apply a rotation to the particle launching."
|
|
(let ((s5-0 (new 'stack-no-clear 'matrix)))
|
|
(let ((a1-1 (new 'stack-no-clear 'quaternion)))
|
|
;; sparticle quaternions don't store w, so figure it out.
|
|
(let* ((v1-0 a1-1)
|
|
(a0-1 arg2)
|
|
(f0-0 (-> a0-1 quat x))
|
|
(f1-0 (-> a0-1 quat y))
|
|
(f3-0 (-> a0-1 quat z))
|
|
)
|
|
(set! (-> v1-0 x) f0-0)
|
|
(set! (-> v1-0 y) f1-0)
|
|
(set! (-> v1-0 z) f3-0)
|
|
(set! (-> v1-0 w)
|
|
(sqrtf (- (- (- 1.0 (* f3-0 f3-0)) (* f1-0 f1-0)) (* f0-0 f0-0)))
|
|
)
|
|
)
|
|
(quaternion->matrix s5-0 a1-1)
|
|
)
|
|
;; rotate, preserving z as usual
|
|
(vector3s-rotate*!
|
|
(the-as vector3s (-> arg0 launchrot))
|
|
(the-as vector3s (-> arg0 launchrot))
|
|
s5-0
|
|
)
|
|
(vector3s-rotate*!
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
(the-as vector3s (-> arg1 vel-sxvel))
|
|
s5-0
|
|
)
|
|
;; also rotate acc if we would have done it previously.
|
|
(if (zero? (logand (sp-cpuinfo-flag use-global-acc) (-> arg1 flags)))
|
|
(vector3s-rotate*!
|
|
(the-as vector3s (-> arg1 acc))
|
|
(the-as vector3s (-> arg1 acc))
|
|
s5-0
|
|
)
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(define-extern sp-launch-particles-var (function sparticle-system sparticle-launcher vector sparticle-launch-state sparticle-launch-control float none)) ;; asm - ret not confirmed
|
|
(set! sp-launch-particles-var
|
|
(the (function sparticle-system sparticle-launcher vector sparticle-launch-state sparticle-launch-control float none)
|
|
(__pc-get-mips2c "sp-launch-particles-var")))
|
|
|
|
;;;;;;;;;;;;;;;
|
|
;; enemy death
|
|
;;;;;;;;;;;;;;;
|
|
|
|
;; for whatever reason the enemy death launch stuff is defined here.
|
|
;; it doesn't use the adgif cache.
|
|
;; but it's a nice example for how to set the
|
|
|
|
(define *death-adgif* (the-as adgif-shader #f))
|
|
|
|
(defun sp-launch-particles-death ((arg0 sparticle-system) (arg1 sparticle-launcher) (arg2 vector))
|
|
(rlet ((vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf2 :class vf)
|
|
(vf3 :class vf)
|
|
(vf30 :class vf)
|
|
(vf31 :class vf)
|
|
(vf4 :class vf)
|
|
(vf5 :class vf)
|
|
(vf6 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(.lvf vf30 (&-> arg2 quad))
|
|
(let ((v1-0 #x437f0000))
|
|
(.mov vf31 v1-0)
|
|
)
|
|
|
|
(let ((s5-0 (new 'stack-no-clear 'sprite-vec-data-2d))
|
|
;; get a particle, from the particle system
|
|
;; this gets us a "cpuinfo", which is the state of a particle.
|
|
(gp-0 (sp-get-particle arg0 0 (the-as sparticle-launch-state #f)))
|
|
)
|
|
(if (not gp-0)
|
|
;; if it fails, give up.
|
|
(return 0)
|
|
)
|
|
|
|
(let* ((a1-2 (-> arg1 init-specs 0))
|
|
;; initialize the sprite fields. this is done to a temporary structure on the stack
|
|
;; the death particle effect has some special initialization stuff below that will
|
|
;; modify this data before setting the actual sprite data.
|
|
(a1-3 (sp-init-fields!
|
|
(&-> s5-0 x)
|
|
(the-as (inline-array sp-field-init-spec) a1-2)
|
|
(sp-field-id sprite-fields-start)
|
|
(sp-field-id sprite-fields-end)
|
|
#t
|
|
)
|
|
)
|
|
)
|
|
|
|
;; initialize the cpu fields, this is the initial particle state.
|
|
(sp-init-fields!
|
|
(&-> gp-0 omega)
|
|
(the-as (inline-array sp-field-init-spec) a1-3)
|
|
(sp-field-id cpu-fields-start)
|
|
(sp-field-id cpu-fields-end)
|
|
#t
|
|
)
|
|
)
|
|
|
|
;; convert rotations
|
|
(set! (-> s5-0 matrix) 0)
|
|
(set! (-> s5-0 rot) (the float (sar (shl (the int (-> s5-0 rot)) 48) 48)))
|
|
|
|
;; convert color/position.
|
|
(.lvf vf4 (&-> s5-0 color quad))
|
|
(.lvf vf5 (&-> s5-0 x-y-z-sx quad))
|
|
(.min.x.vf vf4 vf4 vf31 :mask #b111)
|
|
(.add.vf vf5 vf5 vf30 :mask #b111)
|
|
(.svf (&-> s5-0 color quad) vf4)
|
|
(.svf (&-> s5-0 x-y-z-sx quad) vf5)
|
|
|
|
(when (not *death-adgif*)
|
|
;; first time we get here, set up the adgif shader.
|
|
(set! *death-adgif* (new 'static 'adgif-shader))
|
|
(particle-adgif *death-adgif* (new 'static 'texture-id :index #x18 :page #x2))
|
|
(set! (-> *death-adgif* alpha) (new 'static 'gs-miptbp :tbp1 #x48)) ;; I think this is actually an alpha?
|
|
)
|
|
|
|
;; copy the death-adgif to the adgif of our particle
|
|
(let ((v1-14 (-> *death-adgif* quad 0 quad)))
|
|
(set! (-> gp-0 adgif quad 0 quad) v1-14)
|
|
)
|
|
(let ((v1-16 (-> *death-adgif* quad 1 quad)))
|
|
(set! (-> gp-0 adgif quad 1 quad) v1-16)
|
|
)
|
|
(let ((v1-18 (-> *death-adgif* quad 2 quad)))
|
|
(set! (-> gp-0 adgif quad 2 quad) v1-18)
|
|
)
|
|
(let ((v1-20 (-> *death-adgif* quad 3 quad)))
|
|
(set! (-> gp-0 adgif quad 3 quad) v1-20)
|
|
)
|
|
(let ((v1-22 (-> *death-adgif* quad 4 quad)))
|
|
(set! (-> gp-0 adgif quad 4 quad) v1-22)
|
|
)
|
|
|
|
;; set up some color stuff.
|
|
(.lvf vf4 (&-> (-> *time-of-day-context* current-prt-color) quad))
|
|
(.lvf vf5 (&-> s5-0 color quad))
|
|
(.lvf vf6 (&-> gp-0 fade quad))
|
|
(.mul.vf vf5 vf5 vf4 :mask #b111)
|
|
(.mul.vf vf6 vf6 vf4 :mask #b111)
|
|
(.svf (&-> s5-0 color quad) vf5)
|
|
(.svf (&-> gp-0 fade quad) vf6)
|
|
|
|
;;
|
|
(set! (-> gp-0 key) (the-as sparticle-launch-control 0))
|
|
(set! (-> gp-0 binding) #f)
|
|
|
|
;; copy the sprite data
|
|
(let ((v1-26 (-> gp-0 sprite)))
|
|
(.lvf vf1 (&-> s5-0 x-y-z-sx quad))
|
|
(.lvf vf2 (&-> s5-0 flag-rot-sy quad))
|
|
(.lvf vf3 (&-> s5-0 color quad))
|
|
(.svf (&-> v1-26 x-y-z-sx quad) vf1)
|
|
(.svf (&-> v1-26 flag-rot-sy quad) vf2)
|
|
(.sub.w.vf vf3 vf0 vf0 :mask #b1000)
|
|
(.svf (&-> v1-26 color quad) vf3)
|
|
)
|
|
|
|
;; we're done!
|
|
(logior! (-> gp-0 flags) (sp-cpuinfo-flag ready-to-launch))
|
|
(set! (-> gp-0 cache-alpha) (-> s5-0 a))
|
|
|
|
;; I'm not really sure how the particles get launched from here yet.
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
)
|
|
|
|
|
|
(defun sp-clear-queue ()
|
|
"Launch all particles in the queue."
|
|
(let ((gp-0 *sp-launch-queue*))
|
|
(when (> (-> gp-0 in-use) 0)
|
|
(dotimes (s5-0 (-> gp-0 in-use))
|
|
(let ((v1-4 (-> gp-0 queue s5-0)))
|
|
(sp-launch-particles-var
|
|
(-> v1-4 sp-system)
|
|
(-> v1-4 sp-launcher)
|
|
(-> v1-4 pos)
|
|
(the-as sparticle-launch-state #f)
|
|
(the-as sparticle-launch-control #f)
|
|
1.0
|
|
)
|
|
)
|
|
)
|
|
(set! (-> gp-0 in-use) 0)
|
|
0
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun sp-relaunch-setup-fields ((arg0 object) (arg1 sparticle-launcher) (arg2 sparticle-cpuinfo) (arg3 sprite-vec-data-3d))
|
|
"Reset fields of an existing particle"
|
|
(let ((a1-1 (-> arg1 init-specs 0))
|
|
(s4-0 (logand (-> arg2 flags) (sp-cpuinfo-flag level0 level1)))
|
|
)
|
|
(set! (-> arg2 next-launcher) (the-as basic 0))
|
|
(cond
|
|
((and (logtest? (-> arg2 flags) (sp-cpuinfo-flag bit12))
|
|
(zero? (logand (-> arg2 flags) (sp-cpuinfo-flag aux-list)))
|
|
)
|
|
(let ((f20-0 (-> arg3 r-g-b-a x))
|
|
(f22-0 (-> arg3 r-g-b-a y))
|
|
(f24-0 (-> arg3 r-g-b-a z))
|
|
(f26-0 (-> arg2 fade x))
|
|
(f28-0 (-> arg2 fade y))
|
|
(f30-0 (-> arg2 fade z))
|
|
)
|
|
(set! (-> arg3 r-g-b-a x) 99999.0)
|
|
(set! (-> arg3 r-g-b-a y) 99999.0)
|
|
(set! (-> arg3 r-g-b-a z) 99999.0)
|
|
(set! (-> arg2 fade x) 99999.0)
|
|
(set! (-> arg2 fade y) 99999.0)
|
|
(set! (-> arg2 fade z) 99999.0)
|
|
(let ((a1-2 (sp-init-fields!
|
|
(-> arg3 x-y-z-sx)
|
|
(the-as (inline-array sp-field-init-spec) a1-1)
|
|
(sp-field-id sprite-fields-start)
|
|
(sp-field-id sprite-fields-end)
|
|
#f
|
|
)
|
|
)
|
|
)
|
|
(sp-init-fields!
|
|
(&-> arg2 omega)
|
|
(the-as (inline-array sp-field-init-spec) a1-2)
|
|
(sp-field-id cpu-fields-start)
|
|
(sp-field-id cpu-fields-end)
|
|
#f
|
|
)
|
|
)
|
|
;; clear all flags except for the level.
|
|
(logior! (-> arg2 flags) s4-0)
|
|
(if (logtest? (-> arg2 flags) (sp-cpuinfo-flag level1))
|
|
(-> *level* level1)
|
|
(-> *level* level0)
|
|
)
|
|
(let ((v1-16 (-> *time-of-day-context* current-prt-color)))
|
|
(if (= (-> arg3 r-g-b-a x) 99999.0)
|
|
(set! (-> arg3 r-g-b-a x) f20-0)
|
|
(set! (-> arg3 r-g-b-a x) (* (-> arg3 r-g-b-a x) (-> v1-16 x)))
|
|
)
|
|
(if (= (-> arg3 r-g-b-a y) 99999.0)
|
|
(set! (-> arg3 r-g-b-a y) f22-0)
|
|
(set! (-> arg3 r-g-b-a y) (* (-> arg3 r-g-b-a y) (-> v1-16 y)))
|
|
)
|
|
(if (= (-> arg3 r-g-b-a z) 99999.0)
|
|
(set! (-> arg3 r-g-b-a z) f24-0)
|
|
(set! (-> arg3 r-g-b-a z) (* (-> arg3 r-g-b-a z) (-> v1-16 z)))
|
|
)
|
|
(if (= (-> arg2 fade x) 99999.0)
|
|
(set! (-> arg2 fade x) f26-0)
|
|
(set! (-> arg2 fade x) (* (-> arg2 fade x) (-> v1-16 x)))
|
|
)
|
|
(if (= (-> arg2 fade y) 99999.0)
|
|
(set! (-> arg2 fade y) f28-0)
|
|
(set! (-> arg2 fade y) (* (-> arg2 fade y) (-> v1-16 y)))
|
|
)
|
|
(if (= (-> arg2 fade z) 99999.0)
|
|
(set! (-> arg2 fade z) f30-0)
|
|
(set! (-> arg2 fade z) (* (-> arg2 fade z) (-> v1-16 z)))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(else
|
|
(let ((a1-3 (sp-init-fields!
|
|
(-> arg3 x-y-z-sx)
|
|
(the-as (inline-array sp-field-init-spec) a1-1)
|
|
(sp-field-id sprite-fields-start)
|
|
(sp-field-id sprite-fields-end)
|
|
#f
|
|
)
|
|
)
|
|
)
|
|
(sp-init-fields!
|
|
(&-> arg2 omega)
|
|
(the-as (inline-array sp-field-init-spec) a1-3)
|
|
(sp-field-id cpu-fields-start)
|
|
(sp-field-id cpu-fields-end)
|
|
#f
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun sp-relaunch-particle-2d ((arg0 object) (arg1 sparticle-launcher) (arg2 sparticle-cpuinfo) (arg3 sprite-vec-data-3d))
|
|
"relaunch a 2d particle"
|
|
(sp-relaunch-setup-fields arg0 arg1 arg2 arg3)
|
|
(when (logtest? (-> arg2 flags) (sp-cpuinfo-flag aux-list))
|
|
(set! (-> arg2 func) add-to-sprite-aux-list)
|
|
(set! (-> arg3 r-g-b-a w) 0.0)
|
|
(set! (-> arg2 fade w) 0.0)
|
|
(logclear! (-> arg2 flags) (sp-cpuinfo-flag bit2))
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun sp-relaunch-particle-3d ((arg0 object) (arg1 sparticle-launcher) (arg2 sparticle-cpuinfo) (arg3 sprite-vec-data-3d))
|
|
"relaunch a 3d particle"
|
|
|
|
;; do all the 3d-specific stuff here, the general relaunch only does 2d fields.
|
|
(rlet ((vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf2 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(let ((s4-0 (new 'stack-no-clear 'quaternion)))
|
|
(let* ((v1-0 s4-0)
|
|
(a2-1 arg3)
|
|
(f0-0 (-> a2-1 qx-qy-qz-sy x))
|
|
(f1-0 (-> a2-1 qx-qy-qz-sy y))
|
|
(f3-0 (-> a2-1 qx-qy-qz-sy z))
|
|
)
|
|
(set! (-> v1-0 x) f0-0)
|
|
(set! (-> v1-0 y) f1-0)
|
|
(set! (-> v1-0 z) f3-0)
|
|
(set!
|
|
(-> v1-0 w)
|
|
(sqrtf (- (- (- 1.0 (* f3-0 f3-0)) (* f1-0 f1-0)) (* f0-0 f0-0)))
|
|
)
|
|
)
|
|
(set! (-> arg3 qx-qy-qz-sy x) 0.0)
|
|
(set! (-> arg3 qx-qy-qz-sy y) 0.0)
|
|
(set! (-> arg3 qx-qy-qz-sy z) 0.0)
|
|
(sp-relaunch-setup-fields arg0 arg1 arg2 arg3)
|
|
(let ((a1-1 (new 'stack-no-clear 'vector))
|
|
(s3-0 (new 'stack-no-clear 'quaternion))
|
|
)
|
|
(set-vector!
|
|
a1-1
|
|
(-> arg3 qx-qy-qz-sy x)
|
|
(-> arg3 qx-qy-qz-sy y)
|
|
(-> arg3 qx-qy-qz-sy z)
|
|
1.0
|
|
)
|
|
(quaternion-zxy! s3-0 a1-1)
|
|
(cond
|
|
((logtest? (sp-cpuinfo-flag left-multiply-quat) (-> arg2 flags))
|
|
(quaternion*! s3-0 s4-0 s3-0)
|
|
)
|
|
(else
|
|
(if (logtest? (sp-cpuinfo-flag right-multiply-quat) (-> arg2 flags))
|
|
(quaternion*! s3-0 s3-0 s4-0)
|
|
)
|
|
)
|
|
)
|
|
(cond
|
|
((< (-> s3-0 w) 0.0)
|
|
(.lvf vf1 (&-> arg3 qx-qy-qz-sy quad))
|
|
(.lvf vf2 (&-> s3-0 vec quad))
|
|
(.sub.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> arg3 qx-qy-qz-sy quad) vf1)
|
|
)
|
|
(else
|
|
(.lvf vf1 (&-> arg3 qx-qy-qz-sy quad))
|
|
(.lvf vf2 (&-> s3-0 vec quad))
|
|
(.add.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> arg3 qx-qy-qz-sy quad) vf1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(cond
|
|
(*sp-60-hz*
|
|
(set! (-> arg2 rot-syvel x) (* 5.0 (-> arg2 rot-syvel x)))
|
|
(set! (-> arg2 rot-syvel y) (* 5.0 (-> arg2 rot-syvel y)))
|
|
(set! (-> arg2 rot-syvel z) (* 5.0 (-> arg2 rot-syvel z)))
|
|
)
|
|
(else
|
|
(set! (-> arg2 rot-syvel x) (* 6.0 (-> arg2 rot-syvel x)))
|
|
(set! (-> arg2 rot-syvel y) (* 6.0 (-> arg2 rot-syvel y)))
|
|
(set! (-> arg2 rot-syvel z) (* 6.0 (-> arg2 rot-syvel z)))
|
|
)
|
|
)
|
|
(quaternion-zxy! (-> arg2 rotvel3d) (-> arg2 rot-syvel))
|
|
0
|
|
(none)
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;
|
|
;; launch control
|
|
;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; a launch-control is an instance of a particle effect group. it holds the definition and the state.
|
|
;; the launch-controls are always associated with a process. this allows the memory to be reclaimed once the
|
|
;; particles are despawned.
|
|
|
|
(defmethod initialize sparticle-launch-control ((obj sparticle-launch-control) (arg0 sparticle-launch-group) (arg1 process))
|
|
"start a particle effect."
|
|
(let ((s5-0 0))
|
|
;; init
|
|
(set! (-> obj group) arg0)
|
|
(set! (-> obj proc) arg1)
|
|
(set! (-> obj local-clock) 0)
|
|
(set! (-> obj fade) 1.0)
|
|
(set! (-> obj matrix) 0)
|
|
(set! (-> obj last-spawn-frame)
|
|
(+ (-> *display* real-actual-frame-counter) -2)
|
|
)
|
|
(set! (-> obj last-spawn-time) 0)
|
|
|
|
;; iterate through the effects in the group
|
|
(dotimes (s3-0 (-> arg0 length))
|
|
|
|
(let* ((a0-2 (-> arg0 launcher s3-0)) ;; the group-item (definition of the effect)
|
|
(a1-2 (-> *part-id-table* (-> a0-2 launcher))) ;; the actual effect for the group item
|
|
(v1-9 (-> obj data s5-0)) ;; our state for this particular instance of this effect within the group.
|
|
)
|
|
(when (nonzero? a1-2)
|
|
(set! (-> v1-9 group-item) a0-2)
|
|
(cond
|
|
((= (-> a1-2 type) sparticle-launcher)
|
|
;; init state
|
|
(set! (-> v1-9 accum) 0.0)
|
|
(set! (-> v1-9 spawn-time)
|
|
(the-as uint (+ *particle-300hz-timer* -30000))
|
|
)
|
|
(set! (-> v1-9 offset) (-> a0-2 offset))
|
|
(set! (-> v1-9 randomize) (the-as uint 0))
|
|
(cond
|
|
((logtest? (-> a0-2 flags) (sp-group-item-flag start-dead))
|
|
;; if we aren't immediate
|
|
(logclear! (-> v1-9 flags) (sp-launch-state-flags launcher-active))
|
|
(set! (-> v1-9 origin) #f)
|
|
(set! (-> v1-9 sprite3d) #f)
|
|
(set! (-> v1-9 sprite) #f)
|
|
)
|
|
(else
|
|
(logior! (-> v1-9 flags) (sp-launch-state-flags launcher-active))
|
|
;; set the position now.
|
|
(set! (-> v1-9 origin) (-> obj center))
|
|
(set! (-> v1-9 sprite3d) #f)
|
|
(set! (-> v1-9 sprite) #f)
|
|
)
|
|
)
|
|
(+! s5-0 1)
|
|
)
|
|
(else
|
|
(format 0 "initialize called with non-particle-launcher~%")
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set! (-> obj length) s5-0)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod create-launch-control sparticle-launch-group ((obj sparticle-launch-group) (arg0 process))
|
|
"create a launch-control to hold the state of the particles. stored on the process heap."
|
|
(let ((gp-0 (the-as object (new 'process 'sparticle-launch-control (-> obj length)))))
|
|
(when (zero? (the-as sparticle-launch-control gp-0))
|
|
(go process-drawable-art-error "memory")
|
|
(set! gp-0 0)
|
|
(goto cfg-4)
|
|
)
|
|
(initialize (the-as sparticle-launch-control gp-0) obj arg0)
|
|
(label cfg-4)
|
|
(the-as sparticle-launch-control gp-0)
|
|
)
|
|
)
|
|
|
|
(defmethod kill-and-free-particles sparticle-launch-control ((obj sparticle-launch-control))
|
|
"kill all the particles"
|
|
|
|
;; clear the flag.
|
|
(countdown (v1-0 (-> obj length))
|
|
(let ((a0-3 (-> obj data v1-0)))
|
|
(logclear! (-> a0-3 flags) (sp-launch-state-flags particles-active))
|
|
)
|
|
)
|
|
(set! (-> obj local-clock) 0)
|
|
(set! (-> obj fade) 1.0)
|
|
|
|
;; kill the particles (let them go back to the sparticle system.)
|
|
(kill-all-particles-with-key obj)
|
|
;; release matrices
|
|
(if (> (-> obj matrix) 0)
|
|
(sprite-release-user-hvdf (-> obj matrix))
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod kill-particles sparticle-launch-control ((obj sparticle-launch-control))
|
|
"kill the particles, but don't clear flags or free hvdfs."
|
|
(kill-all-particles-with-key obj)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod is-visible? sparticle-launch-control ((obj sparticle-launch-control) (arg0 vector))
|
|
"Is the effect visible?. arg0 is the offset of the effect"
|
|
(let* ((v1-0 (-> obj group))
|
|
(f0-0 (-> v1-0 bounds w))
|
|
)
|
|
(cond
|
|
((= f0-0 0.0) ;; visibility sphere has 0 size, just say yes always
|
|
#t
|
|
)
|
|
((nonzero? (-> obj matrix)) ;; I guess if we have an extra matrix, we can't figure it out?
|
|
#t
|
|
)
|
|
(else
|
|
;; sphere with offset
|
|
(let ((gp-1 (vector+! (new 'stack-no-clear 'vector) arg0 (the-as vector (-> v1-0 bounds)))))
|
|
(set! (-> gp-1 w) f0-0)
|
|
|
|
;; debug draw sphere
|
|
(if (and *display-actor-vis*
|
|
(or (not *display-actor-anim*)
|
|
(name= *display-actor-anim* (-> obj proc name))
|
|
)
|
|
)
|
|
(add-debug-sphere
|
|
*display-actor-vis*
|
|
(bucket-id debug-draw0)
|
|
gp-1
|
|
(-> gp-1 w)
|
|
(new 'static 'rgba :g #xff :a #x80)
|
|
)
|
|
)
|
|
|
|
;; can we see it?
|
|
(sphere-in-view-frustum? (the-as sphere gp-1))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
(defmethod spawn sparticle-launch-control ((obj sparticle-launch-control) (arg0 vector))
|
|
(set! (-> obj center quad) (-> arg0 quad))
|
|
|
|
;; check if we are visible (remove this check to force particles to be drawn.)
|
|
(if (not (or (is-visible? obj arg0)
|
|
(logtest? (-> obj group flags) (sp-group-flag always-draw screen-space))
|
|
)
|
|
)
|
|
(return (the-as object 0))
|
|
)
|
|
|
|
|
|
(let ((s4-0 *particle-300hz-timer*)
|
|
(s5-0 (-> obj last-spawn-time))
|
|
)
|
|
|
|
;; weird stuff for frame counting
|
|
(let ((v1-8 (-> *display* real-actual-frame-counter)))
|
|
(if (!= v1-8 (+ (-> obj last-spawn-frame) 1))
|
|
(set! s5-0 (- s4-0 (logand (the-as int (-> *sp-frame-time* x)) 255)))
|
|
)
|
|
)
|
|
(set! (-> obj last-spawn-frame) (-> *display* real-actual-frame-counter))
|
|
(set! (-> obj last-spawn-time) s4-0)
|
|
(when (logtest? (-> obj group flags) (sp-group-flag use-local-clock))
|
|
(set! s5-0 (-> obj local-clock))
|
|
(+! (-> obj local-clock) (logand (the-as int (-> *sp-frame-time* x)) 255))
|
|
(set! s4-0 (-> obj local-clock))
|
|
)
|
|
|
|
(let ((f30-0 (vector-vector-distance arg0 (math-camera-pos)))
|
|
;; hour mask
|
|
(s3-1 (ash 1 (if *time-of-day-proc*
|
|
(-> *time-of-day-proc* 0 hour)
|
|
0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(if (nonzero? (-> obj matrix)) ;; if we have an additional matrix, say we're at the camera so we always draw.
|
|
(set! f30-0 0.0)
|
|
)
|
|
|
|
;; loop over particles in the group.
|
|
(let ((s2-1 (-> obj length)))
|
|
(while (begin
|
|
(label cfg-79)
|
|
(nonzero? s2-1)
|
|
)
|
|
(+! s2-1 -1)
|
|
(let* ((a3-0 (-> obj data s2-1))
|
|
(v1-29 (-> a3-0 group-item))
|
|
(a1-4 (-> *part-id-table* (-> v1-29 launcher)))
|
|
)
|
|
(when (and a1-4
|
|
(nonzero? a1-4)
|
|
(logtest? (-> a3-0 flags) (sp-launch-state-flags launcher-active))
|
|
)
|
|
;; we are active, and it is possible to launch.
|
|
(let ((f0-2 1.0))
|
|
(if (!= (-> v1-29 falloff-to) 0.0)
|
|
(set! f0-2 (- 1.0 (/ f30-0 (-> v1-29 falloff-to))))
|
|
)
|
|
|
|
;; reject if bad type
|
|
(let ((a0-26 sparticle-launcher))
|
|
(b! (!= (-> a1-4 type) a0-26) cfg-78 :delay (nop!))
|
|
)
|
|
|
|
;; ??
|
|
(b! (zero? (logand (-> v1-29 flags) (sp-group-item-flag launch-asap)))
|
|
cfg-36 :delay (nop!)
|
|
)
|
|
|
|
(when (zero? (logand (-> a3-0 flags) (sp-launch-state-flags particles-active)))
|
|
;; particles are not active, lets activate them.
|
|
(set! (-> a3-0 spawn-time) (the-as uint s4-0))
|
|
(logior! (-> a3-0 flags) (sp-launch-state-flags particles-active))
|
|
(if (< 0.0 f0-2)
|
|
(sp-launch-particles-var
|
|
(if (logtest? (-> v1-29 flags) (sp-group-item-flag is-3d))
|
|
*sp-particle-system-3d*
|
|
*sp-particle-system-2d*
|
|
)
|
|
a1-4
|
|
(-> a3-0 origin)
|
|
a3-0
|
|
obj
|
|
f0-2
|
|
)
|
|
)
|
|
)
|
|
(b! #t cfg-77 :delay (nop!))
|
|
|
|
|
|
(label cfg-36)
|
|
|
|
;; reject if bad time of day
|
|
(when (logtest? s3-1 (-> v1-29 hour-mask))
|
|
0
|
|
(goto cfg-77)
|
|
)
|
|
(when (not (or (= (-> v1-29 fade-after) 0.0) (< f30-0 (-> v1-29 fade-after))))
|
|
0
|
|
(b! #t cfg-77 :delay (nop!))
|
|
(set! v1-29 (the-as sparticle-group-item 0))
|
|
)
|
|
(b! (nonzero? (-> v1-29 period)) cfg-50)
|
|
(let ((f0-4 (* 0.2 (the float (- s4-0 s5-0)) f0-2)))
|
|
(b! #t cfg-72 :delay (nop!))
|
|
(label cfg-50)
|
|
(let ((a2-5 (mod (+ s5-0 (-> obj data s2-1 offset)) (the-as int (-> v1-29 period))))
|
|
(a0-56 (mod (the-as uint (+ s4-0 (-> obj data s2-1 offset))) (-> v1-29 period)))
|
|
(t0-2 (-> v1-29 length))
|
|
)
|
|
(set! f0-4 (cond
|
|
((and (< a2-5 (the-as int t0-2)) (< a0-56 t0-2))
|
|
(* 0.2 (the float (- s4-0 s5-0)) f0-2)
|
|
)
|
|
((and (< a2-5 (the-as int t0-2)) (>= a0-56 t0-2))
|
|
(* 0.2 (the float (- t0-2 (the-as uint a2-5))) f0-2)
|
|
)
|
|
((and (>= a2-5 (the-as int t0-2)) (< a0-56 t0-2))
|
|
(* 0.2 (the float a0-56) f0-2)
|
|
)
|
|
(else
|
|
(when (zero? (logand (-> v1-29 flags) (sp-group-item-flag bit1)))
|
|
0
|
|
(goto cfg-77)
|
|
)
|
|
(when (< (the-as uint (- s4-0 (the-as int (-> obj data s2-1 spawn-time))))
|
|
(-> v1-29 period)
|
|
)
|
|
0
|
|
(goto cfg-77)
|
|
)
|
|
(set! (-> obj data s2-1 offset) (- (-> v1-29 period) a0-56))
|
|
(* 0.2 (the float (- s4-0 s5-0)) f0-2)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(label cfg-72)
|
|
(set! (-> a3-0 spawn-time) (the-as uint s4-0))
|
|
(logior! (-> a3-0 flags) (sp-launch-state-flags particles-active))
|
|
(if (< 0.0 f0-4)
|
|
(sp-launch-particles-var
|
|
(if (logtest? (-> v1-29 flags) (sp-group-item-flag is-3d))
|
|
*sp-particle-system-3d*
|
|
*sp-particle-system-2d*
|
|
)
|
|
a1-4
|
|
(-> a3-0 origin)
|
|
a3-0
|
|
obj
|
|
f0-4
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(label cfg-77)
|
|
(b! #t cfg-79 :delay (nop!))
|
|
(label cfg-78)
|
|
(format 0 "spawn called for non-sparticle-launcher~%")
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
)
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; tracking callbacks
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; these are commonly used callbacks for making particles follow an object
|
|
|
|
(defun sparticle-track-root ((arg0 object) (arg1 sparticle-cpuinfo) (arg2 vector))
|
|
"track the root of the process drawable"
|
|
(let ((v1-3 (-> (the-as process-drawable (-> arg1 key proc)) root trans)))
|
|
(set! (-> arg2 x) (-> v1-3 x))
|
|
(set! (-> arg2 y) (-> v1-3 y))
|
|
(set! (-> arg2 z) (-> v1-3 z))
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
|
|
(defun sparticle-track-root-prim ((arg0 object) (arg1 sparticle-cpuinfo) (arg2 vector))
|
|
"track the root of the collision geometry (must use collide-shape for root)"
|
|
(let ((v1-4 (-> (the-as collide-shape
|
|
(-> (the-as process-drawable (-> arg1 key proc)) root)
|
|
)
|
|
root-prim
|
|
prim-core
|
|
)
|
|
)
|
|
)
|
|
(set! (-> arg2 x) (-> v1-4 world-sphere x))
|
|
(set! (-> arg2 y) (-> v1-4 world-sphere y))
|
|
(set! (-> arg2 z) (-> v1-4 world-sphere z))
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;
|
|
;; birth funcs
|
|
;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
(defun birth-func-copy-rot-color ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 sprite-vec-data-3d) (arg3 sparticle-launcher) (arg4 sparticle-launch-state))
|
|
(rlet ((vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf2 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(let ((s5-0 (-> arg4 sprite)))
|
|
(let ((s4-0 (new 'stack-no-clear 'vector)))
|
|
(let* ((v1-0 arg2)
|
|
(f0-0 (-> v1-0 qx-qy-qz-sy x))
|
|
(f1-0 (-> v1-0 qx-qy-qz-sy y))
|
|
(f3-0 (-> v1-0 qx-qy-qz-sy z))
|
|
)
|
|
(set! (-> s4-0 x) f0-0)
|
|
(set! (-> s4-0 y) f1-0)
|
|
(set! (-> s4-0 z) f3-0)
|
|
(set! (-> s4-0 w)
|
|
(sqrtf (- (- (- 1.0 (* f3-0 f3-0)) (* f1-0 f1-0)) (* f0-0 f0-0)))
|
|
)
|
|
)
|
|
(quaternion-rotate-y!
|
|
(the-as quaternion s4-0)
|
|
(the-as quaternion s4-0)
|
|
(-> s5-0 sprite rot)
|
|
)
|
|
(let ((v1-3 arg2))
|
|
(cond
|
|
((< (-> s4-0 w) 0.0)
|
|
(.lvf vf1 (&-> v1-3 qx-qy-qz-sy quad))
|
|
(.lvf vf2 (&-> s4-0 quad))
|
|
(.sub.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> v1-3 qx-qy-qz-sy quad) vf1)
|
|
)
|
|
(else
|
|
(.lvf vf1 (&-> v1-3 qx-qy-qz-sy quad))
|
|
(.lvf vf2 (&-> s4-0 quad))
|
|
(.add.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> v1-3 qx-qy-qz-sy quad) vf1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set! (-> arg2 r-g-b-a x) (-> s5-0 sprite r))
|
|
(set! (-> arg2 r-g-b-a y) (-> s5-0 sprite g))
|
|
(set! (-> arg2 r-g-b-a z) (-> s5-0 sprite b))
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
)
|
|
|
|
|
|
(define *global-toggle* 0)
|
|
|
|
(defun birth-func-copy2-rot-color ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 sprite-vec-data-3d) (arg3 sparticle-launcher) (arg4 sparticle-launch-state))
|
|
(rlet ((vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf2 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(let ((s5-0 (-> arg4 sprite)))
|
|
(let ((s4-0 (new 'stack-no-clear 'vector)))
|
|
(let* ((v1-0 arg2)
|
|
(f0-0 (-> v1-0 qx-qy-qz-sy x))
|
|
(f1-0 (-> v1-0 qx-qy-qz-sy y))
|
|
(f3-0 (-> v1-0 qx-qy-qz-sy z))
|
|
)
|
|
(set! (-> s4-0 x) f0-0)
|
|
(set! (-> s4-0 y) f1-0)
|
|
(set! (-> s4-0 z) f3-0)
|
|
(set! (-> s4-0 w)
|
|
(sqrtf (- (- (- 1.0 (* f3-0 f3-0)) (* f1-0 f1-0)) (* f0-0 f0-0)))
|
|
)
|
|
)
|
|
(let ((a1-1 (new-stack-vector0)))
|
|
(set! (-> a1-1 y) (-> s5-0 sprite rot))
|
|
(set! (-> a1-1 z)
|
|
(if (logtest? *global-toggle* 1)
|
|
(the float (sar (shl (the int (- 16384.0 (-> s5-0 sprite sx))) 48) 48))
|
|
(the float (sar (shl (the int (+ 16384.0 (-> s5-0 sprite sx))) 48) 48))
|
|
)
|
|
)
|
|
(quaternion-zxy! (the-as quaternion s4-0) a1-1)
|
|
)
|
|
(let ((v1-14 arg2))
|
|
(cond
|
|
((< (-> s4-0 w) 0.0)
|
|
(.lvf vf1 (&-> v1-14 qx-qy-qz-sy quad))
|
|
(.lvf vf2 (&-> s4-0 quad))
|
|
(.sub.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> v1-14 qx-qy-qz-sy quad) vf1)
|
|
)
|
|
(else
|
|
(.lvf vf1 (&-> v1-14 qx-qy-qz-sy quad))
|
|
(.lvf vf2 (&-> s4-0 quad))
|
|
(.add.vf vf1 vf0 vf2 :mask #b111)
|
|
(.svf (&-> v1-14 qx-qy-qz-sy quad) vf1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set! (-> arg2 r-g-b-a x) (-> s5-0 sprite r))
|
|
(set! (-> arg2 r-g-b-a y) (-> s5-0 sprite g))
|
|
(set! (-> arg2 r-g-b-a z) (-> s5-0 sprite b))
|
|
)
|
|
(set! *global-toggle* (+ *global-toggle* 1))
|
|
0
|
|
(none)
|
|
)
|
|
)
|
|
|
|
(defun birth-func-copy-omega-to-z ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 sprite-vec-data-3d) (arg3 sparticle-launcher) (arg4 sparticle-launch-state))
|
|
(set! (-> arg2 qx-qy-qz-sy z) (+ -16384.0 (-> arg1 omega)))
|
|
(set! (-> arg1 next-time) (-> arg4 sprite next-time))
|
|
(set! (-> arg2 x-y-z-sx w) (* 163.85638 (the float (-> arg4 sprite next-time))))
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun birth-func-random-next-time ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 sprite-vec-data-3d) (arg3 sparticle-launcher) (arg4 sparticle-launch-state))
|
|
(set! (-> arg1 next-time) (the-as uint (the int (rand-vu-float-range 0.0 (-> arg1 user-float)))))
|
|
0
|
|
(none)
|
|
)
|