diff --git a/d2common/d2interface/map_entity.go b/d2common/d2interface/map_entity.go new file mode 100644 index 00000000..926cd438 --- /dev/null +++ b/d2common/d2interface/map_entity.go @@ -0,0 +1,13 @@ +package d2interface + +// MapEntity is something that can be positioned on and rendered on the game map +type MapEntity interface { + Render(target Surface) + Advance(tickTime float64) + GetPosition() (float64, float64) + GetLayer() int + GetPositionF() (float64, float64) + Name() string + Selectable() bool + Highlight() +} diff --git a/d2core/d2asset/composite.go b/d2core/d2asset/composite.go index fb82813c..c3d349ab 100644 --- a/d2core/d2asset/composite.go +++ b/d2core/d2asset/composite.go @@ -138,7 +138,7 @@ func (c *Composite) SetDirection(direction int) { } } -// Direction returns the current direction the composite is facing +// GetDirection returns the current direction the composite is facing func (c *Composite) GetDirection() int { return c.direction } diff --git a/d2core/d2map/d2mapengine/engine.go b/d2core/d2map/d2mapengine/engine.go index 13bfe073..2b951e09 100644 --- a/d2core/d2map/d2mapengine/engine.go +++ b/d2core/d2map/d2mapengine/engine.go @@ -7,10 +7,10 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" - "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapstamp" "github.com/OpenDiablo2/OpenDiablo2/d2common" @@ -21,7 +21,7 @@ import ( // Represents the map data for a specific location type MapEngine struct { seed int64 // The map seed - entities []d2mapentity.MapEntity // Entities on the map + entities []d2interface.MapEntity // Entities on the map tiles []d2ds1.TileRecord // The map tiles size d2common.Size // The size of the map, in tiles levelType d2datadict.LevelTypeRecord // The level type of this map @@ -48,7 +48,7 @@ func (m *MapEngine) GetStartingPosition() (int, int) { } func (m *MapEngine) ResetMap(levelType d2enum.RegionIdType, width, height int) { - m.entities = make([]d2mapentity.MapEntity, 0) + m.entities = make([]d2interface.MapEntity, 0) m.levelType = d2datadict.LevelTypes[levelType] m.size = d2common.Size{Width: width, Height: height} m.tiles = make([]d2ds1.TileRecord, width*height) @@ -190,7 +190,7 @@ func (m *MapEngine) TileAt(tileX, tileY int) *d2ds1.TileRecord { } // Returns a reference to the map entities -func (m *MapEngine) Entities() *[]d2mapentity.MapEntity { +func (m *MapEngine) Entities() *[]d2interface.MapEntity { return &m.entities } @@ -200,12 +200,12 @@ func (m *MapEngine) Seed() int64 { } // Adds an entity to the map engine -func (m *MapEngine) AddEntity(entity d2mapentity.MapEntity) { +func (m *MapEngine) AddEntity(entity d2interface.MapEntity) { m.entities = append(m.entities, entity) } // Removes an entity from the map engine -func (m *MapEngine) RemoveEntity(entity d2mapentity.MapEntity) { +func (m *MapEngine) RemoveEntity(entity d2interface.MapEntity) { if entity == nil { return } diff --git a/d2core/d2map/d2mapentity/map_entity.go b/d2core/d2map/d2mapentity/map_entity.go index 5fcf376a..d5c0a1b0 100644 --- a/d2core/d2map/d2mapentity/map_entity.go +++ b/d2core/d2map/d2mapentity/map_entity.go @@ -3,23 +3,10 @@ package d2mapentity import ( "math" - "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" - "github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2astar" ) -type MapEntity interface { - Render(target d2interface.Surface) - Advance(tickTime float64) - GetPosition() (float64, float64) - GetLayer() int - GetPositionF() (float64, float64) - Name() string - Selectable() bool - Highlight() -} - // mapEntity represents an entity on the map that can be animated type mapEntity struct { LocationX float64 diff --git a/d2core/d2map/d2mapstamp/stamp.go b/d2core/d2map/d2mapstamp/stamp.go index 4b333e1c..b89c6222 100644 --- a/d2core/d2map/d2mapstamp/stamp.go +++ b/d2core/d2map/d2mapstamp/stamp.go @@ -5,12 +5,14 @@ import ( "math/rand" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity" + "github.com/OpenDiablo2/OpenDiablo2/d2core/d2object" "github.com/OpenDiablo2/OpenDiablo2/d2common" "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/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" ) @@ -111,8 +113,8 @@ func (mr *Stamp) TileData(style int32, sequence int32, tileType d2enum.TileType) return nil } -func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2mapentity.MapEntity { - entities := make([]d2mapentity.MapEntity, 0) +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) { @@ -139,7 +141,7 @@ func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2mapentity.MapEntity objectRecord := d2datadict.Objects[lookup.ObjectsTxtId] if objectRecord != nil { - entity, err := d2mapentity.CreateObject((tileOffsetX*5)+object.X, + entity, err := d2object.CreateObject((tileOffsetX*5)+object.X, (tileOffsetY*5)+object.Y, objectRecord, d2resource.PaletteUnits) if err != nil { diff --git a/d2core/d2object/init_function.go b/d2core/d2object/init_function.go new file mode 100644 index 00000000..6429f6c5 --- /dev/null +++ b/d2core/d2object/init_function.go @@ -0,0 +1,37 @@ +package d2object + +import ( + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" +) + +// Finds an init function for the given object +func initObject(ob *Object) bool { + funcs := map[int]func(*Object){ + 8: initTorch, + 14: initTorch, + 17: initWaypoint, + } + + fun, ok := funcs[ob.objectRecord.InitFn] + if !ok { + return false + } + + fun(ob) + + return true +} + +// Initializes torch/brazier type objects +func initTorch(ob *Object) { + if ob.objectRecord.HasAnimationMode[d2enum.AnimationModeObjectOperating] { + ob.setMode("ON", 0) + } +} + +func initWaypoint(ob *Object) { + // Turn these on unconditionally for now, they look nice :) + if ob.objectRecord.HasAnimationMode[d2enum.AnimationModeObjectOperating] { + ob.setMode("ON", 0) + } +} diff --git a/d2core/d2map/d2mapentity/object.go b/d2core/d2object/object.go similarity index 56% rename from d2core/d2map/d2mapentity/object.go rename to d2core/d2object/object.go index 2956c994..3c60df2c 100644 --- a/d2core/d2map/d2mapentity/object.go +++ b/d2core/d2object/object.go @@ -1,6 +1,10 @@ -package d2mapentity +// Package d2object implements objects placed on the map and their functionality +package d2object import ( + "math" + + "github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" @@ -10,26 +14,34 @@ import ( // Object represents a composite of animations that can be projected onto the map. type Object struct { - mapEntity - composite *d2asset.Composite - direction int - highlight bool + composite *d2asset.Composite + highlight bool + LocationX float64 + LocationY float64 + TileX, TileY int // Coordinates of the tile the unit is within + subcellX, subcellY float64 // Subcell coordinates within the current tile // nameLabel d2ui.Label - objectLookup *d2datadict.ObjectLookupRecord objectRecord *d2datadict.ObjectRecord - objectType *d2datadict.ObjectTypeRecord + drawLayer int + name string } // CreateObject creates an instance of AnimatedComposite func CreateObject(x, y int, objectRec *d2datadict.ObjectRecord, palettePath string) (*Object, error) { + locX, locY := float64(x), float64(y) entity := &Object{ - mapEntity: createMapEntity(x, y), objectRecord: objectRec, - objectType: &d2datadict.ObjectTypes[objectRec.Index], - // nameLabel: d2ui.CreateLabel(renderer, d2resource.FontFormal11, d2resource.PaletteStatic), + LocationX: locX, + LocationY: locY, + subcellX: 1 + math.Mod(locX, 5), + subcellY: 1 + math.Mod(locY, 5), + TileX: x / 5, + TileY: y / 5, + name: d2common.TranslateString(objectRec.Name), } + objectType := &d2datadict.ObjectTypes[objectRec.Index] - composite, err := d2asset.LoadComposite(d2enum.ObjectTypeItem, entity.objectType.Token, + composite, err := d2asset.LoadComposite(d2enum.ObjectTypeItem, objectType.Token, d2resource.PaletteUnits) if err != nil { return nil, err @@ -37,24 +49,15 @@ func CreateObject(x, y int, objectRec *d2datadict.ObjectRecord, palettePath stri entity.composite = composite - entity.mapEntity.directioner = entity.rotate - entity.drawLayer = entity.objectRecord.OrderFlag[d2enum.AnimationModeObjectNeutral] - entity.setMode("NU", 0) - // stop torches going crazy for now - // need initFunc handling to set objects up properly - if objectRec.HasAnimationMode[d2enum.AnimationModeObjectOpened] { - entity.setMode("ON", 0) - } + initObject(entity) return entity, nil } // setMode changes the graphical mode of this animated entity func (ob *Object) setMode(animationMode string, direction int) error { - ob.direction = direction - err := ob.composite.SetMode(animationMode, "HTH") if err != nil { return err @@ -63,7 +66,7 @@ func (ob *Object) setMode(animationMode string, direction int) error { ob.composite.SetDirection(direction) mode := d2enum.ObjectAnimationModeFromString(animationMode) - ob.mapEntity.drawLayer = ob.objectRecord.OrderFlag[mode] + ob.drawLayer = ob.objectRecord.OrderFlag[d2enum.AnimationModeObjectNeutral] // For objects their txt record entry overrides animationdata speed := ob.objectRecord.FrameDelta[mode] @@ -86,14 +89,11 @@ func (ob *Object) Selectable() bool { // Render draws this animated entity onto the target func (ob *Object) Render(target d2interface.Surface) { target.PushTranslation( - ob.offsetX+int((ob.subcellX-ob.subcellY)*16), - ob.offsetY+int(((ob.subcellX+ob.subcellY)*8)-5), + int((ob.subcellX-ob.subcellY)*16), + int(((ob.subcellX + ob.subcellY) * 8)), ) if ob.highlight { - // ob.nameLabel.SetText(d2common.TranslateString(ob.objectRecord.Name)) - // ob.nameLabel.SetPosition(-50, -50) - // ob.nameLabel.Render(target) target.PushBrightness(2) defer target.Pop() } @@ -103,10 +103,27 @@ func (ob *Object) Render(target d2interface.Surface) { ob.highlight = false } -// rotate sets direction and changes animation -func (ob *Object) rotate(direction int) { -} - +// Advance updates the animation func (ob *Object) Advance(elapsed float64) { ob.composite.Advance(elapsed) } + +// GetLayer returns which layer of the map the object is drawn +func (ob *Object) GetLayer() int { + return ob.drawLayer +} + +// GetPosition of the object +func (ob *Object) GetPosition() (x, y float64) { + return float64(ob.TileX), float64(ob.TileY) +} + +// GetPositionF of the object but differently +func (ob *Object) GetPositionF() (x, y float64) { + return float64(ob.TileX) + (ob.subcellX / 5.0), float64(ob.TileY) + ob.subcellY/5.0 +} + +// Name gets the name of the object +func (ob *Object) Name() string { + return ob.name +}