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->Set_skillLevel( 0 ); skill->Set_skillPoints( 0 ); if( skill->flag() != flagSkillInTraining ) skill->Clear_expiryTime(); } } } }
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(); 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(); } } uint64 nextStartTime = Win32TimeNow(); 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() ); double SPPerMinute = GetSPPerMin( currentTraining ); double SPToNextLevel = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ) - currentTraining->skillPoints(); uint64 timeTraining = nextStartTime + Win32Time_Minute * SPToNextLevel / SPPerMinute; currentTraining->MoveInto( *this, flagSkillInTraining ); currentTraining->Set_expiryTime( timeTraining ); if( c != NULL ) { OnSkillStartTraining osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = timeTraining; PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } } if( currentTraining->expiryTime() <= Win32TimeNow() ) { // 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->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; } SaveSkillQueue(); }