예제 #1
0
// Objects returns an array of all used objects.
func (level *Level) Objects() []model.LevelObject {
	level.mutex.Lock()
	defer level.mutex.Unlock()

	var result []model.LevelObject

	for index, rawEntry := range level.objectList {
		if rawEntry.IsInUse() {
			entry := model.LevelObject{
				Identifiable: model.Identifiable{ID: fmt.Sprintf("%d", index)},
				Class:        int(rawEntry.Class),
				Subclass:     int(rawEntry.Subclass),
				Type:         int(rawEntry.Type)}

			entry.BaseProperties.TileX = int(rawEntry.X >> 8)
			entry.BaseProperties.FineX = int(rawEntry.X & 0xFF)
			entry.BaseProperties.TileY = int(rawEntry.Y >> 8)
			entry.BaseProperties.FineY = int(rawEntry.Y & 0xFF)
			entry.BaseProperties.Z = int(rawEntry.Z)

			entry.Hacking.Unknown0013 = bytesToIntArray(rawEntry.Unknown0013[:])
			entry.Hacking.Unknown0017 = bytesToIntArray(rawEntry.Unknown0017[:])

			meta := data.LevelObjectClassMetaEntry(rawEntry.Class)
			classStore := level.store.Get(res.ResourceID(4000 + level.id*100 + 10 + entry.Class))
			blockData := classStore.BlockData(0)
			startOffset := meta.EntrySize * int(rawEntry.ClassTableIndex)
			if (startOffset + meta.EntrySize) > len(blockData) {
				fmt.Printf("!!!!! class %d meta says %d bytes size, can't reach index %d in blockData %d",
					int(entry.Class), meta.EntrySize, rawEntry.ClassTableIndex, len(blockData))
			} else {
				entry.Hacking.ClassData = bytesToIntArray(blockData[startOffset+data.LevelObjectPrefixSize : startOffset+meta.EntrySize])
			}

			result = append(result, entry)
		}
	}

	return result
}
예제 #2
0
// AddObject adds a new object at given tile.
func (level *Level) AddObject(template *model.LevelObjectTemplate) (createdIndex int, err error) {
	level.mutex.Lock()
	defer level.mutex.Unlock()

	objID := res.MakeObjectID(res.ObjectClass(template.Class),
		res.ObjectSubclass(template.Subclass), res.ObjectType(template.Type))

	classMeta := data.LevelObjectClassMetaEntry(objID.Class)
	classStore := level.store.Get(res.ResourceID(4000 + level.id*100 + 10 + int(objID.Class)))
	classTable := logic.DecodeLevelObjectClassTable(classStore.BlockData(0), classMeta.EntrySize)
	classChain := classTable.AsChain()
	classIndex, classErr := classChain.AcquireLink()

	if classErr != nil {
		err = classErr
		return
	}
	classEntry := classTable.Entry(classIndex)
	classEntryData := classEntry.Data()
	for index := 0; index < len(classEntryData); index++ {
		classEntryData[index] = 0x00
	}

	objectIndex, objectErr := level.objectChain.AcquireLink()
	if objectErr != nil {
		classChain.ReleaseLink(classIndex)
		err = objectErr
		return
	}
	createdIndex = int(objectIndex)

	locations := []logic.TileLocation{logic.AtTile(uint16(template.TileX), uint16(template.TileY))}

	crossrefIndex, crossrefErr := level.crossrefList.AddObjectToMap(uint16(objectIndex), level.tileMap, locations)
	if crossrefErr != nil {
		classChain.ReleaseLink(classIndex)
		level.objectChain.ReleaseLink(objectIndex)
		err = crossrefErr
		return
	}
	crossrefEntry := level.crossrefList.Entry(crossrefIndex)

	objectEntry := &level.objectList[objectIndex]
	objectEntry.InUse = 1
	objectEntry.Class = objID.Class
	objectEntry.Subclass = objID.Subclass
	objectEntry.Type = objID.Type
	objectEntry.X = data.MapCoordinateOf(byte(template.TileX), byte(template.FineX))
	objectEntry.Y = data.MapCoordinateOf(byte(template.TileY), byte(template.FineY))
	objectEntry.Z = byte(template.Z)
	objectEntry.Rot1 = 0
	objectEntry.Rot2 = 0
	objectEntry.Rot3 = 0
	objectEntry.Hitpoints = 1

	objectEntry.CrossReferenceTableIndex = uint16(crossrefIndex)
	crossrefEntry.LevelObjectTableIndex = uint16(objectIndex)

	objectEntry.ClassTableIndex = uint16(classIndex)
	classEntry.LevelObjectTableIndex = uint16(objectIndex)

	classStore.SetBlockData(0, classTable.Encode())

	objWriter := bytes.NewBuffer(nil)
	binary.Write(objWriter, binary.LittleEndian, level.objectList)
	level.objectListStore.SetBlockData(0, objWriter.Bytes())

	level.crossrefListStore.SetBlockData(0, level.crossrefList.Encode())
	level.onTileDataChanged()

	return
}