More investigation into animation
This commit is contained in:
178
internal/data/has_action.go
Normal file
178
internal/data/has_action.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/emef/bitfield"
|
||||
|
||||
"code.ur.gs/lupine/ordoor/internal/util/asciiscan"
|
||||
)
|
||||
|
||||
// AnimAction represents an animation that is stored in WarHammer.ani
|
||||
type AnimAction int
|
||||
|
||||
// CharacterType represents one of the different types of character in the game.
|
||||
//
|
||||
// TODO: can we load the list of character types anywhere or is it hardcoded in
|
||||
// the original too?
|
||||
type CharacterType int
|
||||
|
||||
const (
|
||||
AnimActionNone AnimAction = 0
|
||||
AnimActionAnim AnimAction = 1
|
||||
AnimActionWalk AnimAction = 2
|
||||
AnimActionExplosion AnimAction = 3
|
||||
AnimActionProjectile AnimAction = 4
|
||||
AnimActionSmoke AnimAction = 5
|
||||
AnimActionStandingShoot AnimAction = 6
|
||||
AnimActionStandingDeath AnimAction = 7
|
||||
AnimActionPain AnimAction = 8
|
||||
AnimActionSpellFx1 AnimAction = 9
|
||||
AnimActionSpellFx2 AnimAction = 10
|
||||
AnimActionSpellFx3 AnimAction = 11
|
||||
AnimActionSpellFx4 AnimAction = 12
|
||||
AnimActionSpellFx5 AnimAction = 13
|
||||
AnimActionRun AnimAction = 14
|
||||
AnimActionCrouch AnimAction = 15
|
||||
AnimActionStand AnimAction = 16
|
||||
AnimActionStandingRead AnimAction = 17
|
||||
AnimActionStandingUnready AnimAction = 18
|
||||
AnimActionCrouchingReady AnimAction = 19
|
||||
AnimActionCrouchingUnready AnimAction = 20
|
||||
AnimActionCrouchingShoot AnimAction = 21
|
||||
AnimActionStandingGrenade AnimAction = 22
|
||||
AnimActionCrouchingGrenade AnimAction = 23
|
||||
AnimActionDrawMelee AnimAction = 24
|
||||
AnimActionSlash AnimAction = 25
|
||||
AnimActionStab AnimAction = 26
|
||||
AnimActionBlown AnimAction = 27
|
||||
AnimActionCrouchingDeath AnimAction = 28
|
||||
AnimActionJump AnimAction = 29
|
||||
AnimActionHeal AnimAction = 30
|
||||
AnimActionTechWork AnimAction = 31
|
||||
AnimActionCast AnimAction = 32
|
||||
AnimActionShoot AnimAction = 33
|
||||
AnimActionDeath AnimAction = 34
|
||||
AnimActionFromWarp AnimAction = 35
|
||||
|
||||
AnimActionStart = AnimActionNone
|
||||
AnimActionEnd = AnimActionFromWarp
|
||||
AnimActionCount = AnimActionEnd - AnimActionStart + 1
|
||||
|
||||
// FIXME: indexed from 1, very annoying
|
||||
CharacterTypeTactical CharacterType = 1
|
||||
CharacterTypeAssault CharacterType = 2
|
||||
CharacterTypeDevastator CharacterType = 3
|
||||
CharacterTypeTerminator CharacterType = 4
|
||||
CharacterTypeApothecary CharacterType = 5
|
||||
CharacterTypeTechmarine CharacterType = 6
|
||||
CharacterTypeChaplain CharacterType = 7
|
||||
CharacterTypeLibrarian CharacterType = 8
|
||||
CharacterTypeCaptain CharacterType = 9
|
||||
CharacterTypeChaosMarine CharacterType = 10
|
||||
CharacterTypeChaosLord CharacterType = 11
|
||||
CharacterTypeChaosChaplain CharacterType = 12
|
||||
CharacterTypeChaosSorcerer CharacterType = 13
|
||||
CharacterTypeChaosTerminator CharacterType = 14
|
||||
CharacterTypeKhorneBerserker CharacterType = 15
|
||||
CharacterTypeBloodThirster CharacterType = 16
|
||||
CharacterTypeBloodLetter CharacterType = 17
|
||||
CharacterTypeFleshHound CharacterType = 18
|
||||
CharacterTypeLordOfChange CharacterType = 19
|
||||
CharacterTypeFlamer CharacterType = 20
|
||||
CharacterTypePinkHorror CharacterType = 21
|
||||
CharacterTypeBlueHorror CharacterType = 22
|
||||
CharacterTypeChaosCultist CharacterType = 23
|
||||
|
||||
CharacterTypeStart = CharacterTypeTactical
|
||||
CharacterTypeEnd = CharacterTypeChaosCultist
|
||||
CharacterTypeCount = CharacterTypeEnd - CharacterTypeStart + 1
|
||||
)
|
||||
|
||||
// HasAction tells us whether a character has an animation or not.
|
||||
type HasAction struct {
|
||||
bits bitfield.BitField
|
||||
}
|
||||
|
||||
func LoadHasAction(filename string) (*HasAction, error) {
|
||||
scanner, err := asciiscan.New(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer scanner.Close()
|
||||
|
||||
out := &HasAction{
|
||||
bits: bitfield.New(int(CharacterTypeCount) * int(AnimActionCount)),
|
||||
}
|
||||
|
||||
// Reuse this for every loop
|
||||
var actions [AnimActionCount]bool
|
||||
ptrs := make([]*bool, len(actions))
|
||||
for i, _ := range actions {
|
||||
ptrs[i] = &actions[i]
|
||||
}
|
||||
|
||||
for c := CharacterTypeStart; c <= CharacterTypeEnd; c++ {
|
||||
if err := scanner.ConsumeBoolPtrs(ptrs...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for j, value := range actions {
|
||||
a := AnimActionStart + AnimAction(j)
|
||||
|
||||
out.set(c, a, value)
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (h *HasAction) Check(c CharacterType, a AnimAction) bool {
|
||||
return h.bits.Test(h.offset(c, a))
|
||||
}
|
||||
|
||||
func (h *HasAction) offset(c CharacterType, a AnimAction) uint32 {
|
||||
// Best to view this as a 2D array with CharacterTypeCount * AnimActionCount elements
|
||||
i := uint32(c - CharacterTypeStart)
|
||||
j := uint32(a - AnimActionStart)
|
||||
|
||||
return (i * uint32(AnimActionCount)) + j
|
||||
}
|
||||
|
||||
func (h *HasAction) set(c CharacterType, a AnimAction, value bool) {
|
||||
if value {
|
||||
h.bits.Set(h.offset(c, a))
|
||||
} else {
|
||||
h.bits.Clear(h.offset(c, a))
|
||||
}
|
||||
}
|
||||
|
||||
// Actions returns the list of animations that a character type has
|
||||
func (h *HasAction) Actions(c CharacterType) []AnimAction {
|
||||
var out []AnimAction
|
||||
|
||||
for j := AnimActionStart; j < AnimActionCount; j++ {
|
||||
if h.Check(c, j) {
|
||||
out = append(out, j)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (h *HasAction) Print() {
|
||||
fmt.Println(" Tac Ass Dev Term Apo Tech Chp Lib Cpt CMar CLrd CChp CSrc CTrm Kbz BTh BL FHnd LoC Flm PHr BHr Cult")
|
||||
for a := AnimActionStart; a <= AnimActionEnd; a++ {
|
||||
fmt.Printf("%.2d", int(a))
|
||||
for c := CharacterTypeStart; c <= CharacterTypeEnd; c++ {
|
||||
if h.Check(c, a) {
|
||||
fmt.Print(" x ")
|
||||
} else {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user