mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 13:30:06 +00:00
[refactor] Move mob drop logic from Combat to ItemManager
This commit is contained in:
parent
c5776b9322
commit
2017b38e23
185
src/Combat.cpp
185
src/Combat.cpp
@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
std::map<int32_t, MobDropChance> Combat::MobDropChances;
|
|
||||||
std::map<int32_t, MobDrop> Combat::MobDrops;
|
|
||||||
/// Player Id -> Bullet Id -> Bullet
|
/// Player Id -> Bullet Id -> Bullet
|
||||||
std::map<int32_t, std::map<int8_t, Bullet>> Combat::Bullets;
|
std::map<int32_t, std::map<int8_t, Bullet>> Combat::Bullets;
|
||||||
|
|
||||||
@ -161,185 +159,6 @@ void Combat::npcAttackPc(Mob *mob, time_t currTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Combat::giveReward(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPotions,
|
|
||||||
int rolledCrate, int rolledCrateType, int rolledEvent) {
|
|
||||||
Player *plr = PlayerManager::getPlayer(sock);
|
|
||||||
|
|
||||||
const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward);
|
|
||||||
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
|
|
||||||
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);
|
|
||||||
|
|
||||||
// sanity check
|
|
||||||
if (MobDrops.find(mob->dropType) == MobDrops.end()) {
|
|
||||||
std::cout << "[WARN] Drop Type " << mob->dropType << " was not found" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// find correct mob drop
|
|
||||||
MobDrop& drop = MobDrops[mob->dropType];
|
|
||||||
|
|
||||||
plr->money += drop.taros;
|
|
||||||
// money nano boost
|
|
||||||
if (plr->iConditionBitFlag & CSB_BIT_REWARD_CASH) {
|
|
||||||
int boost = 0;
|
|
||||||
if (NanoManager::getNanoBoost(plr)) // for gumballs
|
|
||||||
boost = 1;
|
|
||||||
plr->money += drop.taros * (5 + boost) / 25;
|
|
||||||
}
|
|
||||||
// formula for scaling FM with player/mob level difference
|
|
||||||
// TODO: adjust this better
|
|
||||||
int levelDifference = plr->level - mob->level;
|
|
||||||
int fm = drop.fm;
|
|
||||||
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 (NanoManager::getNanoBoost(plr)) // for gumballs
|
|
||||||
boost = 1;
|
|
||||||
fm += fm * (5 + boost) / 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
MissionManager::updateFusionMatter(sock, fm);
|
|
||||||
|
|
||||||
// give boosts 1 in 3 times
|
|
||||||
if (drop.boosts > 0) {
|
|
||||||
if (rolledPotions % 3 == 0)
|
|
||||||
plr->batteryN += drop.boosts;
|
|
||||||
if (rolledBoosts % 3 == 0)
|
|
||||||
plr->batteryW += drop.boosts;
|
|
||||||
}
|
|
||||||
// caps
|
|
||||||
if (plr->batteryW > 9999)
|
|
||||||
plr->batteryW = 9999;
|
|
||||||
if (plr->batteryN > 9999)
|
|
||||||
plr->batteryN = 9999;
|
|
||||||
|
|
||||||
// simple rewards
|
|
||||||
reward->m_iCandy = plr->money;
|
|
||||||
reward->m_iFusionMatter = plr->fusionmatter;
|
|
||||||
reward->m_iBatteryN = plr->batteryN;
|
|
||||||
reward->m_iBatteryW = plr->batteryW;
|
|
||||||
reward->iFatigue = 100; // prevents warning message
|
|
||||||
reward->iFatigue_Level = 1;
|
|
||||||
reward->iItemCnt = 1; // remember to update resplen if you change this
|
|
||||||
|
|
||||||
int slot = ItemManager::findFreeSlot(plr);
|
|
||||||
|
|
||||||
bool awardDrop = false;
|
|
||||||
MobDropChance *chance = nullptr;
|
|
||||||
// sanity check
|
|
||||||
if (MobDropChances.find(drop.dropChanceType) == MobDropChances.end()) {
|
|
||||||
std::cout << "[WARN] Unknown Drop Chance Type: " << drop.dropChanceType << std::endl;
|
|
||||||
return; // this also prevents holiday crate drops, but oh well
|
|
||||||
} else {
|
|
||||||
chance = &MobDropChances[drop.dropChanceType];
|
|
||||||
awardDrop = (rolledCrate % 1000 < chance->dropChance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// no drop
|
|
||||||
if (slot == -1 || !awardDrop) {
|
|
||||||
// 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
|
|
||||||
getReward(&item->sItem, &drop, chance, rolledCrateType);
|
|
||||||
item->iSlotNum = slot;
|
|
||||||
item->eIL = 1; // Inventory Location. 1 means player inventory.
|
|
||||||
|
|
||||||
// update player
|
|
||||||
plr->Inven[slot] = item->sItem;
|
|
||||||
|
|
||||||
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// event crates
|
|
||||||
if (settings::EVENTMODE != 0)
|
|
||||||
giveEventReward(sock, plr, rolledEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Combat::getReward(sItemBase *reward, MobDrop* drop, MobDropChance* chance, int rolled) {
|
|
||||||
reward->iType = 9;
|
|
||||||
reward->iOpt = 1;
|
|
||||||
|
|
||||||
int total = 0;
|
|
||||||
for (int ratio : chance->cratesRatio)
|
|
||||||
total += ratio;
|
|
||||||
|
|
||||||
// randomizing a crate
|
|
||||||
int randomNum = rolled % total;
|
|
||||||
int i = 0;
|
|
||||||
int sum = 0;
|
|
||||||
do {
|
|
||||||
reward->iID = drop->crateIDs[i];
|
|
||||||
sum += chance->cratesRatio[i];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
while (sum<=randomNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Combat::giveEventReward(CNSocket* sock, Player* player, int rolled) {
|
|
||||||
// random drop chance
|
|
||||||
if (rand() % 100 > settings::EVENTCRATECHANCE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// no slot = no reward
|
|
||||||
int slot = ItemManager::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);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Combat::hitMob(CNSocket *sock, Mob *mob, int damage) {
|
int Combat::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) {
|
||||||
@ -396,7 +215,7 @@ void Combat::killMob(CNSocket *sock, Mob *mob) {
|
|||||||
int rolledQItem = rand();
|
int rolledQItem = rand();
|
||||||
|
|
||||||
if (plr->groupCnt == 1 && plr->iIDGroup == plr->iID) {
|
if (plr->groupCnt == 1 && plr->iIDGroup == plr->iID) {
|
||||||
giveReward(sock, mob, rolledBoosts, rolledPotions, rolledCrate, rolledCrateType, rolledEvent);
|
ItemManager::giveMobDrop(sock, mob, rolledBoosts, rolledPotions, rolledCrate, rolledCrateType, rolledEvent);
|
||||||
MissionManager::mobKilled(sock, mob->appearanceData.iNPCType, rolledQItem);
|
MissionManager::mobKilled(sock, mob->appearanceData.iNPCType, rolledQItem);
|
||||||
} else {
|
} else {
|
||||||
Player* otherPlayer = PlayerManager::getPlayerFromID(plr->iIDGroup);
|
Player* otherPlayer = PlayerManager::getPlayerFromID(plr->iIDGroup);
|
||||||
@ -416,7 +235,7 @@ void Combat::killMob(CNSocket *sock, Mob *mob) {
|
|||||||
if (dist > 5000)
|
if (dist > 5000)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
giveReward(sockTo, mob, rolledBoosts, rolledPotions, rolledCrate, rolledCrateType, rolledEvent);
|
ItemManager::giveMobDrop(sockTo, mob, rolledBoosts, rolledPotions, rolledCrate, rolledCrateType, rolledEvent);
|
||||||
MissionManager::mobKilled(sockTo, mob->appearanceData.iNPCType, rolledQItem);
|
MissionManager::mobKilled(sockTo, mob->appearanceData.iNPCType, rolledQItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,19 +12,6 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
struct MobDropChance {
|
|
||||||
int dropChance;
|
|
||||||
std::vector<int> cratesRatio;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MobDrop {
|
|
||||||
std::vector<int> crateIDs;
|
|
||||||
int dropChanceType;
|
|
||||||
int taros;
|
|
||||||
int fm;
|
|
||||||
int boosts;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Bullet {
|
struct Bullet {
|
||||||
int pointDamage;
|
int pointDamage;
|
||||||
int groupDamage;
|
int groupDamage;
|
||||||
@ -33,8 +20,6 @@ struct Bullet {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace Combat {
|
namespace Combat {
|
||||||
extern std::map<int32_t, MobDropChance> MobDropChances;
|
|
||||||
extern std::map<int32_t, MobDrop> MobDrops;
|
|
||||||
extern std::map<int32_t, std::map<int8_t, Bullet>> Bullets;
|
extern std::map<int32_t, std::map<int8_t, Bullet>> Bullets;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
@ -49,9 +34,6 @@ namespace Combat {
|
|||||||
void npcAttackPc(Mob *mob, time_t currTime);
|
void npcAttackPc(Mob *mob, time_t currTime);
|
||||||
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, int rolledBoosts, int rolledPotions, int rolledCrate, int rolledCrateType, int rolledEvent);
|
|
||||||
void getReward(sItemBase *reward, MobDrop *drop, MobDropChance *chance, int rolled);
|
|
||||||
void giveEventReward(CNSocket* sock, Player* player, int rolled);
|
|
||||||
|
|
||||||
std::pair<int,int> lerp(int, int, int, int, int);
|
std::pair<int,int> lerp(int, int, int, int, int);
|
||||||
std::pair<int,int> getDamage(int, int, bool, bool, int, int, int);
|
std::pair<int,int> getDamage(int, int, bool, bool, int, int, int);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "NPCManager.hpp"
|
#include "NPCManager.hpp"
|
||||||
#include "Player.hpp"
|
#include "Player.hpp"
|
||||||
#include "Abilities.hpp"
|
#include "Abilities.hpp"
|
||||||
|
#include "MissionManager.hpp"
|
||||||
|
|
||||||
#include <string.h> // for memset()
|
#include <string.h> // for memset()
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -18,6 +19,9 @@ std::map<int32_t, Crate> ItemManager::Crates;
|
|||||||
std::map<std::pair<int32_t, int32_t>, std::vector<std::map<std::pair<int32_t, int32_t>, ItemManager::Item>::iterator>> ItemManager::CrateItems;
|
std::map<std::pair<int32_t, int32_t>, std::vector<std::map<std::pair<int32_t, int32_t>, ItemManager::Item>::iterator>> ItemManager::CrateItems;
|
||||||
std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> ItemManager::CodeItems;
|
std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> ItemManager::CodeItems;
|
||||||
|
|
||||||
|
std::map<int32_t, MobDropChance> ItemManager::MobDropChances;
|
||||||
|
std::map<int32_t, MobDrop> ItemManager::MobDrops;
|
||||||
|
|
||||||
#ifdef ACADEMY
|
#ifdef ACADEMY
|
||||||
std::map<int32_t, int32_t> ItemManager::NanoCapsules; // crate id -> nano id
|
std::map<int32_t, int32_t> ItemManager::NanoCapsules; // crate id -> nano id
|
||||||
|
|
||||||
@ -709,6 +713,185 @@ void ItemManager::updateEquips(CNSocket* sock, Player* plr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemManager::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPotions,
|
||||||
|
int rolledCrate, int rolledCrateType, int rolledEvent) {
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward);
|
||||||
|
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
|
||||||
|
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);
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if (MobDrops.find(mob->dropType) == MobDrops.end()) {
|
||||||
|
std::cout << "[WARN] Drop Type " << mob->dropType << " was not found" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// find correct mob drop
|
||||||
|
MobDrop& drop = MobDrops[mob->dropType];
|
||||||
|
|
||||||
|
plr->money += drop.taros;
|
||||||
|
// money nano boost
|
||||||
|
if (plr->iConditionBitFlag & CSB_BIT_REWARD_CASH) {
|
||||||
|
int boost = 0;
|
||||||
|
if (NanoManager::getNanoBoost(plr)) // for gumballs
|
||||||
|
boost = 1;
|
||||||
|
plr->money += drop.taros * (5 + boost) / 25;
|
||||||
|
}
|
||||||
|
// formula for scaling FM with player/mob level difference
|
||||||
|
// TODO: adjust this better
|
||||||
|
int levelDifference = plr->level - mob->level;
|
||||||
|
int fm = drop.fm;
|
||||||
|
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 (NanoManager::getNanoBoost(plr)) // for gumballs
|
||||||
|
boost = 1;
|
||||||
|
fm += fm * (5 + boost) / 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
MissionManager::updateFusionMatter(sock, fm);
|
||||||
|
|
||||||
|
// give boosts 1 in 3 times
|
||||||
|
if (drop.boosts > 0) {
|
||||||
|
if (rolledPotions % 3 == 0)
|
||||||
|
plr->batteryN += drop.boosts;
|
||||||
|
if (rolledBoosts % 3 == 0)
|
||||||
|
plr->batteryW += drop.boosts;
|
||||||
|
}
|
||||||
|
// caps
|
||||||
|
if (plr->batteryW > 9999)
|
||||||
|
plr->batteryW = 9999;
|
||||||
|
if (plr->batteryN > 9999)
|
||||||
|
plr->batteryN = 9999;
|
||||||
|
|
||||||
|
// simple rewards
|
||||||
|
reward->m_iCandy = plr->money;
|
||||||
|
reward->m_iFusionMatter = plr->fusionmatter;
|
||||||
|
reward->m_iBatteryN = plr->batteryN;
|
||||||
|
reward->m_iBatteryW = plr->batteryW;
|
||||||
|
reward->iFatigue = 100; // prevents warning message
|
||||||
|
reward->iFatigue_Level = 1;
|
||||||
|
reward->iItemCnt = 1; // remember to update resplen if you change this
|
||||||
|
|
||||||
|
int slot = ItemManager::findFreeSlot(plr);
|
||||||
|
|
||||||
|
bool awardDrop = false;
|
||||||
|
MobDropChance *chance = nullptr;
|
||||||
|
// sanity check
|
||||||
|
if (MobDropChances.find(drop.dropChanceType) == MobDropChances.end()) {
|
||||||
|
std::cout << "[WARN] Unknown Drop Chance Type: " << drop.dropChanceType << std::endl;
|
||||||
|
return; // this also prevents holiday crate drops, but oh well
|
||||||
|
} else {
|
||||||
|
chance = &MobDropChances[drop.dropChanceType];
|
||||||
|
awardDrop = (rolledCrate % 1000 < chance->dropChance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no drop
|
||||||
|
if (slot == -1 || !awardDrop) {
|
||||||
|
// 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, &drop, chance, rolledCrateType);
|
||||||
|
item->iSlotNum = slot;
|
||||||
|
item->eIL = 1; // Inventory Location. 1 means player inventory.
|
||||||
|
|
||||||
|
// update player
|
||||||
|
plr->Inven[slot] = item->sItem;
|
||||||
|
|
||||||
|
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// event crates
|
||||||
|
if (settings::EVENTMODE != 0)
|
||||||
|
giveEventDrop(sock, plr, rolledEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemManager::getMobDrop(sItemBase *reward, MobDrop* drop, MobDropChance* chance, int rolled) {
|
||||||
|
reward->iType = 9;
|
||||||
|
reward->iOpt = 1;
|
||||||
|
|
||||||
|
int total = 0;
|
||||||
|
for (int ratio : chance->cratesRatio)
|
||||||
|
total += ratio;
|
||||||
|
|
||||||
|
// randomizing a crate
|
||||||
|
int randomNum = rolled % total;
|
||||||
|
int i = 0;
|
||||||
|
int sum = 0;
|
||||||
|
do {
|
||||||
|
reward->iID = drop->crateIDs[i];
|
||||||
|
sum += chance->cratesRatio[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (sum<=randomNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemManager::giveEventDrop(CNSocket* sock, Player* player, int rolled) {
|
||||||
|
// random drop chance
|
||||||
|
if (rand() % 100 > settings::EVENTCRATECHANCE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// no slot = no reward
|
||||||
|
int slot = ItemManager::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 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);
|
||||||
|
@ -2,16 +2,31 @@
|
|||||||
|
|
||||||
#include "CNShardServer.hpp"
|
#include "CNShardServer.hpp"
|
||||||
#include "Player.hpp"
|
#include "Player.hpp"
|
||||||
|
#include "MobAI.hpp"
|
||||||
|
|
||||||
struct CrocPotEntry {
|
struct CrocPotEntry {
|
||||||
int multStats, multLooks;
|
int multStats, multLooks;
|
||||||
float base, rd0, rd1, rd2, rd3;
|
float base, rd0, rd1, rd2, rd3;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Crate {
|
struct Crate {
|
||||||
int rarityRatioId;
|
int rarityRatioId;
|
||||||
std::vector<int> itemSets;
|
std::vector<int> itemSets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MobDropChance {
|
||||||
|
int dropChance;
|
||||||
|
std::vector<int> cratesRatio;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MobDrop {
|
||||||
|
std::vector<int> crateIDs;
|
||||||
|
int dropChanceType;
|
||||||
|
int taros;
|
||||||
|
int fm;
|
||||||
|
int boosts;
|
||||||
|
};
|
||||||
|
|
||||||
namespace ItemManager {
|
namespace ItemManager {
|
||||||
enum class SlotType {
|
enum class SlotType {
|
||||||
EQUIP = 0,
|
EQUIP = 0,
|
||||||
@ -36,6 +51,10 @@ namespace ItemManager {
|
|||||||
std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator>> CrateItems;
|
std::vector<std::map<std::pair<int32_t, int32_t>, Item>::iterator>> CrateItems;
|
||||||
extern std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> CodeItems; // code -> vector of <id, type>
|
extern std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> CodeItems; // code -> vector of <id, type>
|
||||||
|
|
||||||
|
// mob drops
|
||||||
|
extern std::map<int32_t, MobDropChance> MobDropChances;
|
||||||
|
extern std::map<int32_t, MobDrop> MobDrops;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
// crate opening logic with all helper functions
|
// crate opening logic with all helper functions
|
||||||
@ -43,6 +62,11 @@ namespace ItemManager {
|
|||||||
int getRarity(Crate& crate, int itemSetId);
|
int getRarity(Crate& crate, int itemSetId);
|
||||||
int getCrateItem(sItemBase& reward, int itemSetId, int rarity, int playerGender);
|
int getCrateItem(sItemBase& reward, int itemSetId, int rarity, int playerGender);
|
||||||
|
|
||||||
|
// mob drops
|
||||||
|
void giveMobDrop(CNSocket *sock, Mob *mob, int rolledBoosts, int rolledPotions, int rolledCrate, int rolledCrateType, int rolledEvent);
|
||||||
|
void getMobDrop(sItemBase *reward, MobDrop *drop, MobDropChance *chance, int rolled);
|
||||||
|
void giveEventDrop(CNSocket* sock, Player* player, int rolled);
|
||||||
|
|
||||||
int findFreeSlot(Player *plr);
|
int findFreeSlot(Player *plr);
|
||||||
Item* getItemData(int32_t id, int32_t type);
|
Item* getItemData(int32_t id, int32_t type);
|
||||||
void checkItemExpire(CNSocket* sock, Player* player);
|
void checkItemExpire(CNSocket* sock, Player* player);
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "ItemManager.hpp"
|
#include "ItemManager.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "MissionManager.hpp"
|
#include "MissionManager.hpp"
|
||||||
#include "Combat.hpp"
|
|
||||||
#include "ChunkManager.hpp"
|
#include "ChunkManager.hpp"
|
||||||
#include "NanoManager.hpp"
|
#include "NanoManager.hpp"
|
||||||
#include "RacingManager.hpp"
|
#include "RacingManager.hpp"
|
||||||
@ -518,7 +517,7 @@ void TableData::loadDrops() {
|
|||||||
for (nlohmann::json::iterator _cratesRatio = dropChance["CratesRatio"].begin(); _cratesRatio != dropChance["CratesRatio"].end(); _cratesRatio++) {
|
for (nlohmann::json::iterator _cratesRatio = dropChance["CratesRatio"].begin(); _cratesRatio != dropChance["CratesRatio"].end(); _cratesRatio++) {
|
||||||
toAdd.cratesRatio.push_back((int)_cratesRatio.value());
|
toAdd.cratesRatio.push_back((int)_cratesRatio.value());
|
||||||
}
|
}
|
||||||
Combat::MobDropChances[(int)dropChance["Type"]] = toAdd;
|
ItemManager::MobDropChances[(int)dropChance["Type"]] = toAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MobDrops
|
// MobDrops
|
||||||
@ -532,21 +531,21 @@ void TableData::loadDrops() {
|
|||||||
|
|
||||||
toAdd.dropChanceType = (int)drop["DropChance"];
|
toAdd.dropChanceType = (int)drop["DropChance"];
|
||||||
// Check if DropChance exists
|
// Check if DropChance exists
|
||||||
if (Combat::MobDropChances.find(toAdd.dropChanceType) == Combat::MobDropChances.end()) {
|
if (ItemManager::MobDropChances.find(toAdd.dropChanceType) == ItemManager::MobDropChances.end()) {
|
||||||
throw TableException(" MobDropChance not found: " + std::to_string((toAdd.dropChanceType)));
|
throw TableException(" MobDropChance not found: " + std::to_string((toAdd.dropChanceType)));
|
||||||
}
|
}
|
||||||
// Check if number of crates is correct
|
// Check if number of crates is correct
|
||||||
if (!(Combat::MobDropChances[(int)drop["DropChance"]].cratesRatio.size() == toAdd.crateIDs.size())) {
|
if (!(ItemManager::MobDropChances[(int)drop["DropChance"]].cratesRatio.size() == toAdd.crateIDs.size())) {
|
||||||
throw TableException(" DropType " + std::to_string((int)drop["DropType"]) + " contains invalid number of crates");
|
throw TableException(" DropType " + std::to_string((int)drop["DropType"]) + " contains invalid number of crates");
|
||||||
}
|
}
|
||||||
|
|
||||||
toAdd.taros = (int)drop["Taros"];
|
toAdd.taros = (int)drop["Taros"];
|
||||||
toAdd.fm = (int)drop["FM"];
|
toAdd.fm = (int)drop["FM"];
|
||||||
toAdd.boosts = (int)drop["Boosts"];
|
toAdd.boosts = (int)drop["Boosts"];
|
||||||
Combat::MobDrops[(int)drop["DropType"]] = toAdd;
|
ItemManager::MobDrops[(int)drop["DropType"]] = toAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "[INFO] Loaded " << Combat::MobDrops.size() << " Mob Drop Types"<< std::endl;
|
std::cout << "[INFO] Loaded " << ItemManager::MobDrops.size() << " Mob Drop Types"<< std::endl;
|
||||||
|
|
||||||
// Rarity Ratios
|
// Rarity Ratios
|
||||||
nlohmann::json rarities = dropData["RarityRatios"];
|
nlohmann::json rarities = dropData["RarityRatios"];
|
||||||
|
Loading…
Reference in New Issue
Block a user