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

;; DECOMP BEGINS

(deftype lurkerworm (process-drawable)
  ((root         collide-shape-moving :override)
   (twister      twister)
   (head-tilt    float)
   (strike-count int32)
   (angle        float)
   (vulnerable   symbol)
   (part2        sparticle-launch-control))
  (:methods
   (lurkerworm-method-20 (_type_) none)
   (particle-effect (_type_) none))
  (:states
   lurkerworm-die
   lurkerworm-idle
   lurkerworm-rest
   lurkerworm-rise
   lurkerworm-sink
   lurkerworm-spot
   lurkerworm-strike))


(defmethod relocate ((this lurkerworm) (offset int))
  (if (nonzero? (-> this part2)) (&+! (-> this part2) offset))
  (if (nonzero? (-> this twister)) (&+! (-> this twister) offset))
  (the-as lurkerworm ((method-of-type process-drawable relocate) this offset)))

(defmethod deactivate ((this lurkerworm))
  (if (nonzero? (-> this part2)) (kill-and-free-particles (-> this part2)))
  ((method-of-type process-drawable deactivate) this)
  (none))

(defskelgroup *lurkerworm-sg*
  lurkerworm
  lurkerworm-lod0-jg
  lurkerworm-idle-ja
  ((lurkerworm-lod0-mg (meters 999999)))
  :bounds (static-spherem 0 2 0 6.5)
  :longest-edge (meters 1.5))

(defpartgroup group-beach-sandworm
  :id 157
  :flags (use-local-clock)
  :bounds (static-bspherem 0 0 0 6)
  :parts
  ((sp-item 656 :fade-after (meters 90) :period (seconds 3) :length (seconds 1))
   (sp-item 657 :fade-after (meters 100) :period (seconds 3) :length (seconds 1.3))
   (sp-item 658 :fade-after (meters 150) :period (seconds 3) :length (seconds 1.4) :offset 120)
   (sp-item 659 :fade-after (meters 60) :period (seconds 3) :length (seconds 1.4) :offset 120)))

(defpartgroup group-beach-sandworm-norocks
  :id 158
  :flags (use-local-clock)
  :bounds (static-bspherem 0 0 0 6)
  :parts
  ((sp-item 656 :fade-after (meters 90) :period (seconds 3) :length (seconds 1))
   (sp-item 658 :fade-after (meters 150) :period (seconds 3) :length (seconds 1.4) :offset 120)
   (sp-item 659 :fade-after (meters 60) :period (seconds 3) :length (seconds 1.4) :offset 120)))

(defpart 656
  :init-specs
  ((:texture (falls-particle-02 effects))
   (:num 4.0)
   (:x (meters 3) (meters 5))
   (:y (meters 1))
   (:scale-x (meters 1) (meters 2))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 130.0 20.0)
   (:g 90.0 20.0)
   (:b 50.0 8.0)
   (:a 0.0)
   (:vel-x (meters -0.02))
   (:vel-y (meters -0.0033333334))
   (:rotvel-z (degrees -0.15) (degrees 0.3))
   (:fade-a 0.21333334)
   (:timer (seconds 3))
   (:flags (bit2 bit12))
   (:next-time (seconds 0.3) (seconds 0.197))
   (:next-launcher 660)
   (:rotate-y (degrees 0) (degrees 360))))

(defpart 660
  :init-specs ((:fade-a -0.21333334)))

(defpart 658
  :init-specs
  ((:texture (falls-particle-02 effects))
   (:num 0.4)
   (:x (meters 0) (meters 1))
   (:scale-x (meters 2) (meters 1))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 90.0 60.0)
   (:g 90.0 10.0)
   (:b 50.0 8.0)
   (:a 0.0)
   (:vel-x (meters 0.0033333334) (meters 0.0033333334))
   (:vel-y (meters 0.026666667))
   (:rotvel-z (degrees -0.3) 1 (degrees 0.6))
   (:fade-a 0.32)
   (:accel-y (meters -0.001))
   (:timer (seconds 1))
   (:flags (bit2 bit12))
   (:rotate-y (degrees 0) (degrees 360))))

(defpart 659
  :init-specs
  ((:texture (falls-particle-02 effects))
   (:num 0.6)
   (:x (meters 0) (meters 1))
   (:scale-x (meters 1) (meters 1))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 45.0 30.0)
   (:g 45.0 5.0)
   (:b 25.0 4.0)
   (:a 0.0)
   (:vel-x (meters 0.0033333334) (meters 0.0033333334))
   (:vel-y (meters 0.026666667))
   (:rotvel-z (degrees -0.3) 1 (degrees 0.6))
   (:fade-a 0.42666668)
   (:accel-y (meters -0.001))
   (:timer (seconds 1))
   (:flags (bit2 bit12))
   (:rotate-y (degrees 0) (degrees 360))))

