diff --git a/d2char.h b/d2char.h index b253ed2..ad703a0 100644 --- a/d2char.h +++ b/d2char.h @@ -58,6 +58,7 @@ enum D2S_ACT { D2S_ACT5 }; +// TODO: Add file hex offsets for each field typedef struct __attribute__((packed)){ uint32_t signature; uint32_t versionID; @@ -74,7 +75,7 @@ typedef struct __attribute__((packed)){ uint32_t unknown3; // TODO uint32_t lastPlayed; uint32_t unknown4; // TODO - uint8_t hotkeys[D2S_HOTKEYS_LENGTH]; // Not implemented. (Yet) + 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 @@ -91,7 +92,7 @@ typedef struct __attribute__((packed)){ uint8_t unknown6[144]; // TODO D2QuestData questData; uint8_t waypointData[D2S_WAYPOINTS_LENGTH]; - uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // Not implemented. (Yet) + uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented } D2CharHeader; uint32_t calcChecksum(D2CharHeader* c, void* charData); diff --git a/d2quest.c b/d2quest.c index 383585f..5c47d7e 100644 --- a/d2quest.c +++ b/d2quest.c @@ -1,148 +1,86 @@ #include "d2char.h" #include "d2quest.h" -void getQuestData_DenOfEvil(D2QuestData* d, int difficulty, void* dest) { - uint16_t questData = d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[0]; - -} - -void getQuestData_SisterBurialGrounds(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_SearchForCain(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_ForgottenTower(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_ToolsOfTheTrade(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_SistersToTheSlaughter(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_RadamentLair(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_HoradricStaff(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_TaintedSun(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_ArcaneSanctuary(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_Summoner(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_SevenTombs(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_GoldenBird(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_BladeOfTheOldReligion(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_KhalimWill(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_LamEsenTome(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_BlackenedTemple(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_Guardian(D2QuestData* d, int difficulty, void* dest) { - +void getCheckpointDescriptions(unsigned int quest, const char* *descriptions[16]) { + memcpy(descriptions,(&checkpointDescriptions) + (quest * 16 * sizeof(const char*)), 16 * sizeof(const char*)); +} + +uint16_t getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty) { + if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_SISTERS_TO_THE_SLAUGHTER) { + return d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[quest]; + } else if(quest >= D2S_QUEST_RADAMENT_LAIR && quest <= D2S_QUEST_SEVEN_TOMBS) { + return d->quests[difficulty].actData[D2S_ACT2].questCheckpoints[quest - D2S_QUEST_RADAMENT_LAIR]; + } else if(quest >= D2S_QUEST_GOLDEN_BIRD && quest <= D2S_QUEST_GUARDIAN) { + return d->quests[difficulty].actData[D2S_ACT3].questCheckpoints[quest - D2S_QUEST_GOLDEN_BIRD]; + } else if(quest >= D2S_QUEST_FALLEN_ANGEL && quest <= D2S_QUEST_TERROR_END) { + return d->quests[difficulty].actData[D2S_ACT4].questCheckpoints[quest - D2S_QUEST_FALLEN_ANGEL]; + } else if(quest >= D2S_QUEST_SIEGE_ON_HARROGATH && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) { + return d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH]; + } + return D2S_QUEST_UNKNOWN; } -void getQuestData_FallenAngel(D2QuestData* d, int difficulty, void* dest) { - +int isQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty) { + // TODO + return 0; } -void getQuestData_Hellforge(D2QuestData* d, int difficulty, void* dest) { - +int isQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty) { + // TODO + return 0; } -void getQuestData_TerrorEnd(D2QuestData* d, int difficulty, void* dest) { - +int isQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty) { + // TODO + return 0; } -void getQuestData_SiegeOnHarrogath(D2QuestData* d, int difficulty, void* dest) { - -} +void setQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool) { + // To reset the quest, just zero out the whole thing + // To set as started, just set the 2nd bit and clear the rest -void getQuestData_RescueOnMountArreat(D2QuestData* d, int difficulty, void* dest) { - + // TODO } -void getQuestData_PrisonOfIce(D2QuestData* d, int difficulty, void* dest) { - -} - -void getQuestData_BetrayalOfHarrogath(D2QuestData* d, int difficulty, void* dest) { - -} +void setQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool) { + // To reset, just clear bit 0 and set bit 1. + // Do the inverse to set reward as collected (but why whould you tho???) -void getQuestData_RiteOfPassage(D2QuestData* d, int difficulty, void* dest) { - + // TODO } -void getQuestData_EveOfDestruction(D2QuestData* d, int difficulty, void* dest) { +void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool) { + // To reset, clear bit 0, bit 12 and bit 13 (13 is kinda optional since it will be cleared by + // the game when loading the savegame). + // To set as completed, just set bit 0 and bit 12 and clear bit 1 + // TODO } -void(*questFunc[])(D2QuestData*,int,void*) = { - &getQuestData_DenOfEvil, - &getQuestData_SisterBurialGrounds, - &getQuestData_SearchForCain, - &getQuestData_ForgottenTower, - &getQuestData_ToolsOfTheTrade, - &getQuestData_SistersToTheSlaughter, - &getQuestData_RadamentLair, - &getQuestData_HoradricStaff, - &getQuestData_TaintedSun, - &getQuestData_ArcaneSanctuary, - &getQuestData_Summoner, - &getQuestData_SevenTombs, - &getQuestData_GoldenBird, - &getQuestData_BladeOfTheOldReligion, - &getQuestData_KhalimWill, - &getQuestData_LamEsenTome, - &getQuestData_BlackenedTemple, - &getQuestData_Guardian, - &getQuestData_FallenAngel, - &getQuestData_Hellforge, - &getQuestData_TerrorEnd, - &getQuestData_SiegeOnHarrogath, - &getQuestData_RescueOnMountArreat, - &getQuestData_PrisonOfIce, - &getQuestData_BetrayalOfHarrogath, - &getQuestData_RiteOfPassage, - &getQuestData_EveOfDestruction -}; - -int getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, void* dest) { - if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) { - questFunc[quest](d,difficulty,dest); +int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty) { + int ret = 0; + switch(specialQuestState) { + case D2S_SPECIALQUEST_AKARA_RESPEC: + ret = d->quests[difficulty].akaraRespecData & D2S_QUEST_STATUS_REWARD_AVAILABLE; + break; + } + return ret; +} + +void setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty, int bool) { + switch(specialQuestState) { + case D2S_SPECIALQUEST_AKARA_RESPEC: + if(bool) { + // This operation only makes sense if the quest is actually completed, otherwise ignore request + if(isQuestCompleted(d,D2S_QUEST_DEN_OF_EVIL,difficulty)) { + d->quests[difficulty].akaraRespecData = 0x8001; + } + } else { + // See above comment + if(isQuestCompleted(d,D2S_QUEST_DEN_OF_EVIL,difficulty)) { + d->quests[difficulty].akaraRespecData = 0x2002; + } + } + break; } - return D2S_QUEST_UNKNOWN; } \ No newline at end of file diff --git a/d2quest.h b/d2quest.h index d48ba73..56c76da 100644 --- a/d2quest.h +++ b/d2quest.h @@ -3,6 +3,8 @@ #include +#include "d2strings.h" + #define D2S_QUESTDATA_HEADER_LENGTH 4 enum D2S_QUEST { @@ -36,113 +38,452 @@ enum D2S_QUEST { D2S_QUEST_EVE_OF_DESTRUCTION }; -typedef struct { - int enteredDen; -} D2S_QUEST_DEN_OF_EVIL_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_SISTER_BURIAL_GROUNDS_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_SEARCH_FOR_CAIN_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_FORGOTTEN_TOWER_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_TOOLS_OF_THE_TRADE_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_SISTERS_TO_THE_SLAUGHTER_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_RADAMENT_LAIR_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_HORADRIC_STAFF_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_TAINTED_SUN_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_ARCANE_SANCTUARY_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_SUMMONER_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_SEVEN_TOMBS_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_GOLDEN_BIRD_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_BLADE_OF_THE_OLD_RELIGION_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_KHALIM_WILL_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_LAM_ESEN_TOME_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_BLACKENED_TEMPLE_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_GUARDIAN_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_FALLEN_ANGEL_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_HELLFORGE_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_TERROR_END_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_SIEGE_ON_HARROGATH_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_RESCUE_ON_MOUNT_ARREAT_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_PRISON_OF_ICE_struct; - -typedef struct { - int enteredDen; -} D2S_QUEST_BETRAYAL_OF_HARROGATH_struct; +enum D2S_QUEST_STATUS { + D2S_QUEST_STATUS_COMPLETED = 0x0001, + D2S_QUEST_STATUS_REWARD_AVAILABLE = 0x0002, + D2S_QUEST_STATUS_STARTED = 0x0004, + D2S_QUEST_STATUS_SEEN_FINISH_ANIMATION = 0x1000, + D2S_QUEST_STATUS_JUST_FINISHED = 0x2000 +}; -typedef struct { - int enteredDen; -} D2S_QUEST_RITE_OF_PASSAGE_struct; +enum D2S_SPECIALQUEST { + D2S_SPECIALQUEST_AKARA_RESPEC +}; -typedef struct { - int enteredDen; -} D2S_QUEST_EVE_OF_DESTRUCTION_struct; +const char* const checkpointDescriptions[] = { + D2S_QUEST_CHECKPOINT_0, + D2S_QUEST_CHECKPOINT_1, + D2S_QUEST_CHECKPOINT_2, + D2S_QUEST_CHECKPOINT_3, + D2S_QUEST_CHECKPOINT_4, + D2S_QUEST_CHECKPOINT_5, + D2S_QUEST_CHECKPOINT_6, + D2S_QUEST_CHECKPOINT_7, + D2S_QUEST_CHECKPOINT_8, + D2S_QUEST_CHECKPOINT_9, + D2S_QUEST_CHECKPOINT_10, + D2S_QUEST_CHECKPOINT_11, + D2S_QUEST_CHECKPOINT_12, + D2S_QUEST_CHECKPOINT_13, + D2S_QUEST_CHECKPOINT_14, + D2S_QUEST_CHECKPOINT_15, + D2S_QUEST_CHECKPOINT_16, + D2S_QUEST_CHECKPOINT_17, + D2S_QUEST_CHECKPOINT_18, + D2S_QUEST_CHECKPOINT_19, + D2S_QUEST_CHECKPOINT_20, + D2S_QUEST_CHECKPOINT_21, + D2S_QUEST_CHECKPOINT_22, + D2S_QUEST_CHECKPOINT_23, + D2S_QUEST_CHECKPOINT_24, + D2S_QUEST_CHECKPOINT_25, + D2S_QUEST_CHECKPOINT_26, + D2S_QUEST_CHECKPOINT_27, + D2S_QUEST_CHECKPOINT_28, + D2S_QUEST_CHECKPOINT_29, + D2S_QUEST_CHECKPOINT_30, + D2S_QUEST_CHECKPOINT_31, + D2S_QUEST_CHECKPOINT_32, + D2S_QUEST_CHECKPOINT_33, + D2S_QUEST_CHECKPOINT_34, + D2S_QUEST_CHECKPOINT_35, + D2S_QUEST_CHECKPOINT_36, + D2S_QUEST_CHECKPOINT_37, + D2S_QUEST_CHECKPOINT_38, + D2S_QUEST_CHECKPOINT_39, + D2S_QUEST_CHECKPOINT_40, + D2S_QUEST_CHECKPOINT_41, + D2S_QUEST_CHECKPOINT_42, + D2S_QUEST_CHECKPOINT_43, + D2S_QUEST_CHECKPOINT_44, + D2S_QUEST_CHECKPOINT_45, + D2S_QUEST_CHECKPOINT_46, + D2S_QUEST_CHECKPOINT_47, + D2S_QUEST_CHECKPOINT_48, + D2S_QUEST_CHECKPOINT_49, + D2S_QUEST_CHECKPOINT_50, + D2S_QUEST_CHECKPOINT_51, + D2S_QUEST_CHECKPOINT_52, + D2S_QUEST_CHECKPOINT_53, + D2S_QUEST_CHECKPOINT_54, + D2S_QUEST_CHECKPOINT_55, + D2S_QUEST_CHECKPOINT_56, + D2S_QUEST_CHECKPOINT_57, + D2S_QUEST_CHECKPOINT_58, + D2S_QUEST_CHECKPOINT_59, + D2S_QUEST_CHECKPOINT_60, + D2S_QUEST_CHECKPOINT_61, + D2S_QUEST_CHECKPOINT_62, + D2S_QUEST_CHECKPOINT_63, + D2S_QUEST_CHECKPOINT_64, + D2S_QUEST_CHECKPOINT_65, + D2S_QUEST_CHECKPOINT_66, + D2S_QUEST_CHECKPOINT_67, + D2S_QUEST_CHECKPOINT_68, + D2S_QUEST_CHECKPOINT_69, + D2S_QUEST_CHECKPOINT_70, + D2S_QUEST_CHECKPOINT_71, + D2S_QUEST_CHECKPOINT_72, + D2S_QUEST_CHECKPOINT_73, + D2S_QUEST_CHECKPOINT_74, + D2S_QUEST_CHECKPOINT_75, + D2S_QUEST_CHECKPOINT_76, + D2S_QUEST_CHECKPOINT_77, + D2S_QUEST_CHECKPOINT_78, + D2S_QUEST_CHECKPOINT_79, + D2S_QUEST_CHECKPOINT_80, + D2S_QUEST_CHECKPOINT_81, + D2S_QUEST_CHECKPOINT_82, + D2S_QUEST_CHECKPOINT_83, + D2S_QUEST_CHECKPOINT_84, + D2S_QUEST_CHECKPOINT_85, + D2S_QUEST_CHECKPOINT_86, + D2S_QUEST_CHECKPOINT_87, + D2S_QUEST_CHECKPOINT_88, + D2S_QUEST_CHECKPOINT_89, + D2S_QUEST_CHECKPOINT_90, + D2S_QUEST_CHECKPOINT_91, + D2S_QUEST_CHECKPOINT_92, + D2S_QUEST_CHECKPOINT_93, + D2S_QUEST_CHECKPOINT_94, + D2S_QUEST_CHECKPOINT_95, + D2S_QUEST_CHECKPOINT_96, + D2S_QUEST_CHECKPOINT_97, + D2S_QUEST_CHECKPOINT_98, + D2S_QUEST_CHECKPOINT_99, + D2S_QUEST_CHECKPOINT_100, + D2S_QUEST_CHECKPOINT_101, + D2S_QUEST_CHECKPOINT_102, + D2S_QUEST_CHECKPOINT_103, + D2S_QUEST_CHECKPOINT_104, + D2S_QUEST_CHECKPOINT_105, + D2S_QUEST_CHECKPOINT_106, + D2S_QUEST_CHECKPOINT_107, + D2S_QUEST_CHECKPOINT_108, + D2S_QUEST_CHECKPOINT_109, + D2S_QUEST_CHECKPOINT_110, + D2S_QUEST_CHECKPOINT_111, + D2S_QUEST_CHECKPOINT_112, + D2S_QUEST_CHECKPOINT_113, + D2S_QUEST_CHECKPOINT_114, + D2S_QUEST_CHECKPOINT_115, + D2S_QUEST_CHECKPOINT_116, + D2S_QUEST_CHECKPOINT_117, + D2S_QUEST_CHECKPOINT_118, + D2S_QUEST_CHECKPOINT_119, + D2S_QUEST_CHECKPOINT_120, + D2S_QUEST_CHECKPOINT_121, + D2S_QUEST_CHECKPOINT_122, + D2S_QUEST_CHECKPOINT_123, + D2S_QUEST_CHECKPOINT_124, + D2S_QUEST_CHECKPOINT_125, + D2S_QUEST_CHECKPOINT_126, + D2S_QUEST_CHECKPOINT_127, + D2S_QUEST_CHECKPOINT_128, + D2S_QUEST_CHECKPOINT_129, + D2S_QUEST_CHECKPOINT_130, + D2S_QUEST_CHECKPOINT_131, + D2S_QUEST_CHECKPOINT_132, + D2S_QUEST_CHECKPOINT_133, + D2S_QUEST_CHECKPOINT_134, + D2S_QUEST_CHECKPOINT_135, + D2S_QUEST_CHECKPOINT_136, + D2S_QUEST_CHECKPOINT_137, + D2S_QUEST_CHECKPOINT_138, + D2S_QUEST_CHECKPOINT_139, + D2S_QUEST_CHECKPOINT_140, + D2S_QUEST_CHECKPOINT_141, + D2S_QUEST_CHECKPOINT_142, + D2S_QUEST_CHECKPOINT_143, + D2S_QUEST_CHECKPOINT_144, + D2S_QUEST_CHECKPOINT_145, + D2S_QUEST_CHECKPOINT_146, + D2S_QUEST_CHECKPOINT_147, + D2S_QUEST_CHECKPOINT_148, + D2S_QUEST_CHECKPOINT_149, + D2S_QUEST_CHECKPOINT_150, + D2S_QUEST_CHECKPOINT_151, + D2S_QUEST_CHECKPOINT_152, + D2S_QUEST_CHECKPOINT_153, + D2S_QUEST_CHECKPOINT_154, + D2S_QUEST_CHECKPOINT_155, + D2S_QUEST_CHECKPOINT_156, + D2S_QUEST_CHECKPOINT_157, + D2S_QUEST_CHECKPOINT_158, + D2S_QUEST_CHECKPOINT_159, + D2S_QUEST_CHECKPOINT_160, + D2S_QUEST_CHECKPOINT_161, + D2S_QUEST_CHECKPOINT_162, + D2S_QUEST_CHECKPOINT_163, + D2S_QUEST_CHECKPOINT_164, + D2S_QUEST_CHECKPOINT_165, + D2S_QUEST_CHECKPOINT_166, + D2S_QUEST_CHECKPOINT_167, + D2S_QUEST_CHECKPOINT_168, + D2S_QUEST_CHECKPOINT_169, + D2S_QUEST_CHECKPOINT_170, + D2S_QUEST_CHECKPOINT_171, + D2S_QUEST_CHECKPOINT_172, + D2S_QUEST_CHECKPOINT_173, + D2S_QUEST_CHECKPOINT_174, + D2S_QUEST_CHECKPOINT_175, + D2S_QUEST_CHECKPOINT_176, + D2S_QUEST_CHECKPOINT_177, + D2S_QUEST_CHECKPOINT_178, + D2S_QUEST_CHECKPOINT_179, + D2S_QUEST_CHECKPOINT_180, + D2S_QUEST_CHECKPOINT_181, + D2S_QUEST_CHECKPOINT_182, + D2S_QUEST_CHECKPOINT_183, + D2S_QUEST_CHECKPOINT_184, + D2S_QUEST_CHECKPOINT_185, + D2S_QUEST_CHECKPOINT_186, + D2S_QUEST_CHECKPOINT_187, + D2S_QUEST_CHECKPOINT_188, + D2S_QUEST_CHECKPOINT_189, + D2S_QUEST_CHECKPOINT_190, + D2S_QUEST_CHECKPOINT_191, + D2S_QUEST_CHECKPOINT_192, + D2S_QUEST_CHECKPOINT_193, + D2S_QUEST_CHECKPOINT_194, + D2S_QUEST_CHECKPOINT_195, + D2S_QUEST_CHECKPOINT_196, + D2S_QUEST_CHECKPOINT_197, + D2S_QUEST_CHECKPOINT_198, + D2S_QUEST_CHECKPOINT_199, + D2S_QUEST_CHECKPOINT_200, + D2S_QUEST_CHECKPOINT_201, + D2S_QUEST_CHECKPOINT_202, + D2S_QUEST_CHECKPOINT_203, + D2S_QUEST_CHECKPOINT_204, + D2S_QUEST_CHECKPOINT_205, + D2S_QUEST_CHECKPOINT_206, + D2S_QUEST_CHECKPOINT_207, + D2S_QUEST_CHECKPOINT_208, + D2S_QUEST_CHECKPOINT_209, + D2S_QUEST_CHECKPOINT_210, + D2S_QUEST_CHECKPOINT_211, + D2S_QUEST_CHECKPOINT_212, + D2S_QUEST_CHECKPOINT_213, + D2S_QUEST_CHECKPOINT_214, + D2S_QUEST_CHECKPOINT_215, + D2S_QUEST_CHECKPOINT_216, + D2S_QUEST_CHECKPOINT_217, + D2S_QUEST_CHECKPOINT_218, + D2S_QUEST_CHECKPOINT_219, + D2S_QUEST_CHECKPOINT_220, + D2S_QUEST_CHECKPOINT_221, + D2S_QUEST_CHECKPOINT_222, + D2S_QUEST_CHECKPOINT_223, + D2S_QUEST_CHECKPOINT_224, + D2S_QUEST_CHECKPOINT_225, + D2S_QUEST_CHECKPOINT_226, + D2S_QUEST_CHECKPOINT_227, + D2S_QUEST_CHECKPOINT_228, + D2S_QUEST_CHECKPOINT_229, + D2S_QUEST_CHECKPOINT_230, + D2S_QUEST_CHECKPOINT_231, + D2S_QUEST_CHECKPOINT_232, + D2S_QUEST_CHECKPOINT_233, + D2S_QUEST_CHECKPOINT_234, + D2S_QUEST_CHECKPOINT_235, + D2S_QUEST_CHECKPOINT_236, + D2S_QUEST_CHECKPOINT_237, + D2S_QUEST_CHECKPOINT_238, + D2S_QUEST_CHECKPOINT_239, + D2S_QUEST_CHECKPOINT_240, + D2S_QUEST_CHECKPOINT_241, + D2S_QUEST_CHECKPOINT_242, + D2S_QUEST_CHECKPOINT_243, + D2S_QUEST_CHECKPOINT_244, + D2S_QUEST_CHECKPOINT_245, + D2S_QUEST_CHECKPOINT_246, + D2S_QUEST_CHECKPOINT_247, + D2S_QUEST_CHECKPOINT_248, + D2S_QUEST_CHECKPOINT_249, + D2S_QUEST_CHECKPOINT_250, + D2S_QUEST_CHECKPOINT_251, + D2S_QUEST_CHECKPOINT_252, + D2S_QUEST_CHECKPOINT_253, + D2S_QUEST_CHECKPOINT_254, + D2S_QUEST_CHECKPOINT_255, + D2S_QUEST_CHECKPOINT_256, + D2S_QUEST_CHECKPOINT_257, + D2S_QUEST_CHECKPOINT_258, + D2S_QUEST_CHECKPOINT_259, + D2S_QUEST_CHECKPOINT_260, + D2S_QUEST_CHECKPOINT_261, + D2S_QUEST_CHECKPOINT_262, + D2S_QUEST_CHECKPOINT_263, + D2S_QUEST_CHECKPOINT_264, + D2S_QUEST_CHECKPOINT_265, + D2S_QUEST_CHECKPOINT_266, + D2S_QUEST_CHECKPOINT_267, + D2S_QUEST_CHECKPOINT_268, + D2S_QUEST_CHECKPOINT_269, + D2S_QUEST_CHECKPOINT_270, + D2S_QUEST_CHECKPOINT_271, + D2S_QUEST_CHECKPOINT_272, + D2S_QUEST_CHECKPOINT_273, + D2S_QUEST_CHECKPOINT_274, + D2S_QUEST_CHECKPOINT_275, + D2S_QUEST_CHECKPOINT_276, + D2S_QUEST_CHECKPOINT_277, + D2S_QUEST_CHECKPOINT_278, + D2S_QUEST_CHECKPOINT_279, + D2S_QUEST_CHECKPOINT_280, + D2S_QUEST_CHECKPOINT_281, + D2S_QUEST_CHECKPOINT_282, + D2S_QUEST_CHECKPOINT_283, + D2S_QUEST_CHECKPOINT_284, + D2S_QUEST_CHECKPOINT_285, + D2S_QUEST_CHECKPOINT_286, + D2S_QUEST_CHECKPOINT_287, + D2S_QUEST_CHECKPOINT_288, + D2S_QUEST_CHECKPOINT_289, + D2S_QUEST_CHECKPOINT_290, + D2S_QUEST_CHECKPOINT_291, + D2S_QUEST_CHECKPOINT_292, + D2S_QUEST_CHECKPOINT_293, + D2S_QUEST_CHECKPOINT_294, + D2S_QUEST_CHECKPOINT_295, + D2S_QUEST_CHECKPOINT_296, + D2S_QUEST_CHECKPOINT_297, + D2S_QUEST_CHECKPOINT_298, + D2S_QUEST_CHECKPOINT_299, + D2S_QUEST_CHECKPOINT_300, + D2S_QUEST_CHECKPOINT_301, + D2S_QUEST_CHECKPOINT_302, + D2S_QUEST_CHECKPOINT_303, + D2S_QUEST_CHECKPOINT_304, + D2S_QUEST_CHECKPOINT_305, + D2S_QUEST_CHECKPOINT_306, + D2S_QUEST_CHECKPOINT_307, + D2S_QUEST_CHECKPOINT_308, + D2S_QUEST_CHECKPOINT_309, + D2S_QUEST_CHECKPOINT_310, + D2S_QUEST_CHECKPOINT_311, + D2S_QUEST_CHECKPOINT_312, + D2S_QUEST_CHECKPOINT_313, + D2S_QUEST_CHECKPOINT_314, + D2S_QUEST_CHECKPOINT_315, + D2S_QUEST_CHECKPOINT_316, + D2S_QUEST_CHECKPOINT_317, + D2S_QUEST_CHECKPOINT_318, + D2S_QUEST_CHECKPOINT_319, + D2S_QUEST_CHECKPOINT_320, + D2S_QUEST_CHECKPOINT_321, + D2S_QUEST_CHECKPOINT_322, + D2S_QUEST_CHECKPOINT_323, + D2S_QUEST_CHECKPOINT_324, + D2S_QUEST_CHECKPOINT_325, + D2S_QUEST_CHECKPOINT_326, + D2S_QUEST_CHECKPOINT_327, + D2S_QUEST_CHECKPOINT_328, + D2S_QUEST_CHECKPOINT_329, + D2S_QUEST_CHECKPOINT_330, + D2S_QUEST_CHECKPOINT_331, + D2S_QUEST_CHECKPOINT_332, + D2S_QUEST_CHECKPOINT_333, + D2S_QUEST_CHECKPOINT_334, + D2S_QUEST_CHECKPOINT_335, + D2S_QUEST_CHECKPOINT_336, + D2S_QUEST_CHECKPOINT_337, + D2S_QUEST_CHECKPOINT_338, + D2S_QUEST_CHECKPOINT_339, + D2S_QUEST_CHECKPOINT_340, + D2S_QUEST_CHECKPOINT_341, + D2S_QUEST_CHECKPOINT_342, + D2S_QUEST_CHECKPOINT_343, + D2S_QUEST_CHECKPOINT_344, + D2S_QUEST_CHECKPOINT_345, + D2S_QUEST_CHECKPOINT_346, + D2S_QUEST_CHECKPOINT_347, + D2S_QUEST_CHECKPOINT_348, + D2S_QUEST_CHECKPOINT_349, + D2S_QUEST_CHECKPOINT_350, + D2S_QUEST_CHECKPOINT_351, + D2S_QUEST_CHECKPOINT_352, + D2S_QUEST_CHECKPOINT_353, + D2S_QUEST_CHECKPOINT_354, + D2S_QUEST_CHECKPOINT_355, + D2S_QUEST_CHECKPOINT_356, + D2S_QUEST_CHECKPOINT_357, + D2S_QUEST_CHECKPOINT_358, + D2S_QUEST_CHECKPOINT_359, + D2S_QUEST_CHECKPOINT_360, + D2S_QUEST_CHECKPOINT_361, + D2S_QUEST_CHECKPOINT_362, + D2S_QUEST_CHECKPOINT_363, + D2S_QUEST_CHECKPOINT_364, + D2S_QUEST_CHECKPOINT_365, + D2S_QUEST_CHECKPOINT_366, + D2S_QUEST_CHECKPOINT_367, + D2S_QUEST_CHECKPOINT_368, + D2S_QUEST_CHECKPOINT_369, + D2S_QUEST_CHECKPOINT_370, + D2S_QUEST_CHECKPOINT_371, + D2S_QUEST_CHECKPOINT_372, + D2S_QUEST_CHECKPOINT_373, + D2S_QUEST_CHECKPOINT_374, + D2S_QUEST_CHECKPOINT_375, + D2S_QUEST_CHECKPOINT_376, + D2S_QUEST_CHECKPOINT_377, + D2S_QUEST_CHECKPOINT_378, + D2S_QUEST_CHECKPOINT_379, + D2S_QUEST_CHECKPOINT_380, + D2S_QUEST_CHECKPOINT_381, + D2S_QUEST_CHECKPOINT_382, + D2S_QUEST_CHECKPOINT_383, + D2S_QUEST_CHECKPOINT_384, + D2S_QUEST_CHECKPOINT_385, + D2S_QUEST_CHECKPOINT_386, + D2S_QUEST_CHECKPOINT_387, + D2S_QUEST_CHECKPOINT_388, + D2S_QUEST_CHECKPOINT_389, + D2S_QUEST_CHECKPOINT_390, + D2S_QUEST_CHECKPOINT_391, + D2S_QUEST_CHECKPOINT_392, + D2S_QUEST_CHECKPOINT_393, + D2S_QUEST_CHECKPOINT_394, + D2S_QUEST_CHECKPOINT_395, + D2S_QUEST_CHECKPOINT_396, + D2S_QUEST_CHECKPOINT_397, + D2S_QUEST_CHECKPOINT_398, + D2S_QUEST_CHECKPOINT_399, + D2S_QUEST_CHECKPOINT_400, + D2S_QUEST_CHECKPOINT_401, + D2S_QUEST_CHECKPOINT_402, + D2S_QUEST_CHECKPOINT_403, + D2S_QUEST_CHECKPOINT_404, + D2S_QUEST_CHECKPOINT_405, + D2S_QUEST_CHECKPOINT_406, + D2S_QUEST_CHECKPOINT_407, + D2S_QUEST_CHECKPOINT_408, + D2S_QUEST_CHECKPOINT_409, + D2S_QUEST_CHECKPOINT_410, + D2S_QUEST_CHECKPOINT_411, + D2S_QUEST_CHECKPOINT_412, + D2S_QUEST_CHECKPOINT_413, + D2S_QUEST_CHECKPOINT_414, + D2S_QUEST_CHECKPOINT_415, + D2S_QUEST_CHECKPOINT_416, + D2S_QUEST_CHECKPOINT_417, + D2S_QUEST_CHECKPOINT_418, + D2S_QUEST_CHECKPOINT_419, + D2S_QUEST_CHECKPOINT_420, + D2S_QUEST_CHECKPOINT_421, + D2S_QUEST_CHECKPOINT_422, + D2S_QUEST_CHECKPOINT_423, + D2S_QUEST_CHECKPOINT_424, + D2S_QUEST_CHECKPOINT_425, + D2S_QUEST_CHECKPOINT_426, + D2S_QUEST_CHECKPOINT_427, + D2S_QUEST_CHECKPOINT_428, + D2S_QUEST_CHECKPOINT_429, + D2S_QUEST_CHECKPOINT_430, + D2S_QUEST_CHECKPOINT_431 +}; typedef struct __attribute__((packed)) { uint16_t actStarted; @@ -154,12 +495,13 @@ typedef struct __attribute__((packed)) { uint16_t actStarted; uint16_t unknown1[2]; uint16_t questCheckpoints[6]; - uint16_t unknown2[7]; } D2XActData; typedef struct __attribute__((packed)) { D2ActData actData[4]; D2XActData expansionAct; + uint16_t akaraRespecData; // This uint16_t determines if the player has used Akara's respec or not + uint16_t unknown1[6]; } D2Quests; typedef struct __attribute__((packed)) { @@ -169,8 +511,26 @@ typedef struct __attribute__((packed)) { D2Quests quests[3]; // 1 set for each difficulty } D2QuestData; -// Returns quest status for the specified quest and act. dest must be a struct of the specified -// quest. Passing anything else may cause the program to crash if it doesn't fit into memory :) -int getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, void* dest); +// Populates `descriptions` with static strings from library memory, no need to free. +// `descriptions` contains one string for each bit field of the quest's uint16_t data. +// Empty entries (non-existant or unknown checkpoints) will have NULL value. Be careful! +void getCheckpointDescriptions(unsigned int quest, const char* *descriptions[16]); + +// Returns quest status for the specified quest and act. +uint16_t getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty); + +int isQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty); +int isQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty); +int isQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty); + +// Set bool to 1 to set the status or 0 to remove it +void setQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); +void setQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); +void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); + +// Some quests have extra fields outside their quest data that govern certain states of the quest +// So far, I only know of the respec that Akara offers when clearing Den of Evil +int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty); +void setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty, int bool); #endif \ No newline at end of file diff --git a/d2strings.h b/d2strings.h index f59ffe0..05cb654 100644 --- a/d2strings.h +++ b/d2strings.h @@ -565,4 +565,474 @@ const char* D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_HARDCORE = "Guardian"; #define D2S_MERC_ID_28 "Barbarian [Hell]" #define D2S_MERC_ID_29 "Barbarian [Hell]" +// Quest checkpoints +// Note: Some quests don't have many checkpoints, but unfortunately lots of checkpoints are +// missing here. Documentation is pretty much scarce and I'm afraid we won't be able to find +// much unless we go through the arduous process of saving and exit for each step/combination +// of steps for each quest and check which bits got modified and why. The existing values have +// been determined by existing sources online and _other methods_ ;) +// Den of Evil +#define D2S_QUEST_CHECKPOINT_0 NULL +#define D2S_QUEST_CHECKPOINT_1 NULL +#define D2S_QUEST_CHECKPOINT_2 NULL +#define D2S_QUEST_CHECKPOINT_3 NULL +#define D2S_QUEST_CHECKPOINT_4 "Entered the Den of Evil" +#define D2S_QUEST_CHECKPOINT_5 NULL +#define D2S_QUEST_CHECKPOINT_6 NULL +#define D2S_QUEST_CHECKPOINT_7 NULL +#define D2S_QUEST_CHECKPOINT_8 NULL +#define D2S_QUEST_CHECKPOINT_9 NULL +#define D2S_QUEST_CHECKPOINT_10 NULL +#define D2S_QUEST_CHECKPOINT_11 NULL +#define D2S_QUEST_CHECKPOINT_12 NULL +#define D2S_QUEST_CHECKPOINT_13 NULL +#define D2S_QUEST_CHECKPOINT_14 NULL +#define D2S_QUEST_CHECKPOINT_15 NULL +// Sister's Burial Grounds +#define D2S_QUEST_CHECKPOINT_16 NULL +#define D2S_QUEST_CHECKPOINT_17 NULL +#define D2S_QUEST_CHECKPOINT_18 NULL +#define D2S_QUEST_CHECKPOINT_19 NULL +#define D2S_QUEST_CHECKPOINT_20 "Entered the Burial Grounds" +#define D2S_QUEST_CHECKPOINT_21 NULL +#define D2S_QUEST_CHECKPOINT_22 NULL +#define D2S_QUEST_CHECKPOINT_23 NULL +#define D2S_QUEST_CHECKPOINT_24 NULL +#define D2S_QUEST_CHECKPOINT_25 NULL +#define D2S_QUEST_CHECKPOINT_26 NULL +#define D2S_QUEST_CHECKPOINT_27 NULL +#define D2S_QUEST_CHECKPOINT_28 NULL +#define D2S_QUEST_CHECKPOINT_29 NULL +#define D2S_QUEST_CHECKPOINT_30 NULL +#define D2S_QUEST_CHECKPOINT_31 NULL +// Tools of the Trade +#define D2S_QUEST_CHECKPOINT_32 NULL +#define D2S_QUEST_CHECKPOINT_33 NULL +#define D2S_QUEST_CHECKPOINT_34 NULL +#define D2S_QUEST_CHECKPOINT_35 NULL +#define D2S_QUEST_CHECKPOINT_36 NULL +#define D2S_QUEST_CHECKPOINT_37 NULL +#define D2S_QUEST_CHECKPOINT_38 "Picked the Horadric Malus" +#define D2S_QUEST_CHECKPOINT_39 NULL +#define D2S_QUEST_CHECKPOINT_40 NULL +#define D2S_QUEST_CHECKPOINT_41 NULL +#define D2S_QUEST_CHECKPOINT_42 NULL +#define D2S_QUEST_CHECKPOINT_43 NULL +#define D2S_QUEST_CHECKPOINT_44 NULL +#define D2S_QUEST_CHECKPOINT_45 NULL +#define D2S_QUEST_CHECKPOINT_46 NULL +#define D2S_QUEST_CHECKPOINT_47 NULL +// The Search for Cain +#define D2S_QUEST_CHECKPOINT_48 NULL +#define D2S_QUEST_CHECKPOINT_49 NULL +#define D2S_QUEST_CHECKPOINT_50 NULL +#define D2S_QUEST_CHECKPOINT_51 NULL +#define D2S_QUEST_CHECKPOINT_52 "Entered Tristram" +#define D2S_QUEST_CHECKPOINT_53 NULL +#define D2S_QUEST_CHECKPOINT_54 NULL +#define D2S_QUEST_CHECKPOINT_55 NULL +#define D2S_QUEST_CHECKPOINT_56 NULL +#define D2S_QUEST_CHECKPOINT_57 NULL +#define D2S_QUEST_CHECKPOINT_58 "Completed the Secret Cow Level" // Moo! +#define D2S_QUEST_CHECKPOINT_59 NULL +#define D2S_QUEST_CHECKPOINT_60 NULL +#define D2S_QUEST_CHECKPOINT_61 NULL +#define D2S_QUEST_CHECKPOINT_62 "The Rogues rescued Deckard Cain" +#define D2S_QUEST_CHECKPOINT_63 NULL +// The Forgotten Tower +#define D2S_QUEST_CHECKPOINT_64 NULL +#define D2S_QUEST_CHECKPOINT_65 NULL +#define D2S_QUEST_CHECKPOINT_66 "Read the Moldy Tome" +#define D2S_QUEST_CHECKPOINT_67 NULL +#define D2S_QUEST_CHECKPOINT_68 NULL +#define D2S_QUEST_CHECKPOINT_69 NULL +#define D2S_QUEST_CHECKPOINT_70 "Entered the Forgotten Tower" +#define D2S_QUEST_CHECKPOINT_71 NULL +#define D2S_QUEST_CHECKPOINT_72 NULL +#define D2S_QUEST_CHECKPOINT_73 NULL +#define D2S_QUEST_CHECKPOINT_74 NULL +#define D2S_QUEST_CHECKPOINT_75 NULL +#define D2S_QUEST_CHECKPOINT_76 NULL +#define D2S_QUEST_CHECKPOINT_77 NULL +#define D2S_QUEST_CHECKPOINT_78 NULL +#define D2S_QUEST_CHECKPOINT_79 NULL +// Sisters to the Slaughter +#define D2S_QUEST_CHECKPOINT_80 NULL +#define D2S_QUEST_CHECKPOINT_81 NULL +#define D2S_QUEST_CHECKPOINT_82 NULL +#define D2S_QUEST_CHECKPOINT_83 NULL +#define D2S_QUEST_CHECKPOINT_84 NULL +#define D2S_QUEST_CHECKPOINT_85 NULL +#define D2S_QUEST_CHECKPOINT_86 NULL +#define D2S_QUEST_CHECKPOINT_87 NULL +#define D2S_QUEST_CHECKPOINT_88 NULL +#define D2S_QUEST_CHECKPOINT_89 NULL +#define D2S_QUEST_CHECKPOINT_90 NULL +#define D2S_QUEST_CHECKPOINT_91 NULL +#define D2S_QUEST_CHECKPOINT_92 NULL +#define D2S_QUEST_CHECKPOINT_93 NULL +#define D2S_QUEST_CHECKPOINT_94 NULL +#define D2S_QUEST_CHECKPOINT_95 NULL +// Radament's Lair +#define D2S_QUEST_CHECKPOINT_96 NULL +#define D2S_QUEST_CHECKPOINT_97 NULL +#define D2S_QUEST_CHECKPOINT_98 NULL +#define D2S_QUEST_CHECKPOINT_99 NULL +#define D2S_QUEST_CHECKPOINT_100 "Found Radament" +#define D2S_QUEST_CHECKPOINT_101 NULL +#define D2S_QUEST_CHECKPOINT_102 NULL +#define D2S_QUEST_CHECKPOINT_103 NULL +#define D2S_QUEST_CHECKPOINT_104 NULL +#define D2S_QUEST_CHECKPOINT_105 NULL +#define D2S_QUEST_CHECKPOINT_106 NULL +#define D2S_QUEST_CHECKPOINT_107 NULL +#define D2S_QUEST_CHECKPOINT_108 NULL +#define D2S_QUEST_CHECKPOINT_109 NULL +#define D2S_QUEST_CHECKPOINT_110 NULL +#define D2S_QUEST_CHECKPOINT_111 NULL +// The Horadric Staff +#define D2S_QUEST_CHECKPOINT_112 NULL +#define D2S_QUEST_CHECKPOINT_113 NULL +#define D2S_QUEST_CHECKPOINT_114 NULL +#define D2S_QUEST_CHECKPOINT_115 NULL +#define D2S_QUEST_CHECKPOINT_116 "Spoke to Cain about the Viper Amulet" +#define D2S_QUEST_CHECKPOINT_117 "Spoke to Cain about the Staff of Kings" +#define D2S_QUEST_CHECKPOINT_118 NULL +#define D2S_QUEST_CHECKPOINT_119 NULL +#define D2S_QUEST_CHECKPOINT_120 NULL +#define D2S_QUEST_CHECKPOINT_121 NULL +#define D2S_QUEST_CHECKPOINT_122 "Spoke to Cain about the Horadric Staff" +#define D2S_QUEST_CHECKPOINT_123 "You crafted the Horadric Staff" +#define D2S_QUEST_CHECKPOINT_124 NULL +#define D2S_QUEST_CHECKPOINT_125 NULL +#define D2S_QUEST_CHECKPOINT_126 NULL +#define D2S_QUEST_CHECKPOINT_127 NULL +// Tainted Sun +#define D2S_QUEST_CHECKPOINT_128 NULL +#define D2S_QUEST_CHECKPOINT_129 NULL +#define D2S_QUEST_CHECKPOINT_130 "The sun is eclipsed" +#define D2S_QUEST_CHECKPOINT_131 "Spoke to Drognan about the eclipse" +#define D2S_QUEST_CHECKPOINT_132 NULL +#define D2S_QUEST_CHECKPOINT_133 NULL +#define D2S_QUEST_CHECKPOINT_134 NULL +#define D2S_QUEST_CHECKPOINT_135 NULL +#define D2S_QUEST_CHECKPOINT_136 NULL +#define D2S_QUEST_CHECKPOINT_137 NULL +#define D2S_QUEST_CHECKPOINT_138 NULL +#define D2S_QUEST_CHECKPOINT_139 NULL +#define D2S_QUEST_CHECKPOINT_140 NULL +#define D2S_QUEST_CHECKPOINT_141 NULL +#define D2S_QUEST_CHECKPOINT_142 NULL +#define D2S_QUEST_CHECKPOINT_143 NULL +// Arcane Sanctuary +#define D2S_QUEST_CHECKPOINT_144 NULL +#define D2S_QUEST_CHECKPOINT_145 NULL +#define D2S_QUEST_CHECKPOINT_146 NULL +#define D2S_QUEST_CHECKPOINT_147 NULL +#define D2S_QUEST_CHECKPOINT_148 NULL +#define D2S_QUEST_CHECKPOINT_149 NULL +#define D2S_QUEST_CHECKPOINT_150 NULL +#define D2S_QUEST_CHECKPOINT_151 NULL +#define D2S_QUEST_CHECKPOINT_152 NULL +#define D2S_QUEST_CHECKPOINT_153 NULL +#define D2S_QUEST_CHECKPOINT_154 NULL +#define D2S_QUEST_CHECKPOINT_155 NULL +#define D2S_QUEST_CHECKPOINT_156 NULL +#define D2S_QUEST_CHECKPOINT_157 NULL +#define D2S_QUEST_CHECKPOINT_158 NULL +#define D2S_QUEST_CHECKPOINT_159 NULL +// The Summoner +#define D2S_QUEST_CHECKPOINT_160 NULL +#define D2S_QUEST_CHECKPOINT_161 NULL +#define D2S_QUEST_CHECKPOINT_162 NULL +#define D2S_QUEST_CHECKPOINT_163 NULL +#define D2S_QUEST_CHECKPOINT_164 NULL +#define D2S_QUEST_CHECKPOINT_165 NULL +#define D2S_QUEST_CHECKPOINT_166 NULL +#define D2S_QUEST_CHECKPOINT_167 NULL +#define D2S_QUEST_CHECKPOINT_168 NULL +#define D2S_QUEST_CHECKPOINT_169 NULL +#define D2S_QUEST_CHECKPOINT_170 NULL +#define D2S_QUEST_CHECKPOINT_171 NULL +#define D2S_QUEST_CHECKPOINT_172 NULL +#define D2S_QUEST_CHECKPOINT_173 NULL +#define D2S_QUEST_CHECKPOINT_174 NULL +#define D2S_QUEST_CHECKPOINT_175 NULL +// The Seven Tombs +#define D2S_QUEST_CHECKPOINT_176 NULL +#define D2S_QUEST_CHECKPOINT_177 NULL +#define D2S_QUEST_CHECKPOINT_178 NULL +#define D2S_QUEST_CHECKPOINT_179 "Spoke to Tyrael" +#define D2S_QUEST_CHECKPOINT_180 "Spoke to Jerhyn (after killing Duriel)" +#define D2S_QUEST_CHECKPOINT_181 "Killed Duriel" +#define D2S_QUEST_CHECKPOINT_182 "Atma congratulated you" +#define D2S_QUEST_CHECKPOINT_183 "Warriv congratulated you" +#define D2S_QUEST_CHECKPOINT_184 "Spoke to Drognan" +#define D2S_QUEST_CHECKPOINT_185 "Spoke to Lysander" +#define D2S_QUEST_CHECKPOINT_186 "Spoke to Cain" +#define D2S_QUEST_CHECKPOINT_187 "Spoke to Fara" +#define D2S_QUEST_CHECKPOINT_188 NULL +#define D2S_QUEST_CHECKPOINT_189 NULL +#define D2S_QUEST_CHECKPOINT_190 NULL +#define D2S_QUEST_CHECKPOINT_191 NULL +// Lam Esen's Tome +#define D2S_QUEST_CHECKPOINT_192 NULL +#define D2S_QUEST_CHECKPOINT_193 NULL +#define D2S_QUEST_CHECKPOINT_194 NULL +#define D2S_QUEST_CHECKPOINT_195 NULL +#define D2S_QUEST_CHECKPOINT_196 NULL +#define D2S_QUEST_CHECKPOINT_197 NULL +#define D2S_QUEST_CHECKPOINT_198 NULL +#define D2S_QUEST_CHECKPOINT_199 NULL +#define D2S_QUEST_CHECKPOINT_200 NULL +#define D2S_QUEST_CHECKPOINT_201 NULL +#define D2S_QUEST_CHECKPOINT_202 NULL +#define D2S_QUEST_CHECKPOINT_203 NULL +#define D2S_QUEST_CHECKPOINT_204 NULL +#define D2S_QUEST_CHECKPOINT_205 NULL +#define D2S_QUEST_CHECKPOINT_206 NULL +#define D2S_QUEST_CHECKPOINT_207 NULL +// Khalim's Will +#define D2S_QUEST_CHECKPOINT_208 NULL +#define D2S_QUEST_CHECKPOINT_209 NULL +#define D2S_QUEST_CHECKPOINT_210 NULL +#define D2S_QUEST_CHECKPOINT_211 NULL +#define D2S_QUEST_CHECKPOINT_212 NULL +#define D2S_QUEST_CHECKPOINT_213 NULL +#define D2S_QUEST_CHECKPOINT_214 NULL +#define D2S_QUEST_CHECKPOINT_215 NULL +#define D2S_QUEST_CHECKPOINT_216 NULL +#define D2S_QUEST_CHECKPOINT_217 NULL +#define D2S_QUEST_CHECKPOINT_218 NULL +#define D2S_QUEST_CHECKPOINT_219 NULL +#define D2S_QUEST_CHECKPOINT_220 NULL +#define D2S_QUEST_CHECKPOINT_221 NULL +#define D2S_QUEST_CHECKPOINT_222 NULL +#define D2S_QUEST_CHECKPOINT_223 NULL +// Blade of the Old Religion +#define D2S_QUEST_CHECKPOINT_224 NULL +#define D2S_QUEST_CHECKPOINT_225 NULL +#define D2S_QUEST_CHECKPOINT_226 "Picked the Gidbinn" +#define D2S_QUEST_CHECKPOINT_227 "Hratli asked you to find the Gidbinn" +#define D2S_QUEST_CHECKPOINT_228 NULL +#define D2S_QUEST_CHECKPOINT_229 NULL +#define D2S_QUEST_CHECKPOINT_230 NULL +#define D2S_QUEST_CHECKPOINT_231 NULL +#define D2S_QUEST_CHECKPOINT_232 NULL +#define D2S_QUEST_CHECKPOINT_233 NULL +#define D2S_QUEST_CHECKPOINT_234 NULL +#define D2S_QUEST_CHECKPOINT_235 NULL +#define D2S_QUEST_CHECKPOINT_236 NULL +#define D2S_QUEST_CHECKPOINT_237 NULL +#define D2S_QUEST_CHECKPOINT_238 NULL +#define D2S_QUEST_CHECKPOINT_239 NULL +// The Golden Bird +#define D2S_QUEST_CHECKPOINT_240 NULL +#define D2S_QUEST_CHECKPOINT_241 NULL +#define D2S_QUEST_CHECKPOINT_242 "Spoke to Cain about the Jade Figurine" +#define D2S_QUEST_CHECKPOINT_243 NULL +#define D2S_QUEST_CHECKPOINT_244 "Spoke to Cain about the Golden Bird" +// This is cleared when you drink it, to avoid players from cloning the item and drinking it more than once +#define D2S_QUEST_CHECKPOINT_245 "Alkor gave you the Potion of Life" +#define D2S_QUEST_CHECKPOINT_246 "Found the Jade Figurine" +#define D2S_QUEST_CHECKPOINT_247 NULL +#define D2S_QUEST_CHECKPOINT_248 NULL +#define D2S_QUEST_CHECKPOINT_249 NULL +#define D2S_QUEST_CHECKPOINT_250 NULL +#define D2S_QUEST_CHECKPOINT_251 NULL +#define D2S_QUEST_CHECKPOINT_252 NULL +#define D2S_QUEST_CHECKPOINT_253 NULL +#define D2S_QUEST_CHECKPOINT_254 NULL +#define D2S_QUEST_CHECKPOINT_255 NULL +// The Blackened Temple +#define D2S_QUEST_CHECKPOINT_256 NULL +#define D2S_QUEST_CHECKPOINT_257 NULL +#define D2S_QUEST_CHECKPOINT_258 NULL +#define D2S_QUEST_CHECKPOINT_259 NULL +#define D2S_QUEST_CHECKPOINT_260 NULL +#define D2S_QUEST_CHECKPOINT_261 NULL +#define D2S_QUEST_CHECKPOINT_262 NULL +#define D2S_QUEST_CHECKPOINT_263 NULL +#define D2S_QUEST_CHECKPOINT_264 NULL +#define D2S_QUEST_CHECKPOINT_265 NULL +#define D2S_QUEST_CHECKPOINT_266 NULL +#define D2S_QUEST_CHECKPOINT_267 NULL +#define D2S_QUEST_CHECKPOINT_268 NULL +#define D2S_QUEST_CHECKPOINT_269 NULL +#define D2S_QUEST_CHECKPOINT_270 NULL +#define D2S_QUEST_CHECKPOINT_271 NULL +// The Guardian +#define D2S_QUEST_CHECKPOINT_272 NULL +#define D2S_QUEST_CHECKPOINT_273 NULL +#define D2S_QUEST_CHECKPOINT_274 NULL +#define D2S_QUEST_CHECKPOINT_275 NULL +#define D2S_QUEST_CHECKPOINT_276 NULL +#define D2S_QUEST_CHECKPOINT_277 NULL +#define D2S_QUEST_CHECKPOINT_278 NULL +#define D2S_QUEST_CHECKPOINT_279 NULL +#define D2S_QUEST_CHECKPOINT_280 NULL +#define D2S_QUEST_CHECKPOINT_281 NULL +#define D2S_QUEST_CHECKPOINT_282 NULL +#define D2S_QUEST_CHECKPOINT_283 NULL +#define D2S_QUEST_CHECKPOINT_284 NULL +#define D2S_QUEST_CHECKPOINT_285 NULL +#define D2S_QUEST_CHECKPOINT_286 NULL +#define D2S_QUEST_CHECKPOINT_287 NULL +// The Fallen Angel +#define D2S_QUEST_CHECKPOINT_288 NULL +#define D2S_QUEST_CHECKPOINT_289 NULL +#define D2S_QUEST_CHECKPOINT_290 NULL +#define D2S_QUEST_CHECKPOINT_291 NULL +#define D2S_QUEST_CHECKPOINT_292 NULL +#define D2S_QUEST_CHECKPOINT_293 NULL +#define D2S_QUEST_CHECKPOINT_294 NULL +#define D2S_QUEST_CHECKPOINT_295 NULL +#define D2S_QUEST_CHECKPOINT_296 NULL +#define D2S_QUEST_CHECKPOINT_297 NULL +#define D2S_QUEST_CHECKPOINT_298 NULL +#define D2S_QUEST_CHECKPOINT_299 NULL +#define D2S_QUEST_CHECKPOINT_300 NULL +#define D2S_QUEST_CHECKPOINT_301 NULL +#define D2S_QUEST_CHECKPOINT_302 NULL +#define D2S_QUEST_CHECKPOINT_303 NULL +// Terror's End +#define D2S_QUEST_CHECKPOINT_304 NULL +#define D2S_QUEST_CHECKPOINT_305 NULL +#define D2S_QUEST_CHECKPOINT_306 NULL +#define D2S_QUEST_CHECKPOINT_307 NULL +#define D2S_QUEST_CHECKPOINT_308 NULL +#define D2S_QUEST_CHECKPOINT_309 NULL +#define D2S_QUEST_CHECKPOINT_310 NULL +#define D2S_QUEST_CHECKPOINT_311 NULL +#define D2S_QUEST_CHECKPOINT_312 NULL +#define D2S_QUEST_CHECKPOINT_313 NULL +#define D2S_QUEST_CHECKPOINT_314 NULL +#define D2S_QUEST_CHECKPOINT_315 NULL +#define D2S_QUEST_CHECKPOINT_316 NULL +#define D2S_QUEST_CHECKPOINT_317 NULL +#define D2S_QUEST_CHECKPOINT_318 NULL +#define D2S_QUEST_CHECKPOINT_319 NULL +// Hell's Forge +#define D2S_QUEST_CHECKPOINT_320 NULL +#define D2S_QUEST_CHECKPOINT_321 NULL +#define D2S_QUEST_CHECKPOINT_322 NULL +#define D2S_QUEST_CHECKPOINT_323 NULL +#define D2S_QUEST_CHECKPOINT_324 NULL +#define D2S_QUEST_CHECKPOINT_325 NULL +#define D2S_QUEST_CHECKPOINT_326 NULL +#define D2S_QUEST_CHECKPOINT_327 NULL +#define D2S_QUEST_CHECKPOINT_328 NULL +#define D2S_QUEST_CHECKPOINT_329 NULL +#define D2S_QUEST_CHECKPOINT_330 NULL +#define D2S_QUEST_CHECKPOINT_331 NULL +#define D2S_QUEST_CHECKPOINT_332 NULL +#define D2S_QUEST_CHECKPOINT_333 NULL +#define D2S_QUEST_CHECKPOINT_334 NULL +#define D2S_QUEST_CHECKPOINT_335 NULL +// Siege on Harrogath +#define D2S_QUEST_CHECKPOINT_336 NULL +#define D2S_QUEST_CHECKPOINT_337 NULL +#define D2S_QUEST_CHECKPOINT_338 NULL +// Apparently, this one is cleared after you kill him AND speak to Larzuk, at which point, bit 5 is set +#define D2S_QUEST_CHECKPOINT_339 "Found Shenk the Overseer" +#define D2S_QUEST_CHECKPOINT_340 NULL +#define D2S_QUEST_CHECKPOINT_341 "Larzuk offers to socket an item" +#define D2S_QUEST_CHECKPOINT_342 NULL +#define D2S_QUEST_CHECKPOINT_343 NULL +#define D2S_QUEST_CHECKPOINT_344 NULL +#define D2S_QUEST_CHECKPOINT_345 NULL +#define D2S_QUEST_CHECKPOINT_346 NULL +#define D2S_QUEST_CHECKPOINT_347 NULL +#define D2S_QUEST_CHECKPOINT_348 NULL +#define D2S_QUEST_CHECKPOINT_349 NULL +#define D2S_QUEST_CHECKPOINT_350 NULL +#define D2S_QUEST_CHECKPOINT_351 NULL +// Rescue on Mount Arreat +#define D2S_QUEST_CHECKPOINT_352 NULL +#define D2S_QUEST_CHECKPOINT_353 NULL +#define D2S_QUEST_CHECKPOINT_354 NULL +#define D2S_QUEST_CHECKPOINT_355 NULL +#define D2S_QUEST_CHECKPOINT_356 NULL +#define D2S_QUEST_CHECKPOINT_357 NULL +#define D2S_QUEST_CHECKPOINT_358 NULL +#define D2S_QUEST_CHECKPOINT_359 NULL +#define D2S_QUEST_CHECKPOINT_360 NULL +#define D2S_QUEST_CHECKPOINT_361 NULL +#define D2S_QUEST_CHECKPOINT_362 NULL +#define D2S_QUEST_CHECKPOINT_363 NULL +#define D2S_QUEST_CHECKPOINT_364 NULL +#define D2S_QUEST_CHECKPOINT_365 NULL +#define D2S_QUEST_CHECKPOINT_366 NULL +#define D2S_QUEST_CHECKPOINT_367 NULL +// Prison of Ice +#define D2S_QUEST_CHECKPOINT_368 NULL +#define D2S_QUEST_CHECKPOINT_369 NULL +#define D2S_QUEST_CHECKPOINT_370 NULL +#define D2S_QUEST_CHECKPOINT_371 NULL +#define D2S_QUEST_CHECKPOINT_372 NULL +#define D2S_QUEST_CHECKPOINT_373 NULL +#define D2S_QUEST_CHECKPOINT_374 NULL +// This is necessary to correctly calculate the player's resistances, as these are not stored anywhere, +// but determined from current equipment and this bit +#define D2S_QUEST_CHECKPOINT_375 "You read the Scroll of Resistance" +#define D2S_QUEST_CHECKPOINT_376 "Rescued Anya and talked to Malah" +#define D2S_QUEST_CHECKPOINT_377 NULL +#define D2S_QUEST_CHECKPOINT_378 NULL +#define D2S_QUEST_CHECKPOINT_379 NULL +#define D2S_QUEST_CHECKPOINT_380 NULL +#define D2S_QUEST_CHECKPOINT_381 NULL +#define D2S_QUEST_CHECKPOINT_382 NULL +#define D2S_QUEST_CHECKPOINT_383 NULL +// Betrayal of Harrogath +#define D2S_QUEST_CHECKPOINT_384 NULL +#define D2S_QUEST_CHECKPOINT_385 NULL +#define D2S_QUEST_CHECKPOINT_386 NULL +#define D2S_QUEST_CHECKPOINT_387 NULL +#define D2S_QUEST_CHECKPOINT_388 "Anya offers to personalise an item for you" +#define D2S_QUEST_CHECKPOINT_389 NULL +#define D2S_QUEST_CHECKPOINT_390 NULL +#define D2S_QUEST_CHECKPOINT_391 NULL +#define D2S_QUEST_CHECKPOINT_392 NULL +#define D2S_QUEST_CHECKPOINT_393 NULL +#define D2S_QUEST_CHECKPOINT_394 NULL +#define D2S_QUEST_CHECKPOINT_395 NULL +#define D2S_QUEST_CHECKPOINT_396 NULL +#define D2S_QUEST_CHECKPOINT_397 NULL +#define D2S_QUEST_CHECKPOINT_398 NULL +#define D2S_QUEST_CHECKPOINT_399 NULL +// Rite of Passage +#define D2S_QUEST_CHECKPOINT_400 NULL +#define D2S_QUEST_CHECKPOINT_401 NULL +#define D2S_QUEST_CHECKPOINT_402 NULL +#define D2S_QUEST_CHECKPOINT_403 NULL +#define D2S_QUEST_CHECKPOINT_404 NULL +#define D2S_QUEST_CHECKPOINT_405 NULL +#define D2S_QUEST_CHECKPOINT_406 NULL +#define D2S_QUEST_CHECKPOINT_407 NULL +#define D2S_QUEST_CHECKPOINT_408 NULL +#define D2S_QUEST_CHECKPOINT_409 NULL +#define D2S_QUEST_CHECKPOINT_410 NULL +#define D2S_QUEST_CHECKPOINT_411 NULL +#define D2S_QUEST_CHECKPOINT_412 NULL +#define D2S_QUEST_CHECKPOINT_413 NULL +#define D2S_QUEST_CHECKPOINT_414 NULL +#define D2S_QUEST_CHECKPOINT_415 NULL +// Eve of Destruction +#define D2S_QUEST_CHECKPOINT_416 NULL +#define D2S_QUEST_CHECKPOINT_417 NULL +#define D2S_QUEST_CHECKPOINT_418 NULL +#define D2S_QUEST_CHECKPOINT_419 NULL +#define D2S_QUEST_CHECKPOINT_420 "Larzuk congratulated you" +#define D2S_QUEST_CHECKPOINT_421 "Cain congratulated you" +#define D2S_QUEST_CHECKPOINT_422 "Malah congratulated you" +#define D2S_QUEST_CHECKPOINT_423 "Spoke to Tyrael" +#define D2S_QUEST_CHECKPOINT_424 "Spoke to Qual-Kehk" +#define D2S_QUEST_CHECKPOINT_425 "Spoke to Anya" +#define D2S_QUEST_CHECKPOINT_426 NULL +#define D2S_QUEST_CHECKPOINT_427 NULL +#define D2S_QUEST_CHECKPOINT_428 NULL +#define D2S_QUEST_CHECKPOINT_429 NULL +#define D2S_QUEST_CHECKPOINT_430 NULL +#define D2S_QUEST_CHECKPOINT_431 NULL + #endif \ No newline at end of file