[9596] Use area trigger zone check for inn leave case.

This is still have false cases but will more correct for specific area triggers.
Also let cleanup code and store less data for Player.
This commit is contained in:
VladimirMangos 2010-03-17 01:38:26 +03:00
parent 56c08e2ef9
commit db51c29235
6 changed files with 91 additions and 108 deletions

View file

@ -837,6 +837,51 @@ uint32 const* GetTalentTabPages(uint32 cls)
return sTalentTabPages[cls]; return sTalentTabPages[cls];
} }
bool IsPointInAreaTriggerZone(AreaTriggerEntry const* atEntry, uint32 mapid, float x, float y, float z, float delta)
{
if (mapid != atEntry->mapid)
return false;
if (atEntry->radius > 0)
{
// if we have radius check it
float dist2 = (x-atEntry->x)*(x-atEntry->x) + (y-atEntry->y)*(y-atEntry->y) + (z-atEntry->z)*(z-atEntry->z);
if(dist2 > (atEntry->radius + delta)*(atEntry->radius + delta))
return false;
}
else
{
// we have only extent
// rotate the players position instead of rotating the whole cube, that way we can make a simplified
// is-in-cube check and we have to calculate only one point instead of 4
// 2PI = 360°, keep in mind that ingame orientation is counter-clockwise
double rotation = 2*M_PI-atEntry->box_orientation;
double sinVal = sin(rotation);
double cosVal = cos(rotation);
float playerBoxDistX = x - atEntry->x;
float playerBoxDistY = y - atEntry->y;
float rotPlayerX = float(atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal);
float rotPlayerY = float(atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal);
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
float dz = z - atEntry->z;
float dx = rotPlayerX - atEntry->x;
float dy = rotPlayerY - atEntry->y;
if( (fabs(dx) > atEntry->box_x/2 + delta) ||
(fabs(dy) > atEntry->box_y/2 + delta) ||
(fabs(dz) > atEntry->box_z/2 + delta) )
{
return false;
}
}
return true;
}
// script support functions // script support functions
MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore() { return &sSoundEntriesStore; } MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore() { return &sSoundEntriesStore; }
MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() { return &sSpellStore; } MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() { return &sSpellStore; }

View file

@ -63,6 +63,8 @@ MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls); uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls);
bool IsPointInAreaTriggerZone(AreaTriggerEntry const* atEntry, uint32 mapid, float x, float y, float z, float delta = 0.0f);
PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level); PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level);
PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattleGroundBracketId id); PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattleGroundBracketId id);

View file