(defpart 657
  :init-specs
  ((:texture (rockbit effects))
   (:num 0.5)
   (:x (meters 0) (meters 1))
   (:scale-x (meters 0.05) (meters 0.4))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 75.0 45.0)
   (:g 75.0 10.0)
   (:b 40.0 6.0)
   (:a 96.0)
   (:vel-x (meters 0.0033333334) (meters 0.0033333334))
   (:vel-y (meters 0.013333334) (meters 0.026666667))
   (:rotvel-z (degrees -0.3) 1 (degrees 0.6))
   (:accel-y (meters -0.001))
   (:timer (seconds 1.5))
   (:flags (bit2 bit12))
   (:rotate-y (degrees 0) (degrees 360))))

(defpart 661
  :init-specs
  ((:texture (falls-particle-02 effects))
   (:num 0.1)
   (:x (meters -0.5) (meters 1))
   (:z (meters -0.5) (meters 1))
   (:scale-x (meters 2) (meters 1))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 90.0 60.0)
   (:g 90.0 10.0)
   (:b 50.0 8.0)
   (:a 0.0)
   (:vel-x (meters 0.0033333334) (meters 0.00083333335))
   (:rotvel-z (degrees -0.3) 1 (degrees 0.6))
   (:fade-a 0.21333334)
   (:accel-y (meters -0.00013333333))
   (:timer (seconds 2))
   (:flags (bit2 bit12))
   (:next-time (seconds 0.5))
   (:next-launcher 662)))

(defpart 662
  :init-specs ((:fade-a -0.10666667)))

(defmethod lurkerworm-method-20 ((this lurkerworm))
  (let ((s5-0 (new 'stack-no-clear 'vector)))
    (vector-! s5-0 (target-pos 0) (-> this root trans))
    (set-target! (-> this twister) (atan (-> s5-0 x) (-> s5-0 z)))
    (twister-method-11 (-> this twister))
    (let* ((f0-5 (sqrtf (+ (* (-> s5-0 x) (-> s5-0 x)) (* (-> s5-0 z) (-> s5-0 z)))))
           (f0-6 (atan (-> s5-0 y) f0-5)))
      (seek! (-> this head-tilt) f0-6 (* 5461.3335 (seconds-per-frame)))))
  (set! (-> this head-tilt) (fmin 8192.0 (fmax -5461.3335 (-> this head-tilt))))
  0
  (none))

(defbehavior lurkerworm-prebind-function lurkerworm ((arg0 pointer) (arg1 int) (arg2 lurkerworm))
  (let ((v1-0 arg2)
        (s5-0 (new 'stack-no-clear 'quaternion))
        (gp-0 (&+ arg0 432)))
    (quaternion-axis-angle! s5-0 -1.0 0.0 0.0 (-> v1-0 head-tilt))
    (quaternion*! (the-as quaternion gp-0) (the-as quaternion gp-0) s5-0))
  0
  (none))

(defun lurkerworm-joint-callback ((arg0 lurkerworm))
  (let ((a1-0 arg0)) (twister-method-12 (-> a1-0 twister) a1-0))
  0
  (none))

(defmethod particle-effect ((this lurkerworm))
  (let ((a2-0 (vector<-cspace! (new 'stack-no-clear 'vector) (-> this node-list data 5))))
    (launch-particles (-> *part-id-table* 661) a2-0))
  (let ((a2-1 (vector<-cspace! (new 'stack-no-clear 'vector) (-> this node-list data 6))))
    (launch-particles (-> *part-id-table* 661) a2-1))
  (let ((a2-2 (vector<-cspace! (new 'stack-no-clear 'vector) (-> this node-list data 7))))
    (launch-particles (-> *part-id-table* 661) a2-2))
  (let ((a2-3 (vector<-cspace! (new 'stack-no-clear 'vector) (-> this node-list data 8))))
    (launch-particles (-> *part-id-table* 661) a2-3))
  0
  (none))

