Files
d2go/pkg/memory/object.go
elb 2eeee0cf1f Npc/Monsters Mode and Portals destination + optimization (#49)
* Added States for monsters and corpses

Now can properly identify if a corpse is interactable with a skill ( barbarian, necromancer)
Also getting states about monsters  : Exemple  Soul Killer with Conviction aura:   State  28 // conviction

Also can tell if monster has a state after you used a skill on it  Exemple:   State 56  Terror ( After using Barbarian skill Howl to fear )

Another Exemple  using Grief on Mephistos he now have  states :    2 poison
    52  Preventheal

will be very useful for further development.

* Added modes to player

Now accessible in koolo using : s.data.PlayerUnit.Mode

Those are Modes for player:
const Death: 0;
        const StandingOutsideTown: 1;
        const Walking: 2;
        const Running: 3;
        const GettingHit: 4;
        const StandingInTown: 5;
        const WalkingInTown: 6;
        const Attacking1: 7;
        const Attacking2: 8;
        const Blocking: 9;
        const CastingSkill: 10;
        const ThrowingItem: 11;
        const Kicking: 12;
        const UsingSkill1: 13;
        const UsingSkill2: 14;
        const UsingSkill3: 15;
        const UsingSkill4: 16;
        const Dead: 17;
        const SkillActionSequence: 18;
        const KnockedBack: 19;

* update Added alias(const) for player modes

can be used like this s.data.PlayerUnit.Mode == mode.StandingInTown

* added modes to object

0 = Object idle
1 = Object operating
2 = Object opened
3 = Object special 1    ?? to be determined what it does exactly
4 = Object special 2    ?? to be determined what it does exactly
5 = Object special 3    ?? to be determined what it does exactly
6 = Object special 4    ?? to be determined what it does exactly
7 = Object special 5    ?? to be determined what it does exactly

* update object mode strings

* Update object_mode.go

* Update object_mode.go

* update object modes again. accurate now

* Added IsSealBoss()  for Chaos Run

* Npc/Monster Modes and Portals destination
also IsEscapingType()  Monster cannot be attacked when airborne or hide in water (NpcMode 8)

* Npc/Monster Modes and Portals destination
also IsEscapingType()  Monster cannot be attacked when airborne or hide in water (NpcMode 8)

* Optimized monsters.go and object.go
also catapults have been added to ignore list

* Tz Frigid Higland ingores added
2024-12-01 22:54:57 +09:00

100 lines
3.4 KiB
Go

package memory
import (
"sort"
"github.com/hectorgimenez/d2go/pkg/data/mode"
"github.com/hectorgimenez/d2go/pkg/data"
"github.com/hectorgimenez/d2go/pkg/data/area"
"github.com/hectorgimenez/d2go/pkg/data/object"
"github.com/hectorgimenez/d2go/pkg/utils"
)
func isPortal(txtFileNo int) bool {
desc, ok := object.Desc[txtFileNo]
return ok && desc.Name == "Portal"
}
func (gd *GameReader) Objects(playerPosition data.Position, hover data.HoverData) []data.Object {
baseAddr := gd.Process.moduleBaseAddressPtr + gd.offset.UnitTable + (2 * 1024)
unitTableBuffer := gd.Process.ReadBytesFromMemory(baseAddr, 128*8)
var objects []data.Object
for i := 0; i < 128; i++ {
objectOffset := 8 * i
objectUnitPtr := uintptr(ReadUIntFromBuffer(unitTableBuffer, uint(objectOffset), Uint64))
for objectUnitPtr > 0 {
// Read minimal data first to check object type
objectType := gd.Process.ReadUInt(objectUnitPtr+0x00, Uint32)
if objectType == 2 {
rawTxtFileNo := gd.Process.ReadUInt(objectUnitPtr+0x04, Uint32) // Extract actual txtFileNo
txtFileNo := rawTxtFileNo & 0xFFFF
unitID := gd.Process.ReadUInt(objectUnitPtr+0x08, Uint32)
objectMode := mode.ObjectMode(gd.Process.ReadUInt(objectUnitPtr+0x0c, Uint32))
unitDataPtr := uintptr(gd.Process.ReadUInt(objectUnitPtr+0x10, Uint64))
//This offset gives timer for each mode to keep progress in real time. exemple: Mode.Operating fresh timer then Mode.Opened new timer (for objects)
// timerValue := uint32(gd.Process.ReadUInt(objectUnitPtr+0x5C, Uint32))
// Path and position data
pathPtr := uintptr(gd.Process.ReadUInt(objectUnitPtr+0x38, Uint64))
// Coordinates (X, Y)
posX := gd.Process.ReadUInt(pathPtr+0x10, Uint16)
posY := gd.Process.ReadUInt(pathPtr+0x14, Uint16)
var shrineData object.ShrineData
var portalData object.PortalData
interactType := gd.Process.ReadUInt(unitDataPtr+0x08, Uint8)
owner := gd.Process.ReadStringFromMemory(unitDataPtr+0x34, 32)
// Handle portals
if isPortal(int(txtFileNo)) {
destArea := area.ID(gd.Process.ReadUInt(unitDataPtr+0x08, Uint8))
portalData.DestArea = destArea
// Handle Shrines
} else {
shrineTextPtr := uintptr(gd.Process.ReadUInt(objectUnitPtr+0x0A, Uint64))
if shrineTextPtr > 0 {
shrineType := gd.Process.ReadUInt(unitDataPtr+0x08, Uint8)
shrineData = object.ShrineData{
ShrineName: object.ShrineTypeNames[object.ShrineType(shrineType)],
ShrineType: object.ShrineType(shrineType),
}
}
}
// Handle objects
objects = append(objects, data.Object{
ID: data.UnitID(unitID),
Name: object.Name(int(txtFileNo)),
IsHovered: data.UnitID(unitID) == hover.UnitID && hover.UnitType == 2 && hover.IsHovered,
InteractType: object.InteractType(interactType),
Shrine: shrineData,
Selectable: objectMode == mode.ObjectModeIdle,
Position: data.Position{
X: int(posX),
Y: int(posY),
},
Owner: owner,
Mode: objectMode,
PortalData: portalData,
})
}
objectUnitPtr = uintptr(gd.Process.ReadUInt(objectUnitPtr+0x150, Uint64))
}
}
if len(objects) > 0 {
sort.SliceStable(objects, func(i, j int) bool {
distanceI := utils.DistanceFromPoint(playerPosition, objects[i].Position)
distanceJ := utils.DistanceFromPoint(playerPosition, objects[j].Position)
return distanceI < distanceJ
})
}
return objects
}