/* * Set a new mapping scheme of property impact */ void CHarvestSource::setNewImpactScheme() { H_AUTO(CHarvestSource_setNewImpactScheme); // Set mapping scheme of property impact if ( _IsInNewbieMode ) { // Force "low dangers" for 1 newbie extractor _IImpactMappingScheme = (uint16)LowDangerMappings[RandomGenerator.rand( 1 )]; } else { // Normal dangers if ( ForageForceImpactScheme.get() == -1 ) _IImpactMappingScheme = (uint16)RandomGenerator.rand( 5 ); else _IImpactMappingScheme = (uint16)ForageForceImpactScheme.get(); } sendMessageToExtractors( "FORAGE_SOURCE_IMPACT_MODE", (sint32)_IImpactMappingScheme ); #ifdef NL_DEBUG nldebug( "FG: map scheme: %u", _IImpactMappingScheme ); #endif }
// ---------------------------------------------------------------------------- void CMissionQueueManager::saveToFile() { H_AUTO(CMissionQueueManagerSaveToFile); if( _InitOk ) { string sFilename = MissionQueueFile.get(); // save file via Backup Service (BS) try { static CPersistentDataRecordRyzomStore pdr; pdr.clear(); store(pdr); CBackupMsgSaveFile msg( sFilename, CBackupMsgSaveFile::SaveFile, Bsi ); { std::string s; pdr.toString(s); msg.DataMsg.serialBuffer((uint8*)&s[0], (uint)s.size()); } Bsi.sendFile( msg ); } catch(const Exception &) { nlwarning("(EGS)<CMissionQueueManager::saveToFile> : Can't serial file %s (connection with BS service down ?)",sFilename.c_str()); return; } } }
/** * updateShardOpenFromFile() * Update ShardOpen from a file. * Read a line of text in the file, converts it to int (atoi), then casts into bool for ShardOpen. */ void updateShardOpenFromFile(const std::string& filename) { CIFile f; if (!f.open(filename)) { nlwarning("Failed to update ShardOpen from file '%s', couldn't open file", filename.c_str()); return; } try { char readBuffer[256]; f.getline(readBuffer, 256); sint state; NLMISC::fromString(std::string(readBuffer), state); setShardOpenState((TShardOpenState)state); nlinfo("Updated ShardOpen state to '%u' from file '%s'", ShardOpen.get(), filename.c_str()); } catch (const Exception& e) { nlwarning("Failed to update ShardOpen from file '%s', exception raised while getline() '%s'", filename.c_str(), e.what()); } }
static void cbGetFileClass( CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId ) { if (!BSReadState.get()) return; CMessage msgOut = getFileClassImp(msgin); // send the output message CUnifiedNetwork::getInstance()->send(serviceId, msgOut); }
static void cbSyncGetFileClass( CMessage& msgin, TSockId from, CCallbackNetBase &netbase) { if (!BSReadState.get()) return; CMessage msgOut = getFileClassImp(msgin); // send the output message netbase.send(msgOut, from); }
static void cbReadMode( CMessage& msgin, TSockId from, CCallbackNetBase &netbase) { // encode the read mode and return CMessage msgout("BS_READ_MODE"); bool readMode = BSReadState.get(); nlWrite(msgout, serial, readMode); // send it back to sender netbase.send(msgout, from); }
//----------------------------------------------------------------------------- static void cbDisconnection( const string &serviceName, NLNET::TServiceId serviceId, void *arg ) { if (serviceName == "BS" && !MasterBSHost.get().empty()) { nlwarning("SLAVE BS: MASTER BS IS DOWN!! File reading allowed!"); MasterBSUp = false; BSReadState = true; IService::getInstance()->addStatusTag("MasterDown"); IService::getInstance()->removeStatusTag("MasterRunning"); } } // cbDisconnection //
void CDirectoryRateStat::writeFile(const std::string& filename, uint32 filesize) { NLMISC::TTime now = NLMISC::CTime::getLocalTime(); if (filename.find("www") != std::string::npos) { _DirectoryMap["www"].write(now, filesize); } else if (filename.find(StatDirFilter.get()) != std::string::npos) { _DirectoryMap[NLMISC::CFile::getPath(filename)].write(now, filesize); } }
// a new front end connecting to me, add it void cbFESConnection (const std::string &serviceName, TServiceId sid, void *arg) { FESList.push_back (CFES ((TServiceId)sid)); nldebug("new FES connection: sid %u", sid.get()); displayFES (); bool dummy; FESList.back().reportStateToLS(dummy); if (!UsePatchMode.get()) { FESList.back().setToAcceptClients(); } }
// ---------------------------------------------------------------------------- void CMissionQueueManager::init() { string sFilename = MissionQueueFile.get(); sFilename = Bsi.getLocalPath() + sFilename; if (CFile::fileExists(sFilename)) { static CPersistentDataRecord pdr; pdr.clear(); pdr.readFromTxtFile(sFilename.c_str()); apply(pdr); } _InitOk = true; }
// ---------------------------------------------------------------------------- void CMissionQueueManager::tickUpdate() { if( IsRingShard ) // Temporary Fix potential problem with multi shard instance Ring unification: return; // Mission saved tick must be adapted for have relative value saved H_AUTO(CMissionQueueManagerUpdate); for ( map<uint32,CMissionQueue>::iterator it = _Queues.begin() ; it != _Queues.end() ; ++it ) { (*it).second.tickUpdate(); } // save file when time has come if (CTickEventHandler::getGameCycle() % MissionQueueSavePeriod.get() == 0) saveToFile(); }
/* * Update */ bool CLogAnalyserService::update() { updateWebConnection(); // erase queries that have timed out NLMISC::TTime ctime = NLMISC::CTime::getLocalTime(); std::deque<CQuery*>::iterator it; for (it=_Finished.begin(); it!=_Finished.end(); ) { if (ctime - (*it)->Timeout > QueryTimeout.get() * 1000) { delete (*it); it = _Finished.erase(it); } else { ++it; } } // current query finished? move to finished, destroy thread if (_Current != NULL && _Current->Finished) { _Finished.push_front(_Current); _Current = NULL; _Thread->wait(); delete _Thread; _Thread = NULL; } // no current running task? create new thread, start query _Mutex.enter(); if (_Current == NULL && !_Requests.empty()) { _Current = _Requests.back(); _Requests.pop_back(); LogTask.Query = _Current; _Thread = IThread::create(&LogTask); _Thread->start(); } _Mutex.leave(); return true; }
//----------------------------------------------------------------------------- void CBackupService::init() { FileManager.init(); setUpdateTimeout(100); _SaveStall = false; // set the connection and disconnection callbacks CUnifiedNetwork::getInstance()->setServiceUpCallback( string("*"), cbConnection, 0); CUnifiedNetwork::getInstance()->setServiceDownCallback( string("*"), cbDisconnection, 0); CUnifiedNetwork::getInstance()->setServiceUpCallback( string("BS"), cbConnection, 0); CUnifiedNetwork::getInstance()->setServiceDownCallback( string("BS"), cbDisconnection, 0); // Init the sheet Id CSheetId::init(false); if (!MasterBSHost.get().empty()) { IService::getInstance()->addStatusTag("SlaveMode"); IService::getInstance()->setCurrentStatus("WaitingMaster"); BSIsSlave = true; FileManager.forbidStall(); // I'm a slave, try to contact master string host = MasterBSHost; if (host.find (":") == string::npos) host += ":49990"; CUnifiedNetwork::getInstance()->addService ("BS", CInetAddress(host)); } // set the initial read state from the config file CConfigFile::CVar *readState = ConfigFile.getVarPtr("BSReadState"); if (readState != NULL) BSReadState = readState->asBool(); initWebConnection(); _CallbackServer = new NLNET::CCallbackServer; _CallbackServer->addCallbackArray(cbSyncArray, sizeofarray(cbSyncArray)); // open the layer 3 callback server if required if (L3ListeningPort != 0) _CallbackServer->init(L3ListeningPort); }
// connection to the LS, send the identification message void cbLSConnection (const std::string &serviceName, TServiceId sid, void *arg) { sint32 shardId; if (IService::getInstance()->haveArg('S')) { // use the command line param if set NLMISC::fromString(IService::getInstance()->getArg('S'), shardId); } else if (IService::getInstance()->ConfigFile.exists ("ShardId")) { // use the config file param if set shardId = IService::getInstance()->ConfigFile.getVar ("ShardId").asInt(); } else { shardId = -1; } if (shardId == -1) { nlerror ("ShardId variable must be valid (>0)"); } CMessage msgout ("WS_IDENT"); msgout.serial (shardId); CUnifiedNetwork::getInstance()->send (sid, msgout); nlinfo ("Connected to %s-%hu and sent identification with shardId '%d'", serviceName.c_str(), sid.get(), shardId); // send state to LS setShardOpenState((TShardOpenState)(ShardOpen.get()), false); // if (!DontUseLS) { CMessage msgrpn("REPORT_NO_PATCH"); CUnifiedNetwork::getInstance()->send("LS", msgrpn); } bool reportPatching = false; list<CFES>::iterator itfs; for (itfs=FESList.begin(); itfs!=FESList.end(); ++itfs) (*itfs).reportStateToLS(reportPatching); }
/** * cbUsePatchMode() * Callback for UsePatchMode */ void cbUsePatchMode(IVariable &var) { // if patch mode not set, set all fs in patching mode to accept clients now if (!UsePatchMode.get()) { nlinfo("UsePatchMode disabled, switch all patching servers to actual frontends"); list<CFES>::iterator it; for (it=FESList.begin(); it!=FESList.end(); ++it) { if ((*it).State == PatchOnly) { (*it).setToAcceptClients(); } } } }
void CGearLatency::setSlot( INVENTORIES::TInventory inventory, uint32 slot, const CStaticItem * form, CCharacter * user ) { static NLMISC::CSheetId equipSheet("big_equip_item.sbrick"); // checks must be done by the caller nlassert(form); nlassert(user); // ignore instant equip items if ( form->TimeToEquip == 0) return; // build a new entry CGearSlot gear; if (inventory == INVENTORIES::equipment) gear.InHand = false; else if (inventory == INVENTORIES::handling) gear.InHand = true; else nlerror("setSlot : Invalid inventory %u ('%s') : must be handling or equipment ",inventory,INVENTORIES::toString(inventory).c_str() ); gear.Slot = slot; gear.LatencyEndDate = (form->TimeToEquip * EquipTimeFactor.get()) + CTickEventHandler::getGameCycle(); // add it in our sorted list std::list<CGearSlot>::iterator it = _GearLatencies.begin(); for (; it != _GearLatencies.end(); ++it) { if ( (*it).LatencyEndDate >= gear.LatencyEndDate ) break; } if ( it == _GearLatencies.end() ) { // user->_PropertyDatabase.setProp( "USER:ACT_TSTART", CTickEventHandler::getGameCycle() ); CBankAccessor_PLR::getUSER().setACT_TSTART(user->_PropertyDatabase, CTickEventHandler::getGameCycle() ); // user->_PropertyDatabase.setProp( "USER:ACT_TEND", gear.LatencyEndDate ); CBankAccessor_PLR::getUSER().setACT_TEND(user->_PropertyDatabase, gear.LatencyEndDate ); // sint64 tmp = (sint64)user->actionCounter(); // user->_PropertyDatabase.setProp( "USER:ACT_NUMBER", tmp ); // user->_PropertyDatabase.setProp( "EXECUTE_PHRASE:SHEET", sint64(equipSheet.asInt()) ); CBankAccessor_PLR::getEXECUTE_PHRASE().setSHEET(user->_PropertyDatabase, equipSheet); // user->_PropertyDatabase.setProp( "EXECUTE_PHRASE:PHRASE", 0 ); CBankAccessor_PLR::getEXECUTE_PHRASE().setPHRASE(user->_PropertyDatabase, 0 ); } _GearLatencies.insert( it, gear ); }// CGearLatency::setSlot
static void cbLoadFile( CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId ) { if (!BSReadState.get()) return; try { CBackupMsgRequestFile msg; msgin.serial(msg); CLoadFile* access = new CLoadFile(msg.FileName, serviceId, msg.RequestId); CBackupService::getInstance()->FileManager.stackFileAccess(access); } catch (...) { nlwarning("WARNING: caught exception in cbLoadFile()"); } }
static void cbSyncLoadFile( CMessage& msgin, TSockId from, CCallbackNetBase &netbase) { if (!BSReadState.get()) return; try { CBackupMsgRequestFile msg; msgin.serial(msg); CLoadFile* access = new CLoadFile(msg.FileName, TRequester(from, &netbase), msg.RequestId); CBackupService::getInstance()->FileManager.stackFileAccess(access); } catch (...) { nlwarning("WARNING: caught exception in cbLoadFile()"); } }
void CMailForumService::checkMail() { TTime now = CTime::getLocalTime(); if (now - LastCheckMail < 10*1000) return; LastCheckMail = now; string dir = CPath::standardizePath(WebRootDirectory)+IncomingMailDirectory.get(); // no path, no mails if (!CFile::isExists(dir)) return; std::vector<std::string> files; CPath::getPathContent(dir, false, false, true, files); if (files.empty()) return; uint i; for (i=0; i<files.size(); ++i) checkFile(files[i]); }
// This function is called by FES to setup its PatchAddress void cbFESPatchAddress(CMessage &msgin, const std::string &serviceName, TServiceId sid) { std::string address; msgin.serial(address); bool acceptClients; msgin.serial(acceptClients); nldebug("Received patch server address '%s' from service %s %d", address.c_str(), serviceName.c_str(), sid.get()); for (list<CFES>::iterator it = FESList.begin(); it != FESList.end(); it++) { if ((*it).SId == sid) { nldebug("Affected patch server address '%s' to frontend %s %d", address.c_str(), serviceName.c_str(), sid.get()); if (!UsePatchMode.get() && !acceptClients) { // not in patch mode, force fs to accept clients acceptClients = true; (*it).setToAcceptClients(); } (*it).PatchAddress = address; (*it).State = (acceptClients ? AcceptClientOnly : PatchOnly); if (acceptClients) nldebug("Frontend %s %d reported to accept client, patching unavailable for that server", address.c_str(), serviceName.c_str(), sid.get()); else nldebug("Frontend %s %d reported to be in patching mode", address.c_str(), serviceName.c_str(), sid.get()); bool dummy; (*it).reportStateToLS(dummy); break; } } }
//----------------------------------------------------------------------------- void cbReadState(IVariable& v) { if (!BSIsSlave) return; CBackupService::getInstance()->FileManager.forbidStall(!BSReadState.get()); }
/* * Report the accumulated XP during an extraction session. Assumes extractor and source not null. */ void CForageProgress::reportXP( CCharacter *extractor, const CHarvestSource *source ) { H_AUTO(CForageProgress_reportXP); #if !FINAL_VERSION nlassert(extractor); nlassert(source); #endif // Don't earn any XP for anyone if the quantity is 0 if ( amount() == 0 ) return; // Count XP depending on class float xpBonusFactor = 0.9f - ForageProspectionXPBonusRatio.get() + ((((float)(source->getStatQuality()))-5.0f)/(75.0f*5.0f)); // basic gives -10%, supreme gives +10% bonus (5 -> 0.0, 80 -> 0.2) float nbParticipants = 1.0f; // at least the extractor // Count XP for prospection (if there was one) const TDataSetRow& prospectorDataSetRow = source->getProspectorDataSetRow(); // can be invalid (auto-spawned source) CCharacter *prospector = PlayerManager.getChar( prospectorDataSetRow ); // checks isAccessible() if ( prospector ) { xpBonusFactor += ForageProspectionXPBonusRatio.get(); if ( prospector != extractor ) ++nbParticipants; } // Find out how many care casters were useful vector<CCharacter*> usefulCareCasters; const CHarvestSource::CForagers& foragers = source->foragers(); CHarvestSource::CForagers::const_iterator itf = foragers.begin(); // the first one is the only one able to extract for ( ++itf; itf!=foragers.end(); ++itf ) { const TDataSetRow& ccRowId = (*itf); CCharacter *careCaster = PlayerManager.getChar( ccRowId ); if ( careCaster && careCaster->forageProgress() ) { // Check if this care caster has not changed his target if ( careCaster->forageProgress()->sourceRowId() == source->rowId() ) { // Check if this care caster has teamed up with the extractor! if ( (careCaster->getTeamId() != CTEAM::InvalidTeamId) && (careCaster->getTeamId() == extractor->getTeamId()) ) { // Check if he casted some useful care if ( careCaster->forageProgress()->hasCastedUsefulCare() ) { usefulCareCasters.push_back( careCaster ); if ( careCaster != prospector ) // don't count the prospector twice ++nbParticipants; } } else { PHRASE_UTILITIES::sendDynamicSystemMessage( careCaster->getEntityRowId(), "FORAGE_CARE_XP_NEEDS_TEAM" ); } } } } // Count XP for number of participants and nasty events xpBonusFactor += (nbParticipants-1.0f) * ForageExtractionNbParticipantsXPBonusRatio.get(); // everyone gets 10% more per additional forager float nbNastyEvents = (float)(source->nbEventTriggered()); xpBonusFactor -= nbNastyEvents * ForageExtractionNastyEventXPMalusRatio.get(); // Count XP per participant float xpPerParticipant = ForageExtractionXPFactor.get() * xpBonusFactor / nbParticipants; // Give XP to extractor reportXPTo( extractor, xpPerParticipant, extractor->getRightHandItem() ); bool isProspectorCredited = false; if ( extractor == prospector ) { SM_STATIC_PARAMS_1(params, STRING_MANAGER::integer); params[0].Int = 0; PHRASE_UTILITIES::sendDynamicSystemMessage( prospector->getEntityRowId(), "FORAGE_XP_PROSPECTION", params ); isProspectorCredited = true; } if ( source->wasProspected() ) { // Give energy back! SCharacteristicsAndScores& focus = extractor->getScores()._PhysicalScores[SCORES::focus]; if ( focus.Current < initialFocus() ) focus.Current = focus.Current() + (sint32)(ForageFocusAutoRegenRatio.get() * (float)(initialFocus()-focus.Current)); } // Give XP to care casters for ( vector<CCharacter*>::iterator icc=usefulCareCasters.begin(); icc!=usefulCareCasters.end(); ++icc ) { CCharacter *careCaster = (*icc); reportXPTo( careCaster, xpPerParticipant, careCaster->getRightHandItem() ); if ( prospector == careCaster ) { SM_STATIC_PARAMS_1(params, STRING_MANAGER::integer); params[0].Int = 0; PHRASE_UTILITIES::sendDynamicSystemMessage( prospector->getEntityRowId(), "FORAGE_XP_PROSPECTION", params ); isProspectorCredited = true; } if ( source->wasProspected() && careCaster->forageProgress() ) { // Give energy back! SCharacteristicsAndScores& focus = careCaster->getScores()._PhysicalScores[SCORES::focus]; if ( focus.Current < careCaster->forageProgress()->initialFocus() ) focus.Current = focus.Current() + (sint32)(ForageFocusAutoRegenRatio.get() * (float)(careCaster->forageProgress()->initialFocus()-focus.Current)); } } // Give XP to "standalone" prospector (if any) if ( prospector && (! isProspectorCredited) ) { reportXPTo( prospector, xpPerParticipant, NULL ); SM_STATIC_PARAMS_1(params, STRING_MANAGER::integer); params[0].Int = 1; PHRASE_UTILITIES::sendDynamicSystemMessage( prospector->getEntityRowId(), "FORAGE_XP_PROSPECTION", params ); } }
//---------------------------------------------------------------------------- void COutpostManager::loadOutpostSaveFiles() { if (!LoadOutposts.get()) return; // only once if (_OutpostSaveFilesLoaded) return; // check preconditions nlassert(_OutpostPrimitivesLoaded); nlassert(CGuildManager::getInstance()->loadedGuilds()); OUTPOST_DBG("Applying outpost save files..."); // all outposts where parsed. Let's try to load their saved files to init the dynamic data. string path = /*Bsi.getLocalPath() +*/ string("outposts"); // create the saved file directory, if needed // CFile::createDirectory(path); // get all the outpost files TOupostFileClassCallback *ccb = new TOupostFileClassCallback; OutpostFiles.clear(); vector<CBackupFileClass> outpostClasses(1); outpostClasses[0].Patterns.push_back("outpost*.bin"); Bsi.syncLoadFileClass("outposts", outpostClasses, ccb); // load all the outpost file loadedOutposts.clear(); TOupostFileCallback *cb = new TOupostFileCallback; Bsi.syncLoadFiles(OutpostFiles, cb); // CPath::getPathContent (path, false, false, true,files ,NULL); // vector<COutpost*> loadedOutposts; // for (uint i = 0; i < files.size(); i++) // { // string file = files[i].substr( path.size() + 1); // // check if we have an outpost file // if ( file.find( "outpost_" ) == 0 && // file.find( ".bin" ) == file.length() - 4 ) // { // // get the corresponding outpost // string aliasStr = file; // aliasStr.resize( file.length() - 4 ); // aliasStr = aliasStr.substr( 8, file.length() - 8 ); // // TAIAlias alias; // NLMISC::fromString(aliasStr, alias); // COutpost * outpost = getOutpostFromAlias( alias ); // if ( !outpost ) // OUTPOST_WRN("Invalid outpost file '%s' ('%u') : not found in the primitive", file.c_str(), alias); // else // { // // load dynamic data // static CPersistentDataRecord pdr; // pdr.clear(); // pdr.readFromBinFile(files[i].c_str()); // outpost->apply( pdr ); // loadedOutposts.push_back( outpost ); // } // } // } OUTPOST_DBG("Outpost save files applied."); OUTPOST_DBG("Initializing unsaved outposts..."); // Init new outpost that have never been saved uint nbNewOutposts = 0; for (vector<NLMISC::CSmartPtr<COutpost> >::const_iterator it = _Outposts.begin(); it != _Outposts.end(); ++it) { if ( std::find( loadedOutposts.begin(), loadedOutposts.end(), *it ) == loadedOutposts.end() ) { COutpost *newOutpost = (*it); newOutpost->initNewOutpost(); ++nbNewOutposts; } } if ( nbNewOutposts != 0 ) { OUTPOST_INF( "Created default squads for %u new outposts", nbNewOutposts ); } OUTPOST_DBG("Unsaved outposts initialized."); OUTPOST_DBG("Registering outposts in guilds..."); // register outposts in guilds for (uint i = 0; i < _Outposts.size(); i++) { _Outposts[i]->registerOutpostInGuilds(); } OUTPOST_DBG("Outposts registered in guilds."); // array of callback items NLNET::TUnifiedCallbackItem _cbArray[] = { { "OUTPOST_SQUAD_CREATED", cbOutpostSquadCreated }, { "OUTPOST_SQUAD_SPAWNED", cbOutpostSquadSpawned }, { "OUTPOST_SQUAD_DESPAWNED", cbOutpostSquadDespawned }, { "OUTPOST_SQUAD_DIED", cbOutpostSquadDied }, { "OUTPOST_SQUAD_LEADER_DIED", cbOutpostSquadLeaderDied }, }; // register call back for outpost manager CUnifiedNetwork::getInstance()->addCallbackArray( _cbArray, sizeof(_cbArray) / sizeof(_cbArray[0]) ); // outpost save files now are loaded _OutpostSaveFilesLoaded = true; // trigger pending ready AI instance events for ( std::set<uint32>::const_iterator it = _PendingReadyAIInstances.begin(); it != _PendingReadyAIInstances.end(); ++it) { onAIInstanceReadyOrDown(*it, true); } _PendingReadyAIInstances.clear(); }
/** * cbShardOpen() * Callback for ShardOpen */ void cbShardOpen(IVariable &var) { setShardOpenState((TShardOpenState)(ShardOpen.get()), false); }
//void cbLSChooseShard (CMessage &msgin, const std::string &serviceName, uint16 sid) std::string lsChooseShard (const std::string &userName, const CLoginCookie &cookie, const std::string &userPriv, const std::string &userExtended, WS::TUserRole userRole, uint32 instanceId, uint32 charSlot) { // the LS warns me that a new client want to come in my shard // // S07: receive the "CS" message from LS and send the "CS" message to the selected FES // /* uint totalNbUsers; CFES *best = findBestFES( totalNbUsers ); if (best == NULL) { // answer the LS that we can't accept the user CMessage msgout ("SCS"); string reason = "No front-end server available"; msgout.serial (reason); msgout.serial (cookie); CUnifiedNetwork::getInstance()->send(sid, msgout); return; } */ uint totalNbUsers; CFES* best = findBestFES( totalNbUsers ); // could not find a good FES or best FES has more players than balance limit if (best == NULL || best->getUsersCountHeuristic() >= OpenFrontEndThreshold) { // open a new frontend openNewFES(); // reselect best FES (will return newly open FES, or previous if no more FES available) best = findBestFES(totalNbUsers); // check there is a FES available if (best == NULL) { // answer the LS that we can't accept the user return "No front-end server available"; } } bool authorizeUser = false; bool forceAuthorize = false; if (userPriv == ":DEV:") { // devs have all privileges authorizeUser = true; forceAuthorize = true; } else if (ShardOpen != ClosedForAll) { const std::string& allowedGroups = OpenGroups; bool userInOpenGroups = (!userPriv.empty() && !allowedGroups.empty() && allowedGroups.find(userPriv) != std::string::npos); // open for all or user is privileged authorizeUser = (ShardOpen == OpenForAll || userInOpenGroups); // let authorized users to force access even if limit is reached forceAuthorize = userInOpenGroups; } bool shardLimitReached = ( (PlayerLimit.get() != -1) && (totalNbUsers >= (uint)PlayerLimit.get()) ); if (!forceAuthorize && (!authorizeUser || shardLimitReached)) { // answer the LS that we can't accept the user CMessage msgout ("SCS"); string reason; if (shardLimitReached) return "The shard is currently full, please try again in 5 minutes."; else return "The shard is closed."; } CMessage msgout ("CS"); msgout.serial (const_cast<CLoginCookie&>(cookie)); msgout.serial (const_cast<string&>(userName), const_cast<string&>(userPriv), const_cast<string&>(userExtended)); msgout.serial (instanceId); msgout.serial (charSlot); CUnifiedNetwork::getInstance()->send (best->SId, msgout); best->NbPendingUsers++; // Update counts uint32 totalNbOnlineUsers = 0, totalNbPendingUsers = 0; for (list<CFES>::iterator it=FESList.begin(); it!=FESList.end(); ++it) { totalNbOnlineUsers += (*it).NbUser; totalNbPendingUsers += (*it).NbPendingUsers; } if (CWelcomeServiceMod::isInitialized()) CWelcomeServiceMod::getInstance()->updateConnectedPlayerCount(totalNbOnlineUsers, totalNbPendingUsers); return ""; }
/* * Update the source state with an extraction (see doc in .h). */ void CHarvestSource::extractMaterial( float *reqPosProps, float *absPosProps, float qualityCeilingFactor, float qualitySlowFactor, float *results, float successFactor, uint8 lifeAbsorberRatio, const TDataSetRow& extractingEntityRow, CHarvestSource::TRealTimeProp& propDrop ) { H_AUTO(CHarvestSource_extractMaterial); CCharacter* player = PlayerManager.getChar( extractingEntityRow ); ++_NbExtractions; // it's 1 at the first call, so that the initial value is used float nbe = (float)_NbExtractions; if ( (successFactor < 0.1f) || ForceDropProp ) { if ( _NbExtractions < 6 ) propDrop = Q; // don't drop A at the beginning (wait to reach 1 (cumulated) would be better) else propDrop = (TRealTimeProp)(RandomGenerator.rand(1)+1); nldebug( "Prop drop %u", propDrop ); } // Aperture: converges towards the requested value, except when a drop occurs (0 at this step) // if ( reqPosProps[A] > 0 ) { float obtainedQuantity = (propDrop == A) ? 0.0f : (results[A]*ForageQuantitySlowFactor.get() + reqPosProps[A]) / (ForageQuantitySlowFactor.get()+1); // Apply possible aperture bonus if ( _BonusForAPct != 0 ) { obtainedQuantity += obtainedQuantity * (float)((uint)_BonusForAPct) * 0.01f; } // Extract material if ( _ForageSite ) obtainedQuantity = _ForageSite->consume( obtainedQuantity ); // consume (and limit) in forage site & deposit if ( obtainedQuantity > _N ) // should not occur because _N uses the deposit quantity obtainedQuantity = _N; _N -= obtainedQuantity; _A = (_A*nbe + obtainedQuantity) / (nbe + 1.0f); // average per source _DepositForK->incKamiAnger( obtainedQuantity, _Foragers ); if ( (obtainedQuantity == 0) && (results[A] != 0) && (! (propDrop == A)) ) PHRASE_UTILITIES::sendDynamicSystemMessage( _Foragers[0], "FORAGE_DEPOSIT_IS_EMPTY" ); results[A] = obtainedQuantity; // add spire effect ( quantity ) if ( player ) { const CSEffect* pEffect = player->lookForActiveEffect( EFFECT_FAMILIES::TotemHarvestQty ); if ( pEffect != NULL ) { results[A] *= ( 1.0f + pEffect->getParamValue() / 100.0f ); } } // add item special effect if ( player ) { std::vector<SItemSpecialEffect> effects = player->lookForSpecialItemEffects(ITEM_SPECIAL_EFFECT::ISE_FORAGE_ADD_RM); std::vector<SItemSpecialEffect>::const_iterator it, itEnd; double addedQty = 0.; for (it=effects.begin(), itEnd=effects.end(); it!=itEnd; ++it) { float rnd = RandomGenerator.frand(); if (rnd<it->EffectArgFloat[0]) { addedQty += it->EffectArgFloat[1]; PHRASE_UTILITIES::sendItemSpecialEffectProcMessage(ITEM_SPECIAL_EFFECT::ISE_FORAGE_ADD_RM, player, NULL, (sint32)(it->EffectArgFloat[1]*100.)); } } results[A] *= 1.0f + (float)addedQty; } } // else // { // results[A] = 0; // } // Speed: always the requested speed (otherwise, looks like a bug for the player when it's the speed of the action) results[S] = reqPosProps[S]; _S = (_S*nbe + results[S]) / (nbe + 1.0f); // average per source // Quality: converges towards the requested value, except when a drop occurs (0 at this step) float usedReqQ = (propDrop == Q) ? 0.0f : reqPosProps[Q] * qualityCeilingFactor; float resQ = (results[Q]*qualitySlowFactor + usedReqQ) / (qualitySlowFactor+1); float maxQOfSource = (float)_MaxQuality; if ( resQ > maxQOfSource ) { resQ = maxQOfSource; //if ( results[Q] < (float)_MaxQuality ) // nldebug( "Quality limited by source to %hu", _MaxQuality ); // TODO: tell the player(s) } if ( (resQ < _Q) || (resQ < reqPosProps[Q]) || (! ForageQualityCeilingClamp.get()) ) { // Set Q only if not increasing and exceeding requested quality results[Q] = resQ; } else { // Clamp Q to the max required by the player results[Q] = reqPosProps[Q]; } float prevQ = _Q; _Q = results[Q]; // now there is only one extractor => the Q of the source is the resulting Q if ( ((prevQ < reqPosProps[Q]) && (_Q == reqPosProps[Q])) || ((prevQ < maxQOfSource) && (_Q == maxQOfSource)) ) { setNewImpactScheme(); // we just reached the max quality } // Calc impact of the new average values // Previously, the impact depended on the level of the extraction: // float quantityBaseImpact = _A * _S * ForageQuantityImpactFactor.get(); // float qualityBaseImpact = (_Q - oldQ) * ForageQualityImpactFactor.get(); // // Now it's constant (=max), but the amount of damage depends on the level of the extraction: float quantityBaseImpact = MaxAS * ForageQuantityImpactFactor.get(); float qualityBaseImpact = MaxDeltaQ * ForageQualityImpactFactor.get(); uint impactScheme = _IImpactMappingScheme; if ( impactScheme >= SpecialNewbieImpactSchemeD) { // Lower impacts for newbies impactScheme -= SpecialNewbieImpactSchemeD; quantityBaseImpact *= 0.5f; qualityBaseImpact *= 0.5f; } if ( ForceAbsorption.get() != 0 ) { absPosProps[A] = ForceAbsorption.get(); absPosProps[Q] = ForceAbsorption.get(); absPosProps[S] = ForceAbsorption.get(); } for ( uint i=D; i!=NbRTProps; ++i ) { if (i==E && _SafeSource) break; uint impactType = ImpactSchemes[impactScheme][i-NbPosRTProps]; float impact; switch ( impactType ) { case 0 : impact = quantityBaseImpact * (1.0f - absPosProps[A]); break; case 1 : impact = qualityBaseImpact * (1.0f - absPosProps[Q]); break; default: impact = (quantityBaseImpact + qualityBaseImpact) / 2.0f * (1.0f - absPosProps[S]); break; // bound on the average of both, absorption of S } impact += RandomGenerator.frandPlusMinus( impact ); // result impact from 0 to impact*2 // add spire effect ( aggressivity ) if ( player ) { const CSEffect* pEffect = player->lookForActiveEffect( EFFECT_FAMILIES::TotemHarvestAgg ); if ( pEffect != NULL ) { impact *= ( 1.0f - pEffect->getParamValue() / 100.0f ); } } if ( impact < 0 ) impact = 0; // impact can't be negative if ( (i==D) && (lifeAbsorberRatio != 0) ) { // Damage the life absorber, instead of impacting D CEntityBase *entity = CEntityBaseManager::getEntityBasePtr( extractingEntityRow ); // getEntityBasePtr() tests TheDataset.isAccessible( extractingEntity ) if ( entity ) { float impactOnHP = ((float)lifeAbsorberRatio) * impact * 0.01f; impact -= impactOnHP; float dmgRatio = impactOnHP * ForageHPRatioPerSourceLifeImpact.get(); sint32 dmg = (sint32)((float)entity->maxHp() * dmgRatio); if ( dmg != 0 ) CHarvestSource::hitEntity( RYZOMID::forageSource, entity, dmg, dmg, true ); } } if ( (_TargetRTProps[i-D] < CommonRiskThreshold*0.90f) && (_TargetRTProps[i-D] + impact > CommonRiskThreshold) ) { // Avoid a brutal unnatural end, make a step just before reaching threshold impactRTProp( (TTargetRTProp)(i-D), CommonRiskThreshold - 2.0f ); } else { // Normal impact impactRTProp( (TTargetRTProp)(i-D), _TargetRTProps[i-D] + impact ); } } }
//---------------------------------------------------------------------------- void COutpostManager::loadOutpostPrimitives() { if (!LoadOutposts.get()) return; // only once if (_OutpostPrimitivesLoaded) return; const CPrimitivesParser::TPrimitivesList & primsList = CPrimitivesParser::getInstance().getPrimitives(); string value; CPrimitivesParser::TPrimitivesList::const_iterator first, last; OUTPOST_DBG("Loading squad templates..."); // *** Squad templates *** // get the primitive list and parse each primitive for ( first = primsList.begin(), last = primsList.end(); first != last; ++first ) { // get the squad_template nodes for ( uint i = 0; i < first->Primitive.RootNode->getNumChildren(); ++i ) { const NLLIGO::IPrimitive* stNode = NULL; if ( first->Primitive.RootNode->getChild( stNode, i ) && stNode != NULL ) { const char *parentClass = "squad_template"; if (stNode->getPropertyByName("class",value) && !nlstricmp(value.c_str(),parentClass) ) { string path = first->FileName; CSquadTemplate squadTemplate; squadTemplate.SquadName = readProperty( stNode, "name", parentClass, path, false, true ); // get the squad_template variants for ( uint j = 0; j < stNode->getNumChildren(); ++j ) { const NLLIGO::IPrimitive* stvNode = NULL; if ( stNode->getChild( stvNode, j ) && stvNode != NULL ) { parentClass = "squad_template_variant"; if (stvNode->getPropertyByName("class",value) && !nlstricmp(value.c_str(),parentClass) ) { path = first->FileName+"."+squadTemplate.SquadName; CSquadTemplate::CSquadTemplateVariant variant; // alias variant.Alias = 0; nlverify( CPrimitivesParser::getAlias(stvNode, variant.Alias) ); // 'name' -> continent or tribe name variant.VariantName = readProperty( stvNode, "name", parentClass, path, false, true ); path += "."+variant.VariantName; // 'is tribe' value = readProperty( stvNode, "is tribe", parentClass, path, true, false, true ); variant.IsTribe = (value == "true"); // 'squad sheet' value = readProperty( stvNode, "squad sheet", parentClass, path ); if ( value.find( ".outpost_squad" ) == string::npos ) value += ".outpost_squad"; variant.SquadSheet = CSheetId(value); if ( variant.SquadSheet == CSheetId::Unknown ) OUTPOST_WRN("PRIM_ERROR : invalid squad sheet '%s' (not in sheet_id.bin) in '%s'", value.c_str(), path.c_str() ); //if ( ! CSheets::getOutpostSquadForm( variant.SquadSheet ) ) // already done when loading outpost // OUTPOST_WRN("PRIM_ERROR : invalid squad sheet '%s' (error in georges form) in %s", value.c_str(), path.c_str() ); // squad members are handled by the AIS if ( stvNode->getNumChildren() == 0 ) OUTPOST_WRN("PRIM_ERROR : '%s' in '%s' has no members", parentClass, path.c_str() ); squadTemplate.Variants.push_back( variant ); } } } { std::string str; str += "Adding Squad template '" + squadTemplate.SquadName + "' ("; std::vector<CSquadTemplate::CSquadTemplateVariant>::const_iterator it, itEnd; it=squadTemplate.Variants.begin(), itEnd=squadTemplate.Variants.end(); if (it!=itEnd) str += it->VariantName; for (++it ; it!=itEnd; ++it) str += ", " + it->VariantName; str += ")"; OUTPOST_DBG("%s", str.c_str()); } addSquadTemplate( squadTemplate ); } } } } OUTPOST_DBG("Squad templates loaded."); OUTPOST_DBG("Loading outposts..."); // *** Outposts (must be done after squad templates) *** // get the primitive list and parse each primitive for ( first = primsList.begin(), last = primsList.end(); first != last; ++first ) { // get the dynamic_system nodes for ( uint i = 0; i < first->Primitive.RootNode->getNumChildren(); ++i ) { const NLLIGO::IPrimitive* dynSystemNode = NULL; if ( first->Primitive.RootNode->getChild( dynSystemNode,i ) && dynSystemNode != NULL ) { if (dynSystemNode->getPropertyByName("class",value) && !nlstricmp(value.c_str(),"dynamic_system") ) { // get the continent, as outpost need a continent to be built. We get this value from the dynamic system node string dynSystemName; nlverify( dynSystemNode->getPropertyByName("name",dynSystemName) ); nlverify( dynSystemNode->getPropertyByName("continent_name",value) ); CONTINENT::TContinent continent = CONTINENT::toContinent( value ); if ( continent == CONTINENT::UNKNOWN ) { OUTPOST_WRN("Invalid continent '%s' in dynamic system '%s' of primitive file '%s'", value.c_str(), dynSystemName.c_str(), first->FileName.c_str() ); break; } // parse all the outpost within this dynamic system. for ( uint j = 0; j < dynSystemNode->getNumChildren(); ++j ) { const NLLIGO::IPrimitive* outpostNode = NULL; if ( dynSystemNode->getChild( outpostNode,j ) && outpostNode != NULL ) { if (outpostNode->getPropertyByName("class",value) && !nlstricmp(value.c_str(),"outpost") ) { CSmartPtr<COutpost> outpost = CSmartPtr<COutpost>(new COutpost()); if ( outpost->build( outpostNode, first->FileName,dynSystemName, continent ) ) { bool multiple = false; for (vector<NLMISC::CSmartPtr<COutpost> >::const_iterator it = _Outposts.begin(); it != _Outposts.end(); ++it) { if ( (*it)->getAlias() == outpost->getAlias() ) { OUTPOST_WRN( "PRIM_ERROR : multiple outpost alias %s %s %s", CPrimitivesParser::aliasToString( outpost->getAlias() ).c_str(), (*it)->getName().c_str(), outpost->getName().c_str() ); multiple = true; } if ( (*it)->getSheet() == outpost->getSheet() ) { OUTPOST_WRN( "PRIM_ERROR : multiple outpost sheet %s %s %s", outpost->getSheet().toString().c_str(), (*it)->getName().c_str(), outpost->getName().c_str() ); multiple = true; } } if( !multiple ) { _Outposts.push_back(outpost); _OutpostsByAlias.insert( make_pair( outpost->getAlias(), outpost ) ); _OutpostsBySheet.insert( make_pair( outpost->getSheet(), outpost ) ); OUTPOST_INF("Outpost '%s' was successfully parsed", outpost->getName().c_str()); // nb : short id starts at 1, 0 is used for invalid _OutpostAliasToShortId.insert( make_pair( outpost->getAlias(), (uint16)_Outposts.size()) ); } } } } } } } } } OUTPOST_DBG("Outposts loaded."); OUTPOST_DBG("Clearing squad templates..."); // No more need of squad templates _SquadTemplates.clear(); OUTPOST_DBG("Squad templates cleared."); // outpost primitives now are loaded _OutpostPrimitivesLoaded = true; }