示例#1
0
bool InventoryItem::Merge(InventoryItemRef to_merge, int32 qty, bool notify) {
    if(typeID() != to_merge->typeID()) {
        _log(ITEM__ERROR, "%s (%u): Asked to merge with %s (%u).", itemName().c_str(), itemID(), to_merge->itemName().c_str(), to_merge->itemID());
        return false;
    }
    if(locationID() != to_merge->locationID() || flag() != to_merge->flag()) {
        _log(ITEM__ERROR, "%s (%u) in location %u, flag %u: Asked to merge with item %u in location %u, flag %u.", itemName().c_str(), itemID(), locationID(), flag(), to_merge->itemID(), to_merge->locationID(), to_merge->flag());
        return false;
    }
    if(qty == 0)
        qty = to_merge->quantity();
    if(qty <= 0) {
        _log(ITEM__ERROR, "%s (%u): Asked to merge with %d units of item %u.", itemName().c_str(), itemID(), qty, to_merge->itemID());
        return false;
    }
    if(!AlterQuantity(qty, notify)) {
        _log(ITEM__ERROR, "%s (%u): Failed to add quantity %d.", itemName().c_str(), itemID(), qty);
        return false;
    }

    if(qty == to_merge->quantity()) {
        to_merge->Delete();
    } else if(!to_merge->AlterQuantity(-qty, notify)) {
        _log(ITEM__ERROR, "%s (%u): Failed to remove quantity %d.", to_merge->itemName().c_str(), to_merge->itemID(), qty);
        return false;
    }

    return true;
}
示例#2
0
void Contract::GetItemRow( InventoryItemRef item, PyPackedRow* into ) const
{
    into->SetField( "contractID",								new PyInt( contractID() ) );
    into->SetField( "itemID",									new PyInt( item->itemID() ) );
    into->SetField( "quantity",									new PyInt( item->quantity() ) );
    into->SetField( "itemTypeID",								new PyInt( item->typeID() ) );
    into->SetField( "inCrate",									new PyBool( true ) );

    if( item->categoryID() == EVEDB::invCategories::Blueprint )
    {
        BlueprintRef bp = m_itemFactory.GetBlueprint( item->itemID() );
        into->SetField( "parentID",								new PyInt( bp->parentBlueprintTypeID() ) );
        into->SetField( "productivityLevel",					new PyInt( bp->productivityLevel() ) );
        into->SetField( "materialLevel",						new PyInt( bp->materialLevel() ) );
        into->SetField( "copy",									new PyInt( bp->copy() ) );
        into->SetField( "licensedProductionRunsRemaining",		new PyInt( bp->licensedProductionRunsRemaining() ) );
    }
    else
    {
        into->SetField( "parentID",								new PyInt( 0 ) );
        into->SetField( "productivityLevel",					new PyInt( 0 ) );
        into->SetField( "materialLevel",						new PyInt( 0 ) );
        into->SetField( "copy",									new PyInt( 0 ) );
        into->SetField( "licensedProductionRunsRemaining",		new PyInt( 0 ) );
    }

    if( item->HasAttribute( AttrDamage ) )
        into->SetField( "damage",								new PyInt( item->GetAttribute( AttrDamage ).get_int() ) );
    else
        into->SetField( "damage",								new PyInt( 0 ) );

    into->SetField( "flagID",									new PyInt( item->flag() ) );
}
示例#3
0
/*
 * InventoryEx
 */
void InventoryEx::ValidateAddItem(EVEItemFlags flag, InventoryItemRef item) const
{
    //double volume = item->quantity() * item->volume();
	EvilNumber volume = EvilNumber(item->quantity()) * item->GetAttribute(AttrVolume);
    double capacity = GetRemainingCapacity( flag );
    if( volume > capacity )
    {
        std::map<std::string, PyRep *> args;

        args["available"] = new PyFloat( capacity );
        args["volume"] = volume.GetPyObject();

        throw PyException( MakeUserError( "NotEnoughCargoSpace", args ) );
    }
}
示例#4
0
void ModuleManager::LoadCharge(InventoryItemRef chargeRef, EVEItemFlags flag)
{
    ActiveModule * mod = (ActiveModule *)(m_Modules->GetModule(flag));			// Should not be dangrous to assume ALL modules where charges are loaded are ACTIVE modules
    if( mod != NULL )
    {
		// Scenarios to handle:
		// + no charge loaded: check capacity >= volume of charge to add, if true, LOAD
		//     - ELSE: if charge to load is qty > 1, calculate smallest integer qty that will EQUAL capacity, SPLIT remainder off, then LOAD!
		// + some charge loaded: check capacity >= volume of charge to add, if true, MERGE new charge to existing
		//     - ELSE: if charge to load is qty > 1, calculate smallest integer qty that added to existing charge qty will EQUAL capacity, SPLIT remainder off, then LOAD!

		// Key facts to get:
		// * existing charge ref -> qty and volume/unit
		// * module ref -> capacity of module
		// * charge to add ref -> qty and volume/unit

		EvilNumber modCapacity = mod->getItem()->GetAttribute(AttrCapacity);
		EvilNumber chargeToLoadVolume = chargeRef->GetAttribute(AttrVolume);
		EvilNumber chargeToLoadQty = EvilNumber(chargeRef->quantity());

		/////////////////////////////////////////
		// chargeRef->Split();
		// chargeRef->Merge();
		// mod->Load(chargeRef);
		// chargeRef->Move(m_Ship->itemID(), flag);		// used to be (m_pOperator->GetLocationID(), flag)
		/////////////////////////////////////////

		//m_Ship->GetOperator()->Client()->MoveItem(chargeRef->itemID(), m_Ship->itemID(), flag);

		if( mod->isLoaded() )
		{
			// Module is loaded, let's check available capacity:
			InventoryItemRef loadedChargeRef = mod->getLoadedChargeRef();
			EvilNumber loadedChargeVolume = loadedChargeRef->GetAttribute(AttrVolume);
			EvilNumber loadedChargeQty = EvilNumber(loadedChargeRef->quantity());
			modCapacity -= (loadedChargeVolume * loadedChargeQty);		// Calculate remaining capacity
			if( chargeRef->typeID() != loadedChargeRef->typeID() )
			{
				// Different charge type is being swapped into this module, so unload what's loaded
				if( IsStation(m_Ship->GetOperator()->GetLocationID()) )
					loadedChargeRef->Move(m_Ship->locationID(), flagHangar);
				else
				{
					m_Ship->ValidateAddItem(flagCargoHold,loadedChargeRef);
					loadedChargeRef->Move(m_Ship->itemID(), flagCargoHold);
				}
				mod->unload();

				// Loading of charge will be performed below
			}
			else
			{
				if( modCapacity > chargeToLoadVolume )
				{
					// Great!  We can load at least one, let's top off the loaded charges:
					uint32 quantityWeCanLoad = floor((modCapacity / chargeToLoadVolume).get_float());
					if( quantityWeCanLoad > 0 )
					{
						if( quantityWeCanLoad < chargeToLoadQty.get_int() )
						{
							// Split chargeRef to qty 'quantityWeCanLoad'
							// Merge new smaller qty 'quantityWeCanLoad' with loadedChargeRef
							// Load this merged charge Ref into module
							InventoryItemRef loadableChargeQtyRef = chargeRef->Split( quantityWeCanLoad );
							loadableChargeQtyRef->ChangeOwner( chargeRef->ownerID() );
							loadedChargeRef->Merge( loadableChargeQtyRef );
							mod->load( loadedChargeRef );
							loadedChargeRef->Move(m_Ship->itemID(), flag);		// used to be (m_pOperator->GetLocationID(), flag)
						}
						else
						{
							// Merge chargeRef with loadedChargeRef
							// Load this merged charge Ref into module
							loadedChargeRef->Merge( chargeRef );
							mod->load( loadedChargeRef );
							loadedChargeRef->Move(m_Ship->itemID(), flag);		// used to be (m_pOperator->GetLocationID(), flag)
						}
					}
					else
						throw PyException( MakeCustomError( "Cannot load even one unit of this charge!" ) );
				}
				else
				{
					throw PyException( MakeCustomError( "Charge is full!" ) );
				}
			}
		}

		// Refresh ammo capacity of module in case it was modified in previous code block ahead of a load action:
		modCapacity = mod->getItem()->GetAttribute(AttrCapacity);

		// Load charge supplied if this module was either never loaded, or just unloaded from a different type right above:
		if( !(mod->isLoaded()) )
		{
			// Module is not loaded at all, let's check total volume of charge to load against available capacity:
			if( modCapacity >= (chargeToLoadVolume * chargeToLoadQty) )
			{
				// We can insert entire stack of chargeRef into module
				// Load chargeRef as-is into module
				mod->load( chargeRef );
				chargeRef->Move(m_Ship->itemID(), flag);		// used to be (m_pOperator->GetLocationID(), flag)
			}
			else
			{
				// We need to split off only as many charge units as can fit into this module
				// Split chargeRef
				uint32 quantityWeCanLoad = floor((modCapacity / chargeToLoadVolume).get_float());
				if( quantityWeCanLoad > 0 )
				{
					// Split chargeRef to qty 'quantityWeCanLoad'
					// Merge new smaller qty 'quantityWeCanLoad' with loadedChargeRef
					// Load this merged charge Ref into module
					InventoryItemRef loadableChargeQtyRef = chargeRef->Split( quantityWeCanLoad );
					loadableChargeQtyRef->ChangeOwner( chargeRef->ownerID() );
					mod->load( loadableChargeQtyRef );
					loadableChargeQtyRef->Move(m_Ship->itemID(), flag);		// used to be (m_pOperator->GetLocationID(), flag)
				}
				else
		            throw PyException( MakeCustomError( "Cannot load even one unit of this charge!" ) );
			}
		}
    }
}
示例#5
0
void Ship::RemoveItem(InventoryItemRef item, uint32 inventoryID, EVEItemFlags flag)
{
    // If item IS a module and it's being removed from a slot:
	if( (item->categoryID() == EVEDB::invCategories::Module) && ((item->flag() >= flagLowSlot0)  &&  (item->flag() <= flagHiSlot7)) )
	{
        m_pOperator->GetShip()->Deactivate( item->itemID(), "online" );
        // m_pOperator->GetShip()->Set_mass( m_pOperator->GetShip()->mass() - item->massAddition() );
        //m_pOperator->GetShip()->SetAttribute(AttrMass,  m_pOperator->GetShip()->GetAttribute(AttrMass) - item->GetAttribute(AttrMassAddition) );
        m_pOperator->GetShip()->UnloadModule( item->itemID() );
    }

	// If item IS a rig and it's being removed from a slot:
	if( (item->categoryID() == EVEDB::invCategories::Module) && ((item->flag() >= flagRigSlot0)  &&  (item->flag() <= flagRigSlot7)) )
	{
		// Don't know what to do when removing a Rig... yet ;)
	}

	// If item IS a rig and it's being removed from a slot:
	if( (item->categoryID() == EVEDB::invCategories::Subsystem) && ((item->flag() >= flagSubSystem0)  &&  (item->flag() <= flagSubSystem7)) )
	{
		// Don't know what to do when removing a Subsystem... yet ;)
	}

	// if item being removed IS a charge, it needs to be removed via Module Manager so modules know charge is removed,
	// BUT, only if it is loaded into a module in one of the 3 slot banks, so we also check its flag value:
	if( (item->categoryID() == EVEDB::invCategories::Charge) && ((item->flag() >= flagLowSlot0)  &&  (item->flag() <= flagHiSlot7)) )
	{
		m_ModuleManager->UnloadCharge(item->flag());
	}

	if( item->flag() == flag )
		// Item's already been moved, let's return
		return;

    // Move New item to its new location:
	if( !( ((item->flag() >= flagLowSlot0)  &&  (item->flag() <= flagHiSlot7)) || ((item->flag() >= flagRigSlot0)  &&  (item->flag() <= flagRigSlot7))
		|| ((item->flag() >= flagSubSystem0)  &&  (item->flag() <= flagSubSystem7)) ) )
    {
        _DecreaseCargoHoldsUsedVolume(item->flag(), (item->getAttribute(AttrVolume).get_float() * item->quantity()));
		m_pOperator->MoveItem(item->itemID(), inventoryID, flag);
	}
	else
	{
		m_pOperator->MoveItem(item->itemID(), inventoryID, flag);
	}
}
示例#6
0
uint32 Ship::AddItem(EVEItemFlags flag, InventoryItemRef item)
{
    ValidateAddItem( flag, item );

    //it's a new module, make sure it's state starts at offline so that it is added correctly
    if( item->categoryID() == EVEDB::invCategories::Module )
        item->PutOffline();

	switch( item->categoryID() )
	{
		case EVEDB::invCategories::Charge:
			{
				m_ModuleManager->LoadCharge(item, flag);
				InventoryItemRef loadedChargeOnModule = m_ModuleManager->GetLoadedChargeOnModule(flag);
				if( loadedChargeOnModule )
				{
					return loadedChargeOnModule->itemID();
				}
				else
					return 0;
			}
			break;

		case EVEDB::invCategories::Module:
			if( m_ModuleManager->FitModule(item, flag) )
				item->Move(itemID(), flag);
			break;

		// The default case handles ANY other items added to ship and assumes they go into one of the valid cargo holds on this ship:
		default:
			//Log::Error( "Ship::AddItem(flag,item)", "ERROR! Function called with item '%s' (id: %u) of category neither Charge nor Module!", item->itemName().c_str(), item->itemID() );
            _IncreaseCargoHoldsUsedVolume(item->flag(), (item->getAttribute(AttrVolume).get_float() * item->quantity()));
			item->Move(itemID(), flag);
			break;
	}

	return 0;
}
示例#7
0
bool Ship::ValidateAddItem(EVEItemFlags flag, InventoryItemRef item) const
{
    CharacterRef character = m_pOperator->GetChar();

    if( flag == flagDroneBay )
    {
        if (item->categoryID() != EVEDB::invCategories::Drone)
        {
            //Can only put drones in drone bay
            throw PyException(MakeUserError("ItemCannotBeInDroneBay"));
        }
    }
    else if( flag == flagShipHangar )
    {
        if (m_pOperator->GetShip()->getAttribute(AttrHasShipMaintenanceBay) != 0)
        {
            // We have no ship maintenance bay
            throw PyException(MakeCustomError("%s has no ship maintenance bay.", item->itemName().c_str()));
        }
        if (item->categoryID() != EVEDB::invCategories::Ship)
        {
            // Only ships may be put here
            throw PyException(MakeCustomError("Only ships may be placed into ship maintenance bay."));
        }
    }
    else if( flag == flagHangar )
    {
        if (m_pOperator->GetShip()->getAttribute(AttrHasCorporateHangars) != 0)
        {
            // We have no corporate hangars
            throw PyException(MakeCustomError("%s has no corporate hangars.", item->itemName().c_str()));
        }
    }
    else if( (flag >= flagLowSlot0)  &&  (flag <= flagHiSlot7) )
    {
        if (m_pOperator->IsClient())
        {
            // SKIP THIS SKILL CHECK if Operator is NOT Client *
            if (!character->canUse(item))
            {
                throw PyException(MakeCustomError("You do not have the required skills to fit this \n%s", item->itemName().c_str()));
            }
        }
        if (!ValidateItemSpecifics(item))
        {
            throw PyException(MakeCustomError("Your ship cannot equip this module"));
        }
        if(item->categoryID() == EVEDB::invCategories::Charge)
		{
			if( m_ModuleManager->GetModule(flag) != NULL )
			{
				InventoryItemRef module;
				module = m_ModuleManager->GetModule(flag)->getItem();
                if (module->getAttribute(AttrChargeSize) != item->getAttribute(AttrChargeSize))
					throw PyException( MakeCustomError( "The charge is not the correct size for this module." ) );
                if (module->getAttribute(AttrChargeGroup1) != item->groupID())
					throw PyException( MakeCustomError( "Incorrect charge type for this module.") );

				// NOTE: Module Manager will check for actual room to load charges and make stack splits, or reject loading altogether
            }
            else
            {
                throw PyException(MakeCustomError("Module at flag '%u' does not exist!", flag));
            }
        }
		else
        {
            if (m_ModuleManager->IsSlotOccupied(flag))
            {
                throw PyException(MakeUserError("SlotAlreadyOccupied"));
            }
        }
        return true;
    }
    else if( (flag >= flagRigSlot0)  &&  (flag <= flagRigSlot7) )
    {
        if (m_pOperator->IsClient())
        {
            // SKIP THIS SKILL CHECK if Operator is NOT Client *
            if (!character->canUse(item))
            {
                throw PyException(MakeCustomError("You do not have the required skills to fit this \n%s", item->itemName().c_str()));
            }
        }
        if (m_pOperator->GetShip()->getAttribute(AttrRigSize) != item->getAttribute(AttrRigSize))
        {
            throw PyException(MakeCustomError("Your ship cannot fit this size module"));
        }
        if (m_pOperator->GetShip()->getAttribute(AttrUpgradeLoad) + item->getAttribute(AttrUpgradeCost) > m_pOperator->GetShip()->getAttribute(AttrUpgradeCapacity))
        {
            throw PyException(MakeCustomError("Your ship cannot handle the extra calibration"));
        }
        return true;
    }
    else if( (flag >= flagSubSystem0)  &&  (flag <= flagSubSystem7) )
    {
        if (m_pOperator->IsClient())
        {
            // SKIP THIS SKILL CHECK if Operator is NOT Client *
            if (!character->canUse(item))
            {
                throw PyException(MakeCustomError("You do not have the required skills to fit this \n%s", item->itemName().c_str()));
            }
        }
        return true;
    }
    // Handle any other flag, legal or not by virtue of GetRemainingVolumeByFlag() and GetCapacity() that handle supported capacity types:
    // (unsupported or illegal flags report capacity of 0.0, so are automatically rejected)
    double capacityRemaining(0.0);
    capacityRemaining = GetRemainingVolumeByFlag(flag);

    // Check for sufficient capacity.
    if ((capacityRemaining < (item->getAttribute(AttrVolume).get_float() * (double) item->quantity())))
    {
        throw PyException(MakeCustomError("Not enough cargo space!<br><br>flag = %u", (uint32) flag));
        return false;
    }

	return true;
}