From 4eaf3b2f0835637971a5eb112ec5ffd9bba4c7de Mon Sep 17 00:00:00 2001 From: FinnHornhoover Date: Sun, 4 Apr 2021 03:45:57 -0700 Subject: [PATCH] altered event drop logic, fixed taro/fm logic --- src/Combat.cpp | 11 ++-- src/Items.cpp | 153 +++++++++++++++++----------------------------- src/Items.hpp | 11 +++- src/TableData.cpp | 8 +++ 4 files changed, 79 insertions(+), 104 deletions(-) diff --git a/src/Combat.cpp b/src/Combat.cpp index 18236f4..186aea8 100644 --- a/src/Combat.cpp +++ b/src/Combat.cpp @@ -225,15 +225,12 @@ void Combat::killMob(CNSocket *sock, Mob *mob) { if (sock != nullptr) { Player* plr = PlayerManager::getPlayer(sock); - int rolledBoosts = Rand::rand(); - int rolledPotions = Rand::rand(); - int rolledCrate = Rand::rand(); - int rolledCrateType = Rand::rand(); - int rolledEvent = Rand::rand(); + Items::DropRoll rolled; + Items::DropRoll eventRolled; int rolledQItem = Rand::rand(); if (plr->groupCnt == 1 && plr->iIDGroup == plr->iID) { - Items::giveMobDrop(sock, mob, rolledBoosts, rolledPotions, rolledCrate, rolledCrateType, rolledEvent); + Items::giveMobDrop(sock, mob, rolled, eventRolled); Missions::mobKilled(sock, mob->appearanceData.iNPCType, rolledQItem); } else { Player* otherPlayer = PlayerManager::getPlayerFromID(plr->iIDGroup); @@ -253,7 +250,7 @@ void Combat::killMob(CNSocket *sock, Mob *mob) { if (dist > 5000) continue; - Items::giveMobDrop(sockTo, mob, rolledBoosts, rolledPotions, rolledCrate, rolledCrateType, rolledEvent); + Items::giveMobDrop(sockTo, mob, rolled, eventRolled); Missions::mobKilled(sockTo, mob->appearanceData.iNPCType, rolledQItem); } } diff --git a/src/Items.cpp b/src/Items.cpp index 7e91f2e..469fdf2 100644 --- a/src/Items.cpp +++ b/src/Items.cpp @@ -26,6 +26,7 @@ std::map> Items::CrateDropTypes; std::map Items::MiscDropChances; std::map Items::MiscDropTypes; std::map Items::MobDrops; +std::map Items::EventToDropMap; std::map Items::MobToDropMap; std::map Items::ItemSets; @@ -700,63 +701,7 @@ static void getMobDrop(sItemBase* reward, const std::vector& weights, const reward->iID = crateIds[chosenIndex]; } -static void giveEventDrop(CNSocket* sock, Player* player, int rolled) { - // random drop chance - if (Rand::rand(100) > settings::EVENTCRATECHANCE) - return; - - // no slot = no reward - int slot = findFreeSlot(player); - if (slot == -1) - return; - - const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); - assert(resplen < CN_PACKET_BUFFER_SIZE - 8); - - uint8_t respbuf[resplen]; - sP_FE2CL_REP_REWARD_ITEM* reward = (sP_FE2CL_REP_REWARD_ITEM*)respbuf; - sItemReward* item = (sItemReward*)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM)); - - // don't forget to zero the buffer! - memset(respbuf, 0, resplen); - - // leave everything here as it is - reward->m_iCandy = player->money; - reward->m_iFusionMatter = player->fusionmatter; - reward->m_iBatteryN = player->batteryN; - reward->m_iBatteryW = player->batteryW; - reward->iFatigue = 100; // prevents warning message - reward->iFatigue_Level = 1; - reward->iItemCnt = 1; // remember to update resplen if you change this - - // which crate to drop - int crateId; - switch (settings::EVENTMODE) { - // knishmas - case 1: crateId = 1187; break; - // halloween - case 2: crateId = 1181; break; - // spring - case 3: crateId = 1126; break; - // what - default: - std::cout << "[WARN] Unknown event Id " << settings::EVENTMODE << std::endl; - return; - } - - item->sItem.iType = 9; - item->sItem.iID = crateId; - item->sItem.iOpt = 1; - item->iSlotNum = slot; - item->eIL = 1; // Inventory Location. 1 means player inventory. - - // update player - player->Inven[slot] = item->sItem; - sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen); -} - -void Items::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPotions, - int rolledCrate, int rolledCrateType, int rolledEvent) { +static void giveSingleDrop(CNSocket *sock, Mob* mob, int mobDropId, const DropRoll& rolled) { Player *plr = PlayerManager::getPlayer(sock); const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); @@ -771,20 +716,12 @@ void Items::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPo memset(respbuf, 0, resplen); // sanity check - if (Items::MobToDropMap.find(mob->appearanceData.iNPCType) == Items::MobToDropMap.end()) { - std::cout << "[WARN] Mob ID " << mob->appearanceData.iNPCType << " has no drops assigned" << std::endl; - return; - } - // find mob drop id - int dropType = Items::MobToDropMap[mob->appearanceData.iNPCType]; - - // sanity check - if (Items::MobDrops.find(dropType) == Items::MobDrops.end()) { - std::cout << "[WARN] Drop Type " << dropType << " was not found" << std::endl; + if (Items::MobDrops.find(mobDropId) == Items::MobDrops.end()) { + std::cout << "[WARN] Drop Type " << mobDropId << " was not found" << std::endl; return; } // find correct mob drop - MobDrop& drop = Items::MobDrops[dropType]; + MobDrop& drop = Items::MobDrops[mobDropId]; // use the keys to fetch data from other maps // sanity check @@ -815,33 +752,37 @@ void Items::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPo } MiscDropType& miscDropType = Items::MiscDropTypes[drop.miscDropTypeId]; - plr->money += miscDropType.taroAmount; - // money nano boost - if (plr->iConditionBitFlag & CSB_BIT_REWARD_CASH) { - int boost = 0; - if (Nanos::getNanoBoost(plr)) // for gumballs - boost = 1; - plr->money += miscDropType.taroAmount * (5 + boost) / 25; + if (rolled.taros % miscDropChance.taroDropChanceTotal < miscDropChance.taroDropChance) { + plr->money += miscDropType.taroAmount; + // money nano boost + if (plr->iConditionBitFlag & CSB_BIT_REWARD_CASH) { + int boost = 0; + if (Nanos::getNanoBoost(plr)) // for gumballs + boost = 1; + plr->money += miscDropType.taroAmount * (5 + boost) / 25; + } } - // formula for scaling FM with player/mob level difference - // TODO: adjust this better - int levelDifference = plr->level - mob->level; - int fm = miscDropType.fmAmount; - if (levelDifference > 0) - fm = levelDifference < 10 ? fm - (levelDifference * fm / 10) : 0; - // scavenger nano boost - if (plr->iConditionBitFlag & CSB_BIT_REWARD_BLOB) { - int boost = 0; - if (Nanos::getNanoBoost(plr)) // for gumballs - boost = 1; - fm += fm * (5 + boost) / 25; + if (rolled.fm % miscDropChance.fmDropChanceTotal < miscDropChance.fmDropChance) { + // formula for scaling FM with player/mob level difference + // TODO: adjust this better + int levelDifference = plr->level - mob->level; + int fm = miscDropType.fmAmount; + if (levelDifference > 0) + fm = levelDifference < 10 ? fm - (levelDifference * fm / 10) : 0; + // scavenger nano boost + if (plr->iConditionBitFlag & CSB_BIT_REWARD_BLOB) { + int boost = 0; + if (Nanos::getNanoBoost(plr)) // for gumballs + boost = 1; + fm += fm * (5 + boost) / 25; + } + + Missions::updateFusionMatter(sock, fm); } - Missions::updateFusionMatter(sock, fm); - - if (rolledPotions % miscDropChance.potionDropChanceTotal < miscDropChance.potionDropChance) + if (rolled.potions % miscDropChance.potionDropChanceTotal < miscDropChance.potionDropChance) plr->batteryN += miscDropType.potionAmount; - if (rolledBoosts % miscDropChance.boostDropChanceTotal < miscDropChance.boostDropChance) + if (rolled.boosts % miscDropChance.boostDropChanceTotal < miscDropChance.boostDropChance) plr->batteryW += miscDropType.boostAmount; // caps @@ -862,13 +803,13 @@ void Items::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPo int slot = findFreeSlot(plr); // no drop - if (slot == -1 || rolledCrate % crateDropChance.dropChanceTotal >= crateDropChance.dropChance) { + if (slot == -1 || rolled.crate % crateDropChance.dropChanceTotal >= crateDropChance.dropChance) { // no room for an item, but you still get FM and taros reward->iItemCnt = 0; sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, sizeof(sP_FE2CL_REP_REWARD_ITEM)); } else { // item reward - getMobDrop(&item->sItem, crateDropChance.crateTypeDropWeights, crateDropType, rolledCrateType); + getMobDrop(&item->sItem, crateDropChance.crateTypeDropWeights, crateDropType, rolled.crateType); item->iSlotNum = slot; item->eIL = 1; // Inventory Location. 1 means player inventory. @@ -877,10 +818,30 @@ void Items::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPo sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen); } +} - // event crates - if (settings::EVENTMODE != 0) - giveEventDrop(sock, plr, rolledEvent); +void Items::giveMobDrop(CNSocket *sock, Mob* mob, const DropRoll& rolled, const DropRoll& eventRolled) { + // sanity check + if (Items::MobToDropMap.find(mob->appearanceData.iNPCType) == Items::MobToDropMap.end()) { + std::cout << "[WARN] Mob ID " << mob->appearanceData.iNPCType << " has no drops assigned" << std::endl; + return; + } + // find mob drop id + int mobDropId = Items::MobToDropMap[mob->appearanceData.iNPCType]; + + giveSingleDrop(sock, mob, mobDropId, rolled); + + if (settings::EVENTMODE != 0) { + // sanity check + if (Items::EventToDropMap.find(settings::EVENTMODE) == Items::EventToDropMap.end()) { + std::cout << "[WARN] Event " << settings::EVENTMODE << " has no mob drop assigned" << std::endl; + return; + } + // find mob drop id + int eventMobDropId = Items::EventToDropMap[settings::EVENTMODE]; + + giveSingleDrop(sock, mob, eventMobDropId, eventRolled); + } } void Items::init() { diff --git a/src/Items.hpp b/src/Items.hpp index 991feb8..97c7733 100644 --- a/src/Items.hpp +++ b/src/Items.hpp @@ -3,6 +3,7 @@ #include "servers/CNShardServer.hpp" #include "Player.hpp" #include "MobAI.hpp" +#include "Rand.hpp" struct CrocPotEntry { int multStats, multLooks; @@ -80,6 +81,13 @@ namespace Items { int weaponType; // TODO: implement more as needed }; + struct DropRoll { + int boosts, potions; + int taros, fm; + int crate, crateType; + + DropRoll() : boosts(Rand::rand()), potions(Rand::rand()), taros(Rand::rand()), fm(Rand::rand()), crate(Rand::rand()), crateType(Rand::rand()) { } + }; // hopefully this is fine since it's never modified after load extern std::map, Item> ItemData; // -> data extern std::map CrocPotTable; // level gap -> entry @@ -94,13 +102,14 @@ namespace Items { extern std::map MiscDropChances; extern std::map MiscDropTypes; extern std::map MobDrops; + extern std::map EventToDropMap; extern std::map MobToDropMap; extern std::map ItemSets; void init(); // mob drops - void giveMobDrop(CNSocket *sock, Mob *mob, int rolledBoosts, int rolledPotions, int rolledCrate, int rolledCrateType, int rolledEvent); + void giveMobDrop(CNSocket *sock, Mob *mob, const DropRoll& rolled, const DropRoll& eventRolled); int findFreeSlot(Player *plr); Item* getItemData(int32_t id, int32_t type); diff --git a/src/TableData.cpp b/src/TableData.cpp index ee8f714..884be73 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -274,6 +274,14 @@ static void loadDrops() { }; } + // Events + nlohmann::json events = dropData["Events"]; + for (nlohmann::json::iterator _event = events.begin(); _event != events.end(); _event++) { + auto event = _event.value(); + + Items::EventToDropMap[(int)event["EventID"]] = (int)event["MobDropID"]; + } + // Mobs nlohmann::json mobs = dropData["Mobs"]; for (nlohmann::json::iterator _mob = mobs.begin(); _mob != mobs.end(); _mob++) {