diff --git a/src/item.cc b/src/item.cc index a429094..3f28cf0 100644 --- a/src/item.cc +++ b/src/item.cc @@ -22,6 +22,7 @@ #include "proto_instance.h" #include "queue.h" #include "random.h" +#include "sfall_config.h" #include "skill.h" #include "stat.h" #include "tile.h" @@ -29,8 +30,14 @@ #include +#include + #define ADDICTION_COUNT (9) +// Max number of books that can be loaded from books.ini. This limit is imposed +// by Sfall. +#define BOOKS_MAX 50 + static int _item_load_(File* stream); static void _item_compact(int inventoryItemIndex, Inventory* inventory); static int _item_move_func(Object* a1, Object* a2, Object* a3, int quantity, bool a5); @@ -49,12 +56,24 @@ static void dudeSetAddiction(int drugPid); static void dudeClearAddiction(int drugPid); static bool dudeIsAddicted(int drugPid); +static void booksInit(); +static void booksInitVanilla(); +static void booksInitCustom(); +static void booksAdd(int bookPid, int messageId, int skill); +static void booksExit(); + typedef struct DrugDescription { int drugPid; int gvar; int field_8; } DrugDescription; +typedef struct BookDescription { + int bookPid; + int messageId; + int skill; +} BookDescription; + // 0x509FFC static char _aItem_1[] = ""; @@ -133,6 +152,8 @@ static Object* _wd_obj; // 0x59E990 static int _wd_gvar; +static std::vector gBooks; + // 0x4770E0 int itemsInit() { @@ -147,6 +168,9 @@ int itemsInit() return -1; } + // SFALL + booksInit(); + return 0; } @@ -160,6 +184,9 @@ void itemsReset() void itemsExit() { messageListFree(&gItemsMessageList); + + // SFALL + booksExit(); } // NOTE: Collapsed. @@ -3229,3 +3256,100 @@ int itemSetMoney(Object* item, int amount) return 0; } + +static void booksInit() +{ + booksInitVanilla(); + booksInitCustom(); +} + +static void booksExit() +{ + gBooks.clear(); +} + +static void booksInitVanilla() +{ + // 802: You learn new science information. + booksAdd(PROTO_ID_BIG_BOOK_OF_SCIENCE, 802, SKILL_SCIENCE); + + // 803: You learn a lot about repairing broken electronics. + booksAdd(PROTO_ID_DEANS_ELECTRONICS, 803, SKILL_REPAIR); + + // 804: You learn new ways to heal injury. + booksAdd(PROTO_ID_FIRST_AID_BOOK, 804, SKILL_FIRST_AID); + + // 805: You learn how to handle your guns better. + booksAdd(PROTO_ID_GUNS_AND_BULLETS, 805, SKILL_SMALL_GUNS); + + // 806: You learn a lot about wilderness survival. + booksAdd(PROTO_ID_SCOUT_HANDBOOK, 806, SKILL_OUTDOORSMAN); +} + +static void booksInitCustom() +{ + char* booksFilePath; + configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_BOOKS_FILE_KEY, &booksFilePath); + if (booksFilePath != NULL && *booksFilePath == '\0') { + booksFilePath = NULL; + } + + if (booksFilePath != NULL) { + Config booksConfig; + if (configInit(&booksConfig)) { + if (configRead(&booksConfig, booksFilePath, false)) { + bool overrideVanilla = false; + configGetBool(&booksConfig, "main", "overrideVanilla", &overrideVanilla); + if (overrideVanilla) { + gBooks.clear(); + } + + int bookCount = 0; + configGetInt(&booksConfig, "main", "count", &bookCount); + if (bookCount > BOOKS_MAX) { + bookCount = BOOKS_MAX; + } + + char sectionKey[4]; + for (int index = 0; index < bookCount; index++) { + // Books numbering starts with 1. + sprintf(sectionKey, "%d", index + 1); + + int bookPid; + if (!configGetInt(&booksConfig, sectionKey, "PID", &bookPid)) continue; + + int messageId; + if (!configGetInt(&booksConfig, sectionKey, "TextID", &messageId)) continue; + + int skill; + if (!configGetInt(&booksConfig, sectionKey, "Skill", &skill)) continue; + + booksAdd(bookPid, messageId, skill); + } + } + + configFree(&booksConfig); + } + } +} + +static void booksAdd(int bookPid, int messageId, int skill) +{ + BookDescription bookDescription; + bookDescription.bookPid = bookPid; + bookDescription.messageId = messageId; + bookDescription.skill = skill; + gBooks.emplace_back(std::move(bookDescription)); +} + +bool booksGetInfo(int bookPid, int* messageIdPtr, int* skillPtr) +{ + for (auto& bookDescription : gBooks) { + if (bookDescription.bookPid == bookPid) { + *messageIdPtr = bookDescription.messageId; + *skillPtr = bookDescription.skill; + return true; + } + } + return false; +} diff --git a/src/item.h b/src/item.h index 74176a2..677a138 100644 --- a/src/item.h +++ b/src/item.h @@ -123,4 +123,6 @@ int itemCapsAdjust(Object* obj, int amount); int itemGetMoney(Object* obj); int itemSetMoney(Object* obj, int a2); +bool booksGetInfo(int bookPid, int* messageIdPtr, int* skillPtr); + #endif /* ITEM_H */ diff --git a/src/proto_instance.cc b/src/proto_instance.cc index 3af1c0a..8edd05a 100644 --- a/src/proto_instance.cc +++ b/src/proto_instance.cc @@ -730,35 +730,8 @@ static int _obj_use_book(Object* book) int messageId = -1; int skill; - switch (book->pid) { - case PROTO_ID_BIG_BOOK_OF_SCIENCE: - // You learn new science information. - messageId = 802; - skill = SKILL_SCIENCE; - break; - case PROTO_ID_DEANS_ELECTRONICS: - // You learn a lot about repairing broken electronics. - messageId = 803; - skill = SKILL_REPAIR; - break; - case PROTO_ID_FIRST_AID_BOOK: - // You learn new ways to heal injury. - messageId = 804; - skill = SKILL_FIRST_AID; - break; - case PROTO_ID_SCOUT_HANDBOOK: - // You learn a lot about wilderness survival. - messageId = 806; - skill = SKILL_OUTDOORSMAN; - break; - case PROTO_ID_GUNS_AND_BULLETS: - // You learn how to handle your guns better. - messageId = 805; - skill = SKILL_SMALL_GUNS; - break; - } - - if (messageId == -1) { + // SFALL + if (!booksGetInfo(book->pid, &messageId, &skill)) { return -1; } diff --git a/src/sfall_config.cc b/src/sfall_config.cc index 3fb83f3..eb78e2c 100644 --- a/src/sfall_config.cc +++ b/src/sfall_config.cc @@ -37,6 +37,7 @@ bool sfallConfigInit(int argc, char** argv) configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_OVERRIDE_CRITICALS_MODE_KEY, 2); configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_OVERRIDE_CRITICALS_FILE_KEY, ""); configSetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_REMOVE_CRITICALS_TIME_LIMITS_KEY, false); + configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_BOOKS_FILE_KEY, ""); char path[COMPAT_MAX_PATH]; char* executable = argv[0]; diff --git a/src/sfall_config.h b/src/sfall_config.h index a459a3d..5458a55 100644 --- a/src/sfall_config.h +++ b/src/sfall_config.h @@ -25,6 +25,7 @@ #define SFALL_CONFIG_OVERRIDE_CRITICALS_MODE_KEY "OverrideCriticalTable" #define SFALL_CONFIG_OVERRIDE_CRITICALS_FILE_KEY "OverrideCriticalFile" #define SFALL_CONFIG_REMOVE_CRITICALS_TIME_LIMITS_KEY "RemoveCriticalTimelimits" +#define SFALL_CONFIG_BOOKS_FILE_KEY "BooksFile" extern bool gSfallConfigInitialized; extern Config gSfallConfig;