Files
questshock/modding/hacked/ss1/content/archive/level/ObjectMainTable.go
T

161 lines
3.8 KiB
Go

package level
import "github.com/inkyblackness/hacked/ss1/content/object"
const (
// ObjectMainEntrySize describes the size, in bytes, of a ObjectMainEntry.
ObjectMainEntrySize = 27
defaultObjectMainEntryCount = 872
)
// ObjectMainEntryModifier is a function that changes properties.
type ObjectMainEntryModifier func(*ObjectMainEntry)
// ObjectMainEntry describes an object in the level.
type ObjectMainEntry struct {
InUse byte
Class object.Class
Subclass object.Subclass
ClassTableIndex int16
CrossReferenceTableIndex int16
Next ObjectID
Prev ObjectID
X Coordinate
Y Coordinate
Z HeightUnit
XRotation RotationUnit
ZRotation RotationUnit
YRotation RotationUnit
_ byte
Type object.Type
Hitpoints int16
Extra [4]byte
}
// Triple returns the unique identifier of the entry.
func (entry ObjectMainEntry) Triple() object.Triple {
return object.TripleFrom(int(entry.Class), int(entry.Subclass), int(entry.Type))
}
// TilePosition returns the tile coordinates of the object.
func (entry ObjectMainEntry) TilePosition() TilePosition {
return TilePosition{X: entry.X.Tile(), Y: entry.Y.Tile()}
}
// FinePosition returns the coordinates of the object within the tile.
func (entry ObjectMainEntry) FinePosition() FinePosition {
return FinePosition{X: entry.X.Fine(), Y: entry.Y.Fine()}
}
// Reset clears the entry and resets all members.
func (entry *ObjectMainEntry) Reset() {
*entry = ObjectMainEntry{}
}
// ObjectMainTable is a list of entries.
// The first entry is reserved for internal use. For the reserved entry,
// the Next field refers to the head of the single-linked free chain,
// and the CrossReferenceTableIndex refers to the head of the double-linked used chain.
type ObjectMainTable []ObjectMainEntry
// DefaultObjectMainTable returns an initialized table with a default size.
func DefaultObjectMainTable() ObjectMainTable {
table := make(ObjectMainTable, defaultObjectMainEntryCount)
table.Reset()
return table
}
// Capacity returns the number of how many objects the table can hold.
func (table ObjectMainTable) Capacity() int {
size := len(table)
if size < 2 {
return 0
}
return size - 1
}
// AllocatedCount returns the number of how many objects are currently allocated in the table.
func (table ObjectMainTable) AllocatedCount() int {
capacity := table.Capacity()
if capacity == 0 {
return 0
}
index := int(table[0].CrossReferenceTableIndex)
count := 0
for (index != 0) && (count < capacity) {
count++
index = int(table[index].Next)
}
return count
}
// Reset wipes the entire table and initializes all links.
func (table ObjectMainTable) Reset() {
tableLen := len(table)
for i := 0; i < tableLen; i++ {
entry := &table[i]
entry.Reset()
entry.Next = ObjectID(i + 1)
}
if tableLen > 0 {
table[tableLen-1].Next = 0
}
}
// Allocate attempts to find an available entry in the table and activates it.
// Returns 0 if not possible (exhausted).
func (table ObjectMainTable) Allocate() ObjectID {
if len(table) < 2 {
return 0
}
start := &table[0]
if start.Next == 0 {
return 0
}
id := start.Next
entry := &table[id]
start.Next = entry.Next
entry.Reset()
entry.Next = ObjectID(start.CrossReferenceTableIndex)
table[start.CrossReferenceTableIndex].Prev = id
entry.Prev = 0
start.CrossReferenceTableIndex = int16(id)
entry.InUse = 1
return id
}
// Release deactivates the entry with given ID.
func (table ObjectMainTable) Release(id ObjectID) {
if (id < 1) || (int(id) >= len(table)) {
return
}
start := &table[0]
entry := &table[id]
if entry.InUse == 0 {
return
}
if entry.Prev == 0 {
start.CrossReferenceTableIndex = int16(entry.Next)
} else {
table[entry.Prev].Next = entry.Next
}
table[entry.Next].Prev = entry.Prev
entry.Reset()
entry.Next = start.Next
start.Next = id
}