mirror of
https://github.com/therealKyp/Earth-and-Beyond-server
synced 2026-08-13 22:23:03 -04:00
430 lines
12 KiB
C++
430 lines
12 KiB
C++
// PlayerInventory.cpp
|
|
//
|
|
// Contains all methods to modify / access player inventory
|
|
|
|
#include "PlayerClass.h"
|
|
#include "ItemBaseManager.h"
|
|
|
|
void Player::SendItemBase(long ItemID)
|
|
{
|
|
g_ItemBaseMgr->SendItem(this, &m_ItemList, ItemID);
|
|
}
|
|
|
|
// Returns the count of items with ID in cargo inventory
|
|
long Player::CargoItemCount(long ItemID)
|
|
{
|
|
long ItemCount = 0;
|
|
|
|
for (u32 i=0; i<ShipIndex()->Inventory.GetCargoSpace(); i++)
|
|
{
|
|
if (ShipIndex()->Inventory.CargoInv.Item[i].GetItemTemplateID() == ItemID)
|
|
{
|
|
ItemCount += ShipIndex()->Inventory.CargoInv.Item[i].GetStackCount();
|
|
}
|
|
}
|
|
|
|
return ItemCount;
|
|
}
|
|
|
|
bool Player::CanCargoAddItem(_Item * myItem)
|
|
{
|
|
return CanCargoAddItem(myItem->ItemTemplateID, myItem->StackCount, myItem->Quality);
|
|
}
|
|
|
|
// Returns whether or not the item with a given stack and quality can be added to inventory
|
|
bool Player::CanCargoAddItem(long ItemID, long Stack, float Quality)
|
|
{
|
|
return (CargoAddItemCount(ItemID, Quality) >= Stack);
|
|
}
|
|
|
|
// Returns how many items with a given quality can be added to inventory
|
|
long Player::CargoAddItemCount(long ItemID, float Quality)
|
|
{
|
|
long Count = 0;
|
|
ItemBase * ItemData = g_ItemBaseMgr->GetItem(ItemID);
|
|
|
|
if (!ItemData)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
for (u32 i=0; i<ShipIndex()->Inventory.GetCargoSpace(); i++)
|
|
{
|
|
if (ShipIndex()->Inventory.CargoInv.Item[i].GetItemTemplateID() == ItemID &&
|
|
ShipIndex()->Inventory.CargoInv.Item[i].GetQuality() == Quality)
|
|
{
|
|
// We found an item stack of the same item and quality
|
|
Count += (ItemData->MaxStack() - ShipIndex()->Inventory.CargoInv.Item[i].GetStackCount());
|
|
}
|
|
else if (ShipIndex()->Inventory.CargoInv.Item[i].GetItemTemplateID() == -1)
|
|
{
|
|
Count += ItemData->MaxStack();
|
|
}
|
|
}
|
|
|
|
return Count;
|
|
}
|
|
|
|
int Player::CargoAddItem(long ItemID, long Stack, int TradeStack)
|
|
{
|
|
_Item TempData;
|
|
memset(&TempData, 0, sizeof(_Item));
|
|
TempData.ItemTemplateID = ItemID;
|
|
TempData.StackCount = Stack;
|
|
TempData.Quality = 1.0f;
|
|
TempData.Structure = 1.0f;
|
|
TempData.TradeStack = TradeStack;
|
|
|
|
return CargoAddItem(&TempData);
|
|
}
|
|
|
|
|
|
struct QualityArray
|
|
{
|
|
int ItemType;
|
|
int ItemField;
|
|
int Direction; // 0 = Up 1 = Down
|
|
float MaxQuality;
|
|
float MinQuality;
|
|
};
|
|
|
|
bool Player::QualityCalculator(_Item * myItem)
|
|
{
|
|
char InstanceInfo[64];
|
|
char IInstanceInfo[64];
|
|
int QArraySize = 7;
|
|
QualityArray QArray[] = {{14, 5, 0, 1.55f, 0.01f }, // Beams
|
|
{15,21, 1, 1.55f, 0.01f }, // ML
|
|
{16,21, 1, 1.55f, 0.01f }, // Projectiles
|
|
{ 2,26, 0, 1.55f, 0.01f }, // Shields
|
|
{ 6,31, 0, 1.35f, 0.01f }, // Engines Thrust
|
|
{ 6,34, 1, 1.55f, 0.01f }, // Engines Warp Drain
|
|
{ 7,20, 0, 1.55f, 0.01f } // Reactors
|
|
};
|
|
|
|
ItemBase * myItemBase = g_ItemBaseMgr->GetItem(myItem->ItemTemplateID);
|
|
|
|
memset(InstanceInfo, 0, sizeof(InstanceInfo));
|
|
|
|
if (!myItemBase) return false; // early return if item invalid
|
|
|
|
for(int x=0;x<QArraySize;x++)
|
|
{
|
|
if (QArray[x].ItemType == myItemBase->ItemType())
|
|
{
|
|
int FieldID = QArray[x].ItemField;
|
|
// Get Field Type
|
|
int FieldType = myItemBase->FieldType(FieldID);
|
|
float FieldData = 0;
|
|
|
|
// Read in Data
|
|
switch(FieldType)
|
|
{
|
|
// Float
|
|
case 1:
|
|
FieldData = myItemBase->Fields(FieldID)->fData;
|
|
break;
|
|
// Int
|
|
case 2:
|
|
FieldData = (float) myItemBase->Fields(FieldID)->iData;
|
|
break;
|
|
}
|
|
|
|
// Calculate Real Quality Percent
|
|
float RealPercent;
|
|
float ChangeRate;
|
|
float ItemQuality = myItem->Quality;
|
|
float NewFieldValue = 0;
|
|
|
|
// Calculate real percent from numbers
|
|
if (ItemQuality < 1.0f)
|
|
{
|
|
ChangeRate = ((1.0f - QArray[x].MinQuality)/1.0f);
|
|
RealPercent = ItemQuality * ChangeRate + QArray[x].MinQuality;
|
|
}
|
|
else
|
|
{
|
|
ChangeRate = ((QArray[x].MaxQuality - 1.0f)/1.0f);
|
|
RealPercent = (ItemQuality - 1.0f)* ChangeRate + 1.0f;
|
|
}
|
|
|
|
// Calculate the field data
|
|
if (QArray[x].Direction == 1)
|
|
{
|
|
NewFieldValue = (1.0f + (1.0f - RealPercent)) * FieldData;
|
|
}
|
|
else
|
|
{
|
|
NewFieldValue = RealPercent * FieldData;
|
|
}
|
|
|
|
// Client does not read below 1
|
|
if (NewFieldValue < 1.0f)
|
|
NewFieldValue = 1.0f;
|
|
|
|
sprintf(IInstanceInfo, "%d:%4.2f^", FieldID,NewFieldValue);
|
|
strcat(InstanceInfo, IInstanceInfo);
|
|
}
|
|
}
|
|
|
|
if (InstanceInfo[0] != 0)
|
|
{
|
|
memcpy(myItem->InstanceInfo, InstanceInfo, sizeof(InstanceInfo));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int Player::CargoAddItem(_Item * myItem)
|
|
{
|
|
if (myItem->ItemTemplateID < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
ItemBase * myItemBase = g_ItemBaseMgr->GetItem(myItem->ItemTemplateID);
|
|
|
|
if (!myItemBase)
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
u32 curTrade = myItem->TradeStack;
|
|
u32 curStack = myItem->StackCount;
|
|
u32 maxStack = myItemBase->MaxStack();
|
|
|
|
SendItemBase(myItem->ItemTemplateID);
|
|
|
|
// Update the instance information
|
|
QualityCalculator(myItem);
|
|
|
|
// If this is a stackable item, check stacks
|
|
if (maxStack > 1)
|
|
{
|
|
for(u32 i=0; i<ShipIndex()->Inventory.GetCargoSpace(); i++)
|
|
{
|
|
if (ShipIndex()->Inventory.CargoInv.Item[i].GetItemTemplateID() == myItem->ItemTemplateID)
|
|
{
|
|
if (ShipIndex()->Inventory.CargoInv.Item[i].GetStackCount() + curStack > maxStack)
|
|
{
|
|
// There is SOME room in this slot
|
|
u32 moved = maxStack - ShipIndex()->Inventory.CargoInv.Item[i].GetStackCount();
|
|
curStack -= moved;
|
|
|
|
ShipIndex()->Inventory.CargoInv.Item[i].AddTradeStack(curTrade < moved ? curTrade : moved);
|
|
curTrade -= moved;
|
|
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetStackCount(maxStack);
|
|
SaveInventoryChange(i);
|
|
}
|
|
else
|
|
{
|
|
// Enough room here for the rest of the stack
|
|
curStack += ShipIndex()->Inventory.CargoInv.Item[i].GetStackCount();
|
|
curTrade += ShipIndex()->Inventory.CargoInv.Item[i].GetTradeStack();
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetStackCount(curStack);
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetTradeStack(curTrade);
|
|
SaveInventoryChange(i);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// At this point, we need to fill empty slots with the item
|
|
for(u32 i=0; i<ShipIndex()->Inventory.GetCargoSpace(); i++)
|
|
{
|
|
if (ShipIndex()->Inventory.CargoInv.Item[i].GetItemTemplateID() == -1)
|
|
{
|
|
if (curStack > maxStack)
|
|
{
|
|
// We have more than a full stack
|
|
curStack -= maxStack;
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetData(myItem);
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetStackCount(maxStack);
|
|
|
|
// The tradable count is the smaller amount of whats left tradable and max stack
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetTradeStack(curTrade < maxStack ? curTrade : maxStack);
|
|
|
|
// The SetTradeStack method converts negative numbers to zero so this is allowerd
|
|
curTrade -= maxStack;
|
|
|
|
SaveInventoryChange(i);
|
|
}
|
|
else
|
|
{
|
|
// Enough room here to finish adding this item
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetData(myItem);
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetStackCount(curStack);
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetTradeStack(curTrade);
|
|
SaveInventoryChange(i);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -3;
|
|
}
|
|
|
|
void Player::CargoRemoveItem(long ItemID, long Stack)
|
|
{
|
|
if (ItemID < 0 || Stack <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
long ItemStack;
|
|
for (u32 i=0; i<ShipIndex()->Inventory.GetCargoSpace(); i++)
|
|
{
|
|
if (ShipIndex()->Inventory.CargoInv.Item[i].GetItemTemplateID() == ItemID)
|
|
{
|
|
ItemStack = ShipIndex()->Inventory.CargoInv.Item[i].GetStackCount();
|
|
|
|
if (ItemStack <= Stack)
|
|
{
|
|
ShipIndex()->Inventory.CargoInv.Item[i].Empty();
|
|
Stack -= ItemStack;
|
|
}
|
|
else
|
|
{
|
|
ItemStack -= Stack;
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetStackCount(ItemStack);
|
|
Stack = 0;
|
|
}
|
|
|
|
SaveInventoryChange(i);
|
|
|
|
if (Stack == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Stack != 0)
|
|
{
|
|
LogMessage("RemoveTradeItem - Stack Remaining: %d\n",Stack);
|
|
}
|
|
}
|
|
|
|
/* Moving an item from Source to Destination, check if they can stack */
|
|
/* Note: If modified, the source and destination stacks have to be inverted */
|
|
|
|
/* This currently does not check quality */
|
|
void Player::CheckStack(int MoveNum, _Item * Source, _Item * Destination)
|
|
{
|
|
/* If the items have the same ID they can stack */
|
|
if (Source->ItemTemplateID == Destination->ItemTemplateID)
|
|
{
|
|
ItemBase * myItemBase = g_ItemBaseMgr->GetItem(Source->ItemTemplateID);
|
|
|
|
if (!myItemBase)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* If the MoveNum has enough items to make a full stack at Destination */
|
|
if (Destination->StackCount + MoveNum > myItemBase->MaxStack())
|
|
{
|
|
int moved = myItemBase->MaxStack() - Destination->StackCount;
|
|
Source->StackCount -= moved;
|
|
Destination->StackCount = myItemBase->MaxStack();
|
|
|
|
/* Now update the trade stacks */
|
|
Destination->TradeStack += (Source->TradeStack < moved ? Source->TradeStack : moved);
|
|
Source->TradeStack -= moved;
|
|
|
|
}
|
|
/* Otherwise the Destination can store the entire MoveNum ammount */
|
|
else
|
|
{
|
|
Destination->StackCount += MoveNum;
|
|
Source->StackCount -= MoveNum;
|
|
|
|
/* Now update the trade stacks */
|
|
Destination->TradeStack += (Source->TradeStack < MoveNum ? Source->TradeStack : MoveNum);
|
|
Source->TradeStack -= MoveNum;
|
|
}
|
|
|
|
/* Switch the Source and Destination stack counts */
|
|
u32 tmpStack = Destination->StackCount;
|
|
Destination->StackCount = Source->StackCount;
|
|
Source->StackCount = tmpStack;
|
|
|
|
/* Now switch their trade stacks aswell */
|
|
tmpStack = Destination->TradeStack;
|
|
Destination->TradeStack = Source->TradeStack;
|
|
Source->TradeStack = tmpStack;
|
|
|
|
/* If weve moved all of the items out of the source, set it to an empty item */
|
|
if (Destination->StackCount == 0)
|
|
{
|
|
memcpy(Destination, &g_ItemBaseMgr->EmptyItem, sizeof(_Item));
|
|
}
|
|
}
|
|
/* If the destination is am empty item and we are moving a substack*/
|
|
else if (Destination->ItemTemplateID == -1 && (u32)MoveNum < Source->StackCount)
|
|
{
|
|
/* Copy the source item to the destination */
|
|
memcpy(Destination, Source, sizeof(_Item));
|
|
|
|
Destination->StackCount = MoveNum;
|
|
Source->StackCount -= MoveNum;
|
|
|
|
/* Now update the trade stacks */
|
|
Destination->TradeStack += (Source->TradeStack < MoveNum ? Source->TradeStack : MoveNum);
|
|
Source->TradeStack -= MoveNum;
|
|
|
|
/* Switch the Source and Destination stack counts */
|
|
u32 tmpStack = Destination->StackCount;
|
|
Destination->StackCount = Source->StackCount;
|
|
Source->StackCount = tmpStack;
|
|
|
|
/* Now switch their trade stacks aswell */
|
|
tmpStack = Destination->TradeStack;
|
|
Destination->TradeStack = Source->TradeStack;
|
|
Source->TradeStack = tmpStack;
|
|
|
|
/* If weve moved all of the items out of the source, set it to an empty item */
|
|
if (Destination->StackCount == 0)
|
|
{
|
|
memcpy(Destination, &g_ItemBaseMgr->EmptyItem, sizeof(_Item));
|
|
}
|
|
}
|
|
}
|
|
|
|
void Player::SetPrices()
|
|
{
|
|
u32 i;
|
|
ItemBase * Item = 0;
|
|
|
|
for (i=0; i<96; i++)
|
|
{
|
|
PlayerIndex()->SecureInv.Item[i].SetPrice(
|
|
GetVenderBuyPrice(PlayerIndex()->SecureInv.Item[i].GetItemTemplateID())
|
|
);
|
|
}
|
|
|
|
for (i=0; i<ShipIndex()->Inventory.GetCargoSpace(); i++)
|
|
{
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetPrice(
|
|
GetVenderBuyPrice(ShipIndex()->Inventory.CargoInv.Item[i].GetItemTemplateID())
|
|
);
|
|
}
|
|
}
|
|
|
|
void Player::ClearPrices()
|
|
{
|
|
u32 i;
|
|
|
|
for (i=0; i<96; i++)
|
|
{
|
|
PlayerIndex()->SecureInv.Item[i].SetPrice(0);
|
|
}
|
|
|
|
for (i=0; i<ShipIndex()->Inventory.GetCargoSpace(); i++)
|
|
{
|
|
ShipIndex()->Inventory.CargoInv.Item[i].SetPrice(0);
|
|
}
|
|
}
|