示例#1
0
bool C4Menu::HasMouse()
{
	int32_t iPlayer = GetControllingPlayer();
	if (iPlayer == NO_OWNER) return true; // free view dialog also has the mouse
	C4Player *pPlr = ::Players.Get(iPlayer);
	if (pPlr && pPlr->MouseControl) return true;
	return false;
}
示例#2
0
/////////////////////////////////////////////////
/// Assistance: Unit treats another unit as an ally it can help
///
/// @note Relations API Tier 1
///
/// Client-side counterpart: <tt>CGUnit_C::CanAssist(const CGUnit_C *this, const CGUnit_C *unit)</tt>
/// Backbone of all spells which can target friendly units.
/// Optional ignoreFlags parameter first appeared in TBC+ clients, backported for API unification between expansions.
/////////////////////////////////////////////////
bool Unit::CanAssist(const Unit* unit, bool /*ignoreFlags*/) const
{
    // Simple sanity check
    if (!unit)
        return false;

    // Original logic

    // We can't assist unselectable unit
    if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
        return false;

    // Exclude non-friendlies at this point
    if (GetReactionTo(unit) < REP_FRIENDLY)
        return false;

    // Pre-WotLK: backbone of lua UnitIsPVP(), a member of unit class client-side
    auto isPvPUI = [](Unit const * self)
    {
        if (Unit const* master = self->GetMaster())
        {
            if (self->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PLAYER))
                return false;
            return master->IsPvP();
        }
        return self->IsPvP();
    };

    // Detect player controlled unit and exit early
    if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
    {
        const Player* thisPlayer = GetControllingPlayer();
        const Player* unitPlayer = unit->GetControllingPlayer();

        if (thisPlayer && unitPlayer)
        {
            if (thisPlayer->IsInDuelWith(unitPlayer))
                return false;

            if (unitPlayer->IsPvPFreeForAll() && !thisPlayer->IsPvPFreeForAll())
                return false;
        }
        return true;
    }

    // If we continue here, unit is an npc. Detect if we are an npc too, so we can exit early
    if (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
        return true;

    // Pre-TBC: We are left with player assisting an npc case here: can assist friendly NPCs with PVP flag
    if (isPvPUI(unit))
        return true;

    return false;
}
示例#3
0
/////////////////////////////////////////////////
/// [Serverside] Opposition: Unit can target a target with a harmful spell
///
/// @note Relations API Tier 3
///
/// This function is not intented to have client-side counterpart by original design.
/// It utilizes SpellEntry for additional target filtering.
/// Also an additional fine grained check needs to be done for AOE spells, because they
/// need to skip PVP enabled targets in some special cases. (Chain spells, AOE)
/////////////////////////////////////////////////
bool Unit::CanAttackSpell(Unit const* target, SpellEntry const* spellInfo, bool isAOE) const
{
    if (spellInfo)
    {
        // inversealive is needed for some spells which need to be casted at dead targets (aoe)
        if (!target->isAlive() && !spellInfo->HasAttribute(SPELL_ATTR_EX2_CAN_TARGET_DEAD))
            return false;
    }

    if (CanAttack(target))
    {
        if (isAOE)
        {
            if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
            {
                if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
                {
                    const Player* thisPlayer = GetControllingPlayer();
                    if (!thisPlayer)
                        return true;

                    const Player* unitPlayer = target->GetControllingPlayer();
                    if (!unitPlayer)
                        return true;

                    if (thisPlayer->IsInDuelWith(unitPlayer))
                        return true;

                    if (unitPlayer->IsPvP() && (!isAOE || thisPlayer->IsPvP()))
                        return true;

                    if (thisPlayer->IsPvPFreeForAll() && unitPlayer->IsPvPFreeForAll())
                        return true;

                    return false;
                }
            }
        }

        return true;
    }
    return false;
}
示例#4
0
/////////////////////////////////////////////////
/// Group: Unit counts as being placed in the same group (party or raid) with another unit (for gameplay purposes)
///
/// @note Relations API Tier 1
///
/// Based on client-side counterpart: <tt>static CGUnit_C::IsUnitInGroup(const CGUnit_C *this, const CGUnit_C *unit)</tt>
/// Additionally contains optional detection of same group from UI standpoint datamined from other functions.
/// Points of view are swapped to fit in with the rest of API, logic is preserved.
/////////////////////////////////////////////////
bool Unit::IsInGroup(Unit const* other, bool party/* = false*/, bool UI/* = false*/) const
{
    // Simple sanity check
    if (!other)
        return false;

    // Original logic adaptation for server (original function was operating as a local player PoV only)

    // Same unit is always in group with itself
    if (this == other)
        return true;

    // Only player controlled
    if (this->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) && other->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
    {
        // UI mode: only players and their current pets/charms are in the party UI
        if (UI)
        {
            const size_t comparisions = 3;
            const Player* thisPlayer[comparisions] = { nullptr, nullptr, nullptr };
            const Player* otherPlayer[comparisions] = { nullptr, nullptr, nullptr };

            auto getUIPlayerComparisions = [] (const Unit* unit, const Player* (&array)[comparisions])
            {
                // In reverse order
                if (unit->GetTypeId() == TYPEID_PLAYER)
                    array[0] = static_cast<const Player*>(unit);
                 ObjectGuid const& summonerGuid = unit->GetSummonerGuid();
                 ObjectGuid const& charmerGuid = unit->GetCharmerGuid();
                 if (summonerGuid.IsPlayer())
                    array[1] = sObjectMgr.GetPlayer(summonerGuid);
                 if (charmerGuid.IsPlayer())
                    array[2] = sObjectMgr.GetPlayer(charmerGuid);
            };

            getUIPlayerComparisions(this, thisPlayer);
            getUIPlayerComparisions(other, otherPlayer);

            for (auto& i : thisPlayer)
            {
                if (i)
                {
                    for (auto& j : otherPlayer)
                    {
                        if (j)
                        {
                            const Group* group = i->GetGroup();
                            if (i == j || (group && group == j->GetGroup() && (!party || group->SameSubGroup(i, j))))
                                return true;
                        }
                    }
                }
            }
            return false;
        }

        // Check if controlling players are in the same group (same logic as client, but not local)
        if (const Player* thisPlayer = GetControllingPlayer())
        {
            if (const Player* otherPlayer = other->GetControllingPlayer())
            {
                const Group* group = thisPlayer->GetGroup();
                return (thisPlayer == otherPlayer || (group && group == otherPlayer->GetGroup() && (!party || group->SameSubGroup(thisPlayer, otherPlayer))));
            }
        }
    }

    // NOTE: For future reference: server uses additional gameplay grouping logic for mobs (in combat and out of combat) - requires research for Tier 2 implementation

    return false;
}
示例#5
0
/////////////////////////////////////////////////
/// Opposition: Unit treats another unit as an enemy it can attack (generic)
///
/// @note Relations API Tier 1
///
/// Client-side counterpart: <tt>CGUnit_C::CanAttack(const CGUnit_C *this, const CGUnit_C *unit)</tt>
/// Backbone of all spells which can target hostile units.
/////////////////////////////////////////////////
bool Unit::CanAttack(const Unit* unit) const
{
    // Simple sanity check
    if (!unit)
        return false;

    // Original logic

    // Creatures cannot attack player ghosts, unless it is a specially flagged ghost creature
    if (GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && static_cast<const Player*>(unit)->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
    {
        if (!(static_cast<const Creature*>(this)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_GHOST_VISIBLE))
            return false;
    }

    // We can't attack unit when at least one of these flags is present on it:
    const uint32 mask = (UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_NON_ATTACKABLE_2 | UNIT_FLAG_TAXI_FLIGHT | UNIT_FLAG_NOT_SELECTABLE);
    if (unit->HasFlag(UNIT_FIELD_FLAGS, mask))
        return false;

    // Cross-check immunity and sanctuary flags: this <-> unit
    const bool thisPlayerControlled = HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
    if (thisPlayerControlled)
    {
        if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PLAYER))
            return false;
    }
    else if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
        return false;

    const bool unitPlayerControlled = unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
    if (unitPlayerControlled)
    {
        if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PLAYER))
            return false;
    }
    else if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
        return false;

    if (thisPlayerControlled || unitPlayerControlled)
    {
        if (thisPlayerControlled && unitPlayerControlled)
        {
            if (IsFriend(unit))
                return false;

            const Player* thisPlayer = GetControllingPlayer();
            if (!thisPlayer)
                return true;

            const Player* unitPlayer = unit->GetControllingPlayer();
            if (!unitPlayer)
                return true;

            if (thisPlayer->IsInDuelWith(unitPlayer))
                return true;

            if (unitPlayer->IsPvP())
                return true;

            if (thisPlayer->IsPvPFreeForAll() && unitPlayer->IsPvPFreeForAll())
                return true;

            return false;
        }
        return (!IsFriend(unit));
    }
    return (IsEnemy(unit) || unit->IsEnemy(this));
}
示例#6
0
/////////////////////////////////////////////////
/// Get unit to unit reaction
///
/// @note Relations API Tier 1
///
/// Client-side counterpart: <tt>CGUnit_C::UnitReaction(const CGUnit_C *this, const CGUnit_C *unit)</tt>
/////////////////////////////////////////////////
ReputationRank Unit::GetReactionTo(Unit const* unit) const
{
    // Simple sanity check
    if (!unit)
        return REP_NEUTRAL;

    // Original logic begins

    if (this == unit)
        return REP_FRIENDLY;

    if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
    {
        const Player* thisPlayer = GetControllingPlayer();

        if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
        {
            const Player* unitPlayer = unit->GetControllingPlayer();

            if (!thisPlayer || !unitPlayer)
                return REP_NEUTRAL;

            // Pre-TBC same player check: not present clientside in this order, but in for optimization (same result achieved through same group check below)
            if (thisPlayer == unitPlayer)
                return REP_FRIENDLY;

            if (unitPlayer->GetUInt32Value(PLAYER_DUEL_TEAM))
            {
                // TODO: Dueling misses duel arbiter and temporary truce during countdown, fix me later...
                if (thisPlayer->IsInDuelWith(unitPlayer))
                    return REP_HOSTILE;
            }

            // Pre-WotLK group check: always, replaced with faction template check in WotLK
            if (thisPlayer->IsInGroup(unitPlayer))
                return REP_FRIENDLY;

            // Pre-WotLK FFA check, known limitation: FFA doesn't work with totem elementals both client-side and server-side
            if (thisPlayer->IsPvPFreeForAll() && unitPlayer->IsPvPFreeForAll())
                return REP_HOSTILE;
        }

        if (thisPlayer)
        {
            if (const FactionTemplateEntry* unitFactionTemplate = unit->GetFactionTemplateEntry())
            {
                if (const ReputationRank* rank = thisPlayer->GetReputationMgr().GetForcedRankIfAny(unitFactionTemplate))
                    return (*rank);

                const FactionEntry* unitFactionEntry = sFactionStore.LookupEntry(unitFactionTemplate->faction);

                // If the faction has reputation ranks available, "at war" and contested PVP flags decide outcome
                if (unitFactionEntry && unitFactionEntry->HasReputation())
                {
                    // Pre-TBC contested check: not present clientside in this order, but in for optimization (same result achieved through faction to unit check below)
                    if (thisPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP) && unitFactionTemplate->IsContestedGuardFaction())
                        return REP_HOSTILE;

                    return thisPlayer->GetReputationMgr().IsAtWar(unitFactionEntry) ? REP_HOSTILE : REP_FRIENDLY;
                }
            }
        }
    }
    // Default fallback if player-specific checks didn't catch anything: facton to unit
    ReputationRank reaction = GetFactionReaction(GetFactionTemplateEntry(), unit);

    // Persuation support
    if (reaction > REP_HOSTILE && reaction < REP_HONORED && (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PERSUADED) || GetPersuadedGuid() == unit->GetObjectGuid()))
    {
        if (const FactionTemplateEntry* unitFactionTemplate = unit->GetFactionTemplateEntry())
        {
            const FactionEntry* unitFactionEntry = sFactionStore.LookupEntry(unitFactionTemplate->faction);
            if (unitFactionEntry && unitFactionEntry->HasReputation())
                reaction = ReputationRank(int32(reaction) + 1);
        }
    }
    return reaction;
}