bool CSector::v_AllClients( CScript & s, CTextConsole * pSrc ) { ADDTOCALLSTACK("CSector::v_AllClients"); CScript script(s.GetArgStr()); CChar * pChar = NULL; bool fRet = false; // Loop through all the characters in m_Chars_Active. // We should start at the end incase some are removed during the loop. size_t i = m_Chars_Active.GetCount(); while ( i > 0 ) { pChar = STATIC_CAST <CChar*>(m_Chars_Active.GetAt(--i)); // Check that a character was returned and keep looking if not. if (pChar == NULL) continue; // Check that the character is a client (we only want to affect // clients with this) if ( ! pChar->IsClient()) continue; // Execute the verb on the client fRet |= pChar->r_Verb(script, pSrc); } return fRet; }
void CSector::SetLightNow( bool fFlash ) { ADDTOCALLSTACK("CSector::SetLightNow"); // Set the light level for all the CClients here. CChar * pChar = STATIC_CAST <CChar*>( m_Chars_Active.GetHead()); for ( ; pChar != NULL; pChar = pChar->GetNext()) { if ( pChar->IsStatFlag( STATF_DEAD | STATF_NightSight )) continue; if ( pChar->IsClient()) { CClient * pClient = pChar->GetClient(); ASSERT(pClient); if ( fFlash ) // This does not seem to work predicably ! { BYTE bPrvLight = m_Env.m_Light; m_Env.m_Light = LIGHT_BRIGHT; // full bright. pClient->addLight(); m_Env.m_Light = bPrvLight; // back to previous. } pClient->addLight(); } // don't fire trigger when server is loading or light is flashing if (( ! g_Serv.IsLoading() && fFlash == false ) && ( IsTrigUsed(TRIGGER_ENVIRONCHANGE) )) { pChar->OnTrigger( CTRIG_EnvironChange, pChar ); } } }
bool CSector::v_AllClients( CScript & s, CTextConsole * pSrc ) { ADDTOCALLSTACK("CSector::v_AllClients"); CScript script(s.GetArgStr()); script.m_iResourceFileIndex = s.m_iResourceFileIndex; // Index in g_Cfg.m_ResourceFiles of the CResourceScript (script file) where the CScript originated script.m_iLineNum = s.m_iLineNum; // Line in the script file where Key/Arg were read CChar * pChar = nullptr; bool fRet = false; // Loop through all the characters in m_Chars_Active. // We should start at the end incase some are removed during the loop. size_t i = m_Chars_Active.GetCount(); while ( i > 0 ) { pChar = static_cast <CChar*>(m_Chars_Active.GetAt(--i)); // Check that a character was returned and keep looking if not. if (pChar == nullptr) continue; // Check that the character is a client (we only want to affect clients with this) if ( ! pChar->IsClient()) continue; // Execute the verb on the client fRet |= pChar->r_Verb(script, pSrc); } return fRet; }
int CItemMulti::Ship_ListObjs( CObjBase ** ppObjList ) { // List all the objects in the structure. // Move the ship and everything on the deck // If too much stuff. then some will fall overboard. hehe. if ( ! IsTopLevel()) return 0; int iMaxDist = Multi_GetMaxDist(); // always list myself first. All other items must see my new region ! int iCount = 0; ppObjList[iCount++] = this; CWorldSearch AreaChar( GetTopPoint(), iMaxDist ); while ( iCount < MAX_MULTI_LIST_OBJS ) { CChar * pChar = AreaChar.GetChar(); if ( pChar == NULL ) break; if ( pChar->IsClient()) { pChar->GetClient()->addPause(); // get rid of flicker. for anyone even seeing this. } if ( ! m_pRegion->IsInside2d( pChar->GetTopPoint())) continue; int zdiff = pChar->GetTopZ() - GetTopZ(); if ( abs( zdiff ) > 3 ) continue; ppObjList[iCount++] = pChar; } CWorldSearch AreaItem( GetTopPoint(), iMaxDist ); while ( iCount < MAX_MULTI_LIST_OBJS ) { CItem * pItem = AreaItem.GetItem(); if ( pItem == NULL ) break; if ( pItem == this ) // already listed. continue; if ( ! Multi_IsPartOf( pItem )) { if ( ! m_pRegion->IsInside2d( pItem->GetTopPoint())) continue; if ( ! pItem->IsMovable()) continue; int zdiff = pItem->GetTopZ() - GetTopZ(); if ( abs( zdiff ) > 3 ) continue; } ppObjList[iCount++] = pItem; } return( iCount ); }
bool CClient::r_GetRef( LPCTSTR & pszKey, CScriptObj * & pRef ) { ADDTOCALLSTACK("CClient::r_GetRef"); int i = FindTableHeadSorted( pszKey, sm_szRefKeys, COUNTOF(sm_szRefKeys)-1 ); if ( i >= 0 ) { pszKey += strlen( sm_szRefKeys[i] ); SKIP_SEPARATORS(pszKey); switch (i) { case CLIR_ACCOUNT: if ( pszKey[-1] != '.' ) // only used as a ref ! break; pRef = GetAccount(); return( true ); case CLIR_GMPAGEP: pRef = m_pGMPage; return( true ); case CLIR_HOUSEDESIGN: pRef = m_pHouseDesign; return( true ); case CLIR_PARTY: if ( !this->m_pChar->m_pParty ) { LPCTSTR oldKey = pszKey; if ( !strnicmp(pszKey, ".CREATE", 7) ) pszKey +=7; CChar * pChar = static_cast<CChar*>(static_cast<CGrayUID>(Exp_GetSingle(pszKey)).CharFind()); if ( !pChar ) return false; if ( !pChar->IsClient() ) return false; CPartyDef::AcceptEvent( pChar , this->GetChar()->GetUID(), true); if ( !this->m_pChar->m_pParty ) return false; pszKey = oldKey; // Restoring back to real pszKey, so we don't get errors for giving an uid instead of PDV_CREATE. } pRef = this->m_pChar->m_pParty; return true; case CLIR_TARG: pRef = m_Targ_UID.ObjFind(); return( true ); case CLIR_TARGPRV: pRef = m_Targ_PrvUID.ObjFind(); return( true ); case CLIR_TARGPROP: pRef = m_Prop_UID.ObjFind(); return( true ); } } return( CScriptObj::r_GetRef( pszKey, pRef )); }
// --------------------------------------------------------- void CPartyDef::AddStatsUpdate( CChar * pChar, PacketSend * pPacket ) { ADDTOCALLSTACK("CPartyDef::AddStatsUpdate"); size_t iQty = m_Chars.GetCharCount(); if ( iQty <= 0 ) return; for ( size_t i = 0; i < iQty; i++ ) { CChar * pCharNow = m_Chars.GetChar(i).CharFind(); if ( pCharNow && pCharNow != pChar ) { if ( pCharNow->CanSee( pChar ) && pCharNow->IsClient() ) pPacket->send(pCharNow->GetClient()); } } }
void CItemContainer::Trade_Delete() { ADDTOCALLSTACK("CItemContainer::Trade_Delete"); // Called when object deleted. ASSERT( IsType(IT_EQ_TRADE_WINDOW) ); CChar * pChar = dynamic_cast <CChar*> (GetParent()); if ( pChar == NULL ) return; if ( pChar->IsClient()) { // Send the cancel trade message. PacketTradeAction cmd(SECURE_TRADE_CLOSE); cmd.prepareClose(this); cmd.send(pChar->GetClient()); } // Drop items back in my pack. CItem * pItemNext; for ( CItem* pItem = GetContentHead(); pItem!=NULL; pItem=pItemNext) { pItemNext = pItem->GetNext(); pChar->ItemBounce( pItem ); } // Kill my trading partner. CItemContainer * pPartner = dynamic_cast <CItemContainer *> ( m_uidLink.ItemFind()); if ( pPartner == NULL ) return; if ( IsTrigUsed(TRIGGER_TRADECLOSE) ) { CChar * pChar2 = dynamic_cast <CChar*> (pPartner->GetParent()); CScriptTriggerArgs Args( pChar2 ); pChar->OnTrigger( CTRIG_TradeClose, pChar , &Args ); CScriptTriggerArgs Args2( pChar ); pChar2->OnTrigger( CTRIG_TradeClose, pChar, &Args2); } m_uidLink.InitUID(); // unlink. pPartner->m_uidLink.InitUID(); pPartner->Delete(); }
void CSector::SetSeason( SEASON_TYPE season ) { ADDTOCALLSTACK("CSector::SetSeason"); // Set the season type. if ( season == m_Env.m_Season ) return; m_Env.m_Season = season; CChar * pChar = STATIC_CAST <CChar*>( m_Chars_Active.GetHead()); for ( ; pChar != NULL; pChar = pChar->GetNext()) { if ( pChar->IsClient() ) pChar->GetClient()->addSeason(season); if ( IsTrigUsed(TRIGGER_ENVIRONCHANGE) ) pChar->OnTrigger(CTRIG_EnvironChange, pChar); } }
void CSector::SetWeather( WEATHER_TYPE w ) { ADDTOCALLSTACK("CSector::SetWeather"); // Set the immediate weather type. // 0=dry, 1=rain or 2=snow. if ( w == m_Env.m_Weather ) return; m_Env.m_Weather = w; CChar * pChar = STATIC_CAST <CChar*>( m_Chars_Active.GetHead()); for ( ; pChar != NULL; pChar = pChar->GetNext()) { if ( pChar->IsClient()) pChar->GetClient()->addWeather( w ); if ( IsTrigUsed(TRIGGER_ENVIRONCHANGE) ) pChar->OnTrigger( CTRIG_EnvironChange, pChar ); } }
void CItemStone::AnnounceWar( const CItemStone * pEnemyStone, bool fWeDeclare, bool fWar ) { ADDTOCALLSTACK("CItemStone::AnnounceWar"); // Announce we are at war or peace. ASSERT(pEnemyStone); bool fAtWar = IsAtWarWith(pEnemyStone); TCHAR *pszTemp = Str_GetTemp(); int len = sprintf( pszTemp, (fWar) ? "%s %s declared war on %s." : "%s %s requested peace with %s.", (fWeDeclare) ? "You" : pEnemyStone->GetName(), (fWeDeclare) ? "have" : "has", (fWeDeclare) ? pEnemyStone->GetName() : "You" ); if ( fAtWar ) { sprintf( pszTemp+len, " War is ON!" ); } else if ( fWar ) { sprintf( pszTemp+len, " War is NOT yet on." ); } else { sprintf( pszTemp+len, " War is OFF." ); } CStoneMember * pMember = STATIC_CAST <CStoneMember *>(GetHead()); for ( ; pMember != NULL; pMember = pMember->GetNext()) { CChar * pChar = pMember->GetLinkUID().CharFind(); if ( pChar == NULL ) continue; if ( ! pChar->IsClient()) continue; pChar->SysMessage( pszTemp ); } }
void CSector::OnTick(int iPulseCount) { ADDTOCALLSTACK_INTENSIVE("CSector::OnTick"); // CWorld gives OnTick() to all CSectors. EXC_TRY("Tick"); EXC_SET("light change"); // do not tick sectors on maps not supported by server if ( !g_MapList.m_maps[m_map] ) return; // 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; bool fSleeping = false; if ( ! ( iPulseCount & 0x7f )) // 30 seconds or so. { // 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("sector sleeping?"); size_t clients = m_Chars_Active.HasClients(); if ( clients <= 0 ) // having no clients inside { // Put the sector to sleep if no clients been here in a while. fSleeping = IsSectorSleeping(); if ( fSleeping ) { if ( !g_Cfg.m_iSectorSleepMask ) return; if (( iPulseCount & g_Cfg.m_iSectorSleepMask ) != ( GetIndex() & g_Cfg.m_iSectorSleepMask )) return; } } EXC_SET("sound effects"); // random weather noises and effects. SOUND_TYPE sound = 0; bool fWeatherChange = false; int iRegionPeriodic = 0; if ( ! ( iPulseCount & 0x7f )) // 30 seconds or so. { // Only do this every x minutes or so (TICK_PER_SEC) // check for local weather change ? 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 ( clients > 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; } } } // regen all creatures and do AI ProfileTask charactersTask(PROFILE_CHARS); //pChar = STATIC_CAST <CChar*>( m_Chars_Active.GetHead()); CChar * pCharNext = NULL; CChar * pChar = dynamic_cast <CChar*>( m_Chars_Active.GetHead()); for ( ; pChar != NULL; 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 ); } } // Can only die on your own tick. if ( !pChar->OnTick() ) pChar->Delete(); EXC_CATCHSUB("Sector"); EXC_DEBUGSUB_START; CPointMap pt = GetBasePoint(); g_Log.EventDebug("char 0%lx '%s'\n", static_cast<DWORD>(pChar->GetUID()), pChar->GetName()); g_Log.EventDebug("sector #%d [%d,%d,%d,%d]\n", GetIndex(), pt.m_x, pt.m_y, pt.m_z, pt.m_map); EXC_DEBUGSUB_END; } // decay items on ground = time out spells / gates etc.. etc.. // No need to check these so often ! ProfileTask itemsTask(PROFILE_ITEMS); CItem * pItemNext = NULL; CItem * pItem = dynamic_cast <CItem*>( m_Items_Timer.GetHead()); for ( ; pItem != NULL; pItem = pItemNext ) { EXC_TRYSUB("TickItem"); pItemNext = pItem->GetNext(); EXC_SETSUB("TimerExpired"); if ( pItem->IsTimerExpired() ) { EXC_SETSUB("ItemTick"); if ( !pItem->OnTick() ) { EXC_SETSUB("ItemDelete"); pItem->Delete(); } else { EXC_SETSUB("TimerExpired2"); if ( pItem->IsTimerExpired() ) // forgot to clear the timer.? strange. { EXC_SETSUB("SetTimeout"); pItem->SetTimeout(-1); } } } EXC_SETSUB("UpdateFlags"); pItem->OnTickStatusUpdate(); #ifdef _WIN32 EXC_CATCHSUB("Sector"); EXC_DEBUGSUB_START; CPointMap pt = GetBasePoint(); g_Log.EventError("item 0%lx '%s' [timer=%lld, type=%lld]\n", static_cast<DWORD>(pItem->GetUID()), pItem->GetName(), pItem->GetTimerAdjusted(), static_cast<int>(pItem->GetType())); g_Log.EventError("sector #%d [%d,%d,%d,%d]\n", GetIndex(), pt.m_x, pt.m_y, pt.m_z, pt.m_map); EXC_DEBUGSUB_END; #else } #ifndef _DEBUG catch ( const CGrayError& e )
bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const CPointMap &pt, LPCTSTR pszArgs ) { ADDTOCALLSTACK("CChar::NPC_OnHearPetCmdTarg"); // Pet commands that required a target. if ( m_fIgnoreNextPetCmd ) { m_fIgnoreNextPetCmd = false; return false; } switch ( iCmd ) { case PC_FOLLOW: case PC_STAY: case PC_STOP: { // Pet friends can use only these commands if ( Memory_FindObjTypes(pSrc, MEMORY_FRIEND) ) break; } default: { // All others commands are avaible only to pet owner if ( !NPC_IsOwnedBy(pSrc, true) ) return false; } } if ( IsStatFlag(STATF_DEAD) ) { // Bonded NPCs still placed on world even when dead. // They can listen to commands, but not to these commands below if ( iCmd == PC_GUARD || iCmd == PC_GUARD_ME || iCmd == PC_ATTACK || iCmd == PC_KILL || iCmd == PC_TRANSFER || iCmd == PC_DROP || iCmd == PC_DROP_ALL ) return true; } bool bSuccess = false; CItem *pItemTarg = dynamic_cast<CItem *>(pObj); CChar *pCharTarg = dynamic_cast<CChar *>(pObj); switch ( iCmd ) { case PC_ATTACK: case PC_KILL: { if ( !pCharTarg || pCharTarg == pSrc ) break; bSuccess = pCharTarg->OnAttackedBy(pSrc, 1, true); // we know who told them to do this. if ( bSuccess ) bSuccess = Fight_Attack(pCharTarg, true); break; } case PC_FOLLOW: if ( !pCharTarg ) break; m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; case PC_FRIEND: { if ( !pCharTarg || !pCharTarg->m_pPlayer || pCharTarg == pSrc ) { Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CONFUSED)); break; } CItemMemory *pMemory = Memory_FindObjTypes(pCharTarg, MEMORY_FRIEND); if ( pMemory ) { pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_ALREADY)); break; } pSrc->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUCCESS1), GetName(), pCharTarg->GetName()); pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUCCESS2), pSrc->GetName(), GetName()); Memory_AddObjTypes(pCharTarg, MEMORY_FRIEND); m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } case PC_UNFRIEND: { if ( !pCharTarg || !pCharTarg->m_pPlayer ) { Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CONFUSED)); break; } CItemMemory *pMemory = Memory_FindObjTypes(pCharTarg, MEMORY_FRIEND); if ( !pMemory ) { pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_NOTFRIEND)); break; } pSrc->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_SUCCESS1), GetName(), pCharTarg->GetName()); pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_SUCCESS2), pSrc->GetName(), GetName()); pMemory->Delete(); m_Act_Targ = pSrc->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } case PC_GO: if ( !pt.IsValidPoint() ) break; m_Act_p = pt; bSuccess = Skill_Start(NPCACT_GOTO); break; case PC_GUARD: if ( !pCharTarg ) break; pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GUARD_SUCCESS), GetName()); m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_GUARD_TARG); break; case PC_TRANSFER: if ( !pCharTarg || !pCharTarg->IsClient() ) break; if ( IsSetOF(OF_PetSlots) ) { if ( !pCharTarg->FollowersUpdate(this, static_cast<short>(maximum(1, GetDefNum("FOLLOWERSLOTS", true, true))), true) ) { pSrc->SysMessageDefault(DEFMSG_PETSLOTS_TRY_TRANSFER); break; } } bSuccess = NPC_PetSetOwner( pCharTarg ); break; case PC_PRICE: // "PRICE" the vendor item. if ( !pItemTarg || !NPC_IsVendor() || !pSrc->IsClient() ) break; if ( IsDigit(pszArgs[0]) ) // did they name a price return NPC_SetVendorPrice(pItemTarg, ATOI(pszArgs)); if ( !NPC_SetVendorPrice(pItemTarg, -1) ) // test if it can be priced return false; pSrc->m_pClient->addPromptConsole(CLIMODE_PROMPT_VENDOR_PRICE, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_SETPRICE_2), pItemTarg->GetUID(), GetUID()); return true; default: break; } // Make some sound to confirm we heard it NPC_OnPetCommand(bSuccess, pSrc); return bSuccess; }
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; }
TRIGRET_TYPE CScriptObj::OnTriggerForLoop( CScript &s, int iType, CTextConsole * pSrc, CScriptTriggerArgs * pArgs, CGString * pResult ) { // loop from start here to the ENDFOR // See WebPageScriptList for dealing with Arrays. CScriptLineContext StartContext = s.GetContext(); CScriptLineContext EndContext = StartContext; int LoopsMade = 0; if ( iType & 8 ) // WHILE { TCHAR * pszCond; TCHAR *pszOrig = Str_GetTemp(); TCHAR *pszTemp = Str_GetTemp(); int iWhile = 0; strcpy( pszOrig, s.GetArgStr() ); while(true) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; pArgs->m_VarsLocal.SetNum( "_WHILE", iWhile, false ); iWhile++; strcpy( pszTemp, pszOrig ); pszCond = pszTemp; ParseText( pszCond, pSrc, 0, pArgs ); if ( !Exp_GetVal( pszCond ) ) break; TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } else ParseText( s.GetArgStr(), pSrc, 0, pArgs ); if ( iType & 4 ) // FOR { int fCountDown = FALSE; int iMin = 0; int iMax = 0; int i; TCHAR * ppArgs[3]; int iQty = Str_ParseCmds( s.GetArgStr(), ppArgs, 3, ", " ); CGString sLoopVar = "_FOR"; switch( iQty ) { case 1: // FOR x iMin = 1; iMax = Exp_GetSingle( ppArgs[0] ); break; case 2: if ( isdigit( *ppArgs[0] ) ) { iMin = Exp_GetSingle( ppArgs[0] ); iMax = Exp_GetSingle( ppArgs[1] ); } else { iMin = 1; iMax = Exp_GetSingle( ppArgs[1] ); sLoopVar = ppArgs[0]; } break; case 3: sLoopVar = ppArgs[0]; iMin = Exp_GetSingle( ppArgs[1] );; iMax = Exp_GetSingle( ppArgs[2] ); break; default: iMin = iMax = 1; break; } if ( iMin > iMax ) fCountDown = true; if ( fCountDown ) for ( i = iMin; i >= iMax; --i ) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; pArgs->m_VarsLocal.SetNum( sLoopVar, i, false ); TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } else for ( i = iMin; i <= iMax; ++i ) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; pArgs->m_VarsLocal.SetNum( sLoopVar, i, false ); TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } if ( (iType & 1) || (iType & 2) ) { int iDist; if ( s.HasArgs() ) iDist = s.GetArgVal(); else iDist = UO_MAP_VIEW_SIZE; CObjBaseTemplate * pObj = dynamic_cast <CObjBaseTemplate *>(this); if ( pObj == NULL ) { iType = 0; DEBUG_ERR(( "FOR Loop trigger on non-world object '%s'\n", GetName())); } CObjBaseTemplate * pObjTop = pObj->GetTopLevelObj(); CPointMap pt = pObjTop->GetTopPoint(); if ( iType & 1 ) // FORITEM, FOROBJ { CWorldSearch AreaItems( pt, iDist ); while(true) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; CItem * pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; TRIGRET_TYPE iRet = pItem->OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } if ( iType & 2 ) // FORCHAR, FOROBJ { CWorldSearch AreaChars( pt, iDist ); while(true) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; CChar * pChar = AreaChars.GetChar(); if ( pChar == NULL ) break; if ( ( iType & 0x10 ) && ( ! pChar->IsClient() ) ) // FORCLIENTS continue; if ( ( iType & 0x20 ) && ( pChar->m_pPlayer == NULL ) ) // FORPLAYERS continue; TRIGRET_TYPE iRet = pChar->OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } } if ( g_Cfg.m_iMaxLoopTimes ) { toomanyloops: if ( LoopsMade >= g_Cfg.m_iMaxLoopTimes ) { g_Log.EventError("Terminating loop cycle since it seems being dead-locked (%d iterations already passed)" DEBUG_CR, LoopsMade); } } if ( EndContext.m_lOffset <= StartContext.m_lOffset ) { // just skip to the end. TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_FALSE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } } else { s.SeekContext( EndContext ); } return( TRIGRET_ENDIF ); }
bool CPartyDef::AcceptEvent( CChar * pCharAccept, CGrayUID uidInviter, bool bForced ) // static { ADDTOCALLSTACK("CPartyDef::AcceptEvent"); // We are accepting the invite to join a party // No security checks if bForced -> true !!! // Party master is only one that can add ! GetChar(0) ASSERT( pCharAccept ); CChar * pCharInviter = uidInviter.CharFind(); if ( pCharInviter == NULL ) return( false ); if ( pCharInviter == pCharAccept ) return( false ); if ( !pCharInviter->IsClient() || !pCharAccept->IsClient() ) return( false ); CPartyDef * pParty = pCharInviter->m_pParty; if ( !bForced ) { CVarDefCont * sTempVal = pCharInviter->GetTagDefs()->GetKey("PARTY_LASTINVITE"); if ( !sTempVal ) return( false ); if ((DWORD)sTempVal->GetValNum() != (DWORD)pCharAccept->GetUID()) return( false ); // Remove the key pCharInviter->DeleteKey("PARTY_LASTINVITE"); if ( !pCharInviter->CanSee( pCharAccept ) ) return( false ); } if ( pCharAccept->m_pParty != NULL ) // Aready in a party ! { if ( pParty == pCharAccept->m_pParty ) // already in this party return true; if ( bForced ) { pCharAccept->m_pParty->RemoveMember( pCharAccept->GetUID(), pCharAccept->GetUID() ); pCharAccept->m_pParty = NULL; } else return false; } TCHAR * pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg( DEFMSG_PARTY_JOINED ), static_cast<LPCTSTR>(pCharAccept->GetName())); if ( pParty == NULL ) { // Create the party now. pParty = new CPartyDef( pCharInviter, pCharAccept ); ASSERT(pParty); g_World.m_Parties.InsertHead( pParty ); pCharInviter->SysMessage( pszMsg ); } else { if ( pParty->IsPartyFull() ) return( false ); if ( !bForced && !pParty->IsPartyMaster(pCharInviter) ) return( false ); // Just add to existing party. pParty->SysMessageAll( pszMsg ); // tell everyone already in the party about this. pParty->AcceptMember( pCharAccept ); } pCharAccept->SysMessageDefault( DEFMSG_PARTY_ADDED ); return( true ); }
bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar * pSrc, CObjBase * pObj, const CPointMap & pt, LPCTSTR pszArgs ) { ADDTOCALLSTACK("CChar::NPC_OnHearPetCmdTarg"); // Pet commands that required a target. if ( iCmd == PC_FOLLOW || iCmd == PC_STAY || iCmd == PC_STOP ) { // Pet friends can use only these commands if ( ! NPC_IsOwnedBy( pSrc ) && Memory_FindObjTypes( pSrc, MEMORY_FRIEND ) == NULL ) return false; } else { // All others commands are avaible only to pet owner if ( ! NPC_IsOwnedBy( pSrc, true ) ) return false; } if ( m_fIgnoreNextPetCmd == true ) { m_fIgnoreNextPetCmd = false; return(false); } bool fSuccess = false; // No they won't do it. // Could be NULL CItem * pItemTarg = dynamic_cast<CItem*>(pObj); CChar * pCharTarg = dynamic_cast<CChar*>(pObj); switch ( iCmd ) { case PC_GO: // Go to the location x,y if ( ! pt.IsValidPoint()) break; m_Act_p = pt; fSuccess = Skill_Start( NPCACT_GOTO ); break; case PC_GUARD: if ( pObj == NULL ) break; m_Act_Targ = pObj->GetUID(); fSuccess = Skill_Start( NPCACT_GUARD_TARG ); break; case PC_TRANSFER: // transfer ownership via the transfer command. if ( pCharTarg == NULL ) break; if ( pCharTarg->IsClient() ) { if ( IsSetOF(OF_PetSlots) ) { if ( !pCharTarg->FollowersUpdate(this, static_cast<short>(maximum(1, GetDefNum("FOLLOWERSLOTS", true, true))), true) ) { pSrc->SysMessageDefault( DEFMSG_PETSLOTS_TRY_TRANSFER ); break; } } fSuccess = NPC_PetSetOwner( pCharTarg ); } break; case PC_KILL: case PC_ATTACK: // Attack the target. if ( pCharTarg == NULL ) break; // refuse to attack friends. if ( NPC_IsOwnedBy( pCharTarg, true )) { fSuccess = false; // take no commands break; } fSuccess = pCharTarg->OnAttackedBy( pSrc, 1, true ); // we know who told them to do this. if ( fSuccess ) { fSuccess = Fight_Attack( pCharTarg, true ); } break; case PC_FOLLOW: if ( pCharTarg == NULL ) break; m_Act_Targ = pCharTarg->GetUID(); fSuccess = Skill_Start( NPCACT_FOLLOW_TARG ); break; case PC_FRIEND: // Not the same as owner, if ( pCharTarg == NULL ) break; Memory_AddObjTypes( pCharTarg, MEMORY_FRIEND ); break; case PC_PRICE: // "PRICE" the vendor item. if ( pItemTarg == NULL ) break; if ( ! NPC_IsVendor()) break; // did they name a price if ( IsDigit( pszArgs[0] )) { return NPC_SetVendorPrice( pItemTarg, ATOI(pszArgs) ); } // test if it is pricable. if ( ! NPC_SetVendorPrice( pItemTarg, -1 )) { return false; } // Now set it's price. if ( ! pSrc->IsClient()) break; pSrc->m_pClient->addPromptConsole( CLIMODE_PROMPT_VENDOR_PRICE, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_SETPRICE_2 ), pItemTarg->GetUID(), GetUID() ); return( true ); default: break; } // Make the yes/no noise. NPC_OnPetCommand( fSuccess, pSrc ); return fSuccess; }