;;-*-Lisp-*-
(in-package goal)
(bundles "SNO.DGO")
(require "levels/snow/snow-ram-h.gc")
(require "levels/snow/snow-ram-boss.gc")
(require "levels/snow/snow-obs.gc")

;; DECOMP BEGINS

(defskelgroup *ram-sg*
  ram
  ram-lod0-jg
  ram-cock-ja
  ((ram-lod0-mg (meters 20)) (ram-lod1-mg (meters 40)) (ram-lod2-mg (meters 999999)))
  :bounds (static-spherem 0 5 0 8.5)
  :longest-edge (meters 7.7))

(defpartgroup group-ram-hit-wall
  :id 526
  :flags (use-local-clock)
  :bounds (static-bspherem 0 0 0 8)
  :parts ((sp-item 1921) (sp-item 1922 :fade-after (meters 60) :falloff-to (meters 60))))

(defpart 1920
  :init-specs
  ((:texture (middot effects))
   (:num 64.0 16.0)
   (:scale-x (meters 0.1) (meters 0.2))
   (:scale-y :copy scale-x)
   (:r 128.0 16.0)
   (:g 128.0 48.0)
   (:b 128.0 64.0)
   (:a 64.0 64.0)
   (:vel-y (meters 0.10666667) (meters 0.053333335))
   (:scalevel-x (meters -0.00066666666))
   (:scalevel-y :copy scalevel-x)
   (:accel-y (meters -0.005) (meters 0.0033333334))
   (:friction 0.92 0.05)
   (:timer (seconds 0.7))
   (:flags (bit0 bit3 bit12))
   (:conerot-x (degrees 0) (degrees 170))
   (:rotate-y (degrees 0) (degrees 180))))

(defpart 1922
  :init-specs
  ((:texture (bigpuff effects))
   (:num 8.0)
   (:scale-x (meters 3) (meters 3))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 100.0)
   (:g 100.0)
   (:b 128.0)
   (:a 64.0 64.0)
   (:vel-y (meters 0.0033333334) (meters 0.013333334))
   (:rotvel-z (degrees -0.2) (degrees 0.4))
   (:fade-a -0.60952383)
   (:accel-y (meters 0.00016666666) (meters 0.00016666666))
   (:timer (seconds 0.7))
   (:flags (bit2 bit3 bit12))
   (:conerot-x (degrees 0) (degrees 180))
   (:conerot-y (degrees 0) (degrees 360))
   (:rotate-y (degrees 0) (degrees 180))))

(defpart 1921
  :init-specs
  ((:texture (starflash effects))
   (:num 1.0)
   (:scale-x (meters 6) (meters 1))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 100.0)
   (:g 100.0)
   (:b 128.0)
   (:a 96.0)
   (:fade-a -2.1333334)
   (:timer (seconds 0.14))
   (:flags (bit2 bit3))))

(defpartgroup group-ram-wheel-puffs
  :id 527
  :flags (use-local-clock)
  :bounds (static-bspherem 0 0 0 8)
  :parts ((sp-item 1923 :fade-after (meters 70) :falloff-to (meters 70))))

(defpart 1923
  :init-specs
  ((:texture (bigpuff effects))
   (:num 1.0)
   (:x (meters -0.5) (meters 1))
   (:z (meters -0.5) (meters 1))
   (:scale-x (meters 1.5) (meters 1.5))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 100.0)
   (:g 100.0)
   (:b 128.0)
   (:a 32.0 32.0)
   (:vel-y (meters 0) (meters 0.0033333334))
   (:rotvel-z (degrees -1.2) (degrees 2.4))
   (:fade-a -0.26666668)
   (:accel-y (meters -0.00033333333))
   (:timer (seconds 0.4))
   (:flags (bit2))))

(defmethod ram-method-20 ((this ram))
  (let ((gp-0 (-> this part)))
    (when (nonzero? gp-0)
      (let ((a2-0 (-> this node-list data 8 bone transform))
            (s5-0 (new 'stack-no-clear 'vector)))
        (set-vector! s5-0 0.0 0.0 -49152.0 1.0)
        (vector-matrix*! s5-0 s5-0 a2-0)
        (set! (-> *part-id-table* 1920 init-specs 16 initial-valuef) (+ 16384.0 (-> this orient-ry)))
        (spawn gp-0 s5-0)))))

(defmethod ram-method-21 ((this ram))
  (let ((gp-0 (-> this part2)))
    (let ((s3-0 (new 'stack-no-clear 'vector))
          (s4-0 (new 'stack-no-clear 'vector)))
      (vector<-cspace! s3-0 (-> this node-list data 5))
      (set-vector! s4-0 13312.0 -5324.8 0.0 1.0)
      (vector-rotate-around-y! s4-0 s4-0 (-> this orient-ry))
      (vector+! s4-0 s4-0 s3-0)
      (spawn gp-0 s4-0)
      (set-vector! s4-0 -13312.0 -5324.8 0.0 1.0)
      (vector-rotate-around-y! s4-0 s4-0 (-> this orient-ry))
      (vector+! s4-0 s4-0 s3-0)
      (spawn gp-0 s4-0))
    (let ((s3-1 (new 'stack-no-clear 'vector))
          (s4-1 (new 'stack-no-clear 'vector)))
      (vector<-cspace! s3-1 (-> this node-list data 6))
      (set-vector! s4-1 13312.0 -5324.8 0.0 1.0)
      (vector-rotate-around-y! s4-1 s4-1 (-> this orient-ry))
      (vector+! s4-1 s4-1 s3-1)
      (spawn gp-0 s4-1)
      (set-vector! s4-1 -13312.0 -5324.8 0.0 1.0)
      (vector-rotate-around-y! s4-1 s4-1 (-> this orient-ry))
      (vector+! s4-1 s4-1 s3-1)
      (spawn gp-0 s4-1))))

