CSector::CSector() : CTimedObject(PROFILE_SECTORS) { m_ListenItems = 0; m_RainChance = 0; // 0 to 100% m_ColdChance = 0; // Will be snow if rain chance success. SetDefaultWeatherChance(); m_dwFlags = 0; m_fSaveParity = false; GoSleep(); // Every sector is sleeping at start, they only awake when any player enter (this eases the load at startup). }
static msg_t AppThread(void *arg) { (void)arg; chRegSetThreadName("App"); #ifdef TRAIN_MODE uint32_t counter; #else int16_t bestResult; int16_t result = 0; uint32_t tmpCode = 0; uint32_t newCode = 0; Status_t tmpStatus = stIdle; uint32_t SignCodeNumb = 999999; int32_t SignTimeoutCounter = 0; #endif while(1) { chThdSleepMilliseconds(9); if(!App.Enabled) continue; // Do nothing // ==== Read accelerations ==== bool AllOperational = true; for(uint8_t i = 0; i < ACC_CNT; i++) { Acc[i].ReadAccelerations(); if(Acc[i].IsOperational) { // Uart.Printf("%u %d %d %d; ", i, Acc[i].a[0], Acc[i].a[1], Acc[i].a[2]); // Copy accelerations to vector. Also, filter is applied here, and acceleration change is checked. Process.AddAcc(i, &Acc[i].a[0]); #ifndef TRAIN_MODE // Prepare to compare bestResult = 9999; newCode = SignCodeNumb; // *** Iterate all subsigns *** chSysLock();// Do not switch to other thread for(uint8_t j = 0; j < SUBSIGN_CNT; j++) { // Check if similar result = Process.IsSimilar(Subsign[j], hyperRadius[j]); if(result > -1) { // Seems like similar tmpCode = (SignCodeNumb * 100) % 1000000 + j; tmpStatus = Analyze(tmpCode); if((tmpStatus != stIdle) and (result < bestResult)) { newCode = tmpCode; App.Status = tmpStatus; bestResult = result; Process.CurrentSubsign = j; SignTimeoutCounter = INITIAL_COUNTDOWN; // Reset timeout counter Uart.Printf("%d\r\n", j); } // if } // if result > -1 } // for chSysUnlock(); SignCodeNumb = newCode; #endif } // if operational else { Uart.Printf("Acc %u fail\r", i); // Try to rise from dead Acc[i].Init(); if(!Acc[i].IsOperational) { AllOperational = false; chThdSleepMilliseconds(450); } } } // for i // Handle status depending on accelerometers state if(!AllOperational) App.Status = stAccFail; else if(App.Status == stAccFail) App.Status = stIdle; // All operational if(App.Status != stAccFail) { // Signal that 'first after power-on' measurement completed FirstTime = false; // ==== Check if time to sleep ==== SleepTimeoutCounter--; if(SleepTimeoutCounter < 0) { SleepTimeoutCounter = 0; // Uart.Printf("Zzz\r"); #if defined SLEEP_ENABLED && !defined TRAIN_MODE GoSleep(); #endif } #ifndef TRAIN_MODE // ==== Check if sign timed out ==== SignTimeoutCounter--; if(SignTimeoutCounter < 0) { SignTimeoutCounter = 0; App.Status = stIdle; // Reset indication SignCodeNumb = (SignCodeNumb * 100) % 1000000 + 99; } #endif } // if not failure #ifdef TRAIN_MODE counter++; if(counter >= 10) { counter=0; // Process.PrintVect(); for(uint8_t i = 0; i < 21; i++) Uart.Printf("%d,", Process.AccVector[i]); Uart.Printf("\r\n"); } #endif } // while 1 return 0; }
bool CSector::r_Verb( CScript & s, CTextConsole * pSrc ) { ADDTOCALLSTACK("CSector::r_Verb"); EXC_TRY("Verb"); ASSERT(pSrc); int index = FindTableSorted( s.GetKey(), sm_szVerbKeys, CountOf(sm_szVerbKeys)-1 ); switch (index) { case SEV_ALLCHARS: // "ALLCHARS" v_AllChars( s, pSrc ); break; case SEV_ALLCHARSIDLE: // "ALLCHARSIDLE" v_AllCharsIdle( s, pSrc ); break; case SEV_ALLCLIENTS: // "ALLCLIENTS" v_AllClients( s, pSrc ); break; case SEV_ALLITEMS: // "ALLITEMS" v_AllItems( s, pSrc ); break; case SEV_AWAKE: if (!IsSleeping()) { break; } GoAwake(); break; case SEV_DRY: // "DRY" SetWeather( WEATHER_DRY ); break; case SEV_LIGHT: if ( g_Cfg.m_bAllowLightOverride ) SetLight( (s.HasArgs()) ? s.GetArgVal() : -1 ); else g_Log.EventWarn("AllowLightOverride flag is disabled in sphere.ini, so sector's LIGHT property wasn't set\n"); break; case SEV_RAIN: SetWeather(s.HasArgs() ? static_cast<WEATHER_TYPE>(s.GetArgVal()) : WEATHER_RAIN); break; case SEV_RESPAWN: ( toupper( s.GetArgRaw()[0] ) == 'A' ) ? g_World.RespawnDeadNPCs() : RespawnDeadNPCs(); break; case SEV_RESTOCK: // x // set restock time of all vendors in World, set the respawn time of all spawns in World. ( toupper( s.GetArgRaw()[0] ) == 'A' ) ? g_World.Restock() : Restock(); break; case SEV_SEASON: SetSeason(static_cast<SEASON_TYPE>(s.GetArgVal())); break; case SEV_SLEEP: { if (IsSleeping()) { break; } if (!s.HasArgs())// with no args it will check if it can sleep before, to avoid possible problems. { if (!CanSleep(true)) { break; } } GoSleep(); } break; case SEV_SNOW: SetWeather( WEATHER_SNOW ); break; default: return( CScriptObj::r_Verb( s, pSrc )); } return true; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPTSRC; EXC_DEBUG_END; return false; }
bool CSector::OnTick() { ADDTOCALLSTACK("CSector::OnTick"); /*Ticking sectors from CWorld * Timer is automatically updated at the end with a 30 seconds default delay * Any return before it will threat this CSector as Sleep and will make it * not tick again until a new player enters (WARNING: even if there are * players already inside). */ EXC_TRY("Tick"); // do not tick sectors on maps not supported by server if ( !g_MapList.m_maps[m_map] ) return true; EXC_SET_BLOCK("light change"); // Check for light change before putting the sector to sleep, since in other case the // world light levels will be shitty bool fEnvironChange = false; bool fLightChange = false; // check for local light level change ? byte bLightPrv = m_Env.m_Light; m_Env.m_Light = GetLightCalc( false ); if ( m_Env.m_Light != bLightPrv ) { fEnvironChange = true; fLightChange = true; } EXC_SET_BLOCK("sector sleeping?"); bool fCanSleep = CanSleep(true); int64 iCurTime = CServerTime::GetCurrentTime().GetTimeRaw(); // Put the sector to sleep if no clients been here in a while. if (fCanSleep && (g_Cfg._iSectorSleepDelay > 0)) { if (!IsSleeping()) { GoSleep(); } return true; } EXC_SET_BLOCK("sound effects"); // random weather noises and effects. SOUND_TYPE sound = 0; bool fWeatherChange = false; int iRegionPeriodic = 0; WEATHER_TYPE weatherprv = m_Env.m_Weather; if ( ! Calc_GetRandVal( 30 )) // change less often { m_Env.m_Weather = GetWeatherCalc(); if ( weatherprv != m_Env.m_Weather ) { fWeatherChange = true; fEnvironChange = true; } } // Random area noises. Only do if clients about. if ( GetClientsNumber() > 0 ) { iRegionPeriodic = 2; static const SOUND_TYPE sm_SfxRain[] = { 0x10, 0x11 }; static const SOUND_TYPE sm_SfxWind[] = { 0x14, 0x15, 0x16 }; static const SOUND_TYPE sm_SfxThunder[] = { 0x28, 0x29 , 0x206 }; // Lightning ? // wind, rain, switch ( GetWeather() ) { case WEATHER_CLOUDY: break; case WEATHER_SNOW: if ( ! Calc_GetRandVal(5) ) sound = sm_SfxWind[ Calc_GetRandVal( CountOf( sm_SfxWind )) ]; break; case WEATHER_RAIN: { int iVal = Calc_GetRandVal(30); if ( iVal < 5 ) { // Mess up the light levels for a sec.. LightFlash(); sound = sm_SfxThunder[ Calc_GetRandVal( CountOf( sm_SfxThunder )) ]; } else if ( iVal < 10 ) sound = sm_SfxRain[ Calc_GetRandVal( CountOf( sm_SfxRain )) ]; else if ( iVal < 15 ) sound = sm_SfxWind[ Calc_GetRandVal( CountOf( sm_SfxWind )) ]; } break; default: break; } } // Check environ changes and inform clients of it. ProfileTask charactersTask(PROFILE_CHARS); CChar * pCharNext = nullptr; CChar * pChar = static_cast <CChar*>( m_Chars_Active.GetHead()); for ( ; pChar != nullptr; pChar = pCharNext ) { EXC_TRYSUB("TickChar"); pCharNext = pChar->GetNext(); if (( fEnvironChange ) && ( IsTrigUsed(TRIGGER_ENVIRONCHANGE) )) pChar->OnTrigger(CTRIG_EnvironChange, pChar); if ( pChar->IsClient()) { CClient * pClient = pChar->GetClient(); ASSERT( pClient ); if ( sound ) pClient->addSound(sound, pChar); if ( fLightChange && ! pChar->IsStatFlag( STATF_DEAD | STATF_NIGHTSIGHT )) pClient->addLight(); if ( fWeatherChange ) pClient->addWeather(GetWeather()); if ( iRegionPeriodic && pChar->m_pArea ) { if ( ( iRegionPeriodic == 2 ) && IsTrigUsed(TRIGGER_REGPERIODIC)) { pChar->m_pArea->OnRegionTrigger( pChar, RTRIG_REGPERIODIC ); --iRegionPeriodic; } if ( IsTrigUsed(TRIGGER_CLIPERIODIC) ) pChar->m_pArea->OnRegionTrigger( pChar, RTRIG_CLIPERIODIC ); } } EXC_CATCHSUB("Sector"); EXC_DEBUGSUB_START; CPointMap pt = GetBasePoint(); g_Log.EventDebug("#0 char 0%x '%s'\n", (dword)(pChar->GetUID()), pChar->GetName()); g_Log.EventDebug("#0 sector #%d [%d,%d,%d,%d]\n", GetIndex(), pt.m_x, pt.m_y, pt.m_z, pt.m_map); EXC_DEBUGSUB_END; } ProfileTask overheadTask(PROFILE_OVERHEAD); EXC_SET_BLOCK("check map cache"); if (fCanSleep && m_iMapBlockCacheTime < iCurTime) // Only if the sector can sleep. { // delete the static CServerMapBlock items that have not been used recently. m_iMapBlockCacheTime = CServerTime::GetCurrentTime().GetTimeRaw() + g_Cfg.m_iMapCacheTime ; CheckMapBlockCache(); } EXC_CATCH; SetTimeoutS(30); // Sector is Awake, make it tick after 30 seconds. EXC_DEBUG_START; CPointMap pt = GetBasePoint(); g_Log.EventError("#4 sector #%d [%hd,%hd,%hhd,%hhu]\n", GetIndex(), pt.m_x, pt.m_y, pt.m_z, pt.m_map); EXC_DEBUG_END; return true; }