Files
jak-project/goal_src/jak2/levels/common/enemy/hover/hover-enemy-battle.gc
T
Hat Kid 67d4eda169 decomp: hover-* files, wasp, crimson-guard-hover, flamer, target-turret, drill-turret, jellyfish (#2198)
Manual patches:

- `drill-turret`: The static data for `*turret-13-path*`,
`*turret-14-path*` and `*turret-15-path*` was decompiled by hand and the
integers in the `set-speed-mult` events have been replaced with boxed
integer arrays that contain only that integer in order to make the
compiler happy. To that effect, the event handler in `target-turret` was
changed to access that array instead of just accessing the int.
- `hover-nav-control`: In `hover-nav-control::10`, `arg2` is usually a
`vector`, but there are some places where it is called with `#t` as
`arg2` and, subsequently, crashes the game because it tries to access
the `quad` of `arg2` if `arg2` is truthy. To mitigate this, the
condition `arg2` has been replaced with `(and (!= arg2 #t) arg2)` (in
this case, it would jump to the `else` that just resets the `dest-vel`
and `transv` `quad`s)
- `drill-baron`: The static data for `*drill-ship-turret-speed-event*`
has been decompiled by hand.

TODOs:
- Jellyfish crash the game
- Destroying the metalhead eggs that are on the breakable wall crashes
the game (already happened with the Peacemaker before)
- Figure out why static data of type `turret-path-event` doesn't
decompile

The docs for all the hover-nav and nav-network code could use some love
in the future, I'm not smart enough to figure out what any of that code
actually means, but it seems to work...

Also threw in the fix for the ▲ that was accidentally left commented
out.
2023-02-09 18:22:56 -05:00

323 lines
10 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
;; name: hover-enemy-battle.gc
;; name in dgo: hover-enemy-battle
;; dgos: FOR, DMI, FRA, STR, NEB, D3A, UNB
(declare-type base-turret process-focusable)
(declare-type turret base-turret)
;; DECOMP BEGINS
(deftype hover-enemy-battle-command (structure)
((command symbol :offset-assert 0)
(wave uint16 :offset-assert 4)
(time time-frame :offset-assert 8)
(alive-count int32 :offset-assert 16)
)
:method-count-assert 9
:size-assert #x14
:flag-assert #x900000014
)
(deftype hover-enemy-manager (process)
((command-table (array hover-enemy-battle-command) :offset-assert 128)
(path path-control :offset-assert 132)
(formation hover-formation-control :offset-assert 136)
(actor-group (pointer actor-group) :offset-assert 140)
(actor-group-count int32 :offset-assert 144)
(total-to-spawn int32 :offset-assert 148)
(num-spawned int32 :offset-assert 152)
(alive-count int32 :offset-assert 156)
(formation-timer time-frame :offset-assert 160)
)
:heap-base #x30
:method-count-assert 19
:size-assert #xa8
:flag-assert #x13003000a8
(:methods
(idle () _type_ :state 14)
(spawning (object object process pointer) _type_ :state 15)
(die () _type_ :state 16)
(hover-enemy-manager-init! (_type_ (array hover-enemy-battle-command)) none 17)
(spawn-enemy (_type_ uint) none 18)
)
)
(defbehavior hover-enemy-manager-handler hover-enemy-manager ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
(local-vars (v0-0 object))
(case arg2
(('join 'leave 'set-type 'get-formation 'set-los)
(when (-> self formation)
(let ((v1-2 (-> self formation))
(a1-8 arg0)
)
(case arg2
(('join)
(hover-formation-control-method-17 v1-2 a1-8)
)
(('leave)
(hover-formation-control-method-18 v1-2 a1-8)
)
(('set-type)
(let ((a1-11 1))
(case (-> arg3 param 0)
(('line)
(set! a1-11 0)
)
(('circle)
(set! a1-11 2)
)
(('semicircle)
(set! a1-11 3)
)
)
(try-update-formation-type v1-2 (the-as formation-type a1-11))
)
)
(('get-formation)
v1-2
)
(('set-los)
(cond
((-> arg3 param 0)
(set! v0-0 (logior (-> v1-2 flags) 2))
(set! (-> v1-2 flags) (the-as uint v0-0))
)
(else
(set! v0-0 (logand -3 (-> v1-2 flags)))
(set! (-> v1-2 flags) (the-as uint v0-0))
)
)
v0-0
)
)
)
)
)
(('num-alive?)
(-> self alive-count)
)
(('num-spawned?)
(-> self num-spawned)
)
(('total-to-spawn?)
(-> self total-to-spawn)
)
(('hover-die)
(set! v0-0 (max 0 (+ (-> self alive-count) -1)))
(set! (-> self alive-count) (the-as int v0-0))
v0-0
)
(('path)
(if (not (logtest? (-> self path flags) (path-control-flag not-found)))
(-> self path)
)
)
)
)
(defbehavior hover-enemy-manager-post hover-enemy-manager ()
(when (-> self formation)
(let ((gp-0 (-> self formation)))
(let ((a0-0 gp-0))
((the-as (function hover-formation-control none) (method-of-object a0-0 hover-formation-control-method-14))
a0-0
)
)
(when (and (logtest? (-> gp-0 flags) 2)
(>= (- (-> self clock frame-counter) (-> self formation-timer)) (seconds 0.2))
)
(hover-formation-control-method-11 gp-0)
(set! (-> self formation-timer) (-> self clock frame-counter))
)
)
)
(if (not (logtest? (-> self path flags) (path-control-flag not-found)))
(debug-draw (-> self path))
)
(none)
)
(defstate idle (hover-enemy-manager)
:virtual #t
:event (behavior ((proc process) (arg1 int) (event-type symbol) (event event-message-block))
(case event-type
(('trigger)
(go-virtual spawning proc arg1 (the-as process event-type) (the-as pointer event))
)
(else
(hover-enemy-manager-handler proc arg1 event-type event)
)
)
)
:code (the-as (function none :behavior hover-enemy-manager) sleep-code)
:post hover-enemy-manager-post
)
(defstate spawning (hover-enemy-manager)
:virtual #t
:event (behavior ((proc process) (arg1 int) (event-type symbol) (event event-message-block))
(case event-type
(('spawning?)
#t
)
(else
(hover-enemy-manager-handler proc arg1 event-type event)
)
)
)
:enter (behavior ((arg0 object) (arg1 object) (arg2 process) (arg3 pointer))
(let ((a0-1 (-> self formation)))
(if a0-1
(set-anchor-proc a0-1 (process->handle *target*))
)
)
(none)
)
:code (behavior ((arg0 object) (arg1 object) (arg2 process) (arg3 pointer))
(let ((gp-0 (-> self command-table)))
(dotimes (s5-0 (-> gp-0 length))
(case (-> gp-0 s5-0 command)
(('spawn)
(spawn-enemy self (-> gp-0 s5-0 wave))
)
(('wait)
)
)
(let ((s4-0 (-> self clock frame-counter)))
(until (>= (- (-> self clock frame-counter) s4-0) (-> gp-0 s5-0 time))
(suspend)
)
)
(while (< (-> gp-0 s5-0 alive-count) (-> self alive-count))
(suspend)
)
)
)
(let ((gp-1 (-> self clock frame-counter)))
(until (>= (- (-> self clock frame-counter) gp-1) (seconds 2))
(suspend)
)
)
(go-virtual die)
(none)
)
:post hover-enemy-manager-post
)
(defstate die (hover-enemy-manager)
:virtual #t
:event hover-enemy-manager-handler
:code (behavior ()
(while (-> self child)
(suspend)
)
(process-entity-status! self (entity-perm-status dead) #t)
(none)
)
)
(defmethod spawn-enemy hover-enemy-manager ((obj hover-enemy-manager) (arg0 uint))
(when (< arg0 (the-as uint (-> obj actor-group-count)))
(dotimes (s4-0 (-> obj actor-group arg0 length))
(let* ((s1-0 (-> obj actor-group arg0 data s4-0 actor))
(s2-0 (-> (the-as entity-actor s1-0) etype))
(s3-0 (new 'stack-no-clear 'transformq))
)
(set! (-> s3-0 trans quad) (-> s1-0 extra trans quad))
(quaternion-copy! (-> s3-0 quat) (-> (the-as entity-actor s1-0) quat))
(set! (-> s3-0 scale x) (the-as float s1-0))
(set! (-> s3-0 scale y) (the-as float #f))
(set! (-> s3-0 scale z) (the-as float #t))
(let ((s1-1 (get-process *default-dead-pool* s2-0 #x4000)))
(when (when s1-1
(let ((t9-2 (method-of-type process activate)))
(t9-2 s1-1 obj (symbol->string (-> s2-0 symbol)) (the-as pointer #x70004000))
)
(run-now-in-process s1-1 enemy-init-by-other obj s3-0)
(-> s1-1 ppointer)
)
(+! (-> obj alive-count) 1)
(+! (-> obj num-spawned) 1)
)
)
)
)
)
0
(none)
)
;; WARN: Return type mismatch process vs hover-enemy-manager.
(defmethod relocate hover-enemy-manager ((obj hover-enemy-manager) (arg0 int))
(when (-> obj formation)
(if (nonzero? (-> obj formation))
(&+! (-> obj formation) arg0)
)
)
(if (nonzero? (-> obj path))
(&+! (-> obj path) arg0)
)
(the-as
hover-enemy-manager
((the-as (function process int process) (find-parent-method hover-enemy-manager 7)) obj arg0)
)
)
(defmethod hover-enemy-manager-init! hover-enemy-manager ((obj hover-enemy-manager) (arg0 (array hover-enemy-battle-command)))
"Initialize this [[hover-enemy-manager]]."
(local-vars (sv-16 res-tag))
(with-pp
(set! (-> obj command-table) arg0)
(set! (-> obj path) (new 'process 'path-control obj 'path 0.0 (-> obj entity) #f))
(logior! (-> obj path flags) (path-control-flag display draw-line draw-point draw-text))
(set! sv-16 (new 'static 'res-tag))
(let ((v1-5 (res-lump-data (-> obj entity) 'actor-groups pointer :tag-ptr (& sv-16))))
(cond
((and v1-5 (nonzero? (-> sv-16 elt-count)))
(set! (-> obj actor-group) (the-as (pointer actor-group) v1-5))
(set! (-> obj actor-group-count) (the-as int (-> sv-16 elt-count)))
)
(else
(set! (-> obj actor-group) (the-as (pointer actor-group) #f))
(set! (-> obj actor-group-count) 0)
0
)
)
)
(set! (-> obj total-to-spawn) 0)
(set! (-> obj num-spawned) 0)
(when (-> obj command-table)
(let ((v1-13 (-> obj command-table)))
(dotimes (a0-6 (-> v1-13 length))
(if (= (-> v1-13 a0-6 command) 'spawn)
(+! (-> obj total-to-spawn) (-> obj actor-group (-> v1-13 a0-6 wave) length))
)
)
)
)
(set! (-> obj formation) #f)
(set! (-> obj formation-timer) (-> pp clock frame-counter))
(set! (-> obj alive-count) 0)
0
(none)
)
)
;; WARN: Return type mismatch object vs none.
(defbehavior hover-enemy-manager-init-by-other hover-enemy-manager ((arg0 entity-actor) (arg1 (array hover-enemy-battle-command)))
(set! (-> self entity) arg0)
(hover-enemy-manager-init! self arg1)
(go-virtual idle)
(none)
)
;; WARN: Return type mismatch process-tree vs process.
(defun hover-manager-spawn ((arg0 turret) (arg1 entity-actor) (arg2 (array hover-enemy-battle-command)))
(the-as process (ppointer->process (process-spawn hover-enemy-manager arg1 arg2 :to arg0)))
)