(defmethod ram-method-22 ((this ram))
  (process-entity-status! this (entity-perm-status complete) #t)
  (let ((v1-0 (alt-actor-list-subtask-incomplete-count this)))
    (cond
      ((zero? v1-0)
       (let ((v1-3 (-> this entity extra perm)))
         (logior! (-> v1-3 status) (entity-perm-status user-set-from-cstage))
         (set! (-> v1-3 user-int8 2) 1))
       (if (not (task-complete? *game-info* (-> this entity extra perm task))) (return #t)))
      ((= v1-0 1) (close-specific-task! (game-task snow-ram) (task-status need-reminder)))
      (else (close-specific-task! (game-task snow-ram) (task-status need-reminder-a)))))
  #f)

(defstate ram-idle (ram)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('touch 'attack)
         (if ((method-of-type touching-shapes-entry prims-touching?)
              (the-as touching-shapes-entry (-> block param 0))
              (-> self root)
              (the-as uint 1))
           (send-event proc 'attack (-> block param 0) (static-attack-info ((shove-up (meters 0.5)) (shove-back (meters 2)))))))))
  :exit
    (behavior ()
      (logior! (-> self mask) (process-mask actor-pause)))
  :trans
    (behavior ()
      (rider-trans)
      (if (-> self give-fuel-cell-anim) (spool-push *art-control* (-> self give-fuel-cell-anim name) 0 self -99.0)))
  :code
    (behavior ()
      (local-vars (sv-16 symbol))
      (ja-channel-push! 1 (seconds 0.075))
      (loop
        (sound-play "set-ram")
        (ja-no-eval :group! ram-cock-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!)))
        (let ((gp-1 #f))
          (sound-play "slam-crash")
          (logclear! (-> self mask) (process-mask actor-pause))
          (ja-no-eval :group! ram-release-ja :num! (seek!) :frame-num 0.0)
          (until (ja-done? 0)
            (let ((f30-0 (ja-aframe-num 0)))
              (when (and (not gp-1) (>= f30-0 61.0))
                (set! gp-1 #t)
                (ram-method-20 self))
              (if (and (>= f30-0 62.0) (< f30-0 97.0)) (ram-method-21 self)))
            (suspend)
            (ja :num! (seek!))))
        (logior! (-> self mask) (process-mask actor-pause))
        (set! sv-16 (the-as symbol #f))
        (apply-function-forward (-> self link) actor-link-dead-hook (& sv-16))
        (when (or sv-16 (nonzero? (-> self root riders num-riders)))
          (let ((v1-67 (-> self entity extra perm)))
            (logior! (-> v1-67 status) (entity-perm-status user-set-from-cstage))
            (set! (-> v1-67 user-int8 0) 1))
          (send-event (ppointer->process (-> self child)) 'jump)
          (go ram-fun-idle))))
  :post rider-post)

(defstate ram-fun-idle (ram)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('notify) (when (= (-> proc type) ram-boss) (if (ram-method-22 self) (go ram-give-fuel-cell))))))
  :trans
    (behavior ()
      (if (-> self give-fuel-cell-anim) (spool-push *art-control* (-> self give-fuel-cell-anim name) 0 self -99.0)))
  :code
    (behavior ()
      (if (-> self give-fuel-cell?) (go ram-give-fuel-cell))
      (ja-channel-push! 1 0)
      (ja :group! ram-idle-ja :num! min)
      (transform-post)
      (logior! (-> self mask) (process-mask sleep-code))
      (suspend)
      0))

(defstate ram-give-fuel-cell (ram)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('notify) (if (and (= (-> proc type) snowcam) (= (-> block param 0) 'die)) (go ram-fun-idle)))))
  :exit
    (behavior ()
      (process-entity-status! self (entity-perm-status bit-3) #f)
      (logior! (-> self mask) (process-mask actor-pause)))
  :code
    (behavior ()
      (set! (-> self give-fuel-cell?) #f)
      (ja-channel-push! 1 0)
      (ja :group! ram-idle-ja :num! min)
      (transform-post)
      (when (and (not (task-complete? *game-info* (-> self entity extra perm task))) (-> self give-fuel-cell-anim))
        (logclear! (-> self mask) (process-mask actor-pause))
        (process-entity-status! self (entity-perm-status bit-3) #t)
        (let ((v1-14 (process-spawn snowcam
                                    :init
                                    pov-camera-init-by-other
                                    (-> self root trans)
                                    *snowcam-sg*
                                    (-> self give-fuel-cell-anim)
                                    0
                                    self
                                    '()
                                    :to
                                    self)))
          (set! (-> (the-as (pointer snowcam) v1-14) 0 seq) (the-as uint 1)))
        (sound-play "cell-prize")
        (logior! (-> self mask) (process-mask sleep-code))
        (suspend)
        0)
      (go ram-fun-idle)))

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

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

(defmethod init-from-entity! ((this ram) (arg0 entity-actor))
  (set! (-> this give-fuel-cell?) #f)
  (set! (-> this link) (new 'process 'actor-link-info this))
  (let ((s4-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-others))))
    (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))
    (alloc-riders s4-0 1)
    (let ((s3-0 (new 'process 'collide-shape-prim-group s4-0 (the-as uint 3) 0)))
      (set! (-> s3-0 prim-core collide-as) (collide-kind ground-object))
      (set! (-> s3-0 collide-with) (collide-kind target))
      (set! (-> s3-0 prim-core action) (collide-action solid rider-plat-sticky))
      (set-vector! (-> s3-0 local-sphere) 0.0 20480.0 0.0 34816.0)
      (set-root-prim! s4-0 s3-0)
      (let ((s2-0 (new 'process 'collide-shape-prim-mesh s4-0 (the-as uint 0) (the-as uint 1))))
        (set! (-> s2-0 prim-core collide-as) (collide-kind ground-object))
        (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) 8)
        (set-vector! (-> s2-0 local-sphere) 0.0 0.0 0.0 20480.0)
        (append-prim s3-0 s2-0))
      (let ((s2-1 (new 'process 'collide-shape-prim-mesh s4-0 (the-as uint 1) (the-as uint 2))))
        (set! (-> s2-1 prim-core collide-as) (collide-kind ground-object))
        (set! (-> s2-1 collide-with) (collide-kind target))
        (set! (-> s2-1 prim-core action) (collide-action solid rider-plat-sticky))
        (set! (-> s2-1 prim-core offense) (collide-offense indestructible))
        (set! (-> s2-1 transform-index) 3)
        (set-vector! (-> s2-1 local-sphere) 0.0 20480.0 0.0 34816.0)
        (append-prim s3-0 s2-1))
      (let ((s2-2 (new 'process 'collide-shape-prim-sphere s4-0 (the-as uint 4))))
        (set! (-> s2-2 prim-core collide-as) (collide-kind enemy))
        (set! (-> s2-2 collide-with) (collide-kind target))
        (set! (-> s2-2 prim-core offense) (collide-offense no-offense))
        (set! (-> s2-2 transform-index) 3)
        (set-vector! (-> s2-2 local-sphere) -4096.0 28672.0 12288.0 2252.8)
        (append-prim s3-0 s2-2)))
    (set! (-> s4-0 nav-radius) 20480.0)
    (backup-collide-with-as s4-0)
    (set! (-> this root) s4-0))
  (process-drawable-from-entity! this arg0)
  (initialize-skeleton this *ram-sg* '())
  (logior! (-> this skel status) (janim-status inited))
  (ja-post)
  (update-transforms! (-> this root))
  (set! (-> this orient-ry) (quaternion-y-angle (-> this root quat)))
  (nav-mesh-connect this (-> this root) (the-as nav-control #f))
  (set! (-> this part) (create-launch-control (-> *part-group-id-table* 526) this))
  (set! (-> this part2) (create-launch-control (-> *part-group-id-table* 527) this))
  (set! (-> this ram-id) (res-lump-value arg0 'extra-id int))
  (case (-> this ram-id)
    ((1)
     (set! (-> this give-fuel-cell-anim)
           (new 'static 'spool-anim :name "snowcam-ram-boss-in-cave-fuel-cell" :index 7 :parts 1 :command-list '()))
     (set-vector! (-> this fuel-cell-dest-pos) 3137396.8 803676.2 -13560558.0 1.0))
    ((2)
     (set! (-> this give-fuel-cell-anim)
           (new 'static 'spool-anim :name "snowcam-ram-boss-ice-pond-fuel-cell" :index 8 :parts 1 :command-list '()))
     (set-vector! (-> this fuel-cell-dest-pos) 2790289.5 1058152.5 -13639766.0 1.0))
    ((3)
     (set! (-> this give-fuel-cell-anim)
           (new 'static 'spool-anim :name "snowcam-ram-boss-snow-ball-fuel-cell" :index 9 :parts 1 :command-list '()))
     (set-vector! (-> this fuel-cell-dest-pos) 4208423.0 1037348.9 -13591491.0 1.0))
    (else (set! (-> this give-fuel-cell-anim) #f)))
  (let ((s4-1 #f))
    (if (nonzero? (-> this entity extra perm user-int8 0)) (set! s4-1 #t))
    (let ((s3-1 (= (res-lump-value arg0 'mode uint128) 1)))
      (when (not s3-1)
        (when (and (-> this entity) (logtest? (-> this entity extra perm status) (entity-perm-status complete)))
          (set! s3-1 #t)
          (if (and (nonzero? (-> this entity extra perm user-int8 2))
                   (not (task-complete? *game-info* (-> this entity extra perm task))))
            (birth-pickup-at-point (-> this fuel-cell-dest-pos)
                                   (pickup-type fuel-cell)
                                   (the float (-> this entity extra perm task))
                                   #f
                                   this
                                   (the-as fact-info #f)))
          (go ram-fun-idle)))
      (cond
        ((and (not s3-1) (has-nav-mesh? arg0))
         (cond
           (s4-1 (process-spawn ram-boss (-> this entity) this #t :to this) (go ram-fun-idle))
           (else (process-spawn ram-boss (-> this entity) this #f :to this) (go ram-idle))))
        (else (go ram-fun-idle)))))
  (none))
