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

;; name: fma-sphere.gc
;; name in dgo: fma-sphere
;; dgos: GAME

;; +++fma-sphere-mode
(defenum fma-sphere-mode
  :type uint32
  :bitfield #t
  (nav 0)
  (kill-once 1)
  (danger 2)
  (deadly-overlap 3)
  )
;; ---fma-sphere-mode


;; DECOMP BEGINS

(deftype fma-sphere-params (structure)
  ((mode         fma-sphere-mode)
   (proc         process-focusable)
   (track-joint  int32)
   (duration     time-frame)
   (sphere       sphere)
   (danger       traffic-danger-info)
   (nav-mesh-id  uint32)
   )
  )


(deftype fma-sphere (process-drawable)
  ((root          collide-shape       :override)
   (first-time?   symbol)
   (mode          fma-sphere-mode)
   (track-handle  handle)
   (track-joint   int32)
   (attack-id     uint32)
   (duration      time-frame)
   (sphere        sphere               :inline)
   (danger        traffic-danger-info  :inline)
   )
  (:state-methods
    idle
    )
  )


(defmethod run-logic? ((this fma-sphere))
  "Should this process be run? Checked by execute-process-tree."
  (or (logtest? *display-scene-control* (scene-controls display-controls))
      (and *display-nav-marks* (logtest? (-> this mode) (fma-sphere-mode nav)))
      (logtest? (-> this mode) (fma-sphere-mode deadly-overlap))
      (>= (-> this track-joint) 0)
      (-> this first-time?)
      )
  )

