Cleaned up item drop logic.

* Replaced bad exception logic with C-style error returns in ItemManager
* Removed unnecessary instances of objects being passed by value
* Fixed whitespace problems
* Added new config options to the default config.ini
* Updated tabledata reference
This commit is contained in:
dongresource 2020-10-18 01:19:05 +02:00
parent 7f716c7278
commit 3ce8cf2129
8 changed files with 167 additions and 145 deletions

View File

@ -38,6 +38,8 @@ xdtdata=tdata/xdt.json
mobdata=tdata/mobs.json mobdata=tdata/mobs.json
# path json # path json
pathdata=tdata/paths.json pathdata=tdata/paths.json
# drop json
dropdata=tdata/drops.json
# gruntwork output (this is what you submit) # gruntwork output (this is what you submit)
gruntwork=tdata/gruntwork.json gruntwork=tdata/gruntwork.json
@ -49,6 +51,15 @@ gruntwork=tdata/gruntwork.json
# any number higher than 50 will disable commands # any number higher than 50 will disable commands
accountlevel=1 accountlevel=1
# should mobs drop event crates?
# 0 = no event
# 1 = Knishmas
# 2 = Halloween
# 3 = Easter
eventmode=0
# percent chance of an event crate dropping each kill
eventcratechance=10
# spawn coordinates (Z is height) # spawn coordinates (Z is height)
# the supplied defaults are at Sector V (future) # the supplied defaults are at Sector V (future)
spawnx=632032 spawnx=632032

View File