(defbehavior lurkerworm-default-event-handler lurkerworm ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (case arg2
    (('attack) (-> arg3 param 1) (go lurkerworm-die))
    (('touch)
     (if ((method-of-type touching-shapes-entry prims-touching?)
          (the-as touching-shapes-entry (-> arg3 param 0))
          (-> self root)
          (the-as uint 1))
       (send-event arg0 'attack (-> arg3 param 0) (new 'static 'attack-info))))))

(defbehavior lurkerworm-default-post-behavior lurkerworm ()
  (lurkerworm-method-20 self)
  (transform-post)
  0
  (none))

lurkerworm-default-event-handler

lurkerworm-default-post-behavior

(defstate lurkerworm-idle (lurkerworm)
  :event lurkerworm-default-event-handler
  :enter
    (behavior ()
      (ja-channel-set! 0)
      (set-time! (-> self state-time)))
  :code
    (behavior ()
      (loop
        (if (and (time-elapsed? (-> self state-time) (seconds 1))
                 *target*
                 (>= 81920.0 (vector-vector-distance (-> self root trans) (-> *target* control trans))))
          (go lurkerworm-spot))
        (suspend)))
  :post lurkerworm-default-post-behavior)

(defstate lurkerworm-spot (lurkerworm)
  :event lurkerworm-default-event-handler
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (sound-play "worm-rise1"))
  :code
    (behavior ()
      (set! (-> self part local-clock) 0)
      (loop
        (spawn (-> self part) (-> self root trans))
        (particle-effect self)
        (when (time-elapsed? (-> self state-time) (seconds 1))
          (if (and *target* (>= 81920.0 (vector-vector-distance (-> self root trans) (-> *target* control trans))))
            (go lurkerworm-rise)
            (go lurkerworm-idle)))
        (suspend)))
  :post lurkerworm-default-post-behavior)

(defstate lurkerworm-rise (lurkerworm)
  :event lurkerworm-default-event-handler
  :enter
    (behavior ()
      (set-time! (-> self state-time)))
  :code
    (behavior ()
      (ja-channel-set! 1)
      (ja-no-eval :group! lurkerworm-rise-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (spawn (-> self part) (-> self root trans))
        (particle-effect self)
        (suspend)
        (ja :num! (seek!)))
      (set! (-> self strike-count) 3)
      (go lurkerworm-rest))
  :post lurkerworm-default-post-behavior)

(defstate lurkerworm-rest (lurkerworm)
  :event lurkerworm-default-event-handler
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self vulnerable) #t))
  :exit
    (behavior ()
      (set! (-> self vulnerable) #f))
  :code
    (behavior ()
      (let* ((f30-0 10.0)
             (f28-0 100.0)
             (v1-1 (/ (the-as int (rand-uint31-gen *random-generator*)) 256))
             (v1-2 (the-as number (logior #x3f800000 v1-1)))
             (s5-0 (the int (+ f30-0 (* f28-0 (+ -1.0 (the-as float v1-2))))))
             (gp-1 (nonzero? (-> self strike-count))))
        (if gp-1 (+! (-> self strike-count) -1))
        (ja-no-eval :group! lurkerworm-idle-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (ja-blend-eval)
          (particle-effect self)
          (when gp-1
            (let* ((f0-13 (- 1.0
                             (* 0.00009765625
                                (+ -16384.0 (if *target* (vector-vector-distance (-> self root trans) (-> *target* control trans)) 4096000.0)))))
                   (f30-2 (/ f0-13 5)))
              (if (< (rand-float-gen) f30-2) (go lurkerworm-strike))))
          (+! s5-0 -1)
          (when (zero? s5-0)
            (if gp-1 (go lurkerworm-strike) (go lurkerworm-sink)))
          (suspend)
          (ja :num! (seek!)))
        (if gp-1 (go lurkerworm-strike) (go lurkerworm-sink))))
  :post lurkerworm-default-post-behavior)

(defstate lurkerworm-strike (lurkerworm)
  :event lurkerworm-default-event-handler
  :code
    (behavior ()
      (ja-no-eval :num! (loop!))
      (ja-channel-push! 1 (seconds 0.135))
      (ja-no-eval :group! lurkerworm-chomp-ja :num! (seek! (ja-aframe 13.0 0)) :frame-num 0.0)
      (until (ja-done? 0)
        (ja-blend-eval)
        (particle-effect self)
        (suspend)
        (ja :num! (seek! (ja-aframe 13.0 0))))
      (ja-no-eval :num! (seek!))
      (ja-channel-push! 1 (seconds 0.135))
      (go lurkerworm-rest))
  :post lurkerworm-default-post-behavior)

(defstate lurkerworm-sink (lurkerworm)
  :event lurkerworm-default-event-handler
  :enter
    (behavior ()
      (set-time! (-> self state-time)))
  :code
    (behavior ()
      (ja-no-eval :group! lurkerworm-sink-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (spawn (-> self part2) (-> self root trans))
        (particle-effect self)
        (suspend)
        (ja :num! (seek!)))
      (go lurkerworm-idle))
  :post lurkerworm-default-post-behavior)

(defstate lurkerworm-die (lurkerworm)
  :event process-drawable-death-event-handler
  :code
    (behavior ()
      (logclear! (-> self mask) (process-mask actor-pause))
      (let ((v1-3 (-> self root root-prim)))
        (set! (-> v1-3 collide-with) (collide-kind))
        (set! (-> v1-3 prim-core collide-as) (collide-kind)))
      0
      (ja-no-eval :group! lurkerworm-die-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (cleanup-for-death self))
  :post lurkerworm-default-post-behavior)

(defmethod init-from-entity! ((this lurkerworm) (arg0 entity-actor))
  (logior! (-> this mask) (process-mask enemy))
  (let ((s4-0 (new 'process 'collide-shape-moving this (collide-list-enum usually-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-group s4-0 (the-as uint 6) 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-vector! (-> s3-0 local-sphere) 0.0 10240.0 0.0 24576.0)
      (set-root-prim! s4-0 s3-0)
      (let ((s2-0 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 0))))
        (set! (-> s2-0 prim-core collide-as) (collide-kind enemy))
        (set! (-> s2-0 collide-with) (collide-kind target))
        (set! (-> s2-0 prim-core action) (collide-action solid))
        (set! (-> s2-0 prim-core offense) (collide-offense indestructible))
        (set! (-> s2-0 transform-index) 3)
        (set-vector! (-> s2-0 local-sphere) 0.0 0.0 0.0 4096.0)
        (append-prim s3-0 s2-0))
      (let ((s2-1 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 0))))
        (set! (-> s2-1 prim-core collide-as) (collide-kind enemy))
        (set! (-> s2-1 collide-with) (collide-kind target))
        (set! (-> s2-1 prim-core action) (collide-action solid))
        (set! (-> s2-1 prim-core offense) (collide-offense indestructible))
        (set! (-> s2-1 transform-index) 5)
        (set-vector! (-> s2-1 local-sphere) 0.0 0.0 0.0 4096.0)
        (append-prim s3-0 s2-1))
      (let ((s2-2 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 0))))
        (set! (-> s2-2 prim-core collide-as) (collide-kind enemy))
        (set! (-> s2-2 collide-with) (collide-kind target))
        (set! (-> s2-2 prim-core action) (collide-action solid))
        (set! (-> s2-2 prim-core offense) (collide-offense indestructible))
        (set! (-> s2-2 transform-index) 6)
        (set-vector! (-> s2-2 local-sphere) 0.0 0.0 0.0 4096.0)
        (append-prim s3-0 s2-2))
      (let ((s2-3 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 0))))
        (set! (-> s2-3 prim-core collide-as) (collide-kind enemy))
        (set! (-> s2-3 collide-with) (collide-kind target))
        (set! (-> s2-3 prim-core action) (collide-action solid))
        (set! (-> s2-3 prim-core offense) (collide-offense indestructible))
        (set! (-> s2-3 transform-index) 7)
        (set-vector! (-> s2-3 local-sphere) 0.0 0.0 0.0 4096.0)
        (append-prim s3-0 s2-3))
      (let ((s2-4 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 0))))
        (set! (-> s2-4 prim-core collide-as) (collide-kind enemy))
        (set! (-> s2-4 collide-with) (collide-kind target))
        (set! (-> s2-4 prim-core action) (collide-action solid))
        (set! (-> s2-4 prim-core offense) (collide-offense indestructible))
        (set! (-> s2-4 transform-index) 8)
        (set-vector! (-> s2-4 local-sphere) 0.0 0.0 0.0 4096.0)
        (append-prim s3-0 s2-4))
      (let ((s2-5 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 1))))
        (set! (-> s2-5 prim-core collide-as) (collide-kind enemy))
        (set! (-> s2-5 collide-with) (collide-kind target))
        (set! (-> s2-5 prim-core offense) (collide-offense normal-attack))
        (set! (-> s2-5 transform-index) 11)
        (set-vector! (-> s2-5 local-sphere) 0.0 0.0 0.0 6144.0)
        (append-prim s3-0 s2-5)))
    (set! (-> s4-0 nav-radius) (* 0.75 (-> s4-0 root-prim local-sphere w)))
    (backup-collide-with-as s4-0)
    (set! (-> this root) s4-0))
  (process-drawable-from-entity! this arg0)
  (initialize-skeleton this *lurkerworm-sg* '())
  (set! (-> this fact) (new 'process 'fact-info-enemy this (pickup-type eco-pill-random) (-> *FACT-bank* default-pill-inc)))
  (set! (-> this angle) 0.0)
  (set! (-> this vulnerable) #f)
  (set! (-> this part) (create-launch-control group-beach-sandworm this))
  (set! (-> this part2) (create-launch-control group-beach-sandworm-norocks this))
  (set! (-> this twister) (new 'process 'twister 3 15 1092.2667 72.81778 0.25 0.001))
  (twister-method-9 (-> this twister) 3 9 910.2222)
  (set! (-> this head-tilt) 0.0)
  (set! (-> this skel prebind-function) lurkerworm-prebind-function)
  (set! (-> this skel postbind-function) lurkerworm-joint-callback)
  (set! (-> this root nav-radius) 12288.0)
  (nav-mesh-connect this (-> this root) (the-as nav-control #f))
  (go lurkerworm-idle)
  (none))
