EvilNumber ME_EffectOnWaste( EvilNumber MaterialAmount, EvilNumber BaseWasteFactor, EvilNumber MaterialEfficiency ) { EvilNumber ME_Factor(0.0); if( MaterialEfficiency >= 0 ) ME_Factor = (1.0 / (MaterialEfficiency.get_float() + 1.0)); else ME_Factor = (1.0 - MaterialEfficiency.get_float()); return (floor(0.5 + (MaterialAmount.get_float() * (BaseWasteFactor.get_float() / 100.0) * ME_Factor.get_float()))); }
EvilNumber EffectiveStanding( EvilNumber YourStanding, EvilNumber ConnectionsSkillLevel, EvilNumber DiplomacySkillLevel ) { EvilNumber SkillLevel(0.0); if( YourStanding < 0.0 ) SkillLevel = DiplomacySkillLevel; else SkillLevel = ConnectionsSkillLevel; return (YourStanding.get_float() + ((10.0 - YourStanding.get_float()) * (0.04 * (SkillLevel.get_float())))); }
void ActiveModuleProcessingComponent::ProcessActiveCycle() { //TO-DO: Check to see if capacitor is drained at activation or after the cycle //check for stop signal if(m_Stop) return; //else consume capacitor EvilNumber capCapacity = m_Ship->GetAttribute(AttrCharge); EvilNumber capNeed = m_Mod->GetAttribute(AttrCapacitorNeed); capCapacity -= capNeed; m_Ship->SetAttribute(AttrCharge, capCapacity.get_float()); //then check if we are targeting another ship or not and apply attribute changes //maybe we can have a check for modules that repeat the same attributes so we //send the changes just once at activation and at deactivation //--pseudocode-- //if(target != self) // m_ShipAttrComp->ModifyTargetShipAttribute(); //else // m_ShipAttrComp->ModifyShipAttribute(); }
/* rewrote attrib calculations and implemented true stacking penality, with checks for exceptions. -allan 13April16 */ void ModifyModuleAttributesComponent::_modifyModuleAttributes(GenericModule* targetMod, uint32 targetAttrID, uint32 sourceAttrID, EVECalculationType type) { uint8 stackSize = 1; EvilNumber modVal = m_Mod->GetAttribute(sourceAttrID), startVal = targetMod->GetAttribute(targetAttrID); /* check for attribs that are NOT penalized here, and bypass stacking method. */ /* note: DCU, rigs and subsystems do not use this method */ if ((targetAttrID != AttrWarpFactor) or (sourceAttrID != AttrCargoCapacityMultiplier)) { std::map<uint16, uint8>::iterator itr = m_attribMap.find(targetAttrID); if (itr != m_attribMap.end()) { /** @todo verify these module states */ if (m_Mod->GetModuleState() == MOD_ONLINE) stackSize = ++itr->second; else if ((m_Mod->GetModuleState() == MOD_OFFLINE) or (m_Mod->GetModuleState() == MOD_DEACTIVATING)) /** @todo implement the difference between MOD_OFFLINE and MOD_DEACTIVATING */ { if (itr->second == 1) m_attribMap.erase(itr); else stackSize = --itr->second; } } else m_attribMap.emplace(targetAttrID, 1); } double effectiveness = 1; if (m_Mod->GetModuleState() == MOD_ONLINE) { effectiveness = exp(-pow(((stackSize - 1)/2.67),2)); //stacking calculation fixed -allan 20Dec15 m_Mod->SetEffectiveness(targetAttrID, effectiveness); } else if ((m_Mod->GetModuleState() == MOD_OFFLINE) or (m_Mod->GetModuleState() == MOD_DEACTIVATING)) { effectiveness = m_Mod->GetEffectiveness(targetAttrID); } if (effectiveness <= 0) { /* this should never happen */ codelog(SHIP__MODULE_ERROR, "MMAC::_modifyModuleAttributes() - effectiveness <= 0"); targetMod->GetShipRef()->GetPilot()->SendErrorMsg("Internal Server Error. Ref: ServerError 25620"); } modVal *= effectiveness; EvilNumber newVal = CalculateNewAttributeValue(startVal, modVal, type); _log(SHIP__MODULE_TRACE, "MMAC::_modifyModuleAttributes() - origVal:%f, Mod:%f, newVal:%f, stackSize:%u, effective:%f, type:%i", \ startVal.get_float(), modVal.get_float(), newVal.get_float(), stackSize, effectiveness, (int)type); SetAttribute(targetMod, targetAttrID, newVal); }
uint32 TargetManager::TimeToLock(ShipRef ship, SystemEntity *target) const { EvilNumber scanRes = ship->GetAttribute(AttrScanResolution); EvilNumber sigRad(500); if( target->Item().get() != NULL ) if( target->Item()->HasAttribute(AttrSignatureRadius) ) sigRad = target->Item()->GetAttribute(AttrSignatureRadius); EvilNumber time = ( EvilNumber(40000) / ( scanRes ) ) /( EvilNumber::pow( e_log( sigRad + e_sqrt( sigRad * sigRad + 1) ), 2) ); return static_cast<uint32>(time.get_float() * 1000); // Timer uses ms instead of seconds }
EvilNumber ProductionTime( EvilNumber BaseProductionTime, EvilNumber ProductivityModifier, EvilNumber ProductionEfficiency, EvilNumber ProductionTimeModifier ) { EvilNumber PE_Factor(0.0); if( ProductionEfficiency >= 0.0 ) PE_Factor = (ProductionEfficiency.get_float() / (1.0 + ProductionEfficiency.get_float())); else PE_Factor = (ProductionEfficiency.get_float() - 1.0); return (BaseProductionTime.get_float() * (1.0 - (ProductivityModifier.get_float() / BaseProductionTime.get_float()) * (PE_Factor.get_float())) * ProductionTimeModifier.get_float()); }
EvilNumber BlueprintInventionChance( EvilNumber BaseChance, EvilNumber EncryptionSkillLevel, EvilNumber DataCore1SkillLevel, EvilNumber DataCore2SkillLevel, EvilNumber MetaLevel, EvilNumber DecryptorModifier ) { return (BaseChance.get_float() * (1+0.01*EncryptionSkillLevel.get_float()) * (1+(DataCore1SkillLevel.get_float()+DataCore2SkillLevel.get_float()) * (0.1 / (5 - MetaLevel.get_float())) * DecryptorModifier.get_float())); }
// set attributes that are not stackable here...calibration, PG, CPU, etc. void ModifyModuleAttributesComponent::ModifyNonStackingModuleAttributes(GenericModule* targetMod, uint32 targetAttrID, uint32 sourceAttrID, EVECalculationType type) { EvilNumber newVal = CalculateNewAttributeValue(targetMod->GetAttribute(targetAttrID), m_Mod->GetAttribute(sourceAttrID), type); if (!targetMod->getItem()->SetAttribute(targetAttrID, newVal)) sLog.Error("MMAC::ModifyNonStackingModuleAttributes()","Failed to set attribute %u to %f on module %u", targetAttrID, newVal.get_float(), targetMod->itemID()); }
EvilNumber TradeBrokerFee( EvilNumber BrokerRelationsSkillLevel, EvilNumber FactionStanding, EvilNumber CorporationStanding ) { return (100.0 * ((0.01 - 0.0005 * BrokerRelationsSkillLevel.get_float()) / (pow( 2, (0.14 * FactionStanding.get_float() + 0.06 * CorporationStanding.get_float()) )))); }
EvilNumber TargetingLockTime( EvilNumber YourEffectiveScanResolution, EvilNumber TargetEffectiveSignatureRadius ) { return (40000.0 / (YourEffectiveScanResolution.get_float() * pow(asinh(TargetEffectiveSignatureRadius.get_float()),2))); }
EvilNumber SkillPointsAtLevel( EvilNumber SkillLevel, EvilNumber SkillRank ) { return (pow( 2, (2.5 * SkillLevel.get_float()) - 2.5 ) * 250.0 * SkillRank); }
EvilNumber MissionStandingIncrease( EvilNumber BaseMissionIncrease, EvilNumber YourSocialSkillLevel ) { return (BaseMissionIncrease * (1 + 0.05 * YourSocialSkillLevel.get_float())); }
EvilNumber RequiredAgentStanding( EvilNumber AgentLevel, EvilNumber AgentQuality ) { return (((AgentLevel.get_float() - 1) * 2) + (AgentQuality.get_float()/20.0)); }
EvilNumber ME_LevelToEliminateWaste( EvilNumber MaterialAmount, EvilNumber BaseWasteFactor ) { return (floor(0.02 * BaseWasteFactor.get_float() * MaterialAmount.get_float())); }
EvilNumber AgentEffectiveQuality( EvilNumber AgentQuality, EvilNumber NegotiationSkillLevel, EvilNumber AgentPersonalStanding ) { return (AgentQuality.get_float() + (5.0 * NegotiationSkillLevel.get_float()) + AgentPersonalStanding.get_float()); }
EvilNumber WasteSkillBased( EvilNumber MaterialAmount, EvilNumber ProductionEfficiency ) { return (floor(0.5 + (MaterialAmount.get_float() * ((25.0 - (5.0 * ProductionEfficiency.get_float())) / 100.0)))); }
EvilNumber PE_ResearchTime( EvilNumber BlueprintBaseResearchTime, EvilNumber ResearchSkillLevel, EvilNumber ResearchSlotModifier, EvilNumber ImplantModifier ) { return (BlueprintBaseResearchTime.get_float() * (1.0 - (0.05 * ResearchSkillLevel.get_float())) * ResearchSlotModifier.get_float() * ImplantModifier.get_float()); }
EvilNumber EffectiveRefiningYield( EvilNumber StationEquipmentYield, EvilNumber RefiningSkillLevel, EvilNumber RefiningEfficiencySkillLevel, EvilNumber OreSpecificProcessingSkillLevel ) { return (StationEquipmentYield.get_float() + 0.375 * (1 + (RefiningSkillLevel.get_float() * 0.02)) * (1 + (RefiningEfficiencySkillLevel.get_float() * 0.04)) * (1 + (OreSpecificProcessingSkillLevel.get_float() * 0.05))); }
EvilNumber StationTaxesForReprocessing( EvilNumber CharacterStandingWithStationOwner ) { return (5.0 - 0.75 * CharacterStandingWithStationOwner.get_float()); }
EvilNumber ProductionTimeModifier( EvilNumber IndustrySkillLevel, EvilNumber ImplantModifier, EvilNumber ProductionSlotModifier ) { return (1.0 - (0.04 * IndustrySkillLevel.get_float()) * ImplantModifier.get_float() * ProductionSlotModifier.get_float()); }
EvilNumber BluePrintCopyTime( EvilNumber BlueprintBaseCopyTime, EvilNumber ScienceSkillLevel, EvilNumber CopySlotModifier, EvilNumber ImplantModifier ) { return (BlueprintBaseCopyTime.get_float() * (1.0 - (0.05 * ScienceSkillLevel.get_float())) * CopySlotModifier.get_float() * ImplantModifier.get_float()); }
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(); }
EvilNumber ResearchPointsPerDay( EvilNumber Multiplier, EvilNumber AgentEffectiveQuality, EvilNumber YourResearchSkillLevel, EvilNumber AgentResearchSkillLevel ) { return (Multiplier.get_float() * (1 + (AgentEffectiveQuality.get_float() / 100.0)) * pow(YourResearchSkillLevel.get_float() + AgentResearchSkillLevel.get_float(),2)); }