mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 13:30:06 +00:00
Merge pull request #92 from gsemaj/crocpot
Implement Croc Pot item combining Fix vehicle type override
This commit is contained in:
commit
77df7b7160
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
std::map<std::pair<int32_t, int32_t>, Item> ItemManager::ItemData;
|
std::map<std::pair<int32_t, int32_t>, Item> ItemManager::ItemData;
|
||||||
std::map<int32_t, std::vector<VendorListing>> ItemManager::VendorTables;
|
std::map<int32_t, std::vector<VendorListing>> ItemManager::VendorTables;
|
||||||
|
std::map<int32_t, CrocPotEntry> ItemManager::CrocPotTable;
|
||||||
|
|
||||||
void ItemManager::init() {
|
void ItemManager::init() {
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
|
||||||
|
@ -5,11 +5,15 @@
|
|||||||
|
|
||||||
struct Item {
|
struct Item {
|
||||||
bool tradeable, sellable;
|
bool tradeable, sellable;
|
||||||
int buyPrice, sellPrice, stackSize, level; // TODO: implement more as needed
|
int buyPrice, sellPrice, stackSize, level, rarity; // TODO: implement more as needed
|
||||||
};
|
};
|
||||||
struct VendorListing {
|
struct VendorListing {
|
||||||
int sort, type, iID;
|
int sort, type, iID;
|
||||||
};
|
};
|
||||||
|
struct CrocPotEntry {
|
||||||
|
int multStats, multLooks;
|
||||||
|
float base, rd0, rd1, rd2, rd3;
|
||||||
|
};
|
||||||
|
|
||||||
namespace ItemManager {
|
namespace ItemManager {
|
||||||
enum class SlotType {
|
enum class SlotType {
|
||||||
@ -20,6 +24,7 @@ namespace ItemManager {
|
|||||||
// hopefully this is fine since it's never modified after load
|
// hopefully this is fine since it's never modified after load
|
||||||
extern std::map<std::pair<int32_t, int32_t>, Item> ItemData; // <id, type> -> data
|
extern std::map<std::pair<int32_t, int32_t>, Item> ItemData; // <id, type> -> data
|
||||||
extern std::map<int32_t, std::vector<VendorListing>> VendorTables;
|
extern std::map<int32_t, std::vector<VendorListing>> VendorTables;
|
||||||
|
extern std::map<int32_t, CrocPotEntry> CrocPotTable; // level gap -> entry
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ void NPCManager::init() {
|
|||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_ITEM_SELL, npcVendorSell);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_ITEM_SELL, npcVendorSell);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_ITEM_RESTORE_BUY, npcVendorBuyback);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_ITEM_RESTORE_BUY, npcVendorBuyback);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_BATTERY_BUY, npcVendorBuyBattery);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_BATTERY_BUY, npcVendorBuyBattery);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_COMBINATION, npcCombineItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPCManager::addNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
|
void NPCManager::addNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
|
||||||
@ -312,6 +313,95 @@ void NPCManager::npcVendorBuyBattery(CNSocket* sock, CNPacketData* data) {
|
|||||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC, sizeof(sP_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC));
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC, sizeof(sP_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NPCManager::npcCombineItems(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_ITEM_COMBINATION))
|
||||||
|
return; // malformed packet
|
||||||
|
|
||||||
|
sP_CL2FE_REQ_PC_ITEM_COMBINATION* req = (sP_CL2FE_REQ_PC_ITEM_COMBINATION*)data->buf;
|
||||||
|
Player* plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
if (req->iCostumeItemSlot < 0 || req->iCostumeItemSlot >= AINVEN_COUNT || req->iStatItemSlot < 0 || req->iStatItemSlot >= AINVEN_COUNT) { // sanity check 1
|
||||||
|
INITSTRUCT(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, failResp);
|
||||||
|
failResp.iCostumeItemSlot = req->iCostumeItemSlot;
|
||||||
|
failResp.iStatItemSlot = req->iStatItemSlot;
|
||||||
|
failResp.iErrorCode = 0;
|
||||||
|
sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL));
|
||||||
|
std::cout << "[WARN] Inventory slot(s) out of range (" << req->iStatItemSlot << " and " << req->iCostumeItemSlot << ")" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sItemBase* itemStats = &plr->Inven[req->iStatItemSlot];
|
||||||
|
sItemBase* itemLooks = &plr->Inven[req->iCostumeItemSlot];
|
||||||
|
Item* itemStatsDat = ItemManager::getItemData(itemStats->iID, itemStats->iType);
|
||||||
|
Item* itemLooksDat = ItemManager::getItemData(itemLooks->iID, itemLooks->iType);
|
||||||
|
|
||||||
|
if (itemStatsDat == nullptr || itemLooksDat == nullptr
|
||||||
|
|| ItemManager::CrocPotTable.find(abs(itemStatsDat->level - itemLooksDat->level)) == ItemManager::CrocPotTable.end()) // sanity check 2
|
||||||
|
{
|
||||||
|
INITSTRUCT(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, failResp);
|
||||||
|
failResp.iCostumeItemSlot = req->iCostumeItemSlot;
|
||||||
|
failResp.iStatItemSlot = req->iStatItemSlot;
|
||||||
|
failResp.iErrorCode = 0;
|
||||||
|
std::cout << "[WARN] Either item ids or croc pot value set not found" << std::endl;
|
||||||
|
sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CrocPotEntry* recipe = &ItemManager::CrocPotTable[abs(itemStatsDat->level - itemLooksDat->level)];
|
||||||
|
int cost = itemStatsDat->buyPrice * recipe->multStats + itemLooksDat->buyPrice * recipe->multLooks;
|
||||||
|
float successChance = recipe->base / 100.0f; // base success chance
|
||||||
|
|
||||||
|
// rarity gap multiplier
|
||||||
|
switch(abs(itemStatsDat->rarity - itemLooksDat->rarity))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
successChance *= recipe->rd0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
successChance *= recipe->rd1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
successChance *= recipe->rd2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
successChance *= recipe->rd3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rolled = (rand() * 1.0f / RAND_MAX) * 100.0f; // success chance out of 100
|
||||||
|
//std::cout << rolled << " vs " << successChance << std::endl;
|
||||||
|
plr->money -= cost;
|
||||||
|
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_REP_PC_ITEM_COMBINATION_SUCC, resp);
|
||||||
|
if (rolled < successChance) {
|
||||||
|
// success
|
||||||
|
resp.iSuccessFlag = 1;
|
||||||
|
|
||||||
|
// modify the looks item with the new stats and set the appearance through iOpt
|
||||||
|
itemLooks->iOpt = (int32_t)itemLooks->iID << 16;
|
||||||
|
itemLooks->iID = itemStats->iID;
|
||||||
|
|
||||||
|
// delete stats item
|
||||||
|
itemStats->iID = 0;
|
||||||
|
itemStats->iOpt = 0;
|
||||||
|
itemStats->iTimeLimit = 0;
|
||||||
|
itemStats->iType = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// failure; don't do anything?
|
||||||
|
resp.iSuccessFlag = 0;
|
||||||
|
}
|
||||||
|
resp.iCandy = plr->money;
|
||||||
|
resp.iNewItemSlot = req->iCostumeItemSlot;
|
||||||
|
resp.iStatItemSlot = req->iStatItemSlot;
|
||||||
|
resp.sNewItem = *itemLooks;
|
||||||
|
|
||||||
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_ITEM_COMBINATION_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_SUCC));
|
||||||
|
}
|
||||||
|
|
||||||
void NPCManager::npcBarkHandler(CNSocket* sock, CNPacketData* data) {} // stubbed for now
|
void NPCManager::npcBarkHandler(CNSocket* sock, CNPacketData* data) {} // stubbed for now
|
||||||
|
|
||||||
void NPCManager::npcUnsummonHandler(CNSocket* sock, CNPacketData* data) {
|
void NPCManager::npcUnsummonHandler(CNSocket* sock, CNPacketData* data) {
|
||||||
|
@ -34,4 +34,5 @@ namespace NPCManager {
|
|||||||
void npcVendorSell(CNSocket* sock, CNPacketData* data);
|
void npcVendorSell(CNSocket* sock, CNPacketData* data);
|
||||||
void npcVendorBuyback(CNSocket* sock, CNPacketData* data);
|
void npcVendorBuyback(CNSocket* sock, CNPacketData* data);
|
||||||
void npcVendorBuyBattery(CNSocket* sock, CNPacketData* data);
|
void npcVendorBuyBattery(CNSocket* sock, CNPacketData* data);
|
||||||
|
void npcCombineItems(CNSocket* sock, CNPacketData* data);
|
||||||
}
|
}
|
||||||
|
@ -110,11 +110,12 @@ void TableData::init() {
|
|||||||
nlohmann::json itemSet;
|
nlohmann::json itemSet;
|
||||||
for (int i = 0; i < 12; i++) {
|
for (int i = 0; i < 12; i++) {
|
||||||
itemSet = xdtData[setNames[i]]["m_pItemData"];
|
itemSet = xdtData[setNames[i]]["m_pItemData"];
|
||||||
|
|
||||||
for (nlohmann::json::iterator _item = itemSet.begin(); _item != itemSet.end(); _item++) {
|
for (nlohmann::json::iterator _item = itemSet.begin(); _item != itemSet.end(); _item++) {
|
||||||
auto item = _item.value();
|
auto item = _item.value();
|
||||||
ItemManager::ItemData[std::pair<int32_t, int32_t>(item["m_iItemNumber"], i == 11 ? 9 : (i == 10 ? 7 : (int)item["m_iEquipLoc"]))]
|
int typeOverride = getItemType(i); // used for special cases where iEquipLoc doesn't indicate item type
|
||||||
= { item["m_iTradeAble"] == 1, item["m_iSellAble"] == 1, item["m_iItemPrice"], item["m_iItemSellPrice"], item["m_iStackNumber"], i > 9 ? 0 : (int)item["m_iMinReqLev"] };
|
ItemManager::ItemData[std::pair<int32_t, int32_t>(item["m_iItemNumber"], typeOverride != -1 ? typeOverride : (int)item["m_iEquipLoc"])]
|
||||||
|
= { item["m_iTradeAble"] == 1, item["m_iSellAble"] == 1, item["m_iItemPrice"], item["m_iItemSellPrice"], item["m_iStackNumber"], i > 9 ? 0 : (int)item["m_iMinReqLev"],
|
||||||
|
i > 9 ? 1 : (int)item["m_iRarity"] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +131,17 @@ void TableData::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "[INFO] Loaded " << ItemManager::VendorTables.size() << " vendor tables" << std::endl;
|
std::cout << "[INFO] Loaded " << ItemManager::VendorTables.size() << " vendor tables" << std::endl;
|
||||||
|
|
||||||
|
// load crocpot entries
|
||||||
|
nlohmann::json crocs = xdtData["m_pCombiningTable"]["m_pCombiningData"];
|
||||||
|
|
||||||
|
for (nlohmann::json::iterator croc = crocs.begin(); croc != crocs.end(); croc++) {
|
||||||
|
CrocPotEntry crocEntry = { croc.value()["m_iStatConstant"], croc.value()["m_iLookConstant"], croc.value()["m_fLevelGapStandard"],
|
||||||
|
croc.value()["m_fSameGrade"], croc.value()["m_fOneGrade"], croc.value()["m_fTwoGrade"], croc.value()["m_fThreeGrade"] };
|
||||||
|
ItemManager::CrocPotTable[croc.value()["m_iLevelGap"]] = crocEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "[INFO] Loaded " << ItemManager::CrocPotTable.size() << " croc pot value sets" << std::endl;
|
||||||
}
|
}
|
||||||
catch (const std::exception& err) {
|
catch (const std::exception& err) {
|
||||||
std::cerr << "[WARN] Malformed xdt.json file! Reason:" << err.what() << std::endl;
|
std::cerr << "[WARN] Malformed xdt.json file! Reason:" << err.what() << std::endl;
|
||||||
@ -179,3 +191,25 @@ void TableData::cleanup() {
|
|||||||
for (auto& pair : NPCManager::NPCs)
|
for (auto& pair : NPCManager::NPCs)
|
||||||
delete pair.second;
|
delete pair.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some item categories either don't possess iEquipLoc or use a different value for item type.
|
||||||
|
*/
|
||||||
|
int TableData::getItemType(int itemSet) {
|
||||||
|
int overriden;
|
||||||
|
switch (itemSet)
|
||||||
|
{
|
||||||
|
case 11: // Chest items don't have iEquipLoc and are type 9.
|
||||||
|
overriden = 9;
|
||||||
|
break;
|
||||||
|
case 10: // General items don't have iEquipLoc and are type 7.
|
||||||
|
overriden = 7;
|
||||||
|
break;
|
||||||
|
case 9: // Vehicles have iEquipLoc 8, but type 10.
|
||||||
|
overriden = 10;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
overriden = -1;
|
||||||
|
}
|
||||||
|
return overriden;
|
||||||
|
}
|
||||||
|
@ -4,4 +4,6 @@
|
|||||||
namespace TableData {
|
namespace TableData {
|
||||||
void init();
|
void init();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
|
int getItemType(int);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user