Commit 00938948301ef2d87243d3a3e9be6ca4d5383ddf

Authored by Imanol-Mikel Barba Sabariego
1 parent 3409b841

Implemented all TODOs up to waypoints. Made API more consistent

d2char.c
... ... @@ -28,39 +28,47 @@ int isHardcore(D2CharHeader* c) {
28 28 return c->charStatus & D2S_CHARSTATUS_HARDCORE;
29 29 }
30 30  
31   -void setHardcore(D2CharHeader* c) {
32   -
  31 +void setHardcore(D2CharHeader* c, int bool) {
  32 + if(bool) {
  33 + c->charProgress |= D2S_CHARSTATUS_HARDCORE;
  34 + } else {
  35 + c->charProgress &= ~D2S_CHARSTATUS_HARDCORE;
  36 + }
33 37 }
34 38  
35 39 int hasDied(D2CharHeader* c) {
36 40 return c->charStatus & D2S_CHARSTATUS_DIED;
37 41 }
38 42  
39   -void setDied(D2CharHeader* c) {
40   -
  43 +void setDied(D2CharHeader* c, int bool) {
  44 + if(bool) {
  45 + c->charProgress |= D2S_CHARSTATUS_DIED;
  46 + } else {
  47 + c->charProgress &= ~D2S_CHARSTATUS_DIED;
  48 + }
41 49 }
42 50  
43 51 int isExpansion(D2CharHeader* c) {
44 52 return c->charStatus & D2S_CHARSTATUS_EXPANSION;
45 53 }
46 54  
47   -void setExpansion(D2CharHeader* c) {
48   -
  55 +void setExpansion(D2CharHeader* c, int bool) {
  56 + if(bool) {
  57 + c->charProgress |= D2S_CHARSTATUS_EXPANSION;
  58 + } else {
  59 + c->charProgress &= ~D2S_CHARSTATUS_EXPANSION;
  60 + }
49 61 }
50 62  
51 63 int isLadder(D2CharHeader* c) {
52 64 return c->charStatus & D2S_CHARSTATUS_LADDER;
53 65 }
54 66  
55   -void setLadder(D2CharHeader* c) {
56   -
57   -}
58   -
59   -D2S_ACT getCurrentAct(D2CharHeader* c) {
60   - if(isExpansion(c)) {
61   - return c->charProgress % 5;
  67 +void setLadder(D2CharHeader* c, int bool) {
  68 + if(bool) {
  69 + c->charProgress |= D2S_CHARSTATUS_LADDER;
62 70 } else {
63   - return c->charProgress % 4;
  71 + c->charProgress &= ~D2S_CHARSTATUS_LADDER;
64 72 }
65 73 }
66 74  
... ... @@ -71,33 +79,34 @@ int isFemale(D2CharHeader* c) {
71 79 }
72 80  
73 81 const char* getCharacterTitle(D2CharHeader* c) {
74   - int tier;
  82 + D2S_DIFFICULTY hardestCleared;
  83 + D2S_ACT act; // We don't care, but need to provide it
  84 + getProgress(c,&act,&hardestCleared);
75 85 if(isExpansion(c)) {
76 86 // Expansion
77   - tier = c->charProgress / 5;
78 87 if(isHardcore(c)) {
79 88 // Expansion Hardcore
80   - switch(tier) {
81   - case 1:
  89 + switch(hardestCleared) {
  90 + case D2S_DIFFICULTY_NORMAL:
82 91 return D2S_CHARPROGRESS_EXPANSION_TIER1_NAME_HARDCORE;
83 92 break;
84   - case 2:
  93 + case D2S_DIFFICULTY_NIGHTMARE:
85 94 return D2S_CHARPROGRESS_EXPANSION_TIER2_NAME_HARDCORE;
86 95 break;
87   - case 3:
  96 + case D2S_DIFFICULTY_HELL:
88 97 return D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_HARDCORE;
89 98 break;
90 99 }
91 100 } else {
92 101 // Expansion Softcore
93   - switch(tier) {
94   - case 1:
  102 + switch(hardestCleared) {
  103 + case D2S_DIFFICULTY_NORMAL:
95 104 return D2S_CHARPROGRESS_EXPANSION_TIER1_NAME;
96 105 break;
97   - case 2:
  106 + case D2S_DIFFICULTY_NIGHTMARE:
98 107 return D2S_CHARPROGRESS_EXPANSION_TIER2_NAME;
99 108 break;
100   - case 3:
  109 + case D2S_DIFFICULTY_HELL:
101 110 return isFemale(c) ? D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_F : D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_M;
102 111 break;
103 112 }
... ... @@ -106,27 +115,27 @@ const char* getCharacterTitle(D2CharHeader* c) {
106 115 // Classic
107 116 if(isHardcore(c)) {
108 117 // Classic Hardcore
109   - switch(tier) {
110   - case 1:
  118 + switch(hardestCleared) {
  119 + case D2S_DIFFICULTY_NORMAL:
111 120 return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_HARDCORE_F : D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_HARDCORE_M;
112 121 break;
113   - case 2:
  122 + case D2S_DIFFICULTY_NIGHTMARE:
114 123 return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER2_NAME_HARDCORE_F : D2S_CHARPROGRESS_CLASSIC_TIER2_NAME_HARDCORE_M;
115 124 break;
116   - case 3:
  125 + case D2S_DIFFICULTY_HELL:
117 126 return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER3_NAME_HARDCORE_F : D2S_CHARPROGRESS_CLASSIC_TIER3_NAME_HARDCORE_M;
118 127 break;
119 128 }
120 129 } else {
121 130 // Classic Softcore
122   - switch(tier) {
123   - case 1:
  131 + switch(hardestCleared) {
  132 + case D2S_DIFFICULTY_NORMAL:
124 133 return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_F : D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_M;
125 134 break;
126   - case 2:
  135 + case D2S_DIFFICULTY_NIGHTMARE:
127 136 return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER2_NAME_F : D2S_CHARPROGRESS_CLASSIC_TIER2_NAME_M;
128 137 break;
129   - case 3:
  138 + case D2S_DIFFICULTY_HELL:
130 139 return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER3_NAME_F : D2S_CHARPROGRESS_CLASSIC_TIER3_NAME_M;
131 140 break;
132 141 }
... ... @@ -160,18 +169,72 @@ D2S_DIFFICULTY getCurrentDifficulty(D2CharHeader* c) {
160 169 return D2S_DIFFICULTY_UNKNOWN;
161 170 }
162 171  
163   -int setProgress(D2S_ACT act, D2S_DIFFICULTY difficulty) {
164   - // TODO
165   - // set c->difficulty and c->progress?
  172 +D2S_ACT getCurrentAct(D2CharHeader* c) {
  173 + for(int i = D2S_DIFFICULTY_NORMAL; i <= D2S_DIFFICULTY_HELL; ++i) {
  174 + if(c->difficulty[i] & D2S_DIFFICULTY_ACTIVE) {
  175 + return (D2S_ACT)(c->difficulty[i] & 0x07);
  176 + }
  177 + }
  178 + return D2S_ACT_UNKNOWN;
  179 +}
  180 +
  181 +void getProgress(D2CharHeader* c, D2S_ACT* act, D2S_DIFFICULTY* difficulty) {
  182 + if(isExpansion(c)) {
  183 + *difficulty = c->charProgress / 5;
  184 + *act = c->charProgress % 5;
  185 + // Unfortunately, this won't distinguish between act IV and act V, because
  186 + // the game does not increment the charProgress when you kill Diablo, so
  187 + // the only way to know is check whether or not you started the act on the
  188 + // quest data
  189 + // NB: This doesn't happen in Classic
  190 + if(*act == D2S_ACT4) {
  191 + if(c->questData.quests[*difficulty].expansionAct.actStarted) {
  192 + ++*act;
  193 + }
  194 + }
  195 + } else {
  196 + *difficulty = c->charProgress / 4;
  197 + *act = c->charProgress % 4;
  198 + }
  199 +}
  200 +
  201 +int setProgress(D2CharHeader* c, D2S_ACT act, D2S_DIFFICULTY difficulty) {
  202 + if(difficulty != D2S_DIFFICULTY_NORMAL ||
  203 + difficulty != D2S_DIFFICULTY_NIGHTMARE ||
  204 + difficulty != D2S_DIFFICULTY_HELL) {
  205 + fprintf(stderr,"libd2char error: Invalid difficulty specified: %d\n", difficulty);
  206 + return -1;
  207 + }
  208 + if(act != D2S_ACT1 ||
  209 + act != D2S_ACT2 ||
  210 + act != D2S_ACT3 ||
  211 + act != D2S_ACT4 ||
  212 + act != D2S_ACT5) {
  213 + fprintf(stderr,"libd2char error: Invalid act specified: %d\n", act);
  214 + return -1;
  215 + }
  216 + uint8_t progress = 0;
  217 + if(isExpansion(c)) {
  218 + progress += difficulty * 5;
  219 + progress += act;
  220 + if(act == D2S_ACT5) {
  221 + // See comment above
  222 + --progress;
  223 + c->questData.quests[difficulty].expansionAct.actStarted = 1;
  224 + }
  225 + } else {
  226 + progress = (difficulty * 4) + act;
  227 + }
  228 + c->charProgress = progress;
166 229 return 0;
167 230 }
168 231  
169 232 int getAttribute(D2S_STAT attr) {
170   - // TODO
  233 + // TODO implement
171 234 return 0;
172 235 }
173 236  
174 237 int setAttribute(D2S_STAT attr, unsigned int value) {
175   - // TODO
  238 + // TODO implement
176 239 return 0;
177 240 }
178 241 \ No newline at end of file
... ...
d2char.h
... ... @@ -45,6 +45,7 @@ typedef enum D2S_VERSION {
45 45 } D2S_VERSION;
46 46  
47 47 typedef enum D2S_CHARCLASS {
  48 + D2S_CHARCLASS_UNKNOWN = -1,
48 49 D2S_CHARCLASS_AMAZON = 0,
49 50 D2S_CHARCLASS_SORCERESS = 1,
50 51 D2S_CHARCLASS_NECROMANCER = 2,
... ... @@ -74,6 +75,7 @@ typedef enum D2S_STAT {
74 75 } D2S_STAT;
75 76  
76 77 typedef enum D2S_ACT {
  78 + D2S_ACT_UNKNOWN = -1,
77 79 D2S_ACT1 = 0,
78 80 D2S_ACT2,
79 81 D2S_ACT3,
... ... @@ -132,16 +134,13 @@ typedef struct __attribute__((packed)){
132 134 uint32_t calcChecksum(D2CharHeader* c, void* charData);
133 135 int checkChecksum(D2CharHeader* c, void* charData);
134 136 int isHardcore(D2CharHeader* c);
135   -void setHardcore(D2CharHeader* c);
  137 +void setHardcore(D2CharHeader* c, int bool);
136 138 int hasDied(D2CharHeader* c);
137   -void setDied(D2CharHeader* c);
  139 +void setDied(D2CharHeader* c, int bool);
138 140 int isExpansion(D2CharHeader* c);
139   -void setExpansion(D2CharHeader* c);
  141 +void setExpansion(D2CharHeader* c, int bool);
140 142 int isLadder(D2CharHeader* c);
141   -void setLadder(D2CharHeader* c);
142   -
143   -// 0 = Act I, 4 = Act V (Expansion)
144   -D2S_ACT getCurrentAct(D2CharHeader* c);
  143 +void setLadder(D2CharHeader* c, int bool);
145 144  
146 145 int isFemale(D2CharHeader* c);
147 146  
... ... @@ -151,10 +150,16 @@ const char* getCharacterTitle(D2CharHeader* c);
151 150 // Writes to user-allocated string. Format is default locale's time representation
152 151 size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen);
153 152  
  153 +// This is the last difficulty played, not the highest available. For that, use getProgress()
154 154 // 0 = Normal, 2 = Hell
155 155 D2S_DIFFICULTY getCurrentDifficulty(D2CharHeader* c);
156 156  
157   -int setProgress(D2S_ACT act, D2S_DIFFICULTY difficulty);
  157 +// This is the last act played, not the highest available. For that, use getProgress()
  158 +// 0 = Act I, 4 = Act V (Expansion)
  159 +D2S_ACT getCurrentAct(D2CharHeader* c);
  160 +
  161 +void getProgress(D2CharHeader* c, D2S_ACT* act, D2S_DIFFICULTY* difficulty);
  162 +int setProgress(D2CharHeader* c, D2S_ACT act, D2S_DIFFICULTY difficulty);
158 163  
159 164 int getAttribute(D2S_STAT attr);
160 165 int setAttribute(D2S_STAT attr, unsigned int value);
... ...
d2mercs.c
... ... @@ -27,13 +27,224 @@ D2S_MERCTYPE getMercType(uint16_t mercID) {
27 27 }
28 28  
29 29 D2S_MERCSUBTYPE getMercSubType(uint16_t mercID) {
30   - // TODO
  30 + D2S_MERCSUBTYPE subtype;
  31 + switch(getMercType(mercID)) {
  32 + case D2S_MERCTYPE_ROGUE:
  33 + if(mercID == 0 || mercID == 2 || mercID == 4) {
  34 + subtype = D2S_MERCSUBTYPE_FIRE_ARROW;
  35 + } else {
  36 + subtype = D2S_MERCSUBTYPE_COLD_ARROW;
  37 + }
  38 + break;
  39 + case D2S_MERCTYPE_DESERT:
  40 + if(mercID == 6 || mercID == 9 || mercID == 12) {
  41 + subtype = D2S_MERCSUBTYPE_COMBAT;
  42 + } if(mercID == 7 || mercID == 10 || mercID == 13) {
  43 + subtype = D2S_MERCSUBTYPE_DEFENSIVE;
  44 + } else {
  45 + subtype = D2S_MERCSUBTYPE_OFFENSIVE;
  46 + }
  47 + break;
  48 + case D2S_MERCTYPE_SORCEROR:
  49 + if(mercID == 15 || mercID == 18 || mercID == 21) {
  50 + subtype = D2S_MERCSUBTYPE_FIRE;
  51 + } if(mercID == 16 || mercID == 19 || mercID == 22) {
  52 + subtype = D2S_MERCSUBTYPE_COLD;
  53 + } else {
  54 + subtype = D2S_MERCSUBTYPE_LIGHTNING;
  55 + }
  56 + break;
  57 + case D2S_MERCTYPE_BARBARIAN:
  58 + case D2S_MERCTYPE_UNKNOWN:
  59 + subtype = D2S_MERCSUBTYPE_NONE;
  60 + break;
  61 + }
  62 + return subtype;
31 63 }
32 64  
33 65 D2S_DIFFICULTY getMercDifficulty(uint16_t mercID) {
34   - // TODO
  66 + if(mercID == 0 || mercID == 1 ||
  67 + mercID == 6 || mercID == 7 || mercID == 8 ||
  68 + mercID == 15 || mercID == 16 || mercID == 17 ||
  69 + mercID == 24 || mercID == 25) {
  70 + return D2S_DIFFICULTY_NORMAL;
  71 + } else if (mercID == 2 || mercID == 3 ||
  72 + mercID == 9 || mercID == 10 || mercID == 11 ||
  73 + mercID == 18 || mercID == 19 || mercID == 20 ||
  74 + mercID == 26 || mercID == 27) {
  75 + return D2S_DIFFICULTY_NIGHTMARE;
  76 + } else if (mercID == 4 || mercID == 5 ||
  77 + mercID == 12 || mercID == 13 || mercID == 14 ||
  78 + mercID == 21 || mercID == 22 || mercID == 23 ||
  79 + mercID == 28 || mercID == 29) {
  80 + return D2S_DIFFICULTY_HELL;
  81 + }
  82 + return D2S_DIFFICULTY_UNKNOWN;
35 83 }
36 84  
37   -int setMerc(D2S_MERCTYPE type, D2S_MERCSUBTYPE subtype, D2S_DIFFICULTY difficulty) {
38   - // TODO
  85 +int setMerc(D2CharHeader* c, D2S_MERCTYPE type, D2S_MERCSUBTYPE subtype, D2S_DIFFICULTY difficulty) {
  86 + switch(type) {
  87 + case D2S_MERCTYPE_ROGUE:
  88 + switch(subtype) {
  89 + case D2S_MERCSUBTYPE_FIRE_ARROW:
  90 + switch(difficulty) {
  91 + case D2S_DIFFICULTY_NORMAL:
  92 + c->mercenaryType = 0;
  93 + return 0;
  94 + break;
  95 + case D2S_DIFFICULTY_NIGHTMARE:
  96 + c->mercenaryType = 2;
  97 + return 0;
  98 + break;
  99 + case D2S_DIFFICULTY_HELL:
  100 + c->mercenaryType = 4;
  101 + return 0;
  102 + break;
  103 + }
  104 + break;
  105 + case D2S_MERCSUBTYPE_COLD_ARROW:
  106 + switch(difficulty) {
  107 + case D2S_DIFFICULTY_NORMAL:
  108 + c->mercenaryType = 1;
  109 + return 0;
  110 + break;
  111 + case D2S_DIFFICULTY_NIGHTMARE:
  112 + c->mercenaryType = 3;
  113 + return 0;
  114 + break;
  115 + case D2S_DIFFICULTY_HELL:
  116 + c->mercenaryType = 5;
  117 + return 0;
  118 + break;
  119 + }
  120 + break;
  121 + }
  122 + break;
  123 + case D2S_MERCTYPE_DESERT:
  124 + switch(subtype) {
  125 + case D2S_MERCSUBTYPE_COMBAT:
  126 + switch(difficulty) {
  127 + case D2S_DIFFICULTY_NORMAL:
  128 + c->mercenaryType = 6;
  129 + return 0;
  130 + break;
  131 + case D2S_DIFFICULTY_NIGHTMARE:
  132 + c->mercenaryType = 9;
  133 + return 0;
  134 + break;
  135 + case D2S_DIFFICULTY_HELL:
  136 + c->mercenaryType = 12;
  137 + return 0;
  138 + break;
  139 + }
  140 + break;
  141 + case D2S_MERCSUBTYPE_DEFENSIVE:
  142 + switch(difficulty) {
  143 + case D2S_DIFFICULTY_NORMAL:
  144 + c->mercenaryType = 7;
  145 + return 0;
  146 + break;
  147 + case D2S_DIFFICULTY_NIGHTMARE:
  148 + c->mercenaryType = 10;
  149 + return 0;
  150 + break;
  151 + case D2S_DIFFICULTY_HELL:
  152 + c->mercenaryType = 13;
  153 + return 0;
  154 + break;
  155 + }
  156 + break;
  157 + case D2S_MERCSUBTYPE_OFFENSIVE:
  158 + switch(difficulty) {
  159 + case D2S_DIFFICULTY_NORMAL:
  160 + c->mercenaryType = 8;
  161 + return 0;
  162 + break;
  163 + case D2S_DIFFICULTY_NIGHTMARE:
  164 + c->mercenaryType = 11;
  165 + return 0;
  166 + break;
  167 + case D2S_DIFFICULTY_HELL:
  168 + c->mercenaryType = 14;
  169 + return 0;
  170 + break;
  171 + }
  172 + break;
  173 + }
  174 + break;
  175 + case D2S_MERCTYPE_SORCEROR:
  176 + switch(subtype) {
  177 + case D2S_MERCSUBTYPE_FIRE:
  178 + switch(difficulty) {
  179 + case D2S_DIFFICULTY_NORMAL:
  180 + c->mercenaryType = 15;
  181 + return 0;
  182 + break;
  183 + case D2S_DIFFICULTY_NIGHTMARE:
  184 + c->mercenaryType = 18;
  185 + return 0;
  186 + break;
  187 + case D2S_DIFFICULTY_HELL:
  188 + c->mercenaryType = 21;
  189 + return 0;
  190 + break;
  191 + }
  192 + break;
  193 + case D2S_MERCSUBTYPE_COLD:
  194 + switch(difficulty) {
  195 + case D2S_DIFFICULTY_NORMAL:
  196 + c->mercenaryType = 16;
  197 + return 0;
  198 + break;
  199 + case D2S_DIFFICULTY_NIGHTMARE:
  200 + c->mercenaryType = 19;
  201 + return 0;
  202 + break;
  203 + case D2S_DIFFICULTY_HELL:
  204 + c->mercenaryType = 22;
  205 + return 0;
  206 + break;
  207 + }
  208 + break;
  209 + case D2S_MERCSUBTYPE_LIGHTNING:
  210 + switch(difficulty) {
  211 + case D2S_DIFFICULTY_NORMAL:
  212 + c->mercenaryType = 17;
  213 + return 0;
  214 + break;
  215 + case D2S_DIFFICULTY_NIGHTMARE:
  216 + c->mercenaryType = 20;
  217 + return 0;
  218 + break;
  219 + case D2S_DIFFICULTY_HELL:
  220 + c->mercenaryType = 23;
  221 + return 0;
  222 + break;
  223 + }
  224 + break;
  225 + }
  226 + break;
  227 + case D2S_MERCTYPE_BARBARIAN:
  228 + // There's actually 2 identifiers for barbarians in each difficulty, they don't seem to have
  229 + // noticeable effect in game, so I'm considering only one of them. If you want to specifcially
  230 + // change to the other type, you probably know already what the mercID is so change it directly
  231 + // in the header instead of using this function
  232 + switch(difficulty) {
  233 + case D2S_DIFFICULTY_NORMAL:
  234 + c->mercenaryType = 24;
  235 + return 0;
  236 + break;
  237 + case D2S_DIFFICULTY_NIGHTMARE:
  238 + c->mercenaryType = 26;
  239 + return 0;
  240 + break;
  241 + case D2S_DIFFICULTY_HELL:
  242 + c->mercenaryType = 28;
  243 + return 0;
  244 + break;
  245 + }
  246 + break;
  247 + }
  248 + fprintf(stderr,"libd2char error: invalid combination of parameters for setMerc()\n");
  249 + return -1;
39 250 }
40 251 \ No newline at end of file
... ...
d2mercs.h
... ... @@ -186,6 +186,6 @@ const char* getMercName(uint16_t mercID, uint16_t mercNameID);
186 186 D2S_MERCTYPE getMercType(uint16_t mercID);
187 187 D2S_MERCSUBTYPE getMercSubType(uint16_t mercID);
188 188 D2S_DIFFICULTY getMercDifficulty(uint16_t mercID);
189   -int setMerc(D2S_MERCTYPE type, D2S_MERCSUBTYPE subtype, D2S_DIFFICULTY difficulty);
  189 +int setMerc(D2CharHeader* c, D2S_MERCTYPE type, D2S_MERCSUBTYPE subtype, D2S_DIFFICULTY difficulty);
190 190  
191 191 #endif
192 192 \ No newline at end of file
... ...
d2quest.c
... ... @@ -17,10 +17,16 @@ int getCheckpointDescriptions(D2S_QUEST quest, const char* *descriptions[16]) {
17 17 return -1;
18 18 }
19 19 memcpy(descriptions,(&checkpointDescriptions) + (quest * 16 * sizeof(const char*)), 16 * sizeof(const char*));
  20 + return 0;
20 21 }
21 22  
22 23 int getQuestStatus(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, uint16_t* data) {
23   - // TODO sanity check diff and quest
  24 + if(difficulty != D2S_DIFFICULTY_NORMAL ||
  25 + difficulty != D2S_DIFFICULTY_NIGHTMARE ||
  26 + difficulty != D2S_DIFFICULTY_HELL) {
  27 + fprintf(stderr,"libd2char error: difficulty %d doesn't exist\n",difficulty);
  28 + return -1;
  29 + }
24 30 if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_SISTERS_TO_THE_SLAUGHTER) {
25 31 *data = d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[quest];
26 32 } else if(quest >= D2S_QUEST_RADAMENT_LAIR && quest <= D2S_QUEST_SEVEN_TOMBS) {
... ... @@ -39,7 +45,12 @@ int getQuestStatus(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, u
39 45 }
40 46  
41 47 int setQuestStatus(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, uint16_t questData) {
42   - // TODO sanity check diff and quest
  48 + if(difficulty != D2S_DIFFICULTY_NORMAL ||
  49 + difficulty != D2S_DIFFICULTY_NIGHTMARE ||
  50 + difficulty != D2S_DIFFICULTY_HELL) {
  51 + fprintf(stderr,"libd2char error: difficulty %d doesn't exist\n",difficulty);
  52 + return -1;
  53 + }
43 54 if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_SISTERS_TO_THE_SLAUGHTER) {
44 55 d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[quest] = questData;
45 56 } else if(quest >= D2S_QUEST_RADAMENT_LAIR && quest <= D2S_QUEST_SEVEN_TOMBS) {
... ... @@ -133,22 +144,34 @@ int setQuestCompleted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty
133 144 return setQuestStatus(d,quest,difficulty,questData);
134 145 }
135 146  
136   -int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, D2S_DIFFICULTY difficulty) {
  147 +int getSpecialQuestStatus(D2QuestData* d, D2S_SPECIALQUEST specialQuestState, D2S_DIFFICULTY difficulty) {
  148 + if(difficulty != D2S_DIFFICULTY_NORMAL ||
  149 + difficulty != D2S_DIFFICULTY_NIGHTMARE ||
  150 + difficulty != D2S_DIFFICULTY_HELL) {
  151 + fprintf(stderr,"libd2char error: difficulty %d doesn't exist\n",difficulty);
  152 + return -1;
  153 + }
137 154 int ret = 0;
138 155 switch(specialQuestState) {
139 156 case D2S_SPECIALQUEST_AKARA_RESPEC:
140 157 ret = d->quests[difficulty].akaraRespecData & D2S_QUEST_STATUS_REWARD_AVAILABLE;
141 158 break;
  159 + default:
  160 + fprintf(stderr,"libd2char error: invalid special quest %d\n",specialQuestState);
  161 + ret = -1;
  162 + break;
142 163 }
143 164 return ret;
144 165 }
145 166  
146   -int setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, D2S_DIFFICULTY difficulty, int bool) {
  167 +int setSpecialQuestStatus(D2QuestData* d, D2S_SPECIALQUEST specialQuestState, D2S_DIFFICULTY difficulty, int bool) {
147 168 if(difficulty != D2S_DIFFICULTY_NORMAL ||
148 169 difficulty != D2S_DIFFICULTY_NIGHTMARE ||
149 170 difficulty != D2S_DIFFICULTY_HELL) {
150 171 fprintf(stderr,"libd2char error: difficulty %d doesn't exist\n",difficulty);
  172 + return -1;
151 173 }
  174 + int ret = 0;
152 175 switch(specialQuestState) {
153 176 case D2S_SPECIALQUEST_AKARA_RESPEC:
154 177 // This operation only makes sense if the quest is actually completed, otherwise ignore request
... ... @@ -160,5 +183,10 @@ int setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, D2S_DI
160 183 }
161 184 }
162 185 break;
  186 + default:
  187 + fprintf(stderr,"libd2char error: invalid special quest %d\n",specialQuestState);
  188 + ret = -1;
  189 + break;
163 190 }
  191 + return ret;
164 192 }
165 193 \ No newline at end of file
... ...
d2skills.c
1   -#include "d2char.h"
2 1 #include "d2skills.h"
3 2  
4 3 #include <stdio.h>
5 4 #include <stdlib.h>
6 5  
7   -D2S_CHARCLASS getSkillClass(D2S_SKILL skillID) {
8   - // TODO
9   -}
10   -
11 6 const char* getSkillName(D2S_SKILL skillID) {
12   - if(skillID > D2S_SKILL_NUMSKILLS) {
  7 + if(skillID > D2S_SKILL_NUMSKILLS || skillID < 0) {
13 8 fprintf(stderr,"libd2char error: skillID %d doesn't exist\n",skillID);
14 9 return NULL;
15 10 }
16   - return skills[skillID];
  11 + return skillNames[skillID];
  12 +}
  13 +
  14 +D2S_SKILL getSkillIDFromCharOffset(D2S_CHARCLASS class, unsigned int offset) {
  15 + if(offset < 0 || offset > D2S_SKILL_MAXSKILLS_PER_CHAR) {
  16 + fprintf(stderr,"libd2char error: Invalid character skill offset: %d\n",offset);
  17 + return D2S_SKILL_UNKNOWN;
  18 + }
  19 + switch(class) {
  20 + case D2S_CHARCLASS_AMAZON:
  21 + return amazonSkills[offset];
  22 + break;
  23 + case D2S_CHARCLASS_SORCERESS:
  24 + return sorceressSkills[offset];
  25 + break;
  26 + case D2S_CHARCLASS_NECROMANCER:
  27 + return necromancerSkills[offset];
  28 + break;
  29 + case D2S_CHARCLASS_PALADIN:
  30 + return paladinSkills[offset];
  31 + break;
  32 + case D2S_CHARCLASS_BARBARIAN:
  33 + return barbarianSkills[offset];
  34 + break;
  35 + case D2S_CHARCLASS_DRUID:
  36 + return druidSkills[offset];
  37 + break;
  38 + case D2S_CHARCLASS_ASSASSIN:
  39 + return assassinSkills[offset];
  40 + break;
  41 + case D2S_CHARCLASS_UNKNOWN:
  42 + default:
  43 + return D2S_SKILL_UNKNOWN;
  44 + break;
  45 + }
17 46 }
18 47 \ No newline at end of file
... ...
d2skills.h
... ... @@ -3,14 +3,605 @@
3 3  
4 4 #include <stdint.h>
5 5  
  6 +#include "d2char.h"
6 7 #include "d2strings.h"
7 8  
8 9 #define D2S_SKILL_NUMSKILLS 357
  10 +#define D2S_SKILL_MAXSKILLS_PER_CHAR 30
9 11  
10   -// TODO skill class trees
11   -typedef int D2S_SKILL;
  12 +typedef enum D2S_SKILL {
  13 + D2S_SKILL_UNKNOWN = -1,
  14 + D2S_SKILL_ATTACK = 0,
  15 + D2S_SKILL_KICK,
  16 + D2S_SKILL_THROW_ITEM,
  17 + D2S_SKILL_UNSUMMON,
  18 + D2S_SKILL_LEFT_HAND_THROW,
  19 + D2S_SKILL_LEFT_HAND_SWING,
  20 + D2S_SKILL_MAGIC_ARROW,
  21 + D2S_SKILL_FIRE_ARROW,
  22 + D2S_SKILL_INNER_SIGHT,
  23 + D2S_SKILL_CRITICAL_STRIKE,
  24 + D2S_SKILL_JAB,
  25 + D2S_SKILL_COLD_ARROW,
  26 + D2S_SKILL_MULTIPLE_SHOT,
  27 + D2S_SKILL_DODGE,
  28 + D2S_SKILL_POWER_STRIKE,
  29 + D2S_SKILL_POISON_JAVELIN,
  30 + D2S_SKILL_EXPLODING_ARROW,
  31 + D2S_SKILL_SLOW_MISSILES,
  32 + D2S_SKILL_AVOID,
  33 + D2S_SKILL_IMPALE,
  34 + D2S_SKILL_LIGHTNING_BOLT,
  35 + D2S_SKILL_ICE_ARROW,
  36 + D2S_SKILL_GUIDED_ARROW,
  37 + D2S_SKILL_PENETRATE,
  38 + D2S_SKILL_CHARGED_STRIKE,
  39 + D2S_SKILL_PLAGUE_JAVELIN,
  40 + D2S_SKILL_STRAFE,
  41 + D2S_SKILL_IMMOLATION_ARROW,
  42 + D2S_SKILL_DOPPLEZON,
  43 + D2S_SKILL_EVADE,
  44 + D2S_SKILL_FEND,
  45 + D2S_SKILL_FREEZING_ARROW,
  46 + D2S_SKILL_VALKYRIE,
  47 + D2S_SKILL_PIERCE,
  48 + D2S_SKILL_LIGHTNING_STRIKE,
  49 + D2S_SKILL_LIGHTNING_FURY,
  50 + D2S_SKILL_FIRE_BOLT,
  51 + D2S_SKILL_WARMTH,
  52 + D2S_SKILL_CHARGED_BOLT,
  53 + D2S_SKILL_ICE_BOLT,
  54 + D2S_SKILL_FROZEN_ARMOR,
  55 + D2S_SKILL_INFERNO,
  56 + D2S_SKILL_STATIC_FIELD,
  57 + D2S_SKILL_TELEKINESIS,
  58 + D2S_SKILL_FROST_NOVA,
  59 + D2S_SKILL_ICE_BLAST,
  60 + D2S_SKILL_BLAZE,
  61 + D2S_SKILL_FIRE_BALL,
  62 + D2S_SKILL_NOVA,
  63 + D2S_SKILL_LIGHTNING,
  64 + D2S_SKILL_SHIVER_ARMOR,
  65 + D2S_SKILL_FIRE_WALL,
  66 + D2S_SKILL_ENCHANT,
  67 + D2S_SKILL_CHAIN_LIGHTNING,
  68 + D2S_SKILL_TELEPORT,
  69 + D2S_SKILL_GLACIAL_SPIKE,
  70 + D2S_SKILL_METEOR,
  71 + D2S_SKILL_THUNDER_STORM,
  72 + D2S_SKILL_ENERGY_SHIELD,
  73 + D2S_SKILL_BLIZZARD,
  74 + D2S_SKILL_CHILLING_ARMOR,
  75 + D2S_SKILL_FIRE_MASTERY,
  76 + D2S_SKILL_HYDRA,
  77 + D2S_SKILL_LIGHTNING_MASTERY,
  78 + D2S_SKILL_FROZEN_ORB,
  79 + D2S_SKILL_COLD_MASTERY,
  80 + D2S_SKILL_AMPLIFY_DAMAGE,
  81 + D2S_SKILL_TEETH,
  82 + D2S_SKILL_BONE_ARMOR,
  83 + D2S_SKILL_SKELETON_MASTERY,
  84 + D2S_SKILL_RAISE_SKELETON,
  85 + D2S_SKILL_DIM_VISION,
  86 + D2S_SKILL_WEAKEN,
  87 + D2S_SKILL_POISON_DAGGER,
  88 + D2S_SKILL_CORPSE_EXPLOSION,
  89 + D2S_SKILL_CLAY_GOLEM,
  90 + D2S_SKILL_IRON_MAIDEN,
  91 + D2S_SKILL_TERROR,
  92 + D2S_SKILL_BONE_WALL,
  93 + D2S_SKILL_GOLEM_MASTERY,
  94 + D2S_SKILL_RAISE_SKELETAL_MAGE,
  95 + D2S_SKILL_CONFUSE,
  96 + D2S_SKILL_LIFE_TAP,
  97 + D2S_SKILL_POISON_EXPLOSION,
  98 + D2S_SKILL_BONE_SPEAR,
  99 + D2S_SKILL_BLOOD_GOLEM,
  100 + D2S_SKILL_ATTRACT,
  101 + D2S_SKILL_DECREPIFY,
  102 + D2S_SKILL_BONE_PRISON,
  103 + D2S_SKILL_SUMMON_RESIST,
  104 + D2S_SKILL_IRON_GOLEM,
  105 + D2S_SKILL_LOWER_RESIST,
  106 + D2S_SKILL_POISON_NOVA,
  107 + D2S_SKILL_BONE_SPIRIT,
  108 + D2S_SKILL_FIRE_GOLEM,
  109 + D2S_SKILL_REVIVE,
  110 + D2S_SKILL_SACRIFICE,
  111 + D2S_SKILL_SMITE,
  112 + D2S_SKILL_MIGHT,
  113 + D2S_SKILL_PRAYER,
  114 + D2S_SKILL_RESIST_FIRE,
  115 + D2S_SKILL_HOLY_BOLT,
  116 + D2S_SKILL_HOLY_FIRE,
  117 + D2S_SKILL_THORNS,
  118 + D2S_SKILL_DEFIANCE,
  119 + D2S_SKILL_RESIST_COLD,
  120 + D2S_SKILL_ZEAL,
  121 + D2S_SKILL_CHARGE,
  122 + D2S_SKILL_BLESSED_AIM,
  123 + D2S_SKILL_CLEANSING,
  124 + D2S_SKILL_RESIST_LIGHTNING,
  125 + D2S_SKILL_VENGEANCE,
  126 + D2S_SKILL_BLESSED_HAMMER,
  127 + D2S_SKILL_CONCENTRATION,
  128 + D2S_SKILL_HOLY_FREEZE,
  129 + D2S_SKILL_VIGOR,
  130 + D2S_SKILL_CONVERSION,
  131 + D2S_SKILL_HOLY_SHIELD,
  132 + D2S_SKILL_HOLY_SHOCK,
  133 + D2S_SKILL_SANCTUARY,
  134 + D2S_SKILL_MEDITATION,
  135 + D2S_SKILL_FIST_OF_THE_HEAVENS,
  136 + D2S_SKILL_FANATICISM,
  137 + D2S_SKILL_CONVICTION,
  138 + D2S_SKILL_REDEMPTION,
  139 + D2S_SKILL_SALVATION,
  140 + D2S_SKILL_BASH,
  141 + D2S_SKILL_SWORD_MASTERY,
  142 + D2S_SKILL_AXE_MASTERY,
  143 + D2S_SKILL_MACE_MASTERY,
  144 + D2S_SKILL_HOWL,
  145 + D2S_SKILL_FIND_POTION,
  146 + D2S_SKILL_LEAP,
  147 + D2S_SKILL_DOUBLE_SWING,
  148 + D2S_SKILL_POLE_ARM_MASTERY,
  149 + D2S_SKILL_THROWING_MASTERY,
  150 + D2S_SKILL_SPEAR_MASTERY,
  151 + D2S_SKILL_TAUNT,
  152 + D2S_SKILL_SHOUT,
  153 + D2S_SKILL_STUN,
  154 + D2S_SKILL_DOUBLE_THROW,
  155 + D2S_SKILL_INCREASED_STAMINA,
  156 + D2S_SKILL_FIND_ITEM,
  157 + D2S_SKILL_LEAP_ATTACK,
  158 + D2S_SKILL_CONCENTRATE,
  159 + D2S_SKILL_IRON_SKIN,
  160 + D2S_SKILL_BATTLE_CRY,
  161 + D2S_SKILL_FRENZY,
  162 + D2S_SKILL_INCREASED_SPEED,
  163 + D2S_SKILL_BATTLE_ORDERS,
  164 + D2S_SKILL_GRIM_WARD,
  165 + D2S_SKILL_WHIRLWIND,
  166 + D2S_SKILL_BERSERK,
  167 + D2S_SKILL_NATURAL_RESISTANCE,
  168 + D2S_SKILL_WAR_CRY,
  169 + D2S_SKILL_BATTLE_COMMAND,
  170 + D2S_SKILL_FIRE_HIT,
  171 + D2S_SKILL_UNHOLY_BOLT,
  172 + D2S_SKILL_SKELETON_RAISE,
  173 + D2S_SKILL_MAGGOT_EGG,
  174 + D2S_SKILL_SHAMAN_FIRE,
  175 + D2S_SKILL_MAGOTTUP,
  176 + D2S_SKILL_MAGOTTDOWN,
  177 + D2S_SKILL_MAGOTTLAY,
  178 + D2S_SKILL_ANDRIAL_SPRAY,
  179 + D2S_SKILL_JUMP,
  180 + D2S_SKILL_SWARM_MOVE,
  181 + D2S_SKILL_NEST,
  182 + D2S_SKILL_QUICK_STRIKE,
  183 + D2S_SKILL_VAMPIRE_FIREBALL,
  184 + D2S_SKILL_VAMPIRE_FIREWALL,
  185 + D2S_SKILL_VAMPIRE_METEOR,
  186 + D2S_SKILL_GARGOYLE_TRAP,
  187 + D2S_SKILL_SPIDER_LAY,
  188 + D2S_SKILL_VAMPIRE_HEAL,
  189 + D2S_SKILL_VAMPIRE_RAISE,
  190 + D2S_SKILL_SUBMERGE,
  191 + D2S_SKILL_FETISH_AURA,
  192 + D2S_SKILL_FETISH_INFERNO,
  193 + D2S_SKILL_ZAKARUM_HEAL,
  194 + D2S_SKILL_EMERGE,
  195 + D2S_SKILL_RESURRECT,
  196 + D2S_SKILL_BESTOW,
  197 + D2S_SKILL_MISSILE_SKILL1,
  198 + D2S_SKILL_MON_TELEPORT,
  199 + D2S_SKILL_PRIME_LIGHTNING,
  200 + D2S_SKILL_PRIME_BOLT,
  201 + D2S_SKILL_PRIME_BLAZE,
  202 + D2S_SKILL_PRIME_FIREWALL,
  203 + D2S_SKILL_PRIME_SPIKE,
  204 + D2S_SKILL_PRIME_ICE_NOVA,
  205 + D2S_SKILL_PRIME_POISON_BALL,
  206 + D2S_SKILL_PRIME_POISON_NOVA,
  207 + D2S_SKILL_DIABLIGHT,
  208 + D2S_SKILL_DIABCOLD,
  209 + D2S_SKILL_DIABFIRE,
  210 + D2S_SKILL_FINGERMAGESPIDER,
  211 + D2S_SKILL_DIABWALL,
  212 + D2S_SKILL_DIABRUN,
  213 + D2S_SKILL_DIABPRISON,
  214 + D2S_SKILL_POISON_BALL_TRAP,
  215 + D2S_SKILL_ANDY_POISON_BOLT,
  216 + D2S_SKILL_HIREABLE_MISSILE,
  217 + D2S_SKILL_DESERT_TURRET,
  218 + D2S_SKILL_ARCANE_TOWER,
  219 + D2S_SKILL_MONBLIZZARD,
  220 + D2S_SKILL_MOSQUITO,
  221 + D2S_SKILL_CURSED_BALL_TRAP_RIGHT,
  222 + D2S_SKILL_CURSED_BALL_TRAP_LEFT,
  223 + D2S_SKILL_MONFROZENARMOR,
  224 + D2S_SKILL_MONBONEARMOR,
  225 + D2S_SKILL_MONBONESPIRIT,
  226 + D2S_SKILL_MONCURSECAST,
  227 + D2S_SKILL_HELLMETEOR,
  228 + D2S_SKILL_REGURGITATOREAT,
  229 + D2S_SKILL_MONFRENZY,
  230 + D2S_SKILL_QUEENDEATH,
  231 + D2S_SKILL_SCROLL_OF_IDENTIFY,
  232 + D2S_SKILL_BOOK_OF_IDENTIFY,
  233 + D2S_SKILL_SCROLL_OF_TOWNPORTAL,
  234 + D2S_SKILL_BOOK_OF_TOWNPORTAL,
  235 + D2S_SKILL_RAVEN,
  236 + D2S_SKILL_POISON_CREEPER,
  237 + D2S_SKILL_WEARWOLF,
  238 + D2S_SKILL_SHAPE_SHIFTING,
  239 + D2S_SKILL_FIRESTORM,
  240 + D2S_SKILL_OAK_SAGE,
  241 + D2S_SKILL_SUMMON_SPIRIT_WOLF,
  242 + D2S_SKILL_WEARBEAR,
  243 + D2S_SKILL_MOLTEN_BOULDER,
  244 + D2S_SKILL_ARCTIC_BLAST,
  245 + D2S_SKILL_CYCLE_OF_LIFE,
  246 + D2S_SKILL_FERAL_RAGE,
  247 + D2S_SKILL_MAUL,
  248 + D2S_SKILL_ERUPTION,
  249 + D2S_SKILL_CYCLONE_ARMOR,
  250 + D2S_SKILL_HEART_OF_WOLVERINE,
  251 + D2S_SKILL_SUMMON_FENRIS,
  252 + D2S_SKILL_RABIES,
  253 + D2S_SKILL_FIRE_CLAWS,
  254 + D2S_SKILL_TWISTER,
  255 + D2S_SKILL_VINES,
  256 + D2S_SKILL_HUNGER,
  257 + D2S_SKILL_SHOCK_WAVE,
  258 + D2S_SKILL_VOLCANO,
  259 + D2S_SKILL_TORNADO,
  260 + D2S_SKILL_SPIRIT_OF_BARBS,
  261 + D2S_SKILL_SUMMON_GRIZZLY,
  262 + D2S_SKILL_FURY,
  263 + D2S_SKILL_ARMAGEDDON,
  264 + D2S_SKILL_HURRICANE,
  265 + D2S_SKILL_FIRE_BLAST,
  266 + D2S_SKILL_CLAW_MASTERY,
  267 + D2S_SKILL_PSYCHIC_HAMMER,
  268 + D2S_SKILL_TIGER_STRIKE,
  269 + D2S_SKILL_DRAGON_TALON,
  270 + D2S_SKILL_SHOCK_FIELD,
  271 + D2S_SKILL_BLADE_SENTINEL,
  272 + D2S_SKILL_QUICKNESS,
  273 + D2S_SKILL_FISTS_OF_FIRE,
  274 + D2S_SKILL_DRAGON_CLAW,
  275 + D2S_SKILL_CHARGED_BOLT_SENTRY,
  276 + D2S_SKILL_WAKE_OF_FIRE_SENTRY,
  277 + D2S_SKILL_WEAPON_BLOCK,
  278 + D2S_SKILL_CLOAK_OF_SHADOWS,
  279 + D2S_SKILL_COBRA_STRIKE,
  280 + D2S_SKILL_BLADE_FURY,
  281 + D2S_SKILL_FADE,
  282 + D2S_SKILL_SHADOW_WARRIOR,
  283 + D2S_SKILL_CLAWS_OF_THUNDER,
  284 + D2S_SKILL_DRAGON_TAIL,
  285 + D2S_SKILL_LIGHTNING_SENTRY,
  286 + D2S_SKILL_INFERNO_SENTRY,
  287 + D2S_SKILL_MIND_BLAST,
  288 + D2S_SKILL_BLADES_OF_ICE,
  289 + D2S_SKILL_DRAGON_FLIGHT,
  290 + D2S_SKILL_DEATH_SENTRY,
  291 + D2S_SKILL_BLADE_SHIELD,
  292 + D2S_SKILL_VENOM,
  293 + D2S_SKILL_SHADOW_MASTER,
  294 + D2S_SKILL_ROYAL_STRIKE,
  295 + D2S_SKILL_WAKE_OF_DESTRUCTION_SENTRY,
  296 + D2S_SKILL_IMP_INFERNO,
  297 + D2S_SKILL_IMP_FIREBALL,
  298 + D2S_SKILL_BAAL_TAUNT,
  299 + D2S_SKILL_BAAL_CORPSE_EXPLODE,
  300 + D2S_SKILL_BAAL_MONSTER_SPAWN,
  301 + D2S_SKILL_CATAPULT_CHARGED_BALL,
  302 + D2S_SKILL_CATAPULT_SPIKE_BALL,
  303 + D2S_SKILL_SUCK_BLOOD,
  304 + D2S_SKILL_CRY_HELP,
  305 + D2S_SKILL_HEALING_VORTEX,
  306 + D2S_SKILL_TELEPORT_2,
  307 + D2S_SKILL_SELF_RESURRECT,
  308 + D2S_SKILL_VINE_ATTACK,
  309 + D2S_SKILL_OVERSEER_WHIP,
  310 + D2S_SKILL_BARBS_AURA,
  311 + D2S_SKILL_WOLVERINE_AURA,
  312 + D2S_SKILL_OAK_SAGE_AURA,
  313 + D2S_SKILL_IMP_FIRE_MISSILE,
  314 + D2S_SKILL_IMPREGNATE,
  315 + D2S_SKILL_SIEGE_BEAST_STOMP,
  316 + D2S_SKILL_MINIONSPAWNER,
  317 + D2S_SKILL_CATAPULTBLIZZARD,
  318 + D2S_SKILL_CATAPULTPLAGUE,
  319 + D2S_SKILL_CATAPULTMETEOR,
  320 + D2S_SKILL_BOLTSENTRY,
  321 + D2S_SKILL_CORPSECYCLER,
  322 + D2S_SKILL_DEATHMAUL,
  323 + D2S_SKILL_DEFENSE_CURSE,
  324 + D2S_SKILL_BLOOD_MANA,
  325 + D2S_SKILL_MON_INFERNO_SENTRY,
  326 + D2S_SKILL_MON_DEATH_SENTRY,
  327 + D2S_SKILL_SENTRY_LIGHTNING,
  328 + D2S_SKILL_FENRIS_RAGE,
  329 + D2S_SKILL_BAAL_TENTACLE,
  330 + D2S_SKILL_BAAL_NOVA,
  331 + D2S_SKILL_BAAL_INFERNO,
  332 + D2S_SKILL_BAAL_COLD_MISSILES,
  333 + D2S_SKILL_MEGA_DEMON_INFERNO,
  334 + D2S_SKILL_EVIL_HUT_SPAWNER,
  335 + D2S_SKILL_COUNTESS_FIREWALL,
  336 + D2S_SKILL_IMPBOLT,
  337 + D2S_SKILL_HORROR_ARCTIC_BLAST,
  338 + D2S_SKILL_DEATH_SENTRY_LTNG,
  339 + D2S_SKILL_VINECYCLER,
  340 + D2S_SKILL_BEARSMITE,
  341 + D2S_SKILL_RESURRECT2,
  342 + D2S_SKILL_BLOODLORD_FRENZY,
  343 + D2S_SKILL_BAAL_TELEPORT,
  344 + D2S_SKILL_IMP_TELEPORT,
  345 + D2S_SKILL_BAAL_CLONE_TELEPORT,
  346 + D2S_SKILL_ZAKARUM_LIGHTNING,
  347 + D2S_SKILL_VAMPIRE_MISSILE,
  348 + D2S_SKILL_MEPHISTO_MISSILE,
  349 + D2S_SKILL_DOOM_KNIGHT_MISSILE,
  350 + D2S_SKILL_ROGUE_MISSILE,
  351 + D2S_SKILL_HYDRA_MISSILE,
  352 + D2S_SKILL_NECRO_MAGE_MISSILE,
  353 + D2S_SKILL_MONBOW,
  354 + D2S_SKILL_MONFIREARROW,
  355 + D2S_SKILL_MONCOLDARROW,
  356 + D2S_SKILL_MONEXPLODINGARROW,
  357 + D2S_SKILL_MONFREEZINGARROW,
  358 + D2S_SKILL_MONPOWERSTRIKE,
  359 + D2S_SKILL_SUCCUBUSBOLT,
  360 + D2S_SKILL_MEPHFROSTNOVA,
  361 + D2S_SKILL_MONICESPEAR,
  362 + D2S_SKILL_SHAMAN_ICE,
  363 + D2S_SKILL_DIABLOGEDDON,
  364 + D2S_SKILL_DELERIUM_CHANGE,
  365 + D2S_SKILL_NIHLATHAK_CORPSE_EXPLOSION,
  366 + D2S_SKILL_SERPENT_CHARGE,
  367 + D2S_SKILL_TRAP_NOVA,
  368 + D2S_SKILL_UNHOLY_BOLTEX,
  369 + D2S_SKILL_SHAMAN_FIREEX,
  370 + D2S_SKILL_IMP_FIRE_MISSILE_EX,
  371 +} D2S_SKILL;
12 372  
13   -const char* const skills[] = {
  373 +const D2S_SKILL amazonSkills[D2S_SKILL_MAXSKILLS_PER_CHAR] = {
  374 + D2S_SKILL_MAGIC_ARROW,
  375 + D2S_SKILL_FIRE_ARROW,
  376 + D2S_SKILL_INNER_SIGHT,
  377 + D2S_SKILL_CRITICAL_STRIKE,
  378 + D2S_SKILL_JAB,
  379 + D2S_SKILL_COLD_ARROW,
  380 + D2S_SKILL_MULTIPLE_SHOT,
  381 + D2S_SKILL_DODGE,
  382 + D2S_SKILL_POWER_STRIKE,
  383 + D2S_SKILL_POISON_JAVELIN,
  384 + D2S_SKILL_EXPLODING_ARROW,
  385 + D2S_SKILL_SLOW_MISSILES,
  386 + D2S_SKILL_AVOID,
  387 + D2S_SKILL_IMPALE,
  388 + D2S_SKILL_LIGHTNING_BOLT,
  389 + D2S_SKILL_ICE_ARROW,
  390 + D2S_SKILL_GUIDED_ARROW,
  391 + D2S_SKILL_PENETRATE,
  392 + D2S_SKILL_CHARGED_STRIKE,
  393 + D2S_SKILL_PLAGUE_JAVELIN,
  394 + D2S_SKILL_STRAFE,
  395 + D2S_SKILL_IMMOLATION_ARROW,
  396 + D2S_SKILL_DOPPLEZON,
  397 + D2S_SKILL_EVADE,
  398 + D2S_SKILL_FEND,
  399 + D2S_SKILL_FREEZING_ARROW,
  400 + D2S_SKILL_VALKYRIE,
  401 + D2S_SKILL_PIERCE,
  402 + D2S_SKILL_LIGHTNING_STRIKE,
  403 + D2S_SKILL_LIGHTNING_FURY
  404 +};
  405 +
  406 +const D2S_SKILL sorceressSkills[D2S_SKILL_MAXSKILLS_PER_CHAR] = {
  407 + D2S_SKILL_FIRE_BOLT,
  408 + D2S_SKILL_WARMTH,
  409 + D2S_SKILL_CHARGED_BOLT,
  410 + D2S_SKILL_ICE_BOLT,
  411 + D2S_SKILL_FROZEN_ARMOR,
  412 + D2S_SKILL_INFERNO,
  413 + D2S_SKILL_STATIC_FIELD,
  414 + D2S_SKILL_TELEKINESIS,
  415 + D2S_SKILL_FROST_NOVA,
  416 + D2S_SKILL_ICE_BLAST,
  417 + D2S_SKILL_BLAZE,
  418 + D2S_SKILL_FIRE_BALL,
  419 + D2S_SKILL_NOVA,
  420 + D2S_SKILL_LIGHTNING,
  421 + D2S_SKILL_SHIVER_ARMOR,
  422 + D2S_SKILL_FIRE_WALL,
  423 + D2S_SKILL_ENCHANT,
  424 + D2S_SKILL_CHAIN_LIGHTNING,
  425 + D2S_SKILL_TELEPORT,
  426 + D2S_SKILL_GLACIAL_SPIKE,
  427 + D2S_SKILL_METEOR,
  428 + D2S_SKILL_THUNDER_STORM,
  429 + D2S_SKILL_ENERGY_SHIELD,
  430 + D2S_SKILL_BLIZZARD,
  431 + D2S_SKILL_CHILLING_ARMOR,
  432 + D2S_SKILL_FIRE_MASTERY,
  433 + D2S_SKILL_HYDRA,
  434 + D2S_SKILL_LIGHTNING_MASTERY,
  435 + D2S_SKILL_FROZEN_ORB,
  436 + D2S_SKILL_COLD_MASTERY
  437 +};
  438 +
  439 +const D2S_SKILL necromancerSkills[D2S_SKILL_MAXSKILLS_PER_CHAR] = {
  440 + D2S_SKILL_AMPLIFY_DAMAGE,
  441 + D2S_SKILL_TEETH,
  442 + D2S_SKILL_BONE_ARMOR,
  443 + D2S_SKILL_SKELETON_MASTERY,
  444 + D2S_SKILL_RAISE_SKELETON,
  445 + D2S_SKILL_DIM_VISION,
  446 + D2S_SKILL_WEAKEN,
  447 + D2S_SKILL_POISON_DAGGER,
  448 + D2S_SKILL_CORPSE_EXPLOSION,
  449 + D2S_SKILL_CLAY_GOLEM,
  450 + D2S_SKILL_IRON_MAIDEN,
  451 + D2S_SKILL_TERROR,
  452 + D2S_SKILL_BONE_WALL,
  453 + D2S_SKILL_GOLEM_MASTERY,
  454 + D2S_SKILL_RAISE_SKELETAL_MAGE,
  455 + D2S_SKILL_CONFUSE,
  456 + D2S_SKILL_LIFE_TAP,
  457 + D2S_SKILL_POISON_EXPLOSION,
  458 + D2S_SKILL_BONE_SPEAR,
  459 + D2S_SKILL_BLOOD_GOLEM,
  460 + D2S_SKILL_ATTRACT,
  461 + D2S_SKILL_DECREPIFY,
  462 + D2S_SKILL_BONE_PRISON,
  463 + D2S_SKILL_SUMMON_RESIST,
  464 + D2S_SKILL_IRON_GOLEM,
  465 + D2S_SKILL_LOWER_RESIST,
  466 + D2S_SKILL_POISON_NOVA,
  467 + D2S_SKILL_BONE_SPIRIT,
  468 + D2S_SKILL_FIRE_GOLEM,
  469 + D2S_SKILL_REVIVE
  470 +};
  471 +
  472 +const D2S_SKILL paladinSkills[D2S_SKILL_MAXSKILLS_PER_CHAR] = {
  473 + D2S_SKILL_SACRIFICE,
  474 + D2S_SKILL_SMITE,
  475 + D2S_SKILL_MIGHT,
  476 + D2S_SKILL_PRAYER,
  477 + D2S_SKILL_RESIST_FIRE,
  478 + D2S_SKILL_HOLY_BOLT,
  479 + D2S_SKILL_HOLY_FIRE,
  480 + D2S_SKILL_THORNS,
  481 + D2S_SKILL_DEFIANCE,
  482 + D2S_SKILL_RESIST_COLD,
  483 + D2S_SKILL_ZEAL,
  484 + D2S_SKILL_CHARGE,
  485 + D2S_SKILL_BLESSED_AIM,
  486 + D2S_SKILL_CLEANSING,
  487 + D2S_SKILL_RESIST_LIGHTNING,
  488 + D2S_SKILL_VENGEANCE,
  489 + D2S_SKILL_BLESSED_HAMMER,
  490 + D2S_SKILL_CONCENTRATION,
  491 + D2S_SKILL_HOLY_FREEZE,
  492 + D2S_SKILL_VIGOR,
  493 + D2S_SKILL_CONVERSION,
  494 + D2S_SKILL_HOLY_SHIELD,
  495 + D2S_SKILL_HOLY_SHOCK,
  496 + D2S_SKILL_SANCTUARY,
  497 + D2S_SKILL_MEDITATION,
  498 + D2S_SKILL_FIST_OF_THE_HEAVENS,
  499 + D2S_SKILL_FANATICISM,
  500 + D2S_SKILL_CONVICTION,
  501 + D2S_SKILL_REDEMPTION,
  502 + D2S_SKILL_SALVATION
  503 +};
  504 +
  505 +const D2S_SKILL barbarianSkills[D2S_SKILL_MAXSKILLS_PER_CHAR] = {
  506 + D2S_SKILL_BASH,
  507 + D2S_SKILL_SWORD_MASTERY,
  508 + D2S_SKILL_AXE_MASTERY,
  509 + D2S_SKILL_MACE_MASTERY,
  510 + D2S_SKILL_HOWL,
  511 + D2S_SKILL_FIND_POTION,
  512 + D2S_SKILL_LEAP,
  513 + D2S_SKILL_DOUBLE_SWING,
  514 + D2S_SKILL_POLE_ARM_MASTERY,
  515 + D2S_SKILL_THROWING_MASTERY,
  516 + D2S_SKILL_SPEAR_MASTERY,
  517 + D2S_SKILL_TAUNT,
  518 + D2S_SKILL_SHOUT,
  519 + D2S_SKILL_STUN,
  520 + D2S_SKILL_DOUBLE_THROW,
  521 + D2S_SKILL_INCREASED_STAMINA,
  522 + D2S_SKILL_FIND_ITEM,
  523 + D2S_SKILL_LEAP_ATTACK,
  524 + D2S_SKILL_CONCENTRATE,
  525 + D2S_SKILL_IRON_SKIN,
  526 + D2S_SKILL_BATTLE_CRY,
  527 + D2S_SKILL_FRENZY,
  528 + D2S_SKILL_INCREASED_SPEED,
  529 + D2S_SKILL_BATTLE_ORDERS,
  530 + D2S_SKILL_GRIM_WARD,
  531 + D2S_SKILL_WHIRLWIND,
  532 + D2S_SKILL_BERSERK,
  533 + D2S_SKILL_NATURAL_RESISTANCE,
  534 + D2S_SKILL_WAR_CRY,
  535 + D2S_SKILL_BATTLE_COMMAND
  536 +};
  537 +
  538 +const D2S_SKILL druidSkills[D2S_SKILL_MAXSKILLS_PER_CHAR] = {
  539 + D2S_SKILL_RAVEN,
  540 + D2S_SKILL_POISON_CREEPER,
  541 + D2S_SKILL_WEARWOLF,
  542 + D2S_SKILL_SHAPE_SHIFTING,
  543 + D2S_SKILL_FIRESTORM,
  544 + D2S_SKILL_OAK_SAGE,
  545 + D2S_SKILL_SUMMON_SPIRIT_WOLF,
  546 + D2S_SKILL_WEARBEAR,
  547 + D2S_SKILL_MOLTEN_BOULDER,
  548 + D2S_SKILL_ARCTIC_BLAST,
  549 + D2S_SKILL_CYCLE_OF_LIFE,
  550 + D2S_SKILL_FERAL_RAGE,
  551 + D2S_SKILL_MAUL,
  552 + D2S_SKILL_ERUPTION,
  553 + D2S_SKILL_CYCLONE_ARMOR,
  554 + D2S_SKILL_HEART_OF_WOLVERINE,
  555 + D2S_SKILL_SUMMON_FENRIS,
  556 + D2S_SKILL_RABIES,
  557 + D2S_SKILL_FIRE_CLAWS,
  558 + D2S_SKILL_TWISTER,
  559 + D2S_SKILL_VINES,
  560 + D2S_SKILL_HUNGER,
  561 + D2S_SKILL_SHOCK_WAVE,
  562 + D2S_SKILL_VOLCANO,
  563 + D2S_SKILL_TORNADO,
  564 + D2S_SKILL_SPIRIT_OF_BARBS,
  565 + D2S_SKILL_SUMMON_GRIZZLY,
  566 + D2S_SKILL_FURY,
  567 + D2S_SKILL_ARMAGEDDON,
  568 + D2S_SKILL_HURRICANE
  569 +};
  570 +
  571 +const D2S_SKILL assassinSkills[D2S_SKILL_MAXSKILLS_PER_CHAR] = {
  572 + D2S_SKILL_FIRE_BLAST,
  573 + D2S_SKILL_CLAW_MASTERY,
  574 + D2S_SKILL_PSYCHIC_HAMMER,
  575 + D2S_SKILL_TIGER_STRIKE,
  576 + D2S_SKILL_DRAGON_TALON,
  577 + D2S_SKILL_SHOCK_FIELD,
  578 + D2S_SKILL_BLADE_SENTINEL,
  579 + D2S_SKILL_QUICKNESS,
  580 + D2S_SKILL_FISTS_OF_FIRE,
  581 + D2S_SKILL_DRAGON_CLAW,
  582 + D2S_SKILL_CHARGED_BOLT_SENTRY,
  583 + D2S_SKILL_WAKE_OF_FIRE_SENTRY,
  584 + D2S_SKILL_WEAPON_BLOCK,
  585 + D2S_SKILL_CLOAK_OF_SHADOWS,
  586 + D2S_SKILL_COBRA_STRIKE,
  587 + D2S_SKILL_BLADE_FURY,
  588 + D2S_SKILL_FADE,
  589 + D2S_SKILL_SHADOW_WARRIOR,
  590 + D2S_SKILL_CLAWS_OF_THUNDER,
  591 + D2S_SKILL_DRAGON_TAIL,
  592 + D2S_SKILL_LIGHTNING_SENTRY,
  593 + D2S_SKILL_INFERNO_SENTRY,
  594 + D2S_SKILL_MIND_BLAST,
  595 + D2S_SKILL_BLADES_OF_ICE,
  596 + D2S_SKILL_DRAGON_FLIGHT,
  597 + D2S_SKILL_DEATH_SENTRY,
  598 + D2S_SKILL_BLADE_SHIELD,
  599 + D2S_SKILL_VENOM,
  600 + D2S_SKILL_SHADOW_MASTER,
  601 + D2S_SKILL_ROYAL_STRIKE
  602 +};
  603 +
  604 +const char* const skillNames[] = {
14 605 D2S_SKILL_0,
15 606 D2S_SKILL_1,
16 607 D2S_SKILL_2,
... ... @@ -372,6 +963,6 @@ const char* const skills[] = {
372 963  
373 964 // Returns static string from library memory, no need to free
374 965 const char* getSkillName(D2S_SKILL skillID);
375   -D2S_CHARCLASS getSkillClass(D2S_SKILL skillID);
  966 +D2S_SKILL getSkillIDFromCharOffset(D2S_CHARCLASS class, unsigned int offset);
376 967  
377 968 #endif
378 969 \ No newline at end of file
... ...
d2waypoints.c
1 1 #include "d2waypoints.h"
2 2 #include "d2char.h"
3 3  
  4 +#include <stdio.h>
  5 +
  6 +const char* getWaypointName(D2S_WAYPOINT waypoint) {
  7 + if(waypoint > D2S_WAYPOINTSDATA_NUMWAYPOINTS) {
  8 + fprintf(stderr,"libd2char error: waypoint %d doesn't exist\n",waypoint);
  9 + return NULL;
  10 + }
  11 + return waypoints[waypoint];
  12 +}
  13 +
4 14 int isWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty) {
5 15 if(waypoint > D2S_WAYPOINTSDATA_NUMWAYPOINTS) {
  16 + fprintf(stderr,"libd2char error: waypoint %d doesn't exist\n",waypoint);
  17 + return -1;
  18 + }
  19 + if(difficulty != D2S_DIFFICULTY_NORMAL ||
  20 + difficulty != D2S_DIFFICULTY_NIGHTMARE ||
  21 + difficulty != D2S_DIFFICULTY_HELL) {
  22 + fprintf(stderr,"libd2char error: difficulty %d doesn't exist\n",difficulty);
6 23 return -1;
7 24 }
8 25 unsigned int byte = waypoint / 8;
... ... @@ -10,12 +27,19 @@ int isWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULT
10 27 return (d->waypoints[difficulty].waypointData[byte] & (1 << offset)) >> offset;
11 28 }
12 29  
13   -// TODO: Return success
14   -void setWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty, int activated) {
  30 +int setWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty, int activated) {
15 31 if(waypoint > D2S_WAYPOINTSDATA_NUMWAYPOINTS) {
16   - return;
  32 + fprintf(stderr,"libd2char error: waypoint %d doesn't exist\n",waypoint);
  33 + return -1;
  34 + }
  35 + if(difficulty != D2S_DIFFICULTY_NORMAL ||
  36 + difficulty != D2S_DIFFICULTY_NIGHTMARE ||
  37 + difficulty != D2S_DIFFICULTY_HELL) {
  38 + fprintf(stderr,"libd2char error: difficulty %d doesn't exist\n",difficulty);
  39 + return -1;
17 40 }
18 41 unsigned int byte = waypoint / 8;
19 42 unsigned int offset = waypoint % 8;
20 43 d->waypoints[difficulty].waypointData[byte] |= (1 << offset);
  44 + return 0;
21 45 }
22 46 \ No newline at end of file
... ...
d2waypoints.h
... ... @@ -13,7 +13,46 @@ typedef enum D2S_DIFFICULTY D2S_DIFFICULTY;
13 13 #define D2S_WAYPOINTSDATA_NUMWAYPOINTS 39
14 14  
15 15 typedef enum D2S_WAYPOINT {
16   -asd
  16 + D2S_WAYPOINT_UNKNOWN = -1,
  17 + D2S_WAYPOINT_ROGUE_ENCAMPMENT = 0,
  18 + D2S_WAYPOINT_COLD_PLAINS,
  19 + D2S_WAYPOINT_STONY_FIELD,
  20 + D2S_WAYPOINT_DARK_WOOD,
  21 + D2S_WAYPOINT_BLACK_MARSH,
  22 + D2S_WAYPOINT_OUTER_CLOISTER,
  23 + D2S_WAYPOINT_JAIL,
  24 + D2S_WAYPOINT_INNER_CLOISTER,
  25 + D2S_WAYPOINT_CATACOMBS,
  26 + D2S_WAYPOINT_LUT_GHOLEIN,
  27 + D2S_WAYPOINT_SEWERS,
  28 + D2S_WAYPOINT_DRY_HILLS,
  29 + D2S_WAYPOINT_HALLS_OF_THE_DEAD,
  30 + D2S_WAYPOINT_FAR_OASIS,
  31 + D2S_WAYPOINT_LOST_CITY,
  32 + D2S_WAYPOINT_PALACE_CELLAR,
  33 + D2S_WAYPOINT_ARCANE_SANCTUARY,
  34 + D2S_WAYPOINT_CANYON_OF_THE_MAGI,
  35 + D2S_WAYPOINT_KURAST_DOCS,
  36 + D2S_WAYPOINT_SPIDER_FOREST,
  37 + D2S_WAYPOINT_GREAT_MARSH,
  38 + D2S_WAYPOINT_FLAYER_JUNGLE,
  39 + D2S_WAYPOINT_LOWER_KURAST,
  40 + D2S_WAYPOINT_KURAST_BAZAAR,
  41 + D2S_WAYPOINT_UPPER_KURAST,
  42 + D2S_WAYPOINT_TRAVINCAL,
  43 + D2S_WAYPOINT_DURANCE_OF_HATE,
  44 + D2S_WAYPOINT_PANDEMONIUM_FORTRESS,
  45 + D2S_WAYPOINT_CITY_OF_THE_DAMNED,
  46 + D2S_WAYPOINT_RIVER_OF_FLAMES,
  47 + D2S_WAYPOINT_HARROGATH,
  48 + D2S_WAYPOINT_FRIGID_HIGHLANDS,
  49 + D2S_WAYPOINT_ARREAT_PLATEAU,
  50 + D2S_WAYPOINT_CRYSTALLINE_PASSAGE,
  51 + D2S_WAYPOINT_HALLS_OF_PAIN,
  52 + D2S_WAYPOINT_GLACIAL_TRAIL,
  53 + D2S_WAYPOINT_FROZEN_TUNDRA,
  54 + D2S_WAYPOINT_ANCIENTS_WAY,
  55 + D2S_WAYPOINT_WORLDSTONE_KEEP
17 56 } D2S_WAYPOINT;
18 57  
19 58 const char* const waypoints[] = {
... ... @@ -71,7 +110,9 @@ typedef struct __attribute__((packed)) {
71 110 D2Waypoints waypoints[3]; // 1 set for each difficulty
72 111 } D2WaypointsData;
73 112  
  113 +// Returns static string from library memory, no need to free
  114 +const char* getWaypointName(D2S_WAYPOINT waypoint);
74 115 int isWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty);
75   -void setWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty, int activated);
  116 +int setWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty, int activated);
76 117  
77 118 #endif
78 119 \ No newline at end of file
... ...