InventoryItemRef InventoryItem::Spawn(ItemFactory &factory, ItemData &data) { // obtain type of new item const ItemType *t = factory.GetType( data.typeID ); if( t == NULL ) return InventoryItemRef(); // See what to do next: switch( t->categoryID() ) { //! TODO not handled. case EVEDB::invCategories::_System: case EVEDB::invCategories::Station: case EVEDB::invCategories::Material: case EVEDB::invCategories::Accessories: case EVEDB::invCategories::Charge: case EVEDB::invCategories::Trading: case EVEDB::invCategories::Bonus: case EVEDB::invCategories::Commodity: case EVEDB::invCategories::Implant: case EVEDB::invCategories::Reaction: break; /////////////////////////////////////// // Entity: /////////////////////////////////////// case EVEDB::invCategories::Entity: { // Spawn generic item for Entities at this time: uint32 itemID = InventoryItem::_SpawnEntity( factory, data ); if( itemID == 0 ) return InventoryItemRef(); InventoryItemRef itemRef = InventoryItem::LoadEntity( factory, itemID, data ); return itemRef; } /////////////////////////////////////// // Blueprint: /////////////////////////////////////// case EVEDB::invCategories::Blueprint: { BlueprintData bdata; // use default blueprint attributes BlueprintRef blueRef = Blueprint::Spawn( factory, data, bdata ); blueRef.get()->SaveAttributes(); return blueRef; } /////////////////////////////////////// // Celestial: // (used for Cargo Containers, Rings, and Biomasses, Wrecks, Large Collidable Objects, Clouds, // Cosmic Signatures, Mobile Sentry Guns, Global Warp Disruptors, Agents in Space, Cosmic Anomaly, Beacons, Wormholes, // and other celestial static objects such as NPC stations, stars, moons, planets, and stargates) /////////////////////////////////////// case EVEDB::invCategories::Celestial: { if ( (t->groupID() == EVEDB::invGroups::Secure_Cargo_Container) || (t->groupID() == EVEDB::invGroups::Cargo_Container) || (t->groupID() == EVEDB::invGroups::Freight_Container) || (t->groupID() == EVEDB::invGroups::Audit_Log_Secure_Container) || (t->groupID() == EVEDB::invGroups::Spawn_Container) || (t->groupID() == EVEDB::invGroups::Wreck) ) { // Spawn new Cargo Container uint32 itemID = CargoContainer::_Spawn( factory, data ); if( itemID == 0 ) return CargoContainerRef(); CargoContainerRef cargoRef = CargoContainer::Load( factory, itemID ); // THESE SHOULD BE MOVED INTO A CargoContainer::Spawn() function that does not exist yet // Create default dynamic attributes in the AttributeMap: cargoRef.get()->SetAttribute(AttrIsOnline, 1); // Is Online cargoRef.get()->SetAttribute(AttrDamage, 0.0); // Structure Damage //cargoRef.get()->SetAttribute(AttrShieldCharge, cargoRef.get()->GetAttribute(AttrShieldCapacity)); // Shield Charge //cargoRef.get()->SetAttribute(AttrArmorDamage, 0.0); // Armor Damage cargoRef.get()->SetAttribute(AttrMass, cargoRef.get()->type().attributes.mass()); // Mass cargoRef.get()->SetAttribute(AttrRadius, cargoRef.get()->type().attributes.radius()); // Radius cargoRef.get()->SetAttribute(AttrVolume, cargoRef.get()->type().attributes.volume()); // Volume cargoRef.get()->SetAttribute(AttrCapacity, cargoRef.get()->type().attributes.capacity()); // Capacity cargoRef.get()->SaveAttributes(); return cargoRef; //uint32 itemID = InventoryItem::_Spawn( factory, data ); //if( itemID == 0 ) // return InventoryItemRef(); //return InventoryItem::Load( factory, itemID ); } else { // Spawn new Celestial Object uint32 itemID = CelestialObject::_Spawn( factory, data ); if( itemID == 0 ) return CelestialObjectRef(); CelestialObjectRef celestialRef = CelestialObject::Load( factory, itemID ); celestialRef.get()->SaveAttributes(); return celestialRef; } } /////////////////////////////////////// // Ship: /////////////////////////////////////// case EVEDB::invCategories::Ship: { ShipRef shipRef = Ship::Spawn( factory, data ); shipRef.get()->SaveAttributes(); return shipRef; } /////////////////////////////////////// // Skill: /////////////////////////////////////// case EVEDB::invCategories::Skill: { return Skill::Spawn( factory, data ); } /////////////////////////////////////// // Owner: /////////////////////////////////////// case EVEDB::invCategories::Owner: { return Owner::Spawn( factory, data ); } /////////////////////////////////////// // Module: /////////////////////////////////////// case EVEDB::invCategories::Module: { // Spawn generic item: uint32 itemID = InventoryItem::_Spawn( factory, data ); if( itemID == 0 ) return InventoryItemRef(); InventoryItemRef itemRef = InventoryItem::Load( factory, itemID ); // THESE SHOULD BE MOVED INTO A Module::Spawn() function that does not exist yet // Create default dynamic attributes in the AttributeMap: itemRef.get()->SetAttribute(AttrIsOnline, 1); // Is Online itemRef.get()->SetAttribute(AttrDamage, 0.0); // Structure Damage //itemRef.get()->SetAttribute(AttrShieldCharge, itemRef.get()->GetAttribute(AttrShieldCapacity)); // Shield Charge //itemRef.get()->SetAttribute(AttrArmorDamage, 0.0); // Armor Damage itemRef.get()->SetAttribute(AttrMass, itemRef.get()->type().attributes.mass()); // Mass itemRef.get()->SetAttribute(AttrRadius, itemRef.get()->type().attributes.radius()); // Radius itemRef.get()->SetAttribute(AttrVolume, itemRef.get()->type().attributes.volume()); // Volume itemRef.get()->SetAttribute(AttrCapacity, itemRef.get()->type().attributes.capacity()); // Capacity itemRef.get()->SaveAttributes(); return itemRef; } /////////////////////////////////////// // Drone: /////////////////////////////////////// case EVEDB::invCategories::Drone: { // Spawn generic item: uint32 itemID = InventoryItem::_Spawn( factory, data ); if( itemID == 0 ) return InventoryItemRef(); InventoryItemRef itemRef = InventoryItem::Load( factory, itemID ); // THESE SHOULD BE MOVED INTO A Drone::Spawn() function that does not exist yet // Create default dynamic attributes in the AttributeMap: itemRef.get()->SetAttribute(AttrIsOnline, 1); // Is Online itemRef.get()->SetAttribute(AttrDamage, 0.0); // Structure Damage itemRef.get()->SetAttribute(AttrShieldCharge, itemRef.get()->GetAttribute(AttrShieldCapacity)); // Shield Charge itemRef.get()->SetAttribute(AttrArmorDamage, 0.0); // Armor Damage itemRef.get()->SetAttribute(AttrMass, itemRef.get()->type().attributes.mass()); // Mass itemRef.get()->SetAttribute(AttrRadius, itemRef.get()->type().attributes.radius()); // Radius itemRef.get()->SetAttribute(AttrVolume, itemRef.get()->type().attributes.volume()); // Volume itemRef.get()->SetAttribute(AttrCapacity, itemRef.get()->type().attributes.capacity()); // Capacity itemRef.get()->SaveAttributes(); return itemRef; } /////////////////////////////////////// // Deployable: /////////////////////////////////////// case EVEDB::invCategories::Deployable: { // Spawn generic item: uint32 itemID = InventoryItem::_Spawn( factory, data ); if( itemID == 0 ) return InventoryItemRef(); InventoryItemRef itemRef = InventoryItem::Load( factory, itemID ); // THESE SHOULD BE MOVED INTO A Deployable::Spawn() function that does not exist yet // Create default dynamic attributes in the AttributeMap: itemRef.get()->SetAttribute(AttrIsOnline, 1); // Is Online itemRef.get()->SetAttribute(AttrDamage, 0.0); // Structure Damage //itemRef.get()->SetAttribute(AttrShieldCharge, itemRef.get()->GetAttribute(AttrShieldCapacity)); // Shield Charge //itemRef.get()->SetAttribute(AttrArmorDamage, 0.0); // Armor Damage itemRef.get()->SetAttribute(AttrMass, itemRef.get()->type().attributes.mass()); // Mass itemRef.get()->SetAttribute(AttrRadius, itemRef.get()->type().attributes.radius()); // Radius itemRef.get()->SetAttribute(AttrVolume, itemRef.get()->type().attributes.volume()); // Volume itemRef.get()->SetAttribute(AttrCapacity, itemRef.get()->type().attributes.capacity()); // Capacity itemRef.get()->SaveAttributes(); return itemRef; } /////////////////////////////////////// // Asteroid: /////////////////////////////////////// case EVEDB::invCategories::Asteroid: { // Spawn generic item: uint32 itemID = InventoryItem::_Spawn( factory, data ); if( itemID == 0 ) return InventoryItemRef(); InventoryItemRef itemRef = InventoryItem::Load( factory, itemID ); // THESE SHOULD BE MOVED INTO AN Asteroid::Spawn() function that does not exist yet // Create default dynamic attributes in the AttributeMap: itemRef.get()->SetAttribute(AttrRadius, 500.0); // Radius itemRef.get()->SetAttribute(AttrMass, 1000000.0); // Mass itemRef.get()->SetAttribute(AttrVolume, 8000.0); // Volume itemRef.get()->SetAttribute(AttrQuantity, 1000.0); // Quantity itemRef.get()->SaveAttributes(); return itemRef; } /////////////////////////////////////// // Structure: /////////////////////////////////////// case EVEDB::invCategories::Structure: { // Spawn generic item: uint32 itemID = InventoryItem::_Spawn( factory, data ); if( itemID == 0 ) return InventoryItemRef(); InventoryItemRef itemRef = InventoryItem::Load( factory, itemID ); // THESE SHOULD BE MOVED INTO A Structure::Spawn() function that does not exist yet // Create default dynamic attributes in the AttributeMap: itemRef.get()->SetAttribute(AttrIsOnline, 1); // Is Online itemRef.get()->SetAttribute(AttrDamage, 0.0); // Structure Damage itemRef.get()->SetAttribute(AttrShieldCharge, itemRef.get()->GetAttribute(AttrShieldCapacity)); // Shield Charge itemRef.get()->SetAttribute(AttrArmorDamage, 0.0); // Armor Damage itemRef.get()->SetAttribute(AttrMass, itemRef.get()->type().attributes.mass()); // Mass itemRef.get()->SetAttribute(AttrRadius, itemRef.get()->type().attributes.radius()); // Radius itemRef.get()->SetAttribute(AttrVolume, itemRef.get()->type().attributes.volume()); // Volume itemRef.get()->SetAttribute(AttrCapacity, itemRef.get()->type().attributes.capacity()); // Capacity itemRef.get()->SaveAttributes(); return itemRef; } } switch( t->groupID() ) { /////////////////////////////////////// // Station: /////////////////////////////////////// case EVEDB::invGroups::Station: { //_log( ITEM__ERROR, "Refusing to create station '%s'.", data.name.c_str() ); //return InventoryItemRef(); //return Station::Spawn( factory, data ); uint32 itemID = Station::_Spawn( factory, data ); if( itemID == 0 ) return StationRef(); StationRef stationRef = Station::Load( factory, itemID ); // THESE SHOULD BE MOVED INTO A Station::Spawn() function that does not exist yet // Create default dynamic attributes in the AttributeMap: stationRef.get()->SetAttribute(AttrIsOnline, 1); // Is Online stationRef.get()->SetAttribute(AttrDamage, 0.0); // Structure Damage stationRef.get()->SetAttribute(AttrShieldCharge,stationRef.get()->GetAttribute(AttrShieldCapacity)); // Shield Charge stationRef.get()->SetAttribute(AttrArmorDamage, 0.0); // Armor Damage stationRef.get()->SetAttribute(AttrMass, stationRef.get()->type().attributes.mass()); // Mass stationRef.get()->SetAttribute(AttrRadius, stationRef.get()->type().attributes.radius()); // Radius stationRef.get()->SetAttribute(AttrVolume, stationRef.get()->type().attributes.volume()); // Volume stationRef.get()->SetAttribute(AttrCapacity, stationRef.get()->type().attributes.capacity()); // Capacity stationRef.get()->SaveAttributes(); return stationRef; } } // Spawn generic item: uint32 itemID = InventoryItem::_Spawn( factory, data ); if( itemID == 0 ) return InventoryItemRef(); InventoryItemRef itemRef = InventoryItem::Load( factory, itemID ); itemRef.get()->SaveAttributes(); return itemRef; }
bool MiningLaser::endCycle(bool continuing) { // Check to see if our target is still in this bubble or has left or been destroyed: if( m_ship->GetOperator()->GetSystemEntity()->Bubble()->GetEntity(m_targetID) == nullptr ) { // Target has left our bubble or been destroyed, deactivate this module: return false; } if (m_ship->GetOperator()->GetSystemEntity()->targets.getTarget(m_targetID, true) == nullptr) { // Target no longer targeted. return false; } // Check range double maxRange = m_item->GetAttribute(AttrMaxRange).get_float(); double targetRange = m_targetEntity->DistanceTo2(m_ship->GetOperator()->GetSystemEntity()); targetRange = std::sqrt(targetRange); targetRange -= m_targetEntity->GetRadius(); if (targetRange > maxRange) { // We must have drifted out of range. // TO-DO: send proper out or range response. SysLog::Error("MiningLaser::Activate()", "ERROR: mining laser target moved out of range!"); return false; } // Retrieve ore from target Asteroid and put into flagCargoHold InventoryItemRef asteroidRef = m_targetEntity->Item(); uint32 remainingOreUnits = asteroidRef->GetAttribute(AttrQuantity).get_int(); double oreUnitVolume = asteroidRef->GetAttribute(AttrVolume).get_float(); // Calculate how many units of ore to pull from the asteroid on this cycle: // Get base mining amount. double oreUnitsToPull = m_item->GetAttribute(AttrMiningAmount).get_float() / oreUnitVolume; // Do we have a crystal? if( m_chargeRef ) { // Yes, apply yield multiplier. if (m_chargeRef->HasAttribute(AttrSpecialisationAsteroidYieldMultiplier)) { // TO-DO: check for correct type of crystal. oreUnitsToPull *= m_chargeRef->GetAttribute(AttrSpecialisationAsteroidYieldMultiplier).get_float(); } // TO-DO: do crystal damage. } // Get percent cycle complete. double cycleTime = getTotalCycleTimeMS(); double percent = 1.0; // Assume full cycle if timer disabled. if(cycleTime != -1) { double usedTime = getElapsedCycleTimeMS(); percent = usedTime / cycleTime; // Limit to range 0.0 - 1.0. percent = std::min(1.0, std::max(0.0, percent)); if(percent == 0.0) { percent = 1.0; } } // Round down to next lowest integer value. oreUnitsToPull = floor(oreUnitsToPull * percent); // Limit to units remaining in asteroid. oreUnitsToPull = std::min(oreUnitsToPull, (double) remainingOreUnits); // Find what cargo hold to use. EVEItemFlags cargoFlag = flagCargoHold; // Check for specialized cargo hold. if (m_ship->HasAttribute(AttrSpecialOreHoldCapacity)) { // We have a specialized ore hold all or goes here. cargoFlag = flagSpecializedOreHold; } // Get cargo hold and remaining capacity. double remainingCargoVolume = m_ship->GetRemainingVolumeByFlag(cargoFlag); // Do we have enough room for the whole stack? if (remainingCargoVolume < (floor((oreUnitsToPull * oreUnitVolume) * 100.0)/100.0)) { // No, Do we have room for at least one unit? if (remainingCargoVolume < oreUnitVolume) { // No, Send cargo full message. PyDict *dict = new PyDict(); PyTuple *tuple = new PyTuple(2); tuple->SetItem(0, new PyInt(MOD_ACTIVATED)); //???? what is this really? tuple->SetItem(1, new PyInt(m_item->typeID())); dict->SetItem(new PyString("modulename"), tuple); PyTuple *error = new PyTuple(2); error->SetItem(0, new PyString("MiningDronesDeactivatedCargoHoldNowFull")); error->SetItem(1, dict); m_error = error; return false; } // Yes, reduce the stack size. oreUnitsToPull = floor(remainingCargoVolume / oreUnitVolume); } // Are we actually pulling anything? if (oreUnitsToPull <= 0.0) { // No, hmmm... thats bad! // TO-DO: send client miner deactivated because hold full message. SysLog::Warning("MiningLaser::DoCycle()", "Somehow MiningLaser could not extract ore from current target asteroid '%s' (id %u)", m_targetEntity->Item()->itemName().c_str(), m_targetEntity->GetID()); checkAsteroidDepleted(remainingOreUnits); return false; } // Check for an existing ore item in the cargo. InventoryItemRef existing = m_ship->GetByTypeFlag(asteroidRef->typeID(), cargoFlag); if (existing.get() != nullptr) { // We have an existing ore sample, add to it. m_ship->AlterCargoQty(existing, oreUnitsToPull); } else { // No existing ore sample, create one. ItemData idata( asteroidRef->typeID(), m_ship->ownerID(), 0, //temp location cargoFlag, oreUnitsToPull ); InventoryItemRef ore = ItemFactory::SpawnItem(idata); if (ore) { m_ship->AddItem(cargoFlag, ore); } else { SysLog::Error("MiningLaser::DoCycle()", "ERROR: Could not create ore stack for '%s' ship (id %u)!", m_ship->itemName().c_str(), m_ship->itemID()); return false; } } // Finally, reduce the amount of ore in the asteroid by how much we took out: remainingOreUnits -= oreUnitsToPull; asteroidRef->SetAttribute(AttrQuantity, remainingOreUnits); // Check to see is ship is full or asteroid depleted. remainingCargoVolume = m_ship->GetRemainingVolumeByFlag(cargoFlag); if ((remainingCargoVolume < oreUnitVolume) || remainingOreUnits == 0) { // Asteroid is empty OR cargo hold is entirely full, either way, DEACTIVATE module immediately! checkAsteroidDepleted(remainingOreUnits); return false; } return true; }