Commit 67c0083bbda0760634bfc0e0a0a00f74d42347a1

Authored by Imanol-Mikel Barba Sabariego
1 parent 6d88e3be

Missing some changes on previous commits

d2char.c
@@ -136,6 +136,10 @@ size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen) { @@ -136,6 +136,10 @@ size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen) {
136 } 136 }
137 137
138 const char* getSkillName(int skillID) { 138 const char* getSkillName(int skillID) {
  139 + if(skillID > D2S_SKILL_NUMSKILLS) {
  140 + fprintf(stderr,"libd2char error: skillID %d doesn't exist\n",skillID);
  141 + return NULL;
  142 + }
139 return skills[skillID]; 143 return skills[skillID];
140 } 144 }
141 145
d2char.h
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 #define D2S_HOTKEYS_LENGTH 64 17 #define D2S_HOTKEYS_LENGTH 64
18 #define D2S_CHAR_APPEARANCE_LENGTH 32 18 #define D2S_CHAR_APPEARANCE_LENGTH 32
19 #define D2S_DIFFICULTY_LENGTH 3 19 #define D2S_DIFFICULTY_LENGTH 3
20 -#define D2S_WAYPOINTS_LENGTH 81 20 +#define D2S_WAYPOINTS_LENGTH 80
21 #define D2S_NPCDATA_LENGTH 51 21 #define D2S_NPCDATA_LENGTH 51
22 22
23 #define D2S_CHARSTATUS_HARDCORE 0x04 23 #define D2S_CHARSTATUS_HARDCORE 0x04
@@ -92,11 +92,18 @@ typedef struct __attribute__((packed)){ @@ -92,11 +92,18 @@ typedef struct __attribute__((packed)){
92 uint8_t unknown6[144]; // TODO 92 uint8_t unknown6[144]; // TODO
93 D2QuestData questData; 93 D2QuestData questData;
94 uint8_t waypointData[D2S_WAYPOINTS_LENGTH]; 94 uint8_t waypointData[D2S_WAYPOINTS_LENGTH];
  95 + uint8_t unknown7; // TODO. Apparently this is always 0x01
95 uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented 96 uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented
96 } D2CharHeader; 97 } D2CharHeader;
97 98
98 // TODO: All setX functions 99 // TODO: All setX functions
99 100
  101 +// TODO: Load from file.
  102 +// int loadD2CharFromFile(const char* file, D2CharHeader** header, void** data);
  103 +
  104 +// TODO: Write to file.
  105 +// int writeD2CharToFile(const char* file, D2CharHeader* header, void* charData,)
  106 +
100 uint32_t calcChecksum(D2CharHeader* c, void* charData); 107 uint32_t calcChecksum(D2CharHeader* c, void* charData);
101 int checkChecksum(D2CharHeader* c, void* charData); 108 int checkChecksum(D2CharHeader* c, void* charData);
102 int isHardcore(D2CharHeader* c); 109 int isHardcore(D2CharHeader* c);
d2mercs.c
1 #include "d2mercs.h" 1 #include "d2mercs.h"
2 2
  3 +#include <stdlib.h>
  4 +
3 int _getMercType(int mercID) { 5 int _getMercType(int mercID) {
4 if(mercID >= 0 && mercID <= 5) { 6 if(mercID >= 0 && mercID <= 5) {
5 return D2S_MERCTYPE_ROGUE; 7 return D2S_MERCTYPE_ROGUE;
@@ -16,5 +18,8 @@ int _getMercType(int mercID) { @@ -16,5 +18,8 @@ int _getMercType(int mercID) {
16 18
17 const char* _getMercName(int mercID, int mercNameID) { 19 const char* _getMercName(int mercID, int mercNameID) {
18 int offset = _getMercType(mercID); 20 int offset = _getMercType(mercID);
  21 + if(offset == D2S_MERCTYPE_UNKNOWN) {
  22 + return NULL;
  23 + }
19 return mercNames[mercNameID + offset]; 24 return mercNames[mercNameID + offset];
20 } 25 }
21 \ No newline at end of file 26 \ No newline at end of file
d2mercs.h
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 3
4 #include "d2strings.h" 4 #include "d2strings.h"
5 5
  6 +// TODO: return compound data (type, subtype, difficulty, not just a string)
  7 +
6 // The values here are the offsets of each merc's names in the table. 8 // The values here are the offsets of each merc's names in the table.
7 // i.e: Merc names from pos 41 to 61 are Desert mercs 9 // i.e: Merc names from pos 41 to 61 are Desert mercs
8 // 10 //
d2quest.c
1 #include "d2char.h" 1 #include "d2char.h"
2 #include "d2quest.h" 2 #include "d2quest.h"
3 3
  4 +#include <stdio.h>
  5 +
4 void getCheckpointDescriptions(unsigned int quest, const char* *descriptions[16]) { 6 void getCheckpointDescriptions(unsigned int quest, const char* *descriptions[16]) {
  7 + if(quest > D2S_QUESTDATA_NUMQUESTS) {
  8 + fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);
  9 + return;
  10 + }
5 memcpy(descriptions,(&checkpointDescriptions) + (quest * 16 * sizeof(const char*)), 16 * sizeof(const char*)); 11 memcpy(descriptions,(&checkpointDescriptions) + (quest * 16 * sizeof(const char*)), 16 * sizeof(const char*));
6 } 12 }
7 13
@@ -17,7 +23,8 @@ uint16_t getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficu @@ -17,7 +23,8 @@ uint16_t getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficu
17 } else if(quest >= D2S_QUEST_SIEGE_ON_HARROGATH && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) { 23 } else if(quest >= D2S_QUEST_SIEGE_ON_HARROGATH && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) {
18 return d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH]; 24 return d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH];
19 } 25 }
20 - return D2S_QUEST_UNKNOWN; 26 + fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);
  27 + return 0;
