BlueprintRef ItemFactory::SpawnBlueprint(ItemData &data, BlueprintData &bpData) { BlueprintRef bi = Blueprint::Spawn(*this, data, bpData); if( !bi ) return BlueprintRef(); m_items.insert( std::make_pair( bi->itemID(), bi ) ); return bi; }
PyResult FactoryService::Handle_GetBlueprintAttributes(PyCallArgs &call) { Call_SingleIntegerArg arg; if(!arg.Decode(&call.tuple)) { _log(SERVICE__ERROR, "Failed to decode args."); return NULL; } BlueprintRef b = ItemFactory::GetBlueprint(arg.arg); if( !b ) return NULL; return b->GetBlueprintAttributes(); }
BlueprintRef Blueprint::SplitBlueprint(int32 qty_to_take, bool notify) { // split item BlueprintRef res = BlueprintRef::StaticCast( InventoryItem::Split( qty_to_take, notify ) ); if( !res ) return BlueprintRef(); // copy our attributes res->SetCopy(m_copy); res->SetMaterialLevel(m_materialLevel); res->SetProductivityLevel(m_productivityLevel); res->SetLicensedProductionRunsRemaining(m_licensedProductionRunsRemaining); return res; }
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() ) ); }
// command to modify blueprint's attributes, we have to give it blueprint's itemID ... // isn't much comfortable, but I don't know about better solution ... PyResult Command_setbpattr( Client* who, CommandDB* db, PyServiceMgr* services, const Seperator& args ) { if( args.argCount() < 6 ) { throw PyException( MakeCustomError("Correct Usage: /setbpattr [blueprintID] [0 (not copy) or 1 (copy)] [material level] [productivity level] [remaining runs]") ); } if( !args.isNumber( 1 ) ) throw PyException( MakeCustomError( "Argument 1 must be blueprint ID. (got %s)", args.arg( 1 ).c_str() ) ); const uint32 blueprintID = atoi( args.arg( 1 ).c_str() ); if( "0" != args.arg( 2 ) && "1" != args.arg( 2 ) ) throw PyException( MakeCustomError( "Argument 2 must be 0 (not copy) or 1 (copy). (got %s)", args.arg( 2 ).c_str() ) ); const bool copy = ( atoi( args.arg( 2 ).c_str() ) ? true : false ); if( !args.isNumber( 3 ) ) throw PyException( MakeCustomError( "Argument 3 must be material level. (got %s)", args.arg( 3 ).c_str() ) ); const uint32 materialLevel = atoi( args.arg( 3 ).c_str() ); if( !args.isNumber( 4 ) ) throw PyException( MakeCustomError( "Argument 4 must be productivity level. (got %s)", args.arg( 4 ).c_str() ) ); const uint32 productivityLevel = atoi( args.arg( 4 ).c_str() ); if( !args.isNumber( 5 ) ) throw PyException( MakeCustomError( "Argument 5 must be remaining licensed production runs. (got %s)", args.arg( 5 ).c_str() ) ); const uint32 licensedProductionRunsRemaining = atoi( args.arg( 5 ).c_str() ); BlueprintRef bp = services->item_factory.GetBlueprint( blueprintID ); if( !bp ) throw PyException( MakeCustomError( "Failed to load blueprint %u.", blueprintID ) ); bp->SetCopy( copy ); bp->SetMaterialLevel( materialLevel ); bp->SetProductivityLevel( productivityLevel ); bp->SetLicensedProductionRunsRemaining( licensedProductionRunsRemaining ); return new PyString( "Properties modified." ); }
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 RamProxyService::_Calculate(const Call_InstallJob &args, InventoryItemRef installedItem, Client *const c, Rsp_InstallJob &into) { if(!m_db.GetAssemblyLineProperties(args.installationAssemblyLineID, into.materialMultiplier, into.timeMultiplier, into.installCost, into.usageCost)) return false; const ItemType *productType; // perform some activity-specific actions switch(args.activityID) { /* * Manufacturing */ case ramActivityManufacturing: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); productType = &bp->productType(); into.productionTime = bp->type().productionTime(); into.materialMultiplier *= bp->materialMultiplier(); into.timeMultiplier *= bp->timeMultiplier(); into.charMaterialMultiplier = c->GetChar()->GetAttribute(AttrManufactureCostMultiplier).get_float(); into.charTimeMultiplier = c->GetChar()->GetAttribute(AttrManufactureTimeMultiplier).get_float(); switch(productType->race()) { case raceCaldari: into.charTimeMultiplier *= double(c->GetChar()->GetAttribute(AttrCaldariTechTimePercent).get_int()) / 100.0; break; case raceMinmatar: into.charTimeMultiplier *= double(c->GetChar()->GetAttribute(AttrMinmatarTechTimePercent).get_int()) / 100.0; break; case raceAmarr: into.charTimeMultiplier *= double(c->GetChar()->GetAttribute(AttrAmarrTechTimePercent).get_int()) / 100.0; break; case raceGallente: into.charTimeMultiplier *= double(c->GetChar()->GetAttribute(AttrGallenteTechTimePercent).get_int()) / 100.0; break; case raceJove: break; case racePirate: break; } break; } /* * Time productivity research */ case ramActivityResearchingTimeProductivity: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); productType = &installedItem->type(); into.productionTime = bp->type().researchProductivityTime(); into.charMaterialMultiplier = double(c->GetChar()->GetAttribute(AttrResearchCostPercent).get_int()) / 100.0; into.charTimeMultiplier = c->GetChar()->GetAttribute(AttrManufacturingTimeResearchSpeed).get_float(); break; } /* * Material productivity research */ case ramActivityResearchingMaterialProductivity: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); productType = &installedItem->type(); into.productionTime = bp->type().researchMaterialTime(); into.charMaterialMultiplier = double(c->GetChar()->GetAttribute(AttrResearchCostPercent).get_int()) / 100.0; into.charTimeMultiplier = c->GetChar()->GetAttribute(AttrMineralNeedResearchSpeed).get_float(); break; } /* * Copying */ case ramActivityCopying: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); productType = &installedItem->type(); // no ceil() here on purpose into.productionTime = (bp->type().researchCopyTime() / bp->type().maxProductionLimit()) * args.licensedProductionRuns; into.charMaterialMultiplier = double(c->GetChar()->GetAttribute(AttrResearchCostPercent).get_int()) / 100.0; into.charTimeMultiplier = c->GetChar()->GetAttribute(AttrCopySpeedPercent).get_float(); break; } default: { productType = &installedItem->type(); into.charMaterialMultiplier = 1.0; into.charTimeMultiplier = 1.0; break; } } if(!m_db.MultiplyMultipliers(args.installationAssemblyLineID, productType->groupID(), into.materialMultiplier, into.timeMultiplier)) return false; // calculate the remaining things into.productionTime *= static_cast<int32>(into.timeMultiplier * into.charTimeMultiplier * args.runs); into.usageCost *= ceil(into.productionTime / 3600.0); into.cost = into.installCost + into.usageCost; // I "hope" this is right, simple tells client how soon will his job be started // Unfortunately, rounding done on client's side causes showing "Start time: 0 seconds" when he has to wait less than minute // I have no idea how to avoid this ... into.maxJobStartTime = m_db.GetNextFreeTime(args.installationAssemblyLineID); return true; }
void RamProxyService::_VerifyInstallJob_Call(const Call_InstallJob &args, InventoryItemRef installedItem, const PathElement &bomLocation, Client *const c) { // ACTIVITY CHECK // *************** const ItemType *productType; switch(args.activityID) { /* * Manufacturing */ case ramActivityManufacturing: { if(installedItem->categoryID() != EVEDB::invCategories::Blueprint) throw(PyException(MakeUserError("RamActivityRequiresABlueprint"))); BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); if(!bp->infinite() && (bp->licensedProductionRunsRemaining() - args.runs) < 0) throw(PyException(MakeUserError("RamTooManyProductionRuns"))); productType = &bp->productType(); break; } /* * Time/Material Research */ case ramActivityResearchingMaterialProductivity: case ramActivityResearchingTimeProductivity: { if(installedItem->categoryID() != EVEDB::invCategories::Blueprint) throw(PyException(MakeUserError("RamActivityRequiresABlueprint"))); BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); if(bp->copy()) throw(PyException(MakeUserError("RamCannotResearchABlueprintCopy"))); productType = &bp->type(); break; } /* * Copying */ case ramActivityCopying: { if(installedItem->categoryID() != EVEDB::invCategories::Blueprint) throw(PyException(MakeUserError("RamActivityRequiresABlueprint"))); BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); if(bp->copy()) throw(PyException(MakeUserError("RamCannotCopyABlueprintCopy"))); productType = &bp->type(); break; } /* * The rest */ case ramActivityResearchingTechnology: case ramActivityDuplicating: case ramActivityReverseEngineering: case ramActivityInvention: /* { if(installedItem->categoryID() != EVEDB::invCategories::Blueprint) throw(PyException(MakeUserError("RamActivityRequiresABlueprint"))); Blueprint *bp = (Blueprint *)installedItem; if(!bp->copy()) throw(PyException(MakeUserError("RamCannotInventABlueprintOriginal"))); uint32 productTypeID = m_db.GetTech2Blueprint(installedItem->typeID()); if(productTypeID == NULL) throw(PyException(MakeUserError("RamInventionNoOutput"))); productType = m_manager->item_factory.type(productTypeID); break; } */ default: { // not supported throw(PyException(MakeUserError("RamActivityInvalid"))); //throw(PyException(MakeUserError("RamNoKnownOutputType"))); } } if(!m_db.IsProducableBy(args.installationAssemblyLineID, productType->groupID())) throw(PyException(MakeUserError("RamBadEndProductForActivity"))); // JOBS CHECK // *********** if(args.activityID == ramActivityManufacturing) { uint32 jobCount = m_db.CountManufacturingJobs(c->GetCharacterID()); if(c->GetChar()->GetAttribute(AttrManufactureSlotLimit).get_int() <= jobCount) { std::map<std::string, PyRep *> exceptArgs; exceptArgs["current"] = new PyInt(jobCount); exceptArgs["max"] = c->GetChar()->GetAttribute(AttrManufactureSlotLimit).GetPyObject(); throw(PyException(MakeUserError("MaxFactorySlotUsageReached", exceptArgs))); } } else { uint32 jobCount = m_db.CountResearchJobs(c->GetCharacterID()); if(c->GetChar()->GetAttribute(AttrMaxLaborotorySlots).get_int() <= jobCount) { std::map<std::string, PyRep *> exceptArgs; exceptArgs["current"] = new PyInt(jobCount); exceptArgs["max"] = c->GetChar()->GetAttribute(AttrMaxLaborotorySlots).GetPyObject(); throw(PyException(MakeUserError("MaxResearchFacilitySlotUsageReached", exceptArgs))); } } // INSTALLATION CHECK // ******************* uint32 regionID = m_db.GetRegionOfContainer(args.installationContainerID); if(regionID == 0) throw(PyException(MakeUserError("RamIsNotAnInstallation"))); if(c->GetRegionID() != regionID) throw(PyException(MakeUserError("RamRangeLimitationRegion"))); // RamStructureNotInSpace // RamStructureNotIsSolarsystem // RamRangeLimitation // RamRangeLimitationJumps // RamRangeLimitationJumpsNoSkill // ASSEMBLY LINE CHECK // ********************* uint32 ownerID; double minCharSec, maxCharSec; EVERamRestrictionMask restrictionMask; EVERamActivity activity; // get properties if(!m_db.GetAssemblyLineVerifyProperties(args.installationAssemblyLineID, ownerID, minCharSec, maxCharSec, restrictionMask, activity)) throw(PyException(MakeUserError("RamInstallationHasNoDefaultContent"))); // check validity of activity if(activity < ramActivityManufacturing || activity > ramActivityInvention) throw(PyException(MakeUserError("RamAssemblyLineHasNoActivity"))); // check security rating if required if((restrictionMask & ramRestrictBySecurity) == ramRestrictBySecurity) { if(minCharSec > c->GetSecurityRating()) throw(PyException(MakeUserError("RamAccessDeniedSecStatusTooLow"))); if(maxCharSec < c->GetSecurityRating()) throw(PyException(MakeUserError("RamAccessDeniedSecStatusTooHigh"))); // RamAccessDeniedCorpSecStatusTooHigh // RamAccessDeniedCorpSecStatusTooLow } // check standing if required if((restrictionMask & ramRestrictByStanding) == ramRestrictByStanding) { // RamAccessDeniedCorpStandingTooLow // RamAccessDeniedStandingTooLow } if((restrictionMask & ramRestrictByAlliance) == ramRestrictByAlliance) { // if(...) throw(PyException(MakeUserError("RamAccessDeniedWrongAlliance"))); } else if((restrictionMask & ramRestrictByCorp) == ramRestrictByCorp) { if(ownerID != c->GetCorporationID()) throw(PyException(MakeUserError("RamAccessDeniedWrongCorp"))); } if(args.isCorpJob) { if((c->GetCorpRole() & corpRoleFactoryManager) != corpRoleFactoryManager) throw(PyException(MakeUserError("RamCannotInstallForCorpByRoleFactoryManager"))); if(args.activityID == ramActivityManufacturing) { if((c->GetCorpRole() & corpRoleCanRentFactorySlot) != corpRoleCanRentFactorySlot) throw(PyException(MakeUserError("RamCannotInstallForCorpByRole"))); } else { if((c->GetCorpRole() & corpRoleCanRentResearchSlot) != corpRoleCanRentResearchSlot) throw(PyException(MakeUserError("RamCannotInstallForCorpByRole"))); } } // INSTALLED ITEM CHECK // ********************* // ownership if(args.isCorpJob) { if(installedItem->ownerID() != c->GetCorporationID()) throw(PyException(MakeUserError("RamCannotInstallItemForAnotherCorp"))); } else { if(installedItem->ownerID() != c->GetCharacterID()) throw(PyException(MakeUserError("RamCannotInstallItemForAnother"))); } // corp hangar permission if( (installedItem->flag() == flagCorpSecurityAccessGroup2 && (c->GetCorpRole() & corpRoleHangarCanTake2) != corpRoleHangarCanTake2) || (installedItem->flag() == flagCorpSecurityAccessGroup3 && (c->GetCorpRole() & corpRoleHangarCanTake3) != corpRoleHangarCanTake3) || (installedItem->flag() == flagCorpSecurityAccessGroup4 && (c->GetCorpRole() & corpRoleHangarCanTake4) != corpRoleHangarCanTake4) || (installedItem->flag() == flagCorpSecurityAccessGroup5 && (c->GetCorpRole() & corpRoleHangarCanTake5) != corpRoleHangarCanTake5) || (installedItem->flag() == flagCorpSecurityAccessGroup6 && (c->GetCorpRole() & corpRoleHangarCanTake6) != corpRoleHangarCanTake6) || (installedItem->flag() == flagCorpSecurityAccessGroup7 && (c->GetCorpRole() & corpRoleHangarCanTake7) != corpRoleHangarCanTake7) ) throw(PyException(MakeUserError("RamAccessDeniedToBOMHangar"))); // large location check if(IsStation(args.installationContainerID)) { if(/*args.isCorpJob && */installedItem->flag() == flagCargoHold) throw(PyException(MakeUserError("RamCorpInstalledItemNotInCargo"))); if(installedItem->locationID() != (uint32)args.installationContainerID) { if((uint32)args.installationContainerID == c->GetLocationID()) { std::map<std::string, PyRep *> exceptArgs; exceptArgs["location"] = new PyString(m_db.GetStationName(args.installationContainerID)); if(args.isCorpJob) throw(PyException(MakeUserError("RamCorpInstalledItemWrongLocation", exceptArgs))); else throw(PyException(MakeUserError("RamInstalledItemWrongLocation", exceptArgs))); } else throw(PyException(MakeUserError("RamRemoteInstalledItemNotInStation"))); } else { if(args.isCorpJob) { if(installedItem->flag() < flagCorpSecurityAccessGroup2 || installedItem->flag() > flagCorpSecurityAccessGroup7) { if((uint32)args.installationContainerID == c->GetLocationID()) { std::map<std::string, PyRep *> exceptArgs; exceptArgs["location"] = new PyString(m_db.GetStationName(args.installationContainerID)); throw(PyException(MakeUserError("RamCorpInstalledItemWrongLocation", exceptArgs))); } else throw(PyException(MakeUserError("RamRemoteInstalledItemNotInOffice"))); } } else { if(installedItem->flag() != flagHangar) { if((uint32)args.installationInvLocationID == c->GetLocationID()) { std::map<std::string, PyRep *> exceptArgs; exceptArgs["location"] = new PyString(m_db.GetStationName(args.installationContainerID)); throw(PyException(MakeUserError("RamInstalledItemWrongLocation", exceptArgs))); } else { throw(PyException(MakeUserError("RamRemoteInstalledItemInStationNotHangar"))); } } } } } else if((uint32)args.installationContainerID == c->GetShipID()) { if(c->GetChar()->flag() != flagPilot) throw(PyException(MakeUserError("RamAccessDeniedNotPilot"))); if(installedItem->locationID() != (uint32)args.installationContainerID) throw(PyException(MakeUserError("RamInstalledItemMustBeInShip"))); } else { // here should be stuff around POS, but I dont certainly know how it should work, so ... // RamInstalledItemBadLocationStructure // RamInstalledItemInStructureNotInContainer // RamInstalledItemInStructureUnknownLocation } // BOM LOCATION CHECK // ******************* // corp hangar permission if( (bomLocation.flag == flagCorpSecurityAccessGroup2 && (c->GetCorpRole() & corpRoleHangarCanTake2) != corpRoleHangarCanTake2) || (bomLocation.flag == flagCorpSecurityAccessGroup3 && (c->GetCorpRole() & corpRoleHangarCanTake3) != corpRoleHangarCanTake3) || (bomLocation.flag == flagCorpSecurityAccessGroup4 && (c->GetCorpRole() & corpRoleHangarCanTake4) != corpRoleHangarCanTake4) || (bomLocation.flag == flagCorpSecurityAccessGroup5 && (c->GetCorpRole() & corpRoleHangarCanTake5) != corpRoleHangarCanTake5) || (bomLocation.flag == flagCorpSecurityAccessGroup6 && (c->GetCorpRole() & corpRoleHangarCanTake6) != corpRoleHangarCanTake6) || (bomLocation.flag == flagCorpSecurityAccessGroup7 && (c->GetCorpRole() & corpRoleHangarCanTake7) != corpRoleHangarCanTake7) ) throw(PyException(MakeUserError("RamAccessDeniedToBOMHangar"))); }
PyResult RamProxyService::Handle_CompleteJob(PyCallArgs &call) { Call_CompleteJob args; if(!args.Decode(&call.tuple)) { _log(CLIENT__ERROR, "Failed to decode args."); return NULL; } _VerifyCompleteJob(args, call.client); // hundreds of variables to allocate ... maybe we can make struct for GetJobProperties and InstallJob? uint32 installedItemID, ownerID, runs, licensedProductionRuns; EVEItemFlags outputFlag; EVERamActivity activity; if(!m_db.GetJobProperties(args.jobID, installedItemID, ownerID, outputFlag, runs, licensedProductionRuns, activity)) return NULL; // return item InventoryItemRef installedItem = m_manager->item_factory.GetItem( installedItemID ); if( !installedItem ) return NULL; installedItem->Move( installedItem->locationID(), outputFlag ); std::vector<RequiredItem> reqItems; if( !m_db.GetRequiredItems( installedItem->typeID(), activity, reqItems ) ) return NULL; // return materials which weren't completely consumed std::vector<RequiredItem>::iterator cur, end; cur = reqItems.begin(); end = reqItems.end(); for(; cur != end; cur++) { if(!cur->isSkill && cur->damagePerJob != 1.0) { uint32 quantity = static_cast<uint32>(cur->quantity * runs * (1.0 - cur->damagePerJob)); if(quantity == 0) continue; ItemData idata( cur->typeID, ownerID, 0, //temp location outputFlag, quantity ); InventoryItemRef item = m_manager->item_factory.SpawnItem( idata ); if( !item ) return NULL; item->Move(args.containerID, outputFlag); } } // if not cancelled, realize result of activity if(!args.cancel) { switch(activity) { /* * Manufacturing */ case ramActivityManufacturing: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); ItemData idata( bp->productTypeID(), ownerID, 0, // temp location outputFlag, bp->productType().portionSize() * runs ); InventoryItemRef item = m_manager->item_factory.SpawnItem( idata ); if( !item ) return NULL; item->Move(args.containerID, outputFlag); } break; /* * Time productivity research */ case ramActivityResearchingTimeProductivity: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); bp->AlterProductivityLevel( runs ); } break; /* * Material productivity research */ case ramActivityResearchingMaterialProductivity: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); bp->AlterMaterialLevel( runs) ; } break; /* * Copying */ case ramActivityCopying: { BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); ItemData idata( installedItem->typeID(), ownerID, 0, //temp location outputFlag, runs ); BlueprintData bdata( true, bp->materialLevel(), bp->productivityLevel(), licensedProductionRuns ); BlueprintRef copy = m_manager->item_factory.SpawnBlueprint( idata, bdata ); if( !copy ) return NULL; copy->Move(args.containerID, outputFlag); } break; /* * The rest is unsupported */ case ramActivityResearchingTechnology: case ramActivityDuplicating: case ramActivityReverseEngineering: case ramActivityInvention: default: { _log(SERVICE__ERROR, "Activity %u is currently unsupported.", activity); } break; } } // regardless on success of this, we will return NULL, so there's no condition here m_db.CompleteJob(args.jobID, args.cancel ? ramCompletedStatusAbort : ramCompletedStatusDelivered); return NULL; }
PyResult RamProxyService::Handle_InstallJob(PyCallArgs &call) { Call_InstallJob args; if(!args.Decode(&call.tuple)) { _log(SERVICE__ERROR, "Failed to decode args."); return NULL; } // load installed item InventoryItemRef installedItem = m_manager->item_factory.GetItem( args.installedItemID ); if( !installedItem ) return NULL; // if output flag not set, put it where it was if(args.flagOutput == flagAutoFit) args.flagOutput = installedItem->flag(); // decode path to BOM location PathElement pathBomLocation; if( !pathBomLocation.Decode( args.bomPath->GetItem(0) ) ) { _log(SERVICE__ERROR, "Failed to decode BOM location."); return NULL; } // verify call _VerifyInstallJob_Call( args, (InventoryItemRef)installedItem, pathBomLocation, call.client ); // this calculates some useful multipliers ... Rsp_InstallJob is used as container ... Rsp_InstallJob rsp; if(!_Calculate(args, (InventoryItemRef)installedItem, call.client, rsp)) return NULL; // I understand sent maxJobStartTime as a limit, so this checks whether it's in limit if(rsp.maxJobStartTime > call.byname["maxJobStartTime"]->AsInt()->value()) throw(PyException(MakeUserError("RamCannotGuaranteeStartTime"))); // query required items for activity std::vector<RequiredItem> reqItems; if(!m_db.GetRequiredItems(installedItem->typeID(), (EVERamActivity)args.activityID, reqItems)) return NULL; // if 'quoteOnly' is 1 -> send quote, if 0 -> install job if(call.byname["quoteOnly"]->AsInt()->value()) { _EncodeBillOfMaterials(reqItems, rsp.materialMultiplier, rsp.charMaterialMultiplier, args.runs, rsp.bom); _EncodeMissingMaterials(reqItems, pathBomLocation, call.client, rsp.materialMultiplier, rsp.charMaterialMultiplier, args.runs, rsp.missingMaterials); return rsp.Encode(); } else { // verify install _VerifyInstallJob_Install(rsp, pathBomLocation, reqItems, args.runs, call.client); // now we are sure everything from the client side is right, we can start it ... // calculate proper start time uint64 beginProductionTime = Win32TimeNow(); if(beginProductionTime < (uint32)rsp.maxJobStartTime) beginProductionTime = rsp.maxJobStartTime; // register our job if( !m_db.InstallJob( args.isCorpJob ? call.client->GetCorporationID() : call.client->GetCharacterID(), call.client->GetCharacterID(), args.installationAssemblyLineID, installedItem->itemID(), beginProductionTime, beginProductionTime + uint64(rsp.productionTime) * Win32Time_Second, args.description.c_str(), args.runs, (EVEItemFlags)args.flagOutput, pathBomLocation.locationID, args.licensedProductionRuns ) ) { return NULL; } // do some activity-specific actions switch(args.activityID) { case ramActivityManufacturing: { // decrease licensed production runs BlueprintRef bp = BlueprintRef::StaticCast( installedItem ); if(!bp->infinite()) bp->AlterLicensedProductionRunsRemaining(-1); } } // pay for assembly lines, move the item away call.client->AddBalance(-rsp.cost); installedItem->Move( installedItem->locationID(), flagFactoryBlueprint ); // query all items contained in "Bill of Materials" location std::vector<InventoryItemRef> items; _GetBOMItems( pathBomLocation, items ); std::vector<RequiredItem>::iterator cur, end; cur = reqItems.begin(); end = reqItems.end(); for(; cur != end; cur++) { if(cur->isSkill) continue; // not interested // calculate needed quantity uint32 qtyNeeded = static_cast<uint32>(ceil(cur->quantity * rsp.materialMultiplier * args.runs)); if(cur->damagePerJob == 1.0) qtyNeeded = static_cast<uint32>(ceil(qtyNeeded * rsp.charMaterialMultiplier)); // skill multiplier is applied only on fully consumed materials std::vector<InventoryItemRef>::iterator curi, endi; curi = items.begin(); endi = items.end(); // consume required materials for(; curi != endi; curi++) { if((*curi)->typeID() == cur->typeID && (*curi)->ownerID() == call.client->GetCharacterID()) { if(qtyNeeded >= (*curi)->quantity()) { qtyNeeded -= (*curi)->quantity(); (*curi)->Delete(); } else { (*curi)->AlterQuantity(-(int32)qtyNeeded); break; // we are done, stop searching } } } } return NULL; } }
PyResult ContractMgrService::Handle_GetContract( PyCallArgs& call ) { Call_SingleIntegerArg arg; PyDict* _contract = new PyDict; if( !arg.Decode( &call.tuple ) ) { codelog(SERVICE__ERROR, "%s: Bad arguments to GetContract in contractMgr", call.client->GetCharacterName() ); return NULL; } // Manual creation of PyPackedRow DBRowDescriptor *header = new DBRowDescriptor(); header->AddColumn( "contractID", DBTYPE_I4 ); header->AddColumn( "issuerID", DBTYPE_I4 ); header->AddColumn( "issuerCorpID", DBTYPE_I4 ); header->AddColumn( "type", DBTYPE_UI1 ); header->AddColumn( "availability", DBTYPE_I4 ); header->AddColumn( "assigneeID", DBTYPE_I4 ); header->AddColumn( "numDays", DBTYPE_I4 ); header->AddColumn( "startStationID", DBTYPE_I4 ); header->AddColumn( "endStationID", DBTYPE_I4 ); header->AddColumn( "startSolarSystemID", DBTYPE_I4 ); header->AddColumn( "endSolarSystemID", DBTYPE_I4 ); header->AddColumn( "startRegionID", DBTYPE_I4 ); header->AddColumn( "endRegionID", DBTYPE_I4 ); header->AddColumn( "price", DBTYPE_CY ); header->AddColumn( "reward", DBTYPE_CY ); header->AddColumn( "collateral", DBTYPE_CY ); header->AddColumn( "title", DBTYPE_WSTR ); header->AddColumn( "description", DBTYPE_WSTR ); header->AddColumn( "forCorp", DBTYPE_BOOL ); header->AddColumn( "status", DBTYPE_UI1 ); header->AddColumn( "acceptorID", DBTYPE_I4 ); header->AddColumn( "dateIssued", DBTYPE_FILETIME ); header->AddColumn( "dateExpired", DBTYPE_FILETIME ); header->AddColumn( "dateAccepted", DBTYPE_FILETIME ); header->AddColumn( "dateCompleted", DBTYPE_FILETIME ); header->AddColumn( "volume", DBTYPE_R8 ); header->AddColumn( "issuerAllianceID", DBTYPE_I4 ); header->AddColumn( "issuerWalletKey", DBTYPE_I4 ); header->AddColumn( "acceptorWalletKey", DBTYPE_I4 ); header->AddColumn( "crateID", DBTYPE_I4 ); ContractRef contract = m_contractManager->GetContract( arg.arg ); uint32 n = 0; PyPackedRow* into = new PyPackedRow( header ); into->SetField( "contractID", new PyInt( contract->contractID() ) ); into->SetField( "issuerID", new PyInt( contract->issuerID() ) ); into->SetField( "issuerCorpID", new PyInt( contract->issuerCorpID() ) ); into->SetField( "type", new PyInt( contract->type() ) ); into->SetField( "availability", new PyInt( contract->avail() ) ); into->SetField( "assigneeID", new PyInt( contract->assigneeID() ) ); into->SetField( "numDays", new PyInt( 0 ) ); into->SetField( "startStationID", new PyInt( contract->startStationID() ) ); into->SetField( "endStationID", new PyInt( contract->endStationID() ) ); into->SetField( "startSolarSystemID", new PyInt( contract->startSolarSystemID() ) ); into->SetField( "endSolarSystemID", new PyInt( contract->endSolarSystemID() ) ); into->SetField( "startRegionID", new PyInt( contract->startRegionID() ) ); into->SetField( "endRegionID", new PyInt( contract->endRegionID() ) ); into->SetField( "price", new PyFloat( contract->price() ) ); into->SetField( "reward", new PyFloat( contract->reward() ) ); into->SetField( "collateral", new PyFloat( contract->collateral() ) ); into->SetField( "title", new PyString( "title" ) ); into->SetField( "description", new PyString( "description" ) ); into->SetField( "forCorp", new PyBool( contract->forCorp() ) ); into->SetField( "status", new PyInt( contract->status() ) ); into->SetField( "acceptorID", new PyInt( contract->acceptorID() ) ); into->SetField( "dateIssued", new PyLong( contract->dateIssued() ) ); into->SetField( "dateExpired", new PyLong( contract->dateExpired() ) ); into->SetField( "dateAccepted", new PyLong( contract->dateAccepted() ) ); into->SetField( "dateCompleted", new PyLong( contract->dateCompleted() ) ); into->SetField( "volume", new PyFloat( contract->volume() ) ); into->SetField( "issuerAllianceID", new PyInt( contract->issuerAllianceID() ) ); into->SetField( "issuerWalletKey", new PyInt( contract->issuerWalletKey() ) ); into->SetField( "acceptorWalletKey", new PyInt( 0 ) ); into->SetField( "crateID", new PyInt( 0 ) ); PyList* itemList = new PyList; DBRowDescriptor *itemHeader = new DBRowDescriptor(); itemHeader->AddColumn( "contractID", DBTYPE_I4 ); itemHeader->AddColumn( "itemID", DBTYPE_I4 ); itemHeader->AddColumn( "quantity", DBTYPE_I4 ); itemHeader->AddColumn( "itemTypeID", DBTYPE_I4 ); itemHeader->AddColumn( "inCrate", DBTYPE_BOOL ); itemHeader->AddColumn( "parentID", DBTYPE_I4 ); itemHeader->AddColumn( "productivityLevel", DBTYPE_I4 ); itemHeader->AddColumn( "materialLevel", DBTYPE_I4 ); itemHeader->AddColumn( "copy", DBTYPE_I4 ); itemHeader->AddColumn( "licensedProductionRunsRemaining", DBTYPE_I4 ); itemHeader->AddColumn( "damage", DBTYPE_R8 ); itemHeader->AddColumn( "flagID", DBTYPE_I2 ); std::map<uint32, ContractGetItemsRef>::const_iterator cur, end; std::map<uint32, ContractGetItemsRef> items = contract->items(); cur = items.begin(); end = items.end(); for(; cur != end; cur++ ) { PyPackedRow* data = new PyPackedRow( itemHeader ); InventoryItemRef item = m_manager->item_factory.GetItem( cur->second->m_itemID ); data->SetField( "contractID", new PyInt( contract->contractID() ) ); data->SetField( "itemID", new PyInt( item->itemID() ) ); data->SetField( "quantity", new PyInt( cur->second->m_quantity ) ); data->SetField( "itemTypeID", new PyInt( item->typeID() ) ); data->SetField( "inCrate", new PyBool( true ) ); if( item->categoryID() == EVEDB::invCategories::Blueprint ) { BlueprintRef bp = m_manager->item_factory.GetBlueprint( item->itemID() ); data->SetField( "parentID", new PyInt( bp->parentBlueprintTypeID() ) ); data->SetField( "productivityLevel", new PyInt( bp->productivityLevel() ) ); data->SetField( "materialLevel", new PyInt( bp->materialLevel() ) ); data->SetField( "copy", new PyInt( bp->copy() ) ); data->SetField( "licensedProductionRunsRemaining", new PyInt( bp->licensedProductionRunsRemaining() ) ); if( bp->HasAttribute( 3 ) ) data->SetField( "damage", new PyFloat( bp->GetAttribute( 3 ).get_float() ) ); else data->SetField( "damage", new PyFloat( 0.0 ) ); data->SetField( "flagID", new PyInt( bp->flag() ) ); } else { data->SetField( "parentID", new PyInt( 0 ) ); data->SetField( "productivityLevel", new PyInt( 0 ) ); data->SetField( "materialLevel", new PyInt( 0 ) ); data->SetField( "copy", new PyInt( 0 ) ); data->SetField( "licensedProductionRunsRemaining", new PyInt( 0 ) ); if( item->HasAttribute( 3 ) ) data->SetField( "damage", new PyFloat( item->GetAttribute( 3 ).get_float() ) ); else data->SetField( "damage", new PyFloat( 0.0 ) ); data->SetField( "flagID", new PyInt( item->flag() ) ); } itemList->AddItem( data ); } std::map<uint32, ContractRequestItemRef>::const_iterator c, e; std::map<uint32, ContractRequestItemRef> requestItems = contract->requestItems(); c = requestItems.begin(); e = requestItems.end(); for(; c != e; c++ ) { PyPackedRow* data = new PyPackedRow( itemHeader ); data->SetField( "contractID", new PyInt( arg.arg ) ); data->SetField( "itemID", new PyInt( 0 ) ); data->SetField( "quantity", new PyInt( c->second->m_quantity ) ); data->SetField( "itemTypeID", new PyInt( c->second->m_typeID ) ); data->SetField( "inCrate", new PyBool( false ) ); data->SetField( "parentID", new PyInt( 0 ) ); data->SetField( "productivityLevel", new PyInt( 0 ) ); data->SetField( "materialLevel", new PyInt( 0 ) ); data->SetField( "copy", new PyInt( 0 ) ); data->SetField( "licensedProductionRunsRemaining", new PyInt( 0 ) ); data->SetField( "damage", new PyFloat( 0.0 ) ); data->SetField( "flagID", new PyInt( 0 ) ); itemList->AddItem( data ); } DBRowDescriptor *bidsHeader = new DBRowDescriptor(); bidsHeader->AddColumn( "bidID", DBTYPE_I4 ); bidsHeader->AddColumn( "contractID", DBTYPE_I4 ); bidsHeader->AddColumn( "issuerID", DBTYPE_I4 ); bidsHeader->AddColumn( "quantity", DBTYPE_I4 ); bidsHeader->AddColumn( "issuerCorpID", DBTYPE_I4 ); bidsHeader->AddColumn( "issuerStationID", DBTYPE_I4 ); bidsHeader->AddColumn( "issuerSolarSystemID", DBTYPE_I4 ); bidsHeader->AddColumn( "issuerRegionID", DBTYPE_I4 ); CRowSet *bids_rowset = new CRowSet( &bidsHeader ); _contract->SetItemString( "items", itemList ); _contract->SetItemString( "bids", bids_rowset ); _contract->SetItemString( "contract", into); PyObject* res = new PyObject( new PyString( "util.KeyVal" ), _contract ); return res; }