d2char.h
4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef D2CHAR_H
#define D2CHAR_H
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "d2quest.h"
#include "d2strings.h"
#include "d2waypoints.h"
#define D2S_HEADER_LENGTH 765
#define D2S_SIGNATURE 0xAA55AA55
#define D2S_CHECKSUM_OFFSET 12
#define D2S_CHECKSUM_LENGTH 4
#define D2S_CHARNAME_LENGTH 16
#define D2S_HOTKEYS_LENGTH 64
#define D2S_CHAR_APPEARANCE_LENGTH 32
#define D2S_DIFFICULTY_LENGTH 3
#define D2S_WAYPOINTS_LENGTH 80
#define D2S_NPCDATA_LENGTH 51
#define D2S_CHARSTATUS_HARDCORE 0x04
#define D2S_CHARSTATUS_DIED 0x08
#define D2S_CHARSTATUS_EXPANSION 0x20
#define D2S_CHARSTATUS_LADDER 0x40
#define D2S_DIFFICULTY_ACTIVE 0x80
typedef enum D2S_DIFFICULTY {
D2S_DIFFICULTY_UNKNOWN = -1,
D2S_DIFFICULTY_NORMAL = 0,
D2S_DIFFICULTY_NIGHTMARE = 1,
D2S_DIFFICULTY_HELL = 2
} D2S_DIFFICULTY;
typedef enum D2S_VERSION {
VER_106 = 71,
VER_107 = 87,
VER_108XP = 87,
VER_108 = 89,
VER_109 = 92,
VER_110 = 96
} D2S_VERSION;
typedef enum D2S_CHARCLASS {
D2S_CHARCLASS_UNKNOWN = -1,
D2S_CHARCLASS_AMAZON = 0,
D2S_CHARCLASS_SORCERESS = 1,
D2S_CHARCLASS_NECROMANCER = 2,
D2S_CHARCLASS_PALADIN = 3,
D2S_CHARCLASS_BARBARIAN = 4,
D2S_CHARCLASS_DRUID = 5,
D2S_CHARCLASS_ASSASSIN = 6
} D2S_CHARCLASS;
typedef enum D2S_ACT {
D2S_ACT_UNKNOWN = -1,
D2S_ACT1 = 0,
D2S_ACT2,
D2S_ACT3,
D2S_ACT4,
D2S_ACT5
} D2S_ACT;
// TODO: Add file hex offsets for each field
typedef struct __attribute__((packed)){
uint32_t signature;
uint32_t versionID;
uint32_t fileSize;
uint32_t checksum;
uint32_t activeWeapon; // Determines which weapon set (I or II in inventory) is currently in use
char name[D2S_CHARNAME_LENGTH];
uint8_t charStatus;
uint8_t charProgress;
uint16_t unknown1; // TODO
uint8_t charClass;
uint16_t unknown2; // TODO
uint8_t charLevel;
uint32_t unknown3; // TODO
uint32_t lastPlayed;
uint32_t unknown4; // TODO
uint8_t hotkeys[D2S_HOTKEYS_LENGTH]; // TODO: Not implemented
uint32_t leftAbility;
uint32_t rightAbility;
uint32_t leftAbilityAlt; // Left ability when alternative weapon set (II) is selected
uint32_t rightAbilityAlt; // Right ability when alternative weapon set (II) is selected
uint8_t charAppearance[D2S_CHAR_APPEARANCE_LENGTH]; // Not implemented. Too bad!
uint8_t difficulty[D2S_DIFFICULTY_LENGTH];
uint32_t mapID; // Not implemented. Too bad!
uint16_t unknown5; // TODO
uint16_t mercenaryDead;
uint32_t mercenarySeed;
uint16_t mercenaryNameID;
uint16_t mercenaryType;
uint32_t mercenaryExp;
uint8_t unknown6[144]; // TODO
D2QuestData questData;
D2WaypointsData waypointsData;
uint8_t unknown7; // TODO. Apparently this is always 0x01
uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented
} D2CharHeader;
// TODO: Load from file.
// int loadD2CharFromFile(const char* file, D2CharHeader** header, void** data);
// TODO: Write to file.
// int writeD2CharToFile(const char* file, D2CharHeader* header, void* charData,)
uint32_t calcChecksum(D2CharHeader* c, void* charData);
int checkChecksum(D2CharHeader* c, void* charData);
int isHardcore(D2CharHeader* c);
void setHardcore(D2CharHeader* c, int bool);
int hasDied(D2CharHeader* c);
void setDied(D2CharHeader* c, int bool);
int isExpansion(D2CharHeader* c);
void setExpansion(D2CharHeader* c, int bool);
int isLadder(D2CharHeader* c);
void setLadder(D2CharHeader* c, int bool);
int isFemale(D2CharHeader* c);
// Returns static string from library memory, no need to free
const char* getCharacterTitle(D2CharHeader* c);
// Writes to user-allocated string. Format is default locale's time representation
size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen);
// This is the last difficulty played, not the highest available. For that, use getProgress()
// 0 = Normal, 2 = Hell
D2S_DIFFICULTY getCurrentDifficulty(D2CharHeader* c);
// This is the last act played, not the highest available. For that, use getProgress()
// 0 = Act I, 4 = Act V (Expansion)
D2S_ACT getCurrentAct(D2CharHeader* c);
void getProgress(D2CharHeader* c, D2S_ACT* act, D2S_DIFFICULTY* difficulty);
int setProgress(D2CharHeader* c, D2S_ACT act, D2S_DIFFICULTY difficulty);
#endif