;;-*-Lisp-*-
(in-package goal)
(bundles "DAR.DGO")
(require "engine/common-obs/generic-obs.gc")
(require "levels/maincave/cavecrystal-light.gc")

;; DECOMP BEGINS

(deftype cavecrystal (process-drawable)
  ((root                       collide-shape :override)
   (is-master?                 symbol)
   (crystal-id                 int32)
   (glow-u                     float)
   (glow-wf-period             int32)
   (glow-wf-offset             int32)
   (prev-compute-glow-time     time-frame)
   (start-fade-time            time-frame)
   (end-fade-time              time-frame)
   (activated-time             time-frame)
   (last-updated-user-lighting time-frame)
   (player-attack-id           uint64)
   (on-color-mult              vector :inline)
   (on-color-emissive          vector :inline)
   (off-color-mult             vector :inline)
   (off-color-emissive         vector :inline))
  (:methods
   (update-connected-crystals! (_type_) none)
   (compute-glow (_type_) float))
  (:states
   cavecrystal-active
   cavecrystal-idle))

(defskelgroup *cavecrystal-sg*
  cavecrystal
  cavecrystal-lod0-jg
  -1
  ((cavecrystal-lod0-mg (meters 20)) (cavecrystal-lod1-mg (meters 999999)))
  :bounds (static-spherem 0 4.7 0 5.4))

(defmethod update-connected-crystals! ((this cavecrystal))
  (when (-> this is-master?)
    (let ((v1-2 (current-time)))
      (when (!= (-> this last-updated-user-lighting) v1-2)
        (set! (-> this last-updated-user-lighting) v1-2)
        (execute-connections *cavecrystal-light-control*))))
  (none))

(defmethod compute-glow ((this cavecrystal))
  (set! (-> this prev-compute-glow-time) (-> *display* game-frame-counter))
  (let* ((gp-1 (max 1 (+ (- 1 (-> this activated-time)) (-> *display* game-frame-counter))))
         (f0-2 (/ (the float (mod (+ (current-time) (-> this glow-wf-offset)) (-> this glow-wf-period)))
                  (the float (-> this glow-wf-period))))
         (f30-1 (* 0.1 (cos (* 65536.0 f0-2)))))
    (cond
      ((>= (seconds 0.067) gp-1)
       (let ((v1-11 (* 0.05 (the float gp-1)))) (fmax 0.0 (fmin 2.0 (+ (* 2.0 v1-11) (* v1-11 f30-1))))))
      ((>= (seconds 0.6) gp-1)
       (let ((a2-0 (* 0.00625 (the float (+ gp-1 (seconds -0.067)))))) (fmin 2.0 (+ (lerp 2.0 1.0 a2-0) f30-1))))
      ((>= (-> this start-fade-time) gp-1) (+ 1.0 f30-1))
      (else
       (let ((v1-20 (fmin 1.0 (* 0.004761905 (the float (- gp-1 (-> this start-fade-time)))))))
         (fmax 0.0 (- (+ 1.0 (* (- 1.0 v1-20) f30-1)) v1-20)))))))

(defstate cavecrystal-idle (cavecrystal)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('attack) (go cavecrystal-active))))
  :trans
    (behavior ()
      (if (and *target* (>= 40960.0 (vector-vector-distance (-> self root trans) (-> *target* control trans))))
        (level-hint-spawn (text-id darkcave-light-hint) "sksp0333" (the-as entity #f) *entity-pool* (game-task none)))
      (update-connected-crystals! self))
  :code
    (behavior ()
      (logior! (-> self mask) (process-mask sleep-code))
      (suspend)
      0))

(defstate cavecrystal-active (cavecrystal)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('attack)
         (let ((v1-1 (-> block param 2)))
           (cond
             ((!= v1-1 (-> self player-attack-id))
              (set! (-> self player-attack-id) v1-1)
              (set! (-> self activated-time) (-> *display* game-frame-counter))
              #t)
             (else #f))))))
  :enter
    (behavior ()
      (logclear! (-> self mask) (process-mask actor-pause))
      (set! (-> self activated-time) (-> *display* game-frame-counter))
      (set! (-> self prev-compute-glow-time) (-> *display* game-frame-counter)))
  :exit
    (behavior ()
      (stop! (-> self sound))
      (if (not (-> self is-master?)) (logior! (-> self mask) (process-mask actor-pause))))
  :trans
    (behavior ()
      (let ((f30-0 (compute-glow self)))
        (set! (-> self glow-u) f30-0)
        (let ((gp-0 (new 'stack-no-clear 'vector))
              (f28-0 1.993))
          (let ((s5-0 (-> self draw color-mult)))
            (vector-! gp-0 (-> self on-color-mult) (-> self off-color-mult))
            (vector+*! s5-0 (-> self off-color-mult) gp-0 f30-0)
            (set! (-> s5-0 x) (fmax 0.0 (fmin (-> s5-0 x) f28-0)))
            (set! (-> s5-0 y) (fmax 0.0 (fmin (-> s5-0 y) f28-0)))
            (set! (-> s5-0 z) (fmax 0.0 (fmin (-> s5-0 z) f28-0)))
            (set! (-> s5-0 w) 1.0))
          (let ((s5-1 (-> self draw color-emissive)))
            (vector-! gp-0 (-> self on-color-emissive) (-> self off-color-emissive))
            (vector+*! s5-1 (-> self off-color-emissive) gp-0 f30-0)
            (set! (-> s5-1 x) (fmax 0.0 (fmin (-> s5-1 x) f28-0)))
            (set! (-> s5-1 y) (fmax 0.0 (fmin (-> s5-1 y) f28-0)))
            (set! (-> s5-1 z) (fmax 0.0 (fmin (-> s5-1 z) f28-0)))
            (set! (-> s5-1 w) 0.0)))
        (cavecrystal-light-control-method-9 *cavecrystal-light-control* (-> self crystal-id) (-> self glow-u) self)
        (update-connected-crystals! self)
        (when (>= 0.0 f30-0)
          (level-hint-spawn (text-id darkcave-light-end) "sksp0332" (the-as entity #f) *entity-pool* (game-task none))
          (go cavecrystal-idle)))
      (update! (-> self sound)))
  :code
    (behavior ()
      (logior! (-> self mask) (process-mask sleep-code))
      (suspend)
      0))

(defmethod deactivate ((this cavecrystal))
  (if (nonzero? (-> this sound)) (stop! (-> this sound)))
  ((method-of-type process-drawable deactivate) this)
  (none))

(defmethod init-from-entity! ((this cavecrystal) (arg0 entity-actor))
  (set! (-> this glow-u) 0.0)
  (set! (-> this player-attack-id) (the-as uint 0))
  (set! (-> this last-updated-user-lighting) 0)
  (set-vector! (-> this off-color-mult) 0.0 0.0 0.0 1.0)
  (set-vector! (-> this off-color-emissive) 0.0 0.0 0.0 0.0)
  (set-vector! (-> this on-color-mult) 1.0 1.0 1.0 1.0)
  (set-vector! (-> this on-color-emissive) 0.0 0.0 0.0 0.0)
  (let ((s4-0 (new 'process 'collide-shape this (collide-list-enum hit-by-others))))
    (let ((s3-0 (new 'process 'collide-shape-prim-mesh s4-0 (the-as uint 0) (the-as uint 0))))
      (set! (-> s3-0 prim-core collide-as) (collide-kind wall-object))
      (set! (-> s3-0 collide-with) (collide-kind target))
      (set! (-> s3-0 prim-core action) (collide-action solid))
      (set! (-> s3-0 prim-core offense) (collide-offense indestructible))
      (set! (-> s3-0 transform-index) 0)
      (set-vector! (-> s3-0 local-sphere) 0.0 19251.2 0.0 22118.4)
      (set-root-prim! s4-0 s3-0))
    (set! (-> s4-0 nav-radius) 4915.2)
    (backup-collide-with-as s4-0)
    (set! (-> this root) s4-0))
  (set! (-> this link) (new 'process 'actor-link-info this))
  (set! (-> this crystal-id) (actor-count-before (-> this link)))
  (set! (-> this is-master?) (= (-> this crystal-id) 3))
  (set! (-> this glow-wf-period) (rand-vu-int-range 225 375))
  (set! (-> this glow-wf-offset) (rand-vu-int-range 0 300))
  (if (-> this is-master?) (logclear! (-> this mask) (process-mask actor-pause)))
  (set! (-> this start-fade-time)
        (the-as time-frame (the int (* 300.0 (res-lump-float (-> this entity) 'timeout :default 8.0)))))
  (process-drawable-from-entity! this arg0)
  (initialize-skeleton this *cavecrystal-sg* '())
  (nav-mesh-connect this (-> this root) (the-as nav-control #f))
  (set! (-> this draw color-mult quad) (-> this off-color-mult quad))
  (set! (-> this draw color-emissive quad) (-> this off-color-emissive quad))
  (ja-channel-push! 1 0)
  (let ((s5-1 (-> this skel root-channel 0)))
    (joint-control-channel-group-eval! s5-1 (the-as art-joint-anim (-> this draw art-group data 3)) num-func-identity)
    (set! (-> s5-1 frame-num) 0.0))
  (ja-post)
  (update-transforms! (-> this root))
  (cavecrystal-light-control-method-9 *cavecrystal-light-control* (-> this crystal-id) 0.0 this)
  (set! (-> this sound) (new 'process 'ambient-sound (static-sound-spec "crystal-on" :fo-max 80) (-> this root trans)))
  (go cavecrystal-idle)
  (none))
