mirror of
https://github.com/open-goal/jak-project
synced 2026-08-07 02:06:59 -04:00
5eeaffcde0
Removes trailing whitespace from goal_src files, eventually the formatter will do this as well but it's not ready yet so this is a decent interim solution. A competent text editor will also do this / flag it for you.
381 lines
8.8 KiB
Common Lisp
381 lines
8.8 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
#|
|
|
Header file for the statistics code.
|
|
|#
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; constants
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
(defconstant KILL_STATS_MAX_ENEMY_TYPES 127)
|
|
(defconstant KILL_STATS_MAX_SOURCE 35)
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; types and enums
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
(defenum kill-stats-source
|
|
:type uint8
|
|
(unknown)
|
|
|
|
(gun-yellow)
|
|
(gun-red)
|
|
(gun-blue)
|
|
(gun-dark)
|
|
(board)
|
|
(board-trick)
|
|
(mech)
|
|
(mech-bonk)
|
|
(turret)
|
|
(punch)
|
|
(flop)
|
|
(uppercut)
|
|
(spin)
|
|
(roll)
|
|
|
|
(darkjak-punch)
|
|
(darkjak-flop)
|
|
(darkjak-uppercut)
|
|
(darkjak-spin)
|
|
(darkjak-roll)
|
|
(darkjak-bomb0)
|
|
(darkjak-bomb1)
|
|
|
|
(indax-punch)
|
|
(indax-spin)
|
|
|
|
(guard)
|
|
(sig)
|
|
(ashelin)
|
|
(jinx)
|
|
(grim)
|
|
(mog)
|
|
(metalhead)
|
|
|
|
(bot)
|
|
(enemy)
|
|
|
|
(max)
|
|
)
|
|
|
|
|
|
(deftype kill-statistics-source-entry (structure)
|
|
((name symbol)
|
|
(amount int32)
|
|
)
|
|
)
|
|
|
|
(deftype kill-statistics-enemy-entry (structure)
|
|
((name symbol)
|
|
(sources int16 KILL_STATS_MAX_SOURCE)
|
|
)
|
|
)
|
|
|
|
|
|
(deftype kill-statistics (structure)
|
|
((enemies kill-statistics-enemy-entry KILL_STATS_MAX_ENEMY_TYPES :inline)
|
|
(allow-unknown? symbol)
|
|
)
|
|
|
|
(:methods
|
|
(initialize (_type_) int)
|
|
(alloc-slot (_type_ symbol) kill-statistics-enemy-entry)
|
|
|
|
(get-total-count (_type_) int)
|
|
(get-enemy-stats (_type_ symbol) kill-statistics-enemy-entry)
|
|
(get-count-for-enemy (_type_ symbol) int)
|
|
(get-count-for-source (_type_ kill-stats-source) int)
|
|
(get-count (_type_ symbol kill-stats-source) int)
|
|
|
|
(increment (_type_ symbol kill-stats-source) int)
|
|
|
|
(print-stats (_type_ object) object)
|
|
)
|
|
)
|
|
|
|
|
|
(deftype statistics (basic)
|
|
((kill-stats kill-statistics :inline)
|
|
)
|
|
(:methods
|
|
(new (symbol type) _type_)
|
|
(print-stats (_type_ object) object))
|
|
)
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; serializing
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(defun kill-source->string ((ks kill-stats-source))
|
|
(enum->string kill-stats-source ks))
|
|
|
|
|
|
(defun string->kill-source ((ks string))
|
|
"return kill-source based on name"
|
|
(string->enum kill-stats-source ks (kill-stats-source unknown)))
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; methods
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(defmethod new statistics ((allocation symbol) (type-to-make type))
|
|
"make a new statistics"
|
|
(let ((obj (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
|
|
(initialize (-> obj kill-stats))
|
|
(false! (-> obj kill-stats allow-unknown?))
|
|
obj))
|
|
|
|
|
|
(defmethod print-stats ((this statistics) out)
|
|
"print the stats as a table to out"
|
|
|
|
(print-stats (-> this kill-stats) out)
|
|
out)
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; kill stats methods
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(defmethod initialize ((this kill-statistics))
|
|
"initialize a kill-statistics to the default values"
|
|
|
|
(dotimes (i KILL_STATS_MAX_ENEMY_TYPES)
|
|
(set! (-> this enemies i name) #f)
|
|
(dotimes (ii KILL_STATS_MAX_SOURCE)
|
|
(set! (-> this enemies i sources ii) 0)
|
|
)
|
|
)
|
|
|
|
0)
|
|
|
|
|
|
(defmethod get-total-count ((this kill-statistics))
|
|
"return the total kill count for every thing tracked in the stats"
|
|
|
|
(let ((amount 0))
|
|
(dotimes (i KILL_STATS_MAX_ENEMY_TYPES)
|
|
(when (-> this enemies i name)
|
|
(dotimes (ii KILL_STATS_MAX_SOURCE)
|
|
(+! amount (-> this enemies i sources ii))
|
|
)))
|
|
amount)
|
|
)
|
|
|
|
|
|
(defmethod get-enemy-stats ((this kill-statistics) (name symbol))
|
|
"return the enemy entry with that name. #f = not found"
|
|
|
|
(dotimes (i KILL_STATS_MAX_ENEMY_TYPES)
|
|
(when (= (-> this enemies i name) name)
|
|
(return (-> this enemies i))))
|
|
(the kill-statistics-enemy-entry #f))
|
|
|
|
(defmethod alloc-slot ((this kill-statistics) (name symbol))
|
|
"allocates an enemy stats entry for that name and returns it. #f = out of memory"
|
|
(dotimes (i KILL_STATS_MAX_ENEMY_TYPES)
|
|
(when (not (-> this enemies i name))
|
|
(set! (-> this enemies i name) name)
|
|
(dotimes (ii KILL_STATS_MAX_SOURCE)
|
|
(set! (-> this enemies i sources ii) 0))
|
|
(return (-> this enemies i)))
|
|
)
|
|
(the kill-statistics-enemy-entry #f))
|
|
|
|
(defmethod increment ((this kill-statistics) (name symbol) (source kill-stats-source))
|
|
"adds one kill to the kill statistics"
|
|
|
|
(let ((kill-stats (get-enemy-stats this name)))
|
|
(if (not kill-stats)
|
|
(set! kill-stats (alloc-slot this name)))
|
|
(when (not kill-stats)
|
|
(format 0 "out of stats memory!~%")
|
|
(return 0))
|
|
|
|
(+! (-> kill-stats sources source) 1))
|
|
)
|
|
|
|
|
|
|
|
(defmethod get-count ((this kill-statistics) (name symbol) (source kill-stats-source))
|
|
"return number of kills for that enemy with that cause of death"
|
|
|
|
(let ((kill-stats (get-enemy-stats this name)))
|
|
(if (not kill-stats)
|
|
(return 0))
|
|
|
|
(-> kill-stats sources source))
|
|
)
|
|
|
|
(defmethod get-count-for-enemy ((this kill-statistics) (name symbol))
|
|
"return number of kills for that enemy"
|
|
|
|
(let ((kill-stats (get-enemy-stats this name))
|
|
(kills 0))
|
|
(if (not kill-stats)
|
|
(return 0))
|
|
|
|
(dotimes (i KILL_STATS_MAX_SOURCE)
|
|
(+! kills (-> kill-stats sources i)))
|
|
kills)
|
|
)
|
|
|
|
(defmethod get-count-for-source ((this kill-statistics) (source kill-stats-source))
|
|
"return number of kills for that source"
|
|
|
|
(let ((kills 0))
|
|
(dotimes (i KILL_STATS_MAX_ENEMY_TYPES)
|
|
(when (-> this enemies i name)
|
|
(+! kills (-> this enemies i sources source))
|
|
)
|
|
)
|
|
kills)
|
|
)
|
|
|
|
|
|
(defmethod print-stats ((this kill-statistics) out)
|
|
"print the stats as a table to out"
|
|
|
|
(format out "----! kill stats (total: ~D) !----~%" (get-total-count this))
|
|
(dotimes (i KILL_STATS_MAX_ENEMY_TYPES)
|
|
(when (-> this enemies i name)
|
|
(format out "~S: ~D total~%" (-> this enemies i name) (get-count-for-enemy this (-> this enemies i name)))
|
|
(dotimes (ii KILL_STATS_MAX_SOURCE)
|
|
(if (nonzero? (-> this enemies i sources ii))
|
|
(format out " ~3D ~S~%" (-> this enemies i sources ii) (kill-source->string (the kill-stats-source ii))))
|
|
)
|
|
)
|
|
)
|
|
out)
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; global variables
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
(define *statistics* (new 'global 'statistics))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; helper functions
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
(defun get-kill-stats ()
|
|
(-> *statistics* kill-stats))
|
|
|
|
|
|
|
|
(define-extern civilian type)
|
|
(define-extern sig type)
|
|
(define-extern ashelin type)
|
|
(define-extern jinx type)
|
|
(define-extern mog type)
|
|
(define-extern grim type)
|
|
(define-extern juicer type)
|
|
(define-extern grunt type)
|
|
(define-extern flitter type)
|
|
(define-extern wasp type)
|
|
(define-extern spyder type)
|
|
(define-extern metalhead-predator type)
|
|
(define-extern metalhead-grunt type)
|
|
(define-extern metalhead-flitter type)
|
|
(define-extern crimson-guard-hover type)
|
|
(define-extern crimson-guard-level type)
|
|
(define-extern roboguard-level type)
|
|
(defun remap-enemy-type-name ((en-type type))
|
|
"returns the appropriate type name (symbol) for the stats tracker"
|
|
|
|
(cond
|
|
((symbol-member? (-> en-type symbol) '(kid kid-escort)) 'kid)
|
|
|
|
((= en-type metalhead-predator) 'predator)
|
|
((= en-type metalhead-grunt) 'grunt)
|
|
((= en-type metalhead-flitter) 'flitter)
|
|
((= en-type crimson-guard-level) 'crimson-guard)
|
|
((= en-type crimson-guard-hover) 'crimson-guard)
|
|
((= en-type roboguard-level) 'roboguard)
|
|
|
|
((type-type? en-type civilian) 'civilian)
|
|
((type-type? en-type sig) 'sig)
|
|
((type-type? en-type ashelin) 'ashelin)
|
|
((type-type? en-type juicer) 'juicer)
|
|
((type-type? en-type grunt) 'grunt)
|
|
((type-type? en-type flitter) 'flitter)
|
|
((type-type? en-type wasp) 'wasp)
|
|
((type-type? en-type spyder) 'spyder)
|
|
(else (-> en-type symbol)))
|
|
)
|
|
|
|
;; all types of metal head
|
|
(define *metalhead-types*
|
|
'(flitter
|
|
grunt
|
|
metalmonk
|
|
juicer
|
|
centurion
|
|
hopper
|
|
hosehead
|
|
rhino
|
|
spyder
|
|
grenadier
|
|
rapid-gunner
|
|
predator
|
|
flamer
|
|
wasp
|
|
ginsu
|
|
pegasus
|
|
mantis
|
|
jellyfish
|
|
flying-spider
|
|
))
|
|
|
|
(defun is-metalhead? ((p process))
|
|
"is p a metal head enemy?"
|
|
|
|
(let ((p-type (remap-enemy-type-name (-> p type)))
|
|
(iter *metalhead-types*))
|
|
(while (not (null? iter))
|
|
(let ((cur (the symbol (car iter))))
|
|
(if (= p-type cur)
|
|
(return #t))
|
|
)
|
|
(set! iter (cdr iter))
|
|
)
|
|
)
|
|
#f)
|
|
|
|
(defun killed-each-metalhead? ()
|
|
"#t = every metal head type has been killed once."
|
|
|
|
(let ((iter *metalhead-types*))
|
|
(while (not (null? iter))
|
|
(let ((cur (the symbol (car iter))))
|
|
(if (= (get-count-for-enemy (get-kill-stats) cur) 0)
|
|
(return #f))
|
|
)
|
|
(set! iter (cdr iter))
|
|
)
|
|
)
|
|
#t)
|
|
|