@ -695,92 +695,43 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
return; return;
} }
if (GetPlayer()->GetMapId() != atEntry->mapid)
{
sLog.outDebug("Player '%s' (GUID: %u) too far (trigger map: %u player map: %u), ignore Area Trigger ID: %u", GetPlayer()->GetName(), atEntry->mapid, GetPlayer()->GetMapId(), GetPlayer()->GetGUIDLow(), Trigger_ID);
return;
}
// delta is safe radius // delta is safe radius
const float delta = 5.0f; const float delta = 5.0f;
// check if player in the range of areatrigger // check if player in the range of areatrigger
Player* pl = GetPlayer(); Player* pl = GetPlayer();
if (atEntry->radius > 0) if (!IsPointInAreaTriggerZone(atEntry, pl->GetMapId(), pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), delta))
{ {
// if we have radius check it sLog.outDebug("Player '%s' (GUID: %u) too far, ignore Area Trigger ID: %u", pl->GetName(), pl->GetGUIDLow(), Trigger_ID);
float dist = pl->GetDistance(atEntry->x, atEntry->y, atEntry->z); return;
if(dist > atEntry->radius + delta)
{
sLog.outDebug("Player '%s' (GUID: %u) too far (radius: %f distance: %f), ignore Area Trigger ID: %u",
pl->GetName(), pl->GetGUIDLow(), atEntry->radius, dist, Trigger_ID);
return;
}
}
else
{
// we have only extent
// rotate the players position instead of rotating the whole cube, that way we can make a simplified
// is-in-cube check and we have to calculate only one point instead of 4
// 2PI = 360°, keep in mind that ingame orientation is counter-clockwise
double rotation = 2*M_PI-atEntry->box_orientation;
double sinVal = sin(rotation);
double cosVal = cos(rotation);
float playerBoxDistX = pl->GetPositionX() - atEntry->x;
float playerBoxDistY = pl->GetPositionY() - atEntry->y;
float rotPlayerX = float(atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal);
float rotPlayerY = float(atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal);
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
float dz = pl->GetPositionZ() - atEntry->z;
float dx = rotPlayerX - atEntry->x;
float dy = rotPlayerY - atEntry->y;
if( (fabs(dx) > atEntry->box_x/2 + delta) ||
(fabs(dy) > atEntry->box_y/2 + delta) ||
(fabs(dz) > atEntry->box_z/2 + delta) )
{
sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u",
pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotPlayerX, rotPlayerY, dz, Trigger_ID);
return;
}
} }
if(Script->scriptAreaTrigger(GetPlayer(), atEntry)) if(Script->scriptAreaTrigger(pl, atEntry))
return; return;
uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger( Trigger_ID ); uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger( Trigger_ID );
if( quest_id && GetPlayer()->isAlive() && GetPlayer()->IsActiveQuest(quest_id) ) if( quest_id && pl->isAlive() && pl->IsActiveQuest(quest_id) )
{ {
Quest const* pQuest = sObjectMgr.GetQuestTemplate(quest_id); Quest const* pQuest = sObjectMgr.GetQuestTemplate(quest_id);
if( pQuest ) if( pQuest )
{ {
if(GetPlayer()->GetQuestStatus(quest_id) == QUEST_STATUS_INCOMPLETE) if(pl->GetQuestStatus(quest_id) == QUEST_STATUS_INCOMPLETE)
GetPlayer()->AreaExploredOrEventHappens( quest_id ); pl->AreaExploredOrEventHappens( quest_id );
} }
} }
if(sObjectMgr.IsTavernAreaTrigger(Trigger_ID)) // enter to tavern, not overwrite city rest
if(sObjectMgr.IsTavernAreaTrigger(Trigger_ID) && pl->GetRestType() != REST_TYPE_IN_CITY)
{ {
// set resting flag we are in the inn // set resting flag we are in the inn
GetPlayer()->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); pl->SetRestType(REST_TYPE_IN_TAVERN, Trigger_ID);
GetPlayer()->InnEnter(time(NULL), atEntry->mapid, atEntry->x, atEntry->y, atEntry->z);
GetPlayer()->SetRestType(REST_TYPE_IN_TAVERN);
if(sWorld.IsFFAPvPRealm())
GetPlayer()->SetFFAPvP(false);
return; return;
} }
if(GetPlayer()->InBattleGround()) if(pl->InBattleGround())
{ {
BattleGround* bg = GetPlayer()->GetBattleGround(); if (BattleGround* bg = pl->GetBattleGround())
if(bg) bg->HandleAreaTrigger(pl, Trigger_ID);
bg->HandleAreaTrigger(GetPlayer(), Trigger_ID);
return; return;
} }

View file

