Example #1
0
func (level *Level) getTileType(x, y int) data.TileType {
	tileType := data.Solid

	if (x >= 0) && (x < 64) && (y >= 0) && (y < 64) {
		entry := level.tileMap.Entry(logic.AtTile(uint16(x), uint16(y)))
		tileType = entry.Type
	}

	return tileType
}
Example #2
0
// SetTileProperties sets the properties of a specific tile.
func (level *Level) SetTileProperties(x, y int, properties model.TileProperties) {
	level.mutex.Lock()
	defer level.mutex.Unlock()

	entry := level.tileMap.Entry(logic.AtTile(uint16(x), uint16(y)))
	flags := uint32(entry.Flags)
	if properties.Type != nil {
		entry.Type = tileType(*properties.Type)
	}
	if properties.FloorHeight != nil {
		entry.Floor = (entry.Floor & 0xE0) | (byte(*properties.FloorHeight) & 0x1F)
	}
	if properties.CeilingHeight != nil {
		entry.Ceiling = (entry.Ceiling & 0xE0) | (byte(*properties.CeilingHeight) & 0x1F)
	}
	if properties.SlopeHeight != nil {
		entry.SlopeHeight = byte(*properties.SlopeHeight)
	}
	if properties.SlopeControl != nil {
		flags = (flags & ^uint32(0x00000C00)) | (uint32(slopeControl(*properties.SlopeControl)) << 10)
	}
	if properties.RealWorld != nil {
		var textureIDs = uint16(entry.Textures)

		if properties.RealWorld.FloorTexture != nil && (*properties.RealWorld.FloorTexture < 0x20) {
			textureIDs = (textureIDs & 0x07FF) | (uint16(*properties.RealWorld.FloorTexture) << 11)
		}
		if properties.RealWorld.FloorTextureRotations != nil {
			entry.Floor = (entry.Floor & 0x9F) | ((byte(*properties.RealWorld.FloorTextureRotations) & 0x3) << 5)
		}
		if properties.RealWorld.CeilingTexture != nil && (*properties.RealWorld.CeilingTexture < 0x20) {
			textureIDs = (textureIDs & 0xF83F) | (uint16(*properties.RealWorld.CeilingTexture) << 6)
		}
		if properties.RealWorld.CeilingTextureRotations != nil {
			entry.Ceiling = (entry.Ceiling & 0x9F) | ((byte(*properties.RealWorld.CeilingTextureRotations) & 0x3) << 5)
		}
		if properties.RealWorld.WallTexture != nil && (*properties.RealWorld.WallTexture < 0x40) {
			textureIDs = (textureIDs & 0xFFC0) | uint16(*properties.RealWorld.WallTexture)
		}
		if properties.RealWorld.UseAdjacentWallTexture != nil {
			flags = flags & ^uint32(0x00000100)
			if *properties.RealWorld.UseAdjacentWallTexture {
				flags |= 0x00000100
			}
		}
		if properties.RealWorld.WallTextureOffset != nil && *properties.RealWorld.WallTextureOffset < 0x20 {
			flags = (flags & ^uint32(0x0000001F)) | uint32(*properties.RealWorld.WallTextureOffset)
		}

		entry.Textures = data.TileTextureInfo(textureIDs)
	}
	entry.Flags = data.TileFlag(flags)

	level.onTileDataChanged()
}
Example #3
0
// TileProperties returns the properties of a specific tile.
func (level *Level) TileProperties(x, y int) (result model.TileProperties) {
	level.mutex.Lock()
	defer level.mutex.Unlock()

	entry := level.tileMap.Entry(logic.AtTile(uint16(x), uint16(y)))
	result.Type = new(model.TileType)
	*result.Type = tileTypes[entry.Type]
	result.SlopeHeight = new(model.HeightUnit)
	*result.SlopeHeight = model.HeightUnit(entry.SlopeHeight)
	result.FloorHeight = new(model.HeightUnit)
	*result.FloorHeight = model.HeightUnit(entry.Floor & 0x1F)
	result.CeilingHeight = new(model.HeightUnit)
	*result.CeilingHeight = model.HeightUnit(entry.Ceiling & 0x1F)
	result.SlopeControl = new(model.SlopeControl)
	*result.SlopeControl = slopeControls[data.SlopeControl((entry.Flags>>10)&0x3)]

	{
		result.CalculatedWallHeights = new(model.CalculatedWallHeights)
		result.CalculatedWallHeights.North = level.calculateWallHeight(entry, DirNorth, x, y+1, DirSouth)
		result.CalculatedWallHeights.East = level.calculateWallHeight(entry, DirEast, x+1, y, DirWest)
		result.CalculatedWallHeights.South = level.calculateWallHeight(entry, DirSouth, x, y-1, DirNorth)
		result.CalculatedWallHeights.West = level.calculateWallHeight(entry, DirWest, x-1, y, DirEast)
	}

	{
		var properties model.RealWorldTileProperties
		var textureIDs = uint16(entry.Textures)

		properties.WallTexture = new(int)
		*properties.WallTexture = int(textureIDs & 0x3F)
		properties.CeilingTexture = new(int)
		*properties.CeilingTexture = int((textureIDs >> 6) & 0x1F)
		properties.CeilingTextureRotations = new(int)
		*properties.CeilingTextureRotations = int((entry.Ceiling >> 5) & 0x03)
		properties.FloorTexture = new(int)
		*properties.FloorTexture = int((textureIDs >> 11) & 0x1F)
		properties.FloorTextureRotations = new(int)
		*properties.FloorTextureRotations = int((entry.Floor >> 5) & 0x03)

		properties.UseAdjacentWallTexture = new(bool)
		*properties.UseAdjacentWallTexture = (entry.Flags & 0x00000100) != 0
		properties.WallTextureOffset = new(model.HeightUnit)
		*properties.WallTextureOffset = model.HeightUnit(entry.Flags & 0x0000001F)

		result.RealWorld = &properties
	}

	return
}
Example #4
0
func (level *Level) calculateWallHeight(thisTile *data.TileMapEntry, thisDir Direction, otherX, otherY int, otherDir Direction) float32 {
	calculatedHeight := float32(0.0)

	if (solidDirections[thisTile.Type] & thisDir) == 0 {
		otherType := level.getTileType(otherX, otherY)

		if (solidDirections[otherType] & otherDir) == 0 {
			otherTile := level.tileMap.Entry(logic.AtTile(uint16(otherX), uint16(otherY)))
			thisCeilingHeight := level.calculatedCeilingHeight(thisTile, thisDir)
			otherCeilingHeight := level.calculatedCeilingHeight(otherTile, otherDir)
			thisFloorHeight := level.calculatedFloorHeight(thisTile, thisDir)
			otherFloorHeight := level.calculatedFloorHeight(otherTile, otherDir)

			if (thisCeilingHeight < otherCeilingHeight) ||
				((thisCeilingHeight == otherCeilingHeight) && thisFloorHeight < otherFloorHeight) {

				if (thisFloorHeight >= otherCeilingHeight) || (otherFloorHeight >= thisCeilingHeight) {
					calculatedHeight = 1.0
				} else {
					minFloorHeight := thisFloorHeight
					maxFloorHeight := otherFloorHeight
					minCeilingHeight := thisCeilingHeight
					if minFloorHeight > otherFloorHeight {
						minFloorHeight = otherFloorHeight
						maxFloorHeight = thisFloorHeight
					}
					if minCeilingHeight > otherCeilingHeight {
						minCeilingHeight = otherCeilingHeight
					}
					calculatedHeight = (float32(maxFloorHeight) - float32(minFloorHeight)) / (float32(minCeilingHeight) - float32(minFloorHeight))
				}

			}
		} else {
			calculatedHeight = 1.0
		}
	}

	return calculatedHeight
}
Example #5
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
}