EvilNumber Character::GetSPPerMin( SkillRef skill ) { EvilNumber primarySkillTrainingAttr = skill->GetAttribute(AttrPrimaryAttribute); EvilNumber secondarySkillTrainingAttr = skill->GetAttribute(AttrSecondaryAttribute); EvilNumber primarySPperMin = GetAttribute( (uint32)(primarySkillTrainingAttr.get_int()) ); EvilNumber secondarySPperMin = GetAttribute( (uint32)(secondarySkillTrainingAttr.get_int()) ); //EvilNumber skillLearningLevel(0); // ////3374 - Skill Learning //SkillRef skillLearning = GetSkill( 3374 ); //if( skillLearning ) // skillLearningLevel = skillLearning->GetAttribute(AttrSkillLevel); primarySPperMin = primarySPperMin + secondarySPperMin / 2.0f; //primarySPperMin = primarySPperMin * (EvilNumber(1.0f) + EvilNumber(0.02f) * skillLearningLevel); // 100% Training bonus for 30day and under character age has been removed in Incursion // http://www.eveonline.com/en/incursion/article/57/learning-skills-are-going-away // Check Total SP Trained for this character against the threshold for granting the 100% training bonus: //if( m_totalSPtrained.get_float() < ((double)MAX_SP_FOR_100PCT_TRAINING_BONUS) ) // primarySPperMin = primarySPperMin * EvilNumber(2.0f); return primarySPperMin; }
uint64 Character::GetEndOfTraining() const { SkillRef skill = GetSkillInTraining(); if( !skill ) return 0; return skill->expiryTime(); }
EvilNumber Character::GetEndOfTraining() const { SkillRef skill = GetSkillInTraining(); if( !skill ) return 0; return skill->GetAttribute(AttrExpiryTime); }
SkillRef ItemFactory::SpawnSkill(ItemData &data) { SkillRef s = Skill::Spawn( *this, data ); if( !s ) return SkillRef(); m_items.insert( std::make_pair( s->itemID(), s ) ); return s; }
SkillRef Skill::Spawn(ItemFactory &factory, ItemData &data) { uint32 skillID = _Spawn( factory, data ); if( skillID == 0 ) return SkillRef(); SkillRef skillRef = Skill::Load( factory, skillID ); skillRef->SetAttribute(AttrIsOnline, 1); // Is Online return skillRef; }
bool Character::HasSkillTrainedToLevel(uint32 skillTypeID, uint32 skillLevel) const { SkillRef requiredSkill; // First, check for existence of skill trained or in training: requiredSkill = GetSkill( skillTypeID ); if( !requiredSkill ) return false; // Second, check for required minimum level of skill, note it must already be trained to this level: if( requiredSkill->GetAttribute(AttrSkillLevel) < skillLevel ) return false; return true; }
double Character::GetSPPerMin(SkillRef skill) const { double primaryVal = attributes.GetReal( (EVEAttributeMgr::Attr)skill->primaryAttribute() ); double secondaryVal = attributes.GetReal( (EVEAttributeMgr::Attr)skill->secondaryAttribute() ); uint8 skillLearningLevel = 0; //3374 - Skill Learning SkillRef skillLearning = GetSkill( 3374 ); if( skillLearning ) skillLearningLevel = skillLearning->skillLevel(); return (primaryVal + secondaryVal / 2.0) * (1.0 + 0.02 * skillLearningLevel) * 2.0; /* this is hacky and should be applied only if total SP < 1.6M */ }
bool Character::InjectSkillIntoBrain(SkillRef skill) { Client *c = m_factory.entity_list.FindCharacter( itemID() ); SkillRef oldSkill = GetSkill( skill->typeID() ); if( oldSkill ) { //TODO: build and send proper UserError for CharacterAlreadyKnowsSkill. if( c != NULL ) c->SendNotifyMsg( "You already know this skill." ); return false; } // TODO: based on config options later, check to see if another character, owned by this characters account, // is training a skill. If so, return. (flagID=61). if( !skill->SkillPrereqsComplete( *this ) ) { // TODO: need to send back a response to the client. need packet specs. _log( ITEM__TRACE, "%s (%u): Requested to train skill %u item %u but prereq not complete.", itemName().c_str(), itemID(), skill->typeID(), skill->itemID() ); if( c != NULL ) c->SendNotifyMsg( "Injection failed! Skill prerequisites incomplete." ); return false; } // are we injecting from a stack of skills? if( skill->quantity() > 1 ) { // split the stack to obtain single item InventoryItemRef single_skill = skill->Split( 1 ); if( !single_skill ) { _log( ITEM__ERROR, "%s (%u): Unable to split stack of %s (%u).", itemName().c_str(), itemID(), skill->itemName().c_str(), skill->itemID() ); return false; } // use single_skill ... single_skill->MoveInto( *this, flagSkill ); } else // use original skill skill->MoveInto( *this, flagSkill ); if( c != NULL ) c->SendNotifyMsg( "Injection of skill complete." ); return true; }
void Character::AddItem(InventoryItemRef item) { Inventory::AddItem( item ); if( item->flag() == flagSkill || item->flag() == flagSkillInTraining ) { // Skill has been added ... if( item->categoryID() != EVEDB::invCategories::Skill ) { _log( ITEM__WARNING, "%s (%u): %s has been added with flag %d.", itemName().c_str(), itemID(), item->category().name().c_str(), (int)item->flag() ); } else { SkillRef skill = SkillRef::StaticCast( item ); if( !skill->singleton() ) { _log( ITEM__TRACE, "%s (%u): Injecting %s.", itemName().c_str(), itemID(), item->itemName().c_str() ); // Make it singleton and set initial skill values. skill->ChangeSingleton( true ); skill->SetAttribute(AttrSkillLevel, 0); skill->SetAttribute(AttrSkillPoints, 0); if( skill->flag() != flagSkillInTraining ) skill->SetAttribute(AttrExpiryTime, 0); } } } }
bool Skill::SkillPrereqsComplete(Character &ch) { SkillRef requiredSkill; if( GetAttribute(AttrRequiredSkill1).get_int() != 0 ) { requiredSkill = ch.GetSkill(static_cast<uint32>(GetAttribute(AttrRequiredSkill1).get_int())); if( !requiredSkill ) return false; if( GetAttribute(AttrRequiredSkill1Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } if( GetAttribute(AttrRequiredSkill2).get_int() != 0 ) { requiredSkill = ch.GetSkill(static_cast<uint32>(GetAttribute(AttrRequiredSkill2).get_int())); if( !requiredSkill ) return false; if( GetAttribute(AttrRequiredSkill2Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } if( GetAttribute(AttrRequiredSkill3).get_int() != 0 ) { requiredSkill = ch.GetSkill(static_cast<uint32>(GetAttribute(AttrRequiredSkill3).get_int())); if( !requiredSkill ) return false; if( GetAttribute(AttrRequiredSkill3Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } return true; }
bool Character::InjectSkillIntoBrain(SkillRef skill, uint8 level) { Client *c = m_factory.entity_list.FindCharacter( itemID() ); SkillRef oldSkill = GetSkill( skill->typeID() ); if( oldSkill ) { oldSkill->attributes.SetNotify(true); oldSkill->Set_skillLevel( level ); oldSkill->Set_skillPoints( pow(2, ( 2.5 * level ) - 2.5 ) * SKILL_BASE_POINTS * ( oldSkill->attributes.GetInt( oldSkill->attributes.Attr_skillTimeConstant ) ) ); return true; } // are we injecting from a stack of skills? if( skill->quantity() > 1 ) { // split the stack to obtain single item InventoryItemRef single_skill = skill->Split( 1 ); if( !single_skill ) { _log( ITEM__ERROR, "%s (%u): Unable to split stack of %s (%u).", itemName().c_str(), itemID(), skill->itemName().c_str(), skill->itemID() ); return false; } // use single_skill ... single_skill->MoveInto( *this, flagSkill ); } else skill->MoveInto( *this, flagSkill ); skill->Set_skillLevel( level ); //TODO: get right number of skill points //skill->Set_skillPoints( SKILL_BASE_POINTS * skillTimeConstant() * pow(32, (level - 1) / 2.0) ); skill->Set_skillPoints( pow(2,( 2.5 * level) - 2.5 ) * SKILL_BASE_POINTS * ( skill->attributes.GetInt( skill->attributes.Attr_skillTimeConstant ) ) ); return true; }
EvilNumber Character::GetSPPerMin( SkillRef skill ) { EvilNumber primarySkillTrainingAttr = skill->GetAttribute(AttrPrimaryAttribute); EvilNumber secondarySkillTrainingAttr = skill->GetAttribute(AttrSecondaryAttribute); EvilNumber primarySPperMin = GetAttribute( (uint32)(primarySkillTrainingAttr.get_int()) ); EvilNumber secondarySPperMin = GetAttribute( (uint32)(secondarySkillTrainingAttr.get_int()) ); EvilNumber skillLearningLevel(0); //3374 - Skill Learning SkillRef skillLearning = GetSkill( 3374 ); if( skillLearning ) skillLearningLevel = skillLearning->GetAttribute(AttrSkillLevel); primarySPperMin = primarySPperMin + secondarySPperMin / 2.0f; primarySPperMin = primarySPperMin * (EvilNumber(1.0f) + EvilNumber(0.02f) * skillLearningLevel); // Check Total SP Trained for this character against the threshold for granting the 100% training bonus: if( m_totalSPtrained.get_float() < ((double)MAX_SP_FOR_100PCT_TRAINING_BONUS) ) primarySPperMin = primarySPperMin * EvilNumber(2.0f); return primarySPperMin; }
bool Skill::FitModuleSkillCheck(InventoryItemRef item, CharacterRef character) { //TODO: move to skills SkillRef requiredSkill; //Primary Skill if(item->GetAttribute(AttrRequiredSkill1) != 0) { requiredSkill = character->GetSkill( static_cast<uint32>(item->GetAttribute(AttrRequiredSkill1).get_int()) ); if( !requiredSkill ) return false; if( item->GetAttribute(AttrRequiredSkill1Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Secondary Skill if(item->GetAttribute(AttrRequiredSkill2) != 0) { requiredSkill = character->GetSkill( static_cast<uint32>(item->GetAttribute(AttrRequiredSkill2).get_int()) ); if( !requiredSkill ) return false; if( item->GetAttribute(AttrRequiredSkill2Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Tertiary Skill if(item->GetAttribute(AttrRequiredSkill3) != 0) { requiredSkill = character->GetSkill( static_cast<uint32>(item->GetAttribute(AttrRequiredSkill3).get_int()) ); if( !requiredSkill ) return false; if( item->GetAttribute(AttrRequiredSkill3Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Quarternary Skill if(item->GetAttribute(AttrRequiredSkill4) != 0) { requiredSkill = character->GetSkill( static_cast<uint32>(item->GetAttribute(AttrRequiredSkill4).get_int()) ); if( !requiredSkill ) return false; if( item->GetAttribute(AttrRequiredSkill4Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Quinary Skill if(item->GetAttribute(AttrRequiredSkill5) != 0) { requiredSkill = character->GetSkill(static_cast<uint32>(item->GetAttribute(AttrRequiredSkill5).get_int())); if( !requiredSkill ) return false; if( item->GetAttribute(AttrRequiredSkill5Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Senary Skill if(item->GetAttribute(AttrRequiredSkill6) != 0) { requiredSkill = character->GetSkill(static_cast<uint32>(item->GetAttribute(AttrRequiredSkill6).get_int())); if( !requiredSkill ) return false; if( item->GetAttribute(AttrRequiredSkill6Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } return true; }
void Character::UpdateSkillQueue() { Client *c = m_factory.entity_list.FindCharacter( itemID() ); SkillRef currentTraining = GetSkillInTraining(); if( currentTraining ) { if( m_skillQueue.empty() || currentTraining->typeID() != m_skillQueue.front().typeID ) { // either queue is empty or skill with different typeID is in training ... // stop training: _log( ITEM__ERROR, "%s (%u): Stopping training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); /* uint64 timeEndTrain = currentTraining->expiryTime(); if(timeEndTrain != 0) { double nextLevelSP = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ); double SPPerMinute = GetSPPerMin( currentTraining ); double minRemaining = (double)(timeEndTrain - Win32TimeNow()) / (double)Win32Time_Minute; currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); } currentTraining->Clear_expiryTime(); */ EvilNumber timeEndTrain = currentTraining->GetAttribute(AttrExpiryTime); if (timeEndTrain != 0) { EvilNumber nextLevelSP = currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) + 1 ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber minRemaining = (timeEndTrain - EvilNumber(Win32TimeNow())) / (double)Win32Time_Minute; //currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); EvilNumber skillPointsTrained = nextLevelSP - (minRemaining * SPPerMinute); currentTraining->SetAttribute(AttrSkillPoints, skillPointsTrained); sLog.Debug( "", "Skill %s (%u) trained %u skill points before termination from training queue", currentTraining->itemName().c_str(), currentTraining->itemID(), skillPointsTrained.get_float() ); } currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrainingStopped osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = 0; PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // nothing currently in training currentTraining = SkillRef(); } } EvilNumber nextStartTime = EvilTimeNow(); while( !m_skillQueue.empty() ) { if( !currentTraining ) { // something should be trained, get desired skill uint32 skillTypeID = m_skillQueue.front().typeID; currentTraining = GetSkill( skillTypeID ); if( !currentTraining ) { _log( ITEM__ERROR, "%s (%u): Skill %u to train was not found.", itemName().c_str(), itemID(), skillTypeID ); break; } sLog.Debug( "Character::UpdateSkillQueue()", "%s (%u): Starting training of skill %s (%u)", m_itemName.c_str(), m_itemID, currentTraining->itemName().c_str(), currentTraining->itemID() ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber NextLevel = currentTraining->GetAttribute(AttrSkillLevel) + 1; EvilNumber SPToNextLevel = currentTraining->GetSPForLevel( NextLevel ) - currentTraining->GetAttribute(AttrSkillPoints); sLog.Debug( " ", "Training skill at %f SP/min", SPPerMinute.get_float() ); sLog.Debug( " ", "%f SP to next Level of %d", SPToNextLevel.get_float(), NextLevel.get_int() ); SPPerMinute.to_float(); SPToNextLevel.to_float(); nextStartTime.to_float(); EvilNumber timeTraining = nextStartTime + EvilTime_Minute * SPToNextLevel / SPPerMinute; currentTraining->MoveInto( *this, flagSkillInTraining ); double dbl_timeTraining = timeTraining.get_float() + (double)(Win32Time_Second * 10); currentTraining->SetAttribute(AttrExpiryTime, dbl_timeTraining); // Set server-side // skill expiry + 10 sec sLog.Debug( " ", "Calculated time to complete training = %s", Win32TimeToString((uint64)dbl_timeTraining).c_str() ); if( c != NULL ) { OnSkillStartTraining osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = timeTraining.get_float(); PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } } if( currentTraining->GetAttribute(AttrExpiryTime) <= EvilTimeNow() ) { // training has been finished: sLog.Debug( "Character::UpdateSkillQueue()", "%s (%u): Finishing training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); currentTraining->SetAttribute(AttrSkillLevel, currentTraining->GetAttribute(AttrSkillLevel) + 1 ); currentTraining->SetAttribute(AttrSkillPoints, currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) ), true); nextStartTime = currentTraining->GetAttribute(AttrExpiryTime); currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrained ost; ost.itemID = currentTraining->itemID(); PyTuple* tmp = ost.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // erase first element in skill queue m_skillQueue.erase( m_skillQueue.begin() ); // nothing currently in training currentTraining = SkillRef(); } // else the skill is in training ... else break; } // Re-Calculate total SP trained and store in internal variable: _CalculateTotalSPTrained(); // Save character and skill data: SaveCharacter(); SaveSkillQueue(); }
bool Ship::ValidateBoardShip(ShipRef ship, CharacterRef character) { SkillRef requiredSkill; //Primary Skill if(ship->GetAttribute(AttrRequiredSkill1).get_int() != 0) { requiredSkill = character->GetSkill( ship->GetAttribute(AttrRequiredSkill1).get_int() ); if( !requiredSkill ) return false; if( ship->GetAttribute(AttrRequiredSkill1Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Secondary Skill if(ship->GetAttribute(AttrRequiredSkill2).get_int() != 0) { requiredSkill = character->GetSkill( ship->GetAttribute(AttrRequiredSkill2).get_int() ); if( !requiredSkill ) return false; if( ship->GetAttribute(AttrRequiredSkill2Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Tertiary Skill if(ship->GetAttribute(AttrRequiredSkill3).get_int() != 0) { requiredSkill = character->GetSkill( ship->GetAttribute(AttrRequiredSkill3).get_int() ); if( !requiredSkill ) return false; if( ship->GetAttribute(AttrRequiredSkill3Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Quarternary Skill if(ship->GetAttribute(AttrRequiredSkill4).get_int() != 0) { requiredSkill = character->GetSkill( ship->GetAttribute(AttrRequiredSkill4).get_int() ); if( !requiredSkill ) return false; if( ship->GetAttribute(AttrRequiredSkill4Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Quinary Skill if(ship->GetAttribute(AttrRequiredSkill5).get_int() != 0) { requiredSkill = character->GetSkill( ship->GetAttribute(AttrRequiredSkill5).get_int() ); if( !requiredSkill ) return false; if( ship->GetAttribute(AttrRequiredSkill5Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } //Senary Skill if(ship->GetAttribute(AttrRequiredSkill6).get_int() != 0) { requiredSkill = character->GetSkill( ship->GetAttribute(AttrRequiredSkill6).get_int() ); if( !requiredSkill ) return false; if( ship->GetAttribute(AttrRequiredSkill6Level) > requiredSkill->GetAttribute(AttrSkillLevel) ) return false; } return true; }
PyResult Command_giveskill( Client* who, CommandDB* db, PyServiceMgr* services, const Seperator& args ) { uint32 typeID; uint8 level; CharacterRef character; EVEItemFlags flag; uint32 gty = 1; //uint8 oldSkillLevel = 0; EvilNumber oldSkillLevel(0); uint32 ownerID = 0; if( args.argCount() == 4 ) { if( args.isNumber( 1 ) ) { ownerID = atoi( args.arg( 1 ).c_str() ); character = services->entity_list.FindCharacter( ownerID )->GetChar(); } else if( args.arg( 1 ) == "me" ) { ownerID = who->GetCharacterID(); character = who->GetChar(); } else if( !args.isNumber( 1 ) ) { const char *name = args.arg( 1 ).c_str(); Client *target = services->entity_list.FindCharacter( name ); if(target == NULL) throw PyException( MakeCustomError( "Cannot find Character by the name of %s", name ) ); ownerID = target->GetCharacterID(); } else throw PyException( MakeCustomError( "Argument 1 must be Character ID or Character Name ") ); if( !args.isNumber( 2 ) ) throw PyException( MakeCustomError( "Argument 2 must be type ID." ) ); typeID = atoi( args.arg( 2 ).c_str() ); if( !args.isNumber( 3 ) ) throw PyException( MakeCustomError( "Argument 3 must be level" ) ); level = atoi( args.arg( 3 ).c_str() ); //levels don't go higher than 5 if( level > 5 ) level = 5; } else throw PyException( MakeCustomError("Correct Usage: /giveskill [Character Name or ID] [skillID] [desired level]") ); SkillRef skill; if(character->HasSkill( typeID ) ) { // Character already has this skill, so let's get the current level and check to see // if we need to update its level to what's required: SkillRef oldSkill = character->GetSkill( typeID ); oldSkillLevel = oldSkill->GetAttribute( AttrSkillLevel ); // Now check the current level to the required level and update it if( oldSkillLevel < level ) { character->InjectSkillIntoBrain( oldSkill, level); return new PyString ( "Gifting skills complete" ); } } else { // Character DOES NOT have this skill, so spawn a new one and then add this // to the character with required level and skill points: ItemData idata( typeID, ownerID, 0, //temp location flag = (EVEItemFlags)flagSkill, gty ); InventoryItemRef item = services->item_factory.SpawnItem( idata ); skill = SkillRef::StaticCast( item ); if( !item ) throw PyException( MakeCustomError( "Unable to create item of type %s.", item->typeID() ) ); character->InjectSkillIntoBrain( skill, level); return new PyString ( "Gifting skills complete" ); } return new PyString ("Skill Gifting Failure"); }
void Character::UpdateSkillQueue() { Client *c = m_factory.entity_list.FindCharacter( itemID() ); SkillRef currentTraining = GetSkillInTraining(); if( currentTraining ) { if( m_skillQueue.empty() || currentTraining->typeID() != m_skillQueue.front().typeID ) { // either queue is empty or skill with different typeID is in training ... // stop training: _log( ITEM__ERROR, "%s (%u): Stopping training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); /* uint64 timeEndTrain = currentTraining->expiryTime(); if(timeEndTrain != 0) { double nextLevelSP = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ); double SPPerMinute = GetSPPerMin( currentTraining ); double minRemaining = (double)(timeEndTrain - Win32TimeNow()) / (double)Win32Time_Minute; currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); } currentTraining->Clear_expiryTime(); */ EvilNumber timeEndTrain = currentTraining->GetAttribute(AttrExpiryTime); if (timeEndTrain != 0) { EvilNumber nextLevelSP = currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) + 1 ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber minRemaining = (timeEndTrain - EvilNumber(Win32TimeNow())) / (double)Win32Time_Minute; //currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); currentTraining->SetAttribute(AttrSkillPoints, nextLevelSP - (minRemaining * SPPerMinute)); } currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrainingStopped osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = 0; PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // nothing currently in training currentTraining = SkillRef(); } } EvilNumber nextStartTime = EvilTimeNow(); while( !m_skillQueue.empty() ) { if( !currentTraining ) { // something should be trained, get desired skill uint32 skillTypeID = m_skillQueue.front().typeID; currentTraining = GetSkill( skillTypeID ); if( !currentTraining ) { _log( ITEM__ERROR, "%s (%u): Skill %u to train was not found.", itemName().c_str(), itemID(), skillTypeID ); break; } _log( ITEM__TRACE, "%s (%u): Starting training of skill %s (%u).", m_itemName.c_str(), m_itemID, currentTraining->itemName().c_str(), currentTraining->itemID() ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); // double SPToNextLevel = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ) - currentTraining->skillPoints(); EvilNumber SPToNextLevel = currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) + 1) - currentTraining->GetAttribute(AttrSkillPoints); //uint64 timeTraining = nextStartTime + Win32Time_Minute * SPToNextLevel / SPPerMinute; EvilNumber timeTraining = nextStartTime + EvilTime_Minute * SPToNextLevel / SPPerMinute; currentTraining->MoveInto( *this, flagSkillInTraining ); //currentTraining->Set_expiryTime( timeTraining ); currentTraining->SetAttribute(AttrExpiryTime, timeTraining); if( c != NULL ) { OnSkillStartTraining osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = timeTraining.get_int(); PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } } //if( currentTraining->expiryTime() <= Win32TimeNow() ) if( currentTraining->GetAttribute(AttrExpiryTime) <= EvilTimeNow() ) { // training has been finished: _log( ITEM__ERROR, "%s (%u): Finishing training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); //currentTraining->Set_skillLevel( currentTraining->skillLevel() + 1 ); //currentTraining->Set_skillPoints( currentTraining->GetSPForLevel( currentTraining->skillLevel() ) ); //nextStartTime = currentTraining->expiryTime(); //currentTraining->Clear_expiryTime(); currentTraining->SetAttribute(AttrSkillLevel, currentTraining->GetAttribute(AttrSkillLevel) + 1 ); currentTraining->SetAttribute(AttrSkillPoints, currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) ) ); nextStartTime = currentTraining->GetAttribute(AttrExpiryTime); currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrained ost; ost.itemID = currentTraining->itemID(); PyTuple* tmp = ost.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // erase first element in skill queue m_skillQueue.erase( m_skillQueue.begin() ); // nothing currently in training currentTraining = SkillRef(); } // else the skill is in training ... else break; } // Re-Calculate total SP trained and store in internal variable: _CalculateTotalSPTrained(); // Save character and skill data: SaveCharacter(); SaveSkillQueue(); }
PyResult ContractMgrService::Handle_CreateContract( PyCallArgs& call ) { Call_CreateContract info; PyList* requestItemTypeList = new PyList; PyList* itemList = new PyList; uint32 flag = 0; bool forCorp = false; double volume = 0; uint32 maxCharContracts = 0; if( call.byname.find( "forCorp" ) != call.byname.end() ) { forCorp = call.byname.find( "forCorp" )->second->AsBool()->value(); } // Let's see the players limit of contracts CharacterRef ch = call.client->GetChar(); if( forCorp ) { if( ch->HasSkill( 25233 ) ) { SkillRef skill = ch->GetSkill( 25233 ); uint32 skillLevel = skill->GetAttribute( 280 ).get_int(); maxCharContracts = ( 10 * skillLevel ) + 10; } else { maxCharContracts = 10; } } else { if( ch->HasSkill( 25235 ) ) { SkillRef skill = ch->GetSkill( 25235 ); uint32 skillLevel = skill->GetAttribute( 280 ).get_int(); maxCharContracts = ( 4 * skillLevel ) + 1; } else { maxCharContracts = 1; } uint32 numOutstandingContractsNonCorp = 0; uint32 numOutstandingContractsForCorp = 0; std::map<uint32, ContractRef>::const_iterator cur, end; std::map<uint32, ContractRef> contracts = m_contractManager->GetContractList(); cur = contracts.begin(); end = contracts.end(); for(; cur != end; cur++ ) { ContractRef contract = cur->second; if( contract->issuerID() == call.client->GetCharacterID() ) { if( contract->forCorp() ) numOutstandingContractsForCorp += 1; else numOutstandingContractsNonCorp += 1; } } if( ( forCorp ) && ( numOutstandingContractsForCorp >= maxCharContracts ) ) { call.client->SendInfoModalMsg( "Your Corporation Contracting skill level only allows you to create %d public contracts for your corp/alliance", maxCharContracts ); return new PyBool( false ); } if( ( !forCorp ) && ( numOutstandingContractsNonCorp >= maxCharContracts ) ) { call.client->SendInfoModalMsg( "Your Contracting skill level only allows you to create %d public contracts", maxCharContracts ); return new PyBool( false ); } } if( !info.Decode( &call.tuple ) ) { codelog(SERVICE__ERROR, "%s: Bad arguments to CreateContract in contractMgr", call.client->GetCharacterName() ); return NULL; } if( call.byname.find( "requestItemTypeList" ) != call.byname.end() ) { requestItemTypeList = call.byname.find( "requestItemTypeList" )->second->AsList(); } if( call.byname.find( "flag" ) != call.byname.end() ) { flag = call.byname.find( "flag" )->second->AsInt()->value(); } if( call.byname.find( "itemList" ) != call.byname.end() ) { itemList = call.byname.find( "itemList" )->second->AsList(); } if( info.endStationID == 0 )info.endStationID = info.startStationID; ContractData* cData = new ContractData( call.client->GetCharacterID(), call.client->GetCorporationID(), info.type, info.avail, info.assigneeID, info.expiretime, info.expiretime, info.startStationID, info.endStationID, call.client->GetSystemID(), call.client->GetSystemID(), call.client->GetRegionID(), call.client->GetRegionID(), info.price, info.reward, info.collateral, info.title, info.description, forCorp, conStatusOutstanding, false, 0, Win32TimeNow(), Win32TimeNow() + ( info.duration * Win32Time_Day ), Win32TimeNow(), Win32TimeNow(), 0, false, 0, 0, 0 ); std::map<uint32, ContractRequestItemRef> requestItems; std::map<uint32, ContractGetItemsRef> items; uint32 itemID = 0; uint32 typeID = 0; for( size_t i = 0; i < itemList->size(); i ++ ) { if( itemList->IsList() ) { if( itemList->GetItem( i )->AsList()->GetItem( 0 )->IsInt() ) itemID = itemList->GetItem( i )->AsList()->GetItem( 0 )->AsInt()->value(); else{ sLog.Error( "ContractMgrService", "Wrong list args" ); break; } } InventoryItemRef item = m_manager->item_factory.GetItem( itemID ); if( item == NULL ) { sLog.Error( "ContractMgrService", "GetItem returned NULL" ); break; } item->Move( call.client->GetStationID(), flagBriefcase, true ); item->ChangeOwner( 1, true ); items.insert( std::make_pair( itemID, ContractGetItemsRef( new ContractGetItems( itemID, itemList->GetItem( i )->AsList()->GetItem( 1 )->AsInt()->value() ) ) ) ); } if( cData->m_type == conTypeItemExchange ) { for( size_t i = 0; i < requestItemTypeList->size(); i ++ ) { if( itemList->IsList() ) { if( requestItemTypeList->GetItem( i )->AsList()->GetItem( 0 )->IsInt() ) typeID = requestItemTypeList->GetItem( i )->AsList()->GetItem( 0 )->AsInt()->value(); else{ sLog.Error( "ContractMgrService", "Wrong list args" ); break; } } requestItems.insert( std::make_pair( itemID, ContractRequestItemRef( new ContractRequestItem(itemID, requestItemTypeList->GetItem( i )->AsList()->GetItem( 1 )->AsInt()->value() ) ) ) ); } } uint32 contractID = 0; sLog.Debug( "ContractMgrService", "Creating contract..." ); ContractRef _contract = ContractRef( new Contract( contractID, *cData, requestItems, items, m_manager->item_factory, *m_contractManager ) ); contractID = m_contractManager->CreateContract( _contract ); sLog.Debug( "ContractMgrService", "Contract created" ); return new PyInt( contractID ); }