[svn] * Updated to 6743 and 685
Moved language id used by Arena to a higher place to solve conflicts Added the empty script folders --HG-- branch : trunk rename : 6731-680 => 6743-685
This commit is contained in:
@@ -47,7 +47,7 @@ AggressorAI::MoveInLineOfSight(Unit *u)
|
||||
if( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
|
||||
return;
|
||||
|
||||
if( !i_creature.getVictim() && !i_creature.hasUnitState(UNIT_STAT_STUNDED) && u->isTargetableForAttack() &&
|
||||
if( !i_creature.getVictim() && !i_creature.hasUnitState(UNIT_STAT_STUNNED) && u->isTargetableForAttack() &&
|
||||
( i_creature.IsHostileTo( u ) /*|| u->getVictim() && i_creature.IsFriendlyTo( u->getVictim() )*/ ) &&
|
||||
u->isInAccessablePlaceFor(&i_creature) )
|
||||
{
|
||||
|
||||
+463
-462
@@ -1,462 +1,463 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "WorldSession.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Log.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Player.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "World.h"
|
||||
#include "SocialMgr.h"
|
||||
|
||||
void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("MSG_INSPECT_ARENA_TEAMS");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 8);
|
||||
|
||||
uint64 guid;
|
||||
recv_data >> guid;
|
||||
sLog.outDebug("Inspect Arena stats " I64FMTD, guid);
|
||||
|
||||
if(Player *plr = objmgr.GetPlayer(guid))
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ARENA_SLOT; i++)
|
||||
{
|
||||
if(uint32 a_id = plr->GetArenaTeamId(i))
|
||||
{
|
||||
if(ArenaTeam *at = objmgr.GetArenaTeamById(a_id))
|
||||
at->InspectStats(this, plr->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_QUERY" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId;
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!arenateam) // arena team not found
|
||||
return;
|
||||
|
||||
arenateam->Query(this);
|
||||
arenateam->Stats(this);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_ROSTER" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!arenateam)
|
||||
return;
|
||||
|
||||
arenateam->Roster(this);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
std::string Invitedname;
|
||||
|
||||
Player * player = NULL;
|
||||
|
||||
recv_data >> ArenaTeamId >> Invitedname;
|
||||
|
||||
if(!Invitedname.empty())
|
||||
{
|
||||
if(!normalizePlayerName(Invitedname))
|
||||
return;
|
||||
|
||||
player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str());
|
||||
}
|
||||
|
||||
if(!player)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
//SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
// can't find related opcode
|
||||
SendNotification("%s is not high enough level to join your team", player->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!arenateam)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM);
|
||||
return;
|
||||
}
|
||||
|
||||
// OK result but not send invite
|
||||
if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
|
||||
return;
|
||||
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamId(arenateam->GetSlot()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(arenateam->GetMembersSize() >= arenateam->GetType() * 2)
|
||||
{
|
||||
// should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL
|
||||
// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL);
|
||||
SendNotification("Your arena team is full, %s cannot join it.", player->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
sLog.outDebug("Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), Invitedname.c_str());
|
||||
|
||||
player->SetArenaTeamIdInvited(arenateam->GetId());
|
||||
|
||||
WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10));
|
||||
data << GetPlayer()->GetName();
|
||||
data << arenateam->GetName();
|
||||
player->GetSession()->SendPacket(&data);
|
||||
|
||||
sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_INVITE");
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_INVITE_ACCEPT"); // empty opcode
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited());
|
||||
if(!at)
|
||||
{
|
||||
// arena team not exist
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamId(at->GetSlot()))
|
||||
{
|
||||
// already in arena team that size
|
||||
return;
|
||||
}
|
||||
|
||||
// not let enemies sign petition
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain()))
|
||||
return;
|
||||
|
||||
if(!at->AddMember(_player->GetGUID()))
|
||||
return;
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_JOIN_SS, 2, _player->GetName(), at->GetName(), "");
|
||||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamInviteDeclineOpcode(WorldPacket & /*recv_data*/)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_INVITE_DECLINE"); // empty opcode
|
||||
|
||||
_player->SetArenaTeamIdInvited(0); // no more invited
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_LEAVE");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// send command result
|
||||
return;
|
||||
}
|
||||
if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1)
|
||||
{
|
||||
// check for correctness
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
return;
|
||||
}
|
||||
// arena team has only one member (=captain)
|
||||
if(_player->GetGUID() == at->GetCaptain())
|
||||
{
|
||||
at->Disband(this);
|
||||
delete at;
|
||||
return;
|
||||
}
|
||||
|
||||
at->DelMember(_player->GetGUID());
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEAVE_SS, 2, _player->GetName(), at->GetName(), "");
|
||||
at->BroadcastPacket(&data);
|
||||
|
||||
//SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_DISBAND");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
at->Disband(this);
|
||||
delete at;
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_REMOVE_FROM_TEAM");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
uint32 ArenaTeamId;
|
||||
std::string name;
|
||||
|
||||
recv_data >> ArenaTeamId;
|
||||
recv_data >> name;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid = objmgr.GetPlayerGUIDByName(name);
|
||||
if(!guid)
|
||||
{
|
||||
// player guid not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == guid)
|
||||
{
|
||||
// unsure
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == guid)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
return;
|
||||
}
|
||||
|
||||
at->DelMember(guid);
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_REMOVE_SSS, 3, name, at->GetName(), _player->GetName());
|
||||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_PROMOTE_TO_CAPTAIN");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
uint32 ArenaTeamId;
|
||||
std::string name;
|
||||
|
||||
recv_data >> ArenaTeamId;
|
||||
recv_data >> name;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid = objmgr.GetPlayerGUIDByName(name);
|
||||
if(!guid)
|
||||
{
|
||||
// player guid not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == guid)
|
||||
{
|
||||
// target player already captain
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
at->SetCaptain(guid);
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEADER_CHANGED_SSS, 3, _player->GetName(), name, at->GetName());
|
||||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3)
|
||||
{
|
||||
WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4);
|
||||
data << unk1;
|
||||
data << str1;
|
||||
data << str2;
|
||||
data << unk3;
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3)
|
||||
{
|
||||
data->Initialize(SMSG_ARENA_TEAM_EVENT, 1+1+1);
|
||||
*data << eventid;
|
||||
*data << str_count;
|
||||
switch(str_count)
|
||||
{
|
||||
case 1:
|
||||
*data << str1;
|
||||
break;
|
||||
case 2:
|
||||
*data << str1;
|
||||
*data << str2;
|
||||
break;
|
||||
case 3:
|
||||
*data << str1;
|
||||
*data << str2;
|
||||
*data << str3;
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Unhandled str_count %u in SendArenaTeamEvent()", str_count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::SendNotInArenaTeamPacket(uint8 type)
|
||||
{
|
||||
WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team
|
||||
uint32 unk = 0;
|
||||
data << uint32(unk); // unk(0)
|
||||
if(!unk)
|
||||
data << uint8(type); // team type (2=2v2,3=3v3,5=5v5), can be used for custom types...
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
/*
|
||||
+ERR_ARENA_NO_TEAM_II "You are not in a %dv%d arena team"
|
||||
|
||||
+ERR_ARENA_TEAM_CREATE_S "%s created. To disband, use /teamdisband [2v2, 3v3, 5v5]."
|
||||
+ERR_ARENA_TEAM_INVITE_SS "You have invited %s to join %s"
|
||||
+ERR_ARENA_TEAM_QUIT_S "You are no longer a member of %s"
|
||||
ERR_ARENA_TEAM_FOUNDER_S "Congratulations, you are a founding member of %s! To leave, use /teamquit [2v2, 3v3, 5v5]."
|
||||
|
||||
+ERR_ARENA_TEAM_INTERNAL "Internal arena team error"
|
||||
+ERR_ALREADY_IN_ARENA_TEAM "You are already in an arena team of that size"
|
||||
+ERR_ALREADY_IN_ARENA_TEAM_S "%s is already in an arena team of that size"
|
||||
+ERR_INVITED_TO_ARENA_TEAM "You have already been invited into an arena team"
|
||||
+ERR_ALREADY_INVITED_TO_ARENA_TEAM_S "%s has already been invited to an arena team"
|
||||
+ERR_ARENA_TEAM_NAME_INVALID "That name contains invalid characters, please enter a new name"
|
||||
+ERR_ARENA_TEAM_NAME_EXISTS_S "There is already an arena team named \"%s\""
|
||||
+ERR_ARENA_TEAM_LEADER_LEAVE_S "You must promote a new team captain using /teamcaptain before leaving the team"
|
||||
+ERR_ARENA_TEAM_PERMISSIONS "You don't have permission to do that"
|
||||
+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM "You are not in an arena team of that size"
|
||||
+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS "%s is not in %s"
|
||||
+ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S "\"%s\" not found"
|
||||
+ERR_ARENA_TEAM_NOT_ALLIED "You cannot invite players from the opposing alliance"
|
||||
|
||||
+ERR_ARENA_TEAM_JOIN_SS "%s has joined %s"
|
||||
+ERR_ARENA_TEAM_YOU_JOIN_S "You have joined %s. To leave, use /teamquit [2v2, 3v3, 5v5]."
|
||||
|
||||
+ERR_ARENA_TEAM_LEAVE_SS "%s has left %s"
|
||||
|
||||
+ERR_ARENA_TEAM_LEADER_IS_SS "%s is the captain of %s"
|
||||
+ERR_ARENA_TEAM_LEADER_CHANGED_SSS "%s has made %s the new captain of %s"
|
||||
|
||||
+ERR_ARENA_TEAM_REMOVE_SSS "%s has been kicked out of %s by %s"
|
||||
|
||||
+ERR_ARENA_TEAM_DISBANDED_S "%s has disbanded %s"
|
||||
|
||||
ERR_ARENA_TEAM_TARGET_TOO_LOW_S "%s is not high enough level to join your team"
|
||||
|
||||
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S "%s is full"
|
||||
|
||||
ERR_ARENA_TEAM_LEVEL_TOO_LOW_I "You must be level %d to form an arena team"
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "WorldSession.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Log.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Player.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "World.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "Language.h"
|
||||
|
||||
void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("MSG_INSPECT_ARENA_TEAMS");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 8);
|
||||
|
||||
uint64 guid;
|
||||
recv_data >> guid;
|
||||
sLog.outDebug("Inspect Arena stats " I64FMTD, guid);
|
||||
|
||||
if(Player *plr = objmgr.GetPlayer(guid))
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ARENA_SLOT; i++)
|
||||
{
|
||||
if(uint32 a_id = plr->GetArenaTeamId(i))
|
||||
{
|
||||
if(ArenaTeam *at = objmgr.GetArenaTeamById(a_id))
|
||||
at->InspectStats(this, plr->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_QUERY" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId;
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!arenateam) // arena team not found
|
||||
return;
|
||||
|
||||
arenateam->Query(this);
|
||||
arenateam->Stats(this);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_ROSTER" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!arenateam)
|
||||
return;
|
||||
|
||||
arenateam->Roster(this);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
std::string Invitedname;
|
||||
|
||||
Player * player = NULL;
|
||||
|
||||
recv_data >> ArenaTeamId >> Invitedname;
|
||||
|
||||
if(!Invitedname.empty())
|
||||
{
|
||||
if(!normalizePlayerName(Invitedname))
|
||||
return;
|
||||
|
||||
player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str());
|
||||
}
|
||||
|
||||
if(!player)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
//SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
// can't find related opcode
|
||||
SendNotification(LANG_HIS_ARENA_LEVEL_REQ_ERROR, player->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!arenateam)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM);
|
||||
return;
|
||||
}
|
||||
|
||||
// OK result but not send invite
|
||||
if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
|
||||
return;
|
||||
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamId(arenateam->GetSlot()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(arenateam->GetMembersSize() >= arenateam->GetType() * 2)
|
||||
{
|
||||
// should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL
|
||||
// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL);
|
||||
SendNotification(LANG_YOUR_ARENA_TEAM_FULL, player->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
sLog.outDebug("Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), Invitedname.c_str());
|
||||
|
||||
player->SetArenaTeamIdInvited(arenateam->GetId());
|
||||
|
||||
WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10));
|
||||
data << GetPlayer()->GetName();
|
||||
data << arenateam->GetName();
|
||||
player->GetSession()->SendPacket(&data);
|
||||
|
||||
sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_INVITE");
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_INVITE_ACCEPT"); // empty opcode
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited());
|
||||
if(!at)
|
||||
{
|
||||
// arena team not exist
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamId(at->GetSlot()))
|
||||
{
|
||||
// already in arena team that size
|
||||
return;
|
||||
}
|
||||
|
||||
// not let enemies sign petition
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain()))
|
||||
return;
|
||||
|
||||
if(!at->AddMember(_player->GetGUID()))
|
||||
return;
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_JOIN_SS, 2, _player->GetName(), at->GetName(), "");
|
||||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamInviteDeclineOpcode(WorldPacket & /*recv_data*/)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_INVITE_DECLINE"); // empty opcode
|
||||
|
||||
_player->SetArenaTeamIdInvited(0); // no more invited
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_LEAVE");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// send command result
|
||||
return;
|
||||
}
|
||||
if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1)
|
||||
{
|
||||
// check for correctness
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
return;
|
||||
}
|
||||
// arena team has only one member (=captain)
|
||||
if(_player->GetGUID() == at->GetCaptain())
|
||||
{
|
||||
at->Disband(this);
|
||||
delete at;
|
||||
return;
|
||||
}
|
||||
|
||||
at->DelMember(_player->GetGUID());
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEAVE_SS, 2, _player->GetName(), at->GetName(), "");
|
||||
at->BroadcastPacket(&data);
|
||||
|
||||
//SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_DISBAND");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 ArenaTeamId; // arena team id
|
||||
recv_data >> ArenaTeamId;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
at->Disband(this);
|
||||
delete at;
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_REMOVE_FROM_TEAM");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
uint32 ArenaTeamId;
|
||||
std::string name;
|
||||
|
||||
recv_data >> ArenaTeamId;
|
||||
recv_data >> name;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid = objmgr.GetPlayerGUIDByName(name);
|
||||
if(!guid)
|
||||
{
|
||||
// player guid not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == guid)
|
||||
{
|
||||
// unsure
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == guid)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
return;
|
||||
}
|
||||
|
||||
at->DelMember(guid);
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_REMOVE_SSS, 3, name, at->GetName(), _player->GetName());
|
||||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_PROMOTE_TO_CAPTAIN");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
uint32 ArenaTeamId;
|
||||
std::string name;
|
||||
|
||||
recv_data >> ArenaTeamId;
|
||||
recv_data >> name;
|
||||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid = objmgr.GetPlayerGUIDByName(name);
|
||||
if(!guid)
|
||||
{
|
||||
// player guid not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == guid)
|
||||
{
|
||||
// target player already captain
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
at->SetCaptain(guid);
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEADER_CHANGED_SSS, 3, _player->GetName(), name, at->GetName());
|
||||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3)
|
||||
{
|
||||
WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4);
|
||||
data << unk1;
|
||||
data << str1;
|
||||
data << str2;
|
||||
data << unk3;
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3)
|
||||
{
|
||||
data->Initialize(SMSG_ARENA_TEAM_EVENT, 1+1+1);
|
||||
*data << eventid;
|
||||
*data << str_count;
|
||||
switch(str_count)
|
||||
{
|
||||
case 1:
|
||||
*data << str1;
|
||||
break;
|
||||
case 2:
|
||||
*data << str1;
|
||||
*data << str2;
|
||||
break;
|
||||
case 3:
|
||||
*data << str1;
|
||||
*data << str2;
|
||||
*data << str3;
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Unhandled str_count %u in SendArenaTeamEvent()", str_count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::SendNotInArenaTeamPacket(uint8 type)
|
||||
{
|
||||
WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team
|
||||
uint32 unk = 0;
|
||||
data << uint32(unk); // unk(0)
|
||||
if(!unk)
|
||||
data << uint8(type); // team type (2=2v2,3=3v3,5=5v5), can be used for custom types...
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
/*
|
||||
+ERR_ARENA_NO_TEAM_II "You are not in a %dv%d arena team"
|
||||
|
||||
+ERR_ARENA_TEAM_CREATE_S "%s created. To disband, use /teamdisband [2v2, 3v3, 5v5]."
|
||||
+ERR_ARENA_TEAM_INVITE_SS "You have invited %s to join %s"
|
||||
+ERR_ARENA_TEAM_QUIT_S "You are no longer a member of %s"
|
||||
ERR_ARENA_TEAM_FOUNDER_S "Congratulations, you are a founding member of %s! To leave, use /teamquit [2v2, 3v3, 5v5]."
|
||||
|
||||
+ERR_ARENA_TEAM_INTERNAL "Internal arena team error"
|
||||
+ERR_ALREADY_IN_ARENA_TEAM "You are already in an arena team of that size"
|
||||
+ERR_ALREADY_IN_ARENA_TEAM_S "%s is already in an arena team of that size"
|
||||
+ERR_INVITED_TO_ARENA_TEAM "You have already been invited into an arena team"
|
||||
+ERR_ALREADY_INVITED_TO_ARENA_TEAM_S "%s has already been invited to an arena team"
|
||||
+ERR_ARENA_TEAM_NAME_INVALID "That name contains invalid characters, please enter a new name"
|
||||
+ERR_ARENA_TEAM_NAME_EXISTS_S "There is already an arena team named \"%s\""
|
||||
+ERR_ARENA_TEAM_LEADER_LEAVE_S "You must promote a new team captain using /teamcaptain before leaving the team"
|
||||
+ERR_ARENA_TEAM_PERMISSIONS "You don't have permission to do that"
|
||||
+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM "You are not in an arena team of that size"
|
||||
+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS "%s is not in %s"
|
||||
+ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S "\"%s\" not found"
|
||||
+ERR_ARENA_TEAM_NOT_ALLIED "You cannot invite players from the opposing alliance"
|
||||
|
||||
+ERR_ARENA_TEAM_JOIN_SS "%s has joined %s"
|
||||
+ERR_ARENA_TEAM_YOU_JOIN_S "You have joined %s. To leave, use /teamquit [2v2, 3v3, 5v5]."
|
||||
|
||||
+ERR_ARENA_TEAM_LEAVE_SS "%s has left %s"
|
||||
|
||||
+ERR_ARENA_TEAM_LEADER_IS_SS "%s is the captain of %s"
|
||||
+ERR_ARENA_TEAM_LEADER_CHANGED_SSS "%s has made %s the new captain of %s"
|
||||
|
||||
+ERR_ARENA_TEAM_REMOVE_SSS "%s has been kicked out of %s by %s"
|
||||
|
||||
+ERR_ARENA_TEAM_DISBANDED_S "%s has disbanded %s"
|
||||
|
||||
ERR_ARENA_TEAM_TARGET_TOO_LOW_S "%s is not high enough level to join your team"
|
||||
|
||||
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S "%s is full"
|
||||
|
||||
ERR_ARENA_TEAM_LEVEL_TOO_LOW_I "You must be level %d to form an arena team"
|
||||
*/
|
||||
|
||||
+952
-952
File diff suppressed because it is too large
Load Diff
+1066
-1065
File diff suppressed because it is too large
Load Diff
+23
-16
@@ -353,6 +353,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
||||
|
||||
static ChatCommand gmCommandTable[] =
|
||||
{
|
||||
{ "chat", SEC_MODERATOR, &ChatHandler::HandleGMChatCommand, "", NULL },
|
||||
{ "list", SEC_PLAYER, &ChatHandler::HandleGMListCommand, "", NULL },
|
||||
{ "visible", SEC_MODERATOR, &ChatHandler::HandleVisibleCommand, "", NULL },
|
||||
{ "fly", SEC_ADMINISTRATOR, &ChatHandler::HandleFlyModeCommand, "", NULL },
|
||||
@@ -507,18 +508,29 @@ const char *ChatHandler::GetMangosString(int32 entry)
|
||||
return m_session->GetMangosString(entry);
|
||||
}
|
||||
|
||||
bool ChatHandler::hasStringAbbr(const char* s1, const char* s2)
|
||||
bool ChatHandler::hasStringAbbr(const char* name, const char* part)
|
||||
{
|
||||
for(;;)
|
||||
// non "" command
|
||||
if( *name )
|
||||
{
|
||||
if( !*s2 )
|
||||
return true;
|
||||
else if( !*s1 )
|
||||
// "" part from non-"" command
|
||||
if( !*part )
|
||||
return false;
|
||||
else if( tolower( *s1 ) != tolower( *s2 ) )
|
||||
return false;
|
||||
++s1; ++s2;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if( !*part )
|
||||
return true;
|
||||
else if( !*name )
|
||||
return false;
|
||||
else if( tolower( *name ) != tolower( *part ) )
|
||||
return false;
|
||||
++name; ++part;
|
||||
}
|
||||
}
|
||||
// allow with any for ""
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChatHandler::SendSysMessage(const char *str)
|
||||
@@ -594,13 +606,9 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, st
|
||||
|
||||
while (*text == ' ') ++text;
|
||||
|
||||
if(!cmd.length())
|
||||
return false;
|
||||
|
||||
for(uint32 i = 0; table[i].Name != NULL; i++)
|
||||
{
|
||||
// allow pass "" command name in table
|
||||
if(strlen(table[i].Name) && !hasStringAbbr(table[i].Name, cmd.c_str()))
|
||||
if( !hasStringAbbr(table[i].Name, cmd.c_str()) )
|
||||
continue;
|
||||
|
||||
// select subcommand from child commands list
|
||||
@@ -688,8 +696,7 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand *table, char const* cmd, ch
|
||||
if(m_session->GetSecurity() < table[i].SecurityLevel)
|
||||
continue;
|
||||
|
||||
if(strlen(table[i].Name) && !hasStringAbbr(table[i].Name, subcmd))
|
||||
continue;
|
||||
if( !hasStringAbbr(table[i].Name, subcmd) )
|
||||
|
||||
(list += "\n ") += table[i].Name;
|
||||
}
|
||||
@@ -717,7 +724,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand *table, const char* cmd)
|
||||
if(m_session->GetSecurity() < table[i].SecurityLevel)
|
||||
continue;
|
||||
|
||||
if(strlen(table[i].Name) && !hasStringAbbr(table[i].Name, cmd))
|
||||
if( !hasStringAbbr(table[i].Name, cmd) )
|
||||
continue;
|
||||
|
||||
// have subcommand
|
||||
|
||||
+2
-1
@@ -69,7 +69,7 @@ class ChatHandler
|
||||
int ParseCommands(const char* text);
|
||||
|
||||
protected:
|
||||
bool hasStringAbbr(const char* s1, const char* s2);
|
||||
bool hasStringAbbr(const char* name, const char* part);
|
||||
void SendGlobalSysMessage(const char *str);
|
||||
|
||||
bool ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcommand);
|
||||
@@ -94,6 +94,7 @@ class ChatHandler
|
||||
bool HandleAnnounceCommand(const char* args);
|
||||
bool HandleNotifyCommand(const char* args);
|
||||
bool HandleGMmodeCommand(const char* args);
|
||||
bool HandleGMChatCommand(const char* args);
|
||||
bool HandleVisibleCommand(const char* args);
|
||||
bool HandleGPSCommand(const char* args);
|
||||
bool HandleTaxiCheatCommand(const char* args);
|
||||
|
||||
+583
-583
File diff suppressed because it is too large
Load Diff
@@ -1,155 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "MapManager.h"
|
||||
#include "Opcodes.h"
|
||||
#include "ConfusedMovementGenerator.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Initialize(T &unit)
|
||||
{
|
||||
const float wander_distance=11;
|
||||
float x,y,z;
|
||||
x = unit.GetPositionX();
|
||||
y = unit.GetPositionY();
|
||||
z = unit.GetPositionZ();
|
||||
uint32 mapid=unit.GetMapId();
|
||||
|
||||
Map const* map = MapManager::Instance().GetBaseMap(mapid);
|
||||
|
||||
i_nextMove = 1;
|
||||
|
||||
bool is_water_ok, is_land_ok;
|
||||
_InitSpecific(unit, is_water_ok, is_land_ok);
|
||||
|
||||
for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx)
|
||||
{
|
||||
const float wanderX=wander_distance*rand_norm() - wander_distance/2;
|
||||
const float wanderY=wander_distance*rand_norm() - wander_distance/2;
|
||||
|
||||
i_waypoints[idx][0] = x + wanderX;
|
||||
i_waypoints[idx][1] = y + wanderY;
|
||||
|
||||
// prevent invalid coordinates generation
|
||||
MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]);
|
||||
MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]);
|
||||
|
||||
bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z);
|
||||
// if generated wrong path just ignore
|
||||
if( is_water && !is_water_ok || !is_water && !is_land_ok )
|
||||
{
|
||||
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
|
||||
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
|
||||
}
|
||||
unit.UpdateGroundPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z);
|
||||
i_waypoints[idx][2] = z;
|
||||
}
|
||||
|
||||
unit.StopMoving();
|
||||
unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
unit.addUnitState(UNIT_STAT_CONFUSED);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
|
||||
{
|
||||
is_water_ok = creature.canSwim();
|
||||
is_land_ok = creature.canWalk();
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
ConfusedMovementGenerator<Player>::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok)
|
||||
{
|
||||
is_water_ok = true;
|
||||
is_land_ok = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Reset(T &unit)
|
||||
{
|
||||
i_nextMove = 1;
|
||||
i_nextMoveTime.Reset(0);
|
||||
i_destinationHolder.ResetUpdate();
|
||||
unit.StopMoving();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||
{
|
||||
if(!&unit)
|
||||
return true;
|
||||
|
||||
if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED))
|
||||
return true;
|
||||
|
||||
if( i_nextMoveTime.Passed() )
|
||||
{
|
||||
// currently moving, update location
|
||||
Traveller<T> traveller(unit);
|
||||
if( i_destinationHolder.UpdateTraveller(traveller, diff, false))
|
||||
{
|
||||
if( i_destinationHolder.HasArrived())
|
||||
{
|
||||
// arrived, stop and wait a bit
|
||||
unit.StopMoving();
|
||||
|
||||
i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
|
||||
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// waiting for next move
|
||||
i_nextMoveTime.Update(diff);
|
||||
if( i_nextMoveTime.Passed() )
|
||||
{
|
||||
// start moving
|
||||
assert( i_nextMove <= MAX_CONF_WAYPOINTS );
|
||||
const float x = i_waypoints[i_nextMove][0];
|
||||
const float y = i_waypoints[i_nextMove][1];
|
||||
const float z = i_waypoints[i_nextMove][2];
|
||||
Traveller<T> traveller(unit);
|
||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Finalize(T &unit)
|
||||
{
|
||||
unit.clearUnitState(UNIT_STAT_CONFUSED);
|
||||
}
|
||||
|
||||
template void ConfusedMovementGenerator<Player>::Initialize(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Initialize(Creature &creature);
|
||||
template void ConfusedMovementGenerator<Player>::Finalize(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Finalize(Creature &creature);
|
||||
template void ConfusedMovementGenerator<Player>::Reset(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Reset(Creature &creature);
|
||||
template bool ConfusedMovementGenerator<Player>::Update(Player &player, const uint32 &diff);
|
||||
template bool ConfusedMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff);
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "MapManager.h"
|
||||
#include "Opcodes.h"
|
||||
#include "ConfusedMovementGenerator.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Initialize(T &unit)
|
||||
{
|
||||
const float wander_distance=11;
|
||||
float x,y,z;
|
||||
x = unit.GetPositionX();
|
||||
y = unit.GetPositionY();
|
||||
z = unit.GetPositionZ();
|
||||
uint32 mapid=unit.GetMapId();
|
||||
|
||||
Map const* map = MapManager::Instance().GetBaseMap(mapid);
|
||||
|
||||
i_nextMove = 1;
|
||||
|
||||
bool is_water_ok, is_land_ok;
|
||||
_InitSpecific(unit, is_water_ok, is_land_ok);
|
||||
|
||||
for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx)
|
||||
{
|
||||
const float wanderX=wander_distance*rand_norm() - wander_distance/2;
|
||||
const float wanderY=wander_distance*rand_norm() - wander_distance/2;
|
||||
|
||||
i_waypoints[idx][0] = x + wanderX;
|
||||
i_waypoints[idx][1] = y + wanderY;
|
||||
|
||||
// prevent invalid coordinates generation
|
||||
MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]);
|
||||
MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]);
|
||||
|
||||
bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z);
|
||||
// if generated wrong path just ignore
|
||||
if( is_water && !is_water_ok || !is_water && !is_land_ok )
|
||||
{
|
||||
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
|
||||
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
|
||||
}
|
||||
unit.UpdateGroundPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z);
|
||||
i_waypoints[idx][2] = z;
|
||||
}
|
||||
|
||||
unit.StopMoving();
|
||||
unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
unit.addUnitState(UNIT_STAT_CONFUSED);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
|
||||
{
|
||||
is_water_ok = creature.canSwim();
|
||||
is_land_ok = creature.canWalk();
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
ConfusedMovementGenerator<Player>::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok)
|
||||
{
|
||||
is_water_ok = true;
|
||||
is_land_ok = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Reset(T &unit)
|
||||
{
|
||||
i_nextMove = 1;
|
||||
i_nextMoveTime.Reset(0);
|
||||
i_destinationHolder.ResetUpdate();
|
||||
unit.StopMoving();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||
{
|
||||
if(!&unit)
|
||||
return true;
|
||||
|
||||
if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
|
||||
return true;
|
||||
|
||||
if( i_nextMoveTime.Passed() )
|
||||
{
|
||||
// currently moving, update location
|
||||
Traveller<T> traveller(unit);
|
||||
if( i_destinationHolder.UpdateTraveller(traveller, diff, false))
|
||||
{
|
||||
if( i_destinationHolder.HasArrived())
|
||||
{
|
||||
// arrived, stop and wait a bit
|
||||
unit.StopMoving();
|
||||
|
||||
i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
|
||||
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// waiting for next move
|
||||
i_nextMoveTime.Update(diff);
|
||||
if( i_nextMoveTime.Passed() )
|
||||
{
|
||||
// start moving
|
||||
assert( i_nextMove <= MAX_CONF_WAYPOINTS );
|
||||
const float x = i_waypoints[i_nextMove][0];
|
||||
const float y = i_waypoints[i_nextMove][1];
|
||||
const float z = i_waypoints[i_nextMove][2];
|
||||
Traveller<T> traveller(unit);
|
||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
ConfusedMovementGenerator<T>::Finalize(T &unit)
|
||||
{
|
||||
unit.clearUnitState(UNIT_STAT_CONFUSED);
|
||||
}
|
||||
|
||||
template void ConfusedMovementGenerator<Player>::Initialize(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Initialize(Creature &creature);
|
||||
template void ConfusedMovementGenerator<Player>::Finalize(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Finalize(Creature &creature);
|
||||
template void ConfusedMovementGenerator<Player>::Reset(Player &player);
|
||||
template void ConfusedMovementGenerator<Creature>::Reset(Creature &creature);
|
||||
template bool ConfusedMovementGenerator<Player>::Update(Player &player, const uint32 &diff);
|
||||
template bool ConfusedMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff);
|
||||
|
||||
+29
-18
@@ -75,6 +75,14 @@ bool VendorItemData::RemoveItem( uint32 item_id )
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t VendorItemData::FindItemSlot(uint32 item_id) const
|
||||
{
|
||||
for(size_t i = 0; i < m_items.size(); ++i )
|
||||
if(m_items[i]->item==item_id)
|
||||
return i;
|
||||
return m_items.size();
|
||||
}
|
||||
|
||||
VendorItem const* VendorItemData::FindItem(uint32 item_id) const
|
||||
{
|
||||
for(VendorItemList::const_iterator i = m_items.begin(); i != m_items.end(); ++i )
|
||||
@@ -1910,26 +1918,29 @@ time_t Creature::GetRespawnTimeEx() const
|
||||
|
||||
void Creature::GetRespawnCoord( float &x, float &y, float &z, float* ori, float* dist ) const
|
||||
{
|
||||
if(CreatureData const* data = objmgr.GetCreatureData(GetDBTableGUIDLow()))
|
||||
if (m_DBTableGuid)
|
||||
{
|
||||
x = data->posX;
|
||||
y = data->posY;
|
||||
z = data->posZ;
|
||||
if(ori)
|
||||
*ori = data->orientation;
|
||||
if(dist)
|
||||
*dist = data->spawndist;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = GetPositionX();
|
||||
y = GetPositionY();
|
||||
z = GetPositionZ();
|
||||
if(ori)
|
||||
*ori = GetOrientation();
|
||||
if(dist)
|
||||
*dist = 0;
|
||||
if (CreatureData const* data = objmgr.GetCreatureData(GetDBTableGUIDLow()))
|
||||
{
|
||||
x = data->posX;
|
||||
y = data->posY;
|
||||
z = data->posZ;
|
||||
if(ori)
|
||||
*ori = data->orientation;
|
||||
if(dist)
|
||||
*dist = data->spawndist;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
x = GetPositionX();
|
||||
y = GetPositionY();
|
||||
z = GetPositionZ();
|
||||
if(ori)
|
||||
*ori = GetOrientation();
|
||||
if(dist)
|
||||
*dist = 0;
|
||||
}
|
||||
|
||||
void Creature::AllLootRemovedFromCorpse()
|
||||
|
||||
@@ -308,6 +308,7 @@ struct VendorItemData
|
||||
}
|
||||
bool RemoveItem( uint32 item_id );
|
||||
VendorItem const* FindItem(uint32 item_id) const;
|
||||
size_t FindItemSlot(uint32 item_id) const;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
|
||||
@@ -1,379 +1,379 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "MapManager.h"
|
||||
#include "FleeingMovementGenerator.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
#define MIN_QUIET_DISTANCE 28.0f
|
||||
#define MAX_QUIET_DISTANCE 43.0f
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
|
||||
{
|
||||
if( !&owner )
|
||||
return;
|
||||
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED) )
|
||||
return;
|
||||
|
||||
if(!_setMoveData(owner))
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
if(!_getPoint(owner, x, y, z))
|
||||
return;
|
||||
|
||||
owner.addUnitState(UNIT_STAT_FLEEING);
|
||||
Traveller<T> traveller(owner);
|
||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
|
||||
{
|
||||
if(!&owner)
|
||||
return false;
|
||||
|
||||
x = owner.GetPositionX();
|
||||
y = owner.GetPositionY();
|
||||
z = owner.GetPositionZ();
|
||||
|
||||
float temp_x, temp_y, angle;
|
||||
const Map * _map = MapManager::Instance().GetBaseMap(owner.GetMapId());
|
||||
//primitive path-finding
|
||||
for(uint8 i = 0; i < 18; i++)
|
||||
{
|
||||
if(i_only_forward && i > 2)
|
||||
break;
|
||||
|
||||
float distance = 5.0f;
|
||||
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
angle = i_cur_angle;
|
||||
break;
|
||||
case 1:
|
||||
angle = i_cur_angle;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 2:
|
||||
angle = i_cur_angle;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 3:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
break;
|
||||
case 4:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
break;
|
||||
case 5:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 6:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 7:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
break;
|
||||
case 8:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
break;
|
||||
case 9:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 10:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 11:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 12:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 13:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 14:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 15:
|
||||
angle = i_cur_angle + M_PI*3/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 16:
|
||||
angle = i_cur_angle - M_PI*3/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 17:
|
||||
angle = i_cur_angle + M_PI;
|
||||
distance /= 2;
|
||||
break;
|
||||
}
|
||||
temp_x = x + distance * cos(angle);
|
||||
temp_y = y + distance * sin(angle);
|
||||
MaNGOS::NormalizeMapCoord(temp_x);
|
||||
MaNGOS::NormalizeMapCoord(temp_y);
|
||||
if( owner.IsWithinLOS(temp_x,temp_y,z))
|
||||
{
|
||||
bool is_water_now = _map->IsInWater(x,y,z);
|
||||
|
||||
if(is_water_now && _map->IsInWater(temp_x,temp_y,z))
|
||||
{
|
||||
x = temp_x;
|
||||
y = temp_y;
|
||||
return true;
|
||||
}
|
||||
float new_z = _map->GetHeight(temp_x,temp_y,z,true);
|
||||
|
||||
if(new_z <= INVALID_HEIGHT)
|
||||
continue;
|
||||
|
||||
bool is_water_next = _map->IsInWater(temp_x,temp_y,new_z);
|
||||
|
||||
if((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok))
|
||||
continue;
|
||||
|
||||
if( !(new_z - z) || distance / fabs(new_z - z) > 1.0f)
|
||||
{
|
||||
float new_z_left = _map->GetHeight(temp_x + 1.0f*cos(angle+M_PI/2),temp_y + 1.0f*sin(angle+M_PI/2),z,true);
|
||||
float new_z_right = _map->GetHeight(temp_x + 1.0f*cos(angle-M_PI/2),temp_y + 1.0f*sin(angle-M_PI/2),z,true);
|
||||
if(fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f)
|
||||
{
|
||||
x = temp_x;
|
||||
y = temp_y;
|
||||
z = new_z;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset( urand(500,1000) );
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::_setMoveData(T &owner)
|
||||
{
|
||||
float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z);
|
||||
|
||||
if(i_to_distance_from_caster > 0.0f)
|
||||
{
|
||||
if((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) ||
|
||||
// if we reach lower distance
|
||||
(i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) ||
|
||||
// if we can't be close
|
||||
(i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) ||
|
||||
// if we reach bigger distance
|
||||
(cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far
|
||||
(i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE) )
|
||||
// if we leave 'quiet zone'
|
||||
{
|
||||
// we are very far or too close, stopping
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset( urand(500,1000) );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// now we are running, continue
|
||||
i_last_distance_from_caster = cur_dist_xyz;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
float cur_dist;
|
||||
float angle_to_caster;
|
||||
|
||||
Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID);
|
||||
|
||||
if(fright)
|
||||
{
|
||||
cur_dist = fright->GetDistance(&owner);
|
||||
if(cur_dist < cur_dist_xyz)
|
||||
{
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
angle_to_caster = fright->GetAngle(&owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI;
|
||||
}
|
||||
|
||||
// if we too close may use 'path-finding' else just stop
|
||||
i_only_forward = cur_dist >= MIN_QUIET_DISTANCE/3;
|
||||
|
||||
//get angle and 'distance from caster' to run
|
||||
float angle;
|
||||
|
||||
if(i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time
|
||||
{
|
||||
angle = rand_norm()*(1.0f - cur_dist/MIN_QUIET_DISTANCE) * M_PI/3 + rand_norm()*M_PI*2/3;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE;
|
||||
i_only_forward = true;
|
||||
}
|
||||
else if(cur_dist < MIN_QUIET_DISTANCE)
|
||||
{
|
||||
angle = M_PI/6 + rand_norm()*M_PI*2/3;
|
||||
i_to_distance_from_caster = cur_dist*2/3 + rand_norm()*(MIN_QUIET_DISTANCE - cur_dist*2/3);
|
||||
}
|
||||
else if(cur_dist > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
angle = rand_norm()*M_PI/3 + M_PI*2/3;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = rand_norm()*M_PI;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
|
||||
int8 sign = rand_norm() > 0.5f ? 1 : -1;
|
||||
i_cur_angle = sign*angle + angle_to_caster;
|
||||
|
||||
// current distance
|
||||
i_last_distance_from_caster = cur_dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Initialize(T &owner)
|
||||
{
|
||||
if(!&owner)
|
||||
return;
|
||||
|
||||
Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID);
|
||||
if(!fright)
|
||||
return;
|
||||
|
||||
_Init(owner);
|
||||
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
i_only_forward = true;
|
||||
i_cur_angle = 0.0f;
|
||||
i_last_distance_from_caster = 0.0f;
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
FleeingMovementGenerator<Creature>::_Init(Creature &owner)
|
||||
{
|
||||
if(!&owner)
|
||||
return;
|
||||
owner.SetUInt64Value(UNIT_FIELD_TARGET, 0);
|
||||
is_water_ok = owner.canSwim();
|
||||
is_land_ok = owner.canWalk();
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
FleeingMovementGenerator<Player>::_Init(Player &)
|
||||
{
|
||||
is_water_ok = true;
|
||||
is_land_ok = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Finalize(T &owner)
|
||||
{
|
||||
owner.clearUnitState(UNIT_STAT_FLEEING);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Reset(T &owner)
|
||||
{
|
||||
Initialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
|
||||
{
|
||||
if( !&owner || !owner.isAlive() )
|
||||
return false;
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED) )
|
||||
return true;
|
||||
|
||||
Traveller<T> traveller(owner);
|
||||
|
||||
i_nextCheckTime.Update(time_diff);
|
||||
|
||||
if( (owner.IsStopped() && !i_destinationHolder.HasArrived()) || !i_destinationHolder.HasDestination() )
|
||||
{
|
||||
_setTargetLocation(owner);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
|
||||
{
|
||||
i_destinationHolder.ResetUpdate(50);
|
||||
if(i_nextCheckTime.Passed() && i_destinationHolder.HasArrived())
|
||||
{
|
||||
_setTargetLocation(owner);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template void FleeingMovementGenerator<Player>::Initialize(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Initialize(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::_setMoveData(Player &);
|
||||
template bool FleeingMovementGenerator<Creature>::_setMoveData(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::_getPoint(Player &, float &, float &, float &);
|
||||
template bool FleeingMovementGenerator<Creature>::_getPoint(Creature &, float &, float &, float &);
|
||||
template void FleeingMovementGenerator<Player>::_setTargetLocation(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::_setTargetLocation(Creature &);
|
||||
template void FleeingMovementGenerator<Player>::Finalize(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Finalize(Creature &);
|
||||
template void FleeingMovementGenerator<Player>::Reset(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Reset(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::Update(Player &, const uint32 &);
|
||||
template bool FleeingMovementGenerator<Creature>::Update(Creature &, const uint32 &);
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "MapManager.h"
|
||||
#include "FleeingMovementGenerator.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
#define MIN_QUIET_DISTANCE 28.0f
|
||||
#define MAX_QUIET_DISTANCE 43.0f
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
|
||||
{
|
||||
if( !&owner )
|
||||
return;
|
||||
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED) )
|
||||
return;
|
||||
|
||||
if(!_setMoveData(owner))
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
if(!_getPoint(owner, x, y, z))
|
||||
return;
|
||||
|
||||
owner.addUnitState(UNIT_STAT_FLEEING);
|
||||
Traveller<T> traveller(owner);
|
||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
|
||||
{
|
||||
if(!&owner)
|
||||
return false;
|
||||
|
||||
x = owner.GetPositionX();
|
||||
y = owner.GetPositionY();
|
||||
z = owner.GetPositionZ();
|
||||
|
||||
float temp_x, temp_y, angle;
|
||||
const Map * _map = MapManager::Instance().GetBaseMap(owner.GetMapId());
|
||||
//primitive path-finding
|
||||
for(uint8 i = 0; i < 18; i++)
|
||||
{
|
||||
if(i_only_forward && i > 2)
|
||||
break;
|
||||
|
||||
float distance = 5.0f;
|
||||
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
angle = i_cur_angle;
|
||||
break;
|
||||
case 1:
|
||||
angle = i_cur_angle;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 2:
|
||||
angle = i_cur_angle;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 3:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
break;
|
||||
case 4:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
break;
|
||||
case 5:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 6:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 7:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
break;
|
||||
case 8:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
break;
|
||||
case 9:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 10:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 11:
|
||||
angle = i_cur_angle + M_PI/4.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 12:
|
||||
angle = i_cur_angle - M_PI/4.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 13:
|
||||
angle = i_cur_angle + M_PI/2.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 14:
|
||||
angle = i_cur_angle - M_PI/2.0f;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 15:
|
||||
angle = i_cur_angle + M_PI*3/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 16:
|
||||
angle = i_cur_angle - M_PI*3/4.0f;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 17:
|
||||
angle = i_cur_angle + M_PI;
|
||||
distance /= 2;
|
||||
break;
|
||||
}
|
||||
temp_x = x + distance * cos(angle);
|
||||
temp_y = y + distance * sin(angle);
|
||||
MaNGOS::NormalizeMapCoord(temp_x);
|
||||
MaNGOS::NormalizeMapCoord(temp_y);
|
||||
if( owner.IsWithinLOS(temp_x,temp_y,z))
|
||||
{
|
||||
bool is_water_now = _map->IsInWater(x,y,z);
|
||||
|
||||
if(is_water_now && _map->IsInWater(temp_x,temp_y,z))
|
||||
{
|
||||
x = temp_x;
|
||||
y = temp_y;
|
||||
return true;
|
||||
}
|
||||
float new_z = _map->GetHeight(temp_x,temp_y,z,true);
|
||||
|
||||
if(new_z <= INVALID_HEIGHT)
|
||||
continue;
|
||||
|
||||
bool is_water_next = _map->IsInWater(temp_x,temp_y,new_z);
|
||||
|
||||
if((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok))
|
||||
continue;
|
||||
|
||||
if( !(new_z - z) || distance / fabs(new_z - z) > 1.0f)
|
||||
{
|
||||
float new_z_left = _map->GetHeight(temp_x + 1.0f*cos(angle+M_PI/2),temp_y + 1.0f*sin(angle+M_PI/2),z,true);
|
||||
float new_z_right = _map->GetHeight(temp_x + 1.0f*cos(angle-M_PI/2),temp_y + 1.0f*sin(angle-M_PI/2),z,true);
|
||||
if(fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f)
|
||||
{
|
||||
x = temp_x;
|
||||
y = temp_y;
|
||||
z = new_z;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset( urand(500,1000) );
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::_setMoveData(T &owner)
|
||||
{
|
||||
float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z);
|
||||
|
||||
if(i_to_distance_from_caster > 0.0f)
|
||||
{
|
||||
if((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) ||
|
||||
// if we reach lower distance
|
||||
(i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) ||
|
||||
// if we can't be close
|
||||
(i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) ||
|
||||
// if we reach bigger distance
|
||||
(cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far
|
||||
(i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE) )
|
||||
// if we leave 'quiet zone'
|
||||
{
|
||||
// we are very far or too close, stopping
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset( urand(500,1000) );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// now we are running, continue
|
||||
i_last_distance_from_caster = cur_dist_xyz;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
float cur_dist;
|
||||
float angle_to_caster;
|
||||
|
||||
Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID);
|
||||
|
||||
if(fright)
|
||||
{
|
||||
cur_dist = fright->GetDistance(&owner);
|
||||
if(cur_dist < cur_dist_xyz)
|
||||
{
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
angle_to_caster = fright->GetAngle(&owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI;
|
||||
}
|
||||
|
||||
// if we too close may use 'path-finding' else just stop
|
||||
i_only_forward = cur_dist >= MIN_QUIET_DISTANCE/3;
|
||||
|
||||
//get angle and 'distance from caster' to run
|
||||
float angle;
|
||||
|
||||
if(i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time
|
||||
{
|
||||
angle = rand_norm()*(1.0f - cur_dist/MIN_QUIET_DISTANCE) * M_PI/3 + rand_norm()*M_PI*2/3;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE;
|
||||
i_only_forward = true;
|
||||
}
|
||||
else if(cur_dist < MIN_QUIET_DISTANCE)
|
||||
{
|
||||
angle = M_PI/6 + rand_norm()*M_PI*2/3;
|
||||
i_to_distance_from_caster = cur_dist*2/3 + rand_norm()*(MIN_QUIET_DISTANCE - cur_dist*2/3);
|
||||
}
|
||||
else if(cur_dist > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
angle = rand_norm()*M_PI/3 + M_PI*2/3;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = rand_norm()*M_PI;
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
|
||||
int8 sign = rand_norm() > 0.5f ? 1 : -1;
|
||||
i_cur_angle = sign*angle + angle_to_caster;
|
||||
|
||||
// current distance
|
||||
i_last_distance_from_caster = cur_dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Initialize(T &owner)
|
||||
{
|
||||
if(!&owner)
|
||||
return;
|
||||
|
||||
Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID);
|
||||
if(!fright)
|
||||
return;
|
||||
|
||||
_Init(owner);
|
||||
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
i_only_forward = true;
|
||||
i_cur_angle = 0.0f;
|
||||
i_last_distance_from_caster = 0.0f;
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
FleeingMovementGenerator<Creature>::_Init(Creature &owner)
|
||||
{
|
||||
if(!&owner)
|
||||
return;
|
||||
owner.SetUInt64Value(UNIT_FIELD_TARGET, 0);
|
||||
is_water_ok = owner.canSwim();
|
||||
is_land_ok = owner.canWalk();
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
FleeingMovementGenerator<Player>::_Init(Player &)
|
||||
{
|
||||
is_water_ok = true;
|
||||
is_land_ok = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Finalize(T &owner)
|
||||
{
|
||||
owner.clearUnitState(UNIT_STAT_FLEEING);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FleeingMovementGenerator<T>::Reset(T &owner)
|
||||
{
|
||||
Initialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
FleeingMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
|
||||
{
|
||||
if( !&owner || !owner.isAlive() )
|
||||
return false;
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED) )
|
||||
return true;
|
||||
|
||||
Traveller<T> traveller(owner);
|
||||
|
||||
i_nextCheckTime.Update(time_diff);
|
||||
|
||||
if( (owner.IsStopped() && !i_destinationHolder.HasArrived()) || !i_destinationHolder.HasDestination() )
|
||||
{
|
||||
_setTargetLocation(owner);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
|
||||
{
|
||||
i_destinationHolder.ResetUpdate(50);
|
||||
if(i_nextCheckTime.Passed() && i_destinationHolder.HasArrived())
|
||||
{
|
||||
_setTargetLocation(owner);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template void FleeingMovementGenerator<Player>::Initialize(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Initialize(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::_setMoveData(Player &);
|
||||
template bool FleeingMovementGenerator<Creature>::_setMoveData(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::_getPoint(Player &, float &, float &, float &);
|
||||
template bool FleeingMovementGenerator<Creature>::_getPoint(Creature &, float &, float &, float &);
|
||||
template void FleeingMovementGenerator<Player>::_setTargetLocation(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::_setTargetLocation(Creature &);
|
||||
template void FleeingMovementGenerator<Player>::Finalize(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Finalize(Creature &);
|
||||
template void FleeingMovementGenerator<Player>::Reset(Player &);
|
||||
template void FleeingMovementGenerator<Creature>::Reset(Creature &);
|
||||
template bool FleeingMovementGenerator<Player>::Update(Player &, const uint32 &);
|
||||
template bool FleeingMovementGenerator<Creature>::Update(Creature &, const uint32 &);
|
||||
|
||||
@@ -852,7 +852,7 @@ namespace MaNGOS
|
||||
bool operator()(Unit* u)
|
||||
{
|
||||
if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
|
||||
(u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNDED) || u->hasUnitState(UNIT_STAT_STUNDED) || u->hasUnitState(UNIT_STAT_CONFUSED)))
|
||||
(u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
+1454
-1454
File diff suppressed because it is too large
Load Diff
@@ -1,86 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "HomeMovementGenerator.h"
|
||||
#include "Creature.h"
|
||||
#include "Traveller.h"
|
||||
#include "MapManager.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::Initialize(Creature & owner)
|
||||
{
|
||||
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::Reset(Creature &)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
|
||||
{
|
||||
if( !&owner )
|
||||
return;
|
||||
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED) )
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
owner.GetRespawnCoord(x, y, z);
|
||||
|
||||
CreatureTraveller traveller(owner);
|
||||
|
||||
uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
modifyTravelTime(travel_time);
|
||||
owner.clearUnitState(UNIT_STAT_ALL_STATE);
|
||||
}
|
||||
|
||||
bool
|
||||
HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
|
||||
{
|
||||
CreatureTraveller traveller( owner);
|
||||
i_destinationHolder.UpdateTraveller(traveller, time_diff, false);
|
||||
|
||||
if (time_diff > i_travel_timer)
|
||||
{
|
||||
owner.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
|
||||
// restore orientation of not moving creature at returning to home
|
||||
if(owner.GetDefaultMovementType()==IDLE_MOTION_TYPE)
|
||||
{
|
||||
if(CreatureData const* data = objmgr.GetCreatureData(owner.GetDBTableGUIDLow()))
|
||||
{
|
||||
owner.SetOrientation(data->orientation);
|
||||
WorldPacket packet;
|
||||
owner.BuildHeartBeatMsg(&packet);
|
||||
owner.SendMessageToSet(&packet, false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
i_travel_timer -= time_diff;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "HomeMovementGenerator.h"
|
||||
#include "Creature.h"
|
||||
#include "Traveller.h"
|
||||
#include "MapManager.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "DestinationHolderImp.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::Initialize(Creature & owner)
|
||||
{
|
||||
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::Reset(Creature &)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
|
||||
{
|
||||
if( !&owner )
|
||||
return;
|
||||
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) )
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
owner.GetRespawnCoord(x, y, z);
|
||||
|
||||
CreatureTraveller traveller(owner);
|
||||
|
||||
uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
modifyTravelTime(travel_time);
|
||||
owner.clearUnitState(UNIT_STAT_ALL_STATE);
|
||||
}
|
||||
|
||||
bool
|
||||
HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
|
||||
{
|
||||
CreatureTraveller traveller( owner);
|
||||
i_destinationHolder.UpdateTraveller(traveller, time_diff, false);
|
||||
|
||||
if (time_diff > i_travel_timer)
|
||||
{
|
||||
owner.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
|
||||
// restore orientation of not moving creature at returning to home
|
||||
if(owner.GetDefaultMovementType()==IDLE_MOTION_TYPE)
|
||||
{
|
||||
if(CreatureData const* data = objmgr.GetCreatureData(owner.GetDBTableGUIDLow()))
|
||||
{
|
||||
owner.SetOrientation(data->orientation);
|
||||
WorldPacket packet;
|
||||
owner.BuildHeartBeatMsg(&packet);
|
||||
owner.SendMessageToSet(&packet, false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
i_travel_timer -= time_diff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+50
-75
@@ -75,7 +75,9 @@ enum MangosStrings
|
||||
LANG_LEVEL_MINREQUIRED = 49,
|
||||
LANG_LEVEL_MINREQUIRED_AND_ITEM = 50,
|
||||
LANG_NPC_TAINER_HELLO = 51,
|
||||
// Room for more level 0
|
||||
LANG_COMMAND_INVALID_ITEM_COUNT = 52,
|
||||
LANG_COMMAND_MAIL_ITEMS_LIMIT = 53,
|
||||
// Room for more level 0 54-99 not used
|
||||
|
||||
// level 1 chat
|
||||
LANG_GLOBAL_NOTIFY = 100,
|
||||
@@ -159,7 +161,7 @@ enum MangosStrings
|
||||
|
||||
LANG_MAIL_SENT = 169,
|
||||
LANG_SOUND_NOT_EXIST = 170,
|
||||
// Room for more level 1
|
||||
// Room for more level 1 171-199 not used
|
||||
|
||||
// level 2 chat
|
||||
LANG_NO_SELECTION = 200,
|
||||
@@ -304,8 +306,11 @@ enum MangosStrings
|
||||
LANG_LOOKUP_PLAYER_CHARACTER = 329,
|
||||
LANG_NO_PLAYERS_FOUND = 330,
|
||||
LANG_EXTENDED_COST_NOT_EXIST = 331,
|
||||
|
||||
// Room for more level 2
|
||||
LANG_GM_ON = 332,
|
||||
LANG_GM_OFF = 333,
|
||||
LANG_GM_CHAT_ON = 334,
|
||||
LANG_GM_CHAT_OFF = 335,
|
||||
// Room for more level 2 336-399 not used
|
||||
|
||||
// level 3 chat
|
||||
LANG_SCRIPTS_RELOADED = 400,
|
||||
@@ -610,79 +615,49 @@ enum MangosStrings
|
||||
|
||||
LANG_BG_GROUP_TOO_LARGE = 711,
|
||||
LANG_ARENA_GROUP_TOO_LARGE = 712,
|
||||
LANG_ARENA_YOUR_TEAM_ONLY = 713,
|
||||
LANG_ARENA_NOT_ENOUGH_PLAYERS = 714,
|
||||
LANG_ARENA_GOLD_WINS = 715,
|
||||
LANG_ARENA_GREEN_WINS = 716,
|
||||
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 717,
|
||||
LANG_BG_GROUP_OFFLINE_MEMBER = 718,
|
||||
LANG_BG_GROUP_MIXED_FACTION = 719,
|
||||
LANG_BG_GROUP_MIXED_LEVELS = 720,
|
||||
LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 721,
|
||||
LANG_BG_GROUP_MEMBER_DESERTER = 722,
|
||||
LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 723,
|
||||
LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713,
|
||||
LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714,
|
||||
LANG_YOUR_BG_LEVEL_REQ_ERROR = 715,
|
||||
LANG_YOUR_ARENA_TEAM_FULL = 716,
|
||||
// Room for BG/ARENA 717-799 not used
|
||||
|
||||
LANG_CANNOT_TELE_TO_BG = 724,
|
||||
LANG_CANNOT_SUMMON_TO_BG = 725,
|
||||
LANG_CANNOT_GO_TO_BG_GM = 726,
|
||||
LANG_CANNOT_GO_TO_BG_FROM_BG = 727,
|
||||
LANG_ARENA_YOUR_TEAM_ONLY = 730,
|
||||
LANG_ARENA_NOT_ENOUGH_PLAYERS = 731,
|
||||
LANG_ARENA_GOLD_WINS = 732,
|
||||
LANG_ARENA_GREEN_WINS = 733,
|
||||
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 734,
|
||||
LANG_BG_GROUP_OFFLINE_MEMBER = 735,
|
||||
LANG_BG_GROUP_MIXED_FACTION = 736,
|
||||
LANG_BG_GROUP_MIXED_LEVELS = 737,
|
||||
LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 738,
|
||||
LANG_BG_GROUP_MEMBER_DESERTER = 739,
|
||||
LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 740,
|
||||
|
||||
LANG_ARENA_TESTING = 728
|
||||
LANG_CANNOT_TELE_TO_BG = 741,
|
||||
LANG_CANNOT_SUMMON_TO_BG = 742,
|
||||
LANG_CANNOT_GO_TO_BG_GM = 743,
|
||||
LANG_CANNOT_GO_TO_BG_FROM_BG = 744,
|
||||
|
||||
LANG_ARENA_TESTING = 745,
|
||||
|
||||
// in game strings
|
||||
LANG_PET_INVALID_NAME = 800,
|
||||
LANG_NOT_ENOUGH_GOLD = 801,
|
||||
LANG_NOT_FREE_TRADE_SLOTS = 802,
|
||||
LANG_NOT_PARTNER_FREE_TRADE_SLOTS = 803,
|
||||
LANG_YOU_NOT_HAVE_PERMISSION = 804,
|
||||
LANG_UNKNOWN_LANGUAGE = 805,
|
||||
LANG_NOT_LEARNED_LANGUAGE = 806,
|
||||
LANG_NEED_CHARACTER_NAME = 807,
|
||||
LANG_PLAYER_NOT_EXIST_OR_OFFLINE = 808,
|
||||
LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND = 809,
|
||||
// Room for in-game strings 810-999 not used
|
||||
|
||||
// FREE IDS 1000-9999
|
||||
|
||||
// Use for not-in-svn patches 10000-10999
|
||||
// Use for custom patches 11000-11999
|
||||
|
||||
// NOT RESERVED IDS 12000-
|
||||
};
|
||||
#endif
|
||||
|
||||
/* NOT USED VALUES
|
||||
// alliance ranks
|
||||
#define LANG_ALI_PRIVATE "Private "
|
||||
#define LANG_ALI_CORPORAL "Corporal "
|
||||
#define LANG_ALI_SERGEANT "Sergeant "
|
||||
#define LANG_ALI_MASTER_SERGEANT "Master Sergeant "
|
||||
#define LANG_ALI_SERGEANT_MAJOR "Sergeant Major "
|
||||
#define LANG_ALI_KNIGHT "Knight "
|
||||
#define LANG_ALI_KNIGHT_LIEUTENANT "Knight-Lieutenant "
|
||||
#define LANG_ALI_KNIGHT_CAPTAIN "Knight-Captain "
|
||||
#define LANG_ALI_KNIGHT_CHAMPION "Knight-Champion "
|
||||
#define LANG_ALI_LIEUTENANT_COMMANDER "Lieutenant Commander "
|
||||
#define LANG_ALI_COMMANDER "Commander "
|
||||
#define LANG_ALI_MARSHAL "Marshal "
|
||||
#define LANG_ALI_FIELD_MARSHAL "Field Marshal "
|
||||
#define LANG_ALI_GRAND_MARSHAL "Grand Marshal "
|
||||
#define LANG_ALI_GAME_MASTER "Game Master "
|
||||
|
||||
// horde ranks
|
||||
#define LANG_HRD_SCOUT "Scout "
|
||||
#define LANG_HRD_GRUNT "Grunt "
|
||||
#define LANG_HRD_SERGEANT "Sergeant "
|
||||
#define LANG_HRD_SENIOR_SERGEANT "Senior Sergeant "
|
||||
#define LANG_HRD_FIRST_SERGEANT "First Sergeant "
|
||||
#define LANG_HRD_STONE_GUARD "Stone Guard "
|
||||
#define LANG_HRD_BLOOD_GUARD "Blood Guard "
|
||||
#define LANG_HRD_LEGIONNARE "Legionnaire "
|
||||
#define LANG_HRD_CENTURION "Centurion "
|
||||
#define LANG_HRD_CHAMPION "Champion "
|
||||
#define LANG_HRD_LIEUTENANT_GENERAL "Lieutenant General "
|
||||
#define LANG_HRD_GENERAL "General "
|
||||
#define LANG_HRD_WARLORD "Warlord "
|
||||
#define LANG_HRD_HIGH_WARLORD "High Warlord "
|
||||
#define LANG_HRD_GAME_MASTER "Game Master "
|
||||
|
||||
#define LANG_NO_RANK "No rank "
|
||||
#define LANG_RANK "%s (Rank %u)"
|
||||
#define LANG_HONOR_TODAY "Today: [Honorable kills: |c0000ff00%u|r] [Dishonorable kills: |c00ff0000%u|r]"
|
||||
#define LANG_HONOR_YESTERDAY "Yesterday: [Kills: |c0000ff00%u|r] [Honor: %u]"
|
||||
#define LANG_HONOR_THIS_WEEK "This week: [Kills: |c0000ff00%u|r] [Honor: %u]"
|
||||
#define LANG_HONOR_LAST_WEEK "Last week: [Kills: |c0000ff00%u|r] [Honor: %u] [Standing: %u]"
|
||||
#define LANG_HONOR_LIFE "Lifetime: [Honorable kills: |c0000ff00%u|r] [Dishonorable kills: |c00ff0000%u|r] [Highest rank %u: %s]"
|
||||
|
||||
// level 2
|
||||
#define LANG_ADD_OBJ "AddObject at Chat.cpp" //log
|
||||
#define LANG_DEMORPHED "Demorphed %s" //log
|
||||
|
||||
// level 3
|
||||
#define LANG_SPAWNING_SPIRIT_HEAL "Spawning spirit healers\n"
|
||||
#define LANG_NO_SPIRIT_HEAL_DB "No spirit healers in database, exiting."
|
||||
|
||||
#define LANG_ADD_OBJ_LV3 "AddObject at Level3.cpp line 1176"
|
||||
|
||||
*/
|
||||
|
||||
+151
-12
@@ -147,9 +147,11 @@ bool ChatHandler::HandleGMmodeCommand(const char* args)
|
||||
{
|
||||
if(!*args)
|
||||
{
|
||||
SendSysMessage(LANG_USE_BOL);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
if(m_session->GetPlayer()->isGameMaster())
|
||||
m_session->SendNotification(LANG_GM_ON);
|
||||
else
|
||||
m_session->SendNotification(LANG_GM_OFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string argstr = (char*)args;
|
||||
@@ -157,7 +159,7 @@ bool ChatHandler::HandleGMmodeCommand(const char* args)
|
||||
if (argstr == "on")
|
||||
{
|
||||
m_session->GetPlayer()->SetGameMaster(true);
|
||||
m_session->SendNotification("GM mode is ON");
|
||||
m_session->SendNotification(LANG_GM_ON);
|
||||
#ifdef _DEBUG_VMAPS
|
||||
VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
vMapManager->processCommand("stoplog");
|
||||
@@ -168,7 +170,7 @@ bool ChatHandler::HandleGMmodeCommand(const char* args)
|
||||
if (argstr == "off")
|
||||
{
|
||||
m_session->GetPlayer()->SetGameMaster(false);
|
||||
m_session->SendNotification("GM mode is OFF");
|
||||
m_session->SendNotification(LANG_GM_OFF);
|
||||
#ifdef _DEBUG_VMAPS
|
||||
VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
vMapManager->processCommand("startlog");
|
||||
@@ -181,6 +183,40 @@ bool ChatHandler::HandleGMmodeCommand(const char* args)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enables or disables hiding of the staff badge
|
||||
bool ChatHandler::HandleGMChatCommand(const char* args)
|
||||
{
|
||||
if(!*args)
|
||||
{
|
||||
if(m_session->GetPlayer()->isGMChat())
|
||||
m_session->SendNotification(LANG_GM_CHAT_ON);
|
||||
else
|
||||
m_session->SendNotification(LANG_GM_CHAT_OFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string argstr = (char*)args;
|
||||
|
||||
if (argstr == "on")
|
||||
{
|
||||
m_session->GetPlayer()->SetGMChat(true);
|
||||
m_session->SendNotification(LANG_GM_CHAT_ON);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argstr == "off")
|
||||
{
|
||||
m_session->GetPlayer()->SetGMChat(false);
|
||||
m_session->SendNotification(LANG_GM_CHAT_OFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
SendSysMessage(LANG_USE_BOL);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//Enable\Dissable Invisible mode
|
||||
bool ChatHandler::HandleVisibleCommand(const char* args)
|
||||
{
|
||||
@@ -195,13 +231,13 @@ bool ChatHandler::HandleVisibleCommand(const char* args)
|
||||
if (argstr == "on")
|
||||
{
|
||||
m_session->GetPlayer()->SetGMVisible(true);
|
||||
m_session->SendNotification(GetMangosString(LANG_INVISIBLE_VISIBLE));
|
||||
m_session->SendNotification(LANG_INVISIBLE_VISIBLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argstr == "off")
|
||||
{
|
||||
m_session->SendNotification(GetMangosString(LANG_INVISIBLE_INVISIBLE));
|
||||
m_session->SendNotification(LANG_INVISIBLE_INVISIBLE);
|
||||
m_session->GetPlayer()->SetGMVisible(false);
|
||||
return true;
|
||||
}
|
||||
@@ -1823,19 +1859,107 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
|
||||
if(!*args)
|
||||
return false;
|
||||
|
||||
// format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12]
|
||||
|
||||
char* pName = strtok((char*)args, " ");
|
||||
char* msgSubject = strtok(NULL, " ");
|
||||
char* msgText = strtok(NULL, "");
|
||||
if(!pName)
|
||||
return false;
|
||||
|
||||
char* tail1 = strtok(NULL, "");
|
||||
if(!tail1)
|
||||
return false;
|
||||
|
||||
char* msgSubject;
|
||||
if(*tail1=='"')
|
||||
msgSubject = strtok(tail1+1, "\"");
|
||||
else
|
||||
{
|
||||
char* space = strtok(tail1, "\"");
|
||||
if(!space)
|
||||
return false;
|
||||
msgSubject = strtok(NULL, "\"");
|
||||
}
|
||||
|
||||
if (!msgSubject)
|
||||
return false;
|
||||
|
||||
char* tail2 = strtok(NULL, "");
|
||||
if(!tail2)
|
||||
return false;
|
||||
|
||||
char* msgText;
|
||||
if(*tail2=='"')
|
||||
msgText = strtok(tail2+1, "\"");
|
||||
else
|
||||
{
|
||||
char* space = strtok(tail2, "\"");
|
||||
if(!space)
|
||||
return false;
|
||||
msgText = strtok(NULL, "\"");
|
||||
}
|
||||
|
||||
if (!msgText)
|
||||
return false;
|
||||
|
||||
// pName, msgSubject, msgText isn't NUL after prev. check
|
||||
|
||||
std::string name = pName;
|
||||
std::string subject = msgSubject;
|
||||
std::string text = msgText;
|
||||
|
||||
// extract items
|
||||
typedef std::pair<uint32,uint32> ItemPair;
|
||||
typedef std::list< ItemPair > ItemPairs;
|
||||
ItemPairs items;
|
||||
|
||||
// get all tail string
|
||||
char* tail = strtok(NULL, "");
|
||||
|
||||
// get from tail next item str
|
||||
while(char* itemStr = strtok(tail, " "))
|
||||
{
|
||||
// and get new tail
|
||||
tail = strtok(NULL, "");
|
||||
|
||||
// parse item str
|
||||
char* itemIdStr = strtok(itemStr, ":");
|
||||
char* itemCountStr = strtok(NULL, " ");
|
||||
|
||||
uint32 item_id = atoi(itemIdStr);
|
||||
if(!item_id)
|
||||
return false;
|
||||
|
||||
ItemPrototype const* item_proto = objmgr.GetItemPrototype(item_id);
|
||||
if(!item_proto)
|
||||
{
|
||||
PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 item_count = itemCountStr ? atoi(itemCountStr) : 1;
|
||||
if(item_count < 1 || item_proto->MaxCount && item_count > item_proto->MaxCount)
|
||||
{
|
||||
PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, item_count,item_id);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
while(item_count > item_proto->Stackable)
|
||||
{
|
||||
items.push_back(ItemPair(item_id,item_proto->Stackable));
|
||||
item_count -= item_proto->Stackable;
|
||||
}
|
||||
|
||||
items.push_back(ItemPair(item_id,item_count));
|
||||
|
||||
if(items.size() > MAX_MAIL_ITEMS)
|
||||
{
|
||||
PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!normalizePlayerName(name))
|
||||
{
|
||||
SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||||
@@ -1844,9 +1968,12 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
|
||||
}
|
||||
|
||||
uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name);
|
||||
|
||||
if(!receiver_guid)
|
||||
{
|
||||
SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 mailId = objmgr.GenerateMailID();
|
||||
uint32 sender_guidlo = m_session->GetPlayer()->GetGUIDLow();
|
||||
@@ -1860,7 +1987,19 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
|
||||
|
||||
Player *receiver = objmgr.GetPlayer(receiver_guid);
|
||||
|
||||
WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_NONE);
|
||||
// fill mail
|
||||
MailItemsInfo mi; // item list preparing
|
||||
|
||||
for(ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr)
|
||||
{
|
||||
if(Item* item = Item::CreateItem(itr->first,itr->second,m_session->GetPlayer()))
|
||||
{
|
||||
item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
|
||||
mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item);
|
||||
}
|
||||
}
|
||||
|
||||
WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
|
||||
|
||||
PSendSysMessage(LANG_MAIL_SENT, name.c_str());
|
||||
return true;
|
||||
|
||||
+1759
-1765
File diff suppressed because it is too large
Load Diff
+342
-342
@@ -1,342 +1,342 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "MotionMaster.h"
|
||||
#include "CreatureAISelector.h"
|
||||
#include "Creature.h"
|
||||
#include "Traveller.h"
|
||||
|
||||
#include "ConfusedMovementGenerator.h"
|
||||
#include "FleeingMovementGenerator.h"
|
||||
#include "HomeMovementGenerator.h"
|
||||
#include "IdleMovementGenerator.h"
|
||||
#include "PointMovementGenerator.h"
|
||||
#include "TargetedMovementGenerator.h"
|
||||
#include "WaypointMovementGenerator.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
inline bool isStatic(MovementGenerator *mv)
|
||||
{
|
||||
return (mv == &si_idleMovement);
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::Initialize()
|
||||
{
|
||||
// clear ALL movement generators (including default)
|
||||
while(!empty())
|
||||
{
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
if( !isStatic( curr ) )
|
||||
delete curr;
|
||||
}
|
||||
|
||||
// set new default movement generator
|
||||
if(i_owner->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner);
|
||||
push( movement == NULL ? &si_idleMovement : movement );
|
||||
top()->Initialize(*i_owner);
|
||||
}
|
||||
else
|
||||
push(&si_idleMovement);
|
||||
}
|
||||
|
||||
MotionMaster::~MotionMaster()
|
||||
{
|
||||
// clear ALL movement generators (including default)
|
||||
while(!empty())
|
||||
{
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
if( !isStatic( curr ) )
|
||||
delete curr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::UpdateMotion(const uint32 &diff)
|
||||
{
|
||||
if( i_owner->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED) )
|
||||
return;
|
||||
assert( !empty() );
|
||||
if (!top()->Update(*i_owner, diff))
|
||||
MovementExpired();
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::Clear(bool reset)
|
||||
{
|
||||
while( !empty() && size() > 1 )
|
||||
{
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
if( !isStatic( curr ) )
|
||||
delete curr;
|
||||
}
|
||||
|
||||
if (reset)
|
||||
{
|
||||
assert( !empty() );
|
||||
top()->Reset(*i_owner);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MovementExpired(bool reset)
|
||||
{
|
||||
if( empty() || size() == 1 )
|
||||
return;
|
||||
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
|
||||
if( !isStatic(curr) )
|
||||
delete curr;
|
||||
|
||||
assert( !empty() );
|
||||
while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
|
||||
{
|
||||
// Should check if target is still valid? If not valid it will crash.
|
||||
curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
delete curr;
|
||||
}
|
||||
if( empty() )
|
||||
Initialize();
|
||||
if (reset) top()->Reset(*i_owner);
|
||||
}
|
||||
|
||||
void MotionMaster::MoveIdle()
|
||||
{
|
||||
if( empty() || !isStatic( top() ) )
|
||||
push( &si_idleMovement );
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveTargetedHome()
|
||||
{
|
||||
if(i_owner->hasUnitState(UNIT_STAT_FLEEING))
|
||||
return;
|
||||
|
||||
Clear(false);
|
||||
|
||||
if(i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID())
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow());
|
||||
Mutate(new HomeMovementGenerator<Creature>());
|
||||
}
|
||||
else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID())
|
||||
{
|
||||
sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveConfused()
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) move confused", i_owner->GetGUIDLow() );
|
||||
Mutate(new ConfusedMovementGenerator<Player>());
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) move confused",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow() );
|
||||
Mutate(new ConfusedMovementGenerator<Creature>());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveChase(Unit* target, float dist, float angle)
|
||||
{
|
||||
// ignore movement request if target not exist
|
||||
if(!target)
|
||||
return;
|
||||
|
||||
i_owner->clearUnitState(UNIT_STAT_FOLLOW);
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) chase to %s (GUID: %u)",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(),
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveFollow(Unit* target, float dist, float angle)
|
||||
{
|
||||
Clear();
|
||||
|
||||
// ignore movement request if target not exist
|
||||
if(!target)
|
||||
return;
|
||||
|
||||
i_owner->addUnitState(UNIT_STAT_FOLLOW);
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(),
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(),
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MovePoint(uint32 id, float x, float y, float z)
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), id, x, y, z );
|
||||
Mutate(new PointMovementGenerator<Player>(id,x,y,z));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(), id, x, y, z );
|
||||
Mutate(new PointMovementGenerator<Creature>(id,x,y,z));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveFleeing(Unit* enemy)
|
||||
{
|
||||
if(!enemy)
|
||||
return;
|
||||
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) flee from %s (GUID: %u)", i_owner->GetGUIDLow(),
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
|
||||
Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(),
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
|
||||
Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) taxi to (Path %u node %u)", i_owner->GetGUIDLow(), path, pathnode);
|
||||
FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(path,pathnode);
|
||||
Mutate(mgen);
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(), path, pathnode );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveDistract(uint32 timer)
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) distracted (timer: %u)", i_owner->GetGUIDLow(), timer);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) (timer: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(), timer);
|
||||
}
|
||||
|
||||
DistractMovementGenerator* mgen = new DistractMovementGenerator(timer);
|
||||
Mutate(mgen);
|
||||
}
|
||||
|
||||
void MotionMaster::Mutate(MovementGenerator *m)
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
switch(top()->GetMovementGeneratorType())
|
||||
{
|
||||
// HomeMovement is not that important, delete it if meanwhile a new comes
|
||||
case HOME_MOTION_TYPE:
|
||||
// DistractMovement interrupted by any other movement
|
||||
case DISTRACT_MOTION_TYPE:
|
||||
MovementExpired(false);
|
||||
}
|
||||
}
|
||||
m->Initialize(*i_owner);
|
||||
push(m);
|
||||
}
|
||||
|
||||
void MotionMaster::propagateSpeedChange()
|
||||
{
|
||||
Impl::container_type::iterator it = Impl::c.begin();
|
||||
for ( ;it != end(); ++it)
|
||||
{
|
||||
(*it)->unitSpeedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
|
||||
{
|
||||
if(empty())
|
||||
return IDLE_MOTION_TYPE;
|
||||
|
||||
return top()->GetMovementGeneratorType();
|
||||
}
|
||||
|
||||
bool MotionMaster::GetDestination(float &x, float &y, float &z)
|
||||
{
|
||||
if(empty())
|
||||
return false;
|
||||
|
||||
return top()->GetDestination(x,y,z);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "MotionMaster.h"
|
||||
#include "CreatureAISelector.h"
|
||||
#include "Creature.h"
|
||||
#include "Traveller.h"
|
||||
|
||||
#include "ConfusedMovementGenerator.h"
|
||||
#include "FleeingMovementGenerator.h"
|
||||
#include "HomeMovementGenerator.h"
|
||||
#include "IdleMovementGenerator.h"
|
||||
#include "PointMovementGenerator.h"
|
||||
#include "TargetedMovementGenerator.h"
|
||||
#include "WaypointMovementGenerator.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
inline bool isStatic(MovementGenerator *mv)
|
||||
{
|
||||
return (mv == &si_idleMovement);
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::Initialize()
|
||||
{
|
||||
// clear ALL movement generators (including default)
|
||||
while(!empty())
|
||||
{
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
if( !isStatic( curr ) )
|
||||
delete curr;
|
||||
}
|
||||
|
||||
// set new default movement generator
|
||||
if(i_owner->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner);
|
||||
push( movement == NULL ? &si_idleMovement : movement );
|
||||
top()->Initialize(*i_owner);
|
||||
}
|
||||
else
|
||||
push(&si_idleMovement);
|
||||
}
|
||||
|
||||
MotionMaster::~MotionMaster()
|
||||
{
|
||||
// clear ALL movement generators (including default)
|
||||
while(!empty())
|
||||
{
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
if( !isStatic( curr ) )
|
||||
delete curr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::UpdateMotion(const uint32 &diff)
|
||||
{
|
||||
if( i_owner->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED) )
|
||||
return;
|
||||
assert( !empty() );
|
||||
if (!top()->Update(*i_owner, diff))
|
||||
MovementExpired();
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::Clear(bool reset)
|
||||
{
|
||||
while( !empty() && size() > 1 )
|
||||
{
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
if( !isStatic( curr ) )
|
||||
delete curr;
|
||||
}
|
||||
|
||||
if (reset)
|
||||
{
|
||||
assert( !empty() );
|
||||
top()->Reset(*i_owner);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MovementExpired(bool reset)
|
||||
{
|
||||
if( empty() || size() == 1 )
|
||||
return;
|
||||
|
||||
MovementGenerator *curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
|
||||
if( !isStatic(curr) )
|
||||
delete curr;
|
||||
|
||||
assert( !empty() );
|
||||
while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
|
||||
{
|
||||
// Should check if target is still valid? If not valid it will crash.
|
||||
curr = top();
|
||||
curr->Finalize(*i_owner);
|
||||
pop();
|
||||
delete curr;
|
||||
}
|
||||
if( empty() )
|
||||
Initialize();
|
||||
if (reset) top()->Reset(*i_owner);
|
||||
}
|
||||
|
||||
void MotionMaster::MoveIdle()
|
||||
{
|
||||
if( empty() || !isStatic( top() ) )
|
||||
push( &si_idleMovement );
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveTargetedHome()
|
||||
{
|
||||
if(i_owner->hasUnitState(UNIT_STAT_FLEEING))
|
||||
return;
|
||||
|
||||
Clear(false);
|
||||
|
||||
if(i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID())
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow());
|
||||
Mutate(new HomeMovementGenerator<Creature>());
|
||||
}
|
||||
else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID())
|
||||
{
|
||||
sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveConfused()
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) move confused", i_owner->GetGUIDLow() );
|
||||
Mutate(new ConfusedMovementGenerator<Player>());
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) move confused",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow() );
|
||||
Mutate(new ConfusedMovementGenerator<Creature>());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveChase(Unit* target, float dist, float angle)
|
||||
{
|
||||
// ignore movement request if target not exist
|
||||
if(!target)
|
||||
return;
|
||||
|
||||
i_owner->clearUnitState(UNIT_STAT_FOLLOW);
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) chase to %s (GUID: %u)",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(),
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveFollow(Unit* target, float dist, float angle)
|
||||
{
|
||||
Clear();
|
||||
|
||||
// ignore movement request if target not exist
|
||||
if(!target)
|
||||
return;
|
||||
|
||||
i_owner->addUnitState(UNIT_STAT_FOLLOW);
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(),
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(),
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MovePoint(uint32 id, float x, float y, float z)
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), id, x, y, z );
|
||||
Mutate(new PointMovementGenerator<Player>(id,x,y,z));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(), id, x, y, z );
|
||||
Mutate(new PointMovementGenerator<Creature>(id,x,y,z));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveFleeing(Unit* enemy)
|
||||
{
|
||||
if(!enemy)
|
||||
return;
|
||||
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) flee from %s (GUID: %u)", i_owner->GetGUIDLow(),
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
|
||||
Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(),
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
|
||||
Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) taxi to (Path %u node %u)", i_owner->GetGUIDLow(), path, pathnode);
|
||||
FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(path,pathnode);
|
||||
Mutate(mgen);
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(), path, pathnode );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionMaster::MoveDistract(uint32 timer)
|
||||
{
|
||||
if(i_owner->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
DEBUG_LOG("Player (GUID: %u) distracted (timer: %u)", i_owner->GetGUIDLow(), timer);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Creature (Entry: %u GUID: %u) (timer: %u)",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow(), timer);
|
||||
}
|
||||
|
||||
DistractMovementGenerator* mgen = new DistractMovementGenerator(timer);
|
||||
Mutate(mgen);
|
||||
}
|
||||
|
||||
void MotionMaster::Mutate(MovementGenerator *m)
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
switch(top()->GetMovementGeneratorType())
|
||||
{
|
||||
// HomeMovement is not that important, delete it if meanwhile a new comes
|
||||
case HOME_MOTION_TYPE:
|
||||
// DistractMovement interrupted by any other movement
|
||||
case DISTRACT_MOTION_TYPE:
|
||||
MovementExpired(false);
|
||||
}
|
||||
}
|
||||
m->Initialize(*i_owner);
|
||||
push(m);
|
||||
}
|
||||
|
||||
void MotionMaster::propagateSpeedChange()
|
||||
{
|
||||
Impl::container_type::iterator it = Impl::c.begin();
|
||||
for ( ;it != end(); ++it)
|
||||
{
|
||||
(*it)->unitSpeedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
|
||||
{
|
||||
if(empty())
|
||||
return IDLE_MOTION_TYPE;
|
||||
|
||||
return top()->GetMovementGeneratorType();
|
||||
}
|
||||
|
||||
bool MotionMaster::GetDestination(float &x, float &y, float &z)
|
||||
{
|
||||
if(empty())
|
||||
return false;
|
||||
|
||||
return top()->GetDestination(x,y,z);
|
||||
}
|
||||
|
||||
+1447
-1447
File diff suppressed because it is too large
Load Diff
+21
-7
@@ -6679,6 +6679,8 @@ void ObjectMgr::LoadTrainerSpell()
|
||||
itr->second.Clear();
|
||||
m_mCacheTrainerSpellMap.clear();
|
||||
|
||||
std::set<uint32> skip_trainers;
|
||||
|
||||
QueryResult *result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer");
|
||||
|
||||
if( !result )
|
||||
@@ -6714,7 +6716,11 @@ void ObjectMgr::LoadTrainerSpell()
|
||||
|
||||
if(!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER))
|
||||
{
|
||||
sLog.outErrorDb("Table `npc_trainer` have data for not creature template (Entry: %u) without trainer flag, ignore", entry);
|
||||
if(skip_trainers.count(entry) == 0)
|
||||
{
|
||||
sLog.outErrorDb("Table `npc_trainer` have data for not creature template (Entry: %u) without trainer flag, ignore", entry);
|
||||
skip_trainers.insert(entry);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -6764,6 +6770,8 @@ void ObjectMgr::LoadVendors()
|
||||
itr->second.Clear();
|
||||
m_mCacheVendorItemMap.clear();
|
||||
|
||||
std::set<uint32> skip_vendors;
|
||||
|
||||
QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor");
|
||||
if( !result )
|
||||
{
|
||||
@@ -6790,7 +6798,7 @@ void ObjectMgr::LoadVendors()
|
||||
uint32 incrtime = fields[3].GetUInt32();
|
||||
uint32 ExtendedCost = fields[4].GetUInt32();
|
||||
|
||||
if(!IsVendorItemValid(entry,item_id,maxcount,incrtime,ExtendedCost))
|
||||
if(!IsVendorItemValid(entry,item_id,maxcount,incrtime,ExtendedCost,NULL,&skip_vendors))
|
||||
continue;
|
||||
|
||||
VendorItemData& vList = m_mCacheVendorItemMap[entry];
|
||||
@@ -6878,7 +6886,7 @@ bool ObjectMgr::RemoveVendorItem( uint32 entry,uint32 item )
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* pl ) const
|
||||
bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* pl, std::set<uint32>* skip_vendors ) const
|
||||
{
|
||||
CreatureInfo const* cInfo = GetCreatureTemplate(vendor_entry);
|
||||
if(!cInfo)
|
||||
@@ -6892,10 +6900,16 @@ bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 m
|
||||
|
||||
if(!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR))
|
||||
{
|
||||
if(pl)
|
||||
ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION);
|
||||
else
|
||||
sLog.outErrorDb("Table `npc_vendor` have data for not creature template (Entry: %u) without vendor flag, ignore", vendor_entry);
|
||||
if(!skip_vendors || skip_vendors->count(vendor_entry)==0)
|
||||
{
|
||||
if(pl)
|
||||
ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION);
|
||||
else
|
||||
sLog.outErrorDb("Table `npc_vendor` have data for not creature template (Entry: %u) without vendor flag, ignore", vendor_entry);
|
||||
|
||||
if(skip_vendors)
|
||||
skip_vendors->insert(vendor_entry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -742,7 +742,7 @@ class ObjectMgr
|
||||
}
|
||||
void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost);
|
||||
bool RemoveVendorItem(uint32 entry,uint32 item);
|
||||
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL ) const;
|
||||
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL ) const;
|
||||
protected:
|
||||
uint32 m_auctionid;
|
||||
uint32 m_mailid;
|
||||
|
||||
+649
-648
File diff suppressed because it is too large
Load Diff
+936
-936
File diff suppressed because it is too large
Load Diff
+58
-16
@@ -265,8 +265,8 @@ Player::Player (WorldSession *session): Unit()
|
||||
if(GetSession()->GetSecurity() >= SEC_GAMEMASTER)
|
||||
SetAcceptTicket(true);
|
||||
|
||||
// players always and GM if set in config accept whispers by default
|
||||
if(GetSession()->GetSecurity() == SEC_PLAYER || sWorld.getConfig(CONFIG_GM_WISPERING_TO))
|
||||
// players always accept
|
||||
if(GetSession()->GetSecurity() == SEC_PLAYER)
|
||||
SetAcceptWhispers(true);
|
||||
|
||||
m_curSelection = 0;
|
||||
@@ -1415,7 +1415,7 @@ uint8 Player::chatTag() const
|
||||
// 0x4 - gm
|
||||
// 0x2 - dnd
|
||||
// 0x1 - afk
|
||||
if(isGameMaster())
|
||||
if(isGMChat())
|
||||
return 4;
|
||||
else if(isDND())
|
||||
return 3;
|
||||
@@ -1555,10 +1555,13 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
}
|
||||
}
|
||||
|
||||
SetSemaphoreTeleport(false);
|
||||
|
||||
if(!GetSession()->PlayerLogout())
|
||||
{
|
||||
// don't reset teleport semaphore while logging out, otherwise m_teleport_dest won't be used in Player::SaveToDB
|
||||
SetSemaphoreTeleport(false);
|
||||
|
||||
UpdateZone(GetZoneId());
|
||||
}
|
||||
|
||||
// new zone
|
||||
if(old_zone != GetZoneId())
|
||||
@@ -9322,6 +9325,11 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
|
||||
ItemPrototype const *pProto = pItem->GetProto();
|
||||
if( pProto )
|
||||
{
|
||||
// May be here should be more stronger checks; STUNNED checked
|
||||
// ROOT, CONFUSED, DISTRACTED, FLEEING this needs to be checked.
|
||||
if (not_loading && hasUnitState(UNIT_STAT_STUNNED))
|
||||
return EQUIP_ERR_YOU_ARE_STUNNED;
|
||||
|
||||
if(pItem->IsBindedNotWith(GetGUID()))
|
||||
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
|
||||
|
||||
@@ -9346,6 +9354,9 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
|
||||
if(isInCombat()&& pProto->Class == ITEM_CLASS_WEAPON && m_weaponChangeTimer != 0)
|
||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW; // maybe exist better err
|
||||
|
||||
if(IsNonMeleeSpellCasted(false))
|
||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||
|
||||
uint8 eslot = FindEquipSlot( pProto, slot, swap );
|
||||
if( eslot == NULL_SLOT )
|
||||
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
||||
@@ -13798,16 +13809,45 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
||||
{
|
||||
switch(sWorld.getConfig(CONFIG_GM_LOGIN_STATE))
|
||||
{
|
||||
case 0: // disable
|
||||
break;
|
||||
case 1: // enable
|
||||
SetGameMaster(true);
|
||||
break;
|
||||
default:
|
||||
case 0: break; // disable
|
||||
case 1: SetGameMaster(true); break; // enable
|
||||
case 2: // save state
|
||||
if(gmstate)
|
||||
if(gmstate & PLAYER_EXTRA_GM_ON)
|
||||
SetGameMaster(true);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(sWorld.getConfig(CONFIG_GM_ACCEPT_TICKETS))
|
||||
{
|
||||
default:
|
||||
case 0: break; // disable
|
||||
case 1: SetAcceptTicket(true); break; // enable
|
||||
case 2: // save state
|
||||
if(gmstate & PLAYER_EXTRA_GM_ACCEPT_TICKETS)
|
||||
SetAcceptTicket(true);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(sWorld.getConfig(CONFIG_GM_CHAT))
|
||||
{
|
||||
default:
|
||||
case 0: break; // disable
|
||||
case 1: SetGMChat(true); break; // enable
|
||||
case 2: // save state
|
||||
if(gmstate & PLAYER_EXTRA_GM_CHAT)
|
||||
SetGMChat(true);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(sWorld.getConfig(CONFIG_GM_WISPERING_TO))
|
||||
{
|
||||
default:
|
||||
case 0: break; // disable
|
||||
case 1: SetAcceptWhispers(true); break; // enable
|
||||
case 2: // save state
|
||||
if(gmstate & PLAYER_EXTRA_ACCEPT_WHISPERS)
|
||||
SetAcceptWhispers(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -14877,7 +14917,7 @@ void Player::SaveToDB()
|
||||
ss << "0";
|
||||
|
||||
ss << ", ";
|
||||
ss << (isGameMaster()? 1 : 0);
|
||||
ss << m_ExtraFlags;
|
||||
|
||||
ss << ", ";
|
||||
ss << uint32(m_stableSlots); // to prevent save uint8 as char
|
||||
@@ -16387,13 +16427,15 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
VendorItem const* crItem = vItems->FindItem(item);
|
||||
if(!crItem)
|
||||
size_t vendor_slot = vItems->FindItemSlot(item);
|
||||
if(vendor_slot >= vItems->GetItemCount())
|
||||
{
|
||||
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
VendorItem const* crItem = vItems->m_items[vendor_slot];
|
||||
|
||||
// check current item amount if it limited
|
||||
if( crItem->maxcount != 0 )
|
||||
{
|
||||
@@ -16520,7 +16562,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||
|
||||
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
|
||||
data << pCreature->GetGUID();
|
||||
data << (uint32)crItem->item;
|
||||
data << (uint32)(vendor_slot+1); // numbered from 1 at client
|
||||
data << (uint32)(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
|
||||
data << (uint32)count;
|
||||
GetSession()->SendPacket(&data);
|
||||
@@ -16559,7 +16601,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||
|
||||
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
|
||||
data << pCreature->GetGUID();
|
||||
data << (uint32)crItem->item;
|
||||
data << (uint32)(vendor_slot+1); // numbered from 1 at client
|
||||
data << (uint32)(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
|
||||
data << (uint32)count;
|
||||
GetSession()->SendPacket(&data);
|
||||
|
||||
@@ -496,6 +496,7 @@ enum PlayerExtraFlags
|
||||
PLAYER_EXTRA_ACCEPT_WHISPERS = 0x0004,
|
||||
PLAYER_EXTRA_TAXICHEAT = 0x0008,
|
||||
PLAYER_EXTRA_GM_INVISIBLE = 0x0010,
|
||||
PLAYER_EXTRA_GM_CHAT = 0x0020, // Show GM badge in chat messages
|
||||
|
||||
// other states
|
||||
PLAYER_EXTRA_PVP_DEATH = 0x0100 // store PvP death status until corpse creating.
|
||||
@@ -954,6 +955,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||
void SetAcceptWhispers(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; }
|
||||
bool isGameMaster() const { return m_ExtraFlags & PLAYER_EXTRA_GM_ON; }
|
||||
void SetGameMaster(bool on);
|
||||
bool isGMChat() const { return GetSession()->GetSecurity() >= SEC_MODERATOR && (m_ExtraFlags & PLAYER_EXTRA_GM_CHAT); }
|
||||
void SetGMChat(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_GM_CHAT; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_CHAT; }
|
||||
bool isTaxiCheater() const { return m_ExtraFlags & PLAYER_EXTRA_TAXICHEAT; }
|
||||
void SetTaxiCheater(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; }
|
||||
bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); }
|
||||
|
||||
@@ -41,7 +41,7 @@ bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||
if(!&unit)
|
||||
return false;
|
||||
|
||||
if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
|
||||
if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
|
||||
return true;
|
||||
|
||||
Traveller<T> traveller(unit);
|
||||
|
||||
@@ -126,7 +126,7 @@ template<>
|
||||
bool
|
||||
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
|
||||
{
|
||||
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED))
|
||||
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
|
||||
{
|
||||
i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer
|
||||
creature.clearUnitState(UNIT_STAT_ROAMING);
|
||||
|
||||
+311
-309
@@ -1,309 +1,311 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "SocialMgr.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Opcodes.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "Player.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "World.h"
|
||||
#include "Util.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1( SocialMgr );
|
||||
|
||||
PlayerSocial::PlayerSocial()
|
||||
{
|
||||
m_playerGUID = 0;
|
||||
}
|
||||
|
||||
PlayerSocial::~PlayerSocial()
|
||||
{
|
||||
m_playerSocialMap.clear();
|
||||
}
|
||||
|
||||
bool PlayerSocial::AddToSocialList(uint32 friend_guid, bool ignore)
|
||||
{
|
||||
// prevent list (client-side) overflow
|
||||
if(m_playerSocialMap.size() >= (255-1))
|
||||
return false;
|
||||
|
||||
uint32 flag = SOCIAL_FLAG_FRIEND;
|
||||
if(ignore)
|
||||
flag = SOCIAL_FLAG_IGNORED;
|
||||
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr != m_playerSocialMap.end())
|
||||
{
|
||||
CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags | %u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
|
||||
m_playerSocialMap[friend_guid].Flags |= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterDatabase.PExecute("INSERT INTO character_social (guid, friend, flags) VALUES ('%u', '%u', '%u')", GetPlayerGUID(), friend_guid, flag);
|
||||
FriendInfo fi;
|
||||
fi.Flags |= flag;
|
||||
m_playerSocialMap[friend_guid] = fi;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerSocial::RemoveFromSocialList(uint32 friend_guid, bool ignore)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr == m_playerSocialMap.end()) // not exist
|
||||
return;
|
||||
|
||||
uint32 flag = SOCIAL_FLAG_FRIEND;
|
||||
if(ignore)
|
||||
flag = SOCIAL_FLAG_IGNORED;
|
||||
|
||||
itr->second.Flags &= ~flag;
|
||||
if(itr->second.Flags == 0)
|
||||
{
|
||||
CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' AND friend = '%u'", GetPlayerGUID(), friend_guid);
|
||||
m_playerSocialMap.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags & ~%u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSocial::SetFriendNote(uint32 friend_guid, std::string note)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr == m_playerSocialMap.end()) // not exist
|
||||
return;
|
||||
|
||||
utf8truncate(note,48); // DB and client size limitation
|
||||
|
||||
CharacterDatabase.escape_string(note);
|
||||
CharacterDatabase.PExecute("UPDATE character_social SET note = '%s' WHERE guid = '%u' AND friend = '%u'", note.c_str(), GetPlayerGUID(), friend_guid);
|
||||
m_playerSocialMap[friend_guid].Note = note;
|
||||
}
|
||||
|
||||
void PlayerSocial::SendSocialList()
|
||||
{
|
||||
Player *plr = objmgr.GetPlayer(GetPlayerGUID());
|
||||
if(!plr)
|
||||
return;
|
||||
|
||||
uint32 size = m_playerSocialMap.size();
|
||||
|
||||
WorldPacket data(SMSG_CONTACT_LIST, (4+4+size*25)); // just can guess size
|
||||
data << uint32(7); // unk flag (0x1, 0x2, 0x4), 0x7 if it include ignore list
|
||||
data << uint32(size); // friends count
|
||||
|
||||
for(PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr)
|
||||
{
|
||||
sSocialMgr.GetFriendInfo(plr, itr->first, itr->second);
|
||||
|
||||
data << uint64(itr->first); // player guid
|
||||
data << uint32(itr->second.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?)
|
||||
data << itr->second.Note; // string note
|
||||
if(itr->second.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend()
|
||||
{
|
||||
data << uint8(itr->second.Status); // online/offline/etc?
|
||||
if(itr->second.Status) // if online
|
||||
{
|
||||
data << uint32(itr->second.Area); // player area
|
||||
data << uint32(itr->second.Level); // player level
|
||||
data << uint32(itr->second.Class); // player class
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
sLog.outDebug("WORLD: Sent SMSG_CONTACT_LIST");
|
||||
}
|
||||
|
||||
bool PlayerSocial::HasFriend(uint32 friend_guid)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr != m_playerSocialMap.end())
|
||||
return itr->second.Flags & SOCIAL_FLAG_FRIEND;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlayerSocial::HasIgnore(uint32 ignore_guid)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(ignore_guid);
|
||||
if(itr != m_playerSocialMap.end())
|
||||
return itr->second.Flags & SOCIAL_FLAG_IGNORED;
|
||||
return false;
|
||||
}
|
||||
|
||||
SocialMgr::SocialMgr()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SocialMgr::~SocialMgr()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SocialMgr::RemovePlayerSocial(uint32 guid)
|
||||
{
|
||||
SocialMap::iterator itr = m_socialMap.find(guid);
|
||||
if(itr != m_socialMap.end())
|
||||
m_socialMap.erase(itr);
|
||||
}
|
||||
|
||||
void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo)
|
||||
{
|
||||
if(!player)
|
||||
return;
|
||||
|
||||
Player *pFriend = ObjectAccessor::FindPlayer(friendGUID);
|
||||
|
||||
uint32 team = player->GetTeam();
|
||||
uint32 security = player->GetSession()->GetSecurity();
|
||||
bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
|
||||
bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST) || security > SEC_PLAYER;
|
||||
|
||||
// PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
|
||||
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
|
||||
if( pFriend && pFriend->GetName() &&
|
||||
( security > SEC_PLAYER ||
|
||||
( pFriend->GetTeam() == team || allowTwoSideWhoList ) &&
|
||||
( pFriend->GetSession()->GetSecurity() == SEC_PLAYER || gmInWhoList && pFriend->IsVisibleGloballyFor(player) )))
|
||||
{
|
||||
friendInfo.Status = FRIEND_STATUS_ONLINE;
|
||||
if(pFriend->isAFK())
|
||||
friendInfo.Status = FRIEND_STATUS_AFK;
|
||||
if(pFriend->isDND())
|
||||
friendInfo.Status = FRIEND_STATUS_DND;
|
||||
friendInfo.Area = pFriend->GetZoneId();
|
||||
friendInfo.Level = pFriend->getLevel();
|
||||
friendInfo.Class = pFriend->getClass();
|
||||
}
|
||||
else
|
||||
{
|
||||
friendInfo.Status = FRIEND_STATUS_OFFLINE;
|
||||
friendInfo.Area = 0;
|
||||
friendInfo.Level = 0;
|
||||
friendInfo.Class = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldPacket *data)
|
||||
{
|
||||
data->Initialize(SMSG_FRIEND_STATUS, 5);
|
||||
*data << uint8(result);
|
||||
*data << uint64(guid);
|
||||
}
|
||||
|
||||
void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast)
|
||||
{
|
||||
FriendInfo fi;
|
||||
|
||||
WorldPacket data;
|
||||
MakeFriendStatusPacket(result, friend_guid, &data);
|
||||
switch(result)
|
||||
{
|
||||
case FRIEND_ONLINE:
|
||||
GetFriendInfo(player, friend_guid, fi);
|
||||
data << uint8(fi.Status);
|
||||
data << uint32(fi.Area);
|
||||
data << uint32(fi.Level);
|
||||
data << uint32(fi.Class);
|
||||
break;
|
||||
case FRIEND_ADDED_ONLINE:
|
||||
GetFriendInfo(player, friend_guid, fi);
|
||||
data << name;
|
||||
data << uint8(fi.Status);
|
||||
data << uint32(fi.Area);
|
||||
data << uint32(fi.Level);
|
||||
data << uint32(fi.Class);
|
||||
break;
|
||||
case FRIEND_ADDED_OFFLINE:
|
||||
data << name;
|
||||
break;
|
||||
}
|
||||
|
||||
if(broadcast)
|
||||
BroadcastToFriendListers(player, &data);
|
||||
else
|
||||
player->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void SocialMgr::BroadcastToFriendListers(Player *player, WorldPacket *packet)
|
||||
{
|
||||
if(!player)
|
||||
return;
|
||||
|
||||
uint32 team = player->GetTeam();
|
||||
uint32 security = player->GetSession()->GetSecurity();
|
||||
uint32 guid = player->GetGUIDLow();
|
||||
bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST);
|
||||
bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
|
||||
|
||||
for(SocialMap::iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
|
||||
{
|
||||
PlayerSocialMap::iterator itr2 = itr->second.m_playerSocialMap.find(guid);
|
||||
if(itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
|
||||
{
|
||||
Player *pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
|
||||
|
||||
// PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
|
||||
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
|
||||
if( pFriend && pFriend->IsInWorld() &&
|
||||
( pFriend->GetSession()->GetSecurity() > SEC_PLAYER ||
|
||||
( pFriend->GetTeam() == team || allowTwoSideWhoList ) &&
|
||||
(security == SEC_PLAYER || gmInWhoList && player->IsVisibleGloballyFor(pFriend) )))
|
||||
{
|
||||
pFriend->GetSession()->SendPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerSocial *SocialMgr::LoadFromDB(QueryResult *result, uint32 guid)
|
||||
{
|
||||
PlayerSocial *social = &m_socialMap[guid];
|
||||
social->SetPlayerGUID(guid);
|
||||
|
||||
if(!result)
|
||||
return social;
|
||||
|
||||
uint32 friend_guid = 0;
|
||||
uint32 flags = 0;
|
||||
std::string note = "";
|
||||
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
friend_guid = fields[0].GetUInt32();
|
||||
flags = fields[1].GetUInt32();
|
||||
note = fields[2].GetCppString();
|
||||
|
||||
social->m_playerSocialMap[friend_guid] = FriendInfo(flags, note);
|
||||
|
||||
// prevent list (client-side) overflow
|
||||
if(social->m_playerSocialMap.size() >= 255)
|
||||
break;
|
||||
}
|
||||
while( result->NextRow() );
|
||||
delete result;
|
||||
return social;
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "SocialMgr.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Opcodes.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "Player.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "World.h"
|
||||
#include "Util.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1( SocialMgr );
|
||||
|
||||
PlayerSocial::PlayerSocial()
|
||||
{
|
||||
m_playerGUID = 0;
|
||||
}
|
||||
|
||||
PlayerSocial::~PlayerSocial()
|
||||
{
|
||||
m_playerSocialMap.clear();
|
||||
}
|
||||
|
||||
bool PlayerSocial::AddToSocialList(uint32 friend_guid, bool ignore)
|
||||
{
|
||||
// client limit
|
||||
if(m_playerSocialMap.size() >= 50)
|
||||
return false;
|
||||
|
||||
uint32 flag = SOCIAL_FLAG_FRIEND;
|
||||
if(ignore)
|
||||
flag = SOCIAL_FLAG_IGNORED;
|
||||
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr != m_playerSocialMap.end())
|
||||
{
|
||||
CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags | %u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
|
||||
m_playerSocialMap[friend_guid].Flags |= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterDatabase.PExecute("INSERT INTO character_social (guid, friend, flags) VALUES ('%u', '%u', '%u')", GetPlayerGUID(), friend_guid, flag);
|
||||
FriendInfo fi;
|
||||
fi.Flags |= flag;
|
||||
m_playerSocialMap[friend_guid] = fi;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerSocial::RemoveFromSocialList(uint32 friend_guid, bool ignore)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr == m_playerSocialMap.end()) // not exist
|
||||
return;
|
||||
|
||||
uint32 flag = SOCIAL_FLAG_FRIEND;
|
||||
if(ignore)
|
||||
flag = SOCIAL_FLAG_IGNORED;
|
||||
|
||||
itr->second.Flags &= ~flag;
|
||||
if(itr->second.Flags == 0)
|
||||
{
|
||||
CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' AND friend = '%u'", GetPlayerGUID(), friend_guid);
|
||||
m_playerSocialMap.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags & ~%u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSocial::SetFriendNote(uint32 friend_guid, std::string note)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr == m_playerSocialMap.end()) // not exist
|
||||
return;
|
||||
|
||||
utf8truncate(note,48); // DB and client size limitation
|
||||
|
||||
CharacterDatabase.escape_string(note);
|
||||
CharacterDatabase.PExecute("UPDATE character_social SET note = '%s' WHERE guid = '%u' AND friend = '%u'", note.c_str(), GetPlayerGUID(), friend_guid);
|
||||
m_playerSocialMap[friend_guid].Note = note;
|
||||
}
|
||||
|
||||
void PlayerSocial::SendSocialList()
|
||||
{
|
||||
Player *plr = objmgr.GetPlayer(GetPlayerGUID());
|
||||
if(!plr)
|
||||
return;
|
||||
|
||||
uint32 size = m_playerSocialMap.size();
|
||||
|
||||
WorldPacket data(SMSG_CONTACT_LIST, (4+4+size*25)); // just can guess size
|
||||
data << uint32(7); // unk flag (0x1, 0x2, 0x4), 0x7 if it include ignore list
|
||||
data << uint32(size); // friends count
|
||||
|
||||
for(PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr)
|
||||
{
|
||||
sSocialMgr.GetFriendInfo(plr, itr->first, itr->second);
|
||||
|
||||
data << uint64(itr->first); // player guid
|
||||
data << uint32(itr->second.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?)
|
||||
data << itr->second.Note; // string note
|
||||
if(itr->second.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend()
|
||||
{
|
||||
data << uint8(itr->second.Status); // online/offline/etc?
|
||||
if(itr->second.Status) // if online
|
||||
{
|
||||
data << uint32(itr->second.Area); // player area
|
||||
data << uint32(itr->second.Level); // player level
|
||||
data << uint32(itr->second.Class); // player class
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
sLog.outDebug("WORLD: Sent SMSG_CONTACT_LIST");
|
||||
}
|
||||
|
||||
bool PlayerSocial::HasFriend(uint32 friend_guid)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
|
||||
if(itr != m_playerSocialMap.end())
|
||||
return itr->second.Flags & SOCIAL_FLAG_FRIEND;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlayerSocial::HasIgnore(uint32 ignore_guid)
|
||||
{
|
||||
PlayerSocialMap::iterator itr = m_playerSocialMap.find(ignore_guid);
|
||||
if(itr != m_playerSocialMap.end())
|
||||
return itr->second.Flags & SOCIAL_FLAG_IGNORED;
|
||||
return false;
|
||||
}
|
||||
|
||||
SocialMgr::SocialMgr()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SocialMgr::~SocialMgr()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SocialMgr::RemovePlayerSocial(uint32 guid)
|
||||
{
|
||||
SocialMap::iterator itr = m_socialMap.find(guid);
|
||||
if(itr != m_socialMap.end())
|
||||
m_socialMap.erase(itr);
|
||||
}
|
||||
|
||||
void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo)
|
||||
{
|
||||
if(!player)
|
||||
return;
|
||||
|
||||
Player *pFriend = ObjectAccessor::FindPlayer(friendGUID);
|
||||
|
||||
uint32 team = player->GetTeam();
|
||||
uint32 security = player->GetSession()->GetSecurity();
|
||||
bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
|
||||
bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST) || security > SEC_PLAYER;
|
||||
|
||||
PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID);
|
||||
if(itr != player->GetSocial()->m_playerSocialMap.end())
|
||||
friendInfo.Note = itr->second.Note;
|
||||
|
||||
// PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
|
||||
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
|
||||
if( pFriend && pFriend->GetName() &&
|
||||
( security > SEC_PLAYER ||
|
||||
( pFriend->GetTeam() == team || allowTwoSideWhoList ) &&
|
||||
( pFriend->GetSession()->GetSecurity() == SEC_PLAYER || gmInWhoList && pFriend->IsVisibleGloballyFor(player) )))
|
||||
{
|
||||
friendInfo.Status = FRIEND_STATUS_ONLINE;
|
||||
if(pFriend->isAFK())
|
||||
friendInfo.Status = FRIEND_STATUS_AFK;
|
||||
if(pFriend->isDND())
|
||||
friendInfo.Status = FRIEND_STATUS_DND;
|
||||
friendInfo.Area = pFriend->GetZoneId();
|
||||
friendInfo.Level = pFriend->getLevel();
|
||||
friendInfo.Class = pFriend->getClass();
|
||||
}
|
||||
else
|
||||
{
|
||||
friendInfo.Status = FRIEND_STATUS_OFFLINE;
|
||||
friendInfo.Area = 0;
|
||||
friendInfo.Level = 0;
|
||||
friendInfo.Class = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldPacket *data)
|
||||
{
|
||||
data->Initialize(SMSG_FRIEND_STATUS, 5);
|
||||
*data << uint8(result);
|
||||
*data << uint64(guid);
|
||||
}
|
||||
|
||||
void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast)
|
||||
{
|
||||
FriendInfo fi;
|
||||
|
||||
WorldPacket data;
|
||||
MakeFriendStatusPacket(result, friend_guid, &data);
|
||||
GetFriendInfo(player, friend_guid, fi);
|
||||
switch(result)
|
||||
{
|
||||
case FRIEND_ADDED_OFFLINE:
|
||||
case FRIEND_ADDED_ONLINE:
|
||||
data << fi.Note;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(result)
|
||||
{
|
||||
case FRIEND_ADDED_ONLINE:
|
||||
case FRIEND_ONLINE:
|
||||
data << uint8(fi.Status);
|
||||
data << uint32(fi.Area);
|
||||
data << uint32(fi.Level);
|
||||
data << uint32(fi.Class);
|
||||
break;
|
||||
}
|
||||
|
||||
if(broadcast)
|
||||
BroadcastToFriendListers(player, &data);
|
||||
else
|
||||
player->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void SocialMgr::BroadcastToFriendListers(Player *player, WorldPacket *packet)
|
||||
{
|
||||
if(!player)
|
||||
return;
|
||||
|
||||
uint32 team = player->GetTeam();
|
||||
uint32 security = player->GetSession()->GetSecurity();
|
||||
uint32 guid = player->GetGUIDLow();
|
||||
bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST);
|
||||
bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
|
||||
|
||||
for(SocialMap::iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
|
||||
{
|
||||
PlayerSocialMap::iterator itr2 = itr->second.m_playerSocialMap.find(guid);
|
||||
if(itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
|
||||
{
|
||||
Player *pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
|
||||
|
||||
// PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
|
||||
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
|
||||
if( pFriend && pFriend->IsInWorld() &&
|
||||
( pFriend->GetSession()->GetSecurity() > SEC_PLAYER ||
|
||||
( pFriend->GetTeam() == team || allowTwoSideWhoList ) &&
|
||||
(security == SEC_PLAYER || gmInWhoList && player->IsVisibleGloballyFor(pFriend) )))
|
||||
{
|
||||
pFriend->GetSession()->SendPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerSocial *SocialMgr::LoadFromDB(QueryResult *result, uint32 guid)
|
||||
{
|
||||
PlayerSocial *social = &m_socialMap[guid];
|
||||
social->SetPlayerGUID(guid);
|
||||
|
||||
if(!result)
|
||||
return social;
|
||||
|
||||
uint32 friend_guid = 0;
|
||||
uint32 flags = 0;
|
||||
std::string note = "";
|
||||
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
friend_guid = fields[0].GetUInt32();
|
||||
flags = fields[1].GetUInt32();
|
||||
note = fields[2].GetCppString();
|
||||
|
||||
social->m_playerSocialMap[friend_guid] = FriendInfo(flags, note);
|
||||
|
||||
// client limit
|
||||
if(social->m_playerSocialMap.size() >= 50)
|
||||
break;
|
||||
}
|
||||
while( result->NextRow() );
|
||||
delete result;
|
||||
return social;
|
||||
}
|
||||
|
||||
+2
-2
@@ -986,7 +986,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
||||
|
||||
if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) )
|
||||
{
|
||||
if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNDED))
|
||||
if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED))
|
||||
unit->SetStandState(PLAYER_STATE_NONE);
|
||||
|
||||
if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI())
|
||||
@@ -2407,7 +2407,7 @@ void Spell::update(uint32 difftime)
|
||||
cancel();
|
||||
|
||||
// check for incapacitating player states
|
||||
if( m_caster->hasUnitState(UNIT_STAT_STUNDED | UNIT_STAT_CONFUSED))
|
||||
if( m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_CONFUSED))
|
||||
cancel();
|
||||
|
||||
// check if player has turned if flag is set
|
||||
|
||||
+6360
-6360
File diff suppressed because it is too large
Load Diff
@@ -1465,7 +1465,7 @@ void Spell::EffectDummy(uint32 i)
|
||||
if(!spell_proto)
|
||||
return;
|
||||
|
||||
if( !unitTarget->hasUnitState(UNIT_STAT_STUNDED) && m_caster->GetTypeId()==TYPEID_PLAYER)
|
||||
if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
// decreased damage (/2) for non-stunned target.
|
||||
SpellModifier *mod = new SpellModifier;
|
||||
@@ -3401,7 +3401,7 @@ void Spell::EffectDistract(uint32 /*i*/)
|
||||
return;
|
||||
|
||||
// target must be OK to do this
|
||||
if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING ) )
|
||||
if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
|
||||
return;
|
||||
|
||||
float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
|
||||
|
||||
@@ -47,7 +47,7 @@ TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
|
||||
if( !i_target.isValid() || !&owner )
|
||||
return;
|
||||
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED) )
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) )
|
||||
return;
|
||||
|
||||
// prevent redundant micro-movement for pets, other followers.
|
||||
@@ -127,7 +127,7 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
|
||||
if( !&owner || !owner.isAlive())
|
||||
return true;
|
||||
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED) )
|
||||
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED) )
|
||||
return true;
|
||||
|
||||
// prevent movement while casting spells with cast time or channel time
|
||||
|
||||
+634
-633
File diff suppressed because it is too large
Load Diff
+8
-8
@@ -470,7 +470,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
|
||||
if(pVictim != this)
|
||||
RemoveSpellsCausingAura(SPELL_AURA_MOD_INVISIBILITY);
|
||||
|
||||
if(pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNDED))
|
||||
if(pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNNED))
|
||||
pVictim->SetStandState(PLAYER_STATE_NONE);
|
||||
}
|
||||
|
||||
@@ -2149,7 +2149,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama
|
||||
|
||||
void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool extra )
|
||||
{
|
||||
if(hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) )
|
||||
if(hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) )
|
||||
return;
|
||||
|
||||
if (!pVictim->isAlive())
|
||||
@@ -2961,7 +2961,7 @@ uint32 Unit::GetDefenseSkillValue(Unit const* target) const
|
||||
|
||||
float Unit::GetUnitDodgeChance() const
|
||||
{
|
||||
if(hasUnitState(UNIT_STAT_STUNDED))
|
||||
if(hasUnitState(UNIT_STAT_STUNNED))
|
||||
return 0.0f;
|
||||
if( GetTypeId() == TYPEID_PLAYER )
|
||||
return GetFloatValue(PLAYER_DODGE_PERCENTAGE);
|
||||
@@ -2980,7 +2980,7 @@ float Unit::GetUnitDodgeChance() const
|
||||
|
||||
float Unit::GetUnitParryChance() const
|
||||
{
|
||||
if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNDED))
|
||||
if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNNED))
|
||||
return 0.0f;
|
||||
|
||||
float chance = 0.0f;
|
||||
@@ -3012,7 +3012,7 @@ float Unit::GetUnitParryChance() const
|
||||
|
||||
float Unit::GetUnitBlockChance() const
|
||||
{
|
||||
if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNDED))
|
||||
if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNNED))
|
||||
return 0.0f;
|
||||
|
||||
if(GetTypeId() == TYPEID_PLAYER)
|
||||
@@ -7985,7 +7985,7 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
|
||||
//FIX ME this hack: don't get feared if stunned
|
||||
if (spellInfo->Mechanic == MECHANIC_FEAR )
|
||||
{
|
||||
if ( hasUnitState(UNIT_STAT_STUNDED) )
|
||||
if ( hasUnitState(UNIT_STAT_STUNNED) )
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8662,7 +8662,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList)
|
||||
return true;
|
||||
|
||||
//If a mob or player is stunned he will not be able to detect stealth
|
||||
if (u->hasUnitState(UNIT_STAT_STUNDED) && (u != this))
|
||||
if (u->hasUnitState(UNIT_STAT_STUNNED) && (u != this))
|
||||
return false;
|
||||
|
||||
// Creature can detect target only in aggro radius
|
||||
@@ -9136,7 +9136,7 @@ bool Unit::SelectHostilTarget()
|
||||
|
||||
if(target)
|
||||
{
|
||||
if(!hasUnitState(UNIT_STAT_STUNDED))
|
||||
if(!hasUnitState(UNIT_STAT_STUNNED))
|
||||
SetInFront(target);
|
||||
((Creature*)this)->AI()->AttackStart(target);
|
||||
return true;
|
||||
|
||||
+2
-2
@@ -346,7 +346,7 @@ enum UnitState
|
||||
UNIT_STAT_DIED = 0x0001,
|
||||
UNIT_STAT_MELEE_ATTACKING = 0x0002, // player is melee attacking someone
|
||||
//UNIT_STAT_MELEE_ATTACK_BY = 0x0004, // player is melee attack by someone
|
||||
UNIT_STAT_STUNDED = 0x0008,
|
||||
UNIT_STAT_STUNNED = 0x0008,
|
||||
UNIT_STAT_ROAMING = 0x0010,
|
||||
UNIT_STAT_CHASE = 0x0020,
|
||||
UNIT_STAT_SEARCHING = 0x0040,
|
||||
@@ -756,7 +756,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||
bool CanFreeMove() const
|
||||
{
|
||||
return !hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_IN_FLIGHT |
|
||||
UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED ) && GetOwnerGUID()==0;
|
||||
UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED ) && GetOwnerGUID()==0;
|
||||
}
|
||||
|
||||
uint32 getLevel() const { return GetUInt32Value(UNIT_FIELD_LEVEL); }
|
||||
|
||||
@@ -85,7 +85,7 @@ WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &di
|
||||
|
||||
// Waypoint movement can be switched on/off
|
||||
// This is quite handy for escort quests and other stuff
|
||||
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED))
|
||||
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
|
||||
return true;
|
||||
|
||||
// prevent a crash at empty waypoint path.
|
||||
|
||||
+8
-5
@@ -642,11 +642,14 @@ void World::LoadConfigSettings(bool reload)
|
||||
m_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
|
||||
}
|
||||
|
||||
m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetBoolDefault("GM.WhisperingTo",false);
|
||||
m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList",false);
|
||||
m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false);
|
||||
m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2);
|
||||
m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false);
|
||||
m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2);
|
||||
m_configs[CONFIG_GM_ACCEPT_TICKETS] = sConfig.GetIntDefault("GM.AcceptTickets",2);
|
||||
m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat",2);
|
||||
m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo",2);
|
||||
|
||||
m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList",false);
|
||||
m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false);
|
||||
m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false);
|
||||
|
||||
m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0);
|
||||
|
||||
|
||||
+542
-540
File diff suppressed because it is too large
Load Diff
+511
-493
File diff suppressed because it is too large
Load Diff
+643
-642
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user