;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/common-obs/generic-obs.gc")
(require "engine/physics/trajectory.gc")
(require "engine/collide/collide-cache.gc")
(require "pc/pckernel.gc")
(require "engine/common-obs/collectables-part.gc")
(require "engine/entity/entity.gc")
(declare-type vent process-drawable)

(declare-type eco eco-collectable)

(defenum collectable-flags
  :bitfield #t
  :type uint32
  (trans 0)
  (fade 1)
  (can-collect 2)
  (fading 3)
  (suck 4)
  (ignore-blue 5)
  (anim 6))

;; DECOMP BEGINS

(define *eco-pill-count* 0)

(deftype collectable (process-drawable)
  ((root            collide-shape-moving :override)
   (pickup-type     pickup-type)
   (pickup-amount   float)
   (notify-parent   basic)
   (old-base        vector :inline)
   (base            vector :inline)
   (extra-trans     vector :inline)
   (jump-pos        vector :inline)
   (flags           collectable-flags)
   (birth-time      time-frame)
   (collect-timeout time-frame)
   (fadeout-timeout time-frame)
   (bob-offset      int64)
   (bob-amount      float)
   (pickup-handle   handle)
   (actor-pause     symbol))
  (:methods
   (initialize (_type_) _type_)
   (initialize-params (_type_ time-frame float) none)))


(defmethod initialize-params ((this collectable) (arg0 time-frame) (arg1 float))
  (logclear! (-> this mask) (process-mask crate enemy platform ambient))
  (logior! (-> this mask) (process-mask collectable))
  (set! (-> this flags) (collectable-flags can-collect ignore-blue))
  (set! (-> this bob-amount) arg1)
  (set! (-> this bob-offset)
        (+ (the-as int (-> this root trans x)) (the-as int (-> this root trans y)) (the-as int (-> this root trans z))))
  (cond
    ((or (= (vector-length (-> this root transv)) 0.0) (logtest? (-> this fact options) (fact-options instant-collect)))
     (vector-reset! (-> this root transv)))
    (else
     (logior! (-> this flags) (collectable-flags trans))
     (logclear! (-> this flags) (collectable-flags can-collect))
     (logclear! (-> this mask) (process-mask actor-pause))
     (set! (-> this bob-amount) 0.0)))
  (when (and (> arg0 0) #t)
    (logior! (-> this flags) (collectable-flags fade))
    (set! (-> this fadeout-timeout) arg0))
  (set! (-> this collect-timeout) (seconds 0.33))
  (set-time! (-> this birth-time))
  (set! (-> this base quad) (-> this root trans quad))
  (set! (-> this old-base quad) (-> this root trans quad))
  (set! (-> this pickup-handle) (the-as handle #f))
  (case (-> this fact pickup-type)
    (((pickup-type eco-pill) (pickup-type eco-green) (pickup-type money) (pickup-type eco-blue))
     (logclear! (-> this flags) (collectable-flags ignore-blue))))
  (if (logtest? (-> this fact options) (fact-options large))
    (set! (-> this root root-prim local-sphere w) (* 2.5 (-> this root root-prim local-sphere w))))
  (none))

(deftype eco-collectable (collectable)
  ((eco-effect          sparticle-launch-group)
   (collect-effect      sparticle-launch-group)
   (collect-effect2     sparticle-launch-group)
   (collect-effect-time time-frame)
   (respawn-delay       time-frame)
   (sound-name          sound-spec)
   (target              handle)
   (suck-time           time-frame)
   (suck-y-offset       float)
   (speed               vector :inline)
   (movie-pos-index     int32))
  (:state-methods
   wait
   (pickup object handle)
   die
   jump
   (notice-blue handle))
  (:methods
   (initialize-effect (_type_ pickup-type) none)
   (initialize-eco (_type_ entity-actor pickup-type float) object)
   (animate (_type_) none)
   (blocked () _type_ :state)))


(defmethod initialize ((this eco-collectable))
  (stack-size-set! (-> this main-thread) 192) ;; og:preserve-this hack increased from 128
  (logior! (-> this mask) (process-mask actor-pause))
  (set! (-> this actor-pause) #t)
  (set! (-> this notify-parent) #f)
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind powerup blue-eco-suck))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set-vector! (-> s4-0 local-sphere) 0.0 3276.8 0.0 3276.8)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> this root) s5-0))
  (set! (-> this fact) (new 'process 'fact-info this (-> this pickup-type) (-> this pickup-amount)))
  (if (logtest? (fact-options respawn) (-> this fact options)) (set! (-> this respawn-delay) (-> this fact fade-time)))
  this)

(defmethod initialize-effect ((this eco-collectable) (arg0 pickup-type))
  (set! (-> this fact pickup-type) arg0)
  (case (-> this fact pickup-type)
    (((pickup-type eco-blue) (pickup-type eco-red) (pickup-type eco-green) (pickup-type eco-yellow))
     (logclear! (-> this mask) (process-mask actor-pause))))
  (set! (-> this sound-name) #f)
  (case arg0
    (((pickup-type eco-yellow))
     (set! (-> this eco-effect) (-> *part-group-id-table* 56))
     (set! (-> this collect-effect) (-> *part-group-id-table* 68))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 57))
     (set! (-> this collect-effect-time) (seconds 0.5))
     (set! (-> this sound-name) (static-sound-spec "yel-eco-idle" :fo-max 15)))
    (((pickup-type eco-red))
     (set! (-> this eco-effect) (-> *part-group-id-table* 48))
     (set! (-> this collect-effect) (-> *part-group-id-table* 69))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 49))
     (set! (-> this collect-effect-time) (seconds 0.5))
     (set! (-> this sound-name) (static-sound-spec "red-eco-idle" :fo-max 15)))
    (((pickup-type eco-blue))
     (set! (-> this eco-effect) (-> *part-group-id-table* 42))
     (set! (-> this collect-effect) (-> *part-group-id-table* 67))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 43))
     (set! (-> this collect-effect-time) (seconds 0.5))
     (set! (-> this sound-name) (static-sound-spec "blue-eco-idle" :fo-max 15)))
    (((pickup-type eco-green))
     (set! (-> this eco-effect) (-> *part-group-id-table* 58))
     (set! (-> this collect-effect) (-> *part-group-id-table* 66))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 61))
     (set! (-> this collect-effect-time) (seconds 0.5))
     (set! (-> this sound-name) (static-sound-spec "green-eco-idle" :fo-max 15)))
    (((pickup-type eco-pill))
     (set! (-> this eco-effect) (-> *part-group-id-table* 59))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 60))
     (set! (-> this collect-effect-time) (seconds 0.5))))
  (set! (-> this part) (create-launch-control (-> this eco-effect) this))
  (if (-> this sound-name) (set! (-> this sound) (new 'process 'ambient-sound (-> this sound-name) (-> this root trans))))
  (none))

