;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/util/types-h.gc")

;; This file contains types for:
;; - the full game state (game-info)
;; - the "load state"
;; - checkpoints

;; DECOMP BEGINS

;; Game parameters.
(deftype game-bank (basic)
  ((life-max-default   float) ;; yes this life system works, but does nothing
   (life-start-default float)
   (life-single-inc    float)
   (money-task-inc     float)
   (money-oracle-inc   float)))

(define *GAME-bank*
  (new 'static
       'game-bank
       :life-max-default 99.0
       :life-start-default 5.0
       :life-single-inc 1.0
       :money-task-inc 90.0
       :money-oracle-inc 120.0))

;; aid
(deftype actor-id (uint32) ())

;;;;;;;;;;;;;;;
;; Load State
;;;;;;;;;;;;;;;

;; The load state system lets gameplay code control the loading state of the game.
;; It is the interface to the code inside of level.gc that actually manages loads.

;; the possible load state for a level.
(deftype level-buffer-state (structure)
  ((name          symbol)
   (display?      symbol)
   (force-vis?    symbol)
   (force-inside? symbol))
  :pack-me)

;; This includes more state than just "loading" - it also has a list of commands to execute and
;; other random state.
(deftype load-state (basic)
  ((want          level-buffer-state 2 :inline)
   (vis-nick      symbol)
   (command-list  pair)
   (object-name   symbol 256)
   (object-status basic 256))
  (:methods
   (new (symbol type) _type_)
   (reset! (_type_) _type_)
   (update! (_type_) int)
   (want-levels (_type_ symbol symbol) int)
   (want-display-level (_type_ symbol symbol) int)
   (want-vis (_type_ symbol) int)
   (want-force-vis (_type_ symbol symbol) int)
   (execute-command (_type_ pair) none)
   (execute-commands-up-to (_type_ float) int)
   (backup-load-state-and-set-cmds (_type_ pair) int)
   (restore-load-state-and-cleanup (_type_) int)
   (restore-load-state (_type_) int)
   (set-force-inside! (_type_ symbol symbol) none)))

(defmethod new load-state ((allocation symbol) (type-to-make type))
  (reset! (object-new allocation type-to-make (the-as int (-> type-to-make size)))))

(define-extern *load-state* load-state)

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Game Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defenum continue-flags
  :type uint32
  :bitfield #t
  (contf00)
  (contf01)
  (warp)
  (demo)
  (intro)
  (sage-intro)
  (sage-demo-convo)
  (title)
  (contf08)
  (contf09)
  (game-start)
  (sage-ecorocks))

;; static data for a continue point
(deftype continue-point (basic)
  ((name          string)
   (level         symbol)
   (flags         continue-flags)
   (trans         vector :inline)
   (quat          quaternion :inline)
   (camera-trans  vector :inline)
   (camera-rot    float 9)
   (load-commands pair)
   (vis-nick      symbol)
   (lev0          symbol)
   (disp0         symbol)
   (lev1          symbol)
   (disp1         symbol))
  (:methods
   (debug-draw! (_type_) none)))

(declare-type entity-perm structure)

(declare-type entity-perm-array basic)

(declare-type game-save basic)

;; Game Info is the full state of the game
;; this information can be saved/loaded from a game save.
;; also, it must be manually synchronized with entity permanent state in the levels
(deftype game-info (basic)
  ((mode                  symbol)
   (save-name             basic)
   (life                  float)
   (life-max              float)
   (money                 float)
   (money-total           float)
   (money-per-level       uint8 32)
   (deaths-per-level      uint8 32)
   (buzzer-total          float)
   (fuel                  float)
   (perm-list             entity-perm-array)
   (task-perm-list        entity-perm-array)
   (current-continue      continue-point)
   (text-ids-seen         bit-array)
   (level-opened          uint8 32)
   (hint-control          (array level-hint-control))
   (task-hint-control     (array task-hint-control-group))
   (total-deaths          int32)
   (continue-deaths       int32)
   (fuel-cell-deaths      int32)
   (game-start-time       time-frame)
   (continue-time         time-frame)
   (death-time            time-frame)
   (hit-time              time-frame)
   (fuel-cell-pickup-time time-frame)
   (fuel-cell-time        (array time-frame))
   (enter-level-time      (array time-frame))
   (in-level-time         (array time-frame))
   (blackout-time         time-frame)
   (letterbox-time        time-frame)
   (hint-play-time        time-frame)
   (display-text-time     time-frame)
   (display-text-handle   handle)
   (death-movie-tick      int32)
   (want-auto-save        symbol)
   (auto-save-proc        handle)
   (auto-save-status      mc-status-code)
   (auto-save-card        int32)
   (auto-save-which       int32)
   (pov-camera-handle     handle)
   (other-camera-handle   handle)
   (death-pos             vector-array)
   (dummy                 basic)
   (auto-save-count       int32))
  (:methods
   (initialize! (_type_ symbol game-save string) _type_)
   (adjust (_type_ symbol float handle) float)
   (task-complete? (_type_ game-task) symbol)
   (lookup-entity-perm-by-aid (_type_ actor-id) entity-perm)
   (get-entity-task-perm (_type_ game-task) entity-perm)
   (copy-perms-from-level! (_type_ level) none)
   (copy-perms-to-level! (_type_ level) none)
   (debug-print (_type_ symbol) _type_)
   (get-or-create-continue! (_type_) continue-point)
   (get-continue-by-name (_type_ string) continue-point)
   (set-continue! (_type_ basic) continue-point)
   (buzzer-count (_type_ game-task) int)
   (seen-text? (_type_ text-id) symbol)
   (mark-text-as-seen (_type_ text-id) none)
   (got-buzzer? (_type_ game-task int) symbol)
   (save-game! (_type_ game-save string) none)
   (load-game! (_type_ game-save) game-save)
   (clear-text-seen! (_type_ text-id) none)
   (get-death-count (_type_ symbol) int)
   (get-health-percent-lost (_type_ symbol) float)))

(define-extern *game-info* game-info)

(when (or (not *game-info*) (zero? *game-info*))
  (let ((temp (new 'static 'game-info :mode 'debug :current-continue #f)))
    (set! (-> temp fuel-cell-time) (new 'global 'boxed-array time-frame 116))
    (set! (-> temp enter-level-time) (new 'global 'boxed-array time-frame 32))
    (set! (-> temp in-level-time) (new 'global 'boxed-array time-frame 32))
    (set! *game-info* temp)))

(define-extern game-task->string (function game-task string))
