1418 lines
36 KiB
C++
1418 lines
36 KiB
C++
#include "stdafx.h"
|
|
#include "../shared/DateTime.h"
|
|
#include "DBAgent.h"
|
|
#include "KingSystem.h"
|
|
#include "Map.h"
|
|
#include <cmath>
|
|
|
|
// Some item ID definitions
|
|
#define MIN_ITEM_ID 100000000
|
|
#define MAX_ITEM_ID 999999999
|
|
|
|
#define MAGE_EARRING 310310004
|
|
#define WARRIOR_EARRING 310310005
|
|
#define ROGUE_EARRING 310310006
|
|
#define PRIEST_EARRING 310310007
|
|
|
|
#define UPGRADE_RUBY_EARRING_MIN 310110005
|
|
#define UPGRADE_RUBY_EARRING_MAX 310110007
|
|
|
|
#define UPGRADE_PEARL_EARRING_MIN 310150005
|
|
#define UPGRADE_PEARL_EARRING_MAX 310150007
|
|
|
|
#define SHADOW_PIECE 700009000
|
|
#define TRINA_PIECE 700002000
|
|
#define KRAVDIS_PIECE 379258000
|
|
|
|
/**
|
|
* @brief Packet handler for the assorted systems that
|
|
* were deemed to come under the 'upgrade' system.
|
|
*
|
|
* @param pkt The packet.
|
|
*/
|
|
void CUser::ItemUpgradeProcess(Packet & pkt)
|
|
{
|
|
if (isDead()
|
|
|| isTrading()
|
|
|| isMerchanting()
|
|
|| isSellingMerchant()
|
|
|| isBuyingMerchant()
|
|
|| isStoreOpen()
|
|
|| isMining()
|
|
|| m_bMerchantStatex)
|
|
return;
|
|
|
|
uint8 opcode = pkt.read<uint8>();
|
|
|
|
switch (opcode)
|
|
{
|
|
case ITEM_UPGRADE:
|
|
ItemUpgrade(pkt);
|
|
break;
|
|
|
|
case ITEM_ACCESSORIES:
|
|
ItemUpgradeAccessories(pkt);
|
|
break;
|
|
|
|
case ITEM_BIFROST_EXCHANGE:
|
|
BifrostPieceProcess(pkt);
|
|
break;
|
|
|
|
case ITEM_PET:
|
|
ItemUpgradePet(pkt);
|
|
break;
|
|
|
|
case ITEM_UPGRADE_REBIRTH:
|
|
ItemUpgradeRebirth(pkt);
|
|
break;
|
|
|
|
case ITEM_SEAL:
|
|
ItemSealProcess(pkt);
|
|
break;
|
|
|
|
case ITEM_CHARACTER_SEAL:
|
|
CharacterSealProcess(pkt);
|
|
break;
|
|
|
|
case ITEM_SPECIAL_EXCHANGE:
|
|
SpecialItemExchange(pkt);
|
|
break;
|
|
|
|
case ITEM_DISASSEMBLING:
|
|
ItemDisassembling(pkt);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Packet handler for the standard item upgrade system.
|
|
*
|
|
* @param pkt The packet.
|
|
*/
|
|
void CUser::ItemUpgrade(Packet & pkt, uint8 nUpgradeType)
|
|
{
|
|
bool Follow = false;
|
|
enum UpgradeErrorCodes
|
|
{
|
|
UpgradeFailed = 0,
|
|
UpgradeSucceeded = 1,
|
|
UpgradeTrading = 2,
|
|
UpgradeNeedCoins = 3,
|
|
UpgradeNoMatch = 4,
|
|
UpgradeRental = 5
|
|
};
|
|
|
|
enum UpgradeType { UpgradeTypeNormal = 1, UpgradeTypePreview = 2 };
|
|
|
|
Packet result(WIZ_ITEM_UPGRADE, nUpgradeType);
|
|
_ITEM_DATA * pOriginItem;
|
|
_ITEM_TABLE * proto;
|
|
int32 nItemID[10]; int8 bPos[10];
|
|
uint16 sNpcID;
|
|
int8 bType = UpgradeTypeNormal, bResult = UpgradeNoMatch,ItemClass = 0;
|
|
bool Trina = false, Karivdis = false, Accessories = false;
|
|
DateTime time;
|
|
|
|
if (isDead() || isTrading() || isStoreOpen() || isMerchanting() || isSellingMerchant() || isBuyingMerchant() || isMining() || m_bMerchantStatex)
|
|
{
|
|
bResult = UpgradeTrading;
|
|
goto fail_return;
|
|
}
|
|
|
|
pkt >> bType; // either preview or upgrade, need to allow for these types
|
|
|
|
if(bType == UpgradeTypePreview)
|
|
{
|
|
bResult = UpgradeFailed;
|
|
goto fail_return;
|
|
}
|
|
|
|
pkt >> sNpcID;
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
pkt >> nItemID[i] >> bPos[i];
|
|
|
|
// Invalid slot ID
|
|
if (bPos[i] != -1 && bPos[i] >= HAVE_MAX)
|
|
return;
|
|
}
|
|
//printf("bPos1:%d,bPos2:%d,bPos3:%d,bPos4:%d,bPos5:%d\n",bPos[0],bPos[1],bPos[2],bPos[3],bPos[4]);
|
|
//printf("nID1:%d,nID2:%d,nID3:%d,nID4:%d,nID5:%d\n",nItemID[0],nItemID[1],nItemID[2],nItemID[3],nItemID[4]);
|
|
|
|
pOriginItem = GetItem(SLOT_MAX + bPos[0]);
|
|
if (pOriginItem->nNum != nItemID[0]
|
|
|| (proto = g_pMain->GetItemPtr(nItemID[0])) == nullptr)
|
|
goto fail_return; // error with error code UpgradeNoMatch ("Items required for upgrade do not match")
|
|
else if (pOriginItem->isRented()
|
|
|| pOriginItem->isSealed()
|
|
|| pOriginItem->nExpirationTime > 0) // unsure if there's another error code for sealed items
|
|
{
|
|
bResult = UpgradeRental;
|
|
goto fail_return;
|
|
}
|
|
|
|
// Invalid item in slot.
|
|
for (int x = 0; x < 10; x++)
|
|
{
|
|
if (bPos[x] != -1 && (nItemID[x] > 0 && nItemID[x] != GetItem(SLOT_MAX + bPos[x])->nNum))
|
|
goto fail_return;
|
|
}
|
|
|
|
{ // scoped lock to prevent race conditions
|
|
int nReqOriginItem = nItemID[0] % 100000;
|
|
_ITEM_UPGRADE * pUpgrade = nullptr;
|
|
foreach_stlmap_nolock (itr, g_pMain->m_ItemUpgradeArray)
|
|
{
|
|
pUpgrade = itr->second;
|
|
|
|
if (pUpgrade->sOriginItem != nReqOriginItem)
|
|
continue;
|
|
|
|
|
|
|
|
if (((nItemID[0] / MIN_ITEM_ID) != 11) &&
|
|
(nItemID[0] / MIN_ITEM_ID) != pUpgrade->nIndex / 100000 && pUpgrade->nIndex < 300000)
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (nItemID[1]== TRINA_PIECE || nItemID[2]== TRINA_PIECE)
|
|
Trina = true;
|
|
if (nItemID[1]== KRAVDIS_PIECE || nItemID[2]== KRAVDIS_PIECE)
|
|
Karivdis = true;
|
|
|
|
|
|
|
|
|
|
if (((nItemID[1]== TRINA_PIECE || nItemID[2]== TRINA_PIECE) && (pUpgrade->bRateType == 4))
|
|
|| (nItemID[1]== KRAVDIS_PIECE || nItemID[2]== KRAVDIS_PIECE) && (pUpgrade->bRateType != 4))
|
|
continue;
|
|
|
|
|
|
if(pUpgrade->bRateType == 1)
|
|
if( nItemID[1] == 379221000 ||
|
|
nItemID[1] == 379222000 ||
|
|
nItemID[1] == 379223000 ||
|
|
nItemID[1] == 379224000 ||
|
|
nItemID[1] == 379225000 ||
|
|
nItemID[1] == 379226000 ||
|
|
nItemID[1] == 379227000 ||
|
|
nItemID[1] == 379228000 ||
|
|
nItemID[1] == 379229000 ||
|
|
nItemID[1] == 379230000 ||
|
|
nItemID[1] == 379231000 ||
|
|
nItemID[1] == 379232000 ||
|
|
nItemID[1] == 379233000 ||
|
|
nItemID[1] == 379234000 ||
|
|
nItemID[1] == 379235000 ||
|
|
nItemID[1] == 379255000 ||
|
|
nItemID[2] == 379221000 ||
|
|
nItemID[2] == 379222000 ||
|
|
nItemID[2] == 379223000 ||
|
|
nItemID[2] == 379224000 ||
|
|
nItemID[2] == 379225000 ||
|
|
nItemID[2] == 379226000 ||
|
|
nItemID[2] == 379227000 ||
|
|
nItemID[2] == 379228000 ||
|
|
nItemID[2] == 379229000 ||
|
|
nItemID[2] == 379230000 ||
|
|
nItemID[2] == 379231000 ||
|
|
nItemID[2] == 379232000 ||
|
|
nItemID[2] == 379233000 ||
|
|
nItemID[2] == 379234000 ||
|
|
nItemID[2] == 379235000 ||
|
|
nItemID[2] == 379255000 )
|
|
ItemClass = 1;
|
|
else
|
|
continue;
|
|
|
|
if( pUpgrade->bRateType == 2)
|
|
if(
|
|
nItemID[1] == 379205000 ||
|
|
nItemID[1] == 379206000 ||
|
|
nItemID[1] == 379208000 ||
|
|
nItemID[1] == 379209000 ||
|
|
nItemID[1] == 379210000 ||
|
|
nItemID[1] == 379211000 ||
|
|
nItemID[1] == 379212000 ||
|
|
nItemID[1] == 379213000 ||
|
|
nItemID[1] == 379214000 ||
|
|
nItemID[1] == 379215000 ||
|
|
nItemID[1] == 379216000 ||
|
|
nItemID[1] == 379217000 ||
|
|
nItemID[1] == 379218000 ||
|
|
nItemID[1] == 379219000 ||
|
|
nItemID[1] == 379220000 ||
|
|
nItemID[2] == 379205000 ||
|
|
nItemID[2] == 379206000 ||
|
|
nItemID[2] == 379208000 ||
|
|
nItemID[2] == 379209000 ||
|
|
nItemID[2] == 379210000 ||
|
|
nItemID[2] == 379211000 ||
|
|
nItemID[2] == 379212000 ||
|
|
nItemID[2] == 379213000 ||
|
|
nItemID[2] == 379214000 ||
|
|
nItemID[2] == 379215000 ||
|
|
nItemID[2] == 379216000 ||
|
|
nItemID[2] == 379217000 ||
|
|
nItemID[2] == 379218000 ||
|
|
nItemID[2] == 379219000 ||
|
|
nItemID[2] == 379220000
|
|
)
|
|
ItemClass = 2;
|
|
else
|
|
continue;
|
|
|
|
if( pUpgrade->bRateType == 3)
|
|
if(
|
|
nItemID[1] == 379021000 ||
|
|
nItemID[1] == 379022000 ||
|
|
nItemID[1] == 379023000 ||
|
|
nItemID[1] == 379024000 ||
|
|
nItemID[1] == 379025000 ||
|
|
nItemID[1] == 379030000 ||
|
|
nItemID[1] == 379031000 ||
|
|
nItemID[1] == 379032000 ||
|
|
nItemID[1] == 379033000 ||
|
|
nItemID[1] == 379034000 ||
|
|
nItemID[1] == 379035000 ||
|
|
nItemID[1] == 379138000 ||
|
|
nItemID[1] == 379139000 ||
|
|
nItemID[1] == 379140000 ||
|
|
nItemID[1] == 379141000 ||
|
|
nItemID[1] == 379016000 ||
|
|
nItemID[2] == 379021000 ||
|
|
nItemID[2] == 379022000 ||
|
|
nItemID[2] == 379023000 ||
|
|
nItemID[2] == 379024000 ||
|
|
nItemID[2] == 379025000 ||
|
|
nItemID[2] == 379030000 ||
|
|
nItemID[2] == 379031000 ||
|
|
nItemID[2] == 379032000 ||
|
|
nItemID[2] == 379033000 ||
|
|
nItemID[2] == 379034000 ||
|
|
nItemID[2] == 379035000 ||
|
|
nItemID[2] == 379138000 ||
|
|
nItemID[2] == 379139000 ||
|
|
nItemID[2] == 379140000 ||
|
|
nItemID[2] == 379141000 ||
|
|
nItemID[1] == 379016000
|
|
)
|
|
ItemClass = 3;
|
|
else
|
|
continue;
|
|
|
|
if( pUpgrade->bRateType == 4)
|
|
if(
|
|
nItemID[1] == 379256000 ||
|
|
nItemID[1] == 379257000 ||
|
|
nItemID[2] == 379256000 ||
|
|
nItemID[2] == 379257000 )
|
|
ItemClass = 4;
|
|
else
|
|
continue;
|
|
|
|
|
|
if (proto->ItemClass == 8)
|
|
{
|
|
Accessories = true;
|
|
if (pUpgrade->bRateType != 8
|
|
|| (pUpgrade->bOriginType != -1
|
|
&& pUpgrade->bOriginType != 23
|
|
&& proto->ItemExt != pUpgrade->bOriginType))
|
|
continue;
|
|
}
|
|
|
|
if (proto->ItemClass != 4
|
|
&& (nItemID[1] == 379257000
|
|
|| nItemID[2] == 379257000))
|
|
goto fail_return;
|
|
|
|
if ((proto->ItemClass == 4
|
|
|| proto->ItemClass == 2
|
|
|| proto->ItemClass == 1)
|
|
&& (nItemID[1] == 379256000
|
|
|| nItemID[2] == 379256000))
|
|
goto fail_return;
|
|
|
|
|
|
if(bPos[0] == bPos[1]
|
|
|| bPos[1] == bPos[2]
|
|
|| bPos[0] == bPos[2])
|
|
continue;
|
|
|
|
if (!(proto->ItemClass <= ItemClass)
|
|
&& !Accessories)
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pUpgrade->bOriginType != -1
|
|
&& pUpgrade->nIndex < 200000 && pUpgrade->nIndex >= 100000)
|
|
{
|
|
switch (pUpgrade->bOriginType)
|
|
{
|
|
case 0:
|
|
if (!proto->isDagger())
|
|
continue;
|
|
break;
|
|
|
|
case 1:
|
|
if (proto->m_bKind != 21)
|
|
continue;
|
|
break;
|
|
|
|
case 2:
|
|
if (proto->m_bKind != 22)
|
|
continue;
|
|
break;
|
|
|
|
case 3:
|
|
if (proto->m_bKind != 31)
|
|
continue;
|
|
break;
|
|
|
|
case 4:
|
|
if (proto->m_bKind != 32)
|
|
continue;
|
|
break;
|
|
|
|
case 5:
|
|
if (proto->m_bKind != 41)
|
|
continue;
|
|
break;
|
|
|
|
case 6:
|
|
if (proto->m_bKind != 42)
|
|
continue;
|
|
break;
|
|
|
|
case 7:
|
|
if (proto->m_bKind != 51)
|
|
continue;
|
|
break;
|
|
|
|
case 8:
|
|
if (proto->m_bKind != 52)
|
|
continue;
|
|
break;
|
|
|
|
case 9:
|
|
if (proto->m_bKind != 70 && proto->m_bKind != 71)
|
|
continue;
|
|
break;
|
|
|
|
case 10:
|
|
if (proto->m_bKind != 110)
|
|
continue;
|
|
break;
|
|
|
|
case 11:
|
|
if ((nItemID[0] / 10000000) != 19)
|
|
continue;
|
|
break;
|
|
|
|
case 12:
|
|
if (proto->m_bKind != 60)
|
|
continue;
|
|
break;
|
|
|
|
case 13:
|
|
if (proto->m_bKind != 210 && proto->m_bKind != 220 && proto->m_bKind != 230 && proto->m_bKind != 240)
|
|
continue;
|
|
break;
|
|
|
|
case 14:
|
|
if (proto->m_bKind != 11)
|
|
continue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((nItemID[0] / MIN_ITEM_ID) != (pUpgrade->nIndex / 100000)
|
|
&& ((nItemID[0] / MIN_ITEM_ID) != 11 && (pUpgrade->nIndex / 100000) == 1)
|
|
&& ((pUpgrade->nIndex / 100000) == 1
|
|
|| (pUpgrade->nIndex / 100000) == 2))
|
|
continue;
|
|
|
|
|
|
|
|
|
|
bool isValidMatch = true;
|
|
// Does our upgrade attempt match the requirements for this upgrade entry?
|
|
for (int x = 1; x < MAX_ITEMS_REQ_FOR_UPGRADE; x++)
|
|
{
|
|
if (bPos[x] == -1
|
|
|| pUpgrade->nReqItem[x-1] == 0)
|
|
continue;
|
|
|
|
_ITEM_DATA * pItem = GetItem(SLOT_MAX + bPos[x]);
|
|
|
|
if (pItem == nullptr
|
|
|| nItemID[x] != pItem->nNum
|
|
|| (nUpgradeType != ITEM_ACCESSORIES
|
|
&& nItemID[x] != pUpgrade->nReqItem[x-1]))
|
|
{
|
|
if(!Trina && !Karivdis)
|
|
isValidMatch = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Not a valid match, try another row.
|
|
if (!isValidMatch)
|
|
continue;
|
|
|
|
if (!hasCoins(pUpgrade->nReqNoah))
|
|
{
|
|
bResult = UpgradeNeedCoins;
|
|
goto fail_return;
|
|
}
|
|
|
|
if(proto->ItemClass > 4 && !Accessories && pUpgrade->nReqItem[0] != 379257000 && pUpgrade->nReqItem[1] != 379257000 && (!Karivdis || !Trina))
|
|
{
|
|
bResult = UpgradeNoMatch;
|
|
goto fail_return;
|
|
}
|
|
else if(proto->ItemClass < 3 && !Accessories && pUpgrade->nReqItem[0] == 379257000 || pUpgrade->nReqItem[1] == 379257000 && (!Karivdis || !Trina))
|
|
{
|
|
bResult = UpgradeNoMatch;
|
|
goto fail_return;
|
|
}
|
|
|
|
|
|
int nNewItemID = pOriginItem->nNum + pUpgrade->nGiveItem;
|
|
|
|
// Does this new item exist?
|
|
_ITEM_TABLE * newProto = g_pMain->GetItemPtr(nNewItemID);
|
|
if (newProto == nullptr)
|
|
continue;
|
|
|
|
bResult = UpgradeSucceeded;
|
|
break;
|
|
}
|
|
|
|
// If we ran out of upgrades to search through, it failed.
|
|
if (bResult != UpgradeSucceeded || pUpgrade == nullptr)
|
|
goto fail_return;
|
|
|
|
// Generate a random number, test if the item burned.
|
|
int rand = myrand(0, myrand(9000, 10000)),GenRate = 0;
|
|
|
|
if((Trina || Karivdis) && pUpgrade->sGenRate < 10000)
|
|
{
|
|
GenRate = (pUpgrade->sGenRate + pUpgrade->sTrinaRate);
|
|
|
|
if(GenRate > 10000)
|
|
GenRate=10000;
|
|
}
|
|
else
|
|
GenRate = pUpgrade->sGenRate;
|
|
|
|
if (bType == UpgradeTypeNormal && GenRate < rand)
|
|
{
|
|
bResult = UpgradeFailed;
|
|
memset(pOriginItem, 0, sizeof(_ITEM_DATA));
|
|
|
|
// Send upgrade notice.
|
|
|
|
if ((pUpgrade->sGenRate < 2001
|
|
&& nUpgradeType != ITEM_ACCESSORIES)
|
|
|| nUpgradeType == ITEM_UPGRADE_REBIRTH
|
|
|| (nUpgradeType == ITEM_ACCESSORIES
|
|
&& pUpgrade->sGenRate < 5001))
|
|
ItemUpgradeNotice(proto, UpgradeFailed);
|
|
|
|
GoldLose(pUpgrade->nReqNoah,true);
|
|
|
|
uint32 tariffTax = 0, nationalTax = 0;
|
|
C3DMap * pMap = GetMap();
|
|
_KNIGHTS_SIEGE_WARFARE *pSiegeWar = g_pMain->GetSiegeMasterKnightsPtr(1);
|
|
CKingSystem *pKingSystem = g_pMain->m_KingSystemArray.GetData(GetNation());
|
|
|
|
if(pMap == nullptr)
|
|
return;
|
|
|
|
if (pMap->GetTariff())
|
|
tariffTax = (pUpgrade->nReqNoah * GetMap()->GetTariff() / 100) ;
|
|
|
|
switch (GetZoneID())
|
|
{
|
|
case ZONE_KARUS:
|
|
nationalTax = pUpgrade->nReqNoah * 10 / 100;
|
|
if(tariffTax >= nationalTax)
|
|
tariffTax -= nationalTax;
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
pKingSystem->m_nTerritoryTax += (tariffTax);
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
pKingSystem->m_nNationalTreasury += (nationalTax);
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_KARUS, (tariffTax));
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_KARUS_ESLANT, (nationalTax));
|
|
break;
|
|
case ZONE_ELMORAD:
|
|
nationalTax = pUpgrade->nReqNoah * 10 / 100;
|
|
if(tariffTax >= nationalTax)
|
|
tariffTax -= nationalTax;
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
pKingSystem->m_nTerritoryTax += (tariffTax);
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
pKingSystem->m_nNationalTreasury += (nationalTax);
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_ELMORAD, (tariffTax));
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_ELMORAD_ESLANT, (nationalTax));
|
|
break;
|
|
case ZONE_ELMORAD_ESLANT:
|
|
nationalTax = pUpgrade->nReqNoah * 10 / 100;
|
|
if(tariffTax >= nationalTax)
|
|
tariffTax -= nationalTax;
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
pKingSystem->m_nTerritoryTax += (tariffTax);
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
pKingSystem->m_nNationalTreasury += (nationalTax);
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_ELMORAD, (tariffTax));
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_ELMORAD_ESLANT, (nationalTax));
|
|
break;
|
|
case ZONE_MORADON:
|
|
|
|
if (pSiegeWar->nMoradonTax < COIN_MAX)
|
|
pSiegeWar->nMoradonTax += tariffTax;
|
|
if (pSiegeWar->nMoradonTax < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_MORADON, tariffTax);
|
|
break;
|
|
case ZONE_MORADONM2:
|
|
if (pSiegeWar->nMoradonTax < COIN_MAX)
|
|
pSiegeWar->nMoradonTax += tariffTax;
|
|
if (pSiegeWar->nMoradonTax < COIN_MAX)
|
|
InsertTaxUpEvent(ZONE_MORADON, tariffTax);
|
|
break;
|
|
default:
|
|
nationalTax = pUpgrade->nReqNoah * 10 / 100;
|
|
if(tariffTax >= nationalTax)
|
|
tariffTax -= nationalTax;
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
pKingSystem->m_nTerritoryTax += (tariffTax);
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
pKingSystem->m_nNationalTreasury += (nationalTax);
|
|
|
|
if (pKingSystem->m_nTerritoryTax < COIN_MAX)
|
|
InsertTaxUpEvent(GetNation(), (tariffTax));
|
|
|
|
if (pKingSystem->m_nNationalTreasury < COIN_MAX)
|
|
InsertTaxUpEvent((GetNation() + 10), (nationalTax));
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
if (nUpgradeType == ITEM_UPGRADE_REBIRTH)
|
|
{
|
|
if (bResult == UpgradeFailed)
|
|
g_pMain->WriteUpgradeLogFile(string_format("[ ItemRebirthUpgrade - %d:%d:%d ] %s : Failed = %s ( Zone =%d, X=%d, Z=%d )\n", time.GetHour(), time.GetMinute(), time.GetSecond(), GetName().c_str(), proto->m_sName.c_str(), GetZoneID(), uint16(GetX()), uint16(GetZ())));
|
|
}
|
|
else if (nUpgradeType == ITEM_ACCESSORIES && pUpgrade->sGenRate)
|
|
{
|
|
if (bResult == UpgradeFailed)
|
|
g_pMain->WriteUpgradeLogFile(string_format("[ ItemAccessories - %d:%d:%d ] %s : Failed = %s ( Zone =%d, X=%d, Z=%d )\n", time.GetHour(), time.GetMinute(), time.GetSecond(), GetName().c_str(), proto->m_sName.c_str(), GetZoneID(), uint16(GetX()), uint16(GetZ())));
|
|
}
|
|
else
|
|
{
|
|
if (bResult == UpgradeFailed && pUpgrade->sGenRate)
|
|
g_pMain->WriteUpgradeLogFile(string_format("[ ItemUpgrade - %d:%d:%d ] %s : Failed = %s ( Zone =%d, X=%d, Z=%d )\n", time.GetHour(), time.GetMinute(), time.GetSecond(), GetName().c_str(), proto->m_sName.c_str(), GetZoneID(), uint16(GetX()), uint16(GetZ())));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (isDead()
|
|
|| isTrading()
|
|
|| isStoreOpen()
|
|
|| isMerchanting()
|
|
|| m_bMerchantStatex
|
|
|| isSellingMerchant()
|
|
|| isBuyingMerchant()
|
|
|| isMining())
|
|
{
|
|
bResult = UpgradeTrading;
|
|
goto fail_return;
|
|
}
|
|
// Generate the new item ID
|
|
int nNewItemID = pOriginItem->nNum + pUpgrade->nGiveItem;
|
|
|
|
// Does this new item exist?
|
|
_ITEM_TABLE * newProto = g_pMain->GetItemPtr(nNewItemID);
|
|
if (newProto == nullptr)
|
|
{ // if not, just say it doesn't match. No point removing the item anyway (like official :/).
|
|
bResult = UpgradeNoMatch;
|
|
goto fail_return;
|
|
}
|
|
|
|
if (bType != UpgradeTypePreview)
|
|
{
|
|
// Update the user's item in their inventory with the new item
|
|
pOriginItem->nNum = nNewItemID;
|
|
|
|
// Reset the durability also, to the new cap.
|
|
pOriginItem->sDuration = newProto->m_sDuration;
|
|
|
|
// Send upgrade notice.
|
|
if ((pUpgrade->sGenRate < 2001
|
|
&& nUpgradeType != ITEM_ACCESSORIES)
|
|
|| nUpgradeType == ITEM_UPGRADE_REBIRTH
|
|
|| (nUpgradeType == ITEM_ACCESSORIES
|
|
&& pUpgrade->sGenRate < 5001))
|
|
ItemUpgradeNotice(newProto, UpgradeSucceeded);
|
|
|
|
// Rob gold upgrade noah
|
|
GoldLose(pUpgrade->nReqNoah,true);
|
|
|
|
if (nUpgradeType == ITEM_UPGRADE_REBIRTH)
|
|
{
|
|
if (bResult == UpgradeSucceeded)
|
|
g_pMain->WriteUpgradeLogFile(string_format("[ ItemRebirthUpgrade - %d:%d:%d ] %s : Succes = %s ( Zone =%d, X=%d, Z=%d )\n", time.GetHour(), time.GetMinute(), time.GetSecond(), GetName().c_str(), newProto->m_sName.c_str(), GetZoneID(), uint16(GetX()), uint16(GetZ())));
|
|
}
|
|
else if (nUpgradeType == ITEM_ACCESSORIES)
|
|
{
|
|
if (bResult == UpgradeSucceeded)
|
|
g_pMain->WriteUpgradeLogFile(string_format("[ ItemAccessories - %d:%d:%d ] %s : Succes = %s ( Zone =%d, X=%d, Z=%d )\n", time.GetHour(), time.GetMinute(), time.GetSecond(), GetName().c_str(), newProto->m_sName.c_str(), GetZoneID(), uint16(GetX()), uint16(GetZ())));
|
|
}
|
|
else
|
|
{
|
|
if (bResult == UpgradeSucceeded)
|
|
g_pMain->WriteUpgradeLogFile(string_format("[ ItemUpgrade - %d:%d:%d ] %s : Succes = %s ( Zone =%d, X=%d, Z=%d )\n", time.GetHour(), time.GetMinute(), time.GetSecond(), GetName().c_str(), newProto->m_sName.c_str(), GetZoneID(), uint16(GetX()), uint16(GetZ())));
|
|
}
|
|
}
|
|
|
|
// Replace the item ID in the list for the packet
|
|
nItemID[0] = nNewItemID;
|
|
}
|
|
|
|
// Remove the source item
|
|
if (bType != UpgradeTypePreview)
|
|
{
|
|
// Remove all required items, if applicable.
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
|
|
if (bPos[i] == -1 || bPos[i] >= HAVE_MAX || nItemID[i] < 1)
|
|
continue;
|
|
|
|
|
|
_ITEM_DATA * pItem = GetItem(SLOT_MAX + bPos[i]);
|
|
|
|
if (pItem->nNum == 0 || pItem->sCount == 0 || (bResult == UpgradeSucceeded && pItem->nNum == pOriginItem->nNum))
|
|
continue;
|
|
|
|
_ITEM_TABLE * pTable = g_pMain->GetItemPtr(pItem->nNum);
|
|
|
|
pItem->sCount--;
|
|
if (pItem->sCount == 0 || (pTable != nullptr && pTable->isAccessory()))
|
|
memset(pItem, 0, sizeof(pItem));
|
|
}
|
|
}
|
|
} // end of scoped lock
|
|
|
|
result << bType;
|
|
|
|
if(Follow)
|
|
printf("1x-%d\n",bResult);
|
|
|
|
result << bResult;
|
|
foreach_array (i, nItemID)
|
|
result << nItemID[i] << bPos[i];
|
|
Send(&result);
|
|
|
|
// Send the result to everyone in the area
|
|
// (i.e. make the anvil do its burned/upgraded indicator thing)
|
|
result.Initialize(WIZ_OBJECT_EVENT);
|
|
result << uint8(OBJECT_ANVIL) << bResult << sNpcID;
|
|
SendToRegion(&result,nullptr,GetEventRoom());
|
|
|
|
return;
|
|
fail_return:
|
|
result << bResult;
|
|
|
|
// The item data's only sent when not experiencing a general error
|
|
if (bResult != 2)
|
|
{
|
|
foreach_array (i, nItemID)
|
|
result << nItemID[i] << bPos[i];
|
|
}
|
|
Send(&result);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Upgrade notice.
|
|
*
|
|
* @param pItem The item.
|
|
*/
|
|
void CUser::ItemUpgradeNotice(_ITEM_TABLE * pItem, uint8 UpgradeResult)
|
|
{
|
|
bool bSendUpgradeNotice = false;
|
|
std::string sUpgradeNotice;
|
|
|
|
// Notice is only rebirth upgrade a Offical stuff.
|
|
if (pItem->m_ItemType == 11 || pItem->m_ItemType == 12 || pItem->m_ItemType == 4)
|
|
bSendUpgradeNotice = true;
|
|
|
|
if (bSendUpgradeNotice)
|
|
{
|
|
Packet result(WIZ_LOGOSSHOUT,uint8(0x02));
|
|
result.SByte();
|
|
|
|
if (UpgradeResult == 0)
|
|
result << uint8(0x05) << uint8(0x00) << GetName() << pItem->m_iNum;
|
|
else if (UpgradeResult == 1)
|
|
result << uint8(0x05) << uint8(0x01) << GetName() << pItem->m_iNum;
|
|
|
|
g_pMain->Send_All(&result);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Packet handler for the accessory upgrade system.
|
|
*
|
|
* @param pkt The packet.
|
|
*/
|
|
void CUser::ItemUpgradeAccessories(Packet & pkt)
|
|
{
|
|
ItemUpgrade(pkt, ITEM_ACCESSORIES);
|
|
}
|
|
|
|
void CUser::ItemUpgradePet(Packet & pkt)
|
|
{
|
|
|
|
Packet result(WIZ_ITEM_UPGRADE,uint8(ITEM_PET));
|
|
uint16 unknown;
|
|
uint32 ItemID;
|
|
uint8 Slot;
|
|
|
|
/*1 Familiar hatching failed.
|
|
2 Invalid name.
|
|
3 This Familiar cannot be incubated.
|
|
4 Limit exceeded.*/
|
|
uint8 Error = 2;
|
|
std::string Name;
|
|
pkt.DByte();
|
|
pkt >> unknown >> ItemID >> Slot >> Name;
|
|
|
|
if(Slot >= HAVE_MAX)
|
|
goto fail_return;
|
|
|
|
//printf("%d %d %d %s\n",unknown,ItemID,Slot,Name.c_str());
|
|
|
|
_ITEM_DATA * pItem = GetItem(SLOT_MAX + Slot);
|
|
|
|
if(ItemID != 600001000
|
|
|| pItem == nullptr
|
|
|| pItem->nNum != ItemID)
|
|
{
|
|
Error = 3;
|
|
goto fail_return;
|
|
}
|
|
uint64 Serial = g_pMain->GenerateItemSerial();
|
|
|
|
if (Name.length() > 21
|
|
|| !g_pMain->WordGuardSystem(Name,Name.length())
|
|
|| Name.length() < 1)
|
|
{
|
|
Error = 2;
|
|
goto fail_return;
|
|
}
|
|
|
|
|
|
CPet * pData = new CPet();
|
|
pData->m_Serial = Serial;
|
|
pData->m_strPetID = Name;
|
|
pData->m_iExp = 0;
|
|
pData->m_bLevel = 1;
|
|
pData->m_sSatisfaction = 10000;
|
|
pData->m_sClass = 101;
|
|
g_pMain->LastPetID++;
|
|
pData->SpecialPetID = g_pMain->LastPetID;
|
|
|
|
uint8 DBResult = g_DBAgent.InsertPetData(Serial,pData);
|
|
|
|
if(DBResult != 1)
|
|
{
|
|
Error = DBResult - 1;
|
|
goto fail_return;
|
|
}
|
|
|
|
g_pMain->m_PetArray.insert(std::make_pair(pData->m_Serial, pData));
|
|
|
|
pItem->nSerialNum = Serial;
|
|
pItem->nNum = 610001000;
|
|
|
|
result.DByte();
|
|
result << uint8(1) << uint32(pItem->nNum) << Slot << uint32(pData->SpecialPetID) << Name << uint8(pData->m_sClass) << uint8(pData->m_bLevel) << uint16((pData->m_iExp* 10000) / g_pMain->GetPetExpByLevel(pData->m_bLevel)) << uint16(pData->m_sSatisfaction);
|
|
Send(&result);
|
|
|
|
fail_return:
|
|
result << uint8(0) << uint8(Error);
|
|
Send(&result);
|
|
}
|
|
|
|
/**
|
|
* @brief Packet handler for the Chaotic Generator system
|
|
* which is used to exchange Bifrost pieces/fragments.
|
|
*
|
|
* @param pkt The packet.
|
|
*/
|
|
|
|
void CUser::BifrostPieceProcess(Packet & pkt)
|
|
{
|
|
enum ResultOpCodes
|
|
{
|
|
Failed = 0,
|
|
Success = 1
|
|
};
|
|
|
|
enum ResultMessages
|
|
{
|
|
EffectNone = 0, // No effect
|
|
EffectRed = 1, // There will be better days.
|
|
EffectGreen = 2, // Don't be too disappointed. You're luck isn't that bad.
|
|
EffectWhite = 3 // It must be your lucky day.
|
|
};
|
|
|
|
uint16 nObjectID = 0;
|
|
uint32 nExchangeItemID = 0;
|
|
|
|
pkt >> nObjectID >> nExchangeItemID;
|
|
|
|
std::vector<uint32> ExchangeIndexList;
|
|
ResultOpCodes resultOpCode = Success;
|
|
ResultMessages resultMessage = EffectNone;
|
|
uint32 nItemID = 0;
|
|
uint8 sItemSlot = 0;
|
|
uint8 sExchangeItemSlot = 0;
|
|
|
|
sExchangeItemSlot = FindSlotForItem(nExchangeItemID, 1) - SLOT_MAX;
|
|
|
|
if (g_pMain->m_ItemExchangeArray.GetSize() > 0)
|
|
{
|
|
foreach_stlmap (itr, g_pMain->m_ItemExchangeArray)
|
|
{
|
|
if (itr->second->nOriginItemNum[0] == nExchangeItemID)
|
|
{
|
|
if (std::find(ExchangeIndexList.begin(),ExchangeIndexList.end(),itr->second->nIndex) == ExchangeIndexList.end())
|
|
ExchangeIndexList.push_back(itr->second->nIndex);
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (ExchangeIndexList.size() > 0)
|
|
{
|
|
uint32 randIndex = myrand(0, (ExchangeIndexList.size() - 1));
|
|
uint32 nExchangeID = ExchangeIndexList[randIndex];
|
|
|
|
_ITEM_EXCHANGE * pExchange = g_pMain->m_ItemExchangeArray.GetData(nExchangeID);
|
|
|
|
if (pExchange == nullptr
|
|
|| !CheckExchange(nExchangeID)
|
|
|| pExchange->bRandomFlag > 101
|
|
|| !CheckExistItemAnd(pExchange->nOriginItemNum[0], pExchange->sOriginItemCount[0], 0, 0, 0, 0, 0, 0, 0, 0))
|
|
resultOpCode = Failed;
|
|
|
|
if (isTrading() || isMerchanting() || isMining() || isStoreOpen())
|
|
resultOpCode = Failed;
|
|
|
|
if (pExchange->bRandomFlag > 0 && resultOpCode == Success)
|
|
{
|
|
uint32 nTotalPercent = 0;
|
|
for (int i = 0; i < ITEMS_IN_EXCHANGE_GROUP; i++)
|
|
nTotalPercent += pExchange->sExchangeItemCount[i];
|
|
|
|
if (nTotalPercent > 10000)
|
|
resultOpCode = Failed;
|
|
|
|
if (resultOpCode == Success)
|
|
{
|
|
uint8 bRandArray[20000];
|
|
memset(&bRandArray, 0, sizeof(bRandArray));
|
|
uint32 sExchangeCount[ITEMS_IN_EXCHANGE_GROUP];
|
|
memcpy(&sExchangeCount, &pExchange->sExchangeItemCount, sizeof(pExchange->sExchangeItemCount));
|
|
|
|
int offset = 0;
|
|
for (int n = 0, i = 0; n < ITEMS_IN_EXCHANGE_GROUP; n++)
|
|
{
|
|
if (sExchangeCount[n] > 0)
|
|
{
|
|
memset(&bRandArray[offset], n, sExchangeCount[n]);
|
|
offset += sExchangeCount[n];
|
|
}
|
|
}
|
|
|
|
uint8 bRandSlot = bRandArray[myrand(0, 20000)];
|
|
nItemID = pExchange->nExchangeItemNum[bRandSlot];
|
|
|
|
sItemSlot = GetEmptySlot() - SLOT_MAX;
|
|
RobItem(pExchange->nOriginItemNum[0], 1);
|
|
GiveItem(nItemID, 1);
|
|
|
|
|
|
_ITEM_TABLE *pItem = g_pMain->m_ItemtableArray.GetData(nItemID);
|
|
|
|
if (pItem != nullptr)
|
|
{
|
|
if (pItem->m_ItemType == 4)
|
|
resultMessage = EffectWhite;
|
|
else if (pItem->m_ItemType == 5 || pItem->m_ItemType == 11 || pItem->m_ItemType == 12)
|
|
resultMessage = EffectGreen;
|
|
else
|
|
resultMessage = EffectRed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Packet result(WIZ_ITEM_UPGRADE);
|
|
result << (uint8)ITEM_BIFROST_EXCHANGE << (uint8)resultOpCode << nItemID << sItemSlot << nExchangeItemID << sExchangeItemSlot << (uint8)resultMessage;
|
|
Send(&result);
|
|
|
|
result.clear();
|
|
result.SetOpcode(WIZ_OBJECT_EVENT);
|
|
result << (uint8)OBJECT_ARTIFACT << (uint8)resultMessage << nObjectID;
|
|
|
|
if (resultOpCode != Failed)
|
|
SendToRegion(&result);
|
|
}
|
|
|
|
/**
|
|
* @brief Packet handler for the Special exchange system
|
|
* which is used to exchange Krowaz meterials.
|
|
*
|
|
* @param pkt The packet.
|
|
*/
|
|
void CUser::SpecialItemExchange(Packet & pkt)
|
|
{
|
|
enum ResultOpCodes
|
|
{
|
|
WrongMaterial = 0,
|
|
Success = 1,
|
|
Failed = 2
|
|
};
|
|
|
|
ResultOpCodes resultOpCode = WrongMaterial;
|
|
|
|
std::vector <uint32> ExchangingItems;
|
|
uint16 sNpcID;
|
|
uint32 nShadowPiece;
|
|
uint8 nShadowPieceSlot;
|
|
uint8 nMaterialCount;
|
|
uint8 nItemSlot[10];
|
|
uint8 nDownFlag;
|
|
uint32 nItemID[10];
|
|
uint8 nItemCount[10];
|
|
|
|
uint32 nItemNumber = 0;
|
|
uint8 sItemSlot = 0;
|
|
|
|
pkt >> sNpcID >> nShadowPiece >> nShadowPieceSlot >> nMaterialCount;
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
nItemID[i] = 0;
|
|
nItemCount[i] = 0;
|
|
}
|
|
|
|
for (int i = 0; i < nMaterialCount; i++)
|
|
pkt >> nItemSlot[i];
|
|
|
|
pkt >> nDownFlag;
|
|
|
|
for (int i = 0; i < nMaterialCount; i++)
|
|
{
|
|
uint8 nReadByte;
|
|
int nDigit = 100000000;
|
|
nItemID[i] = 0;
|
|
for( int x = 0; x < 9; x++ )
|
|
{
|
|
pkt >> nReadByte;
|
|
nItemID[i] += (nReadByte - 48) * nDigit;
|
|
nDigit = nDigit / 10;
|
|
}
|
|
|
|
uint8 nCount[3] = { 0, 0, 0};
|
|
pkt >> nCount[0];
|
|
pkt >> nCount[1];
|
|
pkt >> nCount[2];
|
|
int nCountFinish = 0;
|
|
nCountFinish += (nCount[0] - 48) * 100;
|
|
nCountFinish += (nCount[1] - 48) * 10;
|
|
nCountFinish += (nCount[2] - 48) * 1;
|
|
nItemCount[i] = nCountFinish;
|
|
|
|
_ITEM_DATA * pItem = GetItem(nItemSlot[i] + SLOT_MAX);
|
|
|
|
if(pItem == nullptr)
|
|
return;
|
|
|
|
if(pItem->nNum != nItemID[i]
|
|
|| pItem->sCount < nItemCount[i])
|
|
return;
|
|
|
|
ExchangingItems.push_back(nItemID[i]);
|
|
}
|
|
|
|
std::vector<uint32> ExchangeIndexList;
|
|
|
|
if (nMaterialCount >= 2) // Minimum Required : 2 Material
|
|
{
|
|
if (g_pMain->m_ItemMixArray.GetSize() > 0)
|
|
{
|
|
foreach_stlmap_nolock(itr, g_pMain->m_ItemMixArray)
|
|
{
|
|
|
|
uint8 nOriginItemCount = 0;
|
|
uint8 nMatchCount = 0;
|
|
bool bAddArray = false;
|
|
|
|
if (nMaterialCount == 2)
|
|
nMatchCount = (nShadowPiece == 0 ? 2 : 3);
|
|
else if (nMaterialCount == 3)
|
|
nMatchCount = (nShadowPiece == 0 ? 3 : 4);
|
|
else if (nMaterialCount == 4)
|
|
nMatchCount = (nShadowPiece == 0 ? 4 : 5);
|
|
else if (nMaterialCount == 5)
|
|
nMatchCount = (nShadowPiece == 0 ? 5 : 6);
|
|
else if (nMaterialCount == 6)
|
|
nMatchCount = (nShadowPiece == 0 ? 6 : 7);
|
|
else if (nMaterialCount == 7)
|
|
nMatchCount = (nShadowPiece == 0 ? 7 : 8);
|
|
else if (nMaterialCount == 8)
|
|
nMatchCount = (nShadowPiece == 0 ? 8 : 9);
|
|
else if (nMaterialCount == 9)
|
|
nMatchCount = (nShadowPiece == 0 ? 9 : 10);
|
|
|
|
for (int i = 0; i < nMaterialCount; i++)
|
|
{
|
|
if (nItemID[i] != 0)
|
|
{
|
|
for (int x = 0; x < ITEMS_IN_SPECIAL_ORIGIN_GROUP; x++)
|
|
{
|
|
if (itr->second->nOriginItemNum[x] != 0
|
|
&& nItemID[i] == itr->second->nOriginItemNum[x])
|
|
{
|
|
nOriginItemCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nShadowPiece > 0)
|
|
{
|
|
if (nOriginItemCount == (nMatchCount -1))
|
|
bAddArray = true;
|
|
}
|
|
if (nShadowPiece == 0)
|
|
{
|
|
if (nOriginItemCount == nMatchCount)
|
|
bAddArray = true;
|
|
}
|
|
|
|
if (bAddArray && std::find(ExchangeIndexList.begin(),ExchangeIndexList.end(),itr->second->nIndex) == ExchangeIndexList.end())
|
|
ExchangeIndexList.push_back(itr->second->nIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ExchangeIndexList.size() > 0)
|
|
{
|
|
uint32 randIndex = (ExchangeIndexList.size() - 1);
|
|
uint32 nExchangeID = ExchangeIndexList[randIndex];
|
|
|
|
_ITEM_MIX * pExchange = g_pMain->m_ItemMixArray.GetData(nExchangeID);
|
|
|
|
if (pExchange == nullptr
|
|
|| !CheckSpecialExchange(nExchangeID)
|
|
|| pExchange->bType > 102
|
|
|| !CheckExistSpecialItemAnd(
|
|
pExchange->nOriginItemNum[0], pExchange->sOriginItemCount[0],
|
|
pExchange->nOriginItemNum[1], pExchange->sOriginItemCount[1],
|
|
pExchange->nOriginItemNum[2], pExchange->sOriginItemCount[2],
|
|
pExchange->nOriginItemNum[3], pExchange->sOriginItemCount[3],
|
|
pExchange->nOriginItemNum[4], pExchange->sOriginItemCount[4],
|
|
pExchange->nOriginItemNum[5], pExchange->sOriginItemCount[5],
|
|
pExchange->nOriginItemNum[6], pExchange->sOriginItemCount[6],
|
|
pExchange->nOriginItemNum[7], pExchange->sOriginItemCount[7],
|
|
pExchange->nOriginItemNum[8], pExchange->sOriginItemCount[8],
|
|
pExchange->nOriginItemNum[9], pExchange->sOriginItemCount[9]))
|
|
{
|
|
resultOpCode = WrongMaterial;
|
|
}
|
|
else
|
|
{
|
|
bool bContinueExchange = true;
|
|
|
|
for (int i = 0; i < nMaterialCount; i++)
|
|
{
|
|
if (!bContinueExchange)
|
|
break;
|
|
|
|
if (nItemID[i] != 0)
|
|
{
|
|
for (int x = 0; x < ITEMS_IN_SPECIAL_ORIGIN_GROUP; x++)
|
|
{
|
|
if (pExchange->nOriginItemNum[x] != 0
|
|
&& nItemID[i] == pExchange->nOriginItemNum[x]
|
|
&& nItemCount[i] != pExchange->sOriginItemCount[x])
|
|
{
|
|
bContinueExchange = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isTrading() || isMerchanting() || isSellingMerchant() || isBuyingMerchant() || isStoreOpen() || isMining())
|
|
bContinueExchange = false;
|
|
|
|
uint8 MatchingCase = 0;
|
|
uint8 NeedCount = 0;
|
|
for (int x = 0; x < ITEMS_IN_SPECIAL_ORIGIN_GROUP; x++)
|
|
{
|
|
std::vector<uint32> Used;
|
|
|
|
if(pExchange->nOriginItemNum[x] > 0)
|
|
NeedCount++;
|
|
else
|
|
continue;
|
|
|
|
foreach (itr, ExchangingItems)
|
|
{
|
|
if((*itr) == pExchange->nOriginItemNum[x])
|
|
{
|
|
MatchingCase++;
|
|
*itr = 0;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
if(NeedCount != MatchingCase)
|
|
bContinueExchange = false;
|
|
|
|
if (!bContinueExchange)
|
|
resultOpCode = WrongMaterial;
|
|
else
|
|
{
|
|
uint32 nTotalPercent = 0;
|
|
for (int i = 0; i < ITEMS_IN_SPECIAL_EXCHANGE_GROUP; i++)
|
|
nTotalPercent += pExchange->sExchangeItemCount[i];
|
|
|
|
if (nTotalPercent > 10000)
|
|
resultOpCode = WrongMaterial;
|
|
else
|
|
{
|
|
uint8 bRandArray[10000];
|
|
memset(&bRandArray, 0, sizeof(bRandArray));
|
|
uint16 sExchangeCount[ITEMS_IN_SPECIAL_EXCHANGE_GROUP];
|
|
memcpy(&sExchangeCount, &pExchange->sExchangeItemCount, sizeof(pExchange->sExchangeItemCount));
|
|
|
|
int offset = 0;
|
|
for (int n = 0, i = 0; n < ITEMS_IN_SPECIAL_EXCHANGE_GROUP; n++)
|
|
{
|
|
if (sExchangeCount[n] > 0)
|
|
{
|
|
memset(&bRandArray[offset], n, sExchangeCount[n]);
|
|
offset += sExchangeCount[n];
|
|
}
|
|
}
|
|
|
|
uint8 bRandSlot = bRandArray[myrand(1, 5)];
|
|
nItemNumber = pExchange->nExchangeItemNum[bRandSlot];
|
|
uint16 nItemRate = pExchange->bSuccessRate;
|
|
int rand = myrand(0, myrand(1, 5000));
|
|
|
|
if(nShadowPiece>0)
|
|
nItemRate=10000;
|
|
|
|
if (nItemRate <= rand)
|
|
resultOpCode = Failed;
|
|
else
|
|
{
|
|
sItemSlot = GetEmptySlot() - SLOT_MAX;
|
|
GiveItem(nItemNumber, 1);
|
|
resultOpCode = Success;
|
|
}
|
|
|
|
for (int i = 0; i < ITEMS_IN_ORIGIN_GROUP; i++)
|
|
{
|
|
if (pExchange->nOriginItemNum[i] != 0)
|
|
RobItem(pExchange->nOriginItemNum[i], pExchange->sOriginItemCount[i],false);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return;
|
|
|
|
Packet result(WIZ_ITEM_UPGRADE);
|
|
result << (uint8)ITEM_SPECIAL_EXCHANGE << (uint8)resultOpCode << sNpcID;
|
|
|
|
if (resultOpCode == Success)
|
|
result << nItemNumber << sItemSlot;
|
|
|
|
Send(&result);
|
|
|
|
if (resultOpCode == Success)
|
|
ShowNpcEffect(31033, true);
|
|
else if (resultOpCode == Failed)
|
|
ShowNpcEffect(31034, true);
|
|
}
|
|
/**
|
|
* @brief Packet handler for the upgrading of 'rebirthed' items.
|
|
*
|
|
* @param pkt The packet.
|
|
*/
|
|
void CUser::ItemUpgradeRebirth(Packet & pkt)
|
|
{
|
|
ItemUpgrade(pkt, ITEM_UPGRADE_REBIRTH);
|
|
}
|
|
|
|
void CUser::ItemDisassembling(Packet & pkt)
|
|
{
|
|
enum ResultOpCodes
|
|
{
|
|
Failed = 0,
|
|
Success = 1
|
|
};
|
|
|
|
enum ResultMessages
|
|
{
|
|
nExchangeIndexID1 = 1,
|
|
nExchangeIndexID2 = 2,
|
|
nExchangeIndexID3 = 3
|
|
};
|
|
uint8 nPos;
|
|
uint8 nItemCount = 1;
|
|
ResultOpCodes resultOpCode = Success;
|
|
uint16 nObjectID = 0;
|
|
uint32 nExchangeItemID = 0;
|
|
std::vector<uint32> ExchangeIndexCrashList;
|
|
pkt >> nExchangeItemID >> nPos >> nObjectID;
|
|
Packet result(WIZ_ITEM_UPGRADE);
|
|
|
|
_ITEM_DATA* pItemData = GetItem(nPos + SLOT_MAX);
|
|
_ITEM_TABLE* pItem = g_pMain->GetItemPtr(nExchangeItemID);
|
|
|
|
if (pItemData == nullptr)
|
|
return;
|
|
|
|
if (pItem == nullptr)
|
|
return;
|
|
|
|
if (g_pMain->m_ItemCrashArray.GetSize() > 0)
|
|
{
|
|
foreach_stlmap_nolock(itr, g_pMain->m_ItemCrashArray)
|
|
{
|
|
if (std::find(ExchangeIndexCrashList.begin(),ExchangeIndexCrashList.end(),itr->second->Index) == ExchangeIndexCrashList.end())
|
|
ExchangeIndexCrashList.push_back(itr->second->Index);
|
|
if (pItem->m_ItemType >= 0 && pItem->m_ItemType <= 1 )
|
|
{
|
|
nItemCount = nExchangeIndexID1;
|
|
itr->second->Flag = 2;
|
|
continue;
|
|
}
|
|
else if (pItem->m_ItemType == 5 || pItem->m_ItemType == 11&& itr->second->Flag == 2)
|
|
{
|
|
nItemCount = nExchangeIndexID2;
|
|
itr->second->Flag = 3;
|
|
continue;
|
|
}
|
|
else if (pItem->m_ItemType == 4 || pItem->m_ItemType == 12 || pItem->m_ItemType == 13 && itr->second->Flag == 3)
|
|
{
|
|
nItemCount = nExchangeIndexID3;
|
|
itr->second->Flag = 3;
|
|
continue;
|
|
}
|
|
else
|
|
return;
|
|
|
|
}
|
|
}
|
|
|
|
if (ExchangeIndexCrashList.size() > 0)
|
|
{
|
|
|
|
uint32 randIndex[nExchangeIndexID3];
|
|
uint32 nExchangeID[nExchangeIndexID3];
|
|
|
|
if (pItem->m_ItemType >= 0 && pItem->m_ItemType <= 1)
|
|
nItemCount = nExchangeIndexID1;
|
|
else if (pItem->m_ItemType == 5 || pItem->m_ItemType == 11)
|
|
nItemCount = nExchangeIndexID2;
|
|
else if (pItem->m_ItemType == 4 || pItem->m_ItemType == 12 || pItem->m_ItemType == 13)
|
|
nItemCount = nExchangeIndexID3;
|
|
else
|
|
return;
|
|
|
|
for (int i = 0; i < nItemCount; i++)
|
|
{
|
|
randIndex[i] = myrand(0, (ExchangeIndexCrashList.size() - 1));
|
|
nExchangeID[i] = ExchangeIndexCrashList[randIndex[i]];
|
|
}
|
|
|
|
bool CheckSlot = CheckGiveSlot(nItemCount);
|
|
|
|
if(!CheckSlot
|
|
|| !RobItem(nExchangeItemID, 1))
|
|
return;
|
|
|
|
RobItem(nExchangeItemID, 1);
|
|
uint8 emptySlot = GetEmptySlot();
|
|
result << (uint8)ITEM_DISASSEMBLING << (uint16)resultOpCode << nExchangeItemID << nPos << (uint16)nItemCount;
|
|
|
|
if (emptySlot >= nItemCount)
|
|
{
|
|
for (int i = 0; i < nItemCount; i++)
|
|
{
|
|
_ITEM_CRASH * pExchangeCrashItem = g_pMain->m_ItemCrashArray.GetData(nExchangeID[i]);
|
|
if (pExchangeCrashItem == nullptr)
|
|
continue;
|
|
|
|
int8 pos;
|
|
if ((pos = FindSlotForItem(pExchangeCrashItem->ItemID, pExchangeCrashItem->ItemCount)) < 0)
|
|
continue;
|
|
|
|
GiveItem(pExchangeCrashItem->ItemID, pExchangeCrashItem->ItemCount, true);
|
|
result << pExchangeCrashItem->ItemID << uint8(pos - SLOT_MAX) << (uint16)pExchangeCrashItem->ItemCount;
|
|
}
|
|
}
|
|
}
|
|
Send(&result);
|
|
}
|
|
|