1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-04 01:07:18 -05:00
OpenDiablo2/d2core/d2map/d2mapengine/map_tile.go
gravestench 18c9e85cbc
d2game/d2player/ lint error cleanup (#788)
* d2game/d2player/inventory.go: magic number lint cleanup

* d2game/d2player/mini_panel.go: magic number lint cleanup

* d2game/d2player/skill_select_panel.go: lint cleanup

* d2game/d2player/skilltree.go: removed all lint errors

* removed the rest of the magic number errors from d2game

* hotfix for bug i added in map engine test

* all magic numbers removed (excluding  mapgen)
2020-10-25 00:42:31 -07:00

123 lines
2.8 KiB
Go

package d2mapengine
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
)
// MapTile is a tile placed on the map
type MapTile struct {
Components d2ds1.TileRecord
RegionType d2enum.RegionIdType
SubTiles [25]d2dt1.SubTileFlags
}
// GetSubTileFlags returns the tile flags for the given subtile
func (t *MapTile) GetSubTileFlags(x, y int) *d2dt1.SubTileFlags {
var subtileLookup = [5][5]int{
{20, 21, 22, 23, 24},
{15, 16, 17, 18, 19},
{10, 11, 12, 13, 14},
{5, 6, 7, 8, 9},
{0, 1, 2, 3, 4},
}
return &t.SubTiles[subtileLookup[y][x]]
}
// PrepareTile selects which graphic to use and updates the tiles subtileflags
func (t *MapTile) PrepareTile(x, y int, me *MapEngine) {
for wIdx := range t.Components.Walls {
wall := &t.Components.Walls[wIdx]
options := me.GetTiles(int(wall.Style), int(wall.Sequence), wall.Type)
if options == nil {
break
}
wall.RandomIndex = getRandomTile(options, x, y, me.seed)
for i := range t.SubTiles {
t.SubTiles[i].Combine(options[wall.RandomIndex].SubTileFlags[i])
}
}
for fIdx := range t.Components.Floors {
floor := &t.Components.Floors[fIdx]
options := me.GetTiles(int(floor.Style), int(floor.Sequence), 0)
if options == nil {
break
}
if options[0].MaterialFlags.Lava {
floor.Animated = true
floor.RandomIndex = 0
} else {
floor.RandomIndex = getRandomTile(options, x, y, me.seed)
}
for i := range t.SubTiles {
t.SubTiles[i].Combine(options[floor.RandomIndex].SubTileFlags[i])
}
}
for sIdx := range t.Components.Shadows {
shadow := &t.Components.Shadows[sIdx]
options := me.GetTiles(int(shadow.Style), int(shadow.Sequence), 13)
if options == nil {
break
}
shadow.RandomIndex = getRandomTile(options, x, y, me.seed)
for i := range t.SubTiles {
t.SubTiles[i].Combine(options[shadow.RandomIndex].SubTileFlags[i])
}
}
}
// Walker's Alias Method for weighted random selection with xorshifting for random numbers
// Selects a random tile from the slice, rest of args just used for seeding
func getRandomTile(tiles []d2dt1.Tile, x, y int, seed int64) byte {
var tileSeed uint64
tileSeed = uint64(seed) + uint64(x)
tileSeed *= uint64(y)
const (
xorshiftA = 13
xorshiftB = 17
xorshiftC = 5
)
tileSeed ^= tileSeed << xorshiftA
tileSeed ^= tileSeed >> xorshiftB
tileSeed ^= tileSeed << xorshiftC
weightSum := 0
for i := range tiles {
weightSum += int(tiles[i].RarityFrameIndex)
}
if weightSum == 0 {
return 0
}
random := tileSeed % uint64(weightSum)
sum := 0
for i := range tiles {
sum += int(tiles[i].RarityFrameIndex)
if sum >= int(random) {
return byte(i)
}
}
// This return shouldn't be hit
return 0
}