21 } 28 }
22 29
23 void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, uint16_t questData) { 30 void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, uint16_t questData) {
@@ -31,6 +38,8 @@ void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, @@ -31,6 +38,8 @@ void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty,
31 d->quests[difficulty].actData[D2S_ACT4].questCheckpoints[quest - D2S_QUEST_FALLEN_ANGEL] = questData; 38 d->quests[difficulty].actData[D2S_ACT4].questCheckpoints[quest - D2S_QUEST_FALLEN_ANGEL] = questData;
32 } else if(quest >= D2S_QUEST_SIEGE_ON_HARROGATH && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) { 39 } else if(quest >= D2S_QUEST_SIEGE_ON_HARROGATH && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) {
33 d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH] = questData; 40 d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH] = questData;
  41 + } else {
  42 + fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);
34 } 43 }
35 } 44 }
36 45
@@ -98,6 +107,11 @@ int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsign @@ -98,6 +107,11 @@ int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsign
98 } 107 }
99 108
100 void setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty, int bool) { 109 void setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty, int bool) {
  110 + if(difficulty != D2S_DIFFICULTY_NORMAL ||
  111 + difficulty != D2S_DIFFICULTY_NIGHTMARE ||
  112 + difficulty != D2S_DIFFICULTY_HELL) {
  113 + fprintf(stderr,"libd2char error: difficulty %d doesn't exist\n",difficulty);
  114 + }
101 switch(specialQuestState) { 115 switch(specialQuestState) {
102 case D2S_SPECIALQUEST_AKARA_RESPEC: 116 case D2S_SPECIALQUEST_AKARA_RESPEC:
103 // This operation only makes sense if the quest is actually completed, otherwise ignore request 117 // This operation only makes sense if the quest is actually completed, otherwise ignore request
d2quest.h
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 #include "d2strings.h" 6 #include "d2strings.h"
7 7
8 #define D2S_QUESTDATA_HEADER_LENGTH 4 8 #define D2S_QUESTDATA_HEADER_LENGTH 4
  9 +#define D2S_QUESTDATA_NUMQUESTS 27
9 10
10 enum D2S_QUEST { 11 enum D2S_QUEST {
11 D2S_QUEST_UNKNOWN = -1, 12 D2S_QUEST_UNKNOWN = -1,
@@ -500,17 +501,22 @@ typedef struct __attribute__((packed)) { @@ -500,17 +501,22 @@ typedef struct __attribute__((packed)) {
500 typedef struct __attribute__((packed)) { 501 typedef struct __attribute__((packed)) {
501 D2ActData actData[4]; 502 D2ActData actData[4];
502 D2XActData expansionAct; 503 D2XActData expansionAct;
  504 + // My guess is that the following `uint16_t`s all represents some quest data that was added after
  505 + // the game was launched. This also explains why there's version data (supposedly) and length
  506 + // of the quest data in bytes in the header.
503 uint16_t akaraRespecData; // This uint16_t determines if the player has used Akara's respec or not 507 uint16_t akaraRespecData; // This uint16_t determines if the player has used Akara's respec or not
504 uint16_t unknown1[6]; 508 uint16_t unknown1[6];
505 } D2Quests; 509 } D2Quests;
506 510
507 typedef struct __attribute__((packed)) { 511 typedef struct __attribute__((packed)) {
508 - const char* header[D2S_QUESTDATA_HEADER_LENGTH];  
509 - uint32_t unknown1; 512 + const char* header[D2S_QUESTDATA_HEADER_LENGTH]; // Woo!
  513 + uint32_t unknown1; // This is likely version data
510 uint16_t size; // in bytes 514 uint16_t size; // in bytes
511 D2Quests quests[3]; // 1 set for each difficulty 515 D2Quests quests[3]; // 1 set for each difficulty
512 } D2QuestData; 516 } D2QuestData;
513 517
  518 +// TODO: These functions are completely unsafe, and don't return success
  519 +
514 // Populates `descriptions` with static strings from library memory, no need to free. 520 // Populates `descriptions` with static strings from library memory, no need to free.
515 // `descriptions` contains one string for each bit field of the quest's uint16_t data. 521 // `descriptions` contains one string for each bit field of the quest's uint16_t data.
516 // Empty entries (non-existant or unknown checkpoints) will have NULL value. Be careful! 522 // Empty entries (non-existant or unknown checkpoints) will have NULL value. Be careful!
@@ -527,9 +533,10 @@ int isQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty @@ -527,9 +533,10 @@ int isQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty
527 // Set bool to 1 to set the status or 0 to remove it 533 // Set bool to 1 to set the status or 0 to remove it
528 void setQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); 534 void setQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool);
529 void setQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); 535 void setQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool);
  536 +
530 // When called to set the request to NOT completed (`bool` = 0), this will NOT set the reward collected status 537 // When called to set the request to NOT completed (`bool` = 0), this will NOT set the reward collected status
531 // which *may* render the quest unobtainable, this is done in case we may want to further modify the quest state. 538 // which *may* render the quest unobtainable, this is done in case we may want to further modify the quest state.
532 -// If you want to mark the quest as not completed just to get the reward, please use `setQuestRewardCollected()` 539 +// If you want to mark the quest as not completed just to get the reward, please use `setQuestRewardCollected(,,0)`
533 // instead. 540 // instead.
534 void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); 541 void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool);
535 542
d2skills.h
@@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
5 5
6 #include "d2strings.h" 6 #include "d2strings.h"
7 7
  8 +#define D2S_SKILL_NUMSKILLS 357
  9 +
8 const char* const skills[] = { 10 const char* const skills[] = {
9 D2S_SKILL_0, 11 D2S_SKILL_0,
10 D2S_SKILL_1, 12 D2S_SKILL_1,
d2strings.h
@@ -1035,4 +1035,45 @@ const char* D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_HARDCORE = &quot;Guardian&quot;; @@ -1035,4 +1035,45 @@ const char* D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_HARDCORE = &quot;Guardian&quot;;
1035 #define D2S_QUEST_CHECKPOINT_430 NULL 1035 #define D2S_QUEST_CHECKPOINT_430 NULL
1036 #define D2S_QUEST_CHECKPOINT_431 NULL 1036 #define D2S_QUEST_CHECKPOINT_431 NULL
1037 1037
  1038 +// Waypoints
  1039 +#define D2S_WAYPOINT_0 "Rogue Encampment"
  1040 +#define D2S_WAYPOINT_1 "Cold Plains"
  1041 +#define D2S_WAYPOINT_2 "Stony Field"
  1042 +#define D2S_WAYPOINT_3 "Dark Wood"
  1043 +#define D2S_WAYPOINT_4 "Black Marsh"
  1044 +#define D2S_WAYPOINT_5 "Outer Cloister"
  1045 +#define D2S_WAYPOINT_6 "Jail Level 1"
  1046 +#define D2S_WAYPOINT_7 "Inner Cloister"
  1047 +#define D2S_WAYPOINT_8 "Catacombs Level 2"
  1048 +#define D2S_WAYPOINT_9 "Lut Gholein"
  1049 +#define D2S_WAYPOINT_10 "Sewers Level 2"
  1050 +#define D2S_WAYPOINT_11 "Dry Hills"
  1051 +#define D2S_WAYPOINT_12 "Halls of the Dead Level 2"
  1052 +#define D2S_WAYPOINT_13 "Far Oasis"
  1053 +#define D2S_WAYPOINT_14 "Lost City"
  1054 +#define D2S_WAYPOINT_15 "Palace Cellar Level 1"
  1055 +#define D2S_WAYPOINT_16 "Arcane Sanctuary"
  1056 +#define D2S_WAYPOINT_17 "Canyon of the Magi"
  1057 +#define D2S_WAYPOINT_18 "Kurast Docks"
  1058 +#define D2S_WAYPOINT_19 "Spider Forest"
  1059 +#define D2S_WAYPOINT_20 "Great Marsh"
  1060 +#define D2S_WAYPOINT_21 "Flayer Jungle"
  1061 +#define D2S_WAYPOINT_22 "Lower Kurast"
  1062 +#define D2S_WAYPOINT_23 "Kurast Bazaar"
  1063 +#define D2S_WAYPOINT_24 "Upper Kurast"
  1064 +#define D2S_WAYPOINT_25 "Travincal"
  1065 +#define D2S_WAYPOINT_26 "Durance of Hate Level 2"
  1066 +#define D2S_WAYPOINT_27 "Pandemonium Fortress"
  1067 +#define D2S_WAYPOINT_28 "City of the Damned"
  1068 +#define D2S_WAYPOINT_29 "River of Flames"
  1069 +#define D2S_WAYPOINT_30 "Harrogath"
  1070 +#define D2S_WAYPOINT_31 "Frigid Highlands"
  1071 +#define D2S_WAYPOINT_32 "Arreat Plateau"
  1072 +#define D2S_WAYPOINT_33 "Crystalline Passage"
  1073 +#define D2S_WAYPOINT_34 "Halls of Pain"
  1074 +#define D2S_WAYPOINT_35 "Glacial Trail"
  1075 +#define D2S_WAYPOINT_36 "Frozen Tundra"
  1076 +#define D2S_WAYPOINT_37 "The Ancient's Way"
  1077 +#define D2S_WAYPOINT_38 "Worldstone Keep Level 2"
  1078 +
1038 #endif 1079 #endif
1039 \ No newline at end of file 1080 \ No newline at end of file