;;-*-Lisp-*-
(in-package goal)

;; name: cam-master.gc
;; name in dgo: cam-master
;; dgos: ENGINE, GAME


;; DECOMP BEGINS

(defmethod camera-master-method-16 ((this camera-master) (arg0 symbol))
  (let ((a2-0 (the-as target (handle->process (-> this focus handle))))
        (v1-4 0)
        )
    (if a2-0
        (set! v1-4 (logand (the-as int (-> a2-0 control pat-ignore-mask)) 112))
        )
    (logior (if arg0
                #x9010002
                #x9000002
                )
            v1-4
            )
    )
  )

(defbehavior reset-follow camera-master ()
  (let ((a0-1 (handle->process (-> self focus handle))))
    (when (the-as process-focusable a0-1)
      (set! (-> self tpos-old quad) (-> (get-trans (the-as process-focusable a0-1) 4) quad))
      (set! (-> self tpos-curr quad) (-> self tpos-old quad))
      (set! (-> self tpos-old-adj quad) (-> self tpos-old quad))
      (set! (-> self tpos-curr-adj quad) (-> self tpos-old quad))
      (set! (-> self tpos-tgt quad) (-> self tpos-old quad))
      (set! (-> self upspeed) 0.0)
      )
    )
  )

;; WARN: Return type mismatch none vs symbol.
(defbehavior reset-target-tracking camera-master ()
  (let ((gp-0 (handle->process (-> self focus handle))))
    (the-as
      symbol
      (when gp-0
        (set! (-> self tpos-old quad) (-> (get-trans (the-as process-focusable gp-0) 4) quad))
        (set! (-> self tpos-curr quad) (-> self tpos-old quad))
        (set! (-> self tpos-old-adj quad) (-> self tpos-old quad))
        (set! (-> self tpos-curr-adj quad) (-> self tpos-old quad))
        (set! (-> self tpos-tgt quad) (-> self tpos-old quad))
        (quaternion->matrix (-> self tgt-rot-mat) (get-quat (the-as process-focusable gp-0) 2))
        (quaternion->matrix (-> self tgt-face-mat) (get-quat (the-as process-focusable gp-0) 1))
        (vector-reset! (-> self pitch-off))
        (set! (-> self upspeed) 0.0)
        (set! (-> self on-ground)
              (not (logtest? (-> (the-as process-focusable gp-0) focus-status) (focus-status in-air)))
              )
        (set! (-> self on-pole) #f)
        (set! (-> self ease-t) 1.0)
        (set! (-> self string-max target y) (-> self settings string-max-height))
        (set! (-> self string-max target z) (-> self settings string-max-length))
        (set! (-> self string-push-z) (fmax (-> self string-min value z) (-> *CAMERA-bank* default-string-push-z)))
        (cond
          ((time-elapsed? (get-notice-time (the-as process-focusable gp-0)) (-> *CAMERA-bank* attack-timeout))
           (set! (-> self being-attacked) #f)
           )
          (else
            (set-time! (-> self attack-start))
            (set! (-> self being-attacked) #t)
            (when (or (!= (-> last-try-to-look-at-data horz) 0.0) (!= (-> last-try-to-look-at-data vert) 0.0))
              (set! (-> self string-max target y) (fmax (-> self string-max target y) (-> last-try-to-look-at-data vert)))
              (set! (-> self string-max target z) (fmax (-> self string-max target z) (-> last-try-to-look-at-data horz)))
              (set! (-> self string-push-z) (fmax (-> self string-push-z) (-> self string-max target z)))
              )
            )
          )
        (cond
          ((focus-test? (the-as process-focusable gp-0) under-water)
           (set! (-> self under-water) 2)
           )
          (else
            (set! (-> self under-water) 0)
            0
            )
          )
        (let ((gp-1 (new 'stack-no-clear 'vector)))
          (vector--float*! gp-1 (-> self tpos-curr-adj) (-> self local-down) (-> self settings target-height))
          (tracking-spline-method-10 (-> self target-spline) gp-1)
          )
        )
      )
    )
  )

;; WARN: Return type mismatch object vs symbol.
(defbehavior master-track-target camera-master ()
  (let ((gp-0 (handle->process (-> self focus handle))))
    (the-as
      symbol
      (cond
        ((and *target* (not gp-0))
         (try-update-focus (-> self focus) *target*)
         (logior! (-> self master-options) (cam-master-options-u32 HAVE_TARGET))
         (reset-target-tracking)
         )
        ((and (logtest? (-> self master-options) (cam-master-options-u32 HAVE_TARGET)) (not gp-0))
         (let ((v0-1 (the-as object (logclear (-> self master-options) (cam-master-options-u32 HAVE_TARGET)))))
           (set! (-> self master-options) (the-as cam-master-options-u32 v0-1))
           v0-1
           )
         )
        ((paused?)
         #f
         )
        (gp-0
          (logior! (-> self master-options) (cam-master-options-u32 HAVE_TARGET))
          (cond
            ((time-elapsed? (get-notice-time (the-as target gp-0)) (-> *CAMERA-bank* attack-timeout))
             (set! (-> self being-attacked) #f)
             )
            (else
              (if (not (-> self being-attacked))
                  (set-time! (-> self attack-start))
                  )
              (set! (-> self being-attacked) #t)
              (when (or (!= (-> last-try-to-look-at-data horz) 0.0) (!= (-> last-try-to-look-at-data vert) 0.0))
                (set! (-> self string-max target y) (fmax (-> self string-max target y) (-> last-try-to-look-at-data vert)))
                (set! (-> self string-max target z) (fmax (-> self string-max target z) (-> last-try-to-look-at-data horz)))
                (set! (-> self string-push-z) (fmax (-> self string-push-z) (-> self string-max target z)))
                )
              )
            )
          (cond
            ((focus-test? (the-as target gp-0) under-water)
             (set! (-> self under-water) 2)
             )
            ((> (-> self under-water) 0)
             (+! (-> self under-water) -1)
             )
            )
          (set! (-> self tpos-old quad) (-> self tpos-curr quad))
          (set! (-> self tpos-old-adj quad) (-> self tpos-curr-adj quad))
          (quaternion->matrix (-> self tgt-rot-mat) (get-quat (the-as target gp-0) 2))
          (quaternion->matrix (-> self tgt-face-mat) (get-quat (the-as target gp-0) 1))
          (cond
            ((< (-> self ease-t) 1.0)
             (new 'stack-no-clear 'vector)
             (cond
               ((logtest? (-> self master-options) (cam-master-options-u32 HAVE_EASE_TO_POS))
                (vector-lerp!
                  (-> self tpos-curr)
                  (-> self ease-from)
                  (-> self ease-to)
                  (parameter-ease-sin-clamp (-> self ease-t))
                  )
                (logclear! (-> self master-options) (cam-master-options-u32 HAVE_EASE_TO_POS))
                )
               (else
                 (vector-lerp!
                   (-> self tpos-curr)
                   (-> self ease-from)
                   (get-trans (the-as target gp-0) 4)
                   (parameter-ease-sin-clamp (-> self ease-t))
                   )
                 )
               )
             (+! (-> self ease-t) (-> self ease-step))
             )
            (else
              (set! (-> self tpos-curr quad) (-> (get-trans (the-as target gp-0) 4) quad))
              )
            )
          (when (focus-test? (the-as target gp-0) edge-grab)
            (if *display-cam-los-debug*
                (format *stdcon* "ride edge~%")
                )
            (let ((s5-6 (new 'stack-no-clear 'collide-query)))
              (vector--float*!
                (-> s5-6 start-pos)
                (-> self tpos-curr)
                (-> self local-down)
                (-> self settings target-height)
                )
              (vector-float*! (-> s5-6 move-dist) (-> self tgt-rot-mat vector 2) 4915.2)
              (vector-! (-> s5-6 start-pos) (-> s5-6 start-pos) (-> s5-6 move-dist))
              (let ((s4-4 s5-6))
                (set! (-> s4-4 radius) 4300.8)
                (set! (-> s4-4 collide-with) (collide-spec backgnd obstacle hit-by-others-list camera-blocker pusher))
                (set! (-> s4-4 ignore-process0) #f)
                (set! (-> s4-4 ignore-process1) #f)
                (set! (-> s4-4 ignore-pat) (the-as pat-surface (camera-master-method-16 self #t)))
                (set! (-> s4-4 action-mask) (collide-action solid))
                )
              (let ((f0-16 (fill-and-probe-using-line-sphere *collide-cache* s5-6)))
                (if (and (< 0.0 f0-16) (< f0-16 1.0))
                    (vector+float*! (-> self tpos-curr) (-> self tpos-curr) (-> s5-6 move-dist) (+ -1.0 f0-16))
                    )
                )
              )
            )
          (set! (-> self on-ground) (not (logtest? (-> (the-as target gp-0) focus-status) (focus-status in-air))))
          (let ((s5-7 (new-stack-vector0)))
            0.0
            (cond
              ((and (focus-test? (the-as target gp-0) in-air)
                    (not (logtest? (focus-status halfpipe super) (-> (the-as target gp-0) focus-status)))
                    )
               (if *display-cam-los-debug*
                   (format *stdcon* "air tracking~%")
                   )
               (vector+float*! (-> self tpos-curr-adj) (-> self tpos-curr-adj) (-> self local-down) (-> self upspeed))
               (vector+float*! (-> self tpos-tgt) (-> self tpos-tgt) (-> self local-down) (-> self upspeed))
               (vector-! s5-7 (-> self tpos-curr) (-> self tpos-tgt))
               (let ((f30-0 (vector-dot s5-7 (-> self local-down))))
                 (vector--float*! s5-7 s5-7 (-> self local-down) f30-0)
                 (if (< 0.0 f30-0)
                     (set! (-> self upspeed) (/ (-> self upspeed) 2))
                     )
                 (vector+! (-> self tpos-tgt) (-> self tpos-tgt) s5-7)
                 (let ((f0-26 (/ f30-0 20)))
                   (vector+float*! (-> self tpos-tgt) (-> self tpos-tgt) (-> self local-down) f0-26)
                   )
                 )
               (vector-! s5-7 (-> self tpos-curr-adj) (-> self tpos-tgt))
               (let* ((f0-28 (vector-dot s5-7 (-> self local-down)))
                      (f0-29 (if (< 0.0 f0-28)
                                 (* f0-28 (-> *CAMERA_MASTER-bank* up-move-to-pitch-ratio-in-air))
                                 (* f0-28 (-> *CAMERA_MASTER-bank* down-move-to-pitch-ratio-in-air))
                                 )
                             )
                      )
                 (vector+float*! (-> self tpos-curr-adj) (-> self tpos-tgt) (-> self local-down) f0-29)
                 )
               (vector-! s5-7 (get-trans (the-as target gp-0) 1) (-> self tpos-curr-adj))
               (let* ((f0-31 (vector-dot s5-7 (-> self local-down)))
                      (f0-32 (* 0.03 f0-31))
                      )
                 (if (and (< f0-32 0.0) (< f0-32 (-> self upspeed)))
                     (set! (-> self upspeed) f0-32)
                     )
                 )
               )
              (else
                (if *display-cam-los-debug*
                    (format *stdcon* "ground tracking~%")
                    )
                (vector-! s5-7 (-> self tpos-curr) (-> self tpos-old))
                (let ((f0-34 (vector-dot s5-7 (-> self local-down))))
                  (cond
                    ((and (focus-test? (the-as target gp-0) touch-water)
                          (not (logtest? (focus-status mech) (-> (the-as target gp-0) focus-status)))
                          )
                     (set! (-> self upspeed) 0.0)
                     )
                    ((< 0.0 f0-34)
                     (set! (-> self upspeed) 0.0)
                     )
                    (else
                      (set! (-> self upspeed) f0-34)
                      )
                    )
                  )
                (set! (-> self tpos-tgt quad) (-> self tpos-curr quad))
                (vector-! s5-7 (-> self tpos-curr-adj) (-> self tpos-curr))
                (let* ((f0-38 (vector-dot s5-7 (-> self local-down)))
                       (f0-39 (cond
                                ((logtest? (cam-slave-options RAPID_TRACKING) (-> self settings slave-options))
                                 0.0
                                 )
                                ((< 0.0 f0-38)
                                 (* f0-38 (-> *CAMERA_MASTER-bank* up-move-to-pitch-on-ground))
                                 )
                                (else
                                  (* f0-38 (-> *CAMERA_MASTER-bank* down-move-to-pitch-on-ground))
                                  )
                                )
                              )
                       )
                  (vector+float*! (-> self tpos-curr-adj) (-> self tpos-curr) (-> self local-down) f0-39)
                  )
                )
              )
            )
          (if (not (logtest? (-> self settings slave-options) (cam-slave-options JUMP_PITCHES)))
              (reset-follow)
              )
          (when (and (focus-test? (the-as target gp-0) on-water under-water)
                     (not (logtest? (focus-status mech) (-> (the-as target gp-0) focus-status)))
                     )
            (let ((f0-41 (- (get-water-height (the-as target gp-0)) (-> self settings target-height))))
              (if (< (-> self tpos-curr-adj y) f0-41)
                  (set! (-> self tpos-curr-adj y) f0-41)
                  )
              )
            )
          (vector+! (-> self pitch-off) (-> self pitch-off) (-> self tpos-curr))
          (vector-! (-> self pitch-off) (-> self pitch-off) (-> self tpos-old))
          (vector-float*! (-> self pitch-off) (-> self pitch-off) (-> *CAMERA_MASTER-bank* pitch-off-blend))
          (let ((s5-8 (new 'stack-no-clear 'vector)))
            (vector--float*! s5-8 (-> self tpos-curr-adj) (-> self local-down) (-> self settings target-height))
            (let ((s4-7 (new 'stack-no-clear 'vector)))
              0.0
              (vector-! s4-7 (get-trans (the-as target gp-0) 1) s5-8)
              (let* ((f0-46 (vector-dot s4-7 (-> self local-down)))
                     (f0-47 (+ -4096.0 f0-46))
                     )
                (if (< f0-47 0.0)
                    (vector+float*! s5-8 s5-8 (-> self local-down) f0-47)
                    )
                )
              )
            (tracking-spline-method-17 (-> self target-spline) s5-8 2048.0 0.0 #f)
            )
          (tracking-spline-method-22 (-> self target-spline) 40960.0)
          )
        )
      )
    )
  )

(defun setup-slave-for-hopefull ((arg0 camera-slave))
  (when (= (-> arg0 blend-to-type) (camera-blend-to-type unknown-2))
    (cam-calc-follow! (-> arg0 tracking) (-> arg0 trans) #f)
    (slave-set-rotation! (-> arg0 tracking) (-> arg0 trans) (-> arg0 options) (-> arg0 fov) #f)
    )
  (none)
  )

(defbehavior master-is-hopeful-better? camera-master ((arg0 camera-slave) (arg1 camera-slave))
  (cond
    ((not *camera-combiner*)
     #f
     )
    ((not arg0)
     #t
     )
    (else
      (< (vector-dot (-> arg0 tracking inv-mat vector 2) (-> *camera-combiner* inv-camera-rot vector 2))
         (vector-dot (-> arg1 tracking inv-mat vector 2) (-> *camera-combiner* inv-camera-rot vector 2))
         )
      )
    )
  )

(defbehavior master-choose-entity camera-master ((arg0 cam-setting-data))
  (local-vars
    (v1-22 symbol)
    (sv-96 res-tag)
    (sv-112 process)
    (sv-128 (pointer process))
    (sv-144 int)
    (sv-160 string)
    (sv-176 string)
    (sv-192 uint)
    )
  (let ((s5-0 (entity-by-name (-> arg0 entity-name))))
    (set! (-> arg0 real-entity-name) #f)
    (when s5-0
      (let ((s2-0 (cam-state-from-entity s5-0)))
        (cond
          (s2-0
            (set! (-> arg0 real-entity-name) (-> arg0 entity-name))
            (set! (-> arg0 cam-mode) (the-as symbol s2-0))
            (if (-> arg0 teleport-on-entity-change)
                (send-event *camera* 'teleport)
                )
            )
          (else
            (format 0 "ERROR <GMJ>: camera entity '~S' didn't produce a state~%" (res-lump-struct s5-0 'name structure))
            )
          )
        (set! sv-96 (new 'static 'res-tag))
        (let ((s4-1 (res-lump-data s5-0 'alternates pointer :tag-ptr (& sv-96))))
          (when s4-1
            (let* ((s1-1 (get-process *camera-dead-pool* camera-slave #x4000))
                   (s3-1 (when s1-1
                           (let ((t9-7 (method-of-type camera-slave activate)))
                             (t9-7
                               (the-as camera-slave s1-1)
                               *camera*
                               (symbol->string (-> camera-slave symbol))
                               (the-as pointer #x70004000)
                               )
                             )
                           (run-now-in-process s1-1 cam-slave-init s2-0 s5-0)
                           (the-as (pointer camera-slave) (-> s1-1 ppointer))
                           )
                         )
                   )
              (if s3-1
                  (setup-slave-for-hopefull (the-as camera-slave (ppointer->process s3-1)))
                  (format 0 "ERROR <GMJ>: primary region activate failed~%")
                  )
              (dotimes (s2-1 (the-as int (-> sv-96 elt-count)))
                (let ((s0-0 (entity-by-name (the-as string (-> (the-as (pointer uint32) (&+ s4-1 (* s2-1 4))))))))
                  (cond
                    (s0-0
                      (let ((s1-2 (cam-state-from-entity s0-0)))
                        (cond
                          (s1-2
                            (set! sv-112 (get-process *camera-dead-pool* camera-slave #x4000))
                            (set! v1-22 (when sv-112
                                          (set! sv-128 (the-as (pointer process) v1-22))
                                          (let ((t9-14 (method-of-type camera-slave activate)))
                                            (t9-14
                                              (the-as camera-slave sv-112)
                                              *camera*
                                              (symbol->string (-> camera-slave symbol))
                                              (the-as pointer #x70004000)
                                              )
                                            )
                                          (run-now-in-process sv-112 cam-slave-init s1-2 s0-0)
                                          (set! sv-128 (-> sv-112 ppointer))
                                          v1-22
                                          )
                                  )
                            (cond
                              (sv-128
                                (setup-slave-for-hopefull (the-as camera-slave (ppointer->process sv-128)))
                                (cond
                                  ((master-is-hopeful-better?
                                     (the-as camera-slave (ppointer->process s3-1))
                                     (the-as camera-slave (ppointer->process sv-128))
                                     )
                                   (if s3-1
                                       (deactivate (-> s3-1 0))
                                       )
                                   (set! s3-1 (the-as (pointer camera-slave) sv-128))
                                   (set! (-> arg0 real-entity-name) (the-as string (-> (the-as (pointer uint32) (&+ s4-1 (* s2-1 4))))))
                                   (set! (-> arg0 cam-mode) (the-as symbol s1-2))
                                   )
                                  (else
                                    (deactivate (-> sv-128 0))
                                    )
                                  )
                                )
                              (else
                                (format 0 "ERROR <GMJ>: alternate region activate failed~%")
                                )
                              )
                            )
                          (else
                            (let ((s1-5 format))
                              (set! sv-144 0)
                              (set! sv-160 "ERROR <GMJ>: alternate camera region '~S' didn't produce a state~%")
                              (let ((a2-14 (res-lump-struct s0-0 'name structure)))
                                (s1-5 sv-144 sv-160 a2-14)
                                )
                              )
                            )
                          )
                        )
                      )
                    (else
                      (let ((s1-7 format)
                            (s0-1 0)
                            )
                        (set! sv-176 "ERROR <GMJ>: alternate '~S' not found for '~S'~%")
                        (set! sv-192 (-> (the-as (pointer uint32) (&+ s4-1 (* s2-1 4)))))
                        (let ((a3-8 (res-lump-struct s5-0 'name structure)))
                          (s1-7 s0-1 sv-176 sv-192 a3-8)
                          )
                        )
                      )
                    )
                  )
                )
              (if s3-1
                  (deactivate (-> s3-1 0))
                  )
              )
            )
          )
        )
      )
    )
  (cond
    ((-> arg0 real-entity-name)
     #f
     )
    ((-> arg0 mode-name)
     (let ((s5-1 (-> arg0 mode-name value)))
       (set! (-> arg0 cam-mode) (the-as symbol (if (type? s5-1 state)
                                                   s5-1
                                                   )
                                        )
             )
       )
     (set! (-> arg0 real-entity-name) #f)
     #f
     )
    (else
      (set! (-> arg0 cam-mode) (the-as symbol cam-free-floating))
      (set! (-> arg0 real-entity-name) #f)
      #f
      )
    )
  )

(defun cam-master-set-entity ((arg0 cam-setting-data))
  (if (-> arg0 entity-or-mode-changed)
      (master-choose-entity arg0)
      )
  (let ((s5-0 (entity-by-name (-> arg0 entity-name))))
    (when s5-0
      (set! (-> arg0 fov) (cam-slave-get-fov s5-0))
      (set! (-> arg0 string-min-height)
            (cam-slave-get-float s5-0 'stringMinHeight (-> *CAMERA-bank* default-string-min-y))
            )
      (set! (-> arg0 string-max-height)
            (cam-slave-get-float s5-0 'stringMaxHeight (-> *CAMERA-bank* default-string-max-y))
            )
      (set! (-> arg0 string-min-length)
            (cam-slave-get-float s5-0 'stringMinLength (-> *CAMERA-bank* default-string-min-z))
            )
      (let ((f0-8 (cam-slave-get-float s5-0 'stringMaxLength (-> *CAMERA-bank* default-string-max-z))))
        (if (< 405504.0 f0-8)
            (set! f0-8 (-> *CAMERA-bank* default-string-max-z))
            )
        (set! (-> arg0 string-max-length) f0-8)
        )
      (set! (-> arg0 string-default) #f)
      (set! (-> arg0 string-cliff-height) (cam-slave-get-float s5-0 'stringCliffHeight 163840.0))
      (let ((a1-5 (new 'stack-no-clear 'vector)))
        (when (cam-slave-get-vector-with-offset (the-as entity-actor s5-0) a1-5 'interesting)
          )
        )
      (set! (-> arg0 interp-time) (the-as uint (the int (* 300.0 (cam-slave-get-interp-time s5-0)))))
      (let ((s4-0 (method-of-type res-lump get-property-value))
            (s3-0 s5-0)
            )
        (format (clear *res-key-string*) "~S~S" 'flags '-on)
        (let ((s4-1 (s4-0
                      s3-0
                      (string->symbol *res-key-string*)
                      'interp
                      -1000000000.0
                      (the-as uint128 0)
                      (the-as (pointer res-tag) #f)
                      *res-static-buf*
                      )
                    )
              (s3-1 (method-of-type res-lump get-property-value))
              )
          (format (clear *res-key-string*) "~S~S" 'flags '-off)
          (let ((v1-19 (s3-1
                         s5-0
                         (string->symbol *res-key-string*)
                         'interp
                         -1000000000.0
                         (the-as uint128 0)
                         (the-as (pointer res-tag) #f)
                         *res-static-buf*
                         )
                       )
                )
            (logior! (-> arg0 slave-options) s4-1)
            (logclear! (-> arg0 slave-options) v1-19)
            )
          )
        )
      )
    )
  0
  (none)
  )

(defun cam-master-activate-slave ((arg0 symbol))
  (when (and *camera* (or arg0 (not (-> *camera* slave)) (-> *camera* settings entity-or-mode-changed)))
    (when (and arg0 (-> *camera* slave))
      (deactivate (-> *camera* slave 0))
      (set! (-> *camera* slave) (the-as (pointer camera-slave) #f))
      )
    (let* ((s5-0 (-> *camera* settings))
           (gp-0 (entity-by-name (-> s5-0 real-entity-name)))
           (s5-1 (the-as object (-> s5-0 cam-mode)))
           )
      (if (not (the-as symbol s5-1))
          (set! s5-1 cam-free-floating)
          )
      (send-event
        *camera*
        'set-slave
        (ppointer->process
          (process-spawn camera-slave :init cam-slave-init s5-1 gp-0 :from *camera-dead-pool* :to *camera*)
          )
        )
      )
    )
  0
  (none)
  )

(defstate cam-master-active (camera-master)
  :event (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
    (local-vars (v0-0 object) (v1-125 uint))
    (rlet ((vf0 :class vf))
      (init-vf0-vector)
      (case message
        (('dist-from-interp-src)
         (cond
           ((not *camera-combiner*)
            #x48c80000
            )
           ((= (-> *camera-combiner* interp-val) 0.0)
            0
            )
           (else
             (-> *camera-combiner* dist-from-src)
             )
           )
         )
        (('dist-from-interp-dest)
         (cond
           ((not *camera-combiner*)
            0
            )
           ((= (-> *camera-combiner* interp-val) 0.0)
            #x48c80000
            )
           (else
             (-> *camera-combiner* dist-from-dest)
             )
           )
         )
        (('level-deactivate)
         (format 0 "ERROR <GMJ>: *camera* level-deactivate event not supported anymore~%")
         )
        (('clear-entity)
         (format 0 "ERROR <GMJ>: *camera* clear-entity event not supported anymore~%")
         )
        (('no-intro)
         (format 0 "ERROR <GMJ>: *camera* no-intro event not supported anymore '~S'~%" (-> block param 0))
         )
        (('force-blend)
         (format 0 "ERROR <GMJ>: *camera* force-blend event not supported anymore '~S'~%" (-> block param 0))
         )
        (('teleport-to-transformq)
         (when (> argc 0)
           (let ((gp-1 (the-as object (-> block param 0))))
             (when (-> self slave)
               (deactivate (-> self slave 0))
               (set! (-> self slave) (the-as (pointer camera-slave) #f))
               )
             (set! (-> *camera-combiner* trans quad) (-> (the-as matrix gp-1) vector 0 quad))
             (quaternion->matrix (-> *camera-combiner* inv-camera-rot) (the-as quaternion (+ (the-as uint gp-1) 16)))
             )
           (send-event self 'teleport)
           (cam-master-activate-slave #f)
           #t
           )
         )
        (('teleport-to-other-start-string)
         (let ((gp-2 (new 'stack-no-clear 'vector)))
           (when (-> self slave)
             (deactivate (-> self slave 0))
             (set! (-> self slave) (the-as (pointer camera-slave) #f))
             )
           (set! (-> *camera-combiner* trans quad) (-> *camera-other-trans* quad))
           (vector-! gp-2 (-> self tpos-curr-adj) *camera-other-trans*)
           (vector-normalize! gp-2 1.0)
           (forward-down->inv-matrix (-> *camera-combiner* inv-camera-rot) gp-2 (new 'static 'vector :y -1.0))
           )
         (send-event self 'teleport)
         (cam-master-activate-slave #f)
         )
        (('teleport-to-vector-start-string)
         (when (> argc 0)
           (let ((s5-0 (the-as object (-> block param 0)))
                 (gp-3 (new 'stack-no-clear 'vector))
                 )
             (when (-> self slave)
               (deactivate (-> self slave 0))
               (set! (-> self slave) (the-as (pointer camera-slave) #f))
               )
             (set! (-> *camera-combiner* trans quad) (-> (the-as vector s5-0) quad))
             (vector-! gp-3 (-> self tpos-curr-adj) (the-as vector s5-0))
             (vector-normalize! gp-3 1.0)
             (forward-down->inv-matrix (-> *camera-combiner* inv-camera-rot) gp-3 (new 'static 'vector :y -1.0))
             )
           (send-event self 'teleport)
           (cam-master-activate-slave #f)
           )
         )
        (('change-target)
         (let ((a1-15 (-> block param 0)))
           (cond
             ((not a1-15)
              (clear-focused (-> self focus))
              (logclear! (-> self master-options) (cam-master-options-u32 HAVE_TARGET))
              )
             (else
               (try-update-focus (-> self focus) (the-as process-focusable a1-15))
               (logior! (-> self master-options) (cam-master-options-u32 HAVE_TARGET))
               (reset-target-tracking)
               )
             )
           )
         (set! (-> *camera-combiner* tracking no-follow) #f)
         #f
         )
        (('intro-done?)
         (or (not (-> self slave)) (>= (-> self slave 0 intro-t) 1.0))
         )
        (('query-state)
         (and (-> self slave) (= (-> self slave 0 next-state) (-> block param 0)))
         )
        (('change-to-entity-by-name)
         (format
           0
           "ERROR <GMJ>: *camera* change-to-entity-by-name event not supported anymore '~S'~%"
           (-> block param 0)
           )
         )
        (('change-state)
         (format 0 "ERROR <GMJ>: *camera* change-state event not supported anymore ~A~%" (-> block param 0))
         )
        (('set-slave)
         (let ((s5-1 (process->ppointer (the-as process (-> block param 0))))
               (s4-0 (-> self settings interp-time))
               (gp-4 (-> self slave))
               )
           (when (and s5-1 (!= s5-1 gp-4))
             (set! (-> self slave) (the-as (pointer camera-slave) s5-1))
             (logior! (-> self master-options) (cam-master-options-u32 SET_COMBINER_AXIS))
             (set! (-> *camera-combiner* tracking tilt-adjust target) (-> self slave 0 tracking tilt-adjust target))
             (cond
               ((or (zero? s4-0) (not gp-4))
                (if *math-camera*
                    (set! (-> *math-camera* reset) 1)
                    )
                (send-event *camera-combiner* 'set-interpolation 0)
                (send-event *camera-combiner* 'stop-tracking)
                (if (= (-> (the-as camera-slave (-> s5-1 0)) blend-to-type) (camera-blend-to-type unknown-2))
                    (send-event *camera-combiner* 'start-tracking (ppointer->process s5-1))
                    )
                )
               ((begin
                  (when (< 0.0 (-> gp-4 0 intro-t-step))
                    (set! (-> self outro-t) (-> gp-4 0 intro-t))
                    (set! (-> self outro-t-step) (/ -5.0 (the float s4-0)))
                    (set! (-> self outro-exit-value) (-> gp-4 0 outro-exit-value))
                    (curve-copy! (-> self outro-curve) (-> gp-4 0 intro-curve))
                    )
                  (if (-> self settings no-intro)
                      (set! (-> self outro-t) 0.0)
                      )
                  (send-event *camera-combiner* 'set-interpolation s4-0)
                  (cond
                    ((zero? (-> gp-4 0 blend-from-type))
                     (send-event (ppointer->process (-> self decel)) 'change-state cam-fixed)
                     (send-event *camera-combiner* 'stop-tracking)
                     )
                    (else
                      (send-event (ppointer->process (-> self decel)) 'change-state cam-decel)
                      )
                    )
                  (set! v1-125 (-> *camera-combiner* tracking-status))
                  (zero? v1-125)
                  )
                (case (-> (the-as camera-slave (-> s5-1 0)) blend-to-type)
                  (((camera-blend-to-type unknown-0))
                   )
                  (((camera-blend-to-type unknown-1))
                   )
                  (((camera-blend-to-type unknown-2))
                   (if (= (-> gp-4 0 blend-from-type) 1)
                       (send-event *camera-combiner* 'copy-tracking (ppointer->process gp-4))
                       (send-event *camera-combiner* 'start-tracking (ppointer->process s5-1))
                       )
                   (set! (-> *camera-combiner* tracking-status) (the-as uint 2))
                   )
                  (else
                    (format 0 "unknown blend-to type~%")
                    )
                  )
                )
               ((= v1-125 1)
                (case (-> (the-as camera-slave (-> s5-1 0)) blend-to-type)
                  (((camera-blend-to-type unknown-0))
                   (set! (-> *camera-combiner* tracking-status) (the-as uint 3))
                   )
                  (((camera-blend-to-type unknown-1))
                   (set! (-> *camera-combiner* tracking-status) (the-as uint 3))
                   )
                  (((camera-blend-to-type unknown-2))
                   )
                  (else
                    (format 0 "unknown blend-to type~%")
                    )
                  )
                )
               ((or (= v1-125 2) (= v1-125 3))
                (case (-> (the-as camera-slave (-> s5-1 0)) blend-to-type)
                  (((camera-blend-to-type unknown-0))
                   (set! (-> *camera-combiner* tracking-status) (the-as uint 0))
                   0
                   )
                  (((camera-blend-to-type unknown-1))
                   (set! (-> *camera-combiner* tracking-status) (the-as uint 0))
                   0
                   )
                  (((camera-blend-to-type unknown-2))
                   (set! (-> *camera-combiner* tracking-status) (the-as uint 2))
                   )
                  (else
                    (format 0 "unknown blend-to type~%")
                    )
                  )
                )
               (else
                 (format 0 "unknown combiner status~%")
                 )
               )
             (if gp-4
                 (deactivate (-> gp-4 0))
                 )
             )
           )
         )
        (('ease-in)
         (cond
           ((< argc 1)
            (set! (-> self ease-t) 0.0)
            (logclear! (-> self master-options) (cam-master-options-u32 HAVE_EASE_TO_POS))
            )
           ((< argc 2)
            (if (< (the-as float (-> block param 0)) (-> self ease-t))
                (set! (-> self ease-t) (the-as float (-> block param 0)))
                )
            (logclear! (-> self master-options) (cam-master-options-u32 HAVE_EASE_TO_POS))
            )
           (else
             (if (< (the-as float (-> block param 0)) (-> self ease-t))
                 (set! (-> self ease-t) (the-as float (-> block param 0)))
                 )
             (set! (-> self ease-to quad) (-> (the-as vector (-> block param 1)) quad))
             (logior! (-> self master-options) (cam-master-options-u32 HAVE_EASE_TO_POS))
             )
           )
         (set! (-> self ease-step) 0.033333335)
         (set! v0-0 (-> self ease-from))
         (set! (-> (the-as vector v0-0) quad) (-> self tpos-curr-adj quad))
         v0-0
         )
        (('damp-up)
         (set! (-> self upspeed) 0.0)
         )
        (('reset-follow)
         (reset-follow)
         )
        (('teleport)
         (reset-target-tracking)
         (if (-> self slave)
             (send-event (ppointer->process (-> self slave)) message)
             )
         (send-event *camera-combiner* message)
         )
        (('toggle-slave-option)
         (logxor! (-> self slave-options) (-> block param 0))
         (if (-> self slave)
             (logxor! (-> self slave 0 options) (the-as uint (-> block param 0)))
             )
         (when (-> self decel)
           (set! v0-0 (logxor (-> self decel 0 options) (the-as uint (-> block param 0))))
           (set! (-> self decel 0 options) (the-as cam-slave-options-u32 v0-0))
           v0-0
           )
         )
        (('slave-option?)
         (and (-> self slave) (logtest? (-> self slave 0 options) (-> block param 0)))
         )
        (('set-slave-option)
         (when (-> self slave)
           (set! v0-0 (logior (-> self slave 0 options) (-> block param 0)))
           (set! (-> self slave 0 options) (the-as cam-slave-options-u32 v0-0))
           v0-0
           )
         )
        (('clear-slave-option)
         (when (-> self slave)
           (set! v0-0 (logclear (-> self slave 0 options) (-> block param 0)))
           (set! (-> self slave 0 options) (the-as cam-slave-options-u32 v0-0))
           v0-0
           )
         )
        (('no-follow)
         (when (-> self slave)
           (set! (-> self slave 0 tracking no-follow) (the-as basic #t))
           (vector-reset! (-> self slave 0 tracking follow-off))
           )
         (set! (-> *camera-combiner* tracking no-follow) (the-as basic #t))
         (set! v0-0 (-> *camera-combiner* tracking follow-off))
         (.svf (&-> (the-as vector v0-0) quad) vf0)
         v0-0
         )
        (('yes-follow)
         (if (-> self slave)
             (set! (-> self slave 0 tracking no-follow) #f)
             )
         (set! (-> *camera-combiner* tracking no-follow) #f)
         #f
         )
        (('blend-from-as-fixed)
         (let ((t9-42 format)
               (a0-101 0)
               (a1-35 "ERROR <GMJ>: *camera* blend-from-as-fixed event not supported anymore~%")
               )
           (-> block param 0)
           (t9-42 a0-101 a1-35)
           )
         )
        (('point-of-interest)
         (let ((t9-43 format)
               (a0-102 0)
               (a1-36 "ERROR <GMJ>: *camera* point-of-interest event not supported anymore~%")
               )
           (-> block param 0)
           (t9-43 a0-102 a1-36)
           )
         )
        (('part-water-drip)
         (set-time! (-> self water-drip-time))
         (set! (-> self water-drip-mult) (the-as float (-> block param 0)))
         (set! (-> self water-drip-speed) (the-as float (-> block param 1)))
         )
        (else
          (and (-> self slave) (let ((v1-237 (new 'stack-no-clear 'event-message-block)))
                                 (set! (-> v1-237 from) (process->ppointer proc))
                                 (set! (-> v1-237 num-params) argc)
                                 (set! (-> v1-237 message) message)
                                 (set! (-> v1-237 param 0) (-> block param 0))
                                 (set! (-> v1-237 param 1) (-> block param 1))
                                 (set! (-> v1-237 param 2) (-> block param 2))
                                 (set! (-> v1-237 param 3) (-> block param 3))
                                 (set! (-> v1-237 param 4) (-> block param 4))
                                 (set! (-> v1-237 param 5) (-> block param 5))
                                 (send-event-function (ppointer->process (-> self slave)) v1-237)
                                 )
               )
          )
        )
      )
    )
  :enter (behavior ()
    (let ((v1-1
            (process-spawn camera-slave :init cam-slave-init cam-free-floating #f :from *camera-dead-pool* :to self)
            )
          )
      (set! (-> self slave) (the-as (pointer camera-slave) v1-1))
      (if (not v1-1)
          (format 0 "ERROR <GMJ>: first slave failed to activate~%")
          )
      )
    (let ((v1-8 (process-spawn camera-slave :init cam-slave-init cam-fixed #f :from *camera-dead-pool* :to self)))
      (set! (-> self decel) (the-as (pointer camera-slave) v1-8))
      (if (not v1-8)
          (format 0 "ERROR <GMJ>: decel failed to activate~%")
          )
      )
    (if (and (nonzero? camera-master-debug) *debug-segment*)
        (add-connection *debug-engine* self camera-master-debug self #f #f)
        )
    )
  :trans (behavior ()
    (when (not (paused?))
      (vector-negate!
        (-> self local-down)
        (vector-normalize-copy! (-> self local-down) (-> *standard-dynamics* gravity) 1.0)
        )
      (cam-master-effect)
      )
    )
  :code (behavior ()
    (until #f
      (when *debug-segment*
        (let ((gp-0 (-> *display* frames (-> *display* on-screen) profile-array data 0))
              (v1-7 'camera)
              (s5-0 *profile-camera-color*)
              )
          (when (and *dproc* *debug-segment*)
            (let ((s4-0 (-> gp-0 data (-> gp-0 count))))
              (let ((s3-0 (-> gp-0 base-time)))
                (set! (-> s4-0 name) v1-7)
                (set! (-> s4-0 start-time) (the-as int (- (timer-count (the-as timer-bank #x10000800)) (the-as uint s3-0))))
                )
              (set! (-> s4-0 depth) (the-as uint (-> gp-0 depth)))
              (set! (-> s4-0 color) s5-0)
              (set! (-> gp-0 segment (-> gp-0 depth)) s4-0)
              )
            (+! (-> gp-0 count) 1)
            (+! (-> gp-0 depth) 1)
            (set! (-> gp-0 max-depth) (max (-> gp-0 max-depth) (-> gp-0 depth)))
            )
          )
        0
        )
      (set! (-> self string-min target y) (-> self settings string-min-height))
      (set! (-> self string-max target y) (-> self settings string-max-height))
      (set! (-> self string-min target z) (-> self settings string-min-length))
      (set! (-> self string-max target z) (-> self settings string-max-length))
      (when (logtest? (-> *camera* settings master-options) (cam-master-options IMMEDIATE_STRING_MIN_MAX))
        (set! (-> self string-min value y) (-> self settings string-min-height))
        (set! (-> self string-max value y) (-> self settings string-max-height))
        (set! (-> self string-min value z) (-> self settings string-min-length))
        (set! (-> self string-max value z) (-> self settings string-max-length))
        )
      (set! (-> self string-push-z) (fmax (-> self string-min value z) (-> *CAMERA-bank* default-string-push-z)))
      (master-track-target)
      (set! (-> last-try-to-look-at-data horz) 0.0)
      (set! (-> last-try-to-look-at-data vert) 0.0)
      (when (not (paused?))
        (update! (-> self string-min) (the-as vector #f))
        (update! (-> self string-max) (the-as vector #f))
        )
      (set! (-> self string-min value x)
            (fmin (-> self string-min value x) (+ -4.096 (-> self string-max value x)))
            )
      (set! (-> self string-min value y)
            (fmin (-> self string-min value y) (+ -4.096 (-> self string-max value y)))
            )
      (set! (-> self string-min value z)
            (fmin (-> self string-min value z) (+ -4.096 (-> self string-max value z)))
            )
      (when *debug-segment*
        (let ((gp-1 (-> *display* frames (-> *display* on-screen) profile-array data 0)))
          (when (and *dproc* *debug-segment*)
            (let* ((v1-56 (+ (-> gp-1 depth) -1))
                   (s5-1 (-> gp-1 segment v1-56))
                   (s4-1 (-> gp-1 base-time))
                   )
              (when (>= v1-56 0)
                (set! (-> s5-1 end-time) (the-as int (- (timer-count (the-as timer-bank #x10000800)) (the-as uint s4-1))))
                (+! (-> gp-1 depth) -1)
                )
              )
            )
          )
        0
        )
      (suspend)
      )
    #f
    )
  )

(defbehavior cam-master-init camera-master ()
  (stack-size-set! (-> self main-thread) 512)
  (logclear! (-> self mask) (process-mask menu))
  (set! (-> self master-options) (cam-master-options-u32))
  (set! (-> self settings) (-> *setting-control* cam-current))
  (set! (-> self slave) (the-as (pointer camera-slave) #f))
  (set! (-> self decel) (the-as (pointer camera-slave) #f))
  (set! (-> self slave-options) (the-as uint 560))
  (set! (-> self view-off-param-save) 1.0)
  (set! (-> self changer) (the-as uint (process->ppointer self)))
  (set! (-> self string-push-z) (-> *CAMERA-bank* default-string-push-z))
  (let ((gp-0 (new-stack-vector0)))
    (set! (-> gp-0 y) (-> self settings string-min-height))
    (set! (-> gp-0 z) (-> self settings string-min-length))
    (init (-> self string-min) gp-0 40.96 409.6 0.9)
    (set! (-> gp-0 y) (-> self settings string-max-height))
    (set! (-> gp-0 z) (-> self settings string-max-length))
    (init (-> self string-max) gp-0 40.96 409.6 0.9)
    )
  (set! (-> self outro-t-step) 0.0)
  (reset-to-collide-spec (-> self focus) (collide-spec jak player-list))
  (let ((a1-4 (new-stack-vector0)))
    (tracking-spline-method-10 (-> self target-spline) a1-4)
    )
  (set! (-> self water-drip) (create-launch-control group-rain-screend-drop self))
  (set! (-> self water-drip-time) (seconds -60))
  (go cam-master-active)
  0
  (none)
  )

(defmethod camera-master-method-14 ((this camera-master) (arg0 vector))
  (if (handle->process (-> this focus handle))
      (vector-! arg0 (-> this tpos-curr) (-> this tpos-old))
      (vector-reset! arg0)
      )
  arg0
  )

(defmethod camera-master-method-15 ((this camera-master) (arg0 vector))
  (if (and (-> this slave) (-> this slave 0 next-state) (= (-> this slave 0 next-state name) 'cam-string))
      (set! (-> arg0 quad) (-> this slave 0 view-flat quad))
      (vector-reset! arg0)
      )
  arg0
  )
