void CheckQuestDisables() { uint32 oldMSTime = getMSTime(); uint32 count = m_DisableMap[DISABLE_TYPE_QUEST].size(); if (!count) { SF_LOG_INFO("server.loading", ">> Checked 0 quest disables."); return; } // check only quests, rest already done at startup for (DisableTypeMap::iterator itr = m_DisableMap[DISABLE_TYPE_QUEST].begin(); itr != m_DisableMap[DISABLE_TYPE_QUEST].end();) { const uint32 entry = itr->first; if (!sObjectMgr->GetQuestTemplate(entry)) { SF_LOG_ERROR("sql.sql", "Quest entry %u from `disables` doesn't exist, skipped.", entry); m_DisableMap[DISABLE_TYPE_QUEST].erase(itr++); continue; } if (itr->second.flags) SF_LOG_ERROR("sql.sql", "Disable flags specified for quest %u, useless data.", entry); ++itr; } SF_LOG_INFO("server.loading", ">> Checked %u quest disables in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void GuildFinderMgr::LoadMembershipRequests() { SF_LOG_INFO("server.loading", "Loading guild finder membership requests..."); // 0 1 2 3 4 5 6 QueryResult result = CharacterDatabase.Query("SELECT guildId, playerGuid, availability, classRole, interests, comment, submitTime " "FROM guild_finder_applicant"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 guild finder membership requests. Table `guild_finder_applicant` is empty."); return; } uint32 count = 0; uint32 oldMSTime = getMSTime(); do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); uint32 playerId = fields[1].GetUInt32(); uint8 availability = fields[2].GetUInt8(); uint8 classRoles = fields[3].GetUInt8(); uint8 interests = fields[4].GetUInt8(); std::string comment = fields[5].GetString(); uint32 submitTime = fields[6].GetUInt32(); MembershipRequest request(playerId, guildId, availability, classRoles, interests, comment, time_t(submitTime)); _membershipRequests[guildId].push_back(request); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u guild finder membership requests in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); }
void BattlefieldMgr::InitBattlefield() { Battlefield* pBf = new BattlefieldWG; // respawn, init variables if (!pBf->SetupBattlefield()) { SF_LOG_INFO("misc", "Battlefield : Wintergrasp init failed."); delete pBf; } else { m_BattlefieldSet.push_back(pBf); SF_LOG_INFO("misc", "Battlefield : Wintergrasp successfully initiated."); } /* For Cataclysm: Tol Barad pBf = new BattlefieldTB; // respawn, init variables if (!pBf->SetupBattlefield()) { SF_LOG_DEBUG("bg.battlefield", "Battlefield : Tol Barad init failed."); delete pBf; } else { m_BattlefieldSet.push_back(pBf); SF_LOG_DEBUG("bg.battlefield", "Battlefield : Tol Barad successfully initiated."); } */ }
void HandleDummyHitTarget(SpellEffIndex /*effIndex*/) { SF_LOG_INFO("misc", "SPELL_EFFECT_DUMMY is hits it's target!"); // make caster cast a spell on a unit target of effect if (Unit* target = GetHitUnit()) GetCaster()->CastSpell(target, SPELL_TRIGGERED, true); }
void HandleAfterCast() { SF_LOG_INFO("misc", "All immediate Actions for the spell are finished now"); // this is a safe for triggering additional effects for a spell without interfering // with visuals or with other effects of the spell //GetCaster()->CastSpell(target, SPELL_TRIGGERED, true); }
void LoadWeatherData() { uint32 oldMSTime = getMSTime(); uint32 count = 0; QueryResult result = WorldDatabase.Query("SELECT " "zone, spring_rain_chance, spring_snow_chance, spring_storm_chance," "summer_rain_chance, summer_snow_chance, summer_storm_chance," "fall_rain_chance, fall_snow_chance, fall_storm_chance," "winter_rain_chance, winter_snow_chance, winter_storm_chance," "ScriptName FROM game_weather"); if (!result) { SF_LOG_ERROR("server.loading", ">> Loaded 0 weather definitions. DB table `game_weather` is empty."); return; } do { Field* fields = result->Fetch(); uint32 zone_id = fields[0].GetUInt32(); WeatherData& wzc = mWeatherZoneMap[zone_id]; for (uint8 season = 0; season < WEATHER_SEASONS; ++season) { wzc.data[season].rainChance = fields[season * (MAX_WEATHER_TYPE-1) + 1].GetUInt8(); wzc.data[season].snowChance = fields[season * (MAX_WEATHER_TYPE-1) + 2].GetUInt8(); wzc.data[season].stormChance = fields[season * (MAX_WEATHER_TYPE-1) + 3].GetUInt8(); if (wzc.data[season].rainChance > 100) { wzc.data[season].rainChance = 25; SF_LOG_ERROR("sql.sql", "Weather for zone %u season %u has wrong rain chance > 100%%", zone_id, season); } if (wzc.data[season].snowChance > 100) { wzc.data[season].snowChance = 25; SF_LOG_ERROR("sql.sql", "Weather for zone %u season %u has wrong snow chance > 100%%", zone_id, season); } if (wzc.data[season].stormChance > 100) { wzc.data[season].stormChance = 25; SF_LOG_ERROR("sql.sql", "Weather for zone %u season %u has wrong storm chance > 100%%", zone_id, season); } } wzc.ScriptId = sObjectMgr->GetScriptId(fields[13].GetCString()); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u weather definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void HandleDummyLaunchTarget(SpellEffIndex /*effIndex*/) { uint64 targetGUID = 0; if (Unit* unitTarget = GetHitUnit()) targetGUID = unitTarget->GetGUID(); // we're handling SPELL_EFFECT_DUMMY in effIndex 0 here SF_LOG_INFO("misc", "Spell %u with SPELL_EFFECT_DUMMY is just launched at it's target: " UI64FMTD "!", GetSpellInfo()->Id, targetGUID); }
// Create the Weather object Weather::Weather(uint32 zone, WeatherData const* weatherChances) : m_zone(zone), m_weatherChances(weatherChances) { m_timer.SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_CHANGEWEATHER)); m_type = WEATHER_TYPE_FINE; m_grade = 0; SF_LOG_INFO("misc", "WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (uint32)(m_timer.GetInterval() / (MINUTE*IN_MILLISECONDS))); }
void GuildFinderMgr::LoadGuildSettings() { SF_LOG_INFO("server.loading", "Loading guild finder guild-related settings..."); // 0 1 2 3 4 5 6 7 QueryResult result = CharacterDatabase.Query("SELECT gfgs.guildId, gfgs.availability, gfgs.classRoles, gfgs.interests, gfgs.level, gfgs.listed, gfgs.comment, c.race " "FROM guild_finder_guild_settings gfgs " "LEFT JOIN guild_member gm ON gm.guildid=gfgs.guildId " "LEFT JOIN characters c ON c.guid = gm.guid LIMIT 1"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 guild finder guild-related settings. Table `guild_finder_guild_settings` is empty."); return; } uint32 count = 0; uint32 oldMSTime = getMSTime(); do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); uint8 availability = fields[1].GetUInt8(); uint8 classRoles = fields[2].GetUInt8(); uint8 interests = fields[3].GetUInt8(); uint8 level = fields[4].GetUInt8(); bool listed = (fields[5].GetUInt8() != 0); std::string comment = fields[6].GetString(); TeamId guildTeam = TEAM_ALLIANCE; if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(fields[7].GetUInt8())) if (raceEntry->TeamID == 1) guildTeam = TEAM_HORDE; LFGuildSettings settings(listed, guildTeam, guildId, classRoles, availability, interests, level, comment); _guildSettings[guildId] = settings; ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u guild finder guild-related settings in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); }
void WaypointMgr::Load() { uint32 oldMSTime = getMSTime(); // 0 1 2 3 4 5 6 7 8 9 QueryResult result = WorldDatabase.Query("SELECT id, point, position_x, position_y, position_z, orientation, move_flag, delay, action, action_chance FROM waypoint_data ORDER BY id, point"); if (!result) { SF_LOG_ERROR("server.loading", ">> Loaded 0 waypoints. DB table `waypoint_data` is empty!"); return; } uint32 count = 0; do { Field* fields = result->Fetch(); WaypointData* wp = new WaypointData(); uint32 pathId = fields[0].GetUInt32(); WaypointPath& path = _waypointStore[pathId]; float x = fields[2].GetFloat(); float y = fields[3].GetFloat(); float z = fields[4].GetFloat(); float o = fields[5].GetFloat(); Skyfire::NormalizeMapCoord(x); Skyfire::NormalizeMapCoord(y); wp->id = fields[1].GetUInt32(); wp->x = x; wp->y = y; wp->z = z; wp->orientation = o; wp->run = fields[6].GetBool(); wp->delay = fields[7].GetUInt32(); wp->event_id = fields[8].GetUInt32(); wp->event_chance = fields[9].GetInt16(); path.push_back(wp); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u waypoints in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
// Hacklike storage used for misc creatures that are expected to evade of outside of a certain area. // It is assumed the information is found elswehere and can be handled by the core. So far no luck finding such information/way to extract it. bool ScriptedAI::EnterEvadeIfOutOfCombatArea(uint32 const diff) { if (_evadeCheckCooldown <= diff) _evadeCheckCooldown = 2500; else { _evadeCheckCooldown -= diff; return false; } if (me->IsInEvadeMode() || !me->GetVictim()) return false; float x = me->GetPositionX(); float y = me->GetPositionY(); float z = me->GetPositionZ(); switch (me->GetEntry()) { case NPC_BROODLORD: // broodlord (not move down stairs) if (z > 448.60f) return false; break; case NPC_VOID_REAVER: // void reaver (calculate from center of room) if (me->GetDistance2d(432.59f, 371.93f) < 105.0f) return false; break; case NPC_JAN_ALAI: // jan'alai (calculate by Z) if (z > 12.0f) return false; break; case NPC_SARTHARION: // sartharion (calculate box) if (x > 3218.86f && x < 3275.69f && y < 572.40f && y > 484.68f) return false; break; default: // For most of creatures that certain area is their home area. SF_LOG_INFO("misc", "TSCR: EnterEvadeIfOutOfCombatArea used for creature entry %u, but does not have any definition. Using the default one.", me->GetEntry()); uint32 homeAreaId = me->GetMap()->GetAreaId(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY(), me->GetHomePosition().GetPositionZ()); if (me->GetAreaId() == homeAreaId) return false; } EnterEvadeMode(); return true; }
void HandleOnHit() { SF_LOG_INFO("misc", "Spell just hit target!"); }
void LoadDisables() { uint32 oldMSTime = getMSTime(); // reload case for (DisableMap::iterator itr = m_DisableMap.begin(); itr != m_DisableMap.end(); ++itr) itr->second.clear(); m_DisableMap.clear(); QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables"); uint32 total_count = 0; if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 disables. DB table `disables` is empty!"); return; } Field* fields; do { fields = result->Fetch(); DisableType type = DisableType(fields[0].GetUInt32()); if (type >= MAX_DISABLE_TYPES) { SF_LOG_ERROR("sql.sql", "Invalid type %u specified in `disables` table, skipped.", type); continue; } uint32 entry = fields[1].GetUInt32(); uint8 flags = fields[2].GetUInt8(); std::string params_0 = fields[3].GetString(); std::string params_1 = fields[4].GetString(); DisableData data; data.flags = flags; switch (type) { case DISABLE_TYPE_SPELL: if (!(sSpellMgr->GetSpellInfo(entry) || flags & SPELL_DISABLE_DEPRECATED_SPELL)) { SF_LOG_ERROR("sql.sql", "Spell entry %u from `disables` doesn't exist in dbc, skipped.", entry); continue; } if (!flags || flags > MAX_SPELL_DISABLE_TYPE) { SF_LOG_ERROR("sql.sql", "Disable flags for spell %u are invalid, skipped.", entry); continue; } if (flags & SPELL_DISABLE_MAP) { Tokenizer tokens(params_0, ','); for (uint8 i = 0; i < tokens.size(); ) data.params[0].insert(atoi(tokens[i++])); } if (flags & SPELL_DISABLE_AREA) { Tokenizer tokens(params_1, ','); for (uint8 i = 0; i < tokens.size(); ) data.params[1].insert(atoi(tokens[i++])); } break; // checked later case DISABLE_TYPE_QUEST: break; case DISABLE_TYPE_MAP: { MapEntry const* mapEntry = sMapStore.LookupEntry(entry); if (!mapEntry) { SF_LOG_ERROR("sql.sql", "Map entry %u from `disables` doesn't exist in dbc, skipped.", entry); continue; } bool isFlagInvalid = false; switch (mapEntry->map_type) { case MAP_COMMON: if (flags) isFlagInvalid = true; break; case MAP_DUNGEON: if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DIFFICULTY_HEROIC)) flags -= DUNGEON_STATUSFLAG_HEROIC; if (!flags) isFlagInvalid = true; break; case MAP_RAID: if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, DIFFICULTY_10MAN_HEROIC)) flags -= RAID_STATUSFLAG_10MAN_HEROIC; if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, DIFFICULTY_25MAN_HEROIC)) flags -= RAID_STATUSFLAG_25MAN_HEROIC; if (flags & RAID_STATUSFLAG_10MAN_FLEX && !GetMapDifficultyData(entry, DIFFICULTY_FLEX)) flags -= RAID_STATUSFLAG_10MAN_FLEX; if (flags & RAID_STATUSFLAG_25MAN_LFR && !GetMapDifficultyData(entry, DIFFICULTY_25MAN_LFR)) flags -= RAID_STATUSFLAG_25MAN_LFR; if (!flags) isFlagInvalid = true; break; case MAP_BATTLEGROUND: case MAP_ARENA: SF_LOG_ERROR("sql.sql", "Battleground map %u specified to be disabled in map case, skipped.", entry); continue; } if (isFlagInvalid) { SF_LOG_ERROR("sql.sql", "Disable flags for map %u are invalid, skipped.", entry); continue; } break; } case DISABLE_TYPE_BATTLEGROUND: if (!sBattlemasterListStore.LookupEntry(entry)) { SF_LOG_ERROR("sql.sql", "Battleground entry %u from `disables` doesn't exist in dbc, skipped.", entry); continue; } if (flags) SF_LOG_ERROR("sql.sql", "Disable flags specified for battleground %u, useless data.", entry); break; case DISABLE_TYPE_OUTDOORPVP: if (entry > MAX_OUTDOORPVP_TYPES) { SF_LOG_ERROR("sql.sql", "OutdoorPvPTypes value %u from `disables` is invalid, skipped.", entry); continue; } if (flags) SF_LOG_ERROR("sql.sql", "Disable flags specified for outdoor PvP %u, useless data.", entry); break; case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: if (!sAchievementMgr->GetAchievementCriteria(entry)) { SF_LOG_ERROR("sql.sql", "Achievement Criteria entry %u from `disables` doesn't exist in dbc, skipped.", entry); continue; } if (flags) SF_LOG_ERROR("sql.sql", "Disable flags specified for Achievement Criteria %u, useless data.", entry); break; case DISABLE_TYPE_VMAP: { MapEntry const* mapEntry = sMapStore.LookupEntry(entry); if (!mapEntry) { SF_LOG_ERROR("sql.sql", "Map entry %u from `disables` doesn't exist in dbc, skipped.", entry); continue; } switch (mapEntry->map_type) { case MAP_COMMON: if (flags & VMAP_DISABLE_AREAFLAG) SF_LOG_INFO("misc", "Areaflag disabled for world map %u.", entry); if (flags & VMAP_DISABLE_LIQUIDSTATUS) SF_LOG_INFO("misc", "Liquid status disabled for world map %u.", entry); break; case MAP_DUNGEON: if (flags & VMAP_DISABLE_HEIGHT) SF_LOG_INFO("misc", "Height disabled for instance map %u.", entry); if (flags & VMAP_DISABLE_LOS) SF_LOG_INFO("misc", "LoS disabled for instance map %u.", entry); break; case MAP_RAID: if (flags & VMAP_DISABLE_HEIGHT) SF_LOG_INFO("misc", "Height disabled for raid map %u.", entry); if (flags & VMAP_DISABLE_LOS) SF_LOG_INFO("misc", "LoS disabled for raid map %u.", entry); break; case MAP_BATTLEGROUND: if (flags & VMAP_DISABLE_HEIGHT) SF_LOG_INFO("misc", "Height disabled for battleground map %u.", entry); if (flags & VMAP_DISABLE_LOS) SF_LOG_INFO("misc", "LoS disabled for battleground map %u.", entry); break; case MAP_ARENA: if (flags & VMAP_DISABLE_HEIGHT) SF_LOG_INFO("misc", "Height disabled for arena map %u.", entry); if (flags & VMAP_DISABLE_LOS) SF_LOG_INFO("misc", "LoS disabled for arena map %u.", entry); break; default: break; } break; } case DISABLE_TYPE_MMAP: { MapEntry const* mapEntry = sMapStore.LookupEntry(entry); if (!mapEntry) { SF_LOG_ERROR("sql.sql", "Map entry %u from `disables` doesn't exist in dbc, skipped.", entry); continue; } switch (mapEntry->map_type) { case MAP_COMMON: SF_LOG_INFO("misc", "Pathfinding disabled for world map %u.", entry); break; case MAP_DUNGEON: case MAP_RAID: SF_LOG_INFO("misc", "Pathfinding disabled for instance map %u.", entry); break; case MAP_BATTLEGROUND: SF_LOG_INFO("misc", "Pathfinding disabled for battleground map %u.", entry); break; case MAP_ARENA: SF_LOG_INFO("misc", "Pathfinding disabled for arena map %u.", entry); break; default: break; } break; } default: break; } m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data)); ++total_count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u disables in %u ms", total_count, GetMSTimeDiffToNow(oldMSTime)); }
// Send the new weather to all players in the zone bool Weather::UpdateWeather() { Player* player = sWorld->FindPlayerInZone(m_zone); if (!player) return false; ///- Send the weather packet to all players in this zone if (m_grade >= 1) m_grade = 0.9999f; else if (m_grade < 0) m_grade = 0.0001f; WeatherState state = GetWeatherState(); WorldPacket data(SMSG_WEATHER, (4+4+4)); data << uint32(state) << (float)m_grade << uint8(0); player->SendMessageToSet(&data, true); ///- Log the event char const* wthstr; switch (state) { case WEATHER_STATE_FOG: wthstr = "fog"; break; case WEATHER_STATE_LIGHT_RAIN: wthstr = "light rain"; break; case WEATHER_STATE_MEDIUM_RAIN: wthstr = "medium rain"; break; case WEATHER_STATE_HEAVY_RAIN: wthstr = "heavy rain"; break; case WEATHER_STATE_LIGHT_SNOW: wthstr = "light snow"; break; case WEATHER_STATE_MEDIUM_SNOW: wthstr = "medium snow"; break; case WEATHER_STATE_HEAVY_SNOW: wthstr = "heavy snow"; break; case WEATHER_STATE_LIGHT_SANDSTORM: wthstr = "light sandstorm"; break; case WEATHER_STATE_MEDIUM_SANDSTORM: wthstr = "medium sandstorm"; break; case WEATHER_STATE_HEAVY_SANDSTORM: wthstr = "heavy sandstorm"; break; case WEATHER_STATE_THUNDERS: wthstr = "thunders"; break; case WEATHER_STATE_BLACKRAIN: wthstr = "blackrain"; break; case WEATHER_STATE_FINE: default: wthstr = "fine"; break; } SF_LOG_INFO("misc", "Change the weather of zone %u to %s.", m_zone, wthstr); sScriptMgr->OnWeatherChange(this, state, m_grade); return true; }
//used when player copies mail body to his inventory void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData) { ObjectGuid mailbox; uint32 mailId; recvData >> mailId; mailbox[4] = recvData.ReadBit(); mailbox[1] = recvData.ReadBit(); mailbox[6] = recvData.ReadBit(); mailbox[2] = recvData.ReadBit(); mailbox[5] = recvData.ReadBit(); mailbox[3] = recvData.ReadBit(); mailbox[0] = recvData.ReadBit(); mailbox[7] = recvData.ReadBit(); recvData.ReadByteSeq(mailbox[6]); recvData.ReadByteSeq(mailbox[5]); recvData.ReadByteSeq(mailbox[4]); recvData.ReadByteSeq(mailbox[3]); recvData.ReadByteSeq(mailbox[0]); recvData.ReadByteSeq(mailbox[7]); recvData.ReadByteSeq(mailbox[2]); recvData.ReadByteSeq(mailbox[1]); if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player* player = _player; Mail* m = player->GetMail(mailId); if (!m || (m->body.empty() && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) { player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR); return; } Item* bodyItem = new Item; // This is not bag and then can be used new Item. if (!bodyItem->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM), MAIL_BODY_ITEM_TEMPLATE, player)) { delete bodyItem; return; } // in mail template case we need create new item text if (m->mailTemplateId) { MailTemplateEntry const* mailTemplateEntry = sMailTemplateStore.LookupEntry(m->mailTemplateId); if (!mailTemplateEntry) { player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR); return; } bodyItem->SetText(mailTemplateEntry->content); } else bodyItem->SetText(m->body); bodyItem->SetUInt32Value(ITEM_FIELD_CREATOR, m->sender); bodyItem->SetFlag(ITEM_FIELD_DYNAMIC_FLAGS, ITEM_FLAG_MAIL_TEXT_MASK); SF_LOG_INFO("network", "HandleMailCreateTextItem mailid=%u", mailId); ItemPosCountVec dest; uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, bodyItem, false); if (msg == EQUIP_ERR_OK) { m->checked = m->checked | MAIL_CHECK_MASK_COPIED; m->state = MAIL_STATE_CHANGED; player->m_mailsUpdated = true; player->StoreItem(dest, bodyItem, true); player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_OK); } else { player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_EQUIP_ERROR, msg); delete bodyItem; } }
void WorldSession::HandleSendMail(WorldPacket& recvData) { ObjectGuid mailbox; uint64 money, COD; std::string receiverName, subject, body; uint32 bodyLength, subjectLength, receiverLength; uint32 unk1, unk2; uint8 itemCount; recvData >> unk1 >> unk2; // both unknown recvData >> COD >> money; // money and cod mailbox[0] = recvData.ReadBit(); mailbox[6] = recvData.ReadBit(); mailbox[4] = recvData.ReadBit(); mailbox[1] = recvData.ReadBit(); bodyLength = recvData.ReadBits(11); mailbox[3] = recvData.ReadBit(); receiverLength = recvData.ReadBits(9); mailbox[7] = recvData.ReadBit(); mailbox[5] = recvData.ReadBit(); itemCount = recvData.ReadBits(5); // attached items count if (itemCount > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recvData.rfinish(); // set to end to avoid warnings spam return; } ObjectGuid itemGuids[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < itemCount; ++i) { itemGuids[i][1] = recvData.ReadBit(); itemGuids[i][7] = recvData.ReadBit(); itemGuids[i][2] = recvData.ReadBit(); itemGuids[i][5] = recvData.ReadBit(); itemGuids[i][0] = recvData.ReadBit(); itemGuids[i][6] = recvData.ReadBit(); itemGuids[i][3] = recvData.ReadBit(); itemGuids[i][4] = recvData.ReadBit(); } subjectLength = recvData.ReadBits(9); mailbox[2] = recvData.ReadBit(); for (uint8 i = 0; i < itemCount; ++i) { recvData.read_skip<uint8>(); // item slot in mail, not used recvData.ReadByteSeq(itemGuids[i][3]); recvData.ReadByteSeq(itemGuids[i][0]); recvData.ReadByteSeq(itemGuids[i][2]); recvData.ReadByteSeq(itemGuids[i][1]); recvData.ReadByteSeq(itemGuids[i][6]); recvData.ReadByteSeq(itemGuids[i][5]); recvData.ReadByteSeq(itemGuids[i][7]); recvData.ReadByteSeq(itemGuids[i][4]); } recvData.ReadByteSeq(mailbox[1]); body = recvData.ReadString(bodyLength); recvData.ReadByteSeq(mailbox[0]); subject = recvData.ReadString(subjectLength); recvData.ReadByteSeq(mailbox[2]); recvData.ReadByteSeq(mailbox[6]); recvData.ReadByteSeq(mailbox[5]); recvData.ReadByteSeq(mailbox[7]); recvData.ReadByteSeq(mailbox[3]); recvData.ReadByteSeq(mailbox[4]); receiverName = recvData.ReadString(receiverLength); // packet read complete, now do check if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; if (receiverName.empty()) return; Player* player = _player; if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetSkyFireString(LANG_MAIL_SENDER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint64 receiverGuid = 0; if (normalizePlayerName(receiverName)) receiverGuid = sObjectMgr->GetPlayerGUIDByName(receiverName); if (!receiverGuid) { SF_LOG_INFO("network", "Player %u is sending mail to %s (GUID: not existed!) with subject %s " "and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(), itemCount, money, COD, unk1, unk2); player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } SF_LOG_INFO("network", "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s " "includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiverName.c_str(), GUID_LOPART(receiverGuid), subject.c_str(), body.c_str(), itemCount, money, COD, unk1, unk2); if (player->GetGUID() == receiverGuid) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 cost = itemCount ? 30 * itemCount : 30; // price hardcoded in client uint64 reqmoney = cost + money; if (!player->HasEnoughMoney(reqmoney) && !player->IsGameMaster()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player* receiver = ObjectAccessor::FindPlayer(receiverGuid); uint32 receiverTeam = 0; uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails uint8 receiverLevel = 0; uint32 receiverAccountId = 0; if (receiver) { receiverTeam = receiver->GetTeam(); mailsCount = receiver->GetMailSize(); receiverLevel = receiver->getLevel(); receiverAccountId = receiver->GetSession()->GetAccountId(); } else { receiverTeam = sObjectMgr->GetPlayerTeamByGUID(receiverGuid); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT); stmt->setUInt32(0, GUID_LOPART(receiverGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); mailsCount = fields[0].GetUInt64(); } stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL); stmt->setUInt32(0, GUID_LOPART(receiverGuid)); result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); receiverLevel = fields[0].GetUInt8(); } receiverAccountId = sObjectMgr->GetPlayerAccountIdByGUID(receiverGuid); } // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mailsCount > 100) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // test the receiver's Faction... or all items are account bound bool accountBound = itemCount ? true : false; for (uint8 i = 0; i < itemCount; ++i) { if (Item* item = player->GetItemByGuid(itemGuids[i])) { ItemTemplate const* itemProto = item->GetTemplate(); if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; } } } if (!accountBound && player->GetTeam() != receiverTeam && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } if (receiverLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetSkyFireString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } Item* items[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < itemCount; ++i) { if (!itemGuids[i]) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } Item* item = player->GetItemByGuid(itemGuids[i]); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded(true)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT); return; } if (item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_EXPIRATION)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (COD && item->HasFlag(ITEM_FIELD_DYNAMIC_FLAGS, ITEM_FLAG_WRAPPED)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } if (item->IsNotEmptyBag()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_DESTROY_NONEMPTY_BAG); return; } items[i] = item; } player->SendMailResult(0, MAIL_SEND, MAIL_OK); player->ModifyMoney(-int64(reqmoney)); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; MailDraft draft(subject, body); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (itemCount > 0 || money > 0) { bool log = HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE); if (itemCount > 0) { for (uint8 i = 0; i < itemCount; ++i) { Item* item = items[i]; if (log) { sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail item: %s (Entry: %u Count: %u) " "to player: %s (GUID: %u) (Account: %u)", GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId); } item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); item->DeleteFromInventoryDB(trans); // deletes item from character's inventory item->SetOwnerGUID(receiverGuid); item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId; } if (log && money > 0) { sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: " UI64FMTD " to player: %s (GUID: %u) (Account: %u)", GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), money, receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // Mail sent between guild members arrives instantly if they have the guild perk "Guild Mail" if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) if (guild->GetLevel() >= 17 && guild->IsMember(receiverGuid)) deliver_delay = 0; // will delete item or place to receiver mail list draft .AddMoney(money) .AddCOD(COD) .SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
void AccountMgr::LoadRBAC() { ClearRBAC(); SF_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC"); uint32 oldMSTime = getMSTime(); uint32 count1 = 0; uint32 count2 = 0; uint32 count3 = 0; SF_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading permissions"); QueryResult result = LoginDatabase.Query("SELECT id, name FROM rbac_permissions"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 account permission definitions. DB table `rbac_permissions` is empty."); return; } do { Field* field = result->Fetch(); uint32 id = field[0].GetUInt32(); _permissions[id] = new rbac::RBACPermission(id, field[1].GetString()); ++count1; } while (result->NextRow()); SF_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading linked permissions"); result = LoginDatabase.Query("SELECT id, linkedId FROM rbac_linked_permissions ORDER BY id ASC"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 linked permissions. DB table `rbac_linked_permissions` is empty."); return; } uint32 permissionId = 0; rbac::RBACPermission* permission = NULL; do { Field* field = result->Fetch(); uint32 newId = field[0].GetUInt32(); if (permissionId != newId) { permissionId = newId; permission = _permissions[newId]; } uint32 linkedPermissionId = field[1].GetUInt32(); if (linkedPermissionId == permissionId) { SF_LOG_ERROR("sql.sql", "RBAC Permission %u has itself as linked permission. Ignored", permissionId); continue; } permission->AddLinkedPermission(linkedPermissionId); ++count2; } while (result->NextRow()); SF_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading default permissions"); result = LoginDatabase.Query("SELECT secId, permissionId FROM rbac_default_permissions ORDER BY secId ASC"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 default permission definitions. DB table `rbac_default_permissions` is empty."); return; } uint8 secId = 255; rbac::RBACPermissionContainer* permissions = NULL; do { Field* field = result->Fetch(); uint32 newId = field[0].GetUInt32(); if (secId != newId) { secId = newId; permissions = &_defaultPermissions[secId]; } permissions->insert(field[1].GetUInt32()); ++count3; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u permission definitions, %u linked permissions and %u default permissions in %u ms", count1, count2, count3, GetMSTimeDiffToNow(oldMSTime)); }
void GroupMgr::LoadGroups() { { uint32 oldMSTime = getMSTime(); // Delete all groups whose leader does not exist CharacterDatabase.DirectExecute("DELETE FROM groups WHERE leaderGuid NOT IN (SELECT guid FROM characters)"); // Delete all groups with less than 2 members CharacterDatabase.DirectExecute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)"); // 0 1 2 3 4 5 6 7 8 9 QueryResult result = CharacterDatabase.Query("SELECT g.leaderGuid, g.lootMethod, g.looterGuid, g.lootThreshold, g.icon1, g.icon2, g.icon3, g.icon4, g.icon5, g.icon6" // 10 11 12 13 14 15 16 17 ", g.icon7, g.icon8, g.groupType, g.difficulty, g.raiddifficulty, g.guid, lfg.dungeon, lfg.state FROM groups g LEFT JOIN lfg_data lfg ON lfg.guid = g.guid ORDER BY g.guid ASC"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 group definitions. DB table `groups` is empty!"); return; } uint32 count = 0; do { Field* fields = result->Fetch(); Group* group = new Group; group->LoadGroupFromDB(fields); AddGroup(group); // Get the ID used for storing the group in the database and register it in the pool. uint32 storageId = group->GetDbStoreId(); RegisterGroupDbStoreId(storageId, group); // Increase the next available storage ID if (storageId == NextGroupDbStoreId) NextGroupDbStoreId++; ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u group definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } SF_LOG_INFO("server.loading", "Loading Group members..."); { uint32 oldMSTime = getMSTime(); // Delete all rows from group_member or group_instance with no group CharacterDatabase.DirectExecute("DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)"); CharacterDatabase.DirectExecute("DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)"); // Delete all members that does not exist CharacterDatabase.DirectExecute("DELETE FROM group_member WHERE memberGuid NOT IN (SELECT guid FROM characters)"); // 0 1 2 3 4 QueryResult result = CharacterDatabase.Query("SELECT guid, memberGuid, memberFlags, subgroup, roles FROM group_member ORDER BY guid"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 group members. DB table `group_member` is empty!"); return; } uint32 count = 0; do { Field* fields = result->Fetch(); Group* group = GetGroupByDbStoreId(fields[0].GetUInt32()); if (group) group->LoadMemberFromDB(fields[1].GetUInt32(), fields[2].GetUInt8(), fields[3].GetUInt8(), fields[4].GetUInt8()); else SF_LOG_ERROR("misc", "GroupMgr::LoadGroups: Consistency failed, can't find group (storage id: %u)", fields[0].GetUInt32()); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u group members in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } SF_LOG_INFO("server.loading", "Loading Group instance saves..."); { uint32 oldMSTime = getMSTime(); // 0 1 2 3 4 5 6 QueryResult result = CharacterDatabase.Query("SELECT gi.guid, i.map, gi.instance, gi.permanent, i.difficulty, i.resettime, COUNT(g.guid) " "FROM group_instance gi INNER JOIN instance i ON gi.instance = i.id " "LEFT JOIN character_instance ci LEFT JOIN groups g ON g.leaderGuid = ci.guid ON ci.instance = gi.instance AND ci.permanent = 1 GROUP BY gi.instance ORDER BY gi.guid"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 group-instance saves. DB table `group_instance` is empty!"); return; } uint32 count = 0; do { Field* fields = result->Fetch(); Group* group = GetGroupByDbStoreId(fields[0].GetUInt32()); // group will never be NULL (we have run consistency sql's before loading) MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt16()); if (!mapEntry || !mapEntry->IsDungeon()) { SF_LOG_ERROR("sql.sql", "Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt16()); continue; } uint32 diff = fields[4].GetUInt8(); if (diff >= uint32(mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) { SF_LOG_ERROR("sql.sql", "Wrong dungeon difficulty use in group_instance table: %d", diff + 1); diff = 0; // default for both difficaly types } InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt32()), (bool)fields[6].GetUInt64(), true); group->BindToInstance(save, fields[3].GetBool(), true); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u group-instance saves in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } }
// Calculate the new weather bool Weather::ReGenerate() { if (!m_weatherChances) { m_type = WEATHER_TYPE_FINE; m_grade = 0.0f; return false; } // Weather statistics: ///- 30% - no change ///- 30% - weather gets better (if not fine) or change weather type ///- 30% - weather worsens (if not fine) ///- 10% - radical change (if not fine) uint32 u = urand(0, 99); if (u < 30) return false; // remember old values WeatherType old_type = m_type; float old_grade = m_grade; //78 days between January 1st and March 20nd; 365/4=91 days by season // season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html time_t gtime = sWorld->GetGameTime(); struct tm ltime; ACE_OS::localtime_r(>ime, <ime); uint32 season = ((ltime.tm_yday - 78 + 365)/91)%4; static char const* seasonName[WEATHER_SEASONS] = { "spring", "summer", "fall", "winter" }; SF_LOG_INFO("misc", "Generating a change in %s weather for zone %u.", seasonName[season], m_zone); if ((u < 60) && (m_grade < 0.33333334f)) // Get fair { m_type = WEATHER_TYPE_FINE; m_grade = 0.0f; } if ((u < 60) && (m_type != WEATHER_TYPE_FINE)) // Get better { m_grade -= 0.33333334f; return true; } if ((u < 90) && (m_type != WEATHER_TYPE_FINE)) // Get worse { m_grade += 0.33333334f; return true; } if (m_type != WEATHER_TYPE_FINE) { // Radical change: ///- if light -> heavy ///- if medium -> change weather type ///- if heavy -> 50% light, 50% change weather type if (m_grade < 0.33333334f) { m_grade = 0.9999f; // go nuts return true; } else { if (m_grade > 0.6666667f) { // Severe change, but how severe? uint32 rnd = urand(0, 99); if (rnd < 50) { m_grade -= 0.6666667f; return true; } } m_type = WEATHER_TYPE_FINE; // clear up m_grade = 0; } } // At this point, only weather that isn't doing anything remains but that have weather data uint32 chance1 = m_weatherChances->data[season].rainChance; uint32 chance2 = chance1+ m_weatherChances->data[season].snowChance; uint32 chance3 = chance2+ m_weatherChances->data[season].stormChance; uint32 rnd = urand(0, 99); if (rnd <= chance1) m_type = WEATHER_TYPE_RAIN; else if (rnd <= chance2) m_type = WEATHER_TYPE_SNOW; else if (rnd <= chance3) m_type = WEATHER_TYPE_STORM; else m_type = WEATHER_TYPE_FINE; // New weather statistics (if not fine): ///- 85% light ///- 7% medium ///- 7% heavy // If fine 100% sun (no fog) if (m_type == WEATHER_TYPE_FINE) { m_grade = 0.0f; } else if (u < 90) { m_grade = (float)rand_norm() * 0.3333f; } else { // Severe change, but how severe? rnd = urand(0, 99); if (rnd < 50) m_grade = (float)rand_norm() * 0.3333f + 0.3334f; else m_grade = (float)rand_norm() * 0.3333f + 0.6667f; } // return true only in case weather changes return m_type != old_type || m_grade != old_grade; }
void HandleOnCast() { // cast is validated and spell targets are selected at this moment // this is a last place when the spell can be safely interrupted SF_LOG_INFO("misc", "Spell is about to do take reagents, power, launch missile, do visuals and instant spell effects"); }
void FilterTargets(std::list<Unit*>& /*targetList*/) { // usually you want this call for Area Target spells SF_LOG_INFO("misc", "Spell is about to add targets from targetList to final targets!"); }
void OutdoorPvPMgr::InitOutdoorPvP() { uint32 oldMSTime = getMSTime(); // 0 1 QueryResult result = WorldDatabase.Query("SELECT TypeId, ScriptName FROM outdoorpvp_template"); if (!result) { SF_LOG_ERROR("server.loading", ">> Loaded 0 outdoor PvP definitions. DB table `outdoorpvp_template` is empty."); return; } uint32 count = 0; uint32 typeId = 0; do { Field* fields = result->Fetch(); typeId = fields[0].GetUInt8(); if (DisableMgr::IsDisabledFor(DISABLE_TYPE_OUTDOORPVP, typeId, NULL)) continue; if (typeId >= MAX_OUTDOORPVP_TYPES) { SF_LOG_ERROR("sql.sql", "Invalid OutdoorPvPTypes value %u in outdoorpvp_template; skipped.", typeId); continue; } OutdoorPvPData* data = new OutdoorPvPData(); OutdoorPvPTypes realTypeId = OutdoorPvPTypes(typeId); data->TypeId = realTypeId; data->ScriptId = sObjectMgr->GetScriptId(fields[1].GetCString()); m_OutdoorPvPDatas[realTypeId] = data; ++count; } while (result->NextRow()); OutdoorPvP* pvp; for (uint8 i = 1; i < MAX_OUTDOORPVP_TYPES; ++i) { OutdoorPvPDataMap::iterator iter = m_OutdoorPvPDatas.find(OutdoorPvPTypes(i)); if (iter == m_OutdoorPvPDatas.end()) { SF_LOG_ERROR("sql.sql", "Could not initialize OutdoorPvP object for type ID %u; no entry in database.", uint32(i)); continue; } pvp = sScriptMgr->CreateOutdoorPvP(iter->second); if (!pvp) { SF_LOG_ERROR("outdoorpvp", "Could not initialize OutdoorPvP object for type ID %u; got NULL pointer from script.", uint32(i)); continue; } if (!pvp->SetupOutdoorPvP()) { SF_LOG_ERROR("outdoorpvp", "Could not initialize OutdoorPvP object for type ID %u; SetupOutdoorPvP failed.", uint32(i)); delete pvp; continue; } m_OutdoorPvPSet.push_back(pvp); } SF_LOG_INFO("server.loading", ">> Loaded %u outdoor PvP definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void HandleBeforeHit() { SF_LOG_INFO("misc", "Spell is about to hit target!"); }
void HandleDummyLaunch(SpellEffIndex /*effIndex*/) { SF_LOG_INFO("misc", "Spell %u with SPELL_EFFECT_DUMMY is just launched!", GetSpellInfo()->Id); }
void HandleDummyHit(SpellEffIndex /*effIndex*/) { SF_LOG_INFO("misc", "Spell %u with SPELL_EFFECT_DUMMY has hit!", GetSpellInfo()->Id); }
void HandleAfterHit() { SF_LOG_INFO("misc", "Spell just finished hitting target!"); }
void PoolMgr::LoadFromDB() { // Pool templates { uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.Query("SELECT entry, max_limit FROM pool_template"); if (!result) { mPoolTemplate.clear(); SF_LOG_INFO("server.loading", ">> Loaded 0 object pools. DB table `pool_template` is empty."); return; } uint32 count = 0; do { Field* fields = result->Fetch(); uint32 pool_id = fields[0].GetUInt32(); PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id]; pPoolTemplate.MaxLimit = fields[1].GetUInt32(); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u objects pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } // Creatures SF_LOG_INFO("server.loading", "Loading Creatures Pooling Data..."); { uint32 oldMSTime = getMSTime(); // 1 2 3 QueryResult result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_creature"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 creatures in pools. DB table `pool_creature` is empty."); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); uint32 pool_id = fields[1].GetUInt32(); float chance = fields[2].GetFloat(); CreatureData const* data = sObjectMgr->GetCreatureData(guid); if (!data) { SF_LOG_ERROR("sql.sql", "`pool_creature` has a non existing creature spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id); continue; } if (pool_id > max_pool_id) { SF_LOG_ERROR("sql.sql", "`pool_creature` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { SF_LOG_ERROR("sql.sql", "`pool_creature` has an invalid chance (%f) for creature guid (%u) in pool id (%u), skipped.", chance, guid, pool_id); continue; } PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id]; PoolObject plObject = PoolObject(guid, chance); PoolGroup<Creature>& cregroup = mPoolCreatureGroups[pool_id]; cregroup.SetPoolId(pool_id); cregroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(guid, pool_id); mCreatureSearchMap.insert(p); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u creatures in pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // Gameobjects SF_LOG_INFO("server.loading", "Loading Gameobject Pooling Data..."); { uint32 oldMSTime = getMSTime(); // 1 2 3 QueryResult result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_gameobject"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 gameobjects in pools. DB table `pool_gameobject` is empty."); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); uint32 pool_id = fields[1].GetUInt32(); float chance = fields[2].GetFloat(); GameObjectData const* data = sObjectMgr->GetGOData(guid); if (!data) { SF_LOG_ERROR("sql.sql", "`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id); continue; } GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(data->id); if (goinfo->type != GAMEOBJECT_TYPE_CHEST && goinfo->type != GAMEOBJECT_TYPE_GOOBER && goinfo->type != GAMEOBJECT_TYPE_FISHINGHOLE) { SF_LOG_ERROR("sql.sql", "`pool_gameobject` has a not lootable gameobject spawn (GUID: %u, type: %u) defined for pool id (%u), skipped.", guid, goinfo->type, pool_id); continue; } if (pool_id > max_pool_id) { SF_LOG_ERROR("sql.sql", "`pool_gameobject` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { SF_LOG_ERROR("sql.sql", "`pool_gameobject` has an invalid chance (%f) for gameobject guid (%u) in pool id (%u), skipped.", chance, guid, pool_id); continue; } PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id]; PoolObject plObject = PoolObject(guid, chance); PoolGroup<GameObject>& gogroup = mPoolGameobjectGroups[pool_id]; gogroup.SetPoolId(pool_id); gogroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(guid, pool_id); mGameobjectSearchMap.insert(p); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u gameobject in pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // Pool of pools SF_LOG_INFO("server.loading", "Loading Mother Pooling Data..."); { uint32 oldMSTime = getMSTime(); // 1 2 3 QueryResult result = WorldDatabase.Query("SELECT pool_id, mother_pool, chance FROM pool_pool"); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 pools in pools"); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 child_pool_id = fields[0].GetUInt32(); uint32 mother_pool_id = fields[1].GetUInt32(); float chance = fields[2].GetFloat(); if (mother_pool_id > max_pool_id) { SF_LOG_ERROR("sql.sql", "`pool_pool` mother_pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", mother_pool_id); continue; } if (child_pool_id > max_pool_id) { SF_LOG_ERROR("sql.sql", "`pool_pool` included pool_id (%u) is out of range compared to max pool id in `pool_template`, skipped.", child_pool_id); continue; } if (mother_pool_id == child_pool_id) { SF_LOG_ERROR("sql.sql", "`pool_pool` pool_id (%u) includes itself, dead-lock detected, skipped.", child_pool_id); continue; } if (chance < 0 || chance > 100) { SF_LOG_ERROR("sql.sql", "`pool_pool` has an invalid chance (%f) for pool id (%u) in mother pool id (%u), skipped.", chance, child_pool_id, mother_pool_id); continue; } PoolTemplateData* pPoolTemplateMother = &mPoolTemplate[mother_pool_id]; PoolObject plObject = PoolObject(child_pool_id, chance); PoolGroup<Pool>& plgroup = mPoolPoolGroups[mother_pool_id]; plgroup.SetPoolId(mother_pool_id); plgroup.AddEntry(plObject, pPoolTemplateMother->MaxLimit); SearchPair p(child_pool_id, mother_pool_id); mPoolSearchMap.insert(p); ++count; } while (result->NextRow()); // Now check for circular reference for (uint32 i=0; i < max_pool_id; ++i) { std::set<uint32> checkedPools; for (SearchMap::iterator poolItr = mPoolSearchMap.find(i); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second)) { checkedPools.insert(poolItr->first); if (checkedPools.find(poolItr->second) != checkedPools.end()) { std::ostringstream ss; ss<< "The pool(s) "; for (std::set<uint32>::const_iterator itr=checkedPools.begin(); itr != checkedPools.end(); ++itr) ss << *itr << ' '; ss << "create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool " << poolItr->first << " and child pool " << poolItr->second; SF_LOG_ERROR("sql.sql", "%s", ss.str().c_str()); mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first); mPoolSearchMap.erase(poolItr); --count; break; } } } SF_LOG_INFO("server.loading", ">> Loaded %u pools in mother pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } SF_LOG_INFO("server.loading", "Loading Quest Pooling Data..."); { uint32 oldMSTime = getMSTime(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_QUEST_POOLS); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { SF_LOG_INFO("server.loading", ">> Loaded 0 quests in pools"); } else { PooledQuestRelationBounds creBounds; PooledQuestRelationBounds goBounds; enum eQuestTypes { QUEST_NONE = 0, QUEST_DAILY = 1, QUEST_WEEKLY = 2 }; std::map<uint32, int32> poolTypeMap; uint32 count = 0; do { Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 pool_id = fields[1].GetUInt32(); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); if (!quest) { SF_LOG_ERROR("sql.sql", "`pool_quest` has a non existing quest template (Entry: %u) defined for pool id (%u), skipped.", entry, pool_id); continue; } if (pool_id > max_pool_id) { SF_LOG_ERROR("sql.sql", "`pool_quest` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); continue; } if (!quest->IsDailyOrWeekly()) { SF_LOG_ERROR("sql.sql", "`pool_quest` has an quest (%u) which is not daily or weekly in pool id (%u), use ExclusiveGroup instead, skipped.", entry, pool_id); continue; } if (poolTypeMap[pool_id] == QUEST_NONE) poolTypeMap[pool_id] = quest->IsDaily() ? QUEST_DAILY : QUEST_WEEKLY; int32 currType = quest->IsDaily() ? QUEST_DAILY : QUEST_WEEKLY; if (poolTypeMap[pool_id] != currType) { SF_LOG_ERROR("sql.sql", "`pool_quest` quest %u is %s but pool (%u) is specified for %s, mixing not allowed, skipped.", entry, currType == QUEST_DAILY ? "QUEST_DAILY" : "QUEST_WEEKLY", pool_id, poolTypeMap[pool_id] == QUEST_DAILY ? "QUEST_DAILY" : "QUEST_WEEKLY"); continue; } creBounds = mQuestCreatureRelation.equal_range(entry); goBounds = mQuestGORelation.equal_range(entry); if (creBounds.first == creBounds.second && goBounds.first == goBounds.second) { SF_LOG_ERROR("sql.sql", "`pool_quest` lists entry (%u) as member of pool (%u) but is not started anywhere, skipped.", entry, pool_id); continue; } PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id]; PoolObject plObject = PoolObject(entry, 0.0f); PoolGroup<Quest>& questgroup = mPoolQuestGroups[pool_id]; questgroup.SetPoolId(pool_id); questgroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(entry, pool_id); mQuestSearchMap.insert(p); ++count; } while (result->NextRow()); SF_LOG_INFO("server.loading", ">> Loaded %u quests in pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks SF_LOG_INFO("server.loading", "Starting objects pooling system..."); { uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.Query("SELECT DISTINCT pool_template.entry, pool_pool.pool_id, pool_pool.mother_pool FROM pool_template" " LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry" " LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL"); if (!result) { SF_LOG_INFO("server.loading", ">> Pool handling system initialized, 0 pools spawned."); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 pool_entry = fields[0].GetUInt32(); uint32 pool_pool_id = fields[1].GetUInt32(); if (!CheckPool(pool_entry)) { if (pool_pool_id) // The pool is a child pool in pool_pool table. Ideally we should remove it from the pool handler to ensure it never gets spawned, // however that could recursively invalidate entire chain of mother pools. It can be done in the future but for now we'll do nothing. SF_LOG_ERROR("sql.sql", "Pool Id %u has no equal chance pooled entites defined and explicit chance sum is not 100. This broken pool is a child pool of Id %u and cannot be safely removed.", pool_entry, fields[2].GetUInt32()); else SF_LOG_ERROR("sql.sql", "Pool Id %u has no equal chance pooled entites defined and explicit chance sum is not 100. The pool will not be spawned.", pool_entry); continue; } // Don't spawn child pools, they are spawned recursively by their parent pools if (!pool_pool_id) { SpawnPool(pool_entry); count++; } } while (result->NextRow()); SF_LOG_DEBUG("pool", "Pool handling system initialized, %u pools spawned in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } }