Example #1
0
bool WorldSession::CheckMailBox(ObjectGuid guid)
{
    // GM case
    if (guid == GetPlayer()->GetObjectGuid())
    {
        // command case will return only if player have real access to command
        if (!ChatHandler(GetPlayer()).FindCommand("mailbox"))
        {
            DEBUG_LOG("%s attempt open mailbox in cheating way.", guid.GetString().c_str());
            return false;
        }
    }
    // mailbox case
    else if (guid.IsGameObject())
    {
        if (!GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_MAILBOX))
        {
            DEBUG_LOG("Mailbox %s not found or %s can't interact with him.", guid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str());
            return false;
        }
    }
    // squire case
    else if (guid.IsAnyTypeCreature())
    {
        Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
        if (!creature)
        {
            DEBUG_LOG("%s not found or %s can't interact with him.", creature->GetGuidStr().c_str(), GetPlayer()->GetGuidStr().c_str());
            return false;
        }

        if (!(creature->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_SQUIRE))
        {
            DEBUG_LOG("%s not have access to mailbox.", creature->GetGuidStr().c_str());
            return false;
        }

        if (creature->GetOwnerGuid() != GetPlayer()->GetObjectGuid())
        {
            DEBUG_LOG("%s not owned by %s for access to mailbox.", creature->GetGuidStr().c_str(), GetPlayer()->GetGuidStr().c_str());
            return false;
        }
    }
    else
        return false;

    return true;
}
//-----------------------------------------------//
void WaypointMovementGenerator<Creature>::LoadPath(Creature& creature, int32 pathId, WaypointPathOrigin wpOrigin, uint32 overwriteEntry)
{
    DETAIL_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "LoadPath: loading waypoint path for %s", creature.GetGuidStr().c_str());

    if (!overwriteEntry)
        overwriteEntry = creature.GetEntry();

    if (wpOrigin == PATH_NO_PATH && pathId == 0)
        i_path = sWaypointMgr.GetDefaultPath(overwriteEntry, creature.GetGUIDLow(), &m_PathOrigin);
    else
    {
        m_PathOrigin = wpOrigin == PATH_NO_PATH ? PATH_FROM_ENTRY : wpOrigin;
        i_path = sWaypointMgr.GetPathFromOrigin(overwriteEntry, creature.GetGUIDLow(), pathId, m_PathOrigin);
    }
    m_pathId = pathId;

    // No movement found for entry nor guid
    if (!i_path)
    {
        if (m_PathOrigin == PATH_FROM_EXTERNAL)
            sLog.outErrorScriptLib("WaypointMovementGenerator::LoadPath: %s doesn't have waypoint path %i", creature.GetGuidStr().c_str(), pathId);
        else
            sLog.outErrorDb("WaypointMovementGenerator::LoadPath: %s doesn't have waypoint path %i", creature.GetGuidStr().c_str(), pathId);
        return;
    }

    if (i_path->empty())
        { return; }
    // Initialize the i_currentNode to point to the first node
    i_currentNode = i_path->begin()->first;
    m_lastReachedWaypoint = 0;
}
void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
{
    if (!i_path || i_path->empty())
        { return; }

    m_lastReachedWaypoint = i_currentNode;

    if (m_isArrivalDone)
        { return; }

    creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
    m_isArrivalDone = true;

    WaypointPath::const_iterator currPoint = i_path->find(i_currentNode);
    MANGOS_ASSERT(currPoint != i_path->end());
    WaypointNode const& node = currPoint->second;

    if (node.script_id)
    {
        DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", node.script_id, i_currentNode, creature.GetGuidStr().c_str());
        creature.GetMap()->ScriptsStart(DBS_ON_CREATURE_MOVEMENT, node.script_id, &creature, &creature);
    }

    // We have reached the destination and can process behavior
    if (WaypointBehavior* behavior = node.behavior)
    {
        if (behavior->emote != 0)
            { creature.HandleEmote(behavior->emote); }

        if (behavior->spell != 0)
            { creature.CastSpell(&creature, behavior->spell, false); }

        if (behavior->model1 != 0)
            { creature.SetDisplayId(behavior->model1); }

        if (behavior->textid[0])
        {
            int32 textId = behavior->textid[0];
            // Not only one text is set
            if (behavior->textid[1])
            {
                // Select one from max 5 texts (0 and 1 already checked)
                int i = 2;
                for (; i < MAX_WAYPOINT_TEXT; ++i)
                {
                    if (!behavior->textid[i])
                        { break; }
                }

                textId = behavior->textid[urand(0, i - 1)];
            }

            if (MangosStringLocale const* textData = sObjectMgr.GetMangosStringLocale(textId))
                { creature.MonsterText(textData, NULL); }
            else
                { sLog.outErrorDb("%s reached waypoint %u, attempted to do text %i, but required text-data could not be found", creature.GetGuidStr().c_str(), i_currentNode, textId); }
        }
    }

    // Inform script
    if (creature.AI())
    {
        uint32 type = WAYPOINT_MOTION_TYPE;
        if (m_PathOrigin == PATH_FROM_EXTERNAL && m_pathId > 0)
            type = EXTERNAL_WAYPOINT_MOVE + m_pathId;
        creature.AI()->MovementInform(type, i_currentNode);
    }

    // Wait delay ms
    Stop(node.delay);
}
//-----------------------------------------------//
void WaypointMovementGenerator<Creature>::LoadPath(Creature& creature)
{
    DETAIL_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "LoadPath: loading waypoint path for %s", creature.GetGuidStr().c_str());

    i_path = sWaypointMgr.GetPath(creature.GetGUIDLow());

    // We may LoadPath() for several occasions:

    // 1: When creature.MovementType=2
    //    1a) Path is selected by creature.guid == creature_movement.id
    //    1b) Path for 1a) does not exist and then use path from creature.GetEntry() == creature_movement_template.entry

    // 2: When creature_template.MovementType=2
    //    2a) Creature is summoned and has creature_template.MovementType=2
    //        Creators need to be sure that creature_movement_template is always valid for summons.
    //        Mob that can be summoned anywhere should not have creature_movement_template for example.

    // No movement found for guid
    if (!i_path)
    {
        i_path = sWaypointMgr.GetPathTemplate(creature.GetEntry());

        // No movement found for entry
        if (!i_path)
        {
            sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path",
                            creature.GetName(), creature.GetEntry(), creature.GetGUIDLow());
            return;
        }
    }

    StartMoveNow(creature);
}
void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
{
    if (!i_path || i_path->empty())
        return;

    if (m_isArrivalDone)
        return;

    creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
    m_isArrivalDone = true;

    if (i_path->at(i_currentNode).script_id)
    {
        DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetGuidStr().c_str());
        creature.GetMap()->ScriptsStart(sCreatureMovementScripts, i_path->at(i_currentNode).script_id, &creature, &creature);
    }

    // We have reached the destination and can process behavior
    if (WaypointBehavior* behavior = i_path->at(i_currentNode).behavior)
    {
        if (behavior->emote != 0)
            creature.HandleEmote(behavior->emote);

        if (behavior->spell != 0)
            creature.CastSpell(&creature, behavior->spell, false);

        if (behavior->model1 != 0)
            creature.SetDisplayId(behavior->model1);

        if (behavior->textid[0])
        {
            // Not only one text is set
            if (behavior->textid[1])
            {
                // Select one from max 5 texts (0 and 1 already checked)
                int i = 2;
                for (; i < MAX_WAYPOINT_TEXT; ++i)
                {
                    if (!behavior->textid[i])
                        break;
                }

                creature.MonsterSay(behavior->textid[rand() % i], LANG_UNIVERSAL);
            }
            else
                creature.MonsterSay(behavior->textid[0], LANG_UNIVERSAL);
        }
    }

    // Inform script
    MovementInform(creature);
    Stop(i_path->at(i_currentNode).delay);
}
//-----------------------------------------------//
void WaypointMovementGenerator<Creature>::LoadPath(Creature &creature)
{
    DETAIL_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "LoadPath: loading waypoint path for %s", creature.GetGuidStr().c_str());

    i_path = sWaypointMgr.GetPath(creature.GetGUIDLow());

    // We may LoadPath() for several occasions:

    // 1: When creature.MovementType=2
    //    1a) Path is selected by creature.guid == creature_movement.id
    //    1b) Path for 1a) does not exist and then use path from creature.GetEntry() == creature_movement_template.entry

    // 2: When creature_template.MovementType=2
    //    2a) Creature is summoned and has creature_template.MovementType=2
    //        Creators need to be sure that creature_movement_template is always valid for summons.
    //        Mob that can be summoned anywhere should not have creature_movement_template for example.

    // No movement found for guid
    if (!i_path)
    {
        i_path = sWaypointMgr.GetPathTemplate(creature.GetEntry());

        // No movement found for entry
        if (!i_path)
        {
            sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path",
                creature.GetName(), creature.GetEntry(), creature.GetGUIDLow());
            return;
        }
    }

    // We have to set the destination here (for the first point), right after Initialize. Without, we may not have valid xyz for GetResetPosition
    CreatureTraveller traveller(creature);

    if (creature.CanFly())
        creature.AddSplineFlag(SPLINEFLAG_FLYING);

    const WaypointNode &node = i_path->at(i_currentNode);
    i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
    i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
}
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    if (!&creature)
        return true;

    // Waypoint movement can be switched on/off
    // This is quite handy for escort quests and other stuff
    if (creature.hasUnitState(UNIT_STAT_NOT_MOVE))
    {
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    // prevent a crash at empty waypoint path.
    if (!i_path || i_path->empty())
    {
        creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
        return true;
    }

    if (i_currentNode >= i_path->size())
    {
        sLog.outError("WaypointMovement currentNode (%u) is equal or bigger than path size (creature entry %u)", i_currentNode, creature.GetEntry());
        i_currentNode = 0;
    }

    CreatureTraveller traveller(creature);

    i_nextMoveTime.Update(diff);

    if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true))
    {
        if (!IsActive(creature))                            // force stop processing (movement can move out active zone with cleanup movegens list)
            return true;                                    // not expire now, but already lost
    }

    // creature has been stopped in middle of the waypoint segment
    if (!i_destinationHolder.HasArrived() && creature.IsStopped())
    {
        // Timer has elapsed, meaning this part controlled it
        if (i_nextMoveTime.Passed())
        {
            SetStoppedByPlayer(false);

            creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

            if (creature.CanFly())
                creature.AddSplineFlag(SPLINEFLAG_FLYING);

            // Now we re-set destination to same node and start travel
            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        }
        else // if( !i_nextMoveTime.Passed())
        {
            // unexpected end of timer && creature stopped && not at end of segment
            if (!IsStoppedByPlayer())
            {
                // Put 30 seconds delay
                i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
                i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
                SetStoppedByPlayer(true);                   // Mark we did it
            }
        }
        return true;                                        // Abort here this update
    }

    if (creature.IsStopped())
    {
        if (!m_isArrivalDone)
        {
            if (i_path->at(i_currentNode).orientation != 100)
                creature.SetOrientation(i_path->at(i_currentNode).orientation);

            if (i_path->at(i_currentNode).script_id)
            {
                DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetGuidStr().c_str());
                creature.GetMap()->ScriptsStart(sCreatureMovementScripts, i_path->at(i_currentNode).script_id, &creature, &creature);
            }

            // We have reached the destination and can process behavior
            if (WaypointBehavior *behavior = i_path->at(i_currentNode).behavior)
            {
                if (behavior->emote != 0)
                    creature.HandleEmote(behavior->emote);

                if (behavior->spell != 0)
                {
                    creature.CastSpell(&creature, behavior->spell, false);

                    if (!IsActive(creature))                // force stop processing (cast can change movegens list)
                        return true;                        // not expire now, but already lost
                }

                if (behavior->model1 != 0)
                    creature.SetDisplayId(behavior->model1);

                if (behavior->textid[0])
                {
                    // Not only one text is set
                    if (behavior->textid[1])
                    {
                        // Select one from max 5 texts (0 and 1 already checked)
                        int i = 2;
                        for(; i < MAX_WAYPOINT_TEXT; ++i)
                        {
                            if (!behavior->textid[i])
                                break;
                        }

                        creature.MonsterSay(behavior->textid[rand() % i], LANG_UNIVERSAL);
                    }
                    else
                        creature.MonsterSay(behavior->textid[0], LANG_UNIVERSAL);
                }
            }                                               // wpBehaviour found

            // Can only do this once for the node
            m_isArrivalDone = true;

            // Inform script
            MovementInform(creature);

            if (!IsActive(creature))                        // force stop processing (movement can move out active zone with cleanup movegens list)
                return true;                                // not expire now, but already lost

            // prevent a crash at empty waypoint path.
            if (!i_path || i_path->empty() || i_currentNode >= i_path->size())
            {
                creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
                return true;
            }
        }
    }                                                       // i_creature.IsStopped()

    // This is at the end of waypoint segment (incl. was previously stopped by player, extending the time)
    if (i_nextMoveTime.Passed())
    {
        // If stopped then begin a new move segment
        if (creature.IsStopped())
        {
            creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

            if (creature.CanFly())
                creature.AddSplineFlag(SPLINEFLAG_FLYING);

            if (WaypointBehavior *behavior = i_path->at(i_currentNode).behavior)
            {
                if (behavior->model2 != 0)
                    creature.SetDisplayId(behavior->model2);

                creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
            }

            // behavior for "departure" of the current node is done
            m_isArrivalDone = false;

            // Proceed with increment current node and then send to the next destination
            ++i_currentNode;

            // Oops, end of the line so need to start from the beginning
            if (i_currentNode >= i_path->size())
                i_currentNode = 0;

            if (i_path->at(i_currentNode).orientation != 100)
                creature.SetOrientation(i_path->at(i_currentNode).orientation);

            const WaypointNode &node = i_path->at(i_currentNode);
            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        }
        else
        {
            // If not stopped then stop it
            creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);

            SetStoppedByPlayer(false);

            // Set TimeTracker to waittime for the current node
            i_nextMoveTime.Reset(i_path->at(i_currentNode).delay);
        }
    }

    return true;
}
//-----------------------------------------------//
void WaypointMovementGenerator<Creature>::LoadPath(Creature& creature)
{
    DETAIL_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "LoadPath: loading waypoint path for %s", creature.GetGuidStr().c_str());

    i_path = sWaypointMgr.GetDefaultPath(creature.GetEntry(), creature.GetGUIDLow());
    // No movement found for entry nor guid
    if (!i_path)
    {
        sLog.outErrorDb("WaypointMovementGenerator::LoadPath: %s doesn't have waypoint path", creature.GetGuidStr().c_str());
        return;
    }

    if (i_path->empty())
        return;
    // Initialize the i_currentNode to point to the first node
    i_currentNode = i_path->begin()->first;
    m_lastReachedWaypoint = 0;
}