;;-*-Lisp-*-
(in-package goal)

(import "goal_src/jak1/import/muse-ag.gc")

;; definition of type muse
(deftype muse (nav-enemy)
  ((root-override      collide-shape-moving         :offset        112)
   (current-path-index float                        :offset-assert 400)
   (prev-path-index    float                        :offset-assert 404)
   (dest-path-index    float                        :offset-assert 408)
   (player-path-index  float                        :offset-assert 412)
   (max-path-index     float                        :offset-assert 416)
   (sprint-distance    float                        :offset-assert 420)
   (dest-point         vector               :inline :offset-assert 432)
   (anim               spool-anim                   :offset-assert 448)
   (victory-anim       spool-anim                   :offset-assert 452)
   (old-target-pos     transformq           :inline :offset-assert 464)
   )
  :heap-base #x190
  :method-count-assert 76
  :size-assert         #x200
  :flag-assert         #x4c01900200
  (:states
    muse-caught
    muse-idle
    )
  )

;; definition for method 3 of type muse
(defmethod inspect muse ((obj muse))
  (let ((t9-0 (method-of-type nav-enemy inspect)))
    (t9-0 obj)
    )
  (format #t "~T~Tcurrent-path-index: ~f~%" (-> obj current-path-index))
  (format #t "~T~Tprev-path-index: ~f~%" (-> obj prev-path-index))
  (format #t "~T~Tdest-path-index: ~f~%" (-> obj dest-path-index))
  (format #t "~T~Tplayer-path-index: ~f~%" (-> obj player-path-index))
  (format #t "~T~Tmax-path-index: ~f~%" (-> obj max-path-index))
  (format #t "~T~Tsprint-distance: ~f~%" (-> obj sprint-distance))
  (format #t "~T~Tdest-point: #<vector @ #x~X>~%" (-> obj dest-point))
  (format #t "~T~Tanim: ~A~%" (-> obj anim))
  (format #t "~T~Tvictory-anim: ~A~%" (-> obj victory-anim))
  (format #t "~T~Told-target-pos: #<transformq @ #x~X>~%" (-> obj old-target-pos))
  obj
  )

;; definition of type point-on-path-segment-info
(deftype point-on-path-segment-info (structure)
  ((point               vector :inline   :offset-assert   0)
   (segment             vector 2 :inline :offset-assert  16)
   (dir                 vector :inline   :offset-assert  48)
   (nearest-point       vector :inline   :offset-assert  64)
   (segment-length      float            :offset-assert  80)
   (distance-to-segment float            :offset-assert  84)
   (parametric-index    float            :offset-assert  88)
   )
  :method-count-assert 9
  :size-assert         #x5c
  :flag-assert         #x90000005c
  )

;; definition for method 3 of type point-on-path-segment-info
(defmethod inspect point-on-path-segment-info ((obj point-on-path-segment-info))
  (format #t "[~8x] ~A~%" obj 'point-on-path-segment-info)
  (format #t "~Tpoint: #<vector @ #x~X>~%" (-> obj point))
  (format #t "~Tsegment[2] @ #x~X~%" (-> obj segment))
  (format #t "~Tdir: #<vector @ #x~X>~%" (-> obj dir))
  (format #t "~Tnearest-point: #<vector @ #x~X>~%" (-> obj nearest-point))
  (format #t "~Tsegment-length: ~f~%" (-> obj segment-length))
  (format #t "~Tdistance-to-segment: ~f~%" (-> obj distance-to-segment))
  (format #t "~Tparametric-index: ~f~%" (-> obj parametric-index))
  obj
  )

;; definition for function analyze-point-on-path-segment
;; INFO: Used lq/sq
(defun analyze-point-on-path-segment ((arg0 point-on-path-segment-info))
  (vector-! (-> arg0 dir) (-> arg0 segment 1) (the-as vector (-> arg0 segment)))
  (vector-normalize! (-> arg0 dir) 1.0)
  (set! (-> arg0 segment-length) (vector-vector-distance (the-as vector (-> arg0 segment)) (-> arg0 segment 1)))
  (let ((s5-0 (new 'stack-no-clear 'vector)))
    (vector-! s5-0 (the-as vector (-> arg0 segment)) (-> arg0 point))
    (vector+*! s5-0 s5-0 (-> arg0 dir) (- (vector-dot s5-0 (-> arg0 dir))))
    (vector+! (-> arg0 nearest-point) (-> arg0 point) s5-0)
    (set! (-> arg0 distance-to-segment) (vector-length s5-0))
    (vector-! s5-0 (-> arg0 point) (the-as vector (-> arg0 segment)))
    (set! (-> arg0 parametric-index) (/ (vector-dot (-> arg0 dir) s5-0) (-> arg0 segment-length)))
    )
  (cond
    ((< (-> arg0 parametric-index) 0.0)
     (set! (-> arg0 parametric-index) 0.0)
     (set! (-> arg0 nearest-point quad) (-> arg0 segment 0 quad))
     (let ((f0-10 (vector-vector-distance (-> arg0 nearest-point) (-> arg0 point))))
       (set! (-> arg0 distance-to-segment) f0-10)
       f0-10
       )
     )
    ((< 1.0 (-> arg0 parametric-index))
     (set! (-> arg0 parametric-index) 1.0)
     (set! (-> arg0 nearest-point quad) (-> arg0 segment 1 quad))
     (let ((f0-13 (vector-vector-distance (-> arg0 nearest-point) (-> arg0 point))))
       (set! (-> arg0 distance-to-segment) f0-13)
       f0-13
       )
     )
    )
  )

;; definition for function muse-get-path-point
;; INFO: Return type mismatch int vs none.
(defbehavior muse-get-path-point muse ((arg0 vector) (arg1 int))
  (eval-path-curve-div! (-> self path) arg0 (the float arg1) 'interp)
  0
  (none)
  )

;; definition for function muse-check-dest-point
;; INFO: Used lq/sq
;; INFO: Return type mismatch int vs none.
(defbehavior muse-check-dest-point muse ()
  (let ((gp-0 (new 'stack-no-clear 'point-on-path-segment-info))
        (f26-0 4096000.0)
        (f30-0 0.0)
        (f24-0 4096000.0)
        (f28-0 0.0)
        )
    (let ((s5-0 (+ (-> self path curve num-cverts) -1))
          (s4-0 (target-pos 0))
          )
      (dotimes (s3-0 s5-0)
        (let ((f22-0 (the float s3-0)))
          (let ((f20-0 (the float (+ s3-0 1))))
            (eval-path-curve-div! (-> self path) (the-as vector (-> gp-0 segment)) f22-0 'interp)
            (eval-path-curve-div! (-> self path) (-> gp-0 segment 1) f20-0 'interp)
            )
          (set! (-> gp-0 point quad) (-> s4-0 quad))
          (analyze-point-on-path-segment gp-0)
          (when (< (-> gp-0 distance-to-segment) f24-0)
            (set! f24-0 (-> gp-0 distance-to-segment))
            (set! f28-0 (+ f22-0 (-> gp-0 parametric-index)))
            )
          (set! (-> gp-0 point quad) (-> self collide-info trans quad))
          (analyze-point-on-path-segment gp-0)
          (when (< (-> gp-0 distance-to-segment) f26-0)
            (set! f26-0 (-> gp-0 distance-to-segment))
            (set! f30-0 (+ f22-0 (-> gp-0 parametric-index)))
            )
          )
        0
        )
      )
    (let ((f0-6 (- f30-0 f28-0)))
      (if (< f0-6 (* -0.5 (-> self max-path-index)))
          (+! f0-6 (-> self max-path-index))
          )
      (if (< (* 0.5 (-> self max-path-index)) f0-6)
          (set! f0-6 (- f0-6 (-> self max-path-index)))
          )
      (cond
        ((>= f0-6 0.0)
         (set! (-> self dest-path-index) (the float (the int (+ 2.5 f30-0))))
         (if (>= (-> self dest-path-index) (-> self max-path-index))
             (set! (-> self dest-path-index) (- (-> self dest-path-index) (-> self max-path-index)))
             )
         )
        (else
          (set! (-> self dest-path-index) (+ -1.5 f30-0))
          (if (< (-> self dest-path-index) 0.0)
              (+! (-> self dest-path-index) (-> self max-path-index))
              )
          (set! (-> self dest-path-index) (the float (the int (-> self dest-path-index))))
          )
        )
      )
    )
  (eval-path-curve-div! (-> self path) (-> self dest-point) (-> self dest-path-index) 'interp)
  0
  (none)
  )

;; definition for method 51 of type muse
;; INFO: Return type mismatch int vs none.
(defmethod dummy-51 muse ((obj muse))
  (dotimes (s5-0 2)
    (let ((v1-2 (rand-vu-int-range 3 (+ (-> obj node-list length) -1))))
      (sp-launch-particles-var
        *sp-particle-system-2d*
        (-> *part-id-table* 271)
        (vector<-cspace! (new 'stack-no-clear 'vector) (-> obj node-list data v1-2))
        (the-as sparticle-launch-state #f)
        (the-as sparticle-launch-control #f)
        1.0
        )
      )
    )
  0
  (none)
  )

;; definition for method 39 of type muse
(defmethod common-post muse ((obj muse))
  (spool-push *art-control* (-> obj anim name) 0 obj -99.0)
  (dummy-51 obj)
  ((method-of-type nav-enemy common-post) obj)
  (none)
  )

;; failed to figure out what this is:
(defskelgroup *muse-sg* muse muse-lod0-jg muse-idle-ja
              ((muse-lod0-mg (meters 999999)))
              :bounds (static-spherem 0 2 0 3)
              :shadow muse-shadow-mg
              )

;; definition for method 44 of type muse
(defmethod dummy-44 muse ((obj muse) (arg0 process) (arg1 event-message-block))
  (go muse-caught)
  )

;; definition for method 43 of type muse
(defmethod dummy-43 muse ((obj muse) (arg0 process) (arg1 event-message-block))
  (go muse-caught)
  )

;; failed to figure out what this is:
nav-enemy-default-event-handler

;; failed to figure out what this is:
(defstate muse-idle (muse)
  :event (the-as
    (function process int symbol event-message-block object :behavior muse)
    nav-enemy-default-event-handler
    )
  :trans (behavior ()
    (seek! (-> self sprint-distance) 61440.0 (* 8192.0 (-> *display* seconds-per-frame)))
    (if (and *target* (>= 102400.0 (vector-vector-distance (-> self collide-info trans) (-> *target* control trans))))
        (level-hint-spawn (game-text-id zero) (the-as string #f) (-> self entity) *entity-pool* (game-task none))
        )
    (if (and *target* (>= 81920.0 (vector-vector-distance (-> self collide-info trans) (-> *target* control trans))))
        (go-virtual nav-enemy-chase)
        )
    (none)
    )
  :code (behavior ()
    (when (ja-group? muse-run-ja)
      (ja-channel-push! 1 (seconds 0.1))
      (ja-no-eval :num! (loop!))
      (ja-no-eval :group! muse-run-to-idle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (ja-blend-eval)
        (suspend)
        (ja :num! (seek!))
        )
      )
    (loop
      (ja-no-eval :group! muse-idle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (spool-push *art-control* (-> self anim name) 0 self -99.0)
        (dummy-51 self)
        (suspend)
        (ja :num! (seek!))
        )
      )
    (none)
    )
  :post (the-as (function none :behavior muse) ja-post)
  )

;; failed to figure out what this is:
(defstate nav-enemy-chase (muse)
  :virtual #t
  :event (the-as
    (function process int symbol event-message-block object :behavior muse)
    nav-enemy-default-event-handler
    )
  :enter (behavior ()
    (set! (-> self state-time) (-> *display* base-frame-counter))
    (none)
    )
  :trans (behavior ()
    (cond
      ((or (not *target*)
           (< 102400.0 (vector-vector-distance (-> self collide-info trans) (-> *target* control trans)))
           )
       (set! (-> self target-speed) 0.0)
       (if (= (-> self momentum-speed) 0.0)
           (go muse-idle)
           )
       )
      ((or (not *target*) (< (-> self sprint-distance)
                             (vector-vector-distance (-> self collide-info trans) (-> *target* control trans))
                             )
           )
       (set! (-> self target-speed) 40960.0)
       )
      (else
        (set! (-> self target-speed) 61440.0)
        )
      )
    (seek! (-> self sprint-distance) 0.0 (* 4096.0 (-> *display* seconds-per-frame)))
    (muse-check-dest-point)
    (none)
    )
  :code (behavior ()
    (cond
      ((ja-group? muse-idle-ja)
       (ja-channel-push! 1 (seconds 0.1))
       (ja-no-eval :num! (loop!))
       (ja-no-eval :group! muse-idle-to-run-ja :num! (seek!) :frame-num 0.0)
       (until (ja-done? 0)
         (ja-blend-eval)
         (suspend)
         (ja :num! (seek!))
         )
       )
      (else
        (ja-channel-push! 1 (seconds 0.1))
        )
      )
    (ja :group! muse-run-ja :num! min)
    (loop
      (suspend)
      (ja :num! (loop! (* 0.000016276043 (-> self momentum-speed))))
      )
    (none)
    )
  :post (behavior ()
    (set! (-> self nav destination-pos quad) (-> self dest-point quad))
    (dummy-19
      (-> self nav)
      (-> self nav target-pos)
      (-> self collide-info)
      (-> self nav destination-pos)
      546133.3
      )
    (if (logtest? (nav-control-flags navcf21) (-> self nav flags))
        (logclear! (-> self nav flags) (nav-control-flags navcf10))
        )
    (nav-enemy-travel-post)
    (none)
    )
  )

;; failed to figure out what this is:
(defstate nav-enemy-jump (muse)
  :virtual #t
  :event (the-as
    (function process int symbol event-message-block object :behavior muse)
    nav-enemy-default-event-handler
    )
  :enter (behavior ()
    ((-> (method-of-type nav-enemy nav-enemy-jump) enter))
    (logclear! (-> self nav-enemy-flags) (nav-enemy-flags standing-jump))
    (none)
    )
  :code (-> (method-of-type nav-enemy nav-enemy-jump) code)
  )

;; failed to figure out what this is:
(defstate nav-enemy-jump-land (muse)
  :virtual #t
  :event (the-as
    (function process int symbol event-message-block object :behavior muse)
    nav-enemy-default-event-handler
    )
  :code (behavior ()
    (ja-no-eval :num! (seek!))
    (ja-channel-push! 1 (seconds 0.075))
    (ja-no-eval :group! muse-run-ja :num! (seek! max 0.8) :frame-num (ja-aframe 6.0 0))
    (until (ja-done? 0)
      (ja-blend-eval)
      (suspend)
      (ja :num! (seek! max 0.8))
      )
    (go-virtual nav-enemy-chase)
    (none)
    )
  )

;; failed to figure out what this is:
(defstate muse-caught (muse)
  :event (the-as (function process int symbol event-message-block object :behavior muse) #f)
  :trans (behavior ()
    (spool-push *art-control* (-> self anim name) 0 self -1.0)
    (none)
    )
  :code (behavior ()
    (sound-play "money-pickup")
    (close-specific-task! (game-task misty-muse) (task-status need-reminder))
    (process-entity-status! self (entity-perm-status dead) #t)
    (suspend)
    (when (send-event *target* 'clone-anim self)
      (set-blackout-frames (seconds 10))
      (let ((gp-1 (res-lump-struct (-> self entity) 'movie-pos vector)))
        (cond
          (gp-1
            (move-to-point! (-> self collide-info) gp-1)
            (set-yaw-angle-clear-roll-pitch! (-> self collide-info) (-> gp-1 w))
            )
          (else
            (move-to-point! (-> self collide-info) (-> *target* control trans))
            (quaternion-copy! (-> self collide-info quat) (-> *target* control quat))
            (move-to-ground (-> self collide-info) 40960.0 40960.0 #f (collide-kind background))
            )
          )
        )
      (send-event *target* 'trans 'save (-> self old-target-pos))
      (send-event (ppointer->process (-> *target* sidekick)) 'matrix 'play-anim)
      (send-event *target* 'blend-shape #t)
      (if (!= *kernel-boot-message* 'play)
          (set! (-> self trans-hook)
                (lambda :behavior muse () (spool-push *art-control* (-> self victory-anim name) 0 self -1.0) (none))
                )
          )
      (add-setting! 'music-volume 'rel (-> *setting-control* current music-volume-movie) 0)
      (add-setting! 'sfx-volume 'rel (-> *setting-control* current sfx-volume-movie) 0)
      (add-setting! 'ambient-volume 'rel (-> *setting-control* current ambient-volume-movie) 0)
      (logclear! (-> self mask) (process-mask enemy))
      (process-spawn othercam self 3 #f #t :to self)
      (auto-save-command 'auto-save 0 0 *default-pool*)
      (ja-play-spooled-anim
        (-> self anim)
        (the-as art-joint-anim muse-idle-ja)
        (the-as art-joint-anim muse-idle-ja)
        (the-as (function process-drawable symbol) false-func)
        )
      (remove-setting! 'music-volume)
      (remove-setting! 'sfx-volume)
      (remove-setting! 'ambient-volume)
      (send-event *target* 'blend-shape #f)
      (cond
        ((!= *kernel-boot-message* 'play)
         (set-blackout-frames 0)
         (ja-channel-set! 0)
         (ja-post)
         (clear-collide-with-as (-> self collide-info))
         (send-event *target* 'trans 'reset)
         (let ((gp-4 (ppointer->handle (birth-pickup-at-point
                                         (target-pos 0)
                                         (pickup-type fuel-cell)
                                         (the float (-> self entity extra perm task))
                                         #f
                                         self
                                         (the-as fact-info #f)
                                         )
                                       )
                     )
               )
           (send-event (handle->process (the-as handle gp-4)) 'pickup)
           (while (handle->process (the-as handle gp-4))
             (suspend)
             )
           )
         )
        (else
          (send-event *target* 'trans 'restore (-> self old-target-pos))
          (set-blackout-frames 0)
          (set-blackout-frames (seconds 0.1))
          )
        )
      )
    (none)
    )
  :post (behavior ()
    (dummy-51 self)
    (level-hint-surpress!)
    (kill-current-level-hint '() '() 'exit)
    (ja-post)
    (none)
    )
  )

;; definition for symbol *muse-nav-enemy-info*, type nav-enemy-info
(define *muse-nav-enemy-info* (new 'static 'nav-enemy-info
                                :idle-anim 3
                                :walk-anim 4
                                :turn-anim -1
                                :notice-anim 3
                                :run-anim 4
                                :jump-anim 7
                                :jump-land-anim 8
                                :victory-anim 3
                                :taunt-anim 3
                                :die-anim 3
                                :neck-joint 6
                                :player-look-at-joint 5
                                :run-travel-speed (meters 10)
                                :run-rotate-speed (degrees 999.99994)
                                :run-acceleration (meters 5)
                                :run-turn-time (seconds 0.15)
                                :walk-travel-speed (meters 10)
                                :walk-rotate-speed (degrees 999.99994)
                                :walk-acceleration (meters 1)
                                :walk-turn-time (seconds 0.15)
                                :attack-shove-back (meters 3)
                                :attack-shove-up (meters 2)
                                :shadow-size (meters 2)
                                :notice-nav-radius (meters 1)
                                :nav-nearest-y-threshold (meters 10)
                                :notice-distance (meters 30)
                                :stop-chase-distance (meters 40)
                                :frustration-distance (meters 8)
                                :frustration-time (seconds 4)
                                :die-anim-hold-frame 10000000000.0
                                :jump-anim-start-frame 6.5
                                :jump-land-anim-end-frame 10000000000.0
                                :jump-height-min (meters 1)
                                :jump-height-factor 0.5
                                :jump-start-anim-speed 1.0
                                :shadow-max-y (meters 1)
                                :shadow-min-y (meters -1)
                                :shadow-locus-dist (meters 150)
                                :use-align #f
                                :draw-shadow #t
                                :move-to-ground #t
                                :hover-if-no-ground #f
                                :use-momentum #f
                                :use-flee #f
                                :use-proximity-notice #f
                                :use-jump-blocked #f
                                :use-jump-patrol #f
                                :gnd-collide-with (collide-kind background)
                                :debug-draw-neck #f
                                :debug-draw-jump #f
                                )
        )

;; definition for method 11 of type muse
;; INFO: Used lq/sq
;; INFO: Return type mismatch object vs none.
(defmethod init-from-entity! muse ((obj muse) (arg0 entity-actor))
  (stack-size-set! (-> obj main-thread) 512)
  (set! (-> obj mask) (logior (process-mask enemy) (-> obj mask)))
  (let ((s4-0 (new 'process 'collide-shape-moving obj (collide-list-enum hit-by-player))))
    (set! (-> s4-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s4-0 reaction) default-collision-reaction)
    (set! (-> s4-0 no-reaction)
          (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing)
          )
    (let ((s3-0 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 0))))
      (set! (-> s3-0 prim-core collide-as) (collide-kind enemy))
      (set! (-> s3-0 collide-with) (collide-kind target))
      (set! (-> s3-0 prim-core action) (collide-action solid))
      (set! (-> s3-0 prim-core offense) (collide-offense indestructible))
      (set-vector! (-> s3-0 local-sphere) 0.0 2457.6 0.0 2457.6)
      (set-root-prim! s4-0 s3-0)
      )
    (set! (-> s4-0 nav-radius) (* 0.75 (-> s4-0 root-prim local-sphere w)))
    (backup-collide-with-as s4-0)
    (set! (-> obj collide-info) s4-0)
    )
  (process-drawable-from-entity! obj arg0)
  (initialize-skeleton obj *muse-sg* '())
  (logclear! (-> obj mask) (process-mask actor-pause))
  (TODO-RENAME-45 obj *muse-nav-enemy-info*)
  (set! (-> obj max-path-index) (the float (+ (-> obj path curve num-cverts) -1)))
  (set! (-> obj current-path-index) 7.0)
  (set! (-> obj prev-path-index) 7.0)
  (set! (-> obj dest-path-index) 7.0)
  (set! (-> obj player-path-index) 0.0)
  (eval-path-curve-div! (-> obj path) (-> obj dest-point) (-> obj current-path-index) 'interp)
  (set! (-> obj collide-info trans quad) (-> obj dest-point quad))
  (set! (-> obj nav nearest-y-threshold) 20480.0)
  (set-vector! (-> obj neck twist-max) 8192.0 8192.0 0.0 1.0)
  (set! (-> obj neck up) (the-as uint 0))
  (set! (-> obj neck nose) (the-as uint 1))
  (set! (-> obj neck ear) (the-as uint 2))
  (set! (-> obj neck max-dist) 102400.0)
  (set! (-> obj neck ignore-angle) 16384.0)
  (set! (-> obj anim) (new 'static 'spool-anim
                        :name "muse-victory"
                        :index 9
                        :parts 2
                        :command-list '((1 blackout 0) (219 blackout 60))
                        )
        )
  (set! (-> obj victory-anim) (fuel-cell-pick-anim obj))
  (go muse-idle)
  (none)
  )