@ -16,14 +16,11 @@ std::map<int32_t, Crate> ItemManager::Crates;
/// pair Itemset, Rarity -> vector of pointers (map iterators) to records in ItemData /// pair Itemset, Rarity -> vector of pointers (map iterators) to records in ItemData
std::map<std::pair<int32_t, int32_t>, std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator>> ItemManager::CrateItems; std::map<std::pair<int32_t, int32_t>, std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator>> ItemManager::CrateItems;
// buffer for error messages
char buffer[255];
void ItemManager::init() { void ItemManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_ITEM, itemGMGiveHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_ITEM, itemGMGiveHandler);
//this one is for gumballs // this one is for gumballs
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_USE, itemUseHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_USE, itemUseHandler);
// Bank // Bank
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_BANK_OPEN, itemBankOpenHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_BANK_OPEN, itemBankOpenHandler);
@ -809,9 +806,13 @@ void ItemManager::chestOpenHandler(CNSocket *sock, CNPacketData *data) {
return; // ignore the malformed packet return; // ignore the malformed packet
sP_CL2FE_REQ_ITEM_CHEST_OPEN *chest = (sP_CL2FE_REQ_ITEM_CHEST_OPEN *)data->buf; sP_CL2FE_REQ_ITEM_CHEST_OPEN *chest = (sP_CL2FE_REQ_ITEM_CHEST_OPEN *)data->buf;
Player *player = PlayerManager::getPlayer(sock); Player *plr = PlayerManager::getPlayer(sock);
if (player == nullptr) // chest opening acknowledgement packet
INITSTRUCT(sP_FE2CL_REP_ITEM_CHEST_OPEN_SUCC, resp);
resp.iSlotNum = chest->iSlotNum;
if (plr == nullptr)
return; return;
// item giving packet // item giving packet
@ -827,75 +828,82 @@ void ItemManager::chestOpenHandler(CNSocket *sock, CNPacketData *data) {
memset(respbuf, 0, resplen); memset(respbuf, 0, resplen);
// maintain stats // maintain stats
reward->m_iCandy = player->money; reward->m_iCandy = plr->money;
reward->m_iFusionMatter = player->fusionmatter; reward->m_iFusionMatter = plr->fusionmatter;
reward->iFatigue = 100; // prevents warning message reward->iFatigue = 100; // prevents warning message
reward->iFatigue_Level = 1; reward->iFatigue_Level = 1;
reward->iItemCnt = 1; // remember to update resplen if you change this reward->iItemCnt = 1; // remember to update resplen if you change this
// item reward
if (chest->ChestItem.iType != 9)
std::cout << "[WARN] Player tried to open a crate with incorrect iType ?!" << std::endl;
else
item->sItem = openCrate(chest->ChestItem.iID, player->PCStyle.iGender);
item->iSlotNum = chest->iSlotNum; item->iSlotNum = chest->iSlotNum;
item->eIL = chest->eIL; item->eIL = chest->eIL;
// item reward
if (chest->ChestItem.iType != 9) {
std::cout << "[WARN] Player tried to open a crate with incorrect iType ?!" << std::endl;
return;
}
int itemSetId = -1, rarity = -1, ret = -1;
bool failing = false;
// find the crate
if (Crates.find(chest->ChestItem.iID) == Crates.end()) {
std::cout << "[WARN] Crate " << chest->ChestItem.iID << " not found!" << std::endl;
failing = true;
}
Crate& crate = Crates[chest->ChestItem.iID];
if (!failing)
itemSetId = getItemSetId(crate, chest->ChestItem.iID);
if (itemSetId == -1)
failing = true;
if (!failing)
rarity = getRarity(crate, itemSetId);
if (rarity == -1)
failing = true;
if (!failing)
ret = getCrateItem(item->sItem, itemSetId, rarity, plr->PCStyle.iGender);
if (ret == -1)
failing = true;
// if we failed to open a crate, at least give the player a gumball (suggested by Jade)
if (failing) {
item->sItem.iType = 7;
item->sItem.iID = 119 + (rand() % 3);
item->sItem.iOpt = 1;
}
// update player // update player
player->Inven[chest->iSlotNum] = item->sItem; plr->Inven[chest->iSlotNum] = item->sItem;
// transmit item // transmit item
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen); sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen);
// chest opening acknowledgement packet // transmit chest opening acknowledgement packet
INITSTRUCT(sP_FE2CL_REP_ITEM_CHEST_OPEN_SUCC, resp);
resp.iSlotNum = chest->iSlotNum;
std::cout << "opening chest..." << std::endl; std::cout << "opening chest..." << std::endl;
sock->sendPacket((void*)&resp, P_FE2CL_REP_ITEM_CHEST_OPEN_SUCC, sizeof(sP_FE2CL_REP_ITEM_CHEST_OPEN_SUCC)); sock->sendPacket((void*)&resp, P_FE2CL_REP_ITEM_CHEST_OPEN_SUCC, sizeof(sP_FE2CL_REP_ITEM_CHEST_OPEN_SUCC));
} }
sItemBase ItemManager::openCrate(int crateId, int playerGender) { int ItemManager::getItemSetId(Crate& crate, int crateId) {
sItemBase reward = {};
try {
Crate crate = getCrate(crateId);
int itemSetId = getItemSetId(crate, crateId);
int rarity = getRarity(crate, itemSetId);
reward = getCrateItem(itemSetId, rarity, playerGender);
}
catch (const std::exception& err) {
std::cerr << "[WARN] An error has occured while trying to open a crate. Error description: \n" << err.what() << std::endl;
// if we failed to open a crate, at least give the player a gumball (suggested by Jade)
reward.iType = 7;
reward.iID = 119 + (rand() % 3);
reward.iOpt = 1;
}
return reward;
}
Crate ItemManager::getCrate(int crateId) {
if (Crates.find(crateId) == Crates.end())
throwError(sprintf(buffer, "Crate %d was not found!", crateId));
return Crates[crateId];
}
int ItemManager::getItemSetId(Crate crate, int crateId) {
int itemSetsCount = crate.itemSets.size(); int itemSetsCount = crate.itemSets.size();
if (itemSetsCount == 0) if (itemSetsCount == 0) {
throwError(sprintf(buffer, "Crate %d has no item sets assigned?!", crateId)); std::cout << "[WARN] Crate " << crateId << " has no item sets assigned?!" << std::endl;
return -1;
}
// if crate points to multiple itemSets, choose a random one // if crate points to multiple itemSets, choose a random one
int itemSetIndex = rand() % itemSetsCount; int itemSetIndex = rand() % itemSetsCount;
return crate.itemSets[itemSetIndex]; return crate.itemSets[itemSetIndex];
} }
int ItemManager::getRarity(Crate crate , int itemSetId) { int ItemManager::getRarity(Crate& crate, int itemSetId) {
// find rarity ratio // find rarity ratio
if (RarityRatios.find(crate.rarityRatioId) == RarityRatios.end()) if (RarityRatios.find(crate.rarityRatioId) == RarityRatios.end()) {
throwError(sprintf(buffer, "Rarity Ratio %d not found!", crate.rarityRatioId)); std::cout << "[WARN] Rarity Ratio " << crate.rarityRatioId << " not found!" << std::endl;
return -1;
}
std::vector<int> rarityRatio = RarityRatios[crate.rarityRatioId]; std::vector<int> rarityRatio = RarityRatios[crate.rarityRatioId];
@ -905,7 +913,7 @@ int ItemManager::getRarity(Crate crate , int itemSetId) {
* it is simpler to do here than to fix individually in the file * it is simpler to do here than to fix individually in the file
*/ */
// remember that rarities start from 1 ! // remember that rarities start from 1!
for (int i = 0; i < rarityRatio.size(); i++){ for (int i = 0; i < rarityRatio.size(); i++){
if (CrateItems.find(std::make_pair(itemSetId, i+1)) == CrateItems.end()) if (CrateItems.find(std::make_pair(itemSetId, i+1)) == CrateItems.end())
rarityRatio[i] = 0; rarityRatio[i] = 0;
@ -915,9 +923,10 @@ int ItemManager::getRarity(Crate crate , int itemSetId) {
for (int value : rarityRatio) for (int value : rarityRatio)
total += value; total += value;
// if we didn't find any items, throw exception if (total == 0) {
if (total == 0) std::cout << "Item Set " << itemSetId << " has no items assigned?!" << std::endl;
throwError(sprintf(buffer, "Item Set %d has no items assigned?!", itemSetId)); return -1;
}
// now return a random rarity number // now return a random rarity number
int randomNum = rand() % total; int randomNum = rand() % total;
@ -931,11 +940,13 @@ int ItemManager::getRarity(Crate crate , int itemSetId) {
return rarity; return rarity;
} }
sItemBase ItemManager::getCrateItem(int itemSetId, int rarity, int playerGender) { int ItemManager::getCrateItem(sItemBase& result, int itemSetId, int rarity, int playerGender) {
std::pair key = std::make_pair(itemSetId, rarity); std::pair key = std::make_pair(itemSetId, rarity);
if (CrateItems.find(key) == CrateItems.end()) if (CrateItems.find(key) == CrateItems.end()) {
throwError(sprintf(buffer, "Item Set ID %d Rarity %d items have not been found", itemSetId, rarity)); std::cout << "[WARN] Item Set ID " << itemSetId << " Rarity " << rarity << " items have not been found" << std::endl;
return -1;
}
// only take into account items that have correct gender // only take into account items that have correct gender
std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator> items; std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator> items;
@ -948,20 +959,19 @@ sItemBase ItemManager::getCrateItem(int itemSetId, int rarity, int playerGender)
items.push_back(crateitem); items.push_back(crateitem);
} }
if (items.size() == 0) if (items.size() == 0) {
throwError(sprintf(buffer, "Gender inequality! Set ID %d Rarity %d contains only %s items?!", itemSetId, rarity, playerGender==2 ? "boys" : "girls")); std::cout << "[WARN] Gender inequality! Set ID " << itemSetId << " Rarity " << rarity << " contains only "
<< (playerGender == 2 ? "boys" : "girls") << " items?!" << std::endl;
return -1;
}
auto item = items[rand() % items.size()]; auto item = items[rand() % items.size()];
sItemBase result = {};
result.iID = item->first.first; result.iID = item->first.first;
result.iType = item->first.second; result.iType = item->first.second;
result.iOpt = 1; result.iOpt = 1;
return result; return 0;
}
// argument is here only so we can call sprintf in brackets
void ItemManager::throwError(int ignore) {
throw buffer;
} }
// TODO: use this in cleaned up ItemManager // TODO: use this in cleaned up ItemManager

View File

@ -56,12 +56,9 @@ namespace ItemManager {
void chestOpenHandler(CNSocket* sock, CNPacketData* data); void chestOpenHandler(CNSocket* sock, CNPacketData* data);
// crate opening logic with all helper functions // crate opening logic with all helper functions
sItemBase openCrate(int crateId, int playerGender); int getItemSetId(Crate& crate, int crateId);
Crate getCrate(int crateId); int getRarity(Crate& crate, int itemSetId);
int getItemSetId(Crate crate, int crateId); int getCrateItem(sItemBase& reward, int itemSetId, int rarity, int playerGender);
int getRarity(Crate crate, int itemSetId);
sItemBase getCrateItem(int itemSetId, int rarity, int playerGender);
void throwError(int ignore);
int findFreeSlot(Player *plr); int findFreeSlot(Player *plr);
Item* getItemData(int32_t id, int32_t type); Item* getItemData(int32_t id, int32_t type);

View File

@ -11,9 +11,10 @@
#include <assert.h> #include <assert.h>
std::map<int32_t, Mob*> MobManager::Mobs; std::map<int32_t, Mob*> MobManager::Mobs;
std::queue<int32_t> MobManager::RemovalQueue;
std::map<int32_t, MobDropChance> MobManager::MobDropChances; std::map<int32_t, MobDropChance> MobManager::MobDropChances;
std::map<int32_t, MobDrop> MobManager::MobDrops; std::map<int32_t, MobDrop> MobManager::MobDrops;
std::queue<int32_t> MobManager::RemovalQueue;
bool MobManager::simulateMobs; bool MobManager::simulateMobs;
@ -168,7 +169,7 @@ void MobManager::giveReward(CNSocket *sock, Mob* mob) {
return; return;
} }
// find correct mob drop // find correct mob drop
MobDrop drop = MobDrops[mob->dropType]; MobDrop& drop = MobDrops[mob->dropType];
plr->money += drop.taros; plr->money += drop.taros;
// formula for scaling FM with player/mob level difference // formula for scaling FM with player/mob level difference
@ -197,29 +198,27 @@ void MobManager::giveReward(CNSocket *sock, Mob* mob) {
reward->iFatigue_Level = 1; reward->iFatigue_Level = 1;
reward->iItemCnt = 1; // remember to update resplen if you change this reward->iItemCnt = 1; // remember to update resplen if you change this
int slot = ItemManager::findFreeSlot(plr); int slot = ItemManager::findFreeSlot(plr);
bool awardDrop = false; bool awardDrop = false;
MobDropChance chance; MobDropChance *chance = nullptr;
// sanity check // sanity check
if (MobDropChances.find(drop.dropChanceType) == MobDropChances.end()) if (MobDropChances.find(drop.dropChanceType) == MobDropChances.end()) {
std::cout << "[WARN] Unknown Drop Chance Type: " << drop.dropChanceType << std::endl; std::cout << "[WARN] Unknown Drop Chance Type: " << drop.dropChanceType << std::endl;
else { return; // this also prevents holiday crate drops, but oh well
chance = MobDropChances[drop.dropChanceType]; } else {
awardDrop = (rand() % 1000 < chance.dropChance); chance = &MobDropChances[drop.dropChanceType];
awardDrop = (rand() % 1000 < chance->dropChance);
} }
// no drop // no drop
if (slot == -1 || !awardDrop) { if (slot == -1 || !awardDrop) {
// no room for an item, but you still get FM and taros // no room for an item, but you still get FM and taros
reward->iItemCnt = 0; reward->iItemCnt = 0;
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, sizeof(sP_FE2CL_REP_REWARD_ITEM)); sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, sizeof(sP_FE2CL_REP_REWARD_ITEM));
} else { } else {
// item reward // item reward
item->sItem = getReward(&drop, &chance); getReward(&item->sItem, &drop, chance);
item->iSlotNum = slot; item->iSlotNum = slot;
item->eIL = 1; // Inventory Location. 1 means player inventory. item->eIL = 1; // Inventory Location. 1 means player inventory.
@ -227,7 +226,6 @@ void MobManager::giveReward(CNSocket *sock, Mob* mob) {
plr->Inven[slot] = item->sItem; plr->Inven[slot] = item->sItem;
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen); sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen);
} }
// event crates // event crates
@ -235,10 +233,9 @@ void MobManager::giveReward(CNSocket *sock, Mob* mob) {
giveEventReward(sock, plr); giveEventReward(sock, plr);
} }
sItemBase MobManager::getReward(MobDrop* drop, MobDropChance* chance) { void MobManager::getReward(sItemBase *reward, MobDrop* drop, MobDropChance* chance) {
sItemBase reward = {}; reward->iType = 9;
reward.iType = 9; reward->iOpt = 1;
reward.iOpt = 1;
int total = 0; int total = 0;
for (int ratio : chance->cratesRatio) for (int ratio : chance->cratesRatio)
@ -249,29 +246,26 @@ sItemBase MobManager::getReward(MobDrop* drop, MobDropChance* chance) {
int i = 0; int i = 0;
int sum = 0; int sum = 0;
do { do {
reward.iID = drop->crateIDs[i]; reward->iID = drop->crateIDs[i];
sum += chance->cratesRatio[i]; sum += chance->cratesRatio[i];
i++; i++;
} }
while (sum<=randomNum); while (sum<=randomNum);
return reward;
} }
void MobManager::giveEventReward(CNSocket* sock, Player* player) { void MobManager::giveEventReward(CNSocket* sock, Player* player) {
// random drop chance // random drop chance
if (rand() % 100 > settings::EVENTCRATECHANCE) if (rand() % 100 > settings::EVENTCRATECHANCE)
return; return;
// no slot = no award // no slot = no reward
int slot = ItemManager::findFreeSlot(player); int slot = ItemManager::findFreeSlot(player);
if (slot == -1) if (slot == -1)
return; return;
const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward);
assert(resplen < CN_PACKET_BUFFER_SIZE - 8); assert(resplen < CN_PACKET_BUFFER_SIZE - 8);
// we know it's only one trailing struct, so we can skip full validation
uint8_t respbuf[resplen]; // not a variable length array, don't worry uint8_t respbuf[resplen];
sP_FE2CL_REP_REWARD_ITEM* reward = (sP_FE2CL_REP_REWARD_ITEM*)respbuf; sP_FE2CL_REP_REWARD_ITEM* reward = (sP_FE2CL_REP_REWARD_ITEM*)respbuf;
sItemReward* item = (sItemReward*)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM)); sItemReward* item = (sItemReward*)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM));
@ -315,33 +309,33 @@ void MobManager::giveEventReward(CNSocket* sock, Player* player) {
} }
int MobManager::hitMob(CNSocket *sock, Mob *mob, int damage) { int MobManager::hitMob(CNSocket *sock, Mob *mob, int damage) {
// cannot kill mobs multiple times; cannot harm retreating mobs // cannot kill mobs multiple times; cannot harm retreating mobs
if (mob->state != MobState::ROAMING && mob->state != MobState::COMBAT) { if (mob->state != MobState::ROAMING && mob->state != MobState::COMBAT) {
return 0; // no damage return 0; // no damage
} }
if (mob->state == MobState::ROAMING) { if (mob->state == MobState::ROAMING) {
assert(mob->target == nullptr); assert(mob->target == nullptr);
mob->target = sock; mob->target = sock;
mob->state = MobState::COMBAT; mob->state = MobState::COMBAT;
mob->nextMovement = getTime(); mob->nextMovement = getTime();
mob->nextAttack = 0; mob->nextAttack = 0;
mob->roamX = mob->appearanceData.iX; mob->roamX = mob->appearanceData.iX;
mob->roamY = mob->appearanceData.iY; mob->roamY = mob->appearanceData.iY;
mob->roamZ = mob->appearanceData.iZ; mob->roamZ = mob->appearanceData.iZ;
} }
mob->appearanceData.iHP -= damage; mob->appearanceData.iHP -= damage;
// wake up sleeping monster // wake up sleeping monster
// TODO: remove client-side bit somehow // TODO: remove client-side bit somehow
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ; mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
if (mob->appearanceData.iHP <= 0) if (mob->appearanceData.iHP <= 0)
killMob(mob->target, mob); killMob(mob->target, mob);
return damage; return damage;
} }
void MobManager::killMob(CNSocket *sock, Mob *mob) { void MobManager::killMob(CNSocket *sock, Mob *mob) {

View File

@ -43,7 +43,7 @@ struct Mob : public BaseNPC {
time_t nextAttack = 0; time_t nextAttack = 0;
int roamX, roamY, roamZ; int roamX, roamY, roamZ;
//drop // drop
int dropType; int dropType;
// temporary; until we're sure what's what // temporary; until we're sure what's what
@ -129,7 +129,7 @@ namespace MobManager {
int hitMob(CNSocket *sock, Mob *mob, int damage); int hitMob(CNSocket *sock, Mob *mob, int damage);
void killMob(CNSocket *sock, Mob *mob); void killMob(CNSocket *sock, Mob *mob);
void giveReward(CNSocket *sock, Mob *mob); void giveReward(CNSocket *sock, Mob *mob);
sItemBase getReward(MobDrop *drop, MobDropChance *chance); void getReward(sItemBase *reward, MobDrop *drop, MobDropChance *chance);
void giveEventReward(CNSocket* sock, Player* player); void giveEventReward(CNSocket* sock, Player* player);
std::pair<int,int> lerp(int, int, int, int, int); std::pair<int,int> lerp(int, int, int, int, int);

View File

@ -354,7 +354,9 @@ void TableData::loadDrops() {
toAdd.boosts = (int)drop["Boosts"]; toAdd.boosts = (int)drop["Boosts"];
MobManager::MobDrops[(int)drop["DropType"]] = toAdd; MobManager::MobDrops[(int)drop["DropType"]] = toAdd;
} }
std::cout << "[INFO] Loaded " << MobManager::MobDrops.size() << " Mob Drop Types"<< std::endl; std::cout << "[INFO] Loaded " << MobManager::MobDrops.size() << " Mob Drop Types"<< std::endl;
// Rarity Ratios // Rarity Ratios
nlohmann::json rarities = dropData["RarityRatios"]; nlohmann::json rarities = dropData["RarityRatios"];
for (nlohmann::json::iterator _rarity = rarities.begin(); _rarity != rarities.end(); _rarity++) { for (nlohmann::json::iterator _rarity = rarities.begin(); _rarity != rarities.end(); _rarity++) {
@ -365,6 +367,7 @@ void TableData::loadDrops() {
} }
ItemManager::RarityRatios[(int)rarity["Type"]] = toAdd; ItemManager::RarityRatios[(int)rarity["Type"]] = toAdd;
} }
// Crates // Crates
nlohmann::json crates = dropData["Crates"]; nlohmann::json crates = dropData["Crates"];
for (nlohmann::json::iterator _crate = crates.begin(); _crate != crates.end(); _crate++) { for (nlohmann::json::iterator _crate = crates.begin(); _crate != crates.end(); _crate++) {
@ -376,6 +379,7 @@ void TableData::loadDrops() {
} }
ItemManager::Crates[(int)crate["Id"]] = toAdd; ItemManager::Crates[(int)crate["Id"]] = toAdd;
} }
// Crate Items // Crate Items
nlohmann::json items = dropData["Items"]; nlohmann::json items = dropData["Items"];
int itemCount = 0; int itemCount = 0;
@ -383,27 +387,29 @@ void TableData::loadDrops() {
auto item = _item.value(); auto item = _item.value();
std::pair<int32_t, int32_t> itemSetkey = std::make_pair((int)item["ItemSet"], (int)item["Rarity"]); std::pair<int32_t, int32_t> itemSetkey = std::make_pair((int)item["ItemSet"], (int)item["Rarity"]);
std::pair<int32_t, int32_t> itemDataKey = std::make_pair((int)item["Id"], (int)item["Type"]); std::pair<int32_t, int32_t> itemDataKey = std::make_pair((int)item["Id"], (int)item["Type"]);
if (ItemManager::ItemData.find(itemDataKey) == ItemManager::ItemData.end()) if (ItemManager::ItemData.find(itemDataKey) == ItemManager::ItemData.end())
{ {
char buff[255]; char buff[255];
sprintf(buff, "Unknown item with Id %d and Type %d", (int)item["Id"], (int)item["Type"]); sprintf(buff, "Unknown item with Id %d and Type %d", (int)item["Id"], (int)item["Type"]);
throw TableException(std::string(buff)); throw TableException(std::string(buff));
} }
std::map<std::pair<int32_t, int32_t>, Item>::iterator toAdd = ItemManager::ItemData.find(itemDataKey); std::map<std::pair<int32_t, int32_t>, Item>::iterator toAdd = ItemManager::ItemData.find(itemDataKey);
// if item collection doesn't exist, start a new one // if item collection doesn't exist, start a new one
if (ItemManager::CrateItems.find(itemSetkey) == ItemManager::CrateItems.end()) { if (ItemManager::CrateItems.find(itemSetkey) == ItemManager::CrateItems.end()) {
std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator> vector; std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator> vector;
vector.push_back(toAdd); vector.push_back(toAdd);
ItemManager::CrateItems[itemSetkey] = vector; ItemManager::CrateItems[itemSetkey] = vector;
} } else // else add a new element to existing collection
// else add a new element to existing collection
else
ItemManager::CrateItems[itemSetkey].push_back(toAdd); ItemManager::CrateItems[itemSetkey].push_back(toAdd);
itemCount++; itemCount++;
} }
std::cout << "[INFO] Loaded " << ItemManager::Crates.size() << " Crates containing " std::cout << "[INFO] Loaded " << ItemManager::Crates.size() << " Crates containing "
<<itemCount<<" items" << std::endl; << itemCount << " items" << std::endl;
} }
catch (const std::exception& err) { catch (const std::exception& err) {

View File

@ -103,11 +103,15 @@ int main() {
GroupManager::init(); GroupManager::init();
Database::open(); Database::open();
switch (settings::EVENTMODE) switch (settings::EVENTMODE) {
{ case 0: break; // no event
case 1: std::cout << "[INFO] Event active. Hey, Hey It's Knishmas!" << std::endl; break; case 1: std::cout << "[INFO] Event active. Hey, Hey It's Knishmas!" << std::endl; break;
case 2: std::cout << "[INFO] Event active. Wishing you a spook-tacular Halloween!" << std::endl; break; case 2: std::cout << "[INFO] Event active. Wishing you a spook-tacular Halloween!" << std::endl; break;
case 3: std::cout << "[INFO] Event active. Have a very hoppy Easter!" << std::endl; break; case 3: std::cout << "[INFO] Event active. Have a very hoppy Easter!" << std::endl; break;
default:
std::cout << "[FATAL] Unknown event set in config file." << std::endl;
terminate(0);
/* not reached */
} }
std::cout << "[INFO] Starting Server Threads..." << std::endl; std::cout << "[INFO] Starting Server Threads..." << std::endl;

2
tdata

@ -1 +1 @@
Subproject commit b9a74bd8145f093b7fa8aef8b74191ac672d3dd2 Subproject commit ab1dd0e4398a5b96a9449032aafaaf4e24800283