(defbehavior initialize-eco-by-other eco ((arg0 vector) (arg1 vector) (arg2 fact-info))
  (let ((s3-0 (-> arg2 pickup-type))
        (f30-0 (-> arg2 pickup-spawn-amount)))
    (set! (-> self pickup-amount) f30-0)
    (set! (-> self pickup-type) s3-0)
    (initialize self)
    (set! (-> self fact pickup-type) s3-0)
    (set! (-> self fact pickup-amount) f30-0))
  (set! (-> self fact options) (-> arg2 options))
  (set! (-> self root trans quad) (-> arg0 quad))
  (set! (-> self root transv quad) (-> arg1 quad))
  (initialize-effect self (-> self fact pickup-type))
  (set! (-> self notify-parent) #f)
  (case (-> self fact pickup-type)
    (((pickup-type eco-blue) (pickup-type eco-yellow) (pickup-type eco-red))
     (initialize-params self
                        (the-as time-frame (if (and arg2 (logtest? (-> arg2 options) (fact-options fade))) (the-as int (-> arg2 fade-time)) 0))
                        (the-as float 1024.0)))
    (else (initialize-params self (seconds 15) (the-as float 1024.0))))
  (update-transforms! (-> self root))
  (set! (-> self event-hook) (-> (method-of-object self wait) event))
  (if (logtest? (fact-options eco-blocked) (-> self fact options)) (go-virtual blocked))
  (go-virtual wait)
  (none))

(defmethod initialize-eco ((this eco-collectable) (arg0 entity-actor) (arg1 pickup-type) (arg2 float))
  (set! (-> this pickup-amount) arg2)
  (set! (-> this pickup-type) arg1)
  (initialize this)
  (set! (-> this root trans quad) (-> arg0 extra trans quad))
  (initialize-effect this (-> this fact pickup-type))
  (initialize-params this 0 (the-as float 1024.0))
  (update-transforms! (-> this root))
  (if (logtest? (fact-options eco-blocked) (-> this fact options)) (go (method-of-object this blocked)))
  (go (method-of-object this wait)))

(defmethod animate ((this eco-collectable))
  0
  (none))

(defun add-blue-shake ((arg0 vector) (arg1 vector) (arg2 vector))
  (let* ((f0-0 (vector-vector-distance arg1 arg2))
         (f30-0 (lerp-scale (the-as float 409.6)
                            (the-as float 0.0)
                            f0-0
                            (-> *FACT-bank* suck-suck-dist)
                            (-> *FACT-bank* suck-bounce-dist))))
    (+! (-> arg0 x) (rand-vu-float-range (- f30-0) f30-0))
    (+! (-> arg0 y) (rand-vu-float-range (- f30-0) f30-0))
    (+! (-> arg0 z) (rand-vu-float-range (- f30-0) f30-0)))
  arg0)

(defbehavior check-blue-suck eco-collectable ((arg0 process-drawable))
  (let ((v1-1 (if (and (nonzero? arg0) (type-type? (-> arg0 type) process-drawable)) arg0)))
    (when v1-1
      (let* ((gp-1 (-> v1-1 root))
             (v1-3 (if (and (nonzero? gp-1) (type-type? (-> gp-1 type) collide-shape)) gp-1)))
        (when v1-3
          (let ((a0-5 (-> self root root-prim prim-core))
                (a1-2 (-> (the-as collide-shape v1-3) root-prim prim-core)))
            (if (< (vector-vector-distance (the-as vector a0-5) (the-as vector a1-2)) (-> *FACT-bank* suck-suck-dist))
              (logior! (-> self flags) (collectable-flags suck))))))))
  (none))

(defbehavior add-blue-motion eco-collectable ((arg0 symbol) (arg1 symbol) (arg2 symbol) (arg3 symbol))
  (let* ((gp-0 (handle->process (-> self target)))
         (v1-4 (if (and (nonzero? gp-0) (type-type? (-> gp-0 type) process-drawable)) gp-0)))
    (when v1-4
      (let* ((gp-1 (-> (the-as process-drawable v1-4) root))
             (v1-6 (if (and (nonzero? gp-1) (type-type? (-> gp-1 type) collide-shape)) (the-as collide-shape gp-1))))
        (when v1-6
          (let ((s2-0 (-> self root root-prim prim-core))
                (gp-2 (-> v1-6 root-prim prim-core)))
            (if (and arg1 (rand-vu-percent? (the-as float 0.25))) (eco-blue-glow (the-as vector s2-0)))
            (let ((f0-0 (vector-vector-distance (the-as vector s2-0) (the-as vector gp-2))))
              (cond
                ((and arg3 (< f0-0 8192.0)) (return #t))
                ((begin
                   (set! arg0
                         (and (or (not arg2) (or (< f0-0 (-> *FACT-bank* suck-suck-dist)) (logtest? (-> self flags) (collectable-flags suck))))
                              arg0))
                   arg0)
                 (logior! (-> self flags) (collectable-flags suck))
                 (if (= (-> self speed w) 0.0) (set-time! (-> self suck-time)))
                 (+! (-> self speed w) (* 163840.0 (seconds-per-frame)))
                 (+! (-> self speed y) (* 291271.12 (seconds-per-frame)))
                 (set! (-> self speed y) (fmin (fmin 291271.12 (-> self speed y)) (-> self speed y)))
                 (let ((s5-2 (vector-! (new 'stack-no-clear 'vector) (-> self base) (the-as vector gp-2))))
                   (vector-normalize! s5-2 (fmax 0.0 (- (vector-length s5-2) (* (-> self speed w) (seconds-per-frame)))))
                   (vector-rotate-y! s5-2 s5-2 (* (-> self speed y) (-> self speed z) (seconds-per-frame)))
                   (set! (-> self suck-y-offset)
                         (* 2048.0 (sin (* 873.81335 (the float (mod (- (current-time) (-> self suck-time)) 75))))))
                   (vector+! (-> self base) (the-as vector gp-2) s5-2)))
                ((and arg2
                      (and (< (+ 4096.0 (-> *FACT-bank* suck-bounce-dist)) f0-0) (not (logtest? (-> self flags) (collectable-flags suck)))))
                 (go-virtual wait))
                (arg1 (add-blue-shake (-> self root trans) (the-as vector s2-0) (the-as vector gp-2))))))))))
  #f)

(defstate blocked (eco-collectable)
  :virtual #t
  :trans
    (behavior ()
      (if (task-complete? *game-info* (-> self entity extra perm task)) (go-virtual wait)))
  :code anim-loop)

(defstate jump (eco-collectable)
  :virtual #t
  :code
    (behavior ()
      (if (type-type? (-> self type) fuel-cell) (sound-play "cell-prize"))
      (logclear! (-> self mask) (process-mask actor-pause))
      (let ((gp-1 (new 'stack 'trajectory)))
        (set! (-> self base y) (-> self jump-pos y))
        (setup-from-to-duration! gp-1 (-> self root trans) (-> self jump-pos) (the-as float 300.0) (the-as float -2.2755556))
        (set-time! (-> self state-time))
        (until (time-elapsed? (-> self state-time) (seconds 1))
          (let ((f0-2 (the float (- (current-time) (-> self state-time))))) (eval-position! gp-1 f0-2 (-> self root trans)))
          (transform-post)
          (animate self)
          (suspend)
          (if (nonzero? (-> self skel)) (ja :num! (loop! 0.5)))))
      (set! (-> self root trans quad) (-> self jump-pos quad))
      (set! (-> self base quad) (-> self root trans quad))
      (vector-reset! (-> self root transv))
      (update-transforms! (-> self root))
      (logclear! (-> self flags) (collectable-flags trans))
      (logior! (-> self flags) (collectable-flags can-collect))
      (if (-> self actor-pause) (logior! (-> self mask) (process-mask actor-pause)))
      (go-virtual wait)))

(defstate wait (eco-collectable)
  :virtual #t
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (local-vars (v0-3 object))
      (when (and (or (= message 'touch) (= message 'attack))
                 (and (logtest? (-> self flags) (collectable-flags can-collect))
                      (time-elapsed? (-> self birth-time) (-> self collect-timeout))
                      (!= (-> self next-state name) 'pickup)
                      (send-event proc 'get-pickup (-> self fact pickup-type) (-> self fact pickup-amount))))
        (logclear! (-> self mask) (process-mask actor-pause))
        (go-virtual pickup #f (process->handle proc)))
      (cond
        ((= message 'eco-blue)
         (when (and (not (logtest? (-> self flags) (collectable-flags fading ignore-blue)))
                    (!= (-> self next-state name) 'pickup)
                    (begin
                      (check-blue-suck (the-as process-drawable proc))
                      #t)
                    (logtest? (-> self flags) (collectable-flags can-collect))
                    (time-elapsed? (-> self birth-time) (-> self collect-timeout)))
           (logclear! (-> self mask) (process-mask actor-pause))
           (go-virtual notice-blue (process->handle proc))))
        ((= message 'trans)
         (set! (-> self root trans quad) (-> (the-as vector (-> block param 0)) quad))
         (update-transforms! (-> self root))
         (ja-post))
        ((= message 'jump)
         (logclear! (-> self mask) (process-mask actor-pause))
         (set! (-> self jump-pos quad) (-> (the-as vector (-> block param 0)) quad))
         (go-virtual jump))
        ((= message 'pickup)
         (when (!= (-> self next-state name) 'pickup)
           (if (and (> argc 0) (-> block param 0)) (move-to-point! (-> self root) (the-as vector (-> block param 0))))
           (logclear! (-> self mask) (process-mask actor-pause))
           (go-virtual pickup #f (the-as handle #f))))
        ((= message 'die) (logclear! (-> self mask) (process-mask actor-pause)) (go-virtual die))
        ((= message 'movie-pos) (set! v0-3 (-> block param 0)) (set! (-> self movie-pos-index) (the-as int v0-3)) v0-3)
        ((= message 'actor-pause)
         (cond
           ((-> block param 0)
            (logior! (-> self mask) (process-mask actor-pause))
            (set! v0-3 #t)
            (set! (-> self actor-pause) (the-as symbol v0-3))
            v0-3)
           (else (logclear! (-> self mask) (process-mask actor-pause)) (set! (-> self actor-pause) #f) #f)))
        ((= message 'fade)
         (logior! (-> self flags) (collectable-flags fade))
         (set! (-> self fadeout-timeout) (seconds 0.1))
         (set! v0-3 (current-time))
         (set! (-> self birth-time) (the-as time-frame v0-3))
         v0-3)))
  :enter
    (behavior ()
      (if (and (logtest? (-> self fact options) (fact-options instant-collect can-collect))
               (logtest? (-> self flags) (collectable-flags can-collect))
               (!= (-> self next-state name) 'pickup)
               (send-event *target* 'get-pickup (-> self fact pickup-type) (-> self fact pickup-amount)))
        (go-virtual pickup #f (process->handle *target*))))
  :trans
    (behavior ()
      (cond
        ((logtest? (-> self flags) (collectable-flags trans))
         (vector-v++! (-> self root transv) (compute-acc-due-to-gravity (-> self root) (new-stack-vector0) (the-as float 0.0)))
         (integrate-no-collide! (-> self root) (-> self root transv))
         (when (and (>= 0.0 (-> self root transv y)) (>= (-> self base y) (-> self root trans y)))
           (set! (-> self root trans y) (-> self base y))
           (cond
             ((< (-> self root transv y) -8192.0) (set! (-> self root transv y) (/ (-> self root transv y) -2)))
             (else
              (vector-reset! (-> self root transv))
              (logclear! (-> self flags) (collectable-flags trans))
              (logior! (-> self flags) (collectable-flags can-collect))
              (if (-> self actor-pause) (logior! (-> self mask) (process-mask actor-pause)))
              (set! (-> self base quad) (-> self root trans quad))
              (if (and (logtest? (-> self fact options) (fact-options can-collect))
                       (not (logtest? (-> self flags) (collectable-flags ignore-blue))))
                (go-virtual notice-blue (process->handle *target*)))
              (if (and (logtest? (-> self fact options) (fact-options instant-collect can-collect))
                       (!= (-> self next-state name) 'pickup)
                       (send-event *target* 'get-pickup (-> self fact pickup-type) (-> self fact pickup-amount)))
                (go-virtual pickup #f (process->handle *target*)))))))
        (else (set! (-> self trans-hook) #f)))
      (update-transforms! (-> self root)))
  :code
    (behavior ()
      (loop
        (let ((gp-0 (-> self part))
              (s5-0 (-> self root root-prim prim-core)))
          (when (and (logtest? (-> self flags) (collectable-flags fade)) (time-elapsed? (-> self birth-time) (-> self fadeout-timeout)))
            (let ((v1-10 (- (seconds 1) (- (- (current-time) (-> self birth-time)) (-> self fadeout-timeout)))))
              (cond
                ((< v1-10 0) (process-entity-status! self (entity-perm-status dead) #t) (deactivate self))
                (else
                 (logclear! (-> self mask) (process-mask actor-pause))
                 (set! (-> self actor-pause) #f)
                 (logior! (-> self flags) (collectable-flags fading))
                 (logior! (-> self state-flags) (state-flags fade-out-particles))
                 (set! (-> gp-0 fade) (* 0.0033333334 (the float v1-10)))))))
          (spawn gp-0 (the-as vector s5-0)))
        (if (nonzero? (-> self sound)) (update! (-> self sound)))
        (suspend))))

(defstate notice-blue (eco-collectable)
  :virtual #t
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (when (and (or (= message 'touch) (= message 'attack))
                 (and (logtest? (-> self flags) (collectable-flags can-collect))
                      (time-elapsed? (-> self birth-time) (-> self collect-timeout))
                      (!= (-> self next-state name) 'pickup)
                      (send-event proc 'get-pickup (-> self fact pickup-type) (-> self fact pickup-amount))))
        (logclear! (-> self mask) (process-mask actor-pause))
        (go-virtual pickup #f (process->handle proc))))
  :enter
    (behavior ((arg0 handle))
      (set! (-> self target) arg0)
      (set! (-> self speed quad) (the-as uint128 0))
      (set! (-> self speed z) (the-as float (if (rand-vu-percent? (the-as float 0.5)) 1.0 -1.0)))
      (set! (-> self suck-y-offset) 0.0)
      (logclear! (-> self mask) (process-mask actor-pause)))
  :exit
    (behavior ()
      (if (-> self actor-pause) (logior! (-> self mask) (process-mask actor-pause))))
  :trans
    (behavior ()
      (let ((a1-0 (new 'stack-no-clear 'event-message-block)))
        (set! (-> a1-0 from) self)
        (set! (-> a1-0 num-params) 2)
        (set! (-> a1-0 message) 'query)
        (set! (-> a1-0 param 0) (the-as uint 'powerup))
        (set! (-> a1-0 param 1) (the-as uint 3))
        (if (and (not (send-event-function *target* a1-0)) (not (logtest? (-> self flags) (collectable-flags suck))))
          (go-virtual wait))))
  :code
    (behavior ((arg0 handle))
      (loop
        (set! (-> self root trans quad) (-> self base quad))
        (add-blue-motion #t #f #t #f)
        (update-transforms! (-> self root))
        (if (nonzero? (-> self draw)) (ja-post))
        (let ((a0-5 (-> self part))
              (a1-1 (-> self root root-prim prim-core)))
          (if (nonzero? a0-5) (spawn a0-5 (the-as vector a1-1))))
        (if (nonzero? (-> self sound)) (update! (-> self sound)))
        (suspend))))

(defstate pickup (eco-collectable)
  :virtual #t
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (the-as symbol
              (case message
                (('set-movie-pos)
                 (let ((v1-3 (res-lump-struct (-> self entity) 'movie-pos vector :time (the-as float -1000000000.0))))
                   (the-as symbol (when v1-3 (set! (-> v1-3 quad) (-> (the-as vector (-> block param 0)) quad)) (the-as symbol v1-3)))))
                (('actor-pause)
                 (the-as symbol
                         (cond
                           ((-> block param 0)
                            (logior! (-> self mask) (process-mask actor-pause))
                            (let ((v0-1 #t)) (set! (-> self actor-pause) v0-1) v0-1))
                           (else (logclear! (-> self mask) (process-mask actor-pause)) (set! (-> self actor-pause) #f) #f))))
                (('fade) (process-entity-status! self (entity-perm-status dead) #t) (the-as symbol (deactivate self))))))
  :enter
    (behavior ((arg0 object) (arg1 handle))
      (set! (-> self pickup-handle) arg1)
      (when (-> self notify-parent)
        (let ((gp-0 (new 'stack-no-clear 'event-message-block)))
          (set! (-> gp-0 from) self)
          (set! (-> gp-0 num-params) 1)
          (set! (-> gp-0 message) 'notify)
          (set! (-> gp-0 param 0) (the-as uint 'pickup))
          (let ((s5-0 send-event-function)
                (s4-0 (ppointer->process (-> self parent))))
            (s5-0 (if (and (nonzero? s4-0) (type-type? (-> s4-0 type) process)) s4-0) gp-0))))
      (logclear! (-> self mask) (process-mask actor-pause)))
  :code
    (behavior ((arg0 object) (arg1 handle))
      (clear-collide-with-as (-> self root))
      (if (not (or (= (-> self fact pickup-type) (pickup-type eco-pill)) (logtest? (-> self fact options) (fact-options powerup))))
        (send-event (handle->process arg1) 'powerup (-> self fact pickup-type) (-> self fact pickup-amount)))
      (if (nonzero? (-> self sound)) (stop! (-> self sound)))
      (case (-> self fact pickup-type)
        (((pickup-type eco-yellow)) (sound-play "y-eco-pickup"))
        (((pickup-type eco-red)) (sound-play "r-eco-pickup"))
        (((pickup-type eco-blue))
         (sound-play "b-eco-pickup")
         (case (-> (level-get-target-inside *level*) name)
           (('training)
            (level-hint-spawn (text-id training-eco-reminder) "sagevb23" (the-as entity #f) *entity-pool* (game-task none)))))
        (((pickup-type eco-green)) (sound-play "g-eco-pickup"))
        (((pickup-type eco-green) (pickup-type eco-pill)) (sound-play "pill-pickup")))
      (if (nonzero? (-> self part)) (kill-and-free-particles (-> self part)))
      (let ((gp-6 (handle->process (-> self pickup-handle))))
        (if (nonzero? (-> self collect-effect))
          (process-spawn part-tracker
                         :init
                         part-tracker-init
                         (-> self collect-effect)
                         -1
                         part-tracker-track-target
                         #f
                         #f
                         (-> self root root-prim prim-core)
                         :to
                         gp-6)))
      (if (nonzero? (-> self collect-effect2))
        (process-spawn part-tracker
                       :init
                       part-tracker-init
                       (-> self collect-effect2)
                       -1
                       (lambda ((arg0 part-tracker))
                         (let ((s5-0 (handle->process (-> arg0 userdata))))
                           (when s5-0
                             (let* ((v1-4 (handle->process (-> (the-as eco-collectable s5-0) pickup-handle)))
                                    (a2-0 (cond
                                            ((not v1-4) (-> arg0 root trans))
                                            ((= (-> v1-4 type) target) (vector<-cspace! (new 'stack-no-clear 'vector) (-> (the-as target v1-4) node-list data 5)))
                                            (else (-> (the-as target v1-4) control trans)))))
                               (vector-lerp! (-> arg0 root trans)
                                             (-> arg0 offset)
                                             a2-0
                                             (/ (the float (- (current-time) (-> arg0 start-time)))
                                                (the float (-> (the-as eco-collectable s5-0) collect-effect-time))))))))
                       (process->handle self)
                       #f
                       (-> self root root-prim prim-core)
                       :to
                       self))
      (while (-> self child)
        (suspend))
      (go-virtual die)))

(defstate die (eco-collectable)
  :virtual #t
  :code
    (behavior ()
      (process-entity-status! self (entity-perm-status dead) #t)))

(deftype eco (eco-collectable) ())


(defmethod animate ((this eco))
  (let ((a0-1 (-> this part))
        (a1-0 (-> this root root-prim prim-core)))
    (spawn a0-1 (the-as vector a1-0)))
  (if (nonzero? (-> this sound)) (update! (-> this sound)))
  0
  (none))

(defstate die (eco)
  :virtual #t
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('fade) (process-entity-status! self (entity-perm-status dead) #t) (deactivate self))
        (('die) (go-virtual die))))
  :exit
    (behavior ()
      (process-entity-status! self (entity-perm-status bit-3) #f)
      (if (-> self actor-pause) (logior! (-> self mask) (process-mask actor-pause))))
  :code
    (behavior ()
      (process-entity-status! self (entity-perm-status bit-3) #t)
      (logclear! (-> self mask) (process-mask actor-pause))
      (logclear! (-> self fact options) (fact-options instant-collect can-collect))
      (if (nonzero? (-> self part)) (kill-and-free-particles (-> self part)))
      (cond
        ((nonzero? (-> self respawn-delay))
         (let ((gp-0 (current-time))) (while (not (time-elapsed? gp-0 (-> self respawn-delay))) (suspend))))
        (else
         (while (let ((f30-0 0.0)) (< f30-0 (the-as float (send-event *target* 'query 'pickup (-> self fact pickup-type)))))
           (suspend))))
      (set! (-> self base quad) (-> self old-base quad))
      (set! (-> self root trans quad) (-> self base quad))
      (restore-collide-with-as (-> self root))
      (go-virtual wait)))

(deftype eco-yellow (eco) ())


(defmethod init-from-entity! ((this eco-yellow) (arg0 entity-actor))
  (initialize-eco this arg0 (pickup-type eco-yellow) (-> *FACT-bank* eco-single-inc))
  (none))

(deftype eco-red (eco) ())


(defmethod init-from-entity! ((this eco-red) (arg0 entity-actor))
  (initialize-eco this arg0 (pickup-type eco-red) (-> *FACT-bank* eco-single-inc))
  (none))

(deftype eco-blue (eco) ())


(defmethod init-from-entity! ((this eco-blue) (arg0 entity-actor))
  (initialize-eco this arg0 (pickup-type eco-blue) (-> *FACT-bank* eco-single-inc))
  (none))

(deftype health (eco-collectable) ())


(defmethod animate ((this health))
  (let ((a0-1 (-> this part))
        (a1-0 (-> this root root-prim prim-core)))
    (spawn a0-1 (the-as vector a1-0)))
  (if (nonzero? (-> this sound)) (update! (-> this sound)))
  0
  (none))

(defmethod init-from-entity! ((this health) (arg0 entity-actor))
  (initialize-eco this arg0 (pickup-type eco-green) (-> *FACT-bank* health-single-inc))
  (none))

(deftype eco-pill (eco-collectable) ())


(defmethod animate ((this eco-pill))
  (let ((a0-1 (-> this part))
        (a1-0 (-> this root root-prim prim-core)))
    (spawn a0-1 (the-as vector a1-0)))
  (if (nonzero? (-> this sound)) (update! (-> this sound)))
  0
  (none))

(defmethod init-from-entity! ((this eco-pill) (arg0 entity-actor))
  (initialize-eco this arg0 (pickup-type eco-pill) (-> *FACT-bank* health-small-inc))
  (none))

(defmethod deactivate ((this eco-pill))
  (set! *eco-pill-count* (+ *eco-pill-count* -1))
  ((method-of-type eco-collectable deactivate) this)
  (none))

(defmethod initialize ((this eco-pill))
  (set! *eco-pill-count* (+ *eco-pill-count* 1))
  (stack-size-set! (-> this main-thread) 192) ;; og:preserve-this hack increased from 128
  (logior! (-> this mask) (process-mask actor-pause))
  (set! (-> this actor-pause) #t)
  (set! (-> this notify-parent) #f)
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind powerup blue-eco-suck))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set-vector! (-> s4-0 local-sphere) 0.0 3276.8 0.0 8192.0)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> this root) s5-0))
  (set! (-> this fact) (new 'process 'fact-info this (-> this pickup-type) (-> this pickup-amount)))
  this)

(defskelgroup *money-sg*
  money
  money-lod0-jg
  money-idle-ja
  ((money-lod0-mg (meters 20)) (money-lod1-mg (meters 40)) (money-lod2-mg (meters 999999)))
  :bounds (static-spherem 0 0 0 0.6)
  :texture-level 2)

(defskelgroup *fuel-cell-sg*
  fuel-cell
  fuel-cell-lod0-jg
  fuel-cell-idle-ja
  ((fuel-cell-lod0-mg (meters 999999)))
  :bounds (static-spherem 0 1 0 1.6)
  :texture-level 2)

(deftype money (eco-collectable) ())


(defmethod run-logic? ((this money))
  (or (not (logtest? (-> this mask) (process-mask actor-pause)))
      (or (and (nonzero? (-> this draw))
               (logtest? (-> this draw status) (draw-status was-drawn))
               (>= (+ (-> *ACTOR-bank* pause-dist) (-> this root pause-adjust-distance))
                   (vector-vector-distance (-> this root trans) (math-camera-pos))))
          (and (nonzero? (-> this skel)) (!= (-> this skel root-channel 0) (-> this skel channel)))
          (and (nonzero? (-> this draw)) (logtest? (-> this draw status) (draw-status no-skeleton-update))))))

(defmethod deactivate ((this money))
  (when (= (-> this next-state name) 'pickup)
    (if (not (and (-> this entity) (logtest? (-> this entity extra perm status) (entity-perm-status dead))))
      (format #t "money ~A was killed in pickup~%"))
    (process-entity-status! this (entity-perm-status dead) #t))
  ((method-of-type eco-collectable deactivate) this)
  (none))

(defstate wait (money)
  :virtual #t
  :code
    (behavior ()
      (loop
        (quaternion-rotate-y! (-> self root quat) (-> self root quat) (* 40049.777 (seconds-per-frame)))
        (let ((f30-0 (-> self bob-amount)))
          (when (< 0.0 f30-0)
            (set! (-> self root trans y)
                  (+ (-> self base y)
                     (-> self suck-y-offset)
                     (* f30-0 (sin (* 109.22667 (the float (mod (+ (- (current-time) (-> self birth-time)) (-> self bob-offset)) 600)))))))
            (update-transforms! (-> self root))))
        (ja-post)
        ;; og:preserve-this added particle!
        (with-pc
          (if (-> *pc-settings* money-starburst?) (spawn (-> self part) (-> self root root-prim world-sphere))))
        (suspend))))

(defstate notice-blue (money)
  :virtual #t
  :code
    (behavior ((arg0 handle))
      (loop
        (quaternion-rotate-y! (-> self root quat) (-> self root quat) (* 91022.22 (seconds-per-frame)))
        (set! (-> self root trans quad) (-> self base quad))
        (add-blue-motion #t #t #t #f)
        (let ((f30-0 (-> self bob-amount)))
          (if (< 0.0 f30-0)
            (set! (-> self root trans y)
                  (+ (-> self base y)
                     (-> self suck-y-offset)
                     (* f30-0 (sin (* 109.22667 (the float (mod (+ (- (current-time) (-> self birth-time)) (-> self bob-offset)) 600)))))))))
        (transform-post)
        ;; og:preserve-this added particle!
        (with-pc
          (if (-> *pc-settings* money-starburst?) (spawn (-> self part) (-> self root root-prim world-sphere))))
        (suspend))))

(defstate pickup (money)
  :virtual #t
  :code
    (behavior ((arg0 object) (arg1 handle))
      ;; og:preserve-this added
      (if (nonzero? (-> self part)) (kill-and-free-particles (-> self part)))
      (logclear! (-> self mask) (process-mask actor-pause))
      (clear-collide-with-as (-> self root))
      (process-entity-status! self (entity-perm-status dead) #t)
      (convert-to-hud-object self (the-as hud (ppointer->process (-> *hud-parts* money))))))

(defmethod initialize ((this money))
  (stack-size-set! (-> this main-thread) 192) ;; og:preserve-this hack increased from 128
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind powerup blue-eco-suck))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set-vector! (-> s4-0 local-sphere) 0.0 2048.0 0.0 4915.2)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> this root) s5-0))
  (logior! (-> this mask) (process-mask actor-pause))
  (set! (-> this actor-pause) #t)
  (set! (-> this notify-parent) #f)
  (set! (-> this fact) (new 'process 'fact-info this (pickup-type money) (the-as float 1.0)))
  (let ((a0-10 (-> this entity)))
    (if (when a0-10
          (let ((a0-11 (-> a0-10 extra perm task))) (if a0-11 (= a0-11 (game-task none)))))
      (set! (-> this entity extra perm task) (game-task complete))))
  (initialize-skeleton this *money-sg* '())
  (if (-> this entity) (nav-mesh-connect this (-> this root) (the-as nav-control #f)))
  (set-vector! (-> this draw color-mult) 0.8 0.8 0.8 1.0)
  (set-vector! (-> this draw color-emissive) 0.2 0.2 0.2 1.0)
  ;; og:preserve-this added money starburst
  (set! (-> this part) (create-launch-control (-> *part-group-id-table* 64) this))
  this)

(defmethod init-from-entity! ((this money) (arg0 entity-actor))
  (initialize this)
  (process-drawable-from-entity! this (-> this entity))
  (initialize-params this 0 (the-as float 1024.0))
  (update-transforms! (-> this root))
  (go (method-of-object this wait))
  (none))

(defbehavior money-init-by-other money ((arg0 vector) (arg1 vector) (arg2 fact-info) (arg3 entity-actor))
  (let ((s3-0 (-> arg2 pickup-type))
        (f30-0 (-> arg2 pickup-spawn-amount)))
    (set! (-> self entity) arg3)
    (set! (-> self pickup-type) s3-0)
    (set! (-> self pickup-amount) f30-0)
    (initialize self)
    (set! (-> self fact pickup-type) s3-0)
    (set! (-> self fact pickup-amount) f30-0))
  (set! (-> self fact options) (-> arg2 options))
  (set! (-> self notify-parent) #t)
  (set! (-> self root trans quad) (-> arg0 quad))
  (quaternion-identity! (-> self root quat))
  (vector-identity! (-> self root scale))
  (set! (-> self root transv quad) (-> arg1 quad))
  (initialize-params self (seconds 15) (the-as float 1024.0))
  (update-transforms! (-> self root))
  (set! (-> self event-hook) (-> (method-of-object self wait) event))
  (go-virtual wait)
  (none))

(defbehavior money-init-by-other-no-bob money ((arg0 vector) (arg1 vector) (arg2 fact-info) (arg3 float) (arg4 entity-actor))
  (set! (-> self entity) arg4)
  (set! (-> self pickup-type) (the-as pickup-type arg2))
  (set! (-> self pickup-amount) arg3)
  (initialize self)
  (set! (-> self fact pickup-type) (the-as pickup-type arg2))
  (set! (-> self fact pickup-amount) arg3)
  (set! (-> self notify-parent) #t)
  (set! (-> self root trans quad) (-> arg0 quad))
  (quaternion-identity! (-> self root quat))
  (vector-identity! (-> self root scale))
  (set! (-> self root transv quad) (-> arg1 quad))
  (initialize-params self (seconds 15) (the-as float 0.0))
  (logior! (-> self flags) (collectable-flags ignore-blue))
  (update-transforms! (-> self root))
  (set! (-> self event-hook) (-> (method-of-object self wait) event))
  (go-virtual wait)
  (none))

(define *fuel-cell-tune-pos* (new 'static 'vector :w 1000000000.0))

(deftype fuel-cell (eco-collectable)
  ((victory-anim spool-anim)
   (state-object symbol))
  (:states (fuel-cell-clone-anim handle)
   (fuel-cell-spline-slider handle float float)))


(defun fuel-cell-pick-anim ((arg0 process-drawable))
  (let* ((gp-0 (-> arg0 entity extra trans))
         (a0-2 (res-lump-value (-> arg0 entity) 'movie-mask uint128 :time (the-as float -1000000000.0)))
         (a1-1 8)
         (v1-6 (abs (the int (+ (/ (-> gp-0 x) METER_LENGTH) (/ (-> gp-0 z) METER_LENGTH)))))
         (v1-7 (mod v1-6 a1-1)))
    (while (logtest? a0-2 (ash 1 v1-7))
      (set! v1-7 (mod (+ v1-7 1) a1-1)))
    (when *target*
      (cond
        ((logtest? (-> *target* control root-prim prim-core action) (collide-action racer)) (set! v1-7 16))
        ((logtest? (-> *target* control root-prim prim-core action) (collide-action flut)) (set! v1-7 32))))
    (cond
      ((zero? v1-7) (new 'static 'spool-anim :name "fuel-cell-victory" :index 3 :parts 2 :command-list '()))
      ((= v1-7 1) (new 'static 'spool-anim :name "fuel-cell-victory-2" :index 4 :parts 2 :command-list '()))
      ((= v1-7 2) (new 'static 'spool-anim :name "fuel-cell-victory-3" :index 5 :parts 2 :command-list '()))
      ((= v1-7 3) (new 'static 'spool-anim :name "fuel-cell-victory-4" :index 6 :parts 2 :command-list '()))
      ((= v1-7 4) (new 'static 'spool-anim :name "fuel-cell-victory-5" :index 7 :parts 2 :command-list '()))
      ((= v1-7 5) (new 'static 'spool-anim :name "fuel-cell-victory-6" :index 8 :parts 2 :command-list '()))
      ((= v1-7 6) (new 'static 'spool-anim :name "fuel-cell-victory-7" :index 9 :parts 2 :command-list '()))
      ((= v1-7 7) (new 'static 'spool-anim :name "fuel-cell-victory-8" :index 10 :parts 2 :command-list '()))
      ((= v1-7 16) (new 'static 'spool-anim :name "fuel-cell-racer-victory-1" :index 40 :parts 2 :command-list '()))
      ((= v1-7 32) (new 'static 'spool-anim :name "fuel-cell-flut-victory-1" :index 44 :parts 2 :command-list '()))
      (else (new 'static 'spool-anim :name "fuel-cell-victory-3" :index 5 :parts 2 :command-list '())))))

(defbehavior fuel-cell-animate fuel-cell ()
  (let* ((gp-0 self)
         (s5-0 (if (and (nonzero? gp-0) (type-type? (-> gp-0 type) fuel-cell)) gp-0)))
    (cond
      (s5-0
       (set! (-> s5-0 victory-anim) (fuel-cell-pick-anim s5-0))
       (spool-push *art-control* (-> s5-0 victory-anim name) 0 self (the-as float -99.0)))
      (else (let ((v1-5 (fuel-cell-pick-anim self))) (spool-push *art-control* (-> v1-5 name) 0 self (the-as float -99.0))))))
  (when (nonzero? (-> self part))
    (cond
      ((logtest? (-> self draw status) (draw-status hidden no-anim))
       (kill-and-free-particles (-> self part))
       (if (nonzero? (-> self sound)) (kill-and-free-particles (-> self part))))
      (else
       (let* ((gp-1 (-> self root))
              (v1-20 (if (and (nonzero? gp-1) (type-type? (-> gp-1 type) collide-shape)) gp-1))
              (gp-2 (if v1-20 (-> v1-20 root-prim prim-core) (-> self root trans))))
         (spawn (-> self part) (the-as vector gp-2))
         (when (nonzero? (-> self sound))
           (update-trans! (-> self sound) (the-as vector gp-2))
           (update! (-> self sound)))))))
  (set-vector! (-> self draw color-mult) 0.5 0.5 0.5 1.0)
  (set-vector! (-> self draw color-emissive) 0.5 0.5 0.5 1.0)
  0
  (none))

(method-set! fuel-cell 29 fuel-cell-animate)

(defstate wait (fuel-cell)
  :virtual #t
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (local-vars (v0-3 object))
      (when (and (or (= message 'touch) (= message 'attack))
                 (and (logtest? (-> self flags) (collectable-flags can-collect))
                      (time-elapsed? (-> self birth-time) (-> self collect-timeout))
                      (and (not (handle->process (-> *game-info* other-camera-handle)))
                           (not *progress-process*)
                           (!= (-> self next-state name) 'pickup)
                           *target*
                           (not (logtest? (-> *target* state-flags) (state-flags grabbed dying))))))
        (add-setting! 'allow-progress #f 0.0 0)
        (apply-settings *setting-control*)
        (logclear! (-> self mask) (process-mask actor-pause))
        (go-virtual pickup #f (process->handle proc)))
      (cond
        ((= message 'trans)
         (set! (-> self root trans quad) (-> (the-as vector (-> block param 0)) quad))
         (set! (-> self base quad) (-> self root trans quad))
         (update-transforms! (-> self root)))
        ((= message 'pickup)
         (when (!= (-> self next-state name) 'pickup)
           (if (and (> argc 0) (-> block param 0)) (move-to-point! (-> self root) (the-as vector (-> block param 0))))
           (logclear! (-> self mask) (process-mask actor-pause))
           (go-virtual pickup #f (process->handle *target*))))
        ((= message 'collide-shape)
         (if (-> block param 0) (restore-collide-with-as (-> self root)) (clear-collide-with-as (-> self root))))
        ((= message 'movie-pos) (set! v0-3 (-> block param 0)) (set! (-> self movie-pos-index) (the-as int v0-3)) v0-3)
        ((= message 'anim)
         (cond
           ((-> block param 0)
            (set! v0-3 (logclear (-> self flags) (collectable-flags anim)))
            (set! (-> self flags) (the-as collectable-flags v0-3)))
           (else
            (set! v0-3 (logior (-> self flags) (collectable-flags anim)))
            (set! (-> self flags) (the-as collectable-flags v0-3))))
         v0-3)))
  :code
    (behavior ()
      0.5
      (let ((f28-0 0.0))
        (ja :group! fuel-cell-idle-ja)
        (loop
          (let ((f30-0 (vector-vector-distance (-> self base) (target-pos 0))))
            (set! f28-0
                  (if (and (< f30-0 (-> *FACT-bank* suck-suck-dist)) (not (logtest? (-> self flags) (collectable-flags anim))))
                    (seek f28-0 (the-as float 16384.0) (* 3072.0 (seconds-per-frame)))
                    (seek f28-0 (the-as float 0.0) (* 3072.0 (seconds-per-frame)))))
            (set! (-> self root trans y) (+ (-> self base y) (* 2867.2 (sin f28-0))))
            (let ((f30-1 (lerp-scale (the-as float 0.6) (the-as float 0.5) f30-0 (the-as float 8192.0) (-> *FACT-bank* suck-suck-dist))))
              (transform-post)
              (fuel-cell-animate)
              (suspend)
              (ja :num! (loop! f30-1))))))))

(defstate pickup (fuel-cell)
  :virtual #t
  :enter
    (behavior ((arg0 object) (arg1 handle))
      (set-time! (-> self state-time))
      (set! (-> self state-object) #t)
      (let ((t9-1 (-> (the-as (state eco-collectable) (find-parent-state)) enter))) (if t9-1 (t9-1))))
  :trans
    (behavior ()
      (let ((f30-0 (the-as float
                           (cond
                             ((string= (-> self victory-anim name) "fuel-cell-victory") 97.0)
                             ((string= (-> self victory-anim name) "fuel-cell-victory-2") 97.0)
                             ((string= (-> self victory-anim name) "fuel-cell-victory-3") 97.0)
                             ((string= (-> self victory-anim name) "fuel-cell-victory-4") 97.0)
                             ((string= (-> self victory-anim name) "fuel-cell-victory-5") 77.0)
                             ((string= (-> self victory-anim name) "fuel-cell-victory-6") 97.0)
                             ((string= (-> self victory-anim name) "fuel-cell-victory-7") 97.0)
                             ((string= (-> self victory-anim name) "fuel-cell-victory-8") 97.0)
                             ((string= (-> self victory-anim name) "fuel-cell-racer-victory-1") 88.0)
                             ((string= (-> self victory-anim name) "fuel-cell-flut-victory-1") 150.0)
                             (else 5000.0)))))
        (when (and (logtest? (-> self skel status) (janim-status spool)) (and (>= (ja-aframe-num 0) f30-0) (-> self state-object)))
          (set! (-> self state-object) #f)
          (kill-and-free-particles (-> self part))
          (logior! (-> self draw status) (draw-status skip-bones))
          (if (not (or (logtest? (res-lump-value (-> self entity) 'options fact-options :time (the-as float -1000000000.0))
                                 (fact-options powerup))
                       (and *target* (logtest? (-> *target* control root-prim prim-core action) (collide-action racer)))))
            (send-event *camera* 'teleport-to-other-start-string)))))
  :code
    (behavior ((arg0 object) (arg1 handle))
      (local-vars (sv-96 res-tag))
      (sound-play "pu-powercell")
      (clear-collide-with-as (-> self root))
      (logclear! (-> self mask) (process-mask actor-pause))
      (logclear! (-> self draw status) (draw-status hidden))
      (process-entity-status! self (entity-perm-status dead) #t)
      (stop! (-> self sound))
      (while (handle->process (-> *game-info* other-camera-handle))
        (format #t
                "WARNING: fuel-cell stall ~D ~A ~A~%"
                (current-time)
                (handle->process (-> *game-info* other-camera-handle))
                (-> *level* loading-level))
        (spool-push *art-control* (-> self victory-anim name) 0 self (the-as float -99.0))
        (suspend))
      (while (not (send-event *target* 'clone-anim self))
        (spool-push *art-control* (-> self victory-anim name) 0 self (the-as float -99.0))
        (format #t "WARNING: fuel-cell stall on not cloning.~%")
        (suspend))
      (set! sv-96 (new 'static 'res-tag))
      (let* ((v1-34 (res-lump-data (-> self entity) 'movie-pos (inline-array vector) :tag-ptr (& sv-96) :time (the-as float -1000000000.0)))
             (gp-1 (if (and v1-34 (< (-> self movie-pos-index) (the-as int (-> sv-96 elt-count))))
                     (-> v1-34 (-> self movie-pos-index))
                     (the-as vector #f))))
        (cond
          ((and *debug-segment* (< (-> *fuel-cell-tune-pos* w) 1000000000.0))
           (move-to-point! (-> self root) *fuel-cell-tune-pos*)
           (set-yaw-angle-clear-roll-pitch! (-> self root) (-> *fuel-cell-tune-pos* w)))
          ((= (-> self movie-pos-index) -1))
          (gp-1 (move-to-point! (-> self root) gp-1) (set-yaw-angle-clear-roll-pitch! (-> self root) (-> gp-1 w)))
          (else
           (move-to-point! (-> self root) (-> *target* control trans))
           (set-yaw-angle-clear-roll-pitch! (-> self root) (y-angle (-> *target* control)))
           (move-to-ground (-> self root) (the-as float 40960.0) (the-as float 40960.0) #f (collide-kind background)))))
      (spool-push *art-control* (-> self victory-anim name) 0 self (the-as float -99.0))
      (send-event *target* 'get-pickup (-> self fact pickup-type) (-> self fact pickup-amount))
      (set! (-> self draw bounds w) 32768.0)
      (logior! (-> self skel status) (janim-status inited))
      (send-event *target* 'blend-shape #t)
      (add-setting! 'music-volume 'rel (-> *setting-control* current music-volume-movie) 0)
      (add-setting! 'sfx-volume 'rel (-> *setting-control* current sfx-volume-movie) 0)
      (add-setting! 'ambient-volume 'rel (-> *setting-control* current ambient-volume-movie) 0)
      (process-spawn othercam self 10 #f #t :to self)
      (auto-save-command 'auto-save 0 0 *default-pool*)
      (ja-play-spooled-anim (-> self victory-anim)
                            (the-as art-joint-anim fuel-cell-idle-ja)
                            (the-as art-joint-anim #f)
                            (the-as (function process-drawable symbol) false-func))
      (remove-setting! 'music-volume)
      (remove-setting! 'sfx-volume)
      (remove-setting! 'ambient-volume)
      (send-event *target* 'blend-shape #f)
      (send-event *target* 'end-mode)
      (send-event *camera* 'no-intro)
      (send-event *camera* 'clear-entity)
      (ja-channel-set! 0)
      (suspend)
      (suspend)
      (process-spawn-function process
        (lambda :behavior collectable ((arg0 game-task))
          (while (or (-> *setting-control* current ambient)
                     (-> *setting-control* current movie)
                     (-> *setting-control* current hint)
                     (str-is-playing?))
            (suspend))
          (cond
            ((= arg0 (game-task training-buzzer))
             (level-hint-spawn (text-id training-buzzer-resolution) "asstvb45" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task training-door))
             (level-hint-spawn (text-id training-eco-opened-door) "sagevb25" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task beach-ecorocks))
             (level-hint-spawn (text-id beach-ecorocks-resolution) "sagevb01" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task misty-cannon))
             (level-hint-spawn (text-id misty-cannon-resolution) "sagevb02" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task misty-bike))
             (level-hint-spawn (text-id misty-bike-resolution) "asstvb03" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task firecanyon-end))
             (level-hint-spawn (text-id firecanyon-end-resolution) "sksp0095" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task rolling-robbers))
             (level-hint-spawn (text-id rolling-robbers-resolution) "asstvb20" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task rolling-plants))
             (level-hint-spawn (text-id rolling-plants-resolution) "sagevb03" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task swamp-flutflut))
             (level-hint-spawn (text-id swamp-flutflut-resolution) "asstvb21" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task ogre-boss))
             (level-hint-spawn (text-id ogre-boss-resolution) "asstvb23" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task ogre-end))
             (level-hint-spawn (text-id ogre-race-resolution) "asstvb25" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task beach-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task jungle-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task misty-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task firecanyon-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task rolling-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task sunken-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task swamp-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task ogre-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task cave-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task snow-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task lavatube-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task citadel-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task village1-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task village2-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none)))
            ((= arg0 (game-task village3-buzzer))
             (level-hint-spawn (text-id sidekick-buzzer-resolution) "sksp009k" (the-as entity #f) *entity-pool* (game-task none))))
          (none))
        (the int (-> self fact pickup-amount))
        :to
        self)
      (case (the int (-> self fact pickup-amount))
        (((game-task citadel-sage-blue)) (send-event (process-by-name "blue-sagecage-1" *active-pool*) 'play-anim))
        (((game-task citadel-sage-red)) (send-event (process-by-name "red-sagecage-1" *active-pool*) 'play-anim))
        (((game-task citadel-sage-yellow)) (send-event (process-by-name "yellow-sagecage-1" *active-pool*) 'play-anim))
        (((game-task citadel-sage-green)) (send-event (process-by-name "green-sagecage-1" *active-pool*) 'play-anim))
        (((game-task jungle-eggtop) (game-task snow-eggtop) (game-task snow-ball) (game-task sunken-slide)))
        (else (send-event (ppointer->process (-> *hud-parts* fuel-cell)) 'show)))
      (convert-to-hud-object self (the-as hud (ppointer->process (-> *hud-parts* fuel-cell)))))
  :post
    (behavior ()
      (transform-post)
      (if (-> self state-object) (spawn (-> self part) (the-as vector (-> self root root-prim prim-core))))))

(defmethod initialize ((this fuel-cell))
  (stack-size-set! (-> this main-thread) 512)
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind powerup))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set! (-> s4-0 transform-index) 3)
      (set-vector! (-> s4-0 local-sphere) 0.0 0.0 0.0 4915.2)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> this root) s5-0))
  (logior! (-> this mask) (process-mask actor-pause))
  (set! (-> this actor-pause) #t)
  (set! (-> this notify-parent) #f)
  (set! (-> this fact) (new 'process 'fact-info this (pickup-type fuel-cell) (the-as float 0.0)))
  (initialize-skeleton this *fuel-cell-sg* '())
  (set! (-> this base quad) (-> this root trans quad))
  (set! (-> this old-base quad) (-> this root trans quad))
  (set! (-> this part) (create-launch-control (-> *part-group-id-table* 63) this))
  (set! (-> this sound) (new 'process 'ambient-sound (static-sound-spec "powercell-idle" :fo-max 40) (-> this root trans)))
  (set! (-> this victory-anim) (fuel-cell-pick-anim this))
  this)

(defmethod init-from-entity! ((this fuel-cell) (arg0 entity-actor))
  (initialize this)
  (process-drawable-from-entity! this (-> this entity))
  (initialize-params this 0 (the-as float 1024.0))
  (logclear! (-> this fact options) (fact-options can-collect))
  (update-transforms! (-> this root))
  (go (method-of-object this wait))
  (none))

(defbehavior fuel-cell-init-by-other fuel-cell ((arg0 vector) (arg1 vector) (arg2 fact-info) (arg3 entity-actor))
  (let ((s3-0 (-> arg2 pickup-type))
        (f30-0 (-> arg2 pickup-spawn-amount)))
    (set! (-> self entity) arg3)
    (set! (-> self pickup-type) s3-0)
    (set! (-> self pickup-amount) f30-0)
    (initialize self)
    (set! (-> self fact pickup-type) s3-0)
    (set! (-> self fact pickup-amount) f30-0))
  (set! (-> self fact options) (-> arg2 options))
  (set! (-> self notify-parent) #t)
  (set! (-> self root trans quad) (-> arg0 quad))
  (quaternion-identity! (-> self root quat))
  (vector-identity! (-> self root scale))
  (set! (-> self root transv quad) (-> arg1 quad))
  (initialize-params self 0 (the-as float 1024.0))
  (logclear! (-> self fact options) (fact-options can-collect))
  (update-transforms! (-> self root))
  (let ((gp-1 (res-lump-struct (-> self entity) 'movie-pos structure :time (the-as float -1000000000.0))))
    (cond
      ((and *debug-segment* (< (-> *fuel-cell-tune-pos* w) 1000000000.0))
       (set! (-> self jump-pos quad) (-> *fuel-cell-tune-pos* quad))
       (+! (-> self jump-pos y) 4096.0)
       (go-virtual jump))
      ((and gp-1
            (not (logtest? (res-lump-value (-> self entity) 'options fact-options :time (the-as float -1000000000.0))
                           (fact-options skip-jump-anim)))
            (not (logtest? (-> self fact options) (fact-options skip-jump-anim))))
       (set! (-> self jump-pos quad) (-> (the-as vector gp-1) quad))
       (+! (-> self jump-pos y) 4096.0)
       (go-virtual jump))))
  (set! (-> self event-hook) (-> (method-of-object self wait) event))
  (go-virtual wait)
  (none))

(defstate fuel-cell-clone-anim (fuel-cell)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('pickup)
         (when (!= (-> self next-state name) 'pickup)
           (if (and (> argc 0) (-> block param 0)) (move-to-point! (-> self root) (the-as vector (-> block param 0))))
           (logclear! (-> self mask) (process-mask actor-pause))
           (go-virtual pickup #f (the-as handle #f))))
        (('trans)
         (set! (-> self root trans quad) (-> (the-as vector (-> block param 0)) quad))
         (set! (-> self base quad) (-> self root trans quad))
         (update-transforms! (-> self root)))
        (('stop-cloning 'notify)
         (set! (-> self root trans quad) (-> self draw origin quad))
         (set! (-> self base quad) (-> self root trans quad))
         (ja-channel-set! 1)
         (ja :group! fuel-cell-idle-ja)
         (logclear! (-> self draw status) (draw-status hidden))
         (vector-reset! (-> self draw origin))
         (go-virtual wait))))
  :exit
    (behavior ()
      (if (-> self actor-pause) (logior! (-> self mask) (process-mask actor-pause)))
      (logclear! (-> self skel status) (janim-status spool)))
  :code
    (behavior ((arg0 handle))
      (logclear! (-> self mask) (process-mask actor-pause))
      (clone-anim arg0 3 #t "")
      (format #t "ERROR<GMJ>: clone-anim returned in fuel-cell~%")
      (deactivate self))
  :post
    (behavior ()
      (update-transforms! (-> self root))
      (animate self)))

(defbehavior fuel-cell-init-as-clone fuel-cell ((arg0 handle) (arg1 int))
  (initialize self)
  (set! (-> self fact pickup-type) (pickup-type fuel-cell))
  (set! (-> self fact pickup-amount) (the float arg1))
  (initialize-params self 0 (the-as float 1024.0))
  (logclear! (-> self mask) (process-mask actor-pause))
  (set! (-> self actor-pause) #f)
  (sound-play "cell-prize")
  (go fuel-cell-clone-anim arg0)
  (none))

(defskelgroup *buzzer-sg*
  buzzer
  buzzer-lod0-jg
  buzzer-idle-ja
  ((buzzer-lod0-mg (meters 999999)))
  :bounds (static-spherem 0 1 0 1.6)
  :texture-level 2)

(deftype buzzer (eco-collectable)
  ((victory-anim spool-anim)))


(defmethod animate ((this buzzer))
  (quaternion-rotate-y! (-> this root quat) (-> this root quat) (* 40049.777 (seconds-per-frame)))
  (let ((a0-2 (-> this skel root-channel 0)))
    (set! (-> a0-2 param 0) 1.0)
    (joint-control-channel-group-eval! a0-2 (the-as art-joint-anim #f) num-func-loop!))
  (let ((f0-3 (y-angle (-> this root))))
    (set! (-> *part-id-table* 239 init-specs 4 initial-valuef) (+ 16384.0 f0-3))
    (set! (-> *part-id-table* 240 init-specs 4 initial-valuef) (+ 16384.0 f0-3)))
  (spawn (-> this part) (vector<-cspace! (new 'stack-no-clear 'vector) (-> this node-list data 15)))
  (if (nonzero? (-> this sound)) (update! (-> this sound)))
  (if (and *target* (>= (-> *target* fact buzzer) 6.0))
    (spool-push *art-control* (-> this victory-anim name) 0 this (the-as float -99.0)))
  0
  (none))

(defstate wait (buzzer)
  :virtual #t
  :code
    (behavior ()
      (case (get-reminder (get-task-control (the-as game-task (logand (the int (-> self fact pickup-amount)) #xffff))) 0)
        ((127) (go-virtual pickup #t (the-as handle #f))))
      (loop
        (transform-post)
        (animate self)
        (suspend))))

(defstate pickup (buzzer)
  :virtual #t
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('notify) (process-entity-status! self (entity-perm-status dead) #t))))
  :enter
    (behavior ((arg0 object) (arg1 handle))
      (set! (-> self pickup-handle) arg1)
      (logclear! (-> self mask) (process-mask actor-pause)))
  :code
    (behavior ((arg0 object) (arg1 handle))
      (logclear! (-> self mask) (process-mask actor-pause))
      (process-entity-status! self (entity-perm-status complete) #t)
      (sound-play "buzzer-pickup")
      (case (-> (level-get-target-inside *level*) name)
        (('training)
         (level-hint-spawn (text-id training-buzzer-hint) "asstvb44" (the-as entity #f) *entity-pool* (game-task none)))
        (('firecanyon)
         (level-hint-spawn (text-id firecanyon-buzzer-hint) "sksp0096" (the-as entity #f) *entity-pool* (game-task none)))
        (else (level-hint-spawn (text-id sidekick-hint-buzzer3) "sksp009j" (the-as entity #f) *entity-pool* (game-task none))))
      (ja-channel-set! 0)
      (clear-collide-with-as (-> self root))
      (if (nonzero? (-> self sound)) (stop! (-> self sound)))
      (when (not arg0)
        (let ((v1-18 (manipy-spawn (-> self root trans) #f *buzzer-sg* #f :to *entity-pool*)))
          (send-event (ppointer->process v1-18) 'become-hud-object (ppointer->process (-> *hud-parts* buzzers)))))
      (let* ((s5-2 (logand (the int (-> self fact pickup-amount)) #xffff))
             (s4-1 (get-task-control (the-as game-task s5-2))))
        (if (nonzero? s5-2) (close-specific-task! (the-as game-task s5-2) (task-status need-hint)))
        (when (and (= (get-reminder s4-1 0) 127) (and (-> self entity) (not (task-complete? *game-info* (the-as game-task s5-2)))))
          (if (and *target*
                   (logtest? (-> *target* control root-prim prim-core action) (collide-action racer snowball tube flut))
                   (not arg0))
            (logior! (-> self fact options) (fact-options instant-collect skip-jump-anim)))
          (let ((v1-47 (birth-pickup-at-point (vector+! (new 'stack-no-clear 'vector) (-> self root trans) (new 'static 'vector :y 4096.0 :w 1.0))
                                              (pickup-type fuel-cell)
                                              (the float s5-2)
                                              #f
                                              self
                                              (-> self fact))))
            (when v1-47
              (send-event (ppointer->process v1-47) 'movie-pos (-> self movie-pos-index))
              (ja-channel-set! 0)
              (clear-collide-with-as (-> self root))
              (ja-post)
              (while (-> self child)
                (suspend))))))
      (when (-> self notify-parent)
        (let ((gp-1 (new 'stack-no-clear 'event-message-block)))
          (set! (-> gp-1 from) self)
          (set! (-> gp-1 num-params) 1)
          (set! (-> gp-1 message) 'notify)
          (set! (-> gp-1 param 0) (the-as uint 'pickup))
          (let ((s5-3 send-event-function)
                (s4-2 (ppointer->process (-> self parent))))
            (s5-3 (if (and (nonzero? s4-2) (type-type? (-> s4-2 type) process)) s4-2) gp-1))))))

(defmethod initialize ((this buzzer))
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind powerup blue-eco-suck))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set-vector! (-> s4-0 local-sphere) 0.0 2457.6 0.0 4915.2)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> this root) s5-0))
  (logior! (-> this mask) (process-mask actor-pause))
  (set! (-> this actor-pause) #t)
  (set! (-> this notify-parent) #f)
  (set! (-> this fact) (new 'process 'fact-info this (pickup-type buzzer) (the-as float 0.0)))
  (initialize-skeleton this *buzzer-sg* '())
  (set! (-> this part) (create-launch-control (-> *part-group-id-table* 65) this))
  (set! (-> this sound) (new 'process 'ambient-sound (static-sound-spec "buzzer" :fo-max 40) (-> this root trans)))
  (set! (-> this victory-anim) (fuel-cell-pick-anim this))
  this)

(defmethod init-from-entity! ((this buzzer) (arg0 entity-actor))
  (initialize this)
  (process-drawable-from-entity! this (-> this entity))
  (initialize-params this 0 (the-as float 1024.0))
  (set! (-> this collect-timeout) (seconds 2))
  (update-transforms! (-> this root))
  (update-trans! (-> this sound) (-> this root trans))
  (if (and (-> this entity) (logtest? (-> this entity extra perm status) (entity-perm-status complete)))
    (go (method-of-object this wait))
    (go (method-of-object this pickup) #t (the-as handle #f)))
  (none))

(defbehavior buzzer-init-by-other buzzer ((arg0 vector) (arg1 vector) (arg2 fact-info) (arg3 entity-actor))
  (let ((s3-0 (-> arg2 pickup-type))
        (f30-0 (-> arg2 pickup-spawn-amount)))
    (set! (-> self entity) arg3)
    (set! (-> self pickup-type) s3-0)
    (set! (-> self pickup-amount) f30-0)
    (initialize self)
    (set! (-> self fact pickup-type) s3-0)
    (set! (-> self fact pickup-amount) f30-0))
  (set! (-> self fact options) (-> arg2 options))
  (set! (-> self notify-parent) #t)
  (set! (-> self root trans quad) (-> arg0 quad))
  (quaternion-identity! (-> self root quat))
  (vector-identity! (-> self root scale))
  (set! (-> self root transv quad) (-> arg1 quad))
  (initialize-params self 0 (the-as float 1024.0))
  (update-transforms! (-> self root))
  (update-trans! (-> self sound) (-> self root trans))
  (set! (-> self event-hook) (-> (method-of-object self wait) event))
  (go-virtual wait)
  (none))

(defmethod init-from-entity! ((this eco) (arg0 entity-actor))
  (let ((v1-2 (res-lump-value (-> this entity) 'eco-info pickup-type :time (the-as float -1000000000.0))))
    (set! (-> this type)
          (cond
            ((= v1-2 (pickup-type eco-blue)) eco-blue)
            ((= v1-2 (pickup-type eco-red)) eco-red)
            ((= v1-2 (pickup-type eco-yellow)) eco-yellow)
            ((= v1-2 (pickup-type eco-green)) health)
            ((= v1-2 (pickup-type money)) money)
            ((= v1-2 (pickup-type fuel-cell)) fuel-cell)
            ((= v1-2 (pickup-type buzzer)) buzzer)
            (else eco-pill))))
  (init-from-entity! this arg0)
  (none))

(defbehavior birth-pickup-at-point process ((arg0 vector) (arg1 pickup-type) (arg2 float) (arg3 symbol) (arg4 process-tree) (arg5 fact-info))
  (local-vars
    (v1-2 basic)
    (v1-28 symbol)
    (v1-34 symbol)
    (v1-40 symbol)
    (v1-46 symbol)
    (v1-52 symbol)
    (v1-58 symbol)
    (v1-64 symbol)
    (v1-71 symbol)
    (sv-32 fact-info)
    (sv-48 int)
    (sv-64 process)
    (sv-80 process)
    (sv-96 process)
    (sv-112 process)
    (sv-128 process)
    (sv-144 process)
    (sv-160 process)
    (sv-176 process)
    (sv-192 (pointer process)))
  (set! sv-32 arg5)
  (let ((s1-0 (new-stack-vector0))
        (t9-0 (method-of-type res-lump get-property-value-float)))
    (let ((v1-1 sv-32)) (b! (not v1-1) cfg-3 :likely-delay (set! v1-2 sv-32)))
    (set! v1-2 (nonzero? (-> sv-32 process)))
    (label cfg-3)
    (let ((f30-0 (t9-0 (if v1-2 (-> sv-32 process entity))
                       'pickup-radius
                       'interp
                       (the-as float -1000000000.0)
                       (the-as float
                               (cond
                                 ((= arg1 (pickup-type buzzer)) 0.0)
                                 ((= arg2 1.0) 409.6)
                                 (else 8192.0)))
                       (the-as (pointer res-tag) #f)
                       *res-static-buf*)))
      (set! sv-192 (the-as (pointer process) #f))
      (set! sv-48 (the int arg2))
      (let ((s0-0 (new 'static 'fact-info)))
        (set! (-> s0-0 options) (fact-options))
        (if sv-32 (mem-copy! (&-> s0-0 type) (&-> sv-32 type) 40))
        (set! (-> s0-0 pickup-type) arg1)
        (set! (-> s0-0 pickup-spawn-amount) 1.0)
        (while (> sv-48 0)
          (set! sv-48 (+ sv-48 -1))
          (when arg3
            (set-vector! s1-0 0.0 57001.605 f30-0 1.0)
            (vector-rotate-around-y! s1-0 s1-0 (/ (* 65536.0 (the float sv-48)) arg2)))
          (let ((v1-25 arg1))
            (cond
              ((= v1-25 (pickup-type eco-yellow))
               (set! sv-64 (get-process *pickup-dead-pool* eco-yellow #x4000))
               (set! v1-28
                     (when sv-64
                       (set! sv-192 (the-as (pointer process) v1-28))
                       (let ((t9-4 (method-of-type eco-yellow activate)))
                         (t9-4 (the-as eco-yellow sv-64) arg4 'eco-yellow (the-as pointer #x70004000)))
                       (run-now-in-process sv-64 initialize-eco-by-other arg0 s1-0 s0-0)
                       (set! sv-192 (-> sv-64 ppointer))
                       v1-28))
               sv-192)
              ((= v1-25 (pickup-type eco-red))
               (set! sv-80 (get-process *pickup-dead-pool* eco-red #x4000))
               (set! v1-34
                     (when sv-80
                       (set! sv-192 (the-as (pointer process) v1-34))
                       (let ((t9-7 (method-of-type eco-red activate))) (t9-7 (the-as eco-red sv-80) arg4 'eco-red (the-as pointer #x70004000)))
                       (run-now-in-process sv-80 initialize-eco-by-other arg0 s1-0 s0-0)
                       (set! sv-192 (-> sv-80 ppointer))
                       v1-34))
               (level-hint-spawn (text-id misty-eco-red-hint) "sksp0071" (the-as entity #f) *entity-pool* (game-task none)))
              ((= v1-25 (pickup-type eco-blue))
               (set! sv-96 (get-process *pickup-dead-pool* eco-blue #x4000))
               (set! v1-40
                     (when sv-96
                       (set! sv-192 (the-as (pointer process) v1-40))
                       (let ((t9-11 (method-of-type eco-blue activate)))
                         (t9-11 (the-as eco-blue sv-96) arg4 'eco-blue (the-as pointer #x70004000)))
                       (run-now-in-process sv-96 initialize-eco-by-other arg0 s1-0 s0-0)
                       (set! sv-192 (-> sv-96 ppointer))
                       v1-40))
               sv-192)
              ((= v1-25 (pickup-type eco-green))
               (set! sv-112 (get-process *pickup-dead-pool* health #x4000))
               (set! v1-46
                     (when sv-112
                       (set! sv-192 (the-as (pointer process) v1-46))
                       (let ((t9-14 (method-of-type health activate))) (t9-14 (the-as health sv-112) arg4 'health (the-as pointer #x70004000)))
                       (run-now-in-process sv-112 initialize-eco-by-other arg0 s1-0 s0-0)
                       (set! sv-192 (-> sv-112 ppointer))
                       v1-46))
               sv-192)
              ((= v1-25 (pickup-type eco-pill))
               (set! sv-128 (get-process *pickup-dead-pool* eco-pill #x4000))
               (set! v1-52
                     (when sv-128
                       (set! sv-192 (the-as (pointer process) v1-52))
                       (let ((t9-17 (method-of-type eco-pill activate)))
                         (t9-17 (the-as eco-pill sv-128) arg4 'eco-pill (the-as pointer #x70004000)))
                       (run-now-in-process sv-128 initialize-eco-by-other arg0 s1-0 s0-0)
                       (set! sv-192 (-> sv-128 ppointer))
                       v1-52))
               sv-192)
              ((= v1-25 (pickup-type money))
               (set! sv-144 (get-process *pickup-dead-pool* money #x4000))
               (set! v1-58
                     (when sv-144
                       (set! sv-192 (the-as (pointer process) v1-58))
                       (let ((t9-20 (method-of-type money activate))) (t9-20 (the-as money sv-144) arg4 'money (the-as pointer #x70004000)))
                       (run-now-in-process sv-144 money-init-by-other arg0 s1-0 s0-0 (-> self entity))
                       (set! sv-192 (-> sv-144 ppointer))
                       v1-58))
               sv-192)
              ((= v1-25 (pickup-type fuel-cell))
               (set! (-> s0-0 pickup-spawn-amount) arg2)
               (set! sv-160 (get-process *pickup-dead-pool* fuel-cell #x4000))
               (set! v1-64
                     (when sv-160
                       (set! sv-192 (the-as (pointer process) v1-64))
                       (let ((t9-23 (method-of-type fuel-cell activate)))
                         (t9-23 (the-as fuel-cell sv-160) arg4 'fuel-cell (the-as pointer #x70004000)))
                       (run-now-in-process sv-160 fuel-cell-init-by-other arg0 s1-0 s0-0 (-> self entity))
                       (set! sv-192 (-> sv-160 ppointer))
                       v1-64))
               (set! sv-48 0)
               sv-48)
              ((= v1-25 (pickup-type buzzer))
               (set! (-> s0-0 pickup-spawn-amount) arg2)
               (set! sv-176 (get-process *pickup-dead-pool* buzzer #x4000))
               (set! v1-71
                     (when sv-176
                       (set! sv-192 (the-as (pointer process) v1-71))
                       (let ((t9-26 (method-of-type buzzer activate))) (t9-26 (the-as buzzer sv-176) arg4 'buzzer (the-as pointer #x70004000)))
                       (run-now-in-process sv-176 buzzer-init-by-other arg0 s1-0 s0-0 (-> self entity))
                       (set! sv-192 (-> sv-176 ppointer))
                       v1-71))
               (set! sv-48 0)
               sv-48)
              (else (format 0 "ERROR: unknown type of eco ~d~%" arg1) #f)))))))
  sv-192)

(defmethod drop-pickup ((this fact-info) (arg0 symbol) (arg1 process-tree) (arg2 fact-info) (arg3 int))
  (let ((s3-0 (-> this pickup-type))
        (f30-0 (-> this pickup-amount)))
    (when (= s3-0 (pickup-type eco-pill-random))
      f30-0
      (let ((s1-0 (get-death-count *game-info* #f)))
        (set! s3-0 (pickup-type eco-pill))
        (set! f30-0
              (cond
                ((and (= s1-0 1) *target* (and (>= 1.0 (-> *target* fact health)) (rand-vu-percent? (the-as float 0.1))))
                 (set! s3-0 (pickup-type eco-green))
                 1.0)
                ((and (< 1 s1-0) *target* (and (>= 2.0 (-> *target* fact health)) (rand-vu-percent? (the-as float 0.05))))
                 (set! s3-0 (pickup-type eco-green))
                 1.0)
                ((< 20 *eco-pill-count*) (return (the-as (pointer process) #f)) f30-0)
                ((< 10 *eco-pill-count*) 1.0)
                ((type-type? (-> this type) fact-info-enemy)
                 (+ (rand-vu-float-range (the-as float 3.0) (+ 5.0 f30-0)) (the float arg3)))
                (else (+ (rand-vu-float-range (the-as float 2.0) (+ 3.0 f30-0)) (the float arg3)))))))
    (let ((s2-1 (new 'stack-no-clear 'vector)))
      (set! (-> s2-1 quad) (-> this process root trans quad))
      (+! (-> s2-1 y) 12288.0)
      (let ((s1-1 (new 'stack-no-clear 'collide-tri-result)))
        (if (>= (fill-and-probe-using-y-probe *collide-cache*
                                              s2-1
                                              (the-as float 81920.0)
                                              (collide-kind background)
                                              (the-as process-drawable #f)
                                              s1-1
                                              (new 'static 'pat-surface :noentity #x1))
                0.0)
          (set! (-> s2-1 quad) (-> s1-1 intersect quad))
          (set! (-> s2-1 quad) (-> this process root trans quad))))
      (if (= (the-as int s3-0) 6) (+! (-> s2-1 y) 6144.0))
      (birth-pickup-at-point s2-1 (the-as pickup-type s3-0) f30-0 arg0 arg1 this))))

(deftype ecovalve (process-drawable)
  ((root          collide-shape-moving :override)
   (offset        vector :inline)
   (offset-target vector :inline)
   (block-func    (function vent symbol)))
  (:states
   ecovalve-idle))


(defskelgroup *ecovalve-sg*
  ecovalve
  ecovalve-geo-jg
  ecovalve-idle-ja
  ((ecovalve-geo-mg (meters 999999)))
  :bounds (static-spherem 0 1 0 1.6)
  :texture-level 2)

(defstate ecovalve-idle (ecovalve)
  :code
    (behavior ()
      (transform-post)
      (suspend)
      (transform-post)
      (loop
        (if (not ((-> self block-func) (the-as vent (ppointer->process (-> self parent)))))
          (set-vector! (-> self offset-target) 0.0 0.0 0.0 1.0))
        (when (!= (-> self offset-target y) (-> self offset y))
          (vector-seek! (-> self offset) (-> self offset-target) (* 4096.0 (seconds-per-frame)))
          (move-to-point! (-> self root)
                          (vector+! (new 'stack-no-clear 'vector) (-> (the-as process-drawable (-> self parent 0)) root trans) (-> self offset)))
          (transform-post))
        (suspend))))

(defbehavior ecovalve-init-by-other ecovalve ((arg0 (function vent symbol)))
  (stack-size-set! (-> self main-thread) 128)
  (let ((s5-0 (new 'process 'collide-shape-moving self (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-mesh s5-0 (the-as uint 0) (the-as uint 0))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind enemy))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set! (-> s4-0 prim-core action) (collide-action solid))
      (set! (-> s4-0 prim-core offense) (collide-offense touch))
      (set! (-> s4-0 transform-index) 3)
      (set-vector! (-> s4-0 local-sphere) 0.0 3686.4 0.0 6144.0)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> self root) s5-0))
  (if (and *target* (logtest? (-> *target* control root-prim prim-core action) (collide-action racer)))
    (clear-collide-with-as (-> self root)))
  (set! (-> self block-func) arg0)
  (set! (-> self root trans quad) (-> (the-as process-drawable (-> self parent 0)) root trans quad))
  (set-vector! (-> self offset-target) 0.0 -2252.8 0.0 1.0)
  (if (not ((-> self block-func) (the-as vent (ppointer->process (-> self parent)))))
    (set-vector! (-> self offset-target) 0.0 0.0 0.0 1.0))
  (set! (-> self offset quad) (-> self offset-target quad))
  (initialize-skeleton self *ecovalve-sg* '())
  (move-to-point! (-> self root)
                  (vector+! (new 'stack-no-clear 'vector) (-> (the-as process-drawable (-> self parent 0)) root trans) (-> self offset)))
  (go ecovalve-idle)
  (none))

(deftype vent (process-drawable)
  ((root                collide-shape :override)
   (show-particles      symbol)
   (collect-effect      sparticle-launch-group)
   (collect-effect2     sparticle-launch-group)
   (collect-effect-time time-frame)
   (blocker             entity-actor)
   (block-func          (function vent symbol))
   (pickup-handle       handle))
  (:methods
   (initialize (_type_ entity-actor pickup-type) none))
  (:states
   vent-blocked
   (vent-pickup handle)
   vent-wait-for-touch))


(defmethod initialize ((this vent) (arg0 entity-actor) (arg1 pickup-type))
  (stack-size-set! (-> this main-thread) 128)
  (logior! (-> this mask) (process-mask actor-pause))
  (let ((s3-0 (new 'process 'collide-shape this (collide-list-enum hit-by-player))))
    (let ((s2-0 (new 'process 'collide-shape-prim-sphere s3-0 (the-as uint 0))))
      (set! (-> s2-0 prim-core collide-as) (collide-kind powerup))
      (set! (-> s2-0 collide-with) (collide-kind target))
      (set-vector! (-> s2-0 local-sphere) 0.0 4915.2 0.0 6553.6)
      (set-root-prim! s3-0 s2-0))
    (set! (-> s3-0 nav-radius) (* 0.75 (-> s3-0 root-prim local-sphere w)))
    (backup-collide-with-as s3-0)
    (set! (-> this root) s3-0))
  (set! (-> this root trans quad) (-> arg0 extra trans quad))
  (update-transforms! (-> this root))
  (set! (-> this root pause-adjust-distance) 409600.0)
  (set! (-> this fact) (new 'process 'fact-info this arg1 (-> *FACT-bank* eco-full-inc)))
  (set! (-> this block-func) (the-as (function vent symbol) true-func))
  (case (-> this fact pickup-type)
    (((pickup-type eco-blue))
     (set! (-> this part) (create-launch-control (-> *part-group-id-table* 44) this))
     (set! (-> this collect-effect) (-> *part-group-id-table* 67))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 43))
     (set! (-> this sound) (new 'process 'ambient-sound 'eco-bg-blue (-> this root trans))))
    (((pickup-type eco-red))
     (set! (-> this part) (create-launch-control (-> *part-group-id-table* 50) this))
     (set! (-> this collect-effect) (-> *part-group-id-table* 69))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 49))
     (set! (-> this sound) (new 'process 'ambient-sound 'eco-bg-red (-> this root trans))))
    (((pickup-type eco-green))
     (set! (-> this part) (create-launch-control (-> *part-group-id-table* 62) this))
     (set! (-> this collect-effect) (-> *part-group-id-table* 66))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 61))
     (set! (-> this sound) (new 'process 'ambient-sound 'eco-bg-green (-> this root trans))))
    (((pickup-type eco-yellow))
     (set! (-> this part) (create-launch-control (-> *part-group-id-table* 52) this))
     (set! (-> this collect-effect) (-> *part-group-id-table* 68))
     (set! (-> this collect-effect2) (-> *part-group-id-table* 57))
     (set! (-> this sound) (new 'process 'ambient-sound 'eco-bg-yellow (-> this root trans)))))
  (set! (-> this blocker) (entity-actor-lookup (-> this entity) 'alt-actor 0))
  (when (-> this blocker)
    (logior! (-> this fact options) (fact-options vent-blocked))
    (set! (-> this block-func)
          (lambda ((arg0 vent))
            (not (logtest? (-> arg0 blocker extra perm status) (entity-perm-status complete))))))
  (set! (-> this show-particles) #t)
  (when (logtest? (-> this fact options) (fact-options vent-blocked))
    (when (logtest? (-> this fact options) (fact-options vent-valve))
      (case (-> this fact pickup-type)
        (((pickup-type eco-blue))
         (set! (-> this block-func)
               (the-as (function vent symbol) (lambda () (not (task-complete? *game-info* (game-task jungle-eggtop)))))))
        (((pickup-type eco-red))
         (set! (-> this block-func)
               (the-as (function vent symbol) (lambda () (not (task-complete? *game-info* (game-task red-eggtop)))))))
        (((pickup-type eco-yellow))
         (set! (-> this block-func)
               (the-as (function vent symbol) (lambda () (not (task-complete? *game-info* (game-task snow-eggtop))))))))
      (process-spawn ecovalve (-> this block-func) :from *pickup-dead-pool* :to this))
    (if ((-> this block-func) this) (go vent-blocked)))
  (go vent-wait-for-touch)
  (none))

(defbehavior vent-standard-event-handler vent ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (case arg2
    (('show-particles)
     (let ((v0-0 (the-as object (-> arg3 param 0)))) (set! (-> self show-particles) (the-as symbol v0-0)) v0-0))
    (('hide) (set! (-> self block-func) (the-as (function vent symbol) true-func)) (go vent-blocked))))

(defstate vent-wait-for-touch (vent)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (if (and (or (= message 'touch) (= message 'attack))
               (let ((a1-1 (new 'stack-no-clear 'event-message-block)))
                 (set! (-> a1-1 from) self)
                 (set! (-> a1-1 num-params) 2)
                 (set! (-> a1-1 message) 'get-pickup)
                 (set! (-> a1-1 param 0) (the-as uint (-> self fact pickup-type)))
                 (set! (-> a1-1 param 1) (the-as uint (-> self fact pickup-amount)))
                 (and (= (send-event-function proc a1-1) #t)
                      (or (logtest? (-> self fact options) (fact-options powerup)) (send-event proc 'powerup)))))
        (go vent-pickup (process->handle proc)))
      (vent-standard-event-handler proc argc message block))
  :code
    (behavior ()
      (loop
        (let ((a0-0 (-> self part))
              (a1-0 (-> self root trans))
              (gp-0 (-> self sound)))
          (if (and (nonzero? a0-0) (-> self show-particles)) (spawn a0-0 a1-0))
          (if (nonzero? gp-0) (update! gp-0)))
        (suspend))))

(defstate vent-blocked (vent)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('show) (go vent-wait-for-touch))))
  :code
    (behavior ()
      (loop
        (if (not ((-> self block-func) self)) (go vent-wait-for-touch))
        (suspend))))

(defstate vent-pickup (vent)
  :event vent-standard-event-handler
  :code
    (behavior ((arg0 handle))
      (when (-> self show-particles)
        (when (nonzero? (-> self collect-effect))
          (let* ((s5-0 (handle->process arg0))
                 (gp-0 (if (and (nonzero? s5-0) (type-type? (-> s5-0 type) process-drawable)) s5-0)))
            (when gp-0
              (let* ((s4-0 (-> (the-as process-drawable gp-0) root))
                     (s5-1 (if (and (nonzero? s4-0) (type-type? (-> s4-0 type) collide-shape)) s4-0)))
                (when s5-1
                  (process-spawn part-tracker
                                 :init
                                 part-tracker-init
                                 (-> self collect-effect)
                                 -1
                                 part-tracker-track-target
                                 #f
                                 #f
                                 (-> (the-as collide-shape s5-1) root-prim prim-core)
                                 :to
                                 gp-0)
                  (process-spawn part-tracker
                                 :init
                                 part-tracker-init
                                 (-> self collect-effect2)
                                 -1
                                 part-tracker-move-to-target
                                 #f
                                 #f
                                 (-> self root root-prim prim-core)
                                 :to
                                 self)))))))
      (go vent-wait-for-touch)))

(deftype ventyellow (vent) ())


(defmethod init-from-entity! ((this ventyellow) (arg0 entity-actor))
  (initialize this arg0 (pickup-type eco-yellow))
  (none))

(deftype ventred (vent) ())


(defmethod init-from-entity! ((this ventred) (arg0 entity-actor))
  (initialize this arg0 (pickup-type eco-red))
  (none))

(deftype ventblue (vent) ())


(defmethod init-from-entity! ((this ventblue) (arg0 entity-actor))
  (initialize this arg0 (pickup-type eco-blue))
  (none))

(deftype ecovent (vent) ())


(defmethod init-from-entity! ((this ecovent) (arg0 entity-actor))
  (initialize this arg0 (pickup-type eco-blue))
  (none))
