|
1
2
3
4
|
#ifndef D2CHAR_H
#define D2CHAR_H
#include <stdint.h>
|
|
5
|
#include <stdlib.h>
|
|
6
7
8
9
|
#include <string.h>
#include <time.h>
#include "d2quest.h"
|
|
10
|
#include "d2strings.h"
|
|
11
|
#include "d2waypoints.h"
|
|
12
13
14
15
16
17
18
19
20
|
#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
|
|
21
|
#define D2S_WAYPOINTS_LENGTH 80
|
|
22
23
24
25
26
27
28
|
#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
|
|
29
30
|
#define D2S_DIFFICULTY_ACTIVE 0x80
|
|
31
32
33
34
35
36
37
38
|
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 {
|
|
39
40
41
42
43
44
|
VER_106 = 71,
VER_107 = 87,
VER_108XP = 87,
VER_108 = 89,
VER_109 = 92,
VER_110 = 96
|
|
45
|
} D2S_VERSION;
|
|
46
|
|
|
47
|
typedef enum D2S_CHARCLASS {
|
|
48
|
D2S_CHARCLASS_UNKNOWN = -1,
|
|
49
50
51
52
53
54
55
|
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
|
|
56
57
58
|
} D2S_CHARCLASS;
typedef enum D2S_ACT {
|
|
59
|
D2S_ACT_UNKNOWN = -1,
|
|
60
|
D2S_ACT1 = 0,
|
|
61
62
63
64
|
D2S_ACT2,
D2S_ACT3,
D2S_ACT4,
D2S_ACT5
|
|
65
|
} D2S_ACT;
|
|
66
|
|
|
67
|
// TODO: Add file hex offsets for each field
|
|
68
69
70
71
72
|
typedef struct __attribute__((packed)){
uint32_t signature;
uint32_t versionID;
uint32_t fileSize;
uint32_t checksum;
|
|
73
|
uint32_t activeWeapon; // Determines which weapon set (I or II in inventory) is currently in use
|
|
74
75
76
77
78
79
80
81
82
83
|
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
|
|
84
|
uint8_t hotkeys[D2S_HOTKEYS_LENGTH]; // TODO: Not implemented
|
|
85
86
|
uint32_t leftAbility;
uint32_t rightAbility;
|
|
87
88
89
|
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!
|
|
90
|
uint8_t difficulty[D2S_DIFFICULTY_LENGTH];
|
|
91
92
93
|
uint32_t mapID; // Not implemented. Too bad!
uint16_t unknown5; // TODO
uint16_t mercenaryDead;
|
|
94
95
96
97
|
uint32_t mercenarySeed;
uint16_t mercenaryNameID;
uint16_t mercenaryType;
uint32_t mercenaryExp;
|
|
98
|
uint8_t unknown6[144]; // TODO
|
|
99
|
D2QuestData questData;
|
|
100
|
D2WaypointsData waypointsData;
|
|
101
|
uint8_t unknown7; // TODO. Apparently this is always 0x01
|
|
102
|
uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented
|
|
103
104
|
} D2CharHeader;
|
|
105
|
|
|
106
|
|
|
107
108
109
110
111
112
|
// 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,)
|
|
113
114
115
|
uint32_t calcChecksum(D2CharHeader* c, void* charData);
int checkChecksum(D2CharHeader* c, void* charData);
int isHardcore(D2CharHeader* c);
|
|
116
|
void setHardcore(D2CharHeader* c, int bool);
|
|
117
|
int hasDied(D2CharHeader* c);
|
|
118
|
void setDied(D2CharHeader* c, int bool);
|
|
119
|
int isExpansion(D2CharHeader* c);
|
|
120
|
void setExpansion(D2CharHeader* c, int bool);
|
|
121
|
int isLadder(D2CharHeader* c);
|
|
122
|
void setLadder(D2CharHeader* c, int bool);
|
|
123
124
125
126
127
128
129
130
131
|
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);
|
|
132
|
// This is the last difficulty played, not the highest available. For that, use getProgress()
|
|
133
|
// 0 = Normal, 2 = Hell
|
|
134
|
D2S_DIFFICULTY getCurrentDifficulty(D2CharHeader* c);
|
|
135
|
|
|
136
137
138
139
140
141
|
// 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);
|
|
142
|
|
|
143
|
#endif
|