@ -431,10 +431,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
////////////////////Rest System///////////////////// ////////////////////Rest System/////////////////////
time_inn_enter=0; time_inn_enter=0;
inn_pos_mapid=0; inn_trigger_id=0;
inn_pos_x=0;
inn_pos_y=0;
inn_pos_z=0;
m_rest_bonus=0; m_rest_bonus=0;
rest_type=REST_TYPE_NO; rest_type=REST_TYPE_NO;
////////////////////Rest System///////////////////// ////////////////////Rest System/////////////////////
@ -1246,7 +1243,7 @@ void Player::Update( uint32 p_time )
if (time_inn >= 10) //freeze update if (time_inn >= 10) //freeze update
{ {
float bubble = 0.125f*sWorld.getConfig(CONFIG_FLOAT_RATE_REST_INGAME); float bubble = 0.125f*sWorld.getConfig(CONFIG_FLOAT_RATE_REST_INGAME);
//speed collect rest bonus (section/in hour) //speed collect rest bonus (section/in hour)
SetRestBonus( float(GetRestBonus()+ time_inn*(GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble )); SetRestBonus( float(GetRestBonus()+ time_inn*(GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble ));
UpdateInnerTime(time(NULL)); UpdateInnerTime(time(NULL));
} }
@ -6473,38 +6470,19 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
} }
if(zone->flags & AREA_FLAG_CAPITAL) // in capital city if(zone->flags & AREA_FLAG_CAPITAL) // in capital city
{
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_IN_CITY); SetRestType(REST_TYPE_IN_CITY);
InnEnter(time(0),GetMapId(),0,0,0);
if(sWorld.IsFFAPvPRealm())
SetFFAPvP(false);
}
else // anywhere else else // anywhere else
{ {
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) // but resting (walk from city or maybe in tavern or leave tavern recently) if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) // but resting (walk from city or maybe in tavern or leave tavern recently)
{ {
if (GetRestType()==REST_TYPE_IN_TAVERN) // has been in tavern. Is still in? if (GetRestType()==REST_TYPE_IN_TAVERN) // has been in tavern. Is still in?
{ {
if (GetMapId()!=GetInnPosMapId() || ((GetPositionX()-GetInnPosX())*(GetPositionX()-GetInnPosX())+(GetPositionY()-GetInnPosY())*(GetPositionY()-GetInnPosY())+(GetPositionZ()-GetInnPosZ())*(GetPositionZ()-GetInnPosZ())) > 30*30) AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(inn_trigger_id);
{ if (!at || !IsPointInAreaTriggerZone(at, GetMapId(), GetPositionX(), GetPositionY(), GetPositionY()))
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO); SetRestType(REST_TYPE_NO);
if(sWorld.IsFFAPvPRealm())
SetFFAPvP(true);
}
} }
else // not in tavern (leave city then) else // not in tavern (leave city then)
{
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO); SetRestType(REST_TYPE_NO);
// Set player to FFA PVP when not in rested environment.
if(sWorld.IsFFAPvPRealm())
SetFFAPvP(true);
}
} }
} }
@ -21721,3 +21699,27 @@ Object* Player::GetObjectByTypeMask(ObjectGuid guid, TypeMask typemask)
return NULL; return NULL;
} }
void Player::SetRestType( RestType n_r_type, uint32 areaTriggerId /*= 0*/)
{
rest_type = n_r_type;
if (rest_type == REST_TYPE_NO)
{
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
// Set player to FFA PVP when not in rested environment.
if(sWorld.IsFFAPvPRealm())
SetFFAPvP(true);
}
else
{
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
inn_trigger_id = areaTriggerId;
time_inn_enter = time(NULL);
if(sWorld.IsFFAPvPRealm())
SetFFAPvP(false);
}
}

View file

@ -1099,25 +1099,11 @@ class MANGOS_DLL_SPEC Player : public Unit
void setDeathState(DeathState s); // overwrite Unit::setDeathState void setDeathState(DeathState s); // overwrite Unit::setDeathState
void InnEnter (time_t time, uint32 mapid, float x, float y, float z)
{
inn_pos_mapid = mapid;
inn_pos_x = x;
inn_pos_y = y;
inn_pos_z = z;
time_inn_enter = time;
}
float GetRestBonus() const { return m_rest_bonus; } float GetRestBonus() const { return m_rest_bonus; }
void SetRestBonus(float rest_bonus_new); void SetRestBonus(float rest_bonus_new);
RestType GetRestType() const { return rest_type; } RestType GetRestType() const { return rest_type; }
void SetRestType(RestType n_r_type) { rest_type = n_r_type; } void SetRestType(RestType n_r_type, uint32 areaTriggerId = 0);
uint32 GetInnPosMapId() const { return inn_pos_mapid; }
float GetInnPosX() const { return inn_pos_x; }
float GetInnPosY() const { return inn_pos_y; }
float GetInnPosZ() const { return inn_pos_z; }
time_t GetTimeInnEnter() const { return time_inn_enter; } time_t GetTimeInnEnter() const { return time_inn_enter; }
void UpdateInnerTime (time_t time) { time_inn_enter = time; } void UpdateInnerTime (time_t time) { time_inn_enter = time; }
@ -2472,10 +2458,7 @@ class MANGOS_DLL_SPEC Player : public Unit
////////////////////Rest System///////////////////// ////////////////////Rest System/////////////////////
time_t time_inn_enter; time_t time_inn_enter;
uint32 inn_pos_mapid; uint32 inn_trigger_id;
float inn_pos_x;
float inn_pos_y;
float inn_pos_z;
float m_rest_bonus; float m_rest_bonus;
RestType rest_type; RestType rest_type;
////////////////////Rest System///////////////////// ////////////////////Rest System/////////////////////

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9595" #define REVISION_NR "9596"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__