/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* 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 3 of the License, or
* 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, see .
*
*/
#ifndef __FACTION_H
#define __FACTION_H
#include "Unit.h"
inline bool isHostile(Object* objA, Object* objB)// B is hostile for A?
{
if(!objA || !objB)
return false;
bool hostile = false;
if(objB->m_faction == NULL || objA->m_faction == NULL)
return true;
if(objA == objB)
return false; // can't attack self.. this causes problems with buffs if we dont have it :p
if(objA->GetTypeId() == TYPEID_CORPSE)
return false;
if(objB->GetTypeId() == TYPEID_CORPSE)
return false;
uint32 faction = objB->m_faction->Mask;
uint32 host = objA->m_faction->HostileMask;
if(faction & host)
{
hostile = true;
}
// check friend/enemy list
for(uint32 i = 0; i < 4; i++)
{
if(objA->m_faction->EnemyFactions[i] == objB->m_faction->Faction)
{
hostile = true;
break;
}
if(objA->m_faction->FriendlyFactions[i] == objB->m_faction->Faction)
{
hostile = false;
break;
}
}
// PvP Flag System Checks
// We check this after the normal isHostile test, that way if we're
// on the opposite team we'll already know :p
if(hostile &&
( objA->IsPlayer() || objA->IsPet() || ( objA->IsUnit() && !objA->IsPlayer() && static_cast(objA)->IsTotem() && static_cast(objA)->GetTotemOwner()->IsPvPFlagged() ) ) )
{
if(objB->IsPlayer())
{
// Check PvP Flags.
if(static_cast(objB)->IsPvPFlagged())
return true;
else
return false;
}
if(objB->IsPet())
{
// Check PvP Flags.
if(static_cast(objB)->GetPetOwner() && static_cast(objB)->GetPetOwner()->IsPvPFlagged())
return true;
else
return false;
}
}
// Reputation System Checks
if(objA->IsPlayer() && !objB->IsPlayer()) // PvE
{
if(objB->m_factionDBC->RepListId >= 0)
hostile = ((Player*)objA)->IsHostileBasedOnReputation(objB->m_factionDBC);
}
if(objB->IsPlayer() && !objA->IsPlayer()) // PvE
{
if(objA->m_factionDBC->RepListId >= 0)
hostile = ((Player*)objB)->IsHostileBasedOnReputation(objA->m_factionDBC);
}
return hostile;
}
inline bool isAttackable(Object* objA, Object* objB)// A can attack B?
{
if(!objA || !objB || objB->m_factionDBC == NULL || objA->m_factionDBC == NULL)
return false;
if(objB->m_faction == NULL || objA->m_faction == NULL )
return true;
if(objA == objB)
return false; // can't attack self.. this causes problems with buffs if we dont have it :p
if(objA->GetTypeId() == TYPEID_CORPSE)
return false;
if(objB->GetTypeId() == TYPEID_CORPSE)
return false;
// Players in fiegn death flags can't be attacked
if(objA->IsPlayer())
if(objA->HasFlag(UNIT_FIELD_FLAGS_2, 0x00000001))
return false;
if(objB->IsPlayer())
if(objB->HasFlag(UNIT_FIELD_FLAGS_2, 0x00000001))
return false;
// Checks for untouchable, unattackable
if(objA->IsUnit())
{
if(objA->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT))
return false;
if(objA->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT_2))
return false;
if(objA->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_NO_SELECT))
return false;
if(objA->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_MAKE_CHAR_UNTOUCHABLE))
return false;
}
if(objB->IsUnit())
{
if(objB->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT))
return false;
if(objB->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT_2))
return false;
if(objB->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_NO_SELECT))
return false;
if(objB->HasFlag(UNIT_FIELD_FLAGS, U_FIELD_FLAG_MAKE_CHAR_UNTOUCHABLE))
return false;
//added by Zack : we cannot attack steathed units. Maybe checked in other palces too ?
//!! warning, this presumes that objA is attacking ObjB
if(static_cast(objB)->IsStealth())
return false;
}
if(objA->IsPlayer() && objB->IsPlayer())
{
if(
static_cast(objA)->DuelingWith == static_cast(objB) &&
static_cast(objA)->GetDuelState() == DUEL_STATE_STARTED
)
return true;
if(objA->HasFlag(PLAYER_FLAGS,PLAYER_FLAG_FREE_FOR_ALL_PVP) && objB->HasFlag(PLAYER_FLAGS,PLAYER_FLAG_FREE_FOR_ALL_PVP))
return true; // can hurt each other in FFA pvp
}
// handle for pets in duel
if(objA->IsPet())
{
if(objB->IsPlayer())
if(
static_cast(objA)->GetPetOwner() &&
static_cast(objA)->GetPetOwner()->DuelingWith == static_cast(objB) &&
static_cast(objA)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
if(objB->IsPet())
if(static_cast(objA)->GetPetOwner() &&
static_cast(objB)->GetPetOwner() &&
static_cast(objA)->GetPetOwner()->DuelingWith == static_cast(objB)->GetPetOwner() &&
static_cast(objA)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
}
if(objB->IsPet())
{
if(objA->IsPlayer())
if(
static_cast(objB)->GetPetOwner() && static_cast(objB)->GetPetOwner() &&
static_cast(objB)->GetPetOwner()->DuelingWith == static_cast(objA) &&
static_cast(objB)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
else if(objA->IsPet())
if(static_cast(objA)->GetPetOwner() && static_cast(objB)->GetPetOwner() &&
static_cast(objB)->GetPetOwner() &&
static_cast(objB)->GetPetOwner()->DuelingWith == static_cast(objA)->GetPetOwner() &&
static_cast(objB)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
}
// handle for totems
if(objA->IsUnit() && !objA->IsPlayer()) // must be creature
{
if(static_cast(objA)->IsTotem())
{
if(objB->IsPlayer())
if( static_cast(objA)->GetTotemOwner() &&
static_cast(objA)->GetTotemOwner()->DuelingWith == static_cast(objB) &&
static_cast(objA)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
if(objB->IsPet())
if( static_cast(objA)->GetTotemOwner() &&
static_cast(objA)->GetTotemOwner()->DuelingWith == static_cast(objB)->GetPetOwner() &&
static_cast(objA)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
}
}
if(objB->IsUnit() && !objB->IsPlayer()) // must be creature
{
if(static_cast(objB)->IsTotem())
{
if(objA->IsPlayer())
if( static_cast(objB)->GetTotemOwner() &&
static_cast(objB)->GetTotemOwner()->DuelingWith == static_cast(objA) &&
static_cast(objB)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
if(objA->IsPet())
if( static_cast(objB)->GetTotemOwner() &&
static_cast(objB)->GetTotemOwner()->DuelingWith == static_cast(objA)->GetPetOwner() &&
static_cast(objB)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
)
return true;
}
}
// do not let people attack each other in sancuary
// Dueling is already catered for
AreaTable *atA;
AreaTable *atB;
if(objA->IsPet() && ((Pet*)objA)->GetPetOwner())
atA = sAreaStore.LookupEntry(static_cast(objA)->GetPetOwner()->GetAreaID());
else if (objA->IsPlayer())
atA = sAreaStore.LookupEntry(static_cast(objA)->GetAreaID());
else
atA = NULL;
if(objB->IsPet() && ((Pet*)objB)->GetPetOwner())
atB = sAreaStore.LookupEntry(static_cast(objB)->GetPetOwner()->GetAreaID());
else if (objB->IsPlayer())
atB = sAreaStore.LookupEntry(static_cast(objB)->GetAreaID());
else
atB = NULL;
// We have the area codes
// We know they arent dueling
if (atA && atB)
{
if(atA->AreaFlags & 0x800 || atB->AreaFlags & 0x800)
return false;
}
if(objA->m_faction == objB->m_faction) // same faction can't kill each other unless in ffa pvp/duel
return false;
bool attackable = isHostile(objA, objB); // B is attackable if its hostile for A
/*if((objA->m_faction->HostileMask & 8) && (objB->m_factionDBC->RepListId != 0) &&
(objB->GetTypeId() != TYPEID_PLAYER) && objB->m_faction->Faction != 31) // B is attackable if its a neutral Creature*/
// Neutral Creature Check
if(objA->IsPlayer() || objA->IsPet())
{
if(objB->m_factionDBC->RepListId == -1 && objB->m_faction->HostileMask == 0 && objB->m_faction->FriendlyMask == 0)
{
attackable = true;
}
}
else if(objB->IsPlayer() || objB->IsPet())
{
if(objA->m_factionDBC->RepListId == -1 && objA->m_faction->HostileMask == 0 && objA->m_faction->FriendlyMask == 0)
{
attackable = true;
}
}
return attackable;
}
inline bool isFriendly(Object* objA, Object* objB)// B is friendly to A if its not hostile
{
return !isHostile(objA, objB);
}
inline bool isCombatSupport(Object* objA, Object* objB)// B combat supports A?
{
if(!objA || !objB)
return false;
if(objA->GetTypeId() == TYPEID_CORPSE)
return false;
if(objB->GetTypeId() == TYPEID_CORPSE)
return false;
if(objB->m_faction == 0 || objA->m_faction == 0)
return false;
bool combatSupport = false;
uint32 fSupport = objB->m_faction->FriendlyMask;
uint32 myFaction = objA->m_faction->Mask;
if(myFaction & fSupport)
{
combatSupport = true;
}
// check friend/enemy list
for(uint32 i = 0; i < 4; i++)
{
if(objB->m_faction->EnemyFactions[i] == objA->m_faction->Faction)
{
combatSupport = false;
break;
}
if(objB->m_faction->FriendlyFactions[i] == objA->m_faction->Faction)
{
combatSupport = true;
break;
}
}
return combatSupport;
}
inline bool isAlliance(Object* objA)// A is alliance?
{
FactionTemplateDBC * m_sw_faction = sFactionTmpStore.LookupEntry(11);
FactionDBC * m_sw_factionDBC = sFactionStore.LookupEntry(72);
if(!objA || objA->m_factionDBC == NULL || objA->m_faction == NULL)
return true;
if(m_sw_faction == objA->m_faction || m_sw_factionDBC == objA->m_factionDBC)
return true;
//bool hostile = false;
uint32 faction = m_sw_faction->Faction;
uint32 host = objA->m_faction->HostileMask;
if(faction & host)
return false;
// check friend/enemy list
for(uint32 i = 0; i < 4; i++)
{
if(objA->m_faction->EnemyFactions[i] == faction)
return false;
}
faction = objA->m_faction->Faction;
host = m_sw_faction->HostileMask;
if(faction & host)
return false;
// check friend/enemy list
for(uint32 i = 0; i < 4; i++)
{
if(objA->m_faction->EnemyFactions[i] == faction)
return false;
}
return true;
}
#endif