Files
jak-project/goal_src/jak2/pc/statistics-h.gc
T
Tyler Wilding 5eeaffcde0 scripts: new linter script to detect goal_src files with trailing whitespace (#3387)
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.
2024-02-24 14:27:56 -05:00

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)