Commit f8fab420039a619e9f25498ca55cb995630dd759
1 parent
00938948
Added stat code
Showing
4 changed files
with
129 additions
and
34 deletions
d2char.c
... | ... | @@ -227,14 +227,4 @@ int setProgress(D2CharHeader* c, D2S_ACT act, D2S_DIFFICULTY difficulty) { |
227 | 227 | } |
228 | 228 | c->charProgress = progress; |
229 | 229 | return 0; |
230 | -} | |
231 | - | |
232 | -int getAttribute(D2S_STAT attr) { | |
233 | - // TODO implement | |
234 | - return 0; | |
235 | -} | |
236 | - | |
237 | -int setAttribute(D2S_STAT attr, unsigned int value) { | |
238 | - // TODO implement | |
239 | - return 0; | |
240 | 230 | } |
241 | 231 | \ No newline at end of file | ... | ... |
d2char.h
... | ... | @@ -55,25 +55,6 @@ typedef enum D2S_CHARCLASS { |
55 | 55 | D2S_CHARCLASS_ASSASSIN = 6 |
56 | 56 | } D2S_CHARCLASS; |
57 | 57 | |
58 | -typedef enum D2S_STAT { | |
59 | - D2S_STAT_STRENGTH = 0x00, | |
60 | - D2S_STAT_ENERGY = 0x01, | |
61 | - D2S_STAT_DEXTERITY = 0x02, | |
62 | - D2S_STAT_VITALITY = 0x03, | |
63 | - D2S_STAT_STATPTS = 0x04, | |
64 | - D2S_STAT_SKILLPTS = 0x05, | |
65 | - D2S_STAT_LIFE = 0x06, | |
66 | - D2S_STAT_MAXLIFE = 0x07, | |
67 | - D2S_STAT_MANA = 0x08, | |
68 | - D2S_STAT_MAXMANA = 0x09, | |
69 | - D2S_STAT_STAMINA = 0x0a, | |
70 | - D2S_STAT_MAXSTAMINA = 0x0b, | |
71 | - D2S_STAT_LEVEL = 0x0c, | |
72 | - D2S_STAT_EXPERIENCE = 0x0d, | |
73 | - D2S_STAT_GOLD = 0x0e, | |
74 | - D2S_STAT_GOLDSTASH = 0x0f, | |
75 | -} D2S_STAT; | |
76 | - | |
77 | 58 | typedef enum D2S_ACT { |
78 | 59 | D2S_ACT_UNKNOWN = -1, |
79 | 60 | D2S_ACT1 = 0, |
... | ... | @@ -119,8 +100,6 @@ typedef struct __attribute__((packed)){ |
119 | 100 | D2WaypointsData waypointsData; |
120 | 101 | uint8_t unknown7; // TODO. Apparently this is always 0x01 |
121 | 102 | uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented |
122 | - // TODO Add stats | |
123 | - // TODO Add skills | |
124 | 103 | } D2CharHeader; |
125 | 104 | |
126 | 105 | |
... | ... | @@ -161,7 +140,4 @@ D2S_ACT getCurrentAct(D2CharHeader* c); |
161 | 140 | void getProgress(D2CharHeader* c, D2S_ACT* act, D2S_DIFFICULTY* difficulty); |
162 | 141 | int setProgress(D2CharHeader* c, D2S_ACT act, D2S_DIFFICULTY difficulty); |
163 | 142 | |
164 | -int getAttribute(D2S_STAT attr); | |
165 | -int setAttribute(D2S_STAT attr, unsigned int value); | |
166 | - | |
167 | 143 | #endif |
168 | 144 | \ No newline at end of file | ... | ... |
d2stat.c
0 → 100644
1 | +#include "d2stat.h" | |
2 | + | |
3 | +#include <stdio.h> | |
4 | +#include <string.h> | |
5 | + | |
6 | +// Internal function, gives the offset ***IN BITS, NOT BYTES*** of the specified stat | |
7 | +unsigned long long int _searchStat(D2S_STAT stat, void* charData, size_t dataLen) { | |
8 | + if(!strncmp(charData, D2S_STAT_HEADER, D2S_STAT_HEADER_LENGTH)) { | |
9 | + fprintf(stderr,"libd2char error: Stat header not present in charData\n"); | |
10 | + return 0; | |
11 | + } | |
12 | + unsigned long long int byteOffset = D2S_STAT_HEADER_LENGTH; | |
13 | + unsigned long long int bitOffset = 0; | |
14 | + while(byteOffset < dataLen) { | |
15 | + uint16_t statID = 0; | |
16 | + memcpy(&statID, charData + byteOffset, sizeof(statID)); | |
17 | + statID >>= bitOffset; | |
18 | + statID &= 0x1FF; | |
19 | + if(statID == D2S_STAT_FOOTER) { | |
20 | + break; | |
21 | + } else if(statID == stat) { | |
22 | + return (byteOffset * 8) + bitOffset; | |
23 | + } | |
24 | + byteOffset += statCost[statID] / 8; | |
25 | + bitOffset += statCost[statID] % 8; | |
26 | + } | |
27 | + return 0; | |
28 | +} | |
29 | + | |
30 | +int getStat(D2S_STAT stat, unsigned int* value, void* charData, size_t dataLen) { | |
31 | + unsigned long long int statOffset = _searchStat(stat,charData,dataLen); | |
32 | + if(!statOffset) { | |
33 | + fprintf(stderr,"libd2char error: Unable to find attribute: %d\n", stat); | |
34 | + return -1; | |
35 | + } | |
36 | + uint64_t statValue = 0; | |
37 | + memcpy(&statValue, charData + (statOffset / 8), sizeof(statValue)); | |
38 | + statValue >>= (statOffset % 8); | |
39 | + statValue &= statCostMask[stat]; | |
40 | + *value = (unsigned int)statValue; | |
41 | + return 0; | |
42 | +} | |
43 | + | |
44 | +int setStat(D2S_STAT stat, unsigned int value, void* charData, size_t dataLen) { | |
45 | + unsigned long long int statOffset = _searchStat(stat,charData,dataLen); | |
46 | + if(!statOffset) { | |
47 | + fprintf(stderr,"libd2char error: Unable to find attribute: %d\n", stat); | |
48 | + return -1; | |
49 | + } | |
50 | + uint64_t statValue = 0; | |
51 | + memcpy(&statValue, charData + (statOffset / 8), sizeof(statValue)); | |
52 | + statValue &= (~statCostMask[stat] << (statOffset % 8)); | |
53 | + statValue |= (value << (statOffset % 8)); | |
54 | + memcpy(charData + (statOffset / 8), &statValue, sizeof(statValue)); | |
55 | + return 0; | |
56 | +} | |
0 | 57 | \ No newline at end of file | ... | ... |
d2stat.h
0 → 100644
1 | +#ifndef D2STAT_H | |
2 | +#define D2STAT_H | |
3 | + | |
4 | +#include <stdint.h> | |
5 | +#include <stdlib.h> | |
6 | + | |
7 | +#define D2S_STAT_HEADER "gf" | |
8 | +#define D2S_STAT_HEADER_LENGTH 2 | |
9 | +#define D2S_STAT_FOOTER 0x1FF | |
10 | + | |
11 | +typedef enum D2S_STAT { | |
12 | + D2S_STAT_STRENGTH = 0x00, | |
13 | + D2S_STAT_ENERGY = 0x01, | |
14 | + D2S_STAT_DEXTERITY = 0x02, | |
15 | + D2S_STAT_VITALITY = 0x03, | |
16 | + D2S_STAT_STATPTS = 0x04, | |
17 | + D2S_STAT_SKILLPTS = 0x05, | |
18 | + D2S_STAT_LIFE = 0x06, | |
19 | + D2S_STAT_MAXLIFE = 0x07, | |
20 | + D2S_STAT_MANA = 0x08, | |
21 | + D2S_STAT_MAXMANA = 0x09, | |
22 | + D2S_STAT_STAMINA = 0x0a, | |
23 | + D2S_STAT_MAXSTAMINA = 0x0b, | |
24 | + D2S_STAT_LEVEL = 0x0c, | |
25 | + D2S_STAT_EXPERIENCE = 0x0d, | |
26 | + D2S_STAT_GOLD = 0x0e, | |
27 | + D2S_STAT_GOLDSTASH = 0x0f, | |
28 | +} D2S_STAT; | |
29 | + | |
30 | +// Internal use. Length of each stat in bits | |
31 | +const int statCost[] = { | |
32 | + 10, //D2S_STAT_STRENGTH | |
33 | + 10, //D2S_STAT_ENERGY | |
34 | + 10, //D2S_STAT_DEXTERITY | |
35 | + 10, //D2S_STAT_VITALITY | |
36 | + 10, //D2S_STAT_STATPTS | |
37 | + 8, //D2S_STAT_SKILLPTS | |
38 | + 21, //D2S_STAT_LIFE | |
39 | + 21, //D2S_STAT_MAXLIFE | |
40 | + 21, //D2S_STAT_MANA | |
41 | + 21, //D2S_STAT_MAXMANA | |
42 | + 21, //D2S_STAT_STAMINA | |
43 | + 21, //D2S_STAT_MAXSTAMINA | |
44 | + 7, //D2S_STAT_LEVEL | |
45 | + 32, //D2S_STAT_EXPERIENCE | |
46 | + 25, //D2S_STAT_GOLD | |
47 | + 25 //D2S_STAT_GOLDSTASH | |
48 | +}; | |
49 | + | |
50 | +// Internal use. Mask to apply to the bit offset (when properly shifted) to get the stat value | |
51 | +const uint64_t statCostMask[] = { | |
52 | + 0x00000000000003FF, //D2S_STAT_STRENGTH (10 bits) | |
53 | + 0x00000000000003FF, //D2S_STAT_ENERGY (10 bits) | |
54 | + 0x00000000000003FF, //D2S_STAT_DEXTERITY (10 bits) | |
55 | + 0x00000000000003FF, //D2S_STAT_VITALITY (10 bits) | |
56 | + 0x00000000000003FF, //D2S_STAT_STATPTS (10 bits) | |
57 | + 0x00000000000000FF, //D2S_STAT_SKILLPTS (8 bits) | |
58 | + 0x00000000001FFFFF, //D2S_STAT_LIFE (21 bits) | |
59 | + 0x00000000001FFFFF, //D2S_STAT_MAXLIFE (21 bits) | |
60 | + 0x00000000001FFFFF, //D2S_STAT_MANA (21 bits) | |
61 | + 0x00000000001FFFFF, //D2S_STAT_MAXMANA (21 bits) | |
62 | + 0x00000000001FFFFF, //D2S_STAT_STAMINA (21 bits) | |
63 | + 0x00000000001FFFFF, //D2S_STAT_MAXSTAMINA (21 bits) | |
64 | + 0x000000000000007F, //D2S_STAT_LEVEL (7 bits) | |
65 | + 0x00000000FFFFFFFF, //D2S_STAT_EXPERIENCE (32 bits) | |
66 | + 0x0000000001FFFFFF, //D2S_STAT_GOLD (25 bits) | |
67 | + 0x0000000001FFFFFF //D2S_STAT_GOLDSTASH (25 bits) | |
68 | +}; | |
69 | + | |
70 | +int getStat(D2S_STAT stat, unsigned int* value, void* charData, size_t dataLen); | |
71 | +int setStat(D2S_STAT stat, unsigned int value, void* charData, size_t dataLen); | |
72 | + | |
73 | +#endif | |
0 | 74 | \ No newline at end of file | ... | ... |