2020-06-21 18:40:37 -04:00
|
|
|
package d2mapstamp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
|
2020-09-12 16:25:09 -04:00
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
|
2020-07-04 00:48:31 -04:00
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
2020-09-12 16:25:09 -04:00
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
|
2020-07-01 00:06:06 -04:00
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
2020-09-12 16:25:09 -04:00
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
2020-09-20 17:52:01 -04:00
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
|
2020-09-12 16:51:30 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
subtilesPerTile = 5
|
2020-06-21 18:40:37 -04:00
|
|
|
)
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// Stamp represents a pre-fabricated map stamp that can be placed on a map.
|
2020-06-21 18:40:37 -04:00
|
|
|
type Stamp struct {
|
2020-09-20 17:52:01 -04:00
|
|
|
factory *StampFactory
|
2020-09-12 16:51:30 -04:00
|
|
|
entity *d2mapentity.MapEntityFactory
|
2020-07-21 08:50:45 -04:00
|
|
|
regionPath string // The file path of the region
|
|
|
|
regionID d2enum.RegionIdType
|
2020-09-20 17:52:01 -04:00
|
|
|
levelType d2records.LevelTypeRecord // The level type id for this stamp
|
|
|
|
levelPreset d2records.LevelPresetRecord // The level preset id for this stamp
|
|
|
|
tiles []d2dt1.Tile // The tiles contained on this stamp
|
|
|
|
ds1 *d2ds1.DS1 // The backing DS1 file for this stamp
|
2020-06-21 18:40:37 -04:00
|
|
|
}
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// Size returns the size of the stamp in tiles.
|
2020-09-08 15:58:35 -04:00
|
|
|
func (mr *Stamp) Size() d2geom.Size {
|
|
|
|
return d2geom.Size{Width: int(mr.ds1.Width), Height: int(mr.ds1.Height)}
|
2020-06-21 18:40:37 -04:00
|
|
|
}
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// LevelPreset returns the level preset ID.
|
2020-09-20 17:52:01 -04:00
|
|
|
func (mr *Stamp) LevelPreset() d2records.LevelPresetRecord {
|
2020-06-21 18:40:37 -04:00
|
|
|
return mr.levelPreset
|
|
|
|
}
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// LevelType returns the level type ID.
|
2020-09-20 17:52:01 -04:00
|
|
|
func (mr *Stamp) LevelType() d2records.LevelTypeRecord {
|
2020-06-21 18:40:37 -04:00
|
|
|
return mr.levelType
|
|
|
|
}
|
|
|
|
|
2020-09-12 16:25:09 -04:00
|
|
|
// RegionID returns the regionID
|
2020-07-21 08:50:45 -04:00
|
|
|
func (mr *Stamp) RegionID() d2enum.RegionIdType {
|
|
|
|
return mr.regionID
|
|
|
|
}
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// RegionPath returns the file path of the region.
|
2020-06-21 18:40:37 -04:00
|
|
|
func (mr *Stamp) RegionPath() string {
|
|
|
|
return mr.regionPath
|
|
|
|
}
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// Tile returns the tile at the given x and y tile coordinates.
|
2020-06-21 18:40:37 -04:00
|
|
|
func (mr *Stamp) Tile(x, y int) *d2ds1.TileRecord {
|
|
|
|
return &mr.ds1.Tiles[y][x]
|
|
|
|
}
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// TileData returns the tile data for the tile with given style, sequence and type.
|
2020-07-17 18:51:19 -04:00
|
|
|
func (mr *Stamp) TileData(style, sequence int32, tileType d2enum.TileType) *d2dt1.Tile {
|
|
|
|
for idx := range mr.tiles {
|
|
|
|
tile := &mr.tiles[idx]
|
2020-06-21 18:40:37 -04:00
|
|
|
if tile.Style == style && tile.Sequence == sequence && tile.Type == int32(tileType) {
|
2020-07-17 18:51:19 -04:00
|
|
|
return tile
|
2020-06-21 18:40:37 -04:00
|
|
|
}
|
|
|
|
}
|
2020-07-09 16:11:01 -04:00
|
|
|
|
2020-06-21 18:40:37 -04:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-07-09 16:11:01 -04:00
|
|
|
// Entities spawns all entities and objects in this tile on the map.
|
2020-07-04 00:48:31 -04:00
|
|
|
func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2interface.MapEntity {
|
|
|
|
entities := make([]d2interface.MapEntity, 0)
|
2020-06-21 18:40:37 -04:00
|
|
|
|
|
|
|
for _, object := range mr.ds1.Objects {
|
2020-07-01 00:06:06 -04:00
|
|
|
if object.Type == int(d2enum.ObjectTypeCharacter) {
|
2020-09-20 17:52:01 -04:00
|
|
|
monPreset := mr.factory.asset.Records.Monster.Presets[mr.ds1.Act][object.ID]
|
|
|
|
monstat := mr.factory.asset.Records.Monster.Stats[monPreset]
|
2020-07-01 00:06:06 -04:00
|
|
|
// If monstat is nil here it is a place_ type object, idk how to handle those yet.
|
|
|
|
// (See monpreset and monplace txts for reference)
|
|
|
|
if monstat != nil {
|
|
|
|
// Temorary use of Lookup.
|
2020-07-17 18:51:19 -04:00
|
|
|
npcX, npcY := (tileOffsetX*5)+object.X, (tileOffsetY*5)+object.Y
|
2020-09-12 16:51:30 -04:00
|
|
|
npc, err := mr.entity.NewNPC(npcX, npcY, monstat, 0)
|
2020-07-17 18:51:19 -04:00
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
npc.SetPaths(convertPaths(tileOffsetX, tileOffsetY, object.Paths))
|
|
|
|
entities = append(entities, npc)
|
|
|
|
}
|
2020-06-21 18:40:37 -04:00
|
|
|
}
|
2020-07-01 00:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if object.Type == int(d2enum.ObjectTypeItem) {
|
|
|
|
// For objects the DS1 ID to objectID is hardcoded in the game
|
|
|
|
// use the lookup table
|
2020-09-20 20:30:27 -04:00
|
|
|
lookup := mr.factory.asset.Records.LookupObject(int(mr.ds1.Act), object.Type, object.ID)
|
2020-07-01 00:06:06 -04:00
|
|
|
|
|
|
|
if lookup == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-09-20 20:30:27 -04:00
|
|
|
objectRecord := mr.factory.asset.Records.Object.Details[lookup.ObjectsTxtId]
|
2020-07-01 00:06:06 -04:00
|
|
|
|
|
|
|
if objectRecord != nil {
|
2020-09-12 16:51:30 -04:00
|
|
|
entity, err := mr.entity.NewObject((tileOffsetX*5)+object.X,
|
2020-07-03 14:00:56 -04:00
|
|
|
(tileOffsetY*5)+object.Y, objectRecord, d2resource.PaletteUnits)
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-06-21 18:40:37 -04:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-06-21 18:40:37 -04:00
|
|
|
entities = append(entities, entity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return entities
|
|
|
|
}
|
|
|
|
|
2020-09-08 15:58:35 -04:00
|
|
|
func convertPaths(tileOffsetX, tileOffsetY int, paths []d2path.Path) []d2path.Path {
|
|
|
|
result := make([]d2path.Path, len(paths))
|
2020-06-22 19:33:12 -04:00
|
|
|
for i := 0; i < len(paths); i++ {
|
|
|
|
result[i].Action = paths[i].Action
|
2020-07-18 18:07:13 -04:00
|
|
|
result[i].Position = d2vector.NewPosition(
|
2020-09-12 16:51:30 -04:00
|
|
|
paths[i].Position.X()+float64(tileOffsetX*subtilesPerTile),
|
|
|
|
paths[i].Position.Y()+float64(tileOffsetY*subtilesPerTile))
|
2020-06-22 19:33:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|