1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-27 21:56:19 -04:00
OpenDiablo2/d2core/d2map/d2mapstamp/stamp.go
gravestench fc87b2be7a
Removing d2datadict singletons (#738)
* Remove weapons, armor, misc, itemCommon, itemTyps datadict singletons

- removed loader calls from d2app
- removed the HeroObjects singleton from `d2core/d2inventory`
- added an InventoryItemFactory in d2inventory
- package-level functions that use data records are now methods of the InventoryItemFactory
- renamed ItemGenerator in d2item to ItemFactory
- package-level functions that use records are now methods of ItemFactory
- d2map.MapEntityFactory now has an item factory instance for creating items
- fixed a bug in unique item record loader where it loaded an empty record
- added a PlayerStateFactory for creating a player state (uses the asset manager)
- updated the test inventory/equipment code in d2player to handle errors from the ItemFactory
- character select and character creation screens have a player state and inventory item factory
- updated item tests to use the item factory

* minor edit

* Removed d2datadict.Experience singleton

added a HeroStatsFactory, much like the other factories. The factory  gets an
asset manager reference in order to use data records.

* removed d2datadict.AutoMagic singleton

* removed d2datadict.AutoMap singleton

* removed d2datadict.BodyLocations singleton

* removed d2datadict.Books singleton

* Removed singletons for level records

- removed loader calls in d2app
- changed type references from d2datadict to d2records
- added a `MapGenerator` in d2mapgen which uses thew asset manager and map engine
- package-level map generation functions are now MapGenerator methods
- `d2datadict.GetLevelDetails(id int)` is now a method of the RecordManager

* remove SkillCalc and MissileCalc singletons

* Removed CharStats and ItemStatCost singletons

- added an ItemStatFactory which uses the asset manager to create stats
- package-level functions for stats in d2item are now StatFactory methods
- changed type references from d2datadict to d2records
- `d2player.GetAllPlayerStates` is now a method of the `PlayerStateFactory`

* Removed DkillDesc and Skills singletons from d2datadict

- removed loader calls from d2app
- diablo2stats.Stat instances are given a reference to the factory for doing record lookups

* update the stats test to use mock a asset manager and stat factory

* fixed diablo2stats tests and diablo2item tests

* removed CompCodes singleton from d2datadict

* remove cubemain singleton from d2datadict

* removed DifficultyLevels singleton from d2datadict

* removed ElemTypes singleton from d2datadict

* removed events.go loader from d2datadict (was unused)

* removed Gems singleton from d2datadict

* removed Hireling and Inventory singletons from d2datadict

* removed MagicPrefix and MagicSuffix singletons from d2datadict

* removed ItemRatios singleton from d2datadict

* removed Missiles singleton from d2datadict

* removed MonModes singleton

* Removed all monster and npc singletons from d2datadict

- MapStamp instances now get a reference to their factory for doing record lookups

* removed SoundEntry and SoundEnviron singletons from d2datadict
2020-09-20 17:52:01 -04:00

135 lines
4.2 KiB
Go

package d2mapstamp
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
)
const (
subtilesPerTile = 5
)
// Stamp represents a pre-fabricated map stamp that can be placed on a map.
type Stamp struct {
factory *StampFactory
entity *d2mapentity.MapEntityFactory
regionPath string // The file path of the region
regionID d2enum.RegionIdType
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
}
// Size returns the size of the stamp in tiles.
func (mr *Stamp) Size() d2geom.Size {
return d2geom.Size{Width: int(mr.ds1.Width), Height: int(mr.ds1.Height)}
}
// LevelPreset returns the level preset ID.
func (mr *Stamp) LevelPreset() d2records.LevelPresetRecord {
return mr.levelPreset
}
// LevelType returns the level type ID.
func (mr *Stamp) LevelType() d2records.LevelTypeRecord {
return mr.levelType
}
// RegionID returns the regionID
func (mr *Stamp) RegionID() d2enum.RegionIdType {
return mr.regionID
}
// RegionPath returns the file path of the region.
func (mr *Stamp) RegionPath() string {
return mr.regionPath
}
// Tile returns the tile at the given x and y tile coordinates.
func (mr *Stamp) Tile(x, y int) *d2ds1.TileRecord {
return &mr.ds1.Tiles[y][x]
}
// TileData returns the tile data for the tile with given style, sequence and type.
func (mr *Stamp) TileData(style, sequence int32, tileType d2enum.TileType) *d2dt1.Tile {
for idx := range mr.tiles {
tile := &mr.tiles[idx]
if tile.Style == style && tile.Sequence == sequence && tile.Type == int32(tileType) {
return tile
}
}
return nil
}
// Entities spawns all entities and objects in this tile on the map.
func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2interface.MapEntity {
entities := make([]d2interface.MapEntity, 0)
for _, object := range mr.ds1.Objects {
if object.Type == int(d2enum.ObjectTypeCharacter) {
monPreset := mr.factory.asset.Records.Monster.Presets[mr.ds1.Act][object.ID]
monstat := mr.factory.asset.Records.Monster.Stats[monPreset]
// 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.
npcX, npcY := (tileOffsetX*5)+object.X, (tileOffsetY*5)+object.Y
npc, err := mr.entity.NewNPC(npcX, npcY, monstat, 0)
if err == nil {
npc.SetPaths(convertPaths(tileOffsetX, tileOffsetY, object.Paths))
entities = append(entities, npc)
}
}
}
if object.Type == int(d2enum.ObjectTypeItem) {
// For objects the DS1 ID to objectID is hardcoded in the game
// use the lookup table
lookup := d2datadict.LookupObject(int(mr.ds1.Act), object.Type, object.ID)
if lookup == nil {
continue
}
objectRecord := d2datadict.Objects[lookup.ObjectsTxtId]
if objectRecord != nil {
entity, err := mr.entity.NewObject((tileOffsetX*5)+object.X,
(tileOffsetY*5)+object.Y, objectRecord, d2resource.PaletteUnits)
if err != nil {
panic(err)
}
entities = append(entities, entity)
}
}
}
return entities
}
func convertPaths(tileOffsetX, tileOffsetY int, paths []d2path.Path) []d2path.Path {
result := make([]d2path.Path, len(paths))
for i := 0; i < len(paths); i++ {
result[i].Action = paths[i].Action
result[i].Position = d2vector.NewPosition(
paths[i].Position.X()+float64(tileOffsetX*subtilesPerTile),
paths[i].Position.Y()+float64(tileOffsetY*subtilesPerTile))
}
return result
}