;;-*-Lisp-*-
(in-package goal)
(bundles "ROB.DGO")
(require "levels/maincave/baby-spider.gc")
(declare-type spider-egg process-drawable)

;; DECOMP BEGINS

(deftype cave-trap (process-drawable)
  ((root            collide-shape :override)
   (spider-count    int32)
   (alt-actors      (array entity-actor))
   (spawn-delay     time-frame)
   (last-spawn-time time-frame)
   (debug-targ-pos  vector :inline))
  (:methods
   (cave-trap-method-20 (_type_) symbol))
  (:states
   cave-trap-active
   cave-trap-give-up
   cave-trap-idle))

(deftype spider-vent (process-drawable)
  ((last-spawn-time time-frame))
  (:states
   spider-vent-idle))

(defstate spider-vent-idle (spider-vent)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (local-vars (v0-0 object))
      (case message
        (('can-spawn?) (return (time-elapsed? (-> self last-spawn-time) (seconds 1))) v0-0)
        (('notify-spawned) (set! v0-0 (current-time)) (set! (-> self last-spawn-time) (the-as time-frame v0-0)) v0-0)))
  :code
    (behavior ()
      (logior! (-> self mask) (process-mask sleep-code))
      (suspend)
      0))

(defmethod init-from-entity! ((this spider-vent) (arg0 entity-actor))
  (set! (-> this last-spawn-time) 0)
  (set! (-> this root) (new 'process 'trsqv))
  (process-drawable-from-entity! this arg0)
  (go spider-vent-idle)
  (none))

(defbehavior cave-trap-default-event-handler cave-trap ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (case arg2
    (('untrigger)
     (when (= (-> arg0 type) baby-spider)
       (let ((v0-0 (the-as object (max 0 (+ (-> self spider-count) -1)))))
         (set! (-> self spider-count) (the-as int v0-0))
         v0-0)))
    (('notify) (if (and (= (-> arg0 type) spider-egg) (= (-> self next-state name) 'cave-trap-idle)) (go cave-trap-active)))))

(deftype spawn-baby-spider-best (structure)
  ((index int32)
   (dist  float)))

(deftype spawn-baby-spider-work (structure)
  ((best spawn-baby-spider-best 4 :inline)))

(defmethod cave-trap-method-20 ((this cave-trap))
  (set-time! (-> this last-spawn-time))
  (set! (-> this spawn-delay) (rand-vu-int-range (seconds 0.1) (seconds 0.5)))
  (let ((s5-0 (new 'stack-no-clear 'spawn-baby-spider-work)))
    (let ((s4-0 (new 'stack-no-clear 'vector)))
      (dotimes (v1-2 4)
        (set! (-> s5-0 best v1-2 index) -1))
      (set! (-> s4-0 quad) (-> (matrix-local->world #f #f) vector 2 quad))
      (set! (-> s4-0 y) 0.0)
      (vector-normalize! s4-0 102400.0)
      (vector+! s4-0 s4-0 (camera-pos))
      (set! (-> s4-0 y) (-> (target-pos 0) y))
      (dotimes (s3-2 (-> this alt-actors length))
        (let* ((v1-10 (-> this alt-actors s3-2))
               (s1-0 (if v1-10 (-> v1-10 extra process)))
               (s2-2 (if (and (nonzero? s1-0) (type-type? (-> s1-0 type) process-drawable)) s1-0)))
          (when s2-2
            (when (send-event s2-2 'can-spawn?)
              (let ((f30-0 (vector-vector-distance s4-0 (-> (the-as process-drawable s2-2) root trans)))
                    (a0-12 (new 'stack-no-clear 'sphere)))
                (let ((v1-16 (-> s5-0 best 3)))
                  (when (or (< (-> v1-16 index) 0) (< f30-0 (-> v1-16 dist)))
                    (set! (-> v1-16 index) s3-2)
                    (set! (-> v1-16 dist) f30-0)))
                (set! (-> a0-12 quad) (-> (the-as process-drawable s2-2) root trans quad))
                (set! (-> a0-12 w) 4096.0)
                (when (sphere-in-view-frustum? a0-12)
                  (let ((v1-18 (-> s5-0 best 2)))
                    (when (or (< (-> v1-18 index) 0) (< f30-0 (-> v1-18 dist)))
                      (set! (-> v1-18 index) s3-2)
                      (set! (-> v1-18 dist) f30-0)))
                  (when (>= 40960.0 f30-0)
                    (let ((v1-19 (-> s5-0 best 1)))
                      (when (or (< (-> v1-19 index) 0) (< f30-0 (-> v1-19 dist)))
                        (set! (-> v1-19 index) s3-2)
                        (set! (-> v1-19 dist) f30-0)))
                    (when (= (-> s2-2 type) spider-egg)
                      (let ((v1-21 (-> s5-0 best)))
                        (when (or (< (-> v1-21 0 index) 0) (< f30-0 (-> v1-21 0 dist)))
                          (set! (-> v1-21 0 index) s3-2)
                          (set! (-> v1-21 0 dist) f30-0))))))))))))
    (dotimes (s4-1 4)
      (let ((v1-29 (-> s5-0 best s4-1 index)))
        (when (>= v1-29 0)
          (let* ((v1-32 (-> this alt-actors v1-29))
                 (s2-3 (if v1-32 (-> v1-32 extra process)))
                 (s3-3 (if (and (nonzero? s2-3) (type-type? (-> s2-3 type) process-drawable)) s2-3))
                 (s2-4 (new 'stack-no-clear 'vector))
                 (s1-1 (new 'stack-no-clear 'baby-spider-spawn-params)))
            (vector-! s2-4 (target-pos 0) (-> (the-as process-drawable s3-3) root trans))
            (vector-normalize! s2-4 1.0)
            (init! s1-1 (= (-> s3-3 type) spider-egg) #t #t #t 7 1 'untrigger)
            (let ((v1-40 (process-spawn baby-spider this (-> (the-as process-drawable s3-3) root trans) s2-4 s1-1 :to this)))
              (when v1-40
                (set! (-> (the-as baby-spider (-> v1-40 0)) die-if-not-visible?) #t)
                (+! (-> this spider-count) 1)
                (send-event s3-3 'notify-spawned)
                (return #f))))))))
  #f)

(defstate cave-trap-idle (cave-trap)
  :event cave-trap-default-event-handler
  :trans
    (behavior ()
      (when *target*
        (let* ((gp-0 (target-pos 0))
               (f0-0 (vector-vector-xz-distance (-> self root trans) (target-pos 0)))
               (f1-1 (- (-> gp-0 y) (-> self root trans y))))
          (when (and (>= 61440.0 f1-1) (>= f1-1 -16384.0))
            (when (>= 274432.0 f0-0)
              (when (or (>= 188416.0 f0-0) (send-event *target* 'query 'powerup (pickup-type eco-yellow)))
                (level-hint-spawn (text-id cave-trap-nest-hint) "sksp0341" (the-as entity #f) *entity-pool* (game-task none))
                (close-specific-task! (game-task cave-spider-tunnel) (task-status need-hint))
                (go cave-trap-active)))))))
  :code
    (behavior ()
      (logior! (-> self mask) (process-mask sleep-code))
      (suspend)
      0))

(defstate cave-trap-active (cave-trap)
  :event cave-trap-default-event-handler
  :enter
    (behavior ()
      (set! (-> self spawn-delay) (seconds 0.5)))
  :trans
    (behavior ()
      (cond
        (*target*
         (let* ((gp-0 (target-pos 0))
                (f0-0 (vector-vector-xz-distance (-> self root trans) (target-pos 0)))
                (f1-1 (- (-> gp-0 y) (-> self root trans y))))
           (if (or (< 73728.0 f1-1) (< f1-1 -24576.0) (< 368640.0 f0-0)) (go cave-trap-give-up)))
         (if (and (< (-> self spider-count) 8) (time-elapsed? (-> self last-spawn-time) (-> self spawn-delay)))
           (cave-trap-method-20 self)))
        (else (go cave-trap-give-up)))
      0)
  :code
    (behavior ()
      (logior! (-> self mask) (process-mask sleep-code))
      (suspend)
      0))

(defstate cave-trap-give-up (cave-trap)
  :event cave-trap-default-event-handler
  :code
    (behavior ()
      (suspend)
      (go cave-trap-idle)))

(defmethod relocate ((this cave-trap) (arg0 int))
  (if (nonzero? (-> this alt-actors)) (&+! (-> this alt-actors) arg0))
  (call-parent-method this arg0))

(defmethod init-from-entity! ((this cave-trap) (arg0 entity-actor))
  (set! (-> this spider-count) 0)
  (set! (-> this spawn-delay) 0)
  (set! (-> this last-spawn-time) 0)
  (let ((s4-0 (new 'process 'collide-shape this (collide-list-enum hit-by-player))))
    (let ((s3-0 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 0))))
      (set! (-> s3-0 prim-core offense) (collide-offense no-offense))
      (set-vector! (-> s3-0 local-sphere) 0.0 0.0 0.0 4096.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 root) s4-0))
  (process-drawable-from-entity! this arg0)
  (set! (-> this nav) (new 'process 'nav-control (-> this root) 16 40960.0))
  (logior! (-> this nav flags) (nav-control-flags display-marks navcf3 navcf5 navcf6 navcf7))
  (set! (-> this nav nearest-y-threshold) 409600.0)
  (logclear! (-> this root nav-flags) (nav-flags navf0))
  (set! (-> this path) (new 'process 'path-control this 'path 0.0))
  (logior! (-> this path flags) (path-control-flag display draw-line draw-point draw-text))
  (let ((s4-1 (entity-actor-count arg0 'alt-actor)))
    (set! (-> this alt-actors) (new 'process 'boxed-array entity-actor s4-1))
    (dotimes (s3-1 s4-1)
      (set! (-> this alt-actors s3-1) (entity-actor-lookup arg0 'alt-actor s3-1))))
  (go cave-trap-idle)
  (none))
