129 lines
3.1 KiB
Go
129 lines
3.1 KiB
Go
package assetstore
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/data"
|
|
"code.ur.gs/lupine/ordoor/internal/idx"
|
|
)
|
|
|
|
type Animation struct {
|
|
Frames []*Sprite
|
|
}
|
|
|
|
func (a *AssetStore) AnimationsIndex() (*idx.Idx, error) {
|
|
if a.idx != nil {
|
|
return a.idx, nil
|
|
}
|
|
|
|
filename, err := a.lookup("WarHammer", "idx", "Idx")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
idx, err := idx.Load(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
a.idx = idx
|
|
return idx, nil
|
|
}
|
|
|
|
func (a *AssetStore) AnimationsObject() (*Object, error) {
|
|
if a.aniObj != nil {
|
|
return a.aniObj, nil
|
|
}
|
|
|
|
filename, err := a.lookup("WarHammer", "ani", "Anim")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
obj, err := a.ObjectByPath(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
a.aniObj = obj
|
|
return obj, nil
|
|
}
|
|
|
|
func (a *AssetStore) Animation(groupIdx, recIdx int) (*Animation, error) {
|
|
idx, err := a.AnimationsIndex()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
obj, err := a.AnimationsObject()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
group := idx.Groups[groupIdx]
|
|
if group.Spec.Count == 0 {
|
|
return &Animation{}, nil
|
|
}
|
|
|
|
// rec := group.Records[recIdx]
|
|
det := group.Details[recIdx]
|
|
|
|
first := int(group.Spec.SpriteIdx) + int(det.FirstSprite)
|
|
last := int(group.Spec.SpriteIdx) + int(det.LastSprite)
|
|
count := last - first + 1
|
|
|
|
sprites, err := obj.Sprites(first, count)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Animation{Frames: sprites}, nil
|
|
}
|
|
|
|
func (a *AssetStore) CharacterAnimation(ctype data.CharacterType, action data.AnimAction) (*Animation, error) {
|
|
ha, err := a.HasAction()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !ha.Check(ctype, action) {
|
|
return nil, fmt.Errorf("character %s: animation %s: not available", ctype, action)
|
|
}
|
|
|
|
// FIXME: we still need to be able to go from CTYPE to GROUP. In particular,
|
|
// squad leaders seem to be a modification on top of a previous group, which
|
|
// is a bit awkward. For now, hardcode it. How are captain modifiers stored?
|
|
group, ok := map[data.CharacterType]int{
|
|
data.CharacterTypeTactical: 1, // Has captain
|
|
data.CharacterTypeAssault: 3, // Has captain
|
|
data.CharacterTypeDevastator: 5,
|
|
data.CharacterTypeTerminator: 6, // Has captain
|
|
data.CharacterTypeApothecary: 8,
|
|
data.CharacterTypeTechmarine: 9,
|
|
data.CharacterTypeChaplain: 10,
|
|
data.CharacterTypeLibrarian: 11,
|
|
data.CharacterTypeCaptain: 12,
|
|
data.CharacterTypeChaosMarine: 13,
|
|
data.CharacterTypeChaosLord: 14,
|
|
data.CharacterTypeChaosChaplain: 15,
|
|
data.CharacterTypeChaosSorcerer: 16,
|
|
data.CharacterTypeChaosTerminator: 17,
|
|
data.CharacterTypeKhorneBerserker: 18,
|
|
data.CharacterTypeBloodThirster: 19, // This is a rotating thing?
|
|
data.CharacterTypeBloodLetter: 20,
|
|
data.CharacterTypeFleshHound: 21,
|
|
data.CharacterTypeLordOfChange: 22, // Another rotating thing?
|
|
data.CharacterTypeFlamer: 23,
|
|
data.CharacterTypePinkHorror: 24,
|
|
data.CharacterTypeBlueHorror: 25,
|
|
data.CharacterTypeChaosCultist: 26,
|
|
}[ctype]
|
|
if !ok {
|
|
return nil, fmt.Errorf("Unknown character type: %s", ctype)
|
|
}
|
|
|
|
rec := ha.Index(ctype, action)
|
|
|
|
return a.Animation(group, rec)
|
|
}
|