Char Editor
Moderators: Nefarius, Havvoric
Char Editor
I have made so many changes to the texts that most char editors fail. So I decided that I would create my own and started moving through the d2s file structure post that has been provided. I noticed that making any minor change to the d2s file screws it over unless you edit the checksum. So, off I went hunting and found the following C++ code for the check sum.
viewtopic.php?f=8&t=7102&hilit=checksum
Is it still the correct code - that post is almost 9 years old?
If it is, is there an easier way to get the checksum rather than running through the entire file? IE if I change my Str from 10 to 50, surely I can reflect the 0x0a being changed to 0x32 without going through the whole file??? If not, I'll live with it.
viewtopic.php?f=8&t=7102&hilit=checksum
Is it still the correct code - that post is almost 9 years old?
If it is, is there an easier way to get the checksum rather than running through the entire file? IE if I change my Str from 10 to 50, surely I can reflect the 0x0a being changed to 0x32 without going through the whole file??? If not, I'll live with it.
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
one of the easy way is to modify Udietoo. That's what I did for another mod editor.
That's pretty simple, to resume, you just change the path looking for patch_d2.mpq to your custom patch. In this new patch, you store your mod files.
That's pretty simple, to resume, you just change the path looking for patch_d2.mpq to your custom patch. In this new patch, you store your mod files.
Re: Char Editor
I dont give out the texts for my mod. So I have to create something for someone if he/she wants to try out the mod.
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
the hash is still correct, but its not needed unless you've changed the savefile structure, thats the only thing that really breaks the editors.
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
Well, I wasn't going to post this right away until I was ready to tackle the checksum but I guess, it's time. I have changed the structure.
A) Chars are created with a custom potion that allows them to customize their stats at creation. I save a 32 bit itemstat flag to the save file to prohibit multiple uses of the potion.
B) Every char has a class specific quest that is tied to defeating a particular boss who drops a potion. The potion saves another 32 bit itemstat counter to the save file that opens up special skills. This counter is increased in Norm, NM, and Hell.
So my first question - where is this information saved in the file? At the end? Is it's location in the savefile tied to the itemstat id? Or do I just guess and test?
I'll ask more questions when I get ready to actually calculate it (to make sure I understand that post.)
A) Chars are created with a custom potion that allows them to customize their stats at creation. I save a 32 bit itemstat flag to the save file to prohibit multiple uses of the potion.
B) Every char has a class specific quest that is tied to defeating a particular boss who drops a potion. The potion saves another 32 bit itemstat counter to the save file that opens up special skills. This counter is increased in Norm, NM, and Hell.
So my first question - where is this information saved in the file? At the end? Is it's location in the savefile tied to the itemstat id? Or do I just guess and test?
I'll ask more questions when I get ready to actually calculate it (to make sure I understand that post.)
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
thats not what I meant by changing the structure, I meant that you have literally changed the structure by recoding it(ie: my skills aren't saved as an slvl, they are an id+slvl).
That data is saved in the character statstream section, which is at a variable position in the file (as it has streams before and after it).
That data is saved in the character statstream section, which is at a variable position in the file (as it has streams before and after it).
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
Ok. So a question. Is there any defining byte that marks the start of the character statstream? I'm assuming that the extra bytes I am saving to the file are in the same place relative to the start of the character statstream. If this assumption is wrong, got any hints for me? Thank you.
EDIT: Is OneInTen's description of the bitfield for char stats correct?
viewtopic.php?f=8&t=9011&start=50
My Itemstatcost has 29s rather than 31s for the last two entries.
EDIT: Is OneInTen's description of the bitfield for char stats correct?
viewtopic.php?f=8&t=9011&start=50
My Itemstatcost has 29s rather than 31s for the last two entries.
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
There is a defineing WORD used to indicate each section start. as for that topic, its right for vanilla, but everything you need is in itemstatcost, just note that stats with no value aren't saved.
see this: viewtopic.php?f=8&t=9011
see this: viewtopic.php?f=8&t=9011
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
EDIT: I think I got. What a weird way of reading a string. Off to confirm the next stat.
EDIT 2: Yup I got it. Wow. Talking about making life difficult for yourself.
Ok Binary string time.
The pic below shows the stat section of the char save file.
Taking the first four bytes after the stream maker "67 66" I have
00 60 09 10
I converted each byte into bits getting
0000 0000 0110 0000 0000 1001 0001 0000
According to this post
I then take the next 10 bits = 11 0000 0000 = which should equal the value of the str on my char.
Sadly 11 0000 0000 = 768 not 176 which is the current str on my char.
If I reverse the bits, I get 00 0000 0011 = 3
I'm not sure what I'm doing wrong. Any help would be appreciated.
EDIT 2: Yup I got it. Wow. Talking about making life difficult for yourself.
Ok Binary string time.
The pic below shows the stat section of the char save file.
Taking the first four bytes after the stream maker "67 66" I have
00 60 09 10
I converted each byte into bits getting
0000 0000 0110 0000 0000 1001 0001 0000
According to this post
So I take the first 9 bits = 0 0000 0000 = the str itemstat id of 0OneInTen" wrote:OK, I've traced through the save routine and decoded the stats portion of the save file.The way to use this table is that the game stores the ID in 9 bits, followed by the value in the number of bits indicated by width.Code: Select all
ID Desc Width 00 Str 10 01 Dex 10 02 Con 10 03 Energy 10 04 Skill pts 10 05 Stat pts 8 06 HP current 21 07 HP base 21 08 Mana current 21 09 Mana base 21 10 Stamina current 21 11 Stamina base 21 12 Level 7 13 XP 32 14 Gold inventory 31 15 Gold stash 31
I then take the next 10 bits = 11 0000 0000 = which should equal the value of the str on my char.
Sadly 11 0000 0000 = 768 not 176 which is the current str on my char.
If I reverse the bits, I get 00 0000 0011 = 3
I'm not sure what I'm doing wrong. Any help would be appreciated.
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
you need to use the CVsSaveBits column as the width, not that table.
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
Ok so this is where I'm at.
The numbers are correct.
The Life and Max Life sections look funny but thats because life is mostly controlled via a passive skill and not charstats so the base never changes even if your life is 4242/4242 when you save the game.
WP Level is an anti rushing feature. WPs will kill you if you are too low of a level.
The Potion of Destiny allows you to customize your character upon creation.
The Elixir of Grace enables stat potions to be used.
There are three class specific quests that I added. If you do the quest, you can access to some locked skills.
All and all, everything is correct, though I forgot to add a section for the number of Skill Tomes read... tomorrow's job.
I was reading in the save file structure thread and the thread seems to focus on the item stream. I would prefer to go after the wp stream or quest stream next. Do you know where any information is on the WP stream and how it's organized? That particular thread doesnt really offer much other than where the stream starts and finishes. I found something awhile ago posted by Paul but I forgot to save his page. His page was not hosted on this site but on his own private one with a link to it somewhere around here.
Any help/suggestions/guidance is appreciated.
The numbers are correct.
The Life and Max Life sections look funny but thats because life is mostly controlled via a passive skill and not charstats so the base never changes even if your life is 4242/4242 when you save the game.
WP Level is an anti rushing feature. WPs will kill you if you are too low of a level.
The Potion of Destiny allows you to customize your character upon creation.
The Elixir of Grace enables stat potions to be used.
There are three class specific quests that I added. If you do the quest, you can access to some locked skills.
All and all, everything is correct, though I forgot to add a section for the number of Skill Tomes read... tomorrow's job.
I was reading in the save file structure thread and the thread seems to focus on the item stream. I would prefer to go after the wp stream or quest stream next. Do you know where any information is on the WP stream and how it's organized? That particular thread doesnt really offer much other than where the stream starts and finishes. I found something awhile ago posted by Paul but I forgot to save his page. His page was not hosted on this site but on his own private one with a link to it somewhere around here.
Any help/suggestions/guidance is appreciated.
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
only items and stats are steams, the rest are just structured chunks:
viewtopic.php?p=433280#p433280
viewtopic.php?p=433280#p433280
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
Ok, I've made some progress; however, I need some help with the Quest stuff. I'm trying to decipher the bits in the quest section of the save file but I'm lost. I've read Nec's thread (it looks like a 2d array) and found this thread:
viewtopic.php?f=8&t=22194
I'm not sure how to piece it all together. I appreciate any assistance on deciphering this string of bits.
This is what I've accomplished so far. Quests are the last thing I want to code.
http://www3.telus.net/public/TMNICKLE/C ... or%205.jpg
viewtopic.php?f=8&t=22194
I'm not sure how to piece it all together. I appreciate any assistance on deciphering this string of bits.
This is what I've accomplished so far. Quests are the last thing I want to code.
http://www3.telus.net/public/TMNICKLE/C ... or%205.jpg
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
the quest data is a set of bitflags for each quest:
the custom flags depends on the quest
Code: Select all
enum eD2VanilliaQuestFlags
{
QFLAG_REWARD_GRANTED = 0,
QFLAG_REWARD_PENDING = 1,
QFLAG_QUEST_STARTED = 2,
QFLAG_QUEST_LEAVE_TOWN = 3,
QFLAG_QUEST_ENTER_AREA = 4,
QFLAG_CUSTOM_1 = 5,
QFLAG_CUSTOM_2 = 6,
QFLAG_CUSTOM_3 = 7,
QFLAG_CUSTOM_4 = 8,
QFLAG_CUSTOM_5 = 9,
QFLAG_CUSTOM_6 = 10, //0xA
QFLAG_CUSTOM_7 = 11, //0xB
QFLAG_UPDATE_QUEST_LOG = 12, //0xC
QFLAG_PRIMARY_GOAL_ACHIEVED = 13, //0xD
QFLAG_QUEST_COMPLETED_NOW = 14, //0xE
QFLAG_QUEST_COMPLETED_BEFORE = 15, //0xF
};
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
This helps. However, it appears that I have more bits than I need. Here's a picture to explain where I'm stuck - basically where does the Act 1 section start? (I hope you're not color blind)
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
that are way more that just 6 quests per act to be exact, there are 41 sets of flags per difficulty, to check a quest flag you do:
or more simply:
Code: Select all
/*
Date: Wed Aug 05 17:58:33 2009
Author: Necrolis
Function: QUESTS_CheckFlag
Address: D2Common.#11107
Comments:
*/
BOOL __fastcall QUESTS_CheckFlag(D2QuestFlagStrc* pQuestData, DWORD nQuest, DWORD nFlag)
{
if(pQuestData == NULL)
return FALSE;
BYTE* pQuestFlags = pQuestData->pBuffer;
DWORD i = (nQuest << 4) | nFlag;
DWORD fFlags = pQuestFlags[i >> 3];
return ((fFlags & gdwBitMask[i & 7]) ? TRUE : FALSE);
}
Code: Select all
DWORD i = (nQuest << 4) | nFlag;
BYTE Flags = pArray[i >> 3];
return fFlags & (1 << (i & 7));
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
OK - I have some things working and somethings failing. This is what I have so far. I can read and edit all WP information, skill level information, and quest information. Currently, I have not enabled the ability to edit stats though I can correctly read them. (but the edit ability is coming). I wanted to test out my changes and I'm happy with the results. Everything I can edit can be exported and re-imported matching exactly what I changed. Because I have a dozen or so test files at various stages in the game and my program reads those values, quests, wp, skills, etc correctly, I'm confident I got it right. TY Necrolis.
What is failing is my understanding of C++ and the code I linked to in the first post of this thread. The code calculates the checksum. This is what I have in C#, and is to the best of my ability what I think that C++ code is doing. (For all you guru's - don't laugh too hard, I'm a rookie coder but having fun nonetheless.) When looking at the C++ code and my code below, what am I doing wrong? The checksum is close but not the same.
What is failing is my understanding of C++ and the code I linked to in the first post of this thread. The code calculates the checksum. This is what I have in C#, and is to the best of my ability what I think that C++ code is doing. (For all you guru's - don't laugh too hard, I'm a rookie coder but having fun nonetheless.) When looking at the C++ code and my code below, what am I doing wrong? The checksum is close but not the same.
Code: Select all
private void CalculateCheckSum()
{
// Convert the checksum code found at https://d2mods.info/forum/viewtopic.php?f=8&t=7102&hilit=checksum
// posted by Krabat into C# with an intermediate level of knowledge at best.
uint uiTempSum = 0; // Initialize the sum to zero.
uint uiStrangeBoolFromC = 0; // C++ boolean ?? that C# doesnt seem to like very much
// Reinitialize Checksum to 0
// FYI
// iCheckSumLocation is correctly found at +0x0C :)
// Test Save File = 3D 32 61 C0 according to XVI32. Because everything seems to be backwards, I display
// the check sum as C0 61 32 3D in my program. This is the value I am trying to reproduce in this method.
// byD2SFile is a byte array that contains all the bytes in the test d2s file.
// The bytes are read into the array from the d2s file one byte at a time and a counter is increased by 1
// to keep track of the number of bytes read in. This counter is called iNumBytes.
// The bytes match the save file when opened up with XVI32 both in number and in value. :)
byD2SFile[iCheckSumLocation] = 0;
byD2SFile[iCheckSumLocation + 1] = 0;
byD2SFile[iCheckSumLocation + 2] = 0;
byD2SFile[iCheckSumLocation + 3] = 0;
for (int i = 0; i < iNumBytes; i++) // Sum over all the bytes in the save file
{
uiTempSum = (uiTempSum << 1) + byD2SFile[i];
uiStrangeBoolFromC = (uiTempSum & 0x80000000); // This is the weird stuff in the C++ code I'm not sure about.
if (uiStrangeBoolFromC > 0) uiTempSum = uiTempSum + 1;
}
listBox1.Items.Add(string.Format("Checksum = {0}", uiTempSum)); // Display the integer value of the checksum
}
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
the C++ hashing algo used is a little miss-leading, its actually bit rotation that is done. your thing fails because you add before the rotation is complete (so if the addition of the next byte rolls the sign bit, the rotation is incorrect), in C# it should look like:
(you should really use marshaled structs for the header )
Code: Select all
private uint32 HashFile()
{
uint32 Hash = 0;
File[12] = 0;
File[13] = 0;
File[14] = 0;
File[15] = 0;
for(uint i = 0; i < FileLength; i++)
{
Hash = (Hash << 1) | (Hash >> 31); //this is bit rotation, aka _rotl in C
Hash += File[i];
}
File[12] = (Hash >> 24) & 0xFF;
File[13] = (Hash >> 16) & 0xFF;
File[14] = (Hash >> 8) & 0xFF;
File[15] = (Hash) & 0xFF;
return Hash;
}
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
Re: Char Editor
TY Necrolis! It works perfect. I'd be happy to send you a case of beer for your time.
However I do have 3 noob questions.
Question 1
This is how I understand the line of code you gave me. Whatever my sum is, left shift it 1 bit OR right shift it 31 bits. Let this new result be equal to my sum. How does the program know what branch of the OR to do?
Question 2
This is a portion of the code in C++ that I followed. I want to know if this is correct. I've stared at it for awhile now. It's not clear to me how this is a rotation.
uiCS & 0x80000000 must produce either 0x00000000 or 0x80000000 depending on whether or not the leading bit in uiCS is a 0 or 1 respectively. This is where the confusion starts. If the result was 0x00000000, I thought it was adding nothing to the entire checksum and if the the result was 0x80000000, I thought the checksum was being increased by 1 because of the '+' infront of (uiCS & 0x80.....) If it's not doing that, what is it doing?
The other train of thought I had was its not adding one or zero, but rather setting the lead bit to 0 or 1. The reason why I rejected this idea was - how does it help? If the leading bit is already a 1, ANDing it with 0x80000000 is not going to change anything and if the lead bit is 0, ANDing it with 0x80000000 is not going to do anything either.
Needless to say, I'm still totally confused.
Question 3
I've used a number of structures and lists to make this program work. There are so many bits and bytes to keep track of, I dont know any other way. Maybe when I take the next level of C#, I will learn a more efficient way to do this but for now, here's my growing list of structures and lists. (I have as many of them as I do so I know exactly what I'm editing and where I'm editing it. Easy debugging ftw. Efficiency ftl )
However I do have 3 noob questions.
Question 1
Code: Select all
uiTempSum = ((uiTempSum << 1) | (uiTempSum >> 31));
Question 2
Code: Select all
uiCS = (uiCS<<1) + ( uiCS & 0x80000000 ? 1 : 0 );
uiCS & 0x80000000 must produce either 0x00000000 or 0x80000000 depending on whether or not the leading bit in uiCS is a 0 or 1 respectively. This is where the confusion starts. If the result was 0x00000000, I thought it was adding nothing to the entire checksum and if the the result was 0x80000000, I thought the checksum was being increased by 1 because of the '+' infront of (uiCS & 0x80.....) If it's not doing that, what is it doing?
The other train of thought I had was its not adding one or zero, but rather setting the lead bit to 0 or 1. The reason why I rejected this idea was - how does it help? If the leading bit is already a 1, ANDing it with 0x80000000 is not going to change anything and if the lead bit is 0, ANDing it with 0x80000000 is not going to do anything either.
Needless to say, I'm still totally confused.
Question 3
What is a marshaled structure?Necrolis" wrote:(you should really use marshaled structs for the header )
I've used a number of structures and lists to make this program work. There are so many bits and bytes to keep track of, I dont know any other way. Maybe when I take the next level of C#, I will learn a more efficient way to do this but for now, here's my growing list of structures and lists. (I have as many of them as I do so I know exactly what I'm editing and where I'm editing it. Easy debugging ftw. Efficiency ftl )
Code: Select all
public List<strctCharData> LstCharData = new List<strctCharData>();
public List<strctWPData> LstNORMWPData = new List<strctWPData>();
public List<strctWPData> LstNMWPData = new List<strctWPData>();
public List<strctWPData> LstHELLWPData = new List<strctWPData>();
public List<strctPlayerSkills> LstAmazonData = new List<strctPlayerSkills>();
public List<strctPlayerSkills> LstAssassinData = new List<strctPlayerSkills>();
public List<strctPlayerSkills> LstBarbarianData = new List<strctPlayerSkills>();
public List<strctPlayerSkills> LstDruidData = new List<strctPlayerSkills>();
public List<strctPlayerSkills> LstNecromancerData = new List<strctPlayerSkills>();
public List<strctPlayerSkills> LstPaladinData = new List<strctPlayerSkills>();
public List<strctPlayerSkills> LstSorceressData = new List<strctPlayerSkills>();
public List<strctQuest> LstPlayerQuestData = new List<strctQuest>();
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
I want to add more functionality to my editor. When a HC char dies, what do I need to edit so I can "revive" him?
AfterMath Overview: http://www.aftermathcentral.com
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Following the path of least resistance is what makes rivers and men crooked.
- Author Unknown
Mod Completion: Always under Construction
D2SE Compatible Only
Playing AfterMath v3.0.1 ~ 1020 MB
Released March 31, 2017
Re: Char Editor
Hmmm, seems I never noticed your older reply... anyways, newest question first
so basically, just do:
2. the `uiCS & 0x80000000 ? 1 : 0` part extracts the most significant bit then turns it into an LSB via the ternary operator, this is the same as a right shift by 31, adding the result to the left shift of 1 yields the rotation.
3. marshaled structs allow direct and easy access to the structed parts of the save file, see this or this.
You need to unset the has died flag, at +0x24 from the start of the file, the flags are:Trevor" wrote:I want to add more functionality to my editor. When a HC char dies, what do I need to edit so I can "revive" him?
Code: Select all
enum eD2GameFlags
{
GFLAG_NEWBIE = 0x001, //first time entering the game
GFLAG_HARDCORE = 0x004,
GFLAG_HASDIED = 0x008,
GFLAG_EXPANSION = 0x020,
GFLAG_NOTLADDER = 0x040
};
Code: Select all
pHeader->fFlags &= ~GFLAG_HASDIED;
1. a bitwise OR is always executed, the code says, combine the bits resulting from a right shift by 31 and a left shift by 1 (this is bit rotation, aka a bit shift the does wrapping).Trevor" wrote: However I do have 3 noob questions.
Question 1This is how I understand the line of code you gave me. Whatever my sum is, left shift it 1 bit OR right shift it 31 bits. Let this new result be equal to my sum. How does the program know what branch of the OR to do?Code: Select all
uiTempSum = ((uiTempSum << 1) | (uiTempSum >> 31));
Question 2This is a portion of the code in C++ that I followed. I want to know if this is correct. I've stared at it for awhile now. It's not clear to me how this is a rotation.Code: Select all
uiCS = (uiCS<<1) + ( uiCS & 0x80000000 ? 1 : 0 );
uiCS & 0x80000000 must produce either 0x00000000 or 0x80000000 depending on whether or not the leading bit in uiCS is a 0 or 1 respectively. This is where the confusion starts. If the result was 0x00000000, I thought it was adding nothing to the entire checksum and if the the result was 0x80000000, I thought the checksum was being increased by 1 because of the '+' infront of (uiCS & 0x80.....) If it's not doing that, what is it doing?
The other train of thought I had was its not adding one or zero, but rather setting the lead bit to 0 or 1. The reason why I rejected this idea was - how does it help? If the leading bit is already a 1, ANDing it with 0x80000000 is not going to change anything and if the lead bit is 0, ANDing it with 0x80000000 is not going to do anything either.
Needless to say, I'm still totally confused.
Question 3What is a marshaled structure?Necrolis" wrote:(you should really use marshaled structs for the header )
I've used a number of structures and lists to make this program work. There are so many bits and bytes to keep track of, I dont know any other way. Maybe when I take the next level of C#, I will learn a more efficient way to do this but for now, here's my growing list of structures and lists. (I have as many of them as I do so I know exactly what I'm editing and where I'm editing it. Easy debugging ftw. Efficiency ftl )Code: Select all
public List<strctCharData> LstCharData = new List<strctCharData>(); public List<strctWPData> LstNORMWPData = new List<strctWPData>(); public List<strctWPData> LstNMWPData = new List<strctWPData>(); public List<strctWPData> LstHELLWPData = new List<strctWPData>(); public List<strctPlayerSkills> LstAmazonData = new List<strctPlayerSkills>(); public List<strctPlayerSkills> LstAssassinData = new List<strctPlayerSkills>(); public List<strctPlayerSkills> LstBarbarianData = new List<strctPlayerSkills>(); public List<strctPlayerSkills> LstDruidData = new List<strctPlayerSkills>(); public List<strctPlayerSkills> LstNecromancerData = new List<strctPlayerSkills>(); public List<strctPlayerSkills> LstPaladinData = new List<strctPlayerSkills>(); public List<strctPlayerSkills> LstSorceressData = new List<strctPlayerSkills>(); public List<strctQuest> LstPlayerQuestData = new List<strctQuest>();
2. the `uiCS & 0x80000000 ? 1 : 0` part extracts the most significant bit then turns it into an LSB via the ternary operator, this is the same as a right shift by 31, adding the result to the left shift of 1 yields the rotation.
3. marshaled structs allow direct and easy access to the structed parts of the save file, see this or this.
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal
-
- Posts: 3
- Joined: Fri Jul 10, 2020 4:08 pm
Re: Char Editor
fixed my corrupted d2s with That is ALL needed,
be aware that next line just brings in ERROR.
ps. before fixing the checksum, be sure to set its 4 bytes to 00 00 00 00 by hex editor, as itself is right included in the sumcheck, tricky~
Code: Select all
uiCS = ((uiCS<<1) |( uiCS >> 31))+ (unsigned)buf[i];
be aware that next line just brings in ERROR.
Code: Select all
uiCS = (uiCS<<1) + ( uiCS & 0x80000000 ? 1 : 0 ); //tested to be WRONG
Re: Char Editor
This exactly what the code I posted does...D2Joy wrote: ↑Tue Jul 14, 2020 11:49 pmfixed my corrupted d2s withThat is ALL needed,Code: Select all
uiCS = ((uiCS<<1) |( uiCS >> 31))+ (unsigned)buf[i];
be aware that next line just brings in ERROR.ps. before fixing the checksum, be sure to set its 4 bytes to 00 00 00 00 by hex editor, as itself is right included in the sumcheck, tricky~Code: Select all
uiCS = (uiCS<<1) + ( uiCS & 0x80000000 ? 1 : 0 ); //tested to be WRONG
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal