//.........这里部分代码省略.........
}
// do not process players which are not in world
if (!pl->IsInWorld())
continue;
// check if target is globally visible for player
if (!pl->IsVisibleGloballyFor(_player))
continue;
// check if target's level is in level range
uint32 lvl = pl->getLevel();
if (lvl < level_min || lvl > level_max)
continue;
// check if class matches classmask
uint32 class_ = pl->getClass();
if (!(classmask & (1 << class_)))
continue;
// check if race matches racemask
uint32 race = pl->getRace();
if (!(racemask & (1 << race)))
continue;
uint32 pzoneid = pl->GetZoneId();
bool z_show = true;
for (uint32 i = 0; i < zones_count; ++i)
{
if (zoneids[i] == pzoneid)
{
z_show = true;
break;
}
z_show = false;
}
if (!z_show)
continue;
std::string pname = pl->GetName();
std::wstring wpname;
if (!Utf8toWStr(pname, wpname))
continue;
wstrToLower(wpname);
if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos))
continue;
std::string gname = sGuildMgr.GetGuildNameById(pl->GetGuildId());
std::wstring wgname;
if (!Utf8toWStr(gname, wgname))
continue;
wstrToLower(wgname);
if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos))
continue;
std::string aname;
if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(pzoneid))
aname = areaEntry->area_name[GetSessionDbcLocale()];
bool s_show = true;
for (uint32 i = 0; i < str_count; ++i)
{
if (!str[i].empty())
{
if (wgname.find(str[i]) != std::wstring::npos ||
wpname.find(str[i]) != std::wstring::npos ||
Utf8FitTo(aname, str[i]))
{
s_show = true;
break;
}
s_show = false;
}
}
if (!s_show)
continue;
data << pname; // player name
data << gname; // guild name
data << uint32(lvl); // player level
data << uint32(class_); // player class
data << uint32(race); // player race
data << uint32(pzoneid); // player zone id
// 50 is maximum player count sent to client
if ((++clientcount) == 49)
break;
}
uint32 count = m.size();
data.put(0, clientcount); // insert right count, listed count
data.put(4, count > 49 ? count : clientcount); // insert right count, online count
SendPacket(&data);
DEBUG_LOG("WORLD: Send SMSG_WHO Message");
}
static bool HandleGroupListCommand(ChatHandler* handler, char const* args)
{
// Get ALL the variables!
Player* playerTarget;
uint32 phase = 0;
uint64 guidTarget;
std::string nameTarget;
std::string zoneName;
const char* onlineState = "";
// Parse the guid to uint32...
uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER);
// ... and try to extract a player out of it.
if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget))
{
playerTarget = sObjectMgr->GetPlayerByLowGUID(parseGUID);
guidTarget = parseGUID;
}
// If not, we return false and end right away.
else if (!handler->extractPlayerTarget((char*)args, &playerTarget, &guidTarget, &nameTarget))
return false;
// Next, we need a group. So we define a group variable.
Group* groupTarget = NULL;
// We try to extract a group from an online player.
if (playerTarget)
groupTarget = playerTarget->GetGroup();
// If not, we extract it from the SQL.
if (!groupTarget)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER);
stmt->setUInt32(0, guidTarget);
PreparedQueryResult resultGroup = CharacterDatabase.Query(stmt);
if (resultGroup)
groupTarget = sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32());
}
// If both fails, players simply has no party. Return false.
if (!groupTarget)
{
handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, nameTarget.c_str());
handler->SetSentErrorMessage(true);
return false;
}
// We get the group members after successfully detecting a group.
Group::MemberSlotList const& members = groupTarget->GetMemberSlots();
// To avoid a cluster fuck, namely trying multiple queries to simply get a group member count...
handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "raid" : "party"), members.size());
// ... we simply move the group type and member count print after retrieving the slots and simply output it's size.
// While rather dirty codestyle-wise, it saves space (if only a little). For each member, we look several informations up.
for (Group::MemberSlotList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
{
// Define temporary variable slot to iterator.
Group::MemberSlot const& slot = *itr;
// Check for given flag and assign it to that iterator
std::string flags;
if (slot.flags & MEMBER_FLAG_ASSISTANT)
flags = "Assistant";
if (slot.flags & MEMBER_FLAG_MAINTANK)
{
if (!flags.empty())
flags.append(", ");
flags.append("MainTank");
}
if (slot.flags & MEMBER_FLAG_MAINASSIST)
{
if (!flags.empty())
flags.append(", ");
flags.append("MainAssist");
}
if (flags.empty())
flags = "None";
// Check if iterator is online. If is...
Player* p = ObjectAccessor::FindPlayer((*itr).guid);
if (p && p->IsInWorld())
{
// ... than, it prints information like "is online", where he is, etc...
onlineState = "online";
phase = (!p->IsGameMaster() ? p->GetPhaseMask() : -1);
uint32 locale = handler->GetSessionDbcLocale();
AreaTableEntry const* area = GetAreaEntryByAreaID(p->GetAreaId());
if (area)
{
AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
if (zone)
zoneName = zone->area_name[locale];
}
}
//.........这里部分代码省略.........
// Get water state on map
GridMapLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, GridMapLiquidData *data)
{
// Check water type (if no water return)
if (!m_liquidFlags && !m_liquidType)
return LIQUID_MAP_NO_WATER;
// Get cell
float cx = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
float cy = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
int x_int = (int)cx & (MAP_RESOLUTION - 1);
int y_int = (int)cy & (MAP_RESOLUTION - 1);
// Check water type in cell
int idx = (x_int>>3)*16 + (y_int>>3);
uint8 type = m_liquidFlags ? m_liquidFlags[idx] : m_liquidType;
uint32 entry = 0;
if (m_liquidEntry)
{
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(m_liquidEntry[idx]))
{
entry = liquidEntry->Id;
type &= MAP_LIQUID_TYPE_DARK_WATER;
uint32 liqTypeIdx = liquidEntry->Type;
if (entry < 21)
{
if (AreaTableEntry const* area = sAreaStore.LookupEntry(getArea(x, y)))
{
uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
if (!overrideLiquid && area->zone)
{
area = GetAreaEntryByAreaID(area->zone);
if (area)
overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
}
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
{
entry = overrideLiquid;
liqTypeIdx = liq->Type;
}
}
}
type |= 1 << liqTypeIdx;
}
}
if (type == 0)
return LIQUID_MAP_NO_WATER;
// Check req liquid type mask
if (ReqLiquidType && !(ReqLiquidType & type))
return LIQUID_MAP_NO_WATER;
// Check water level:
// Check water height map
int lx_int = x_int - m_liquid_offY;
if (lx_int < 0 || lx_int >= m_liquid_height)
return LIQUID_MAP_NO_WATER;
int ly_int = y_int - m_liquid_offX;
if (ly_int < 0 || ly_int >= m_liquid_width)
return LIQUID_MAP_NO_WATER;
// Get water level
float liquid_level = m_liquid_map ? m_liquid_map[lx_int * m_liquid_width + ly_int] : m_liquidLevel;
// Get ground level (sub 0.2 for fix some errors)
float ground_level = getHeight(x, y);
// Check water level and ground level
if (liquid_level < ground_level || z < ground_level - 2)
return LIQUID_MAP_NO_WATER;
// All ok in water -> store data
if (data)
{
data->entry = entry;
data->type_flags = type;
data->level = liquid_level;
data->depth_level = ground_level;
}
// For speed check as int values
int delta = int((liquid_level - z) * 10);
// Get position delta
if (delta > 20) // Under water
return LIQUID_MAP_UNDER_WATER;
if (delta > 0) // In water
return LIQUID_MAP_IN_WATER;
if (delta > -1) // Walk on water
return LIQUID_MAP_WATER_WALK;
// Above water
return LIQUID_MAP_ABOVE_WATER;
}
//.........这里部分代码省略.........
(*iter)->AddPassenger(plrMover);
break;
}
}
if (!foundNewTransport)
{
plrMover->m_transport = NULL;
movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
movementInfo.t_time = 0;
movementInfo.t_seat = -1;
}
}
}
if (!mover->GetTransport() && !mover->GetVehicle())
{
GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid);
if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
movementInfo.t_guid = 0;
}
}
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
{
plrMover->m_transport->RemovePassenger(plrMover);
plrMover->m_transport = NULL;
movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
movementInfo.t_time = 0;
movementInfo.t_seat = -1;
movementInfo.t_guid = 0LL;
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == CMSG_MOVE_FALL_LAND && plrMover && !plrMover->isInFlight())
{
plrMover->HandleFall(movementInfo);
}
if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
{
// now client not include swimming flag in case jumping under water
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
}
// Hack Fix, clean emotes when moving
if (plrMover && plrMover->GetLastPlayedEmote())
plrMover->HandleEmoteCommand(0);
//if (plrMover)
// sAnticheatMgr->StartHackDetection(plrMover, movementInfo, opcode);
uint32 mstime = getMSTime();
if (m_clientTimeDelay == 0)
m_clientTimeDelay = mstime - movementInfo.time;
movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY;
movementInfo.guid = mover->GetGUID();
mover->m_movementInfo = movementInfo;
// this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
if (mover->GetVehicle())
{
mover->SetOrientation(movementInfo.pos.GetOrientation());
return;
}
mover->UpdatePosition(movementInfo.pos);
/* process position-change */
WorldPacket data(SMSG_MOVE_UPDATE, recvPacket.size());
//movementInfo.Alive32 = movementInfo.time; // hack, but it's work in 505 in this way ...
mover->WriteMovementInfo(data);
mover->SendMessageToSet(&data, _player);
if (plrMover) // nothing is charmed, or player charmed
{
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId());
float depth = zone ? zone->MaxDepth : -500.0f;
if (movementInfo.pos.GetPositionZ() < depth)
{
if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
{
// NOTE: this is actually called many times while falling
// even after the player has been teleported away
// TODO: discard movement packets after the player is rooted
if (plrMover->isAlive())
{
plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
// player can be alive if GM/etc
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
if (!plrMover->isAlive())
plrMover->KillPlayer();
}
}
}
}
}
//.........这里部分代码省略.........
continue;
}
if ((temp.spell_hit.schoolMask & pSpell->SchoolMask) != pSpell->SchoolMask)
sLog.outErrorEventAI("Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.spell_hit.schoolMask, i);
}
if (!temp.spell_hit.schoolMask)
sLog.outErrorEventAI("Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.spell_hit.schoolMask, i);
if (temp.spell_hit.repeatMax < temp.spell_hit.repeatMin)
sLog.outErrorEventAI("Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
break;
case EVENT_T_RANGE:
if (temp.range.maxDist < temp.range.minDist)
sLog.outErrorEventAI("Creature %u are using event(%u) with param2 < param1 (MaxDist < MinDist). Event will never repeat.", temp.creature_id, i);
if (temp.range.repeatMax < temp.range.repeatMin)
sLog.outErrorEventAI("Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
break;
case EVENT_T_OOC_LOS:
if (temp.ooc_los.repeatMax < temp.ooc_los.repeatMin)
sLog.outErrorEventAI("Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
break;
case EVENT_T_SPAWNED:
switch (temp.spawned.condition)
{
case SPAWNED_EVENT_ALWAY:
break;
case SPAWNED_EVENT_MAP:
if (!sMapStore.LookupEntry(temp.spawned.conditionValue1))
sLog.outErrorEventAI("Creature %u are using spawned event(%u) with param1 = %u 'map specific' but map (param2: %u) does not exist. Event will never repeat.", temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1);
break;
case SPAWNED_EVENT_ZONE:
if (!GetAreaEntryByAreaID(temp.spawned.conditionValue1))
sLog.outErrorEventAI("Creature %u are using spawned event(%u) with param1 = %u 'area specific' but area (param2: %u) does not exist. Event will never repeat.", temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1);
break;
default:
sLog.outErrorEventAI("Creature %u are using invalid spawned event %u mode (%u) in param1", temp.creature_id, i, temp.spawned.condition);
break;
}
break;
case EVENT_T_FRIENDLY_HP:
if (temp.friendly_hp.repeatMax < temp.friendly_hp.repeatMin)
sLog.outErrorEventAI("Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
break;
case EVENT_T_FRIENDLY_IS_CC:
if (temp.friendly_is_cc.repeatMax < temp.friendly_is_cc.repeatMin)
sLog.outErrorEventAI("Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
break;
case EVENT_T_FRIENDLY_MISSING_BUFF:
{
SpellEntry const* pSpell = sSpellStore.LookupEntry(temp.friendly_buff.spellId);
if (!pSpell)
{
sLog.outErrorEventAI("Creature %u has nonexistent SpellID(%u) defined in event %u.", temp.creature_id, temp.friendly_buff.spellId, i);
continue;
}
if (temp.friendly_buff.radius <= 0)
{
sLog.outErrorEventAI("Creature %u has wrong radius (%u) for EVENT_T_FRIENDLY_MISSING_BUFF defined in event %u.", temp.creature_id, temp.friendly_buff.radius, i);
continue;
}
if (temp.friendly_buff.repeatMax < temp.friendly_buff.repeatMin)
sLog.outErrorEventAI("Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
break;
}
//.........这里部分代码省略.........
{
plrMover->m_transport = transport;
transport->AddPassenger(plrMover);
}
}
else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid)
{
bool foundNewTransport = false;
plrMover->m_transport->RemovePassenger(plrMover);
if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
{
foundNewTransport = true;
plrMover->m_transport = transport;
transport->AddPassenger(plrMover);
}
if (!foundNewTransport)
{
plrMover->m_transport = NULL;
movementInfo.ResetTransport();
}
}
}
if (!mover->GetTransport() && !mover->GetVehicle())
{
GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
movementInfo.transport.guid = 0;
}
}
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
{
plrMover->m_transport->RemovePassenger(plrMover);
plrMover->m_transport = NULL;
movementInfo.ResetTransport();
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
plrMover->HandleFall(movementInfo);
if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
{
// now client not include swimming flag in case jumping under water
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
}
uint32 mstime = getMSTime();
/*----------------------*/
if (m_clientTimeDelay == 0)
m_clientTimeDelay = mstime - movementInfo.time;
/* process position-change */
movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY;
movementInfo.guid = mover->GetGUID();
mover->m_movementInfo = movementInfo;
/*----------------------*/
/* process position-change */
// this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
if (mover->GetVehicle())
{
mover->SetOrientation(movementInfo.pos.GetOrientation());
return;
}
mover->UpdatePosition(movementInfo.pos);
WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size());
mover->WriteMovementInfo(data);
mover->SendMessageToSet(&data, _player);
if (plrMover) // nothing is charmed, or player charmed
{
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId());
float depth = zone ? zone->MaxDepth : -500.0f;
if (movementInfo.pos.GetPositionZ() < depth)
{
if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
{
// NOTE: this is actually called many times while falling
// even after the player has been teleported away
/// @todo discard movement packets after the player is rooted
if (plrMover->IsAlive())
{
plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
// player can be alive if GM/etc
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
if (!plrMover->IsAlive())
plrMover->KillPlayer();
}
}
}
}
}
请发表评论