mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 05:20:05 +00:00
altered event drop logic, fixed taro/fm logic
This commit is contained in:
parent
44fd66b511
commit
4eaf3b2f08
@ -225,15 +225,12 @@ void Combat::killMob(CNSocket *sock, Mob *mob) {
|
|||||||
if (sock != nullptr) {
|
if (sock != nullptr) {
|
||||||
Player* plr = PlayerManager::getPlayer(sock);
|
Player* plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
int rolledBoosts = Rand::rand();
|
Items::DropRoll rolled;
|
||||||
int rolledPotions = Rand::rand();
|
Items::DropRoll eventRolled;
|
||||||
int rolledCrate = Rand::rand();
|
|
||||||
int rolledCrateType = Rand::rand();
|
|
||||||
int rolledEvent = Rand::rand();
|
|
||||||
int rolledQItem = Rand::rand();
|
int rolledQItem = Rand::rand();
|
||||||
|
|
||||||
if (plr->groupCnt == 1 && plr->iIDGroup == plr->iID) {
|
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);
|
Missions::mobKilled(sock, mob->appearanceData.iNPCType, rolledQItem);
|
||||||
} else {
|
} else {
|
||||||
Player* otherPlayer = PlayerManager::getPlayerFromID(plr->iIDGroup);
|
Player* otherPlayer = PlayerManager::getPlayerFromID(plr->iIDGroup);
|
||||||
@ -253,7 +250,7 @@ void Combat::killMob(CNSocket *sock, Mob *mob) {
|
|||||||
if (dist > 5000)
|
if (dist > 5000)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Items::giveMobDrop(sockTo, mob, rolledBoosts, rolledPotions, rolledCrate, rolledCrateType, rolledEvent);
|
Items::giveMobDrop(sockTo, mob, rolled, eventRolled);
|
||||||
Missions::mobKilled(sockTo, mob->appearanceData.iNPCType, rolledQItem);
|
Missions::mobKilled(sockTo, mob->appearanceData.iNPCType, rolledQItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
153
src/Items.cpp
153
src/Items.cpp
@ -26,6 +26,7 @@ std::map<int32_t, std::vector<int32_t>> Items::CrateDropTypes;
|
|||||||
std::map<int32_t, MiscDropChance> Items::MiscDropChances;
|
std::map<int32_t, MiscDropChance> Items::MiscDropChances;
|
||||||
std::map<int32_t, MiscDropType> Items::MiscDropTypes;
|
std::map<int32_t, MiscDropType> Items::MiscDropTypes;
|
||||||
std::map<int32_t, MobDrop> Items::MobDrops;
|
std::map<int32_t, MobDrop> Items::MobDrops;
|
||||||
|
std::map<int32_t, int32_t> Items::EventToDropMap;
|
||||||
std::map<int32_t, int32_t> Items::MobToDropMap;
|
std::map<int32_t, int32_t> Items::MobToDropMap;
|
||||||
std::map<int32_t, ItemSet> Items::ItemSets;
|
std::map<int32_t, ItemSet> Items::ItemSets;
|
||||||
|
|
||||||
@ -700,63 +701,7 @@ static void getMobDrop(sItemBase* reward, const std::vector<int>& weights, const
|
|||||||
reward->iID = crateIds[chosenIndex];
|
reward->iID = crateIds[chosenIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void giveEventDrop(CNSocket* sock, Player* player, int rolled) {
|
static void giveSingleDrop(CNSocket *sock, Mob* mob, int mobDropId, const DropRoll& 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) {
|
|
||||||
Player *plr = PlayerManager::getPlayer(sock);
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward);
|
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);
|
memset(respbuf, 0, resplen);
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if (Items::MobToDropMap.find(mob->appearanceData.iNPCType) == Items::MobToDropMap.end()) {
|
if (Items::MobDrops.find(mobDropId) == Items::MobDrops.end()) {
|
||||||
std::cout << "[WARN] Mob ID " << mob->appearanceData.iNPCType << " has no drops assigned" << std::endl;
|
std::cout << "[WARN] Drop Type " << mobDropId << " was not found" << 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;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// find correct mob drop
|
// find correct mob drop
|
||||||
MobDrop& drop = Items::MobDrops[dropType];
|
MobDrop& drop = Items::MobDrops[mobDropId];
|
||||||
|
|
||||||
// use the keys to fetch data from other maps
|
// use the keys to fetch data from other maps
|
||||||
// sanity check
|
// sanity check
|
||||||
@ -815,33 +752,37 @@ void Items::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPo
|
|||||||
}
|
}
|
||||||
MiscDropType& miscDropType = Items::MiscDropTypes[drop.miscDropTypeId];
|
MiscDropType& miscDropType = Items::MiscDropTypes[drop.miscDropTypeId];
|
||||||
|
|
||||||
plr->money += miscDropType.taroAmount;
|
if (rolled.taros % miscDropChance.taroDropChanceTotal < miscDropChance.taroDropChance) {
|
||||||
// money nano boost
|
plr->money += miscDropType.taroAmount;
|
||||||
if (plr->iConditionBitFlag & CSB_BIT_REWARD_CASH) {
|
// money nano boost
|
||||||
int boost = 0;
|
if (plr->iConditionBitFlag & CSB_BIT_REWARD_CASH) {
|
||||||
if (Nanos::getNanoBoost(plr)) // for gumballs
|
int boost = 0;
|
||||||
boost = 1;
|
if (Nanos::getNanoBoost(plr)) // for gumballs
|
||||||
plr->money += miscDropType.taroAmount * (5 + boost) / 25;
|
boost = 1;
|
||||||
|
plr->money += miscDropType.taroAmount * (5 + boost) / 25;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// formula for scaling FM with player/mob level difference
|
if (rolled.fm % miscDropChance.fmDropChanceTotal < miscDropChance.fmDropChance) {
|
||||||
// TODO: adjust this better
|
// formula for scaling FM with player/mob level difference
|
||||||
int levelDifference = plr->level - mob->level;
|
// TODO: adjust this better
|
||||||
int fm = miscDropType.fmAmount;
|
int levelDifference = plr->level - mob->level;
|
||||||
if (levelDifference > 0)
|
int fm = miscDropType.fmAmount;
|
||||||
fm = levelDifference < 10 ? fm - (levelDifference * fm / 10) : 0;
|
if (levelDifference > 0)
|
||||||
// scavenger nano boost
|
fm = levelDifference < 10 ? fm - (levelDifference * fm / 10) : 0;
|
||||||
if (plr->iConditionBitFlag & CSB_BIT_REWARD_BLOB) {
|
// scavenger nano boost
|
||||||
int boost = 0;
|
if (plr->iConditionBitFlag & CSB_BIT_REWARD_BLOB) {
|
||||||
if (Nanos::getNanoBoost(plr)) // for gumballs
|
int boost = 0;
|
||||||
boost = 1;
|
if (Nanos::getNanoBoost(plr)) // for gumballs
|
||||||
fm += fm * (5 + boost) / 25;
|
boost = 1;
|
||||||
|
fm += fm * (5 + boost) / 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
Missions::updateFusionMatter(sock, fm);
|
||||||
}
|
}
|
||||||
|
|
||||||
Missions::updateFusionMatter(sock, fm);
|
if (rolled.potions % miscDropChance.potionDropChanceTotal < miscDropChance.potionDropChance)
|
||||||
|
|
||||||
if (rolledPotions % miscDropChance.potionDropChanceTotal < miscDropChance.potionDropChance)
|
|
||||||
plr->batteryN += miscDropType.potionAmount;
|
plr->batteryN += miscDropType.potionAmount;
|
||||||
if (rolledBoosts % miscDropChance.boostDropChanceTotal < miscDropChance.boostDropChance)
|
if (rolled.boosts % miscDropChance.boostDropChanceTotal < miscDropChance.boostDropChance)
|
||||||
plr->batteryW += miscDropType.boostAmount;
|
plr->batteryW += miscDropType.boostAmount;
|
||||||
|
|
||||||
// caps
|
// caps
|
||||||
@ -862,13 +803,13 @@ void Items::giveMobDrop(CNSocket *sock, Mob* mob, int rolledBoosts, int rolledPo
|
|||||||
int slot = findFreeSlot(plr);
|
int slot = findFreeSlot(plr);
|
||||||
|
|
||||||
// no drop
|
// 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
|
// 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
|
||||||
getMobDrop(&item->sItem, crateDropChance.crateTypeDropWeights, crateDropType, rolledCrateType);
|
getMobDrop(&item->sItem, crateDropChance.crateTypeDropWeights, crateDropType, rolled.crateType);
|
||||||
item->iSlotNum = slot;
|
item->iSlotNum = slot;
|
||||||
item->eIL = 1; // Inventory Location. 1 means player inventory.
|
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);
|
sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// event crates
|
void Items::giveMobDrop(CNSocket *sock, Mob* mob, const DropRoll& rolled, const DropRoll& eventRolled) {
|
||||||
if (settings::EVENTMODE != 0)
|
// sanity check
|
||||||
giveEventDrop(sock, plr, rolledEvent);
|
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() {
|
void Items::init() {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "servers/CNShardServer.hpp"
|
#include "servers/CNShardServer.hpp"
|
||||||
#include "Player.hpp"
|
#include "Player.hpp"
|
||||||
#include "MobAI.hpp"
|
#include "MobAI.hpp"
|
||||||
|
#include "Rand.hpp"
|
||||||
|
|
||||||
struct CrocPotEntry {
|
struct CrocPotEntry {
|
||||||
int multStats, multLooks;
|
int multStats, multLooks;
|
||||||
@ -80,6 +81,13 @@ namespace Items {
|
|||||||
int weaponType;
|
int weaponType;
|
||||||
// TODO: implement more as needed
|
// 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
|
// 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, CrocPotEntry> CrocPotTable; // level gap -> entry
|
extern std::map<int32_t, CrocPotEntry> CrocPotTable; // level gap -> entry
|
||||||
@ -94,13 +102,14 @@ namespace Items {
|
|||||||
extern std::map<int32_t, MiscDropChance> MiscDropChances;
|
extern std::map<int32_t, MiscDropChance> MiscDropChances;
|
||||||
extern std::map<int32_t, MiscDropType> MiscDropTypes;
|
extern std::map<int32_t, MiscDropType> MiscDropTypes;
|
||||||
extern std::map<int32_t, MobDrop> MobDrops;
|
extern std::map<int32_t, MobDrop> MobDrops;
|
||||||
|
extern std::map<int32_t, int32_t> EventToDropMap;
|
||||||
extern std::map<int32_t, int32_t> MobToDropMap;
|
extern std::map<int32_t, int32_t> MobToDropMap;
|
||||||
extern std::map<int32_t, ItemSet> ItemSets;
|
extern std::map<int32_t, ItemSet> ItemSets;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
// mob drops
|
// 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);
|
int findFreeSlot(Player *plr);
|
||||||
Item* getItemData(int32_t id, int32_t type);
|
Item* getItemData(int32_t id, int32_t type);
|
||||||
|
@ -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
|
// Mobs
|
||||||
nlohmann::json mobs = dropData["Mobs"];
|
nlohmann::json mobs = dropData["Mobs"];
|
||||||
for (nlohmann::json::iterator _mob = mobs.begin(); _mob != mobs.end(); _mob++) {
|
for (nlohmann::json::iterator _mob = mobs.begin(); _mob != mobs.end(); _mob++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user