;;-*-Lisp-*-
(in-package goal)
(bundles "SWA.DGO")
(require "engine/common-obs/nav-enemy.gc")

;; note: changed for high fps

(declare-type swamp-rat-nest process-drawable)

(declare-type billy process-taskable)

;; DECOMP BEGINS

(deftype swamp-rat (nav-enemy)
  ((up-vector          vector :inline)
   (state-float        float)
   (state-vector       vector :inline)
   (_hack              uint64)
   (wiggle-time        time-frame)
   (wiggle-angle       float)
   (delta-wiggle-angle float)
   (wiggle-factor      float)
   (min-height         float)
   (chase-rest-time    time-frame)
   (target-nav-time    time-frame))
  (:states
   swamp-rat-spawn))


(defskelgroup *swamp-rat-sg*
  swamp-rat
  swamp-rat-lod0-jg
  swamp-rat-idle-ja
  ((swamp-rat-lod0-mg (meters 20)) (swamp-rat-lod1-mg (meters 40)) (swamp-rat-lod2-mg (meters 999999)))
  :bounds (static-spherem 0 1 0 4)
  :longest-edge (meters 1))

(defmethod touch-handler ((this swamp-rat) (arg0 process) (arg1 event-message-block))
  (when ((method-of-type touching-shapes-entry prims-touching?)
         (the-as touching-shapes-entry (-> arg1 param 0))
         (-> this collide-info)
         (the-as uint 1))
    (when (nav-enemy-send-attack arg0 (the-as touching-shapes-entry (-> arg1 param 0)) 'generic)
      (let* ((s5-1 (-> this parent))
             (a0-4 (if (and (nonzero? s5-1) (type-type? pointer process-drawable)) s5-1)))
        (if a0-4 (send-event (the-as process-tree a0-4) 'victory) (go (method-of-object this nav-enemy-victory)))))))

(defbehavior swamp-rat-default-event-handler swamp-rat ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (case arg2
    (('victory) (go-virtual nav-enemy-victory))
    (else (nav-enemy-default-event-handler arg0 arg1 arg2 arg3))))

swamp-rat-default-event-handler

(defmethod common-post ((this swamp-rat))
  (when (logtest? (-> this collide-info status) (cshape-moving-flags onsurf))
    (vector-deg-seek (-> this up-vector) (-> this up-vector) (-> this collide-info surface-normal) 910.2222)
    (vector-normalize! (-> this up-vector) 1.0))
  (forward-up-nopitch->quaternion (-> this collide-info quat)
                                  (vector-z-quaternion! (new-stack-vector0) (-> this collide-info quat))
                                  (-> this up-vector))
  (call-parent-method this)
  (none))

(defmethod nav-enemy-method-38 ((this swamp-rat))
  (integrate-for-enemy-with-move-to-ground! (-> this collide-info)
                                            (-> this collide-info transv)
                                            (collide-kind background)
                                            8192.0
                                            #t
                                            #f
                                            #f)
  (when (< (-> this collide-info trans y) (-> this min-height))
    (let ((a1-1 (new 'stack-no-clear 'vector)))
      (set! (-> a1-1 quad) (-> this collide-info trans quad))
      (set! (-> a1-1 y) (-> this min-height))
      (move-to-ground-point! (-> this collide-info) a1-1 (-> this collide-info transv) *y-vector*)))
  0
  (none))

(defstate nav-enemy-idle (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :post
    (behavior ()
      (ja-post)))

(defstate nav-enemy-patrol (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :code
    (behavior ()
      (let ((f30-0 (nav-enemy-rnd-float-range 0.9 1.1)))
        (loop
          (ja-no-eval :group! (-> self draw art-group data (-> self nav-info walk-anim)) :num! (seek! max f30-0) :frame-num 0.0)
          (until (ja-done? 0)
            (suspend)
            (ja :num! (seek! max f30-0)))))))

(defstate nav-enemy-notice (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :code
    (behavior ()
      (ja-no-eval :num! (loop!))
      (ja-channel-push! 1 (seconds 0.17))
      (ja-no-eval :group! swamp-rat-notice-ja :num! (seek! (ja-aframe 30.0 0)) :frame-num 0.0)
      (until (ja-done? 0)
        (ja-blend-eval)
        (suspend)
        (ja :num! (seek! (ja-aframe 30.0 0))))
      (ja-no-eval :num! (seek!))
      (go-virtual nav-enemy-chase)))

(defbehavior swamp-rat-update-wiggle-params swamp-rat ()
  (let* ((f0-0 (rand-vu-float-range 0.0 1.0))
         (f1-1 (+ 1.0 (* 2.0 f0-0)))
         (f2-2 f1-1)
         (f2-4 (/ 1.0 f2-2))
         (f0-2 (+ 1.0 (/ f0-0 5))))
    (set! (-> self delta-wiggle-angle) (* 910.2222 f1-1))
    (set! (-> self wiggle-factor) (* 1.5 f2-4))
    (set! (-> self target-speed) (* 28672.0 f0-2))))

(defbehavior swamp-rat-update-wiggle-target swamp-rat ((arg0 vector))
  ;; og:preserve-this changed for high fps
  (+! (-> self wiggle-angle) (* DISPLAY_FPS_RATIO (-> self delta-wiggle-angle)))
  (if (< 65536.0 (-> self wiggle-angle)) (+! (-> self wiggle-angle) -65536.0))
  (let* ((v1-3 (-> self collide-info trans))
         (a1-1 (vector-! (new 'stack-no-clear 'vector) v1-3 arg0))
         (s3-0 (vector-rotate-around-y! (new 'stack-no-clear 'vector) a1-1 16384.0))
         (v1-4 (vector+*! (new 'stack-no-clear 'vector) arg0 s3-0 (* (-> self wiggle-factor) (sin (-> self wiggle-angle)))))
         (v0-3 (-> self nav target-pos)))
    (set! (-> v0-3 quad) (-> v1-4 quad))
    v0-3))

(defstate nav-enemy-chase (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :trans
    (behavior ()
      (if (time-elapsed? (-> self state-time) (-> self chase-rest-time)) (go-virtual nav-enemy-victory))
      ((-> (method-of-type nav-enemy nav-enemy-chase) trans)))
  :code
    (behavior ()
      (set-time! (-> self target-nav-time))
      (set! (-> self wiggle-time) (+ (current-time) (seconds -10)))
      (set! (-> self wiggle-angle) 0.0)
      (set! (-> self chase-rest-time) (rand-vu-int-range (seconds 1) (seconds 4)))
      (ja-channel-push! 1 (seconds 0.17))
      (ja :group! swamp-rat-run-ja :num! min)
      (loop
        (when (time-elapsed? (-> self wiggle-time) (seconds 1))
          (set-time! (-> self wiggle-time))
          (swamp-rat-update-wiggle-params))
        (suspend)
        (ja :num! (loop!))))
  :post
    (behavior ()
      (swamp-rat-update-wiggle-target (target-pos 0))
      (nav-enemy-travel-post)))

(defstate nav-enemy-stop-chase (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :code
    (-> (method-of-type nav-enemy nav-enemy-stop-chase)
        code))

(defstate nav-enemy-stare (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :code
    (behavior ()
      (set! (-> self rotate-speed) 1456355.5)
      (set! (-> self turn-time) (seconds 0.075))
      (let ((f30-0 (rand-vu-float-range 0.8 1.2)))
        (loop
          (logior! (-> self nav-enemy-flags) (nav-enemy-flags enable-travel))
          (ja-channel-push! 1 (seconds 0.1))
          (ja-no-eval :group! swamp-rat-celebrate-ja :num! (seek! max f30-0) :frame-num 0.0)
          (until (ja-done? 0)
            (suspend)
            (ja :num! (seek! max f30-0)))
          (ja-no-eval :num! (loop!))
          (logclear! (-> self nav-enemy-flags) (nav-enemy-flags enable-travel))
          (let ((gp-0 (rand-vu-int-range 300 600)))
            (suspend-for gp-0
              (ja :num-func num-func-identity :frame-num 0.0)
              (ja-blend-eval)
              (suspend)))))))

(defstate nav-enemy-give-up (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.075))
      (ja-no-eval :group! swamp-rat-idle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (logclear! (-> self nav flags) (nav-control-flags navcf17 navcf19))
      (nav-enemy-get-new-patrol-point)
      (ja-no-eval :group! swamp-rat-idle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (seek-to-point-toward-point! (-> self collide-info)
                                     (-> self nav destination-pos)
                                     (-> self rotate-speed)
                                     (-> self turn-time))
        (suspend)
        (ja :num! (seek!)))
      (go-virtual nav-enemy-patrol)))

(defstate nav-enemy-attack (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.075))
      (ja-no-eval :group! swamp-rat-idle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (go-virtual nav-enemy-victory)))

(defstate nav-enemy-victory (swamp-rat)
  :virtual #t
  :event swamp-rat-default-event-handler
  :code
    (-> (method-of-type nav-enemy nav-enemy-victory)
        code))

(defstate swamp-rat-spawn (swamp-rat)
  :event swamp-rat-default-event-handler
  :code
    (behavior ()
      (let ((gp-0 (new-stack-vector0)))
        (set! (-> gp-0 x) 0.0)
        (set! (-> gp-0 y) (- (-> *standard-dynamics* gravity-length)))
        (set! (-> gp-0 z) 0.0)
        (set! (-> gp-0 w) 1.0)
        (let ((f30-0 0.125))
          (set-time! (-> self state-time))
          (ja :group! swamp-rat-fall-ja :num! min)
          (loop
            (set! f30-0 (seek f30-0 1.5 0.1))
            (vector-v++! (-> self collide-info transv) gp-0)
            (integrate-for-enemy-with-move-to-ground! (-> self collide-info)
                                                      (-> self collide-info transv)
                                                      (collide-kind background)
                                                      8192.0
                                                      #t
                                                      #f
                                                      #f)
            (when (or (logtest? (-> self collide-info status) (cshape-moving-flags tsurf))
                      (or (< (-> self collide-info trans y) (-> self min-height)) (time-elapsed? (-> self state-time) (seconds 1))))
              0
              (goto cfg-13))
            (vector-float*! (-> self collide-info scale) *identity-vector* f30-0)
            (ja :num! (loop!))
            (suspend))))
      (label cfg-13)
      (if (< (-> self collide-info trans y) (-> self min-height)) (set! (-> self collide-info trans y) (-> self min-height)))
      (set! (-> self collide-info transv quad) (-> *null-vector* quad))
      (vector-float*! (-> self collide-info scale) *identity-vector* 1.5)
      (ja-no-eval :group! swamp-rat-bounce-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (if (target-in-range? self (-> self nav-info stop-chase-distance)) (go-virtual nav-enemy-chase) (go-virtual nav-enemy-idle)))
  :post nav-enemy-simple-post)

(define *swamp-rat-nav-enemy-info*
  (new 'static
       'nav-enemy-info
       :idle-anim 4
       :walk-anim 7
       :turn-anim 7
       :notice-anim 8
       :run-anim 9
       :jump-anim 9
       :jump-land-anim 6
       :victory-anim 10
       :taunt-anim 10
       :die-anim 11
       :neck-joint 7
       :run-travel-speed (meters 7)
       :run-rotate-speed (degrees 7999.9995)
       :run-acceleration (meters 1)
       :run-turn-time (seconds 0.075)
       :walk-travel-speed (meters 2)
       :walk-rotate-speed (degrees 7999.9995)
       :walk-acceleration (meters 1)
       :walk-turn-time (seconds 0.075)
       :attack-shove-back (meters 3)
       :attack-shove-up (meters 2)
       :shadow-size (meters 1)
       :notice-nav-radius (meters 1)
       :nav-nearest-y-threshold (meters 10)
       :notice-distance (meters 30)
       :stop-chase-distance (meters 40)
       :frustration-distance (meters 3)
       :frustration-time (seconds 1.5)
       :die-anim-hold-frame 20.0
       :jump-anim-start-frame 19.0
       :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 #f
       :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))

(defmethod initialize-collision ((this swamp-rat))
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum usually-hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 3))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind enemy))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set! (-> s4-0 prim-core action) (collide-action solid))
      (set! (-> s4-0 prim-core offense) (collide-offense normal-attack))
      (set-vector! (-> s4-0 local-sphere) 0.0 3686.4001 0.0 3686.4001)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> this collide-info) s5-0))
  0
  (none))

(defmethod nav-enemy-method-48 ((this swamp-rat))
  (initialize-skeleton this *swamp-rat-sg* '())
  (init-defaults! this *swamp-rat-nav-enemy-info*)
  (vector-float*! (-> this collide-info scale) *identity-vector* 1.5)
  (set! (-> this neck up) (the-as uint 1))
  (set! (-> this neck nose) (the-as uint 2))
  (set! (-> this neck ear) (the-as uint 0))
  (set! (-> this wiggle-angle) 0.0)
  (set! (-> this delta-wiggle-angle) 910.2222)
  (set! (-> this wiggle-factor) 1.5)
  (set! (-> this reaction-time) (rand-vu-int-range (seconds 0.1) (seconds 0.8)))
  (set! (-> this chase-rest-time) (seconds 1))
  (set! (-> this water) (new 'process 'water-control this 7 0.0 8192.0 2048.0))
  (set! (-> this water flags) (water-flags wt01))
  (set! (-> this water height) (res-lump-float (-> this entity) 'water-height))
  (set! (-> this water ripple-size) 12288.0)
  (set! (-> this min-height) (+ -2048.0 (-> this water height)))
  (set! (-> this up-vector quad) (-> *y-vector* quad))
  0
  (none))

(defbehavior swamp-rat-init-by-other swamp-rat ((arg0 billy) (arg1 vector) (arg2 vector) (arg3 pickup-type) (arg4 symbol))
  (initialize-collision self)
  (if arg4 (logclear! (-> self mask) (process-mask actor-pause)) (logior! (-> self mask) (process-mask actor-pause)))
  (set! (-> self collide-info trans quad) (-> arg1 quad))
  (forward-up->quaternion (-> self collide-info quat) arg2 *up-vector*)
  (vector-float*! (-> self collide-info scale) *identity-vector* 1.5)
  (vector-float*! (-> self collide-info transv) arg2 49152.0)
  (set! (-> self entity) (-> arg0 entity))
  (nav-enemy-method-48 self)
  (set! (-> self enemy-info pickup-type) arg3)
  (go swamp-rat-spawn)
  (none))
