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

;; note: changed for high fps

;; DECOMP BEGINS

(defun find-adjacent-bounds-one ((arg0 nav-mesh) (arg1 nav-poly) (arg2 int) (arg3 (array int8)) (arg4 (array int8)) (arg5 vector))
  (local-vars (v0-2 object) (v1-2 int) (v1-30 int) (a0-2 int) (a0-12 int) (sv-16 nav-poly) (sv-32 int))
  (let ((v1-1 (+ arg2 1))) (let ((a0-1 2)) (set-on-less-than a0-2 a0-1 v1-1)) (move-if-not-zero v1-2 0 a0-2 v1-1))
  (let ((v1-4 (-> arg1 adj-poly v1-2)))
    (cond
      ((= v1-4 255))
      ((not (logtest? (-> arg0 poly v1-4 pat) 1))
       (format 0 "ERROR<GMJ>: find-adjacent-bounds-one given a non-boundary edge to start~%")
       (return #f))))
  (let ((s0-0 (-> arg1 vertex (-> arg3 arg2))))
    (set! sv-16 arg1)
    (while (begin
             (label cfg-28)
             #t)
      (set! sv-32 0)
      (while (< sv-32 3)
        (cond
          ((and (= sv-32 arg2) (= sv-16 arg1)))
          ((= s0-0 (-> sv-16 vertex (-> arg4 sv-32)))
           (vector+! arg5 (-> arg0 origin) (the-as vector (-> arg0 vertex (-> sv-16 vertex (-> arg3 sv-32)))))
           (let ((v1-29 (+ sv-32 1)))
             (let ((a0-11 2)) (set-on-less-than a0-12 a0-11 v1-29))
             (move-if-not-zero v1-30 0 a0-12 v1-29))
           (let ((v1-32 (-> sv-16 adj-poly v1-30)))
             (if (= v1-32 255) (return #t))
             (let ((v1-35 (-> arg0 poly v1-32)))
               (set! v0-2
                     (cond
                       ((= arg1 v1-35) (format 0 "ERROR<GMJ>: find-adjacent-bounds-one given tried to go back~%"))
                       (else
                        (cond
                          ((logtest? (-> v1-35 pat) 1) (return #t))
                          (else (set! arg1 sv-16) (set! sv-16 v1-35) (goto cfg-28)))
                        v0-2)))))))
        (set! sv-32 (+ sv-32 1)))
      (format 0 "ERROR<GMJ>: abnormal exit from find-adjacent-bounds-one~%")
      (return #f)))
  #f)

;; WARN: Function find-adjacent-bounds has a return type of none, but the expression builder found a return statement.
(defun find-adjacent-bounds ((arg0 nav-mesh) (arg1 clip-travel-vector-to-mesh-return-info))
  (when (!= (-> arg1 found-boundary) #t)
    (format 0 "ERROR<GMJ>: find-adjacent-bounds passed info which doesn't specify a boundary edge~%")
    (return #f))
  (find-adjacent-bounds-one arg0 (-> arg1 poly) (-> arg1 edge) *edge-vert0-table* *edge-vert1-table* (-> arg1 vert-prev))
  (find-adjacent-bounds-one arg0 (-> arg1 poly) (-> arg1 edge) *edge-vert1-table* *edge-vert0-table* (-> arg1 vert-next))
  (vector-reset! (-> arg1 prev-normal))
  (vector-reset! (-> arg1 next-normal))
  (set! (-> arg1 prev-normal x) (- (-> arg1 vert-prev z) (-> arg1 vert-0 z)))
  (set! (-> arg1 prev-normal z) (- (-> arg1 vert-0 x) (-> arg1 vert-prev x)))
  (set! (-> arg1 next-normal x) (- (-> arg1 vert-1 z) (-> arg1 vert-next z)))
  (set! (-> arg1 next-normal z) (- (-> arg1 vert-next x) (-> arg1 vert-1 x)))
  (vector-normalize! (-> arg1 prev-normal) 1.0)
  (vector-normalize! (-> arg1 next-normal) 1.0)
  (camera-line (-> arg1 vert-prev) (-> arg1 vert-0) (new 'static 'vector4w :x #xff :w #x80))
  (camera-line (-> arg1 vert-0) (-> arg1 vert-1) (new 'static 'vector4w :y #xff :w #x80))
  (camera-line (-> arg1 vert-1) (-> arg1 vert-next) (new 'static 'vector4w :z #xff :w #x80))
  (let ((s5-1 (new 'stack-no-clear 'vector)))
    (vector+! s5-1 (-> arg1 vert-prev) (-> arg1 vert-0))
    (vector-float*! s5-1 s5-1 0.5)
    (camera-line-rel-len s5-1 (-> arg1 prev-normal) 8192.0 (new 'static 'vector4w :x #xff :w #x80))
    (vector+! s5-1 (-> arg1 vert-0) (-> arg1 vert-1))
    (vector-float*! s5-1 s5-1 0.5)
    (camera-line-rel-len s5-1 (-> arg1 boundary-normal) 8192.0 (new 'static 'vector4w :y #xff :w #x80))
    (vector+! s5-1 (-> arg1 vert-1) (-> arg1 vert-next))
    (vector-float*! s5-1 s5-1 0.5)
    (camera-line-rel-len s5-1 (-> arg1 next-normal) 8192.0 (new 'static 'vector4w :z #xff :w #x80)))
  (none))

(deftype fleeing-nav-enemy-info (structure)
  ((min-reflect-angle       float)
   (max-reflect-angle       float)
   (max-boundary-deflection float)
   (deflection-min-dist     float)
   (deflection-max-dist     float)
   (reflection-time         int32)
   (travel-rotate-speed     float)
   (blend_interp_angle      float)
   (min-speed-adjust        float)
   (max-speed-adjust        float)
   (speed-adjust-center     float)
   (speed-adjust-range      float)
   (abort-notice-distance   float)
   (min-notice-dist         float)
   (max-notice-dist         float)
   (min-stop-chase-dist     float)
   (max-stop-chase-dist     float)
   (max-flee-rotation       float))
  :allow-misaligned)


(deftype fleeing-nav-enemy (nav-enemy)
  ((last-reflection-time time-frame)
   (run-blend-interp     float)
   (desired-travel       vector :inline)
   (saved-travel         vector :inline)
   (speed-adjust         float)
   (flee-info            fleeing-nav-enemy-info :inline))
  (:states
   fleeing-nav-enemy-debug))


(defbehavior fleeing-nav-enemy-adjust-nav-info fleeing-nav-enemy ()
  (let ((f30-0 (vector-vector-distance (-> *camera* tpos-curr-adj) (-> *camera* tpos-old-adj))))
    ;; og:preserve-this
    ;; High FPS fix: stop-chase and notice distances are calculated between a min/max range where
    ;; the further the camera moved since last frame decides how close the chosen value is to the
    ;; max distance. Since this is called more often above 60 FPS, the distance is skewed to the
    ;; lower end. This scales the distance back up based on the FPS ratio.
    (set! f30-0 (/ f30-0 DISPLAY_FPS_RATIO))
    (set! (-> self nav-info notice-distance)
          (lerp-clamp (-> self flee-info min-notice-dist)
                      (-> self flee-info max-notice-dist)
                      (parameter-ease-sin-clamp (* 0.00081380206 (+ -409.6 f30-0)))))
    (set! (-> self nav-info stop-chase-distance)
          (lerp-clamp (-> self flee-info min-stop-chase-dist)
                      (-> self flee-info max-stop-chase-dist)
                      (parameter-ease-sin-clamp (* 0.00081380206 (+ -409.6 f30-0)))))))

(defun fleeing-nav-enemy-clip-travel ((arg0 fleeing-nav-enemy) (arg1 vector))
  (local-vars (sv-224 vector) (sv-240 vector) (sv-256 vector) (sv-272 vector) (sv-288 vector))
  (let ((s2-0 (new 'stack 'clip-travel-vector-to-mesh-return-info))
        (gp-0 (new 'stack-no-clear 'vector))
        (s1-0 #f))
    (set! (-> gp-0 quad) (-> arg0 nav travel quad))
    (set! (-> arg0 nav travel quad) (-> arg1 quad))
    (nav-control-method-24 (-> arg0 nav) (-> arg0 flee-info deflection-max-dist) s2-0)
    (when (-> s2-0 found-boundary)
      (let ((s0-0 (new 'stack-no-clear 'vector))
            (s3-0 (new 'stack-no-clear 'vector)))
        0.0
        0.0
        (vector-! s0-0 (-> s2-0 intersection) (-> arg0 collide-info trans))
        (set! (-> arg0 nav travel quad) (-> s0-0 quad))
        (let ((f28-0 (vector-dot s0-0 (-> s2-0 boundary-normal))))
          (set! (-> s0-0 quad) (-> arg1 quad))
          (set! (-> s0-0 y) 0.0)
          (vector-normalize! s0-0 1.0)
          (let ((f30-0 (vector-dot s0-0 (-> s2-0 boundary-normal))))
            (cond
              ((< (-> arg0 flee-info deflection-min-dist) f28-0)
               (let* ((f0-9 (/ (- f28-0 (-> arg0 flee-info deflection-min-dist))
                               (- (-> arg0 flee-info deflection-max-dist) (-> arg0 flee-info deflection-min-dist))))
                      (f0-10 (fmin 1.0 f0-9))
                      (f28-1 (* (- 1.0 f0-10) (-> arg0 flee-info max-boundary-deflection))))
                 (cond
                   ((< (cos f28-1) f30-0)
                    (vector--float*! s3-0 s0-0 (-> s2-0 boundary-normal) f30-0)
                    (let ((s0-1 vector-normalize!)) (set! sv-224 s3-0) (let ((a1-7 (sin f28-1))) (s0-1 sv-224 a1-7)))
                    (let ((s0-2 vector+float*!))
                      (set! sv-240 s3-0)
                      (set! sv-256 s3-0)
                      (let ((s2-1 (-> s2-0 boundary-normal))
                            (a3-1 (cos f28-1)))
                        (s0-2 sv-240 sv-256 s2-1 a3-1))))
                   (else (let ((v1-15 s3-0)) (set! (-> v1-15 quad) (-> s0-0 quad)) v1-15)))))
              ((< (cos (-> arg0 flee-info min-reflect-angle)) f30-0)
               (vector--float*! s3-0 s0-0 (-> s2-0 boundary-normal) f30-0)
               (vector-normalize! s3-0 (sin (-> arg0 flee-info min-reflect-angle)))
               (let ((s1-2 vector--float*!)
                     (s0-4 s3-0))
                 (set! sv-272 s3-0)
                 (let ((s2-2 (-> s2-0 boundary-normal))
                       (a3-3 (cos (-> arg0 flee-info min-reflect-angle))))
                   (s1-2 s0-4 sv-272 s2-2 a3-3)))
               (set! s1-0 #t))
              ((< f30-0 (cos (-> arg0 flee-info max-reflect-angle)))
               (vector--float*! s3-0 s0-0 (-> s2-0 boundary-normal) f30-0)
               (vector-normalize! s3-0 (sin (-> arg0 flee-info max-reflect-angle)))
               (let ((s1-4 vector--float*!)
                     (s0-6 s3-0))
                 (set! sv-288 s3-0)
                 (let ((s2-3 (-> s2-0 boundary-normal))
                       (a3-5 (cos (-> arg0 flee-info max-reflect-angle))))
                   (s1-4 s0-6 sv-288 s2-3 a3-5)))
               (set! s1-0 #t))
              (else (vector--float*! s3-0 s0-0 (-> s2-0 boundary-normal) (* 2.0 f30-0)) (set! s1-0 #t)))))
        (vector-normalize-copy! arg1 s3-0 (-> arg0 flee-info deflection-max-dist))))
    (set! (-> arg0 nav travel quad) (-> gp-0 quad))
    s1-0))

(defun fleeing-nav-enemy-adjust-travel ((arg0 fleeing-nav-enemy) (arg1 object))
  (let ((s3-0 (new 'stack-no-clear 'matrix))
        (s4-0 (new 'stack-no-clear 'vector)))
    (let ((s5-0 (new 'stack-no-clear 'vector)))
      (set! (-> s4-0 quad) (-> arg0 saved-travel quad))
      (set! (-> s4-0 y) 0.0)
      (set! (-> s5-0 quad) (-> arg0 desired-travel quad))
      (set! (-> s5-0 y) 0.0)
      (vector-normalize! s4-0 1.0)
      (vector-normalize! s5-0 1.0)
      (matrix-from-two-vectors-max-angle-partial! s3-0 s4-0 s5-0 (-> arg0 flee-info travel-rotate-speed) 0.2))
    (vector-matrix*! (-> arg0 saved-travel) s4-0 s3-0))
  (vector-float*! (-> arg0 saved-travel) (-> arg0 saved-travel) (-> arg0 flee-info deflection-max-dist))
  (set! (-> arg0 nav travel quad) (-> arg0 saved-travel quad))
  (vector+! (-> arg0 nav target-pos) (-> arg0 collide-info trans) (-> arg0 nav travel)))

(defbehavior fleeing-nav-enemy-chase-post-func fleeing-nav-enemy ()
  (let ((gp-0 (new 'stack-no-clear 'matrix))
        (s5-0 (new 'stack-no-clear 'matrix)))
    (quaternion->matrix gp-0 (-> self collide-info quat))
    (set! (-> self collide-info old-y-angle-diff) 0.0)
    (nav-enemy-travel-post)
    (quaternion->matrix s5-0 (-> self collide-info quat))
    (set! (-> self run-blend-interp) (acos (vector-dot (-> s5-0 vector 2) (-> gp-0 vector 2))))
    (set! (-> self run-blend-interp) (/ (-> self run-blend-interp) (-> self flee-info blend_interp_angle)))
    (if (< (vector-dot (-> s5-0 vector 2) (-> gp-0 vector 0)) 0.0)
      (set! (-> self run-blend-interp) (- (-> self run-blend-interp))))))

(defbehavior fleeing-nav-enemy-chase-post fleeing-nav-enemy ()
  (let ((gp-0 (new 'stack-no-clear 'vector)))
    (vector-! gp-0 (-> self collide-info trans) (target-pos 0))
    (let* ((f0-1 (vector-dot (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> self desired-travel) 1.0) gp-0))
           (f0-3 (/ (- (-> self flee-info speed-adjust-center) f0-1) (-> self flee-info speed-adjust-range)))
           (f1-3 (+ 1.0 f0-3)))
      (set! (-> self target-speed)
            (* (fmax (-> self flee-info min-speed-adjust) (fmin (-> self flee-info max-speed-adjust) f1-3))
               (-> self nav-info run-travel-speed))))
    (when (time-elapsed? (-> self last-reflection-time) (-> self flee-info reflection-time))
      (let ((s3-0 (new 'stack-no-clear 'matrix))
            (s5-2 (new 'stack-no-clear 'vector)))
        (let ((s4-1 (new 'stack-no-clear 'vector)))
          (set! (-> s5-2 quad) (-> self desired-travel quad))
          (set! (-> s5-2 y) 0.0)
          (set! (-> s4-1 quad) (-> gp-0 quad))
          (set! (-> s4-1 y) 0.0)
          (if (= (vector-normalize-ret-len! s5-2 1.0) 0.0) (set! (-> s5-2 quad) (-> s4-1 quad)))
          (vector-normalize-ret-len! s4-1 1.0)
          (matrix-from-two-vectors-max-angle-partial! s3-0 s5-2 s4-1 (-> self flee-info max-flee-rotation) 0.25))
        (vector-matrix*! s5-2 s5-2 s3-0)
        (vector-float*! (-> self desired-travel) s5-2 (-> self flee-info deflection-max-dist)))))
  (if (fleeing-nav-enemy-clip-travel self (-> self desired-travel)) (set-time! (-> self last-reflection-time)))
  (fleeing-nav-enemy-adjust-travel self (-> self desired-travel))
  (fleeing-nav-enemy-chase-post-func)
  0
  (none))

(defstate nav-enemy-patrol (fleeing-nav-enemy)
  :virtual #t
  :enter
    (-> (method-of-type nav-enemy nav-enemy-patrol)
        enter)
  :exit
    (-> (method-of-type nav-enemy nav-enemy-patrol)
        exit)
  :trans
    (behavior ()
      ((-> (method-of-type nav-enemy nav-enemy-patrol) trans))
      (fleeing-nav-enemy-adjust-nav-info))
  :code
    (-> (method-of-type nav-enemy nav-enemy-patrol)
        code)
  :post
    (-> (method-of-type nav-enemy nav-enemy-patrol)
        post))

(defstate nav-enemy-notice (fleeing-nav-enemy)
  :virtual #t
  :enter
    (-> (method-of-type nav-enemy nav-enemy-notice)
        enter)
  :trans
    (behavior ()
      (fleeing-nav-enemy-adjust-nav-info))
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.075))
      (let ((f30-0 (nav-enemy-rnd-float-range 1.0 1.2)))
        (ja-no-eval :group! (-> self draw art-group data (-> self nav-info notice-anim)) :num! (seek! max f30-0) :frame-num 0.0)
        (until (ja-done? 0)
          (seek-toward-heading-vec! (-> self collide-info) (-> self nav travel) (-> self rotate-speed) (-> self turn-time))
          (if (and *target*
                   (>= (-> self flee-info abort-notice-distance)
                       (vector-vector-distance (-> self collide-info trans) (-> *target* control trans))))
            (go-virtual nav-enemy-chase))
          (suspend)
          (ja :num! (seek! max f30-0))))
      (go-virtual nav-enemy-chase))
  :post
    (-> (method-of-type nav-enemy nav-enemy-notice)
        post))

(defstate nav-enemy-chase (fleeing-nav-enemy)
  :virtual #t
  :enter
    (behavior ()
      (logior! (-> self nav flags) (nav-control-flags navcf12))
      ((-> (method-of-type nav-enemy nav-enemy-chase) enter)))
  :exit
    (behavior ()
      (logclear! (-> self nav flags) (nav-control-flags navcf12)))
  :trans
    (behavior ()
      ((-> (method-of-type nav-enemy nav-enemy-chase) trans))
      (fleeing-nav-enemy-adjust-nav-info))
  :code
    (-> (method-of-type nav-enemy nav-enemy-chase)
        code)
  :post
    (-> (method-of-type nav-enemy nav-enemy-chase)
        post))

(defstate nav-enemy-stop-chase (fleeing-nav-enemy)
  :virtual #t
  :enter
    (-> (method-of-type nav-enemy nav-enemy-stop-chase)
        enter)
  :trans
    (behavior ()
      ((-> (method-of-type nav-enemy nav-enemy-stop-chase) trans))
      (fleeing-nav-enemy-adjust-nav-info))
  :code
    (-> (method-of-type nav-enemy nav-enemy-stop-chase)
        code)
  :post
    (-> (method-of-type nav-enemy nav-enemy-stop-chase)
        post))

(defstate fleeing-nav-enemy-debug (fleeing-nav-enemy)
  :enter
    (-> (method-of-type nav-enemy nav-enemy-chase)
        enter)
  :code
    (behavior ()
      (let ((gp-0 (new-stack-vector0))
            (s5-0 (new-stack-vector0)))
        (set! (-> gp-0 x) 1.0)
        (set! (-> s5-0 x) 1.0)
        (loop
          (when (cpad-pressed? 1 r3)
            (suspend)
            (go fleeing-nav-enemy-debug))
          (let ((s2-0 (new-stack-vector0))
                (s4-0 (new-stack-vector0)))
            (let ((s3-0 (new-stack-matrix0)))
              (clmf-input s2-0 s4-0 1)
              (vector-float*! s2-0 s2-0 409.6)
              (vector-float*! s4-0 s4-0 1820.4445)
              (matrix-axis-angle! s3-0 (-> *camera* local-down) (-> s2-0 y))
              (vector-matrix*! gp-0 gp-0 s3-0))
            (if *target* (vector-! gp-0 (-> self collide-info trans) (target-pos 0)))
            (vector-normalize! gp-0 (-> self flee-info deflection-max-dist))
            (let ((s3-3 (new 'stack-no-clear 'vector)))
              (set! (-> s3-3 quad) (-> self nav travel quad))
              (set! (-> self nav travel quad) (-> s5-0 quad))
              (set! (-> self desired-travel quad) (-> gp-0 quad))
              (fleeing-nav-enemy-clip-travel self (-> self desired-travel))
              (fleeing-nav-enemy-adjust-travel self (-> self desired-travel))
              (set! (-> s5-0 quad) (-> self nav travel quad))
              (set! (-> self nav travel quad) (-> s3-3 quad)))
            (vector+! (-> self nav target-pos) (-> self collide-info trans) s4-0))
          (suspend))))
  :post nav-enemy-travel-post)

(define *lightning-mole-hole* (new 'static 'vector :x -241664.0 :y 106496.0 :z -6393856.0))

(deftype lightning-mole (fleeing-nav-enemy)
  ((debug-vector vector :inline)
   (alt-actor    entity-actor))
  (:states
   lightning-mole-debug-blend
   lightning-mole-debug-run
   lightning-mole-dive
   lightning-mole-gone
   lightning-mole-head-for-hole
   lightning-mole-hiding
   lightning-mole-yelp))


(defskelgroup *lightning-mole-sg*
  lightning-mole
  lightning-mole-lod0-jg
  lightning-mole-idle-ja
  ((lightning-mole-lod0-mg (meters 20)) (lightning-mole-lod1-mg (meters 40)) (lightning-mole-lod2-mg (meters 999999)))
  :bounds (static-spherem 0 0 0 8)
  :shadow lightning-mole-shadow-mg)

(defbehavior lightning-mole-task-complete? lightning-mole ()
  (local-vars (sv-16 symbol))
  (process-entity-status! self (entity-perm-status complete) #t)
  (when (or (-> self link prev) (-> self link next))
    (set! sv-16 (the-as symbol #f))
    (apply-all (-> self link) actor-link-subtask-complete-hook (& sv-16))
    (cond
      (sv-16
       (close-specific-task! (-> self entity extra perm task) (task-status need-reminder))
       (process-spawn-function process
         (lambda :behavior lightning-mole ()
           (while (or (-> *setting-control* current ambient) (-> *setting-control* current movie) (-> *setting-control* current hint))
             (suspend))
           (level-hint-spawn (text-id rolling-moles-resolution) "sksp0112" (the-as entity #f) *entity-pool* (game-task none))
           (none))
         :to
         self)
       (format #t "lightning-mole task is complete~%"))
      (else))
    sv-16))

(defbehavior lightning-mole-hole-post lightning-mole ()
  (set! (-> self nav target-pos quad) (-> *lightning-mole-hole* quad))
  (nav-enemy-travel-post)
  0
  (none))

(defbehavior lightning-mole-run-code lightning-mole ()
  (when (!= (ja-group) lightning-mole-run-ja)
    (ja-channel-push! 1 (seconds 0.2))
    (ja :group! lightning-mole-run-ja))
  (loop
    (ja :num! (loop! (-> self speed-adjust)))
    (suspend))
  (none))

(defstate lightning-mole-debug-blend (lightning-mole)
  :trans
    (behavior ()
      (let ((gp-0 (new-stack-vector0)))
        (let ((a1-0 (new-stack-vector0))) (clmf-input gp-0 a1-0 1))
        (set! (-> self run-blend-interp) (-> gp-0 y)))
      (set! (-> self speed-adjust) 1.0))
  :code lightning-mole-run-code
  :post ja-post)

(defstate lightning-mole-debug-run (lightning-mole)
  :enter
    (behavior ()
      (set! (-> self speed-adjust) 1.0)
      (set-vector! (-> self debug-vector) 0.0 0.0 1.0 1.0)
      (set! (-> self saved-travel quad) (-> self debug-vector quad))
      ((-> (method-of-type nav-enemy nav-enemy-chase) enter)))
  :trans
    (behavior ()
      (when (cpad-pressed? 1 r3)
        (logclear! (-> *cpad-list* cpads 1 button0-abs 0) (pad-buttons r3))
        (logclear! (-> *cpad-list* cpads 1 button0-rel 0) (pad-buttons r3))
        (go lightning-mole-debug-run)))
  :code lightning-mole-run-code
  :post
    (behavior ()
      (let ((gp-0 (new 'stack-no-clear 'vector)))
        (let ((s4-0 (new-stack-vector0))
              (a1-0 (new-stack-vector0))
              (s5-0 (new-stack-matrix0)))
          (clmf-input s4-0 a1-0 1)
          (vector-float*! s4-0 s4-0 1820.4445)
          (matrix-axis-angle! s5-0 (-> *camera* local-down) (-> s4-0 y))
          (vector-matrix*! (-> self debug-vector) (-> self debug-vector) s5-0))
        (vector-normalize! (-> self debug-vector) (-> self flee-info deflection-max-dist))
        (camera-line-rel (-> self collide-info trans) (-> self debug-vector) (new 'static 'vector4w :x #x80 :y #x80 :w #x80))
        (set! (-> gp-0 quad) (-> self debug-vector quad))
        (set! (-> self target-speed) (-> self nav-info run-travel-speed))
        (format *stdcon* "tgt-speed ~M defmd ~M~%" (-> self target-speed) (-> self flee-info deflection-max-dist))
        (if (time-elapsed? (-> self last-reflection-time) (-> self flee-info reflection-time))
          (vector-normalize-copy! (-> self desired-travel) gp-0 (-> self flee-info deflection-max-dist))))
      (if (fleeing-nav-enemy-clip-travel self (-> self desired-travel)) (set-time! (-> self last-reflection-time)))
      (set! (-> self debug-vector quad) (-> self desired-travel quad))
      (fleeing-nav-enemy-adjust-travel self (-> self desired-travel))
      (fleeing-nav-enemy-chase-post-func)
      (camera-line-rel (-> self collide-info trans) (-> self desired-travel) (new 'static 'vector4w :x #x80 :w #x80))
      (camera-line-rel (-> self collide-info trans) (-> self nav travel) (new 'static 'vector4w :z #x80 :w #x80))
      (camera-line (-> self collide-info trans) (-> self nav target-pos) (new 'static 'vector4w :z #x80 :w #x80))))

(defstate lightning-mole-gone (lightning-mole)
  :code
    (behavior ()
      (cleanup-for-death self)
      (ja-channel-set! 0)
      (ja-post)
      (while (-> self child)
        (suspend))
      (deactivate self)))

(defstate lightning-mole-hiding (lightning-mole)
  :enter
    (behavior ()
      (ja-channel-set! 0)
      (clear-collide-with-as (-> self collide-info)))
  :trans
    (behavior ()
      (when (task-closed? (-> self entity extra perm task) (task-status need-introduction))
        (ja-channel-set! 1)
        (ja :group! lightning-mole-idle-ja)
        (restore-collide-with-as (-> self collide-info))
        (go-virtual nav-enemy-idle)))
  :code
    (behavior ()
      (loop
        (suspend))))

(defstate lightning-mole-dive (lightning-mole)
  :trans
    (behavior ()
      (when (< (vector-vector-xz-distance *lightning-mole-hole* (-> self collide-info trans)) 61440.0)
        (let ((a1-1 (new 'stack-no-clear 'event-message-block)))
          (set! (-> a1-1 from) self)
          (set! (-> a1-1 num-params) 0)
          (set! (-> a1-1 message) 'hide)
          (let ((t9-1 send-event-function)
                (v1-2 (-> self alt-actor)))
            (t9-1 (if v1-2 (-> v1-2 extra process)) a1-1)))))
  :code
    (behavior ()
      (let ((f30-0 (nav-enemy-rnd-float-range 0.9 1.1))
            (gp-0 (new 'stack-no-clear 'vector)))
        (vector+! gp-0 *lightning-mole-hole* (new 'static 'vector :x 81920.0 :y 40960.0))
        (hide-hud-quick)
        (if *target* (logior! (-> *target* mask) (process-mask sleep)))
        (ambient-hint-spawn "gamcam20" (the-as vector #f) *entity-pool* 'camera)
        (ja-channel-push! 1 (seconds 0.2))
        (ja-no-eval :group! lightning-mole-dive-ja :num! (seek! max f30-0) :frame-num 0.0)
        (until (ja-done? 0)
          (let ((s5-0 (new 'stack-no-clear 'vector)))
            (set! (-> *camera-other-fov* data) 11650.845)
            (vector-! s5-0 *lightning-mole-hole* gp-0)
            (vector-normalize! s5-0 1.0)
            (forward-down->inv-matrix *camera-other-matrix* s5-0 (-> *camera* local-down)))
          (set! (-> *camera-other-trans* quad) (-> gp-0 quad))
          (set! (-> *camera-other-root* quad) (-> *lightning-mole-hole* quad))
          (set! *camera-look-through-other* 2)
          (suspend)
          (ja :num! (seek! max f30-0))))
      (lightning-mole-task-complete?)
      (if *target* (logclear! (-> *target* mask) (process-mask sleep)))
      (go lightning-mole-gone))
  :post lightning-mole-hole-post)

(defstate lightning-mole-head-for-hole (lightning-mole)
  :enter
    (behavior ()
      (clear-collide-with-as (-> self collide-info)))
  :trans
    (behavior ()
      (when (< (vector-vector-xz-distance *lightning-mole-hole* (-> self collide-info trans)) 61440.0)
        (let ((a1-1 (new 'stack-no-clear 'event-message-block)))
          (set! (-> a1-1 from) self)
          (set! (-> a1-1 num-params) 0)
          (set! (-> a1-1 message) 'hide)
          (let ((t9-1 send-event-function)
                (v1-3 (-> self alt-actor)))
            (t9-1 (if v1-3 (-> v1-3 extra process)) a1-1))))
      (if (< (vector-vector-distance (-> self collide-info trans) *lightning-mole-hole*) 40960.0) (go lightning-mole-dive)))
  :code
    (-> (method-of-type fleeing-nav-enemy nav-enemy-chase)
        code)
  :post lightning-mole-hole-post)

(defstate lightning-mole-yelp (lightning-mole)
  :enter
    (behavior ()
      (clear-collide-with-as (-> self collide-info))
      ((-> (method-of-type fleeing-nav-enemy nav-enemy-chase) enter)))
  :exit
    (behavior ()
      (restore-collide-with-as (-> self collide-info)))
  :trans
    (-> (method-of-type fleeing-nav-enemy nav-enemy-chase)
        trans)
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.2))
      (let ((f30-0 (nav-enemy-rnd-float-range 0.9 1.1)))
        (ja-no-eval :group! lightning-mole-yelp-ja :num! (seek! max f30-0) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek! max f30-0))))
      (go-virtual nav-enemy-chase))
  :post nav-enemy-simple-post)

(defstate nav-enemy-stop-chase (lightning-mole)
  :virtual #t
  :code lightning-mole-run-code
  :post fleeing-nav-enemy-chase-post)

(defstate nav-enemy-chase (lightning-mole)
  :virtual #t
  :enter
    (behavior ()
      (set! (-> self speed-adjust) 1.0)
      (set! (-> self run-blend-interp) 0.0)
      (vector-! (-> self saved-travel) (-> self collide-info trans) (target-pos 0))
      ((-> (method-of-type fleeing-nav-enemy nav-enemy-chase) enter)))
  :trans
    (behavior ()
      (let ((s3-0 (new 'stack-no-clear 'vector))
            (s4-0 (new 'stack-no-clear 'vector))
            (gp-0 (new 'stack-no-clear 'vector)))
        0.0
        0.0
        (let ((f30-0 (vector-vector-distance (-> self collide-info trans) (target-pos 0))))
          0.0
          0.0
          (let ((s5-1 (new 'stack-no-clear 'vector)))
            (vector-! s3-0 *lightning-mole-hole* (-> self collide-info trans))
            (vector-! s4-0 (-> self collide-info trans) (target-pos 0))
            (vector-! gp-0 *lightning-mole-hole* (target-pos 0))
            (let ((f26-0 (vector-normalize-ret-len! s3-0 1.0))
                  (f28-0 (vector-normalize-ret-len! s4-0 1.0)))
              (vector-normalize! gp-0 1.0)
              (set! (-> s5-1 quad) (-> *camera* tgt-face-mat vector 2 quad))
              (set! (-> s5-1 y) 0.0)
              (vector-normalize! s5-1 1.0)
              (let ((f24-0 (vector-dot s5-1 s4-0)))
                (when (< f26-0 61440.0)
                  (let ((a1-7 (new 'stack-no-clear 'event-message-block)))
                    (set! (-> a1-7 from) self)
                    (set! (-> a1-7 num-params) 0)
                    (set! (-> a1-7 message) 'hide)
                    (let ((t9-8 send-event-function)
                          (v1-10 (-> self alt-actor)))
                      (t9-8 (if v1-10 (-> v1-10 extra process)) a1-7))))
                (if (and (< 40960.0 f26-0)
                         (< f26-0 81920.0)
                         (< f30-0 204800.0)
                         (< (+ 20480.0 f26-0) f28-0)
                         (< (cos 7281.778) (vector-dot s5-1 gp-0))
                         (< (cos 7281.778) f24-0))
                  (go lightning-mole-head-for-hole)))))))
      ((-> (method-of-type fleeing-nav-enemy nav-enemy-chase) trans)))
  :code lightning-mole-run-code
  :post fleeing-nav-enemy-chase-post)

(defmethod attack-handler ((this lightning-mole) (arg0 process) (arg1 event-message-block))
  (send-event arg0 'get-attack-count 1)
  (when (!= (-> this state) lightning-mole-yelp)
    (send-event arg0 'jump 32768.0 32768.0)
    (go lightning-mole-yelp))
  #t)

(defmethod touch-handler ((this lightning-mole) (arg0 process) (arg1 event-message-block))
  (when (!= (-> this state) lightning-mole-yelp)
    (send-event arg0 'jump 32768.0 32768.0)
    (go lightning-mole-yelp))
  #t)

(define *lightning-mole-nav-enemy-info*
  (new 'static
       'nav-enemy-info
       :idle-anim 5
       :walk-anim 7
       :turn-anim -1
       :notice-anim 6
       :run-anim 7
       :jump-anim -1
       :jump-land-anim -1
       :victory-anim 12
       :taunt-anim -1
       :die-anim -1
       :neck-joint 5
       :player-look-at-joint 5
       :run-travel-speed (meters 30)
       :run-rotate-speed (degrees 3000)
       :run-acceleration (meters 1)
       :run-turn-time (seconds 0.1)
       :walk-travel-speed (meters 30)
       :walk-rotate-speed (degrees 3000)
       :walk-acceleration (meters 1)
       :walk-turn-time (seconds 0.1)
       :attack-shove-back (meters 3)
       :attack-shove-up (meters 2)
       :shadow-size (meters 2)
       :notice-nav-radius (meters 2)
       :nav-nearest-y-threshold (meters 10)
       :notice-distance (meters 35)
       :stop-chase-distance (meters 45)
       :frustration-distance (meters 8)
       :frustration-time (seconds 4)
       :die-anim-hold-frame 10000000000.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 #t
       :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 init-from-entity! ((this lightning-mole) (arg0 entity-actor))
  (let ((s4-0 (new 'process 'collide-shape-moving this (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 attackable attackable-unused))
      (set! (-> s3-0 prim-core offense) (collide-offense indestructible))
      (set-vector! (-> s3-0 local-sphere) 0.0 10240.0 0.0 10240.0)
      (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! (-> this collide-info) s4-0))
  (process-drawable-from-entity! this arg0)
  (initialize-skeleton this *lightning-mole-sg* '())
  (init-defaults! this *lightning-mole-nav-enemy-info*)
  (logclear! (-> this nav flags) (nav-control-flags navcf5 navcf6 navcf7))
  (set! (-> this draw origin-joint-index) (the-as uint 3))
  (set! (-> this reaction-time) (seconds 0.05))
  (set! (-> this last-reflection-time) 0)
  (set! (-> this collide-info pause-adjust-distance) 122880.0)
  (set! (-> this link) (new 'process 'actor-link-info this))
  (set! (-> this alt-actor) (entity-actor-lookup arg0 'alt-actor 0))
  (set! (-> this flee-info min-reflect-angle) 10922.667)
  (set! (-> this flee-info max-reflect-angle) 14563.556)
  (set! (-> this flee-info max-boundary-deflection) 18204.445)
  (set! (-> this flee-info deflection-min-dist) 20480.0)
  (set! (-> this flee-info deflection-max-dist) 49152.0)
  (set! (-> this flee-info reflection-time) 225)
  (set! (-> this flee-info travel-rotate-speed) 1820.4445)
  (set! (-> this flee-info blend_interp_angle) 2184.5334)
  (set! (-> this flee-info min-speed-adjust) 0.8)
  (set! (-> this flee-info max-speed-adjust) 1.2)
  (set! (-> this flee-info speed-adjust-center) 40960.0)
  (set! (-> this flee-info speed-adjust-range) 20480.0)
  (set! (-> this flee-info abort-notice-distance) 49152.0)
  (set! (-> this flee-info min-notice-dist) 61440.0)
  (set! (-> this flee-info max-notice-dist) 143360.0)
  (set! (-> this flee-info min-stop-chase-dist) 40960.0)
  (set! (-> this flee-info max-stop-chase-dist) 184320.0)
  (set! (-> this flee-info max-flee-rotation) 364.0889)
  (cond
    ((and (-> this entity) (logtest? (-> this entity extra perm status) (entity-perm-status complete)))
     (go lightning-mole-gone))
    ((task-closed? (-> this entity extra perm task) (task-status need-introduction))
     (go (method-of-object this nav-enemy-idle)))
    (else (go lightning-mole-hiding)))
  (none))

(defpartgroup group-peeper
  :id 456
  :duration (seconds 0.017)
  :bounds (static-bspherem 0 0 0 15)
  :parts
  ((sp-item 1768)
   (sp-item 1769 :period (seconds 0.4) :length (seconds 0.1))
   (sp-item 1770 :period (seconds 0.4) :length (seconds 0.2))))

(defpart 1768
  :init-specs
  ((:texture (bigpuff effects))
   (:num 0.25)
   (:x (meters -2) (meters 4))
   (:y (meters -2))
   (:z (meters -2) (meters 4))
   (:scale-x (meters 4) (meters 2))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 128.0 64.0)
   (:g 96.0 32.0)
   (:b 64.0 16.0)
   (:a 32.0 32.0)
   (:vel-x (meters -0.006666667) (meters 0.013333334))
   (:vel-y (meters 0.04) (meters 0.026666667))
   (:vel-z (meters -0.006666667) (meters 0.013333334))
   (:rotvel-z (degrees -1.2) (degrees 2.4))
   (:fade-a -0.21333334)
   (:accel-y (meters -0.00066666666))
   (:friction 0.97)
   (:timer (seconds 1.5))
   (:flags (bit2 bit12))))

(defpart 1769
  :init-specs
  ((:texture (bigpuff effects))
   (:num 0.5)
   (:x (meters -2) (meters 4))
   (:y (meters -2))
   (:z (meters -2) (meters 4))
   (:scale-x (meters 4) (meters 2))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 128.0 64.0)
   (:g 96.0 32.0)
   (:b 64.0 16.0)
   (:a 32.0 32.0)
   (:vel-x (meters -0.006666667) (meters 0.013333334))
   (:vel-y (meters 0.04) (meters 0.026666667))
   (:vel-z (meters -0.006666667) (meters 0.013333334))
   (:rotvel-z (degrees -1.2) (degrees 2.4))
   (:fade-a -0.21333334)
   (:friction 0.98)
   (:timer (seconds 1.5))
   (:flags (bit2 bit12))))

(defpart 1770
  :init-specs
  ((:texture (rockbit effects))
   (:num 5.0)
   (:x (meters -1) (meters 2))
   (:y (meters 0))
   (:z (meters -1) (meters 2))
   (:scale-x (meters 0.25) (meters 0.1))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 128.0 64.0)
   (:g 96.0 32.0)
   (:b 64.0 16.0)
   (:a 128.0)
   (:vel-y (meters 0.06666667) (meters 0.053333335))
   (:rotvel-z (degrees -1.2) (degrees 2.4))
   (:accel-y (meters -0.0026666666))
   (:timer (seconds 1.5))
   (:flags (bit2 bit12))
   (:userdata 106496.0)
   (:func 'check-drop-level-rolling-dirt)
   (:conerot-x (degrees 0) (degrees 20))
   (:conerot-y (degrees 180) (degrees 180))
   (:conerot-radius (meters 0) (meters 2))))

(defpart 1771
  :init-specs
  ((:texture (rockbit effects))
   (:num 1.0 1.0)
   (:y (meters 0))
   (:scale-x (meters 0.15) (meters 0.05))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 128.0 64.0)
   (:g 96.0 32.0)
   (:b 64.0 16.0)
   (:a 128.0)
   (:vel-y (meters 0.033333335) (meters 0.016666668))
   (:rotvel-z (degrees -1.2) (degrees 2.4))
   (:accel-y (meters -0.0026666666))
   (:timer (seconds 1))
   (:flags (bit2 bit12))
   (:userdata 106496.0)
   (:func 'check-drop-level-rolling-dirt-finish)
   (:conerot-x (degrees 0) (degrees 30))
   (:conerot-y (degrees 0) (degrees 360))
   (:conerot-radius (meters 0))))

(defpart 1772
  :init-specs
  ((:texture (rockbit effects))
   (:num 1.0)
   (:scale-x (meters 0.15) (meters 0.05))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 128.0 64.0)
   (:g 96.0 32.0)
   (:b 64.0 16.0)
   (:a 64.0 64.0)
   (:vel-y (meters 0) (meters 0.013333334))
   (:rotvel-z (degrees -1.2) (degrees 2.4))
   (:fade-a -0.14222223)
   (:friction 0.9)
   (:timer (seconds 3))
   (:flags (bit2 bit12))
   (:conerot-x (degrees 90))
   (:conerot-y (degrees 0) (degrees 360))))

(defun check-drop-level-rolling-dirt ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 vector))
  (when (< (-> arg2 y) (-> arg1 user-float))
    (let ((gp-0 (new 'stack-no-clear 'vector)))
      (sp-kill-particle arg0 arg1)
      (set-vector! gp-0 (-> arg2 x) (-> arg1 user-float) (-> arg2 z) 1.0)
      (launch-particles (-> *part-id-table* 1771) gp-0)))
  (none))

(defun check-drop-level-rolling-dirt-finish ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 vector))
  (when (< (-> arg2 y) (-> arg1 user-float))
    (let ((gp-0 (new 'stack-no-clear 'vector)))
      (sp-kill-particle arg0 arg1)
      (if (< (rand-float-gen) 0.05) (sound-play "land-grass"))
      (set-vector! gp-0 (-> arg2 x) (-> arg1 user-float) (-> arg2 z) 1.0)
      (launch-particles (-> *part-id-table* 1772) gp-0)))
  (none))

(deftype peeper (process-drawable) ()
  (:states
   peeper-down
   peeper-hide
   peeper-up
   peeper-wait))


(defstate peeper-wait (peeper)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('hide) (let ((v0-0 (current-time))) (set! (-> self state-time) v0-0) v0-0))))
  :enter
    (behavior ()
      (if (nonzero? (-> self sound)) (stop! (-> self sound)))
      (set-time! (-> self state-time)))
  :trans
    (behavior ()
      (if (and (time-elapsed? (-> self state-time) (seconds 1))
               (not (and *target* (>= 81920.0 (vector-vector-xz-distance (-> self root trans) (-> *target* control trans))))))
        (go peeper-up)))
  :code
    (behavior ()
      (logior! (-> self draw status) (draw-status hidden))
      (loop
        (suspend)))
  :post ja-post)

(defstate peeper-hide (peeper)
  :code
    (behavior ()
      (if (nonzero? (-> self sound)) (stop! (-> self sound)))
      (ja-no-eval :num! (seek! max 2.0))
      (while (not (ja-done? 0))
        (suspend)
        (ja-eval))
      (logior! (-> self draw status) (draw-status hidden))
      (go peeper-wait))
  :post ja-post)

(defstate peeper-down (peeper)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('hide) (go peeper-wait))))
  :trans
    (behavior ()
      (if (and *target* (>= 61440.0 (vector-vector-xz-distance (-> self root trans) (-> *target* control trans))))
        (go peeper-wait)))
  :code
    (behavior ()
      (logior! (-> self draw status) (draw-status hidden))
      (set-time! (-> self state-time))
      (until (time-elapsed? (-> self state-time) (seconds 1))
        (suspend))
      (let* ((f30-0 2.0)
             (v1-10 (/ (the-as int (rand-uint31-gen *random-generator*)) 256))
             (v1-11 (the-as number (logior #x3f800000 v1-10))))
        (countdown (gp-0 (+ (the int (* f30-0 (+ -1.0 (the-as float v1-11)))) 1))
          (set-time! (-> self state-time))
          (until (time-elapsed? (-> self state-time) (seconds 5))
            (if (nonzero? (-> self sound)) (update! (-> self sound)))
            (spawn (-> self part) (-> self root trans))
            (suspend))
          (set-time! (-> self state-time))
          (if (nonzero? (-> self sound)) (stop! (-> self sound)))
          (until (time-elapsed? (-> self state-time) (seconds 3))
            (suspend))))
      (go peeper-up))
  :post ja-post)

(defstate peeper-up (peeper)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('hide) (go peeper-hide))))
  :enter
    (behavior ()
      (if (nonzero? (-> self sound)) (stop! (-> self sound)))
      (logclear! (-> self draw status) (draw-status hidden)))
  :trans
    (behavior ()
      (if (and *target* (>= 61440.0 (vector-vector-xz-distance (-> self root trans) (-> *target* control trans))))
        (go peeper-hide)))
  :code
    (behavior ()
      (loop
        (ja-no-eval :group! lightning-mole-peep-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!)))
        (go peeper-down)))
  :post ja-post)

(defmethod init-from-entity! ((this peeper) (arg0 entity-actor))
  (set! (-> this root) (new 'process 'trsqv))
  (process-drawable-from-entity! this arg0)
  (initialize-skeleton this *lightning-mole-sg* '())
  (set! (-> this part) (create-launch-control group-peeper this))
  (set! (-> this sound) (new 'process 'ambient-sound arg0 (-> this root trans)))
  (go peeper-up)
  (none))