(defstate idle (fma-sphere)
  :virtual #t
  :event (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
    (case message
      (('touched)
       (let ((v1-1 (-> block param 0)))
         (if v1-1
             (send-event
               proc
               'attack
               v1-1
               (static-attack-info :mask (vehicle-impulse-factor) ((id (-> self attack-id))
                                                                   (damage 2.0)
                                                                   (vehicle-damage-factor 1.0)
                                                                   (vehicle-impulse-factor 1.0)
                                                                   (mode 'eco-red)
                                                                   (attacker-velocity (-> self root transv))
                                                                   (knock (knocked-type explode-or-darkjak))
                                                                   )
                                   )
               )
             )
         )
       )
      )
    )
  :enter (behavior ()
    (set-time! (-> self state-time))
    (set! (-> self first-time?) #f)
    (if (logtest? (-> self mode) (fma-sphere-mode kill-once))
        (send-event *traffic-manager* 'kill-traffic-sphere (-> self sphere))
        )
    )
  :trans (behavior ()
    (local-vars (at-0 int))
    (rlet ((vf0 :class vf)
           (vf1 :class vf)
           (vf2 :class vf)
           )
      (init-vf0-vector)
      (let ((v1-0 (-> self duration)))
        (if (and (nonzero? v1-0) (time-elapsed? (-> self state-time) v1-0))
            (go empty-state)
            )
        )
      (let ((v1-5 (-> self track-joint)))
        (when (>= v1-5 0)
          (let ((a2-0 (handle->process (-> self track-handle)))
                (gp-0 (new 'stack-no-clear 'vector))
                )
            (when a2-0
              (vector-copy! gp-0 (-> self sphere))
              (set! (-> gp-0 w) 1.0)
              (vector-matrix*! gp-0 gp-0 (-> (the-as process-drawable a2-0) node-list data v1-5 bone transform))
              (let ((v1-9 (-> self root)))
                (vector-! (-> v1-9 transv) gp-0 (-> v1-9 trans))
                (let ((a0-12 (-> v1-9 transv)))
                  (.lvf vf1 (&-> (-> v1-9 transv) quad))
                  (let ((f0-1 (-> self clock frames-per-second)))
                    (.mov at-0 f0-1)
                    )
                  (.mov vf2 at-0)
                  (.mov.vf.w vf1 vf0)
                  (.mul.x.vf.xyz vf1 vf1 vf2)
                  (.svf (&-> a0-12 quad) vf1)
                  )
                )
              (move-to-point! (-> self root) gp-0)
              (set! (-> self danger sphere x) (-> gp-0 x))
              (set! (-> self danger sphere y) (-> gp-0 y))
              (set! (-> self danger sphere z) (-> gp-0 z))
              )
            )
          )
        )
      (if (logtest? (-> self mode) (fma-sphere-mode danger))
          (send-event *traffic-manager* 'add-danger-sphere (-> self danger))
          )
      (when (logtest? (-> self mode) (fma-sphere-mode deadly-overlap))
        (let ((a1-10 (new 'stack-no-clear 'overlaps-others-params)))
          (set! (-> a1-10 options) (overlaps-others-options))
          (set! (-> a1-10 collide-with-filter) (the-as collide-spec -1))
          (set! (-> a1-10 tlist) *touching-list*)
          (find-overlapping-shapes (-> self root) a1-10)
          )
        )
      (if (or (logtest? *display-scene-control* (scene-controls display-controls))
              (and *display-nav-marks* (logtest? (-> self mode) (fma-sphere-mode nav)))
              )
          (add-debug-sphere
            #t
            (bucket-id debug)
            (-> self root trans)
            (-> self sphere r)
            (new 'static 'rgba :r #x80 :g #x40 :a #x80)
            )
          )
      )
    )
  :code sleep-code
  )

(defbehavior fma-sphere-init-by-other fma-sphere ((fma-parms fma-sphere-params))
  (set! (-> self mode) (-> fma-parms mode))
  (set! (-> self first-time?) #t)
  (set! (-> self duration) (-> fma-parms duration))
  (cond
    ((and (-> fma-parms proc) (>= (-> fma-parms track-joint) 0))
     (set! (-> self track-joint) (-> fma-parms track-joint))
     (set! (-> self track-handle) (process->handle (-> fma-parms proc)))
     )
    (else
      (set! (-> self track-joint) -1)
      (set! (-> self track-handle) (the-as handle #f))
      )
    )
  (cond
    ((-> fma-parms danger)
     (mem-copy! (the-as pointer (-> self danger)) (the-as pointer (-> fma-parms danger)) 54)
     (cond
       (sphere
         (set! (-> self sphere quad) (-> fma-parms sphere quad))
         (set! (-> self danger sphere quad) (-> fma-parms sphere quad))
         )
       (else
         (set! (-> self sphere quad) (-> self danger sphere quad))
         )
       )
     )
    (sphere
      (set! (-> self sphere quad) (-> fma-parms sphere quad))
      (when (logtest? (-> self mode) (fma-sphere-mode danger))
        (set! (-> self danger sphere quad) (-> fma-parms sphere quad))
        (set! (-> self danger velocity quad) (the-as uint128 0))
        (set! (-> self danger notify-radius) (+ 40960.0 (-> self sphere r)))
        (set! (-> self danger danger-level) 1.0)
        (set! (-> self danger decay-rate) 0.0)
        (set! (-> self danger flags) (the-as uint 1))
        (set! (-> self danger danger-type) (the-as uint 4))
        )
      )
    (else
      (format 0 "ERROR: Initializing an fma-sphere without a sphere or danger info!~%")
      (go empty-state)
      )
    )
  (let ((s5-0 (new 'process 'collide-shape self (collide-list-enum hit-by-player))))
    (let ((v1-32 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> v1-32 prim-core collide-as) (collide-spec obstacle))
      (set-vector! (-> v1-32 local-sphere) 0.0 0.0 0.0 4096.0)
      (set! (-> s5-0 total-prims) (the-as uint 1))
      (set! (-> s5-0 root-prim) v1-32)
      )
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (let ((v1-35 (-> s5-0 root-prim)))
      (set! (-> s5-0 backup-collide-as) (-> v1-35 prim-core collide-as))
      (set! (-> s5-0 backup-collide-with) (-> v1-35 prim-core collide-with))
      )
    (set! (-> self root) s5-0)
    )
  (let ((s5-1 (-> self root)))
    (set! (-> s5-1 nav-radius) (-> self sphere r))
    (set! (-> s5-1 root-prim local-sphere w) (-> self sphere r))
    (vector-copy! (-> s5-1 trans) (-> self sphere))
    (set! (-> s5-1 trans w) 1.0)
    (vector-identity! (-> s5-1 scale))
    (quaternion-identity! (-> s5-1 quat))
    (cond
      ((logtest? (-> self mode) (fma-sphere-mode deadly-overlap))
       (set! (-> s5-1 event-self) 'touched)
       (let ((v1-43 (-> s5-1 root-prim)))
         (set! (-> v1-43 prim-core collide-with) (collide-spec crate civilian enemy hit-by-others-list))
         (logior! (-> v1-43 prim-core action) (collide-action deadly))
         )
       )
      (else
        (let ((v1-44 (-> s5-1 root-prim)))
          (set! (-> v1-44 prim-core collide-as) (collide-spec))
          (set! (-> v1-44 prim-core collide-with) (collide-spec))
          )
        0
        )
      )
    (update-transforms s5-1)
    )
  (logclear! (-> self mask) (process-mask actor-pause enemy))
  (when (logtest? (-> self mode) (fma-sphere-mode nav))
    (let ((a0-33 (if (zero? (-> fma-parms nav-mesh-id))
                     (find-nearest-nav-mesh (-> self root trans) (the-as float #x7f800000))
                     (get-nav-mesh (the-as actor-id (-> fma-parms nav-mesh-id)))
                     )
                 )
          )
      (cond
        (a0-33
          (add-process-drawable-to-nav-mesh a0-33 self #f)
          )
        (else
          (format 0 "ERROR: fma-sphere-init-by-other: failed to find nearest nav-mesh!~%")
          (go empty-state)
          )
        )
      )
    )
  (when (logtest? (-> self mode) (fma-sphere-mode deadly-overlap))
    (let* ((v1-62 *game-info*)
           (a0-37 (+ (-> v1-62 attack-id) 1))
           )
      (set! (-> v1-62 attack-id) a0-37)
      (set! (-> self attack-id) a0-37)
      )
    )
  (go-virtual idle)
  )
