[11557] Duel related fixes

* Implement duel allowed check base at proper area flag AREA_FLAG_DUEL (0x00000040)
  This allow duels for example in capital area 4570 and allow/fogbid correctly some other zones and areas.
* Implement duel cancel at leave duel allowed area
* Fixed code for duels work in sunctuary if area allow duels.
This commit is contained in:
VladimirMangos 2011-05-29 01:42:47 +04:00
parent 7205023415
commit 4a087e6bda
8 changed files with 89 additions and 63 deletions

View file

@ -221,7 +221,7 @@ enum AreaFlags
AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag? AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
AREA_FLAG_UNK4 = 0x00000040, // many zones have this flag AREA_FLAG_DUEL = 0x00000040, // zones where duels allowed
AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?) AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)

View file

@ -1324,9 +1324,8 @@ void Player::Update( uint32 update_diff, uint32 p_time )
} }
} }
Unit *owner = pVictim->GetOwner(); Player *vOwner = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself();
Unit *u = owner ? owner : pVictim; if (vOwner && vOwner->IsPvP() && !IsInDuelWith(vOwner))
if (u->IsPvP() && (!duel || duel->opponent != u))
{ {
UpdatePvP(true); UpdatePvP(true);
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
@ -6792,6 +6791,9 @@ void Player::UpdateArea(uint32 newArea)
if (area) if (area)
{ {
// check leave duel allowed area
CheckDuelArea(area);
// Dalaran restricted flight zone // Dalaran restricted flight zone
if ((area->flags & AREA_FLAG_CANNOT_FLY) && IsFreeFlying() && !isGameMaster() && !HasAura(58600)) if ((area->flags & AREA_FLAG_CANNOT_FLY) && IsFreeFlying() && !isGameMaster() && !HasAura(58600))
CastSpell(this, 58600, true); // Restricted Flight Area CastSpell(this, 58600, true); // Restricted Flight Area
@ -6898,6 +6900,15 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
UpdateZoneDependentPets(); UpdateZoneDependentPets();
} }
void Player::CheckDuelArea(AreaTableEntry const* areaEntry)
{
if (!duel)
return;
if (!(areaEntry->flags & AREA_FLAG_DUEL))
DuelComplete(DUEL_FLED);
}
//If players are too far way of duel flag... then player loose the duel //If players are too far way of duel flag... then player loose the duel
void Player::CheckDuelDistance(time_t currTime) void Player::CheckDuelDistance(time_t currTime)
{ {
@ -6906,7 +6917,11 @@ void Player::CheckDuelDistance(time_t currTime)
GameObject* obj = GetMap()->GetGameObject(GetGuidValue(PLAYER_DUEL_ARBITER)); GameObject* obj = GetMap()->GetGameObject(GetGuidValue(PLAYER_DUEL_ARBITER));
if (!obj) if (!obj)
{
// player not at duel start map
DuelComplete(DUEL_FLED);
return; return;
}
if (duel->outOfBound == 0) if (duel->outOfBound == 0)
{ {

View file

@ -1717,7 +1717,9 @@ class MANGOS_DLL_SPEC Player : public Unit
/** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/ /** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/
DuelInfo *duel; DuelInfo *duel;
bool IsInDuelWith(Player const* player) const { return duel && duel->opponent == player && duel->startTime != 0; }
void UpdateDuelFlag(time_t currTime); void UpdateDuelFlag(time_t currTime);
void CheckDuelArea(AreaTableEntry const* areaEntry);
void CheckDuelDistance(time_t currTime); void CheckDuelDistance(time_t currTime);
void DuelComplete(DuelCompleteType type); void DuelComplete(DuelCompleteType type);
void SendDuelCountdown(uint32 counter); void SendDuelCountdown(uint32 counter);

View file

@ -645,9 +645,8 @@ void Spell::FillTargetMap()
Player *me = (Player*)m_caster; Player *me = (Player*)m_caster;
for (UnitList::const_iterator itr = tmpUnitMap.begin(); itr != tmpUnitMap.end(); ++itr) for (UnitList::const_iterator itr = tmpUnitMap.begin(); itr != tmpUnitMap.end(); ++itr)
{ {
Unit *owner = (*itr)->GetOwner(); Player *targetOwner = (*itr)->GetCharmerOrOwnerPlayerOrPlayerItself();
Unit *u = owner ? owner : (*itr); if (targetOwner && targetOwner != me && targetOwner->IsPvP() && !me->IsInDuelWith(targetOwner))
if(u!=m_caster && u->IsPvP() && (!me->duel || me->duel->opponent != u))
{ {
me->UpdatePvP(true); me->UpdatePvP(true);
me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);

View file

@ -7782,23 +7782,15 @@ void Spell::EffectDuel(SpellEffectIndex eff_idx)
return; return;
// Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
// Don't have to check the target's map since you cannot challenge someone across maps AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetAreaId());
uint32 mapid = caster->GetMapId(); if (casterAreaEntry && !(casterAreaEntry->flags & AREA_FLAG_DUEL))
if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
{ {
SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
return; return;
} }
AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId()); AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetAreaId());
if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) ) if (targetAreaEntry && !(targetAreaEntry->flags & AREA_FLAG_DUEL))
{
SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
return;
}
AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
{ {
SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
return; return;

View file

@ -5402,7 +5402,7 @@ bool Unit::IsHostileTo(Unit const* unit) const
Player const* pTarget = (Player const*)target; Player const* pTarget = (Player const*)target;
// Duel // Duel
if(pTester->duel && pTester->duel->opponent == pTarget && pTester->duel->startTime != 0) if (pTester->IsInDuelWith(pTarget))
return true; return true;
// Group // Group
@ -5514,7 +5514,7 @@ bool Unit::IsFriendlyTo(Unit const* unit) const
Player const* pTarget = (Player const*)target; Player const* pTarget = (Player const*)target;
// Duel // Duel
if(pTester->duel && pTester->duel->opponent == target && pTester->duel->startTime != 0) if (pTester->IsInDuelWith(pTarget))
return false; return false;
// Group // Group
@ -5883,6 +5883,15 @@ Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself()
return GetTypeId()==TYPEID_PLAYER ? (Player*)this : NULL; return GetTypeId()==TYPEID_PLAYER ? (Player*)this : NULL;
} }
Player const* Unit::GetCharmerOrOwnerPlayerOrPlayerItself() const
{
ObjectGuid guid = GetCharmerOrOwnerGuid();
if (guid.IsPlayer())
return ObjectAccessor::FindPlayer(guid);
return GetTypeId() == TYPEID_PLAYER ? (Player const*)this : NULL;
}
Pet* Unit::GetPet() const Pet* Unit::GetPet() const
{ {
if (ObjectGuid pet_guid = GetPetGuid()) if (ObjectGuid pet_guid = GetPetGuid())
@ -7707,13 +7716,15 @@ void Unit::SetInCombatWith(Unit* enemy)
//check for duel //check for duel
if (eOwner->GetTypeId() == TYPEID_PLAYER && ((Player*)eOwner)->duel) if (eOwner->GetTypeId() == TYPEID_PLAYER && ((Player*)eOwner)->duel)
{ {
Unit const* myOwner = GetCharmerOrOwnerOrSelf(); if (Player const* myOwner = GetCharmerOrOwnerPlayerOrPlayerItself())
if(((Player const*)eOwner)->duel->opponent == myOwner) {
if (myOwner->IsInDuelWith((Player const*)eOwner))
{ {
SetInCombatState(true,enemy); SetInCombatState(true,enemy);
return; return;
} }
} }
}
SetInCombatState(false,enemy); SetInCombatState(false,enemy);
} }
@ -10376,7 +10387,7 @@ void Unit::SetContestedPvP(Player *attackedPlayer)
{ {
Player* player = GetCharmerOrOwnerPlayerOrPlayerItself(); Player* player = GetCharmerOrOwnerPlayerOrPlayerItself();
if (!player || (attackedPlayer && (attackedPlayer == player || (player->duel && player->duel->opponent == attackedPlayer)))) if (!player || (attackedPlayer && (attackedPlayer == player || player->IsInDuelWith(attackedPlayer))))
return; return;
player->SetContestedPvPTimer(30000); player->SetContestedPvPTimer(30000);
@ -10792,16 +10803,22 @@ bool Unit::IsAllowedDamageInArea(Unit* pVictim) const
if (pVictim == this) if (pVictim == this)
return true; return true;
// non player controlled unit can damage anywhere
if (!IsCharmerOrOwnerPlayerOrPlayerItself())
return true;
// can damage own pet anywhere // can damage own pet anywhere
if (pVictim->GetOwnerGuid() == GetObjectGuid()) if (pVictim->GetOwnerGuid() == GetObjectGuid())
return true; return true;
// non player controlled unit can damage anywhere
Player const* pOwner = GetCharmerOrOwnerPlayerOrPlayerItself();
if (!pOwner)
return true;
// can damage non player controlled victim anywhere // can damage non player controlled victim anywhere
if (!pVictim->IsCharmerOrOwnerPlayerOrPlayerItself()) Player const* vOwner = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself();
if (!vOwner)
return true;
// can damage opponent in duel
if (pOwner->IsInDuelWith(vOwner))
return true; return true;
// can't damage player controlled unit by player controlled unit in sanctuary // can't damage player controlled unit by player controlled unit in sanctuary

View file

@ -1530,6 +1530,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
} }
bool IsCharmerOrOwnerPlayerOrPlayerItself() const; bool IsCharmerOrOwnerPlayerOrPlayerItself() const;
Player* GetCharmerOrOwnerPlayerOrPlayerItself(); Player* GetCharmerOrOwnerPlayerOrPlayerItself();
Player const* GetCharmerOrOwnerPlayerOrPlayerItself() const;
float GetCombatDistance( const Unit* target ) const; float GetCombatDistance( const Unit* target ) const;
void SetPet(Pet* pet); void SetPet(Pet* pet);

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 "11556" #define REVISION_NR "11557"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__