// regular minionexp
// [uid] [ monster id ] [ x ] [ y ] [HP] [len] [ unk ] [ uniq monst code ] [???-->
//byte[] data = {0xac, 0x99, 0x1e, 0x74, 0x9b, 0xc5, 0x01, 0x8b, 0x0e, 0xc7, 0x13, 0x80, 0x17, 0x11, 0x20, 0x40, 0x64, 0xc0, 0x51, 0x00, 0x00, 0x00, 0x00};
//byte[] data = {0xac, 0x31, 0x93, 0x87, 0x4e, 0xc5, 0x01, 0x90, 0x0e, 0xc6, 0x13, 0x80, 0x17, 0x11, 0x08, 0x40, 0x64, 0xc0, 0x51, 0x00, 0x00, 0x00, 0x00};
// eldritch
// should be: extra fast, stone skin, extra strong, immune to cold
byte[] data = {0xac, 0x28, 0xa6, 0xf4, 0xd0, 0xc5, 0x01, 0x91, 0x0e, 0xc3, 0x13, 0x80, 0x1b, 0x11, 0x08, 0x40, 0x13, 0x03, 0x10, 0x60, 0xc0, 0x51, 0x60, 0x01, 0x50, 0x43, 0x00};
// pindle
// should be: fire enchanted, stone skin, lightning enchanted, immune to physical, immune to poison
//byte[] data = {0xac, 0x5a, 0x1d, 0x0b, 0x4c, 0xb8, 0x01, 0x4a, 0x27, 0x9f, 0x33, 0x80, 0x1b, 0x31, 0x60, 0xa0, 0xa1, 0x01, 0x10, 0x49, 0xe0, 0x88, 0xb0, 0x00, 0x60, 0xae, 0x04 };
// mephisto
//byte[] data = {0xac, 0x20, 0x0b, 0x3d, 0x98, 0xf2, 0x00, 0x87, 0x44, 0x82, 0x1f, 0x80, 0x19, 0xa1, 0xb0, 0x00, 0x00, 0x00, 0x60, 0x17, 0x0f, 0x69, 0x3c, 0xfc, 0x07};
/*
[1] (BYTE) ID
[5] (DWORD) Monster/NPC ID
[7] (WORD) Location X
[9] (WORD) Location Y
[11](BYTE) Life % // not sure?
[12](BYTE) Packet Length
(WORD) Unknown
(DWORD) A0 A1 01 10 - Always for pindle, unique boss code
(BYTE) Status codes - varies on how much each boss has, most I've seen is 3, so if a boss has 3 status codes, you'll have 3 bytes extra in the packet
(BYTE) B0 - This tells us that the status codes come to an end.
(BYTE) 00 - Always, unknown
(WORD) Unknown
(BYTE) 00 to 06 - always.
*/
NPC npc = new NPC();
npc.UID = BitConverter.ToUInt32(data, 1);
npc.ID = (NPCCode)BitConverter.ToUInt16(data, 5);
npc.X = BitConverter.ToUInt16(data, 7);
npc.Y = BitConverter.ToUInt16(data, 9);
npc.Life = data[10];
//int length = data[12];
//data[14] = unknown
uint ChampionID = BitConverter.ToUInt32(data, 18);
int mod1 = data[19];
int mod2 = data[20];
int mod3 = data[21];
int mod4 = data[22];
I'm trying to make sense of the packet after the 18th byte (also life % would be nice to know--or is it 0-128?).
I found a couple old documents (I believe Ringo did) about this, but they seem to be for 1.10 or at least only have 1.10 values:
public enum MonsterAttribute
{
ExtraStrong = 0x28,
ExtraFast = 0x30,
Cursed = 0x38,
MagicResistance = 0x40,
FireEnhanced = 0x49,
LightningEnhanced = 0x88,
ColdEnhanced = 0x90,
ImmuneToPosion = 0xB8,
Thief = 0xC0,
ManaBurn = 0xC8,
Teleportation = 0xD0,
Specialhit = 0xD8,
StoneSkin = 0xE0,
MultipleShot = 0xE8,
AuraEnhanced = 0xF0
}
Thanks for any replies/suggestions :)
EDIT: Looking through D2Smells, I just found this: public enum MonsterMods
{
None = 0,
PhysicalImmune = 1,
MagicImmune = 2,
FireImmune = 4,
LightningImmune = 8,
ColdImmune = 16,
PoisonImmune = 32,
ExtraStrong = 64,
ExtraFast = 128,
Cursed = 254,
MagicResistant = 512,
FireEnchanted = 1024,
LightningEnchanted = 2048,
ColdEnchanted = 4096,
ManaBurn = 8192,
Teleportation = 16384,
SpectralHit = 32768,
StoneSkin = 65536,
MultiShot = 131072,
ConvictionAura = 262144,
MightAura = 524288,
HolyFireAura = 1048576,
BlessedAimAura = 2097152,
HolyFreezeAura = 4194304,
HolyShockAura = 8388608,
FanaticismAura = 16777216
}
It appears to be "bitwise" (is that what you call them?) flags--I'll see if I can't make sense of that.
EDIT #2: Using ET's enumeration, I got 1 mod for Eldritch right:
NPC npc = new NPC();
npc.UID = BitConverter.ToUInt32(data, 1);
npc.ID = (NPCCode)BitConverter.ToUInt16(data, 5);
npc.X = BitConverter.ToUInt16(data, 7);
npc.Y = BitConverter.ToUInt16(data, 9);
npc.Life = data[10];
//int length = data[12];
//data[14] = unknown
uint ChampionID = BitConverter.ToUInt32(data, 18);
uint mod1 = BitConverter.ToUInt32(data, 22);
List<MonsterMods> mods = new List<MonsterMods>();
foreach (int mod in Enum.GetValues(typeof(MonsterMods)))
{
if ((mod1 & mod) == mod)
mods.Add((MonsterMods)mod);
}
Produces:
- mods Count = 6 System.Collections.Generic.List<D2Data.MonsterMods>
[0] None D2Data.MonsterMods
[1] PoisonImmune D2Data.MonsterMods
[2] ExtraStrong D2Data.MonsterMods
[3] HolyFireAura D2Data.MonsterMods
[4] HolyFreezeAura D2Data.MonsterMods
[5] FanaticismAura D2Data.MonsterMods
Extra Strong is the only correct mod.
uh, I remember this being a kind of tricky one.
Btw, NPC's life (apart from in message 0x7F and maybe another) has to be devided by 1.28 to get the true percentage.
Also i think some of the higher bits in the start flag (1st word after the packets lengh) state if the NPC has a prefix/suffix/Appellation or is a Champion etc. (see UniquePrefix.txt, UniqueSuffix.txt and UniqueAppellation.txt)
Then right after the prefix's are the bonus enhancements. (the ones your trying to parse) These (I think) are stored in a byte array (8bits per code) and is null terminated (or 0xB0 terminated, one of the 2)
I cant remember what the last nibble does tho, nothing to important i dont think.
if d2 doesnt patch when the ladder resets tomorow, i will try dig up some old projects that could parse this.
hope this helps
Thanks a lot, I really appreciate a reply from you :)
I'll look at those text files you mentioned and see if I can't do it myself before tomorrow.
EDIT: MonUMod.txt looks like what I want--I'll keep going.
Quote from: Insolence on June 24, 2007, 12:06 PM
Thanks a lot, I really appreciate a reply from you :)
I'll look at those text files you mentioned and see if I can't do it myself before tomorrow.
EDIT: MonUMod.txt looks like what I want--I'll keep going.
Sorry I didnt reply back when I said I would, I have been kinda busy (hands up, Playing new ladder :P)
I had a quick dig around but I cant seem to find the project I had in mind.
However I managed to find some old notes from back when I was trying to determin a super unique monster from the stats string.
Just reading them brought back a few memorys, so I have tryed adding what I can remember about other types of enhanced monsters that can be.
(DWORD) NPC ID
(WORD) NPC Code
(WORD) NPC Spawn X
(WORD) NPC Spawn Y
(BYTE) NPC Life% (LifePer / 1.28)
(BYTE) Message Lengh
~~ Stats String ~~
(BITS[4]) Effect
0 = unknown (never is 0?)
1 = normal
2 = normal
3 = get hit
4 = shoot missile
5 = melee punch
6 = dodge/block attack
7 = invisible (animation that test NPC did not support)
8 = raise from floor
9 = invisible (animation that test NPC did not support)
10 = invisible (animation that test NPC did not support)
11 = invisible (animation that test NPC did not support)
12 = Dead on floor in pile (corpse)
13 = stands montionless/1 frame animation (for IE, if the npc was frozen when it came inview)
14 = normal?
15 = normal?
(BITS[4]) BaseFlag
if 0 then stop.
If 1st bit then monster has extra batterys/stats up its ass?
some combo with the 2nd, 3rd and 4th bit (somtimes 1st), can efect lengh(below)
(BITS[X]) unknown
relates to animation effects and verys in lengh, depending on the NPC code
normaly around 20 bits long?
(BITS[8]) MonFlag
bit 1 = unknown?
bit 2 = unknown?
bit 3 = if not set, monster is normal? (effects later decodeing)
bit 4 = Is Champion
bit 5 = Is Super prefixed
bit 6 = Is Super unique (bit 5 must be set, other wise normal monster?)
bit 7 = Is Minion
bit 8 = Is Cloaked
'For super uniques (such as eldritch) - (prefix'ed NPC's work abit like this to i think)
(BITS[13]) Super unique code
Line number (0 based) to SuperUniques.txt
this line number is NOT 13 bits long, its around 7 - 9 bits, the end nibble is unknown
Do Untill (Enhancments = 0) Or (Enhancments = 0xB0)
(BITS[8]) Enhancment
0x28 = Extra Strong
0x30 = Extra Fast
0x38 = Cursed
0x40 = Magic Res
0x48/0x49 = Fire Enhanced
0x88 = Lightning Enhanced
0x90 = Cold Enhanced
0xB0 = End Of Enhancements
0xB8 = Psn Immune
0xC0 = Thief
0xC8 = Mana Burn
0xD0 = Teleportation
0xD8 = Special Hit
0xE0 = Stone Skin
0xE8 = Multiple Shot
0xF0 = Aura Enhanced
Note, the enhancment is about 4 bits long
The 1st few bits might be a small flag (See fire-enhanced)
Also i think each enhancement pair/order can add a new bonus of its own here, not sure.
Loop
(BITS[8]) 0x00 (Enhancement terminator?)
(BITS[24]) unknown
I can remember this being really time consuming, due to the lack of info printed over an NPC.
Hopefully there is enough info here for you to do what your doing (if you havent done it already), but if you want to define the lower-quality (=< prefixed) unique monsters, then it shouldnt be to hard, with a few observations.
Im not 100% sure what your aiming to do. (im guessing just grab the enhancements/super unique code so you know eldritch when you see him?)
If I have missed out any notes, just shout what your unsure about or where your trying to get to.
Hope this helps
No problem, I've been super busy with the ladder too :D
I really appreciate you sharing this information with me; I'm basically using it to intelligently chicken. Chicken on immune, chicken on MSLE, etc. Also, to target monsters (not other harmless NPC's) and such. I think using the information from this is very important in a bot.
I couldn't figure out how to get all this stuff from packets correctly--sadly--but I figured this out using memory, finally. I still can't get whether or not he's immune to lightning, but this is something.
MonsterData struct:
[StructLayout(LayoutKind.Explicit)]
public struct MonsterData
{
[FieldOffset(0x00)] [MarshalAs(UnmanagedType.ByValArray, SizeConst=22)] public byte[] _1;
// Union
[FieldOffset(0x16)] public byte fFlags;
[FieldOffset(0x17)] public UInt16 _2;
[FieldOffset(0x18)] public uint _3;
[FieldOffset(0x1C)] [MarshalAs(UnmanagedType.ByValArray, SizeConst=9)] public byte[] anEnchants;
[FieldOffset(0x25)] public byte _4;
[FieldOffset(0x26)] public UInt16 wUniqueNo;
[FieldOffset(0x28)] public byte _5;
[FieldOffset(0x2C)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst=28)] public string wName;
}
Cast wUniqueNo to:
public enum UniqueMonster
{
Bishibosh,
Bonebreak,
Coldcrow,
Rakanishu,
TreeheadWoodFist,
Griswold,
TheCountess,
PitspawnFouldog,
FlamespikeTheCrawler,
Boneash,
Radament,
BloodwitchTheWild,
Fangskin,
Beetleburst,
Leatherarm,
ColdwormTheBurrower,
FireEye,
DarkElder,
TheSummoner,
AncientKaaTheSoulless,
TheSmith,
WebMageTheBurning,
WitchDoctorEndugu,
Stormtree,
SarinaTheBattlemaid,
IcehawkRiftwing,
IsmailVilehand,
GelebFlamefinger,
BremmSparkfist,
ToorcIcefist,
WyandVoidfinger,
MafferDragonhand,
WingedDeath,
TheTormentor,
Taintbreeder,
RiftwraithTheCannibal,
InfectorofSouls,
LordDeSeis,
GrandVizierofChaos,
TheCowKing,
Corpsefire,
TheFeatureCreep,
SiegeBoss,
AncientBarbarian1,
AncientBarbarian2,
AncientBarbarian3,
AxeDweller,
BonesawBreaker,
DacFarren,
MegaflowRectifier,
EyebackUnleashed,
ThreashSocket,
Pindleskin,
SnapchipShatter,
AnodizedElite,
VinvearMolech,
SharpToothSayer,
MagmaTorquer,
BlazeRipper,
Frozenstein,
NihlathakBoss,
BaalSubject1,
BaalSubject2,
BaalSubject3,
BaalSubject4,
BaalSubject5
}
And the anEnchants are:
public enum Enchant
{
None,
RndName,
HpMultiply,
Light,
LevelAdd,
Strong,
Fast,
Curse,
Resist,
Fire,
PoisonDead,
DurielDead,
BloodRaven,
Rage,
SpcDamage,
PartyDead,
Champion,
Lightning,
Cold,
Hireable,
Scarab,
KillSelf,
QuestComplete,
PoisonHit,
Thief,
ManaBurn,
Teleport,
SpectralHit,
StoneSkin,
MultiShot,
Aura,
GoBoom,
FireSpikeExplode,
SuicideMinionExplode,
AiAfterDeath,
ShatterOnDeath,
Ghostly,
Fanatic,
Possessed,
Berserk,
WormsOnDeath,
AlwaysRunAi,
LightningDeath
}
what's with the horribly annoying "[FieldOffset(0x17)]" stuff in your C# pastes?
Quote from: betawarz on July 17, 2007, 09:38 PM
what's with the horribly annoying "[FieldOffset(0x17)]" stuff in your C# pastes?
Not sure if I needed them in that struct (could've done sequential, I think), but I'm specifying specific offsets for unmanaged memory.
you mean that stuff is part of the C# compiler directives, or something? eww.
Quote from: betawarz on July 18, 2007, 11:20 AM
you mean that stuff is part of the C# compiler directives, or something? eww.
No. It's not part of the compiler.
may be a day the search button get life and start eating all us.
http://forum.valhallalegends.com/index.php?topic=15790.0
also it can success that a day u need to get the states soo u will ask for 0xaa instead of using the search button, http://forum.valhallalegends.com/index.php?topic=16228.0
and i think that all other questions that a new botmaker can do, have been asked and replyed by the members like ringo for hundreds of times.
Quote from: Insolence on July 17, 2007, 07:20 AM
I couldn't figure out how to get all this stuff from packets correctly--sadly--but I figured this out using memory, finally. I still can't get whether or not he's immune to lightning, but this is something.
MonsterData struct:
[StructLayout(LayoutKind.Explicit)]
public struct MonsterData
{
[FieldOffset(0x00)] [MarshalAs(UnmanagedType.ByValArray, SizeConst=22)] public byte[] _1;
// Union
[FieldOffset(0x16)] public byte fFlags;
[FieldOffset(0x17)] public UInt16 _2;
[FieldOffset(0x18)] public uint _3;
[FieldOffset(0x1C)] [MarshalAs(UnmanagedType.ByValArray, SizeConst=9)] public byte[] anEnchants;
[FieldOffset(0x25)] public byte _4;
[FieldOffset(0x26)] public UInt16 wUniqueNo;
[FieldOffset(0x28)] public byte _5;
[FieldOffset(0x2C)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst=28)] public string wName;
}
Cast wUniqueNo to:
public enum UniqueMonster
{
Bishibosh,
Bonebreak,
Coldcrow,
Rakanishu,
TreeheadWoodFist,
Griswold,
TheCountess,
PitspawnFouldog,
FlamespikeTheCrawler,
Boneash,
Radament,
BloodwitchTheWild,
Fangskin,
Beetleburst,
Leatherarm,
ColdwormTheBurrower,
FireEye,
DarkElder,
TheSummoner,
AncientKaaTheSoulless,
TheSmith,
WebMageTheBurning,
WitchDoctorEndugu,
Stormtree,
SarinaTheBattlemaid,
IcehawkRiftwing,
IsmailVilehand,
GelebFlamefinger,
BremmSparkfist,
ToorcIcefist,
WyandVoidfinger,
MafferDragonhand,
WingedDeath,
TheTormentor,
Taintbreeder,
RiftwraithTheCannibal,
InfectorofSouls,
LordDeSeis,
GrandVizierofChaos,
TheCowKing,
Corpsefire,
TheFeatureCreep,
SiegeBoss,
AncientBarbarian1,
AncientBarbarian2,
AncientBarbarian3,
AxeDweller,
BonesawBreaker,
DacFarren,
MegaflowRectifier,
EyebackUnleashed,
ThreashSocket,
Pindleskin,
SnapchipShatter,
AnodizedElite,
VinvearMolech,
SharpToothSayer,
MagmaTorquer,
BlazeRipper,
Frozenstein,
NihlathakBoss,
BaalSubject1,
BaalSubject2,
BaalSubject3,
BaalSubject4,
BaalSubject5
}
And the anEnchants are:
public enum Enchant
{
None,
RndName,
HpMultiply,
Light,
LevelAdd,
Strong,
Fast,
Curse,
Resist,
Fire,
PoisonDead,
DurielDead,
BloodRaven,
Rage,
SpcDamage,
PartyDead,
Champion,
Lightning,
Cold,
Hireable,
Scarab,
KillSelf,
QuestComplete,
PoisonHit,
Thief,
ManaBurn,
Teleport,
SpectralHit,
StoneSkin,
MultiShot,
Aura,
GoBoom,
FireSpikeExplode,
SuicideMinionExplode,
AiAfterDeath,
ShatterOnDeath,
Ghostly,
Fanatic,
Possessed,
Berserk,
WormsOnDeath,
AlwaysRunAi,
LightningDeath
}
Why not just use the cell sheets in the MPQ's for the names and such?
If I remember all the text data, aura info etc.. you could ever want is in them cell sheets.
Cell sheets? Err, you mean text files?
Which text files?
Mega bump, I still haven't figured this out (just gave up on it) -- I was wondering if I could get a few more hints about this part:
(BITS[4]) BaseFlag
if 0 then stop.
If 1st bit then monster has extra batterys/stats up its ass?
some combo with the 2nd, 3rd and 4th bit (somtimes 1st), can efect lengh(below)
(BITS[X]) unknown
relates to animation effects and verys in lengh, depending on the NPC code
normaly around 20 bits long?
Still working on it, will post what I figure out :)