2020-04-16 15:30:47 +01:00
|
|
|
package assetstore
|
|
|
|
|
|
|
|
import (
|
2020-06-13 15:07:32 +01:00
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/data"
|
2020-04-16 15:30:47 +01:00
|
|
|
"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
|
|
|
|
}
|
|
|
|
|
2020-06-13 23:10:21 +01:00
|
|
|
func (a *AssetStore) Animation(groupIdx int, recId int, compass int) (*Animation, error) {
|
|
|
|
realIdx, err := a.AnimationsIndex()
|
2020-04-16 15:30:47 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-06-13 23:10:21 +01:00
|
|
|
// FIXME: are we using the right value if we need to make this change?
|
|
|
|
if compass == 0 {
|
|
|
|
compass = 8
|
|
|
|
}
|
|
|
|
|
2020-04-16 15:30:47 +01:00
|
|
|
obj, err := a.AnimationsObject()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-06-13 23:10:21 +01:00
|
|
|
group := realIdx.Groups[groupIdx]
|
2020-04-16 15:30:47 +01:00
|
|
|
if group.Spec.Count == 0 {
|
|
|
|
return &Animation{}, nil
|
|
|
|
}
|
|
|
|
|
2020-06-13 23:10:21 +01:00
|
|
|
var det *idx.Detail
|
|
|
|
for i, rec := range group.Records {
|
|
|
|
if /*int(rec.ActionID) == int(action) && */ int(rec.Compass) == compass {
|
|
|
|
det = &group.Details[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if det == nil {
|
|
|
|
return nil, fmt.Errorf("Couldn't find anim (%v %v %v)", groupIdx, recId, compass)
|
|
|
|
}
|
2020-04-16 15:30:47 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2020-06-13 15:07:32 +01:00
|
|
|
|
2020-06-13 23:10:21 +01:00
|
|
|
func (a *AssetStore) CharacterAnimation(ctype data.CharacterType, action data.AnimAction, compass int) (*Animation, error) {
|
2020-06-13 15:07:32 +01:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2020-06-13 23:10:21 +01:00
|
|
|
return a.Animation(group, int(action), compass)
|
2020-06-13 15:07:32 +01:00
|
|
|
}
|