void PointMovementGenerator<Creature>::MovementInform(Creature &unit)
{
    if (unit.AI())
        unit.AI()->MovementInform(POINT_MOTION_TYPE, id);

    if (unit.IsTemporarySummon())
    {
        TemporarySummon* pSummon = (TemporarySummon*)(&unit);
        if (pSummon->GetSummonerGuid().IsCreature())
            if(Creature* pSummoner = unit.GetMap()->GetCreature(pSummon->GetSummonerGuid()))
                if (pSummoner->AI())
                    pSummoner->AI()->SummonedMovementInform(&unit, POINT_MOTION_TYPE, id);
    }
}
 void SpawnFlameTriggers(uint8 point)
 {
     for(uint8 j = 0; j < 50; ++j)
     {
         if (point == 1)
             me->SummonCreature(NPC_BREATH_TRIGGER, 480.0f-(j*3), -518.0f+(j/16.0f), 105.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
         else
             me->SummonCreature(NPC_BREATH_TRIGGER, 480.0f-(j*3), -510.0f+(j/16.0f), 105.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
     }
     // and out of loop, cover the small room
     if (point == 0)
     {
         Creature *cr;
         if (cr = me->SummonCreature(NPC_BREATH_TRIGGER, 483, -484.9f, 105, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
             cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FLAME_BREATH_H : SPELL_FLAME_BREATH_N, true);
         if (cr = me->SummonCreature(NPC_BREATH_TRIGGER, 471.0f, -484.7f, 105, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
             cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FLAME_BREATH_H : SPELL_FLAME_BREATH_N, true);
         
         for (uint8 j = 0; j < 7; j++)
             if (cr = me->SummonCreature(NPC_BREATH_TRIGGER, 477.0f, -507.0f+(j*3), 105.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
                 cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FLAME_BREATH_H : SPELL_FLAME_BREATH_N, true);
     }
 }
Example #3
0
void ObjectGridEvacuator::Visit(CreatureMapType &m)
{
    // creature in unloading grid can have respawn point in another grid
    // if it will be unloaded then it will not respawn in original grid until unload/load original grid
    // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
    for (CreatureMapType::iterator iter = m.begin(); iter != m.end();)
    {
        Creature* c = iter->getSource();
        ++iter;

        ASSERT(!c->isPet() && "ObjectGridRespawnMover must not be called for pets");
        c->GetMap()->CreatureRespawnRelocation(c, true);
    }
}
Example #4
0
Transport::~Transport()
{
    for(CreatureSet::iterator itr = m_NPCPassengerSet.begin(); itr != m_NPCPassengerSet.end(); ++itr)
    {
         Creature* passenger = *itr;
         Map* map = passenger->GetMap();
         passenger->SetTransport(NULL);
         passenger->CleanupsBeforeDelete();
         map->Remove(passenger, true);
    }

    m_NPCPassengerSet.clear();

    m_WayPoints.clear();
    m_passengers.clear();
}
Example #5
0
		void SpawnAdds() {
			for (uint8 i = 0; i < 4; ++i) {
				Creature *pCreature = (Unit::GetCreature((*me), AddGUID[i]));
				if (!pCreature || !pCreature->isAlive()) {
					if (pCreature)
						pCreature->setDeathState(DEAD);
					pCreature = me->SummonCreature(AddEntry[i], Pos_X[i], POS_Y,
							POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0);
					if (pCreature)
						AddGUID[i] = pCreature->GetGUID();
				} else {
					pCreature->AI()->EnterEvadeMode();
					pCreature->GetMap()->CreatureRelocation(me, Pos_X[i], POS_Y,
							POS_Z, ORIENT);
					pCreature->StopMoving();
				}
			}
		}
bool ChargeMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
    i_nextMoveTime.Update(diff);

    if(i_nextMoveTime.Passed())
    {
        i_nextMoveTime.Reset(m_pointTime);
        float angle = creature.GetAngle(m_path[curPoint].x,m_path[curPoint].y);
        creature.GetMap()->CreatureRelocation(&creature, m_path[curPoint].x, m_path[curPoint].y, m_path[curPoint].z, angle);

        if(curPoint >= m_end)
        {
            creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
            return false;
        }
        ++curPoint;
    }
    return true;
}
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)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
    {
        sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for %u.", i_path->at(i_currentNode)->event_id, i_currentNode, creature.GetGUID());
        creature.GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, &creature, NULL/*, false*/);
    }

    // Inform script
    MovementInform(creature);
    Stop(i_path->at(i_currentNode)->delay);
}
bool EffectAuraDummy_npc_scourged_flamespitter(const Aura* pAura, bool bApply)
{
    if (pAura->GetId() == SPELL_REINFORCED_NET && pAura->GetEffIndex() == EFFECT_INDEX_0 && bApply)
    {
        Creature* pCreature = (Creature*)pAura->GetTarget();
        Unit* pCaster = pAura->GetCaster();
        if (!pCreature || !pCaster || pCaster->GetTypeId() != TYPEID_PLAYER || pCreature->GetEntry() != NPC_FLAMESPITTER)
            return false;

        // move the flamespitter to the ground level
        pCreature->GetMotionMaster()->Clear();
        pCreature->SetWalk(false);

        float fGroundZ = pCreature->GetMap()->GetHeight(pCreature->GetPhaseMask(), pCreature->GetPositionX(), pCreature->GetPositionY(), pCreature->GetPositionZ());
        pCreature->GetMotionMaster()->MovePoint(1, pCreature->GetPositionX(), pCreature->GetPositionY(), fGroundZ);
        return true;
    }

    return false;
}
bool
HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
{
    CreatureTraveller traveller(owner);
    i_destinationHolder.UpdateTraveller(traveller, time_diff);

    if (time_diff > i_travel_timer)
    { 
	       float x, y, z;
	       owner.GetRespawnCoord(x, y, z);
	       float myx, myy, myz;
	       owner.GetPosition(myx, myy, myz);
	       if (x != myx || y != myy || z != myz)
	       {
	           Position travelto = owner.GetMap()->getNextPositionOnPathToLocation(myx,myy,myz,x,y,z);
	           uint32 travel_time = i_destinationHolder.SetDestination(traveller, travelto.m_positionX, travelto.m_positionY, travelto.m_positionZ);
	           modifyTravelTime(travel_time);
	           return true;
	        }

        owner.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);

        // restore orientation of not moving creature at returning to home
        if (owner.GetDefaultMovementType() == IDLE_MOTION_TYPE)
        {
            //sLog.outDebug("Entering HomeMovement::GetDestination(z,y,z)");
            owner.SetOrientation(ori);
            WorldPacket packet;
            owner.BuildHeartBeatMsg(&packet);
            owner.SendMessageToSet(&packet, false);
        }

        owner.clearUnitState(UNIT_STAT_EVADE);
        owner.AI()->JustReachedHome();
        return false;
    }

    i_travel_timer -= time_diff;

    return true;
}
Example #10
0
void instance_uldaman::Update(uint32 uiDiff)
{
    if (GetData(TYPE_ALTAR_EVENT) != IN_PROGRESS)
        return;

    if (!m_uiKeeperCooldown)
        return;

    if (m_uiKeeperCooldown <= uiDiff)
    {
        for (GuidList::const_iterator itr = m_lKeepers.begin(); itr != m_lKeepers.end(); ++itr)
        {
            // Get Keeper which is alive and out of combat
            Creature* pKeeper = instance->GetCreature(*itr);
            if (!pKeeper || !pKeeper->IsAlive() || pKeeper->getVictim())
                continue;

            // Get starter player for attack
            Player* pPlayer = pKeeper->GetMap()->GetPlayer(m_playerGuid);
            if (!pPlayer || !pPlayer->IsAlive())
            {
                // If he's not available, then get a random player, within a reasonamble distance in map
                pPlayer = GetPlayerInMap(true, false);
                if (!pPlayer || !pPlayer->IsWithinDistInMap(pKeeper, 50.0f))
                {
                    SetData(TYPE_ALTAR_EVENT, NOT_STARTED);
                    return;
                }
            }

            // Attack the player
            pKeeper->RemoveAurasDueToSpell(SPELL_STONED);
            pKeeper->AI()->AttackStart(pPlayer);
            break;
        }

        m_uiKeeperCooldown = 0;
    }
    else
        m_uiKeeperCooldown -= uiDiff;
}
void ObjectGridRespawnMover::Visit(CreatureMapType &m) {
	// creature in unloading grid can have respawn point in another grid
	// if it will be unloaded then it will not respawn in original grid until unload/load original grid
	// move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
	for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) {
		Creature * c = iter->getSource();
		++iter;

		ASSERT(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets");

		Cell const& cur_cell = c->GetCurrentCell();

		float resp_x, resp_y, resp_z;
		c->GetRespawnCoord(resp_x, resp_y, resp_z);
		CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y);
		Cell resp_cell(resp_val);

		if (cur_cell.DiffGrid(resp_cell)) {
			c->GetMap()->CreatureRespawnRelocation(c);
			// false result ignored: will be unload with other creatures at grid
		}
	}
}
Example #12
0
 void Test() override
 {
     switch (GetTestStep())
     {
         case 0:
         {
             Creature* c = SpawnCreature(1, 1);
             if (!c)
                 Fail("Failed to summon a creature");
             else if (c->GetMap() != GetMap())
                 Fail("Creature summoned on the wrong map");
             else if (!c->FindNearestCreature(NPC_MAGMADAR, 50.0f))
                 Fail("Unit magmadar not found near creature");
             SpawnPlayer(0, CLASS_WARLOCK, RACE_GNOME);
             Wait(500);
             NextStep();
             break;
         }
         case 1:
         {
             Player* p = GetTestPlayer(0);
             if (!p)
                 Fail("Unable to summon a player");
             else if (p->getClass() != CLASS_WARLOCK && p->getRace() != RACE_GNOME)
                 Fail("Bad player class or race");
             else if (p->FindMap() != GetMap())
                 Fail("Bad player map");
             else if (p->GetInstanceId() != GetMap()->GetInstanceId())
                 Fail("Diff instance id (player vs map)");
             else if (!p->FindNearestCreature(NPC_MAGMADAR, 50.0f))
                 Fail("Unit magmadar not found near player");
             else
                 Finish();
             return;
         }
     }
 }
Example #13
0
    bool EffectDummy(Unit* /*pCaster*/, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Object* pTarget, ObjectGuid /*originalCasterGuid*/) override
    {
        Creature* pCreatureTarget = pTarget->ToCreature();
        if (uiEffIndex != EFFECT_INDEX_0 || pCreatureTarget->GetEntry() != NPC_SUB_BOSS_TRIGGER)
            return true;

        ScriptedInstance* pInstance = (ScriptedInstance*)pCreatureTarget->GetInstanceData();

        if (!pInstance)
            return true;

        if (Creature* ptarget = pCreatureTarget->GetMap()->GetCreature(ObjectGuid(pInstance->GetData64(DATA64_GOTH_RANDOM_LEFT))))
        {
            uint32 uiTriggered = SPELL_A_TO_SKULL;

            if (uiSpellId == SPELL_B_TO_ANCHOR_2)
                uiTriggered = SPELL_B_TO_SKULL;
            else if (uiSpellId == SPELL_C_TO_ANCHOR_2)
                uiTriggered = SPELL_C_TO_SKULL;

            pCreatureTarget->CastSpell(ptarget, uiTriggered, true);
        }
        return true;
    }
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
{
    float destX = i_x;
    float destY = i_y;
    float destZ = i_z;

    creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    // check if new random position is assigned, GetReachableRandomPosition may fail
    if (creature.GetMap()->GetReachableRandomPosition(&creature, destX, destY, destZ, i_radius))
    {
        Movement::MoveSplineInit init(creature);
        init.MoveTo(destX, destY, destZ, true);
        init.SetWalk(true);
        init.Launch();
        if (roll_chance_i(MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK))
            i_nextMoveTime.Reset(50);
        else
            i_nextMoveTime.Reset(urand(3000, 10000));       // Keep a short wait time
    }
    else
        i_nextMoveTime.Reset(50);                           // Retry later
    return;
}
Example #15
0
    void FilterTargets(std::list<WorldObject*>& targets)
    {
        // Shards of torment seems to target tanks if no other targets are available as of Warlords of Draenor
        if (targets.size() <= 1)
        {
            _hasTarget = !targets.empty();
            return;
        }

        Creature* caster = GetCaster()->ToCreature();
        if (!caster || !caster->IsAIEnabled)
            return;

        if (WorldObject* tank = caster->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO))
            targets.remove(tank);

        std::list<WorldObject*> melee, ranged;
        for (WorldObject* target : targets)
        {
            if (caster->IsWithinMeleeRange(target->ToUnit()))
                melee.push_back(target);
            else
                ranged.push_back(target);
        }

        targets.clear();

        if (caster->GetMap()->Is25ManRaid())
            if (WorldObject* target = GetRandomContainerElement(ranged, melee))
                targets.push_back(target);

        if (WorldObject* target = GetRandomContainerElement(melee, ranged))
            targets.push_back(target);

        _hasTarget = !targets.empty();
    }
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);
}
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_UNKNOWN7);

            // 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 creature %u (entry %u).", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetDBTableGUIDLow(), creature.GetEntry());
                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.Say(behavior->textid[rand() % i], 0, 0);
                    }
                    else
                        creature.Say(behavior->textid[0], 0, 0);
                }
            }                                               // 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_UNKNOWN7);

            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 HandleDummy(SpellEffIndex /*effIndex*/)
        {
            uint32 roll = urand(1, 100);

            uint8 ev;
            if (roll <= 50)
                ev = EVENT_MISS;
            else if (roll <= 83)
                ev = EVENT_HIT;
            else
                ev = EVENT_MISS_BIRD;

            Unit* shooter = GetCaster();
            Creature* wilhelm = GetHitUnit()->ToCreature();
            Creature* apple = shooter->FindNearestCreature(NPC_APPLE, 30);
            Creature* drostan = shooter->FindNearestCreature(NPC_DROSTAN, 30);

            if (!wilhelm || !apple || !drostan)
                return;

            switch (ev)
            {
                case EVENT_MISS_BIRD:
                {
                    Creature* crunchy = shooter->FindNearestCreature(NPC_CRUNCHY, 30);
                    Creature* bird = shooter->FindNearestCreature(NPC_THICKBIRD, 30);

                    if (!bird || !crunchy)
                        ; // fall to EVENT_MISS
                    else
                    {
                        shooter->CastSpell(bird, SPELL_MISS_BIRD_APPLE);
                        bird->CastSpell(bird, SPELL_BIRD_FALL);
                        wilhelm->AI()->Talk(SAY_WILHELM_MISS);
                        drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS);

                        bird->KillSelf();
                        crunchy->GetMotionMaster()->MovePoint(0, bird->GetPositionX(), bird->GetPositionY(),
                            bird->GetMap()->GetWaterOrGroundLevel(bird->GetPhaseShift(), bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ()));
                        /// @todo Make crunchy perform emote eat when he reaches the bird

                        break;
                    }
                }
                case EVENT_MISS:
                {
                    shooter->CastSpell(wilhelm, SPELL_MISS_APPLE);
                    wilhelm->AI()->Talk(SAY_WILHELM_MISS);
                    drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS);
                    break;
                }
                case EVENT_HIT:
                {
                    shooter->CastSpell(apple, SPELL_HIT_APPLE);
                    apple->CastSpell(apple, SPELL_APPLE_FALL);
                    wilhelm->AI()->Talk(SAY_WILHELM_HIT);
                    if (Player* player = shooter->ToPlayer())
                        player->KilledMonsterCredit(NPC_APPLE);
                    break;
                }
            }
        }
    //move selected creature
    static bool HandleNpcMoveCommand(ChatHandler* handler, const char* args)
    {
        uint32 lowguid = 0;

        Creature* pCreature = handler->getSelectedCreature();

        if (!pCreature)
        {
            // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
            char* cId = handler->extractKeyFromLink((char*)args,"Hcreature");
            if (!cId)
                return false;

            lowguid = atoi(cId);

            /* FIXME: impossible without entry
            if (lowguid)
                pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
            */

            // Attempting creature load from DB data
            if (!pCreature)
            {
                CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
                if (!data)
                {
                    handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
                    handler->SetSentErrorMessage(true);
                    return false;
                }

                uint32 map_id = data->mapid;

                if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
                {
                    handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
                    handler->SetSentErrorMessage(true);
                    return false;
                }
            }
            else
            {
                lowguid = pCreature->GetDBTableGUIDLow();
            }
        }
        else
        {
            lowguid = pCreature->GetDBTableGUIDLow();
        }

        float x = handler->GetSession()->GetPlayer()->GetPositionX();
        float y = handler->GetSession()->GetPlayer()->GetPositionY();
        float z = handler->GetSession()->GetPlayer()->GetPositionZ();
        float o = handler->GetSession()->GetPlayer()->GetOrientation();

        if (pCreature)
        {
            if (CreatureData const* data = sObjectMgr->GetCreatureData(pCreature->GetDBTableGUIDLow()))
            {
                const_cast<CreatureData*>(data)->posX = x;
                const_cast<CreatureData*>(data)->posY = y;
                const_cast<CreatureData*>(data)->posZ = z;
                const_cast<CreatureData*>(data)->orientation = o;
            }
            pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
            pCreature->GetMotionMaster()->Initialize();
            if (pCreature->isAlive())                            // dead creature will reset movement generator at respawn
            {
                pCreature->setDeathState(JUST_DIED);
                pCreature->Respawn();
            }
        }

        WorldDatabase.PExecute("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
        handler->PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
        return true;
    }
Example #20
0
void WorldSession::SendListInventory(ObjectGuid vendorguid)
{
    DEBUG_LOG("WORLD: Sent SMSG_LIST_INVENTORY");

    Creature* pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR);

    if (!pCreature)
    {
        DEBUG_LOG("WORLD: SendListInventory - %s not found or you can't interact with him.", vendorguid.GetString().c_str());
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, ObjectGuid(), 0);
        return;
    }

    // remove fake death
    if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);

    // Stop the npc if moving
    if (!pCreature->IsStopped())
        pCreature->StopMoving();

    VendorItemData const* vItems = pCreature->GetVendorItems();
    VendorItemData const* tItems = pCreature->GetVendorTemplateItems();

    uint8 customitems = vItems ? vItems->GetItemCount() : 0;
    uint8 numitems = customitems + (tItems ? tItems->GetItemCount() : 0);

    std::vector<bool> bitFlags;

    float discountMod = _player->GetReputationPriceDiscount(pCreature);

    uint8 count = 0;
    ByteBuffer buffer;
    for (uint8 vendorslot = 0; vendorslot < numitems; ++vendorslot)
    {
        VendorItem const* crItem = vendorslot < customitems ? vItems->GetItem(vendorslot) : tItems->GetItem(vendorslot - customitems);

        if (crItem)
        {
            uint32 price, displayId, buyCount, maxDurability;
            int32 maxCount;

            if (crItem->type == VENDOR_ITEM_TYPE_ITEM)
            {
                ItemPrototype const * pProto = ObjectMgr::GetItemPrototype(crItem->item);
                if (!pProto)
                    continue;

                if (!_player->isGameMaster())
                {
                    // class wrong item skip only for bindable case
                    if ((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP)
                        continue;

                    // race wrong item skip always
                    if ((pProto->Flags2 & ITEM_FLAG2_HORDE_ONLY) && _player->GetTeam() != HORDE)
                        continue;

                    if ((pProto->Flags2 & ITEM_FLAG2_ALLIANCE_ONLY) && _player->GetTeam() != ALLIANCE)
                        continue;

                    if ((pProto->AllowableRace & _player->getRaceMask()) == 0)
                        continue;

                    if (crItem->conditionId && !sObjectMgr.IsPlayerMeetToCondition(crItem->conditionId, _player, pCreature->GetMap(), pCreature, CONDITION_FROM_VENDOR))
                        continue;
                }

                // possible item coverting for BoA case
                if (pProto->Flags & ITEM_FLAG_BOA)
                {
                    // convert if can use and then buy
                    if (pProto->RequiredReputationFaction && uint32(_player->GetReputationRank(pProto->RequiredReputationFaction)) >= pProto->RequiredReputationRank)
                    {
                        // checked at convert data loading as existed
                        if (uint32 newItemId = sObjectMgr.GetItemConvert(crItem->item, _player->getRaceMask()))
                            pProto = ObjectMgr::GetItemPrototype(newItemId);
                    }
                }

                ++count;
                if (count >= MAX_VENDOR_ITEMS)
                    break;

                // reputation discount
                maxDurability = pProto->MaxDurability;
                price = (crItem->ExtendedCost == 0 || pProto->Flags2 & ITEM_FLAG2_EXT_COST_REQUIRES_GOLD) ? uint32(floor(pProto->BuyPrice * discountMod)) : 0;
                displayId = pProto->DisplayInfoID;
                maxCount = crItem->maxcount <= 0 ? -1 : int32(pCreature->GetVendorItemCurrentCount(crItem));
                buyCount = pProto->BuyCount;

            }
            else if (crItem->type == VENDOR_ITEM_TYPE_CURRENCY)
            {
                CurrencyTypesEntry const * pCurrency = sCurrencyTypesStore.LookupEntry(crItem->item);
                if (!pCurrency)
                    continue;

                if (pCurrency->Category == CURRENCY_CATEGORY_META)
                    continue;

                ++count;
                if (count >= MAX_VENDOR_ITEMS)
                    break;

                maxDurability = 0;
                price = 0;
                displayId = 0;
                maxCount = -1;
                buyCount = crItem->maxcount;
            }
            else
                continue;

            bitFlags.push_back(crItem->ExtendedCost == 0);
            bitFlags.push_back(true);                       // unk

            buffer << uint32(vendorslot + 1);               // client size expected counting from 1
            buffer << uint32(maxDurability);

            if (crItem->ExtendedCost)
                buffer << uint32(crItem->ExtendedCost);

            buffer << uint32(crItem->item);
            buffer << uint32(crItem->type);
            buffer << uint32(price);
            buffer << uint32(displayId);
            buffer << int32(maxCount);
            buffer << uint32(buyCount);
        }
    }

    WorldPacket data(SMSG_LIST_INVENTORY, (8 + 3 + 1 + 1 + numitems * 8 * 4));

    data.WriteGuidMask<1, 0>(vendorguid);
    data.WriteBits(count, 21);
    data.WriteGuidMask<3, 6, 5, 2, 7>(vendorguid);

    for (uint32 i = 0; i < bitFlags.size(); ++i)
        data.WriteBit(bitFlags[i]);

    data.WriteGuidMask<4>(vendorguid);
    data.FlushBits();
    data.append(buffer);

    data.WriteGuidBytes<5, 4, 1, 0, 6>(vendorguid);
    data << uint8(count == 0);
    data.WriteGuidBytes<2, 3, 7>(vendorguid);

    SendPacket(&data);
}
Example #21
0
    void SetData(uint32 type, uint32 data)
    {
        switch(type)
        {
            case DATA_RAGEWINTERCHILLEVENT: Encounters[0] = data; break;
            case DATA_ANETHERONEVENT:       
                Encounters[1] = data;                
                break;
            case DATA_KAZROGALEVENT:        Encounters[2] = data; break;
            case DATA_AZGALOREVENT:    
                {
                    Encounters[3] = data; 
                    if(data==DONE)
                    {                    
                        if(ArchiYell)break;
                        ArchiYell = true;

                        Creature* pCreature = instance->GetCreatureInMap(Azgalor);
                        if(pCreature)
                        {                    
                            Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000);
            
                            Map *map = pCreature->GetMap();
                            if (map->IsDungeon() && pUnit)
                            {
                                pUnit->SetVisibility(VISIBILITY_OFF);
                                Map::PlayerList const &PlayerList = map->GetPlayers();
                                if (PlayerList.isEmpty())
                                     return;
                              
                                for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                                {
                                     if (i->getSource())
                                     {
                                        WorldPacket data(SMSG_MESSAGECHAT, 200);                
                                        pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,"All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more.",0,"Archimonde",i->getSource()->GetGUID());
                                        i->getSource()->GetSession()->SendPacket(&data);

                                        WorldPacket data2(SMSG_PLAY_SOUND, 4);
                                        data2 << 10986;
                                        i->getSource()->GetSession()->SendPacket(&data2);
                                     }
                                }
                            }
                        }
                    }
                }
                break;
            case DATA_ARCHIMONDEEVENT:      Encounters[4] = data; break;
            case DATA_RESET_TRASH_COUNT:    Trash = 0;            break;

            case DATA_TRASH:
                if(data) Trash = data;
                else     Trash--;
                UpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash);
                break;
            case DATA_ALLIANCE_RETREAT:                
                allianceRetreat = data;
                OpenDoor(HordeGate,true);
                SaveToDB();
                break;
            case DATA_HORDE_RETREAT: 
                hordeRetreat = data;
                OpenDoor(ElfGate,true);
                SaveToDB();
                break;
            case DATA_RAIDDAMAGE:
                RaidDamage += data;
                if(RaidDamage >= MINRAIDDAMAGE)
                    RaidDamage = MINRAIDDAMAGE;
                break;
            case DATA_RESET_RAIDDAMAGE:
                RaidDamage = 0;
                break;
        }

         debug_log("SD2: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data);

        if(data == DONE)
        {
            OUT_SAVE_INST_DATA;

            std::ostringstream saveStream;
            saveStream << Encounters[0] << " " << Encounters[1] << " " << Encounters[2] << " "
                << Encounters[3] << " " << Encounters[4]
                << " " << allianceRetreat << " " << hordeRetreat
                << " " << RaidDamage;

            str_data = saveStream.str();

            SaveToDB();
            OUT_SAVE_INST_DATA_COMPLETE;
        }

    }
void
RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
    float X,Y,Z,nx,ny,nz,wander_distance,ori,dist;

    creature.GetRespawnCoord(X, Y, Z, &ori, &wander_distance);

    Z = creature.GetPositionZ();
    TerrainInfo const* map = creature.GetTerrain();

    // For 2D/3D system selection
    //bool is_land_ok  = creature.canWalk();                // not used?
    //bool is_water_ok = creature.canSwim();                // not used?
    bool is_air_ok   = creature.canFly();

    const float angle = rand_norm_f()*(M_PI_F*2.0f);
    const float range = rand_norm_f()*wander_distance;
    const float distanceX = range * cos(angle);
    const float distanceY = range * sin(angle);

    nx = X + distanceX;
    ny = Y + distanceY;
    nz = Z;

    // prevent invalid coordinates generation
    MaNGOS::NormalizeMapCoord(nx);
    MaNGOS::NormalizeMapCoord(ny);

    dist = distanceX*distanceX + distanceY*distanceY;

    if (is_air_ok)                                          // 3D system above ground and above water (flying mode)
    {
        // Limit height change
        const float distanceZ = rand_norm_f() * sqrtf(dist)/2.0f;
        if(urand(0, 1))
            nz += distanceZ;
        else
            nz -= distanceZ;
        if(fabs(nz-Z) > wander_distance)
            nz = Z;
        float tz = map->GetHeight(nx, ny, nz, true);  // Map check only, vmap needed here but need to alter vmaps checks for height.
        float wz = map->GetWaterLevel(nx, ny, nz);

        // Problem here, we must fly above the ground and water, not under. Let's try on next tick
        if (tz >= nz || wz >= nz)
            return;
    }
    //else if (is_water_ok)                                 // 3D system under water and above ground (swimming mode)
    else                                                    // 2D only
    {
        nz = Z;
        if (!creature.GetMap()->IsNextZcoordOK(nx, ny, nz, dist))
            return;                                         // let's forget this bad coords where a z cannot be find and retry at next tick
        creature.UpdateGroundPositionZ(nx, ny, nz, dist);
    }

    Traveller<Creature> traveller(creature);

    creature.SetOrientation(creature.GetAngle(nx, ny));
    i_destinationHolder.SetDestination(traveller, nx, ny, nz);
    creature.addUnitState(UNIT_STAT_ROAMING_MOVE);

    if (is_air_ok && !(creature.canWalk() && creature.IsAtGroundLevel(Coords(nx, ny, nz))))
    {
        i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
        creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
    }
    //else if (is_water_ok)                                 // Swimming mode to be done with more than this check
    else
    {
        i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(), 10000+i_destinationHolder.GetTotalTravelTime()));
        creature.AddSplineFlag(SPLINEFLAG_WALKMODE);
    }
}
Example #23
0
/*
Tribute Event
*/
void instance_dire_maul::GordokTributeEvent(uint32 diff)
{
	if(1<2)return;
	Creature* pChoRush = instance->GetCreature(m_uiChoRushGUID);
	Creature* pMizzle = instance->GetCreature(m_uiMizzleGUID);
	Creature* pTrigger = instance->GetCreature(m_uiTributeTriggerGUID);

	Map* pMap;
	pMap = pChoRush->GetMap();

	Map::PlayerList const &PlayerList = pMap->GetPlayers();

	if ((GetData(TYPE_KING_GORDOK) == DONE) && pMap->GetCreature(m_uiChoRushGUID)->isAlive() && !pChoRushHome)
	{
		pChoRush->SetFlag(UNIT_NPC_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PASSIVE);
		pChoRush->setFaction(35);
		pChoRush->DeleteThreatList();
		pChoRush->CombatStop();
		pChoRush->SetCanAttackPlayer(false);
		pChoRush->AI()->EnterEvadeMode();

		pChoRushHome = true;
		GossipStepGordok = 1;
		Text_Timer_Event = 1000;
	}
	else if ((TYPE_KING_GORDOK == DONE) && pMap->GetCreature(m_uiChoRushGUID)->isDead())
	{
		for(Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
		{
			Player* pPlayer = itr->getSource();
			if (pPlayer->IsWithinDistInMap(pTrigger, 30.0f))
					pTrigger->CastSpell(pPlayer, SPELL_KING_OF_GORDOK, false);
		}
	}

	if(pChoRushHome)
	{
		if (Text_Timer_Event<diff)
		{
			switch (GossipStepGordok)
			{
				case 1:
				DoScriptText(ChoRush_SAY_1, pChoRush);
				pChoRush->HandleEmote(EMOTE_STATE_TALK);
				pChoRush->SummonCreature(NPC_MIZZLE_THE_CRAFTY, 817.666f, 478.371f, 37.3182f, 3.07057f, TEMPSUMMON_TIMED_DESPAWN, 9000000);
				Text_Timer_Event = 5000;
				break;

				case 2:
				pChoRush->HandleEmote(EMOTE_STATE_SIT);
				DoScriptText(Mizzle_SAY_1, pMizzle);
				pMizzle->HandleEmote(EMOTE_STATE_TALK);
				Text_Timer_Event = 5000;
				break;

				case 3:
				DoScriptText(Mizzle_SAY_2, pMizzle);
				pMizzle->HandleEmote(EMOTE_STATE_TALK);
				Text_Timer_Event = 8000;
				break;

				case 4:
				for(Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
				{
					Player* pPlayer = itr->getSource();
					if (pPlayer->IsWithinDistInMap(pMizzle, 50.0f))
							pMizzle->CastSpell(pPlayer, SPELL_KING_OF_GORDOK, false);
				}
				if (pMap->GetCreature(m_uiMoldarGUID)->isAlive() && pMap->GetCreature(m_uiMizzleGUID)->isAlive() && pMap->GetCreature(m_uiFengusGUID)->isAlive())
				{
					pMizzle->SummonObject(pMap, GO_GORDOK_TRIBUTE, 809.899719f, 482.306366f, 37.318359f, 0.212846f);
					pMizzle->HandleEmote(EMOTE_ONESHOT_APPLAUD);
				}
				pChoRushHome = false;
				break;
			}
		}
		else Text_Timer_Event -= diff;
	}
}
void WorldSession::SendListInventory(ObjectGuid vendorguid)
{
    DEBUG_LOG("WORLD: Sent SMSG_LIST_INVENTORY");

    Creature* pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR);

    if (!pCreature)
    {
        DEBUG_LOG("WORLD: SendListInventory - %s not found or you can't interact with him.", vendorguid.GetString().c_str());
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, ObjectGuid(), 0);
        return;
    }

    // remove fake death
    if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);

    // Stop the npc if moving
    pCreature->StopMoving();

    VendorItemData const* vItems = pCreature->GetVendorItems();
    VendorItemData const* tItems = pCreature->GetVendorTemplateItems();

    if (!vItems && !tItems)
    {
        WorldPacket data(SMSG_LIST_INVENTORY, (8 + 1 + 1));
        data << ObjectGuid(vendorguid);
        data << uint8(0);                                   // count==0, next will be error code
        data << uint8(0);                                   // "Vendor has no inventory"
        SendPacket(&data);
        return;
    }

    uint8 customitems = vItems ? vItems->GetItemCount() : 0;
    uint8 numitems = customitems + (tItems ? tItems->GetItemCount() : 0);

    uint8 count = 0;

    WorldPacket data(SMSG_LIST_INVENTORY, (8 + 1 + numitems * 8 * 4));
    data << ObjectGuid(vendorguid);

    size_t count_pos = data.wpos();
    data << uint8(count);

    float discountMod = _player->GetReputationPriceDiscount(pCreature);

    for (int i = 0; i < numitems; ++i)
    {
        VendorItem const* crItem = i < customitems ? vItems->GetItem(i) : tItems->GetItem(i - customitems);

        if (crItem)
        {
            uint32 itemId = crItem->item;
            ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId);
            if (pProto)
            {
                if (!_player->isGameMaster())
                {
                    // class wrong item skip only for bindable case
                    if ((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP)
                        continue;

                    // race wrong item skip always
                    if ((pProto->AllowableRace & _player->getRaceMask()) == 0)
                        continue;

                    if (crItem->conditionId && !sObjectMgr.IsPlayerMeetToCondition(crItem->conditionId, _player, pCreature->GetMap(), pCreature, CONDITION_FROM_VENDOR))
                        continue;
                }

                ++count;

                uint32 price = 0;
                // check if the item to sell is a mount
                switch (itemId) {
                    case 1132: // all normal mounts
                    case 2411:
                    case 2414:
                    case 5655:
                    case 5656:
                    case 5665:
                    case 5668:
                    case 5864:
                    case 5872:
                    case 5873:
                    case 8563:
                    case 8588:
                    case 8591:
                    case 8592:
                    case 8595:
                    case 8629:
                    case 8631:
                    case 8632:
                    case 13321:
                    case 13322:
                    case 13331:
                    case 13332:
                    case 13333:
                    case 15277:
                    case 15290:
                    case 28481:
                    case 28927:
                    case 29220:
                    case 29221:
                    case 29222:
                    case 29743:
                    case 29744:
                    case 33224:
                    case 33976:
                        // apply discount for regular mount and set price
                        price = uint32(floor(AccountTypes(sWorld.getConfig(CONFIG_UINT32_MOUNT_COST)) * discountMod));
                        break;
                    case 8586: // all epic mounts
                    case 12302:
                    case 12303:
                    case 12330:
                    case 12351:
                    case 12353:
                    case 12354:
                    case 13086:
                    case 13317:
                    case 13326:
                    case 13327:
                    case 13328:
                    case 13329:
                    case 13334:
                    case 15292:
                    case 15293:
                    case 18766:
                    case 18767:
                    case 18772:
                    case 18773:
                    case 18774:
                    case 18776:
                    case 18777:
                    case 18778:
                    case 18785:
                    case 18786:
                    case 18787:
                    case 18788:
                    case 18789:
                    case 18790:
                    case 18791:
                    case 18793:
                    case 18794:
                    case 18795:
                    case 18796:
                    case 18797:
                    case 18798:
                    case 18902:
                    case 21176:
                    case 21218:
                    case 21321:
                    case 21323:
                    case 21324:
                    case 28936:
                    case 29102:
                    case 29103:
                    case 29104:
                    case 29105:
                    case 29223:
                    case 29224:
                    case 29227:
                    case 29229:
                    case 29230:
                    case 29231:
                    case 29745:
                    case 29746:
                    case 29747:
                    case 33225:
                    case 33977:
                    case 35513:
                    case 37719:
                    case 37828:
                    case 38576:
                        // apply discount for epic mount and set price
                        price = uint32(floor(AccountTypes(sWorld.getConfig(CONFIG_UINT32_EPIC_MOUNT_COST)) * discountMod));
                        break;
                    default:
                        // any other items
                        price = uint32(floor(pProto->BuyPrice * discountMod));
                        break;
                }

                data << uint32(count);
                data << uint32(itemId);
                data << uint32(pProto->DisplayInfoID);
                data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem));
                data << uint32(price);
                data << uint32(pProto->MaxDurability);
                data << uint32(pProto->BuyCount);
                data << uint32(crItem->ExtendedCost);
            }
        }
    }

    if (count == 0)
    {
        data << uint8(0);                                   // "Vendor has no inventory"
        SendPacket(&data);
        return;
    }

    data.put<uint8>(count_pos, count);
    SendPacket(&data);
}
bool
WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff)
{
    if (!&unit)
        return true;

    if (!path_id)
        return false;

    // Waypoint movement can be switched on/off
    // This is quite handy for escort quests and other stuff
    if (unit.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
        return true;

    // Clear the generator if the path doesn't exist
    if (!waypoints || !waypoints->size())
        return false;

    Traveller<Creature> traveller(unit);

    i_nextMoveTime.Update(diff);
    i_destinationHolder.UpdateTraveller(traveller, diff, true);

    if (i_nextMoveTime.GetExpiry() < TIMEDIFF_NEXT_WP)
    {
        if (unit.IsStopped())
        {
            if (StopedByPlayer)
            {
                ASSERT(node);
                InitTraveller(unit, *node);
                i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
                i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
                StopedByPlayer = false;
                return true;
            }

            if (i_currentNode == waypoints->size() - 1) // If that's our last waypoint
            {
                if (repeating)         // If the movement is repeating
                    i_currentNode = 0; // Start moving all over again
                else
                {
                    unit.SetHomePosition(node->x, node->y, node->z, unit.GetOrientation());
                    unit.GetMotionMaster()->Initialize();
                    return false; // Clear the waypoint movement
                }
            }
            else
                ++i_currentNode;

            node = waypoints->at(i_currentNode);
            InitTraveller(unit, *node);
            i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
            i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());

            //Call for creature group update
            if (unit.GetFormation() && unit.GetFormation()->getLeader() == &unit)
                unit.GetFormation()->LeaderMoveTo(node->x, node->y, node->z);
        }
        else
        {
            //Determine waittime
            if (node->delay)
                i_nextMoveTime.Reset(node->delay);

            //note: disable "start" for mtmap
            if (node->event_id && urand(0,99) < node->event_chance)
                unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/);

            i_destinationHolder.ResetTravelTime();
            MovementInform(unit);
            unit.UpdateWaypointID(i_currentNode);
            unit.ClearUnitState(UNIT_STAT_ROAMING);
            unit.Relocate(node->x, node->y, node->z);
        }
    }
    else
    {
        if (unit.IsStopped() && !i_destinationHolder.HasArrived())
        {
            if (!StopedByPlayer)
            {
                i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
                i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
                StopedByPlayer = true;
            }
        }
    }
    return true;
}
    void SetData(uint32 type, uint32 data)
    {
        switch(type)
        {
            case DATA_RAGEWINTERCHILLEVENT: Encounters[0] = data; break;
            case DATA_ANETHERONEVENT:
                Encounters[1] = data;
                break;
            case DATA_KAZROGALEVENT:        Encounters[2] = data; break;
            case DATA_AZGALOREVENT:
                {
                    Encounters[3] = data;
                    if (data == DONE)
                    {
                        if (ArchiYell)break;
                        ArchiYell = true;

                        Creature* pCreature = instance->GetCreature(Azgalor);
                        if (pCreature)
                        {
                            Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000);

                            Map* pMap = pCreature->GetMap();
                            if (pMap->IsDungeon() && pUnit)
                            {
                                pUnit->SetVisibility(VISIBILITY_OFF);
                                Map::PlayerList const &PlayerList = pMap->GetPlayers();
                                if (PlayerList.isEmpty())
                                     return;

                                for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                                {
                                     if (i->getSource())
                                     {
                                        WorldPacket data(SMSG_MESSAGECHAT, 200);
                                        pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,YELL_EFFORTS,0,YELL_EFFORTS_NAME,i->getSource()->GetGUID());
                                        i->getSource()->GetSession()->SendPacket(&data);

                                        WorldPacket data2(SMSG_PLAY_SOUND, 4);
                                        data2 << 10986;
                                        i->getSource()->GetSession()->SendPacket(&data2);
                                     }
                                }
                            }
                        }
                    }
                }
                break;
            case DATA_ARCHIMONDEEVENT:      Encounters[4] = data; break;
            case DATA_RESET_TRASH_COUNT:    Trash = 0;            break;

            case DATA_TRASH:
                if (data) Trash = data;
                else     Trash--;
                UpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash);
                break;
            case DATA_ALLIANCE_RETREAT:
                allianceRetreat = data;
                OpenDoor(HordeGate,true);
                SaveToDB();
                break;
            case DATA_HORDE_RETREAT:
                hordeRetreat = data;
                OpenDoor(ElfGate,true);
                SaveToDB();
                break;
            case DATA_RAIDDAMAGE:
                RaidDamage += data;
                if (RaidDamage >= MINRAIDDAMAGE)
                    RaidDamage = MINRAIDDAMAGE;
                break;
            case DATA_RESET_RAIDDAMAGE:
                RaidDamage = 0;
                break;
        }

         debug_log("BSCR: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data);

        if (data == DONE)
            SaveToDB();
    }
Example #27
0
void WorldSession::SendListInventory(ObjectGuid vendorguid)
{
    DEBUG_LOG("WORLD: Sent SMSG_LIST_INVENTORY");

    Creature* pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR);

    if (!pCreature)
    {
        DEBUG_LOG("WORLD: SendListInventory - %s not found or you can't interact with him.", vendorguid.GetString().c_str());
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, nullptr, ObjectGuid(), 0);
        return;
    }

    // Stop the npc if moving
    pCreature->StopMoving();

    VendorItemData const* vItems = pCreature->GetVendorItems();
    VendorItemData const* tItems = pCreature->GetVendorTemplateItems();

    if (!vItems && !tItems)
    {
        WorldPacket data(SMSG_LIST_INVENTORY, (8 + 1 + 1));
        data << ObjectGuid(vendorguid);
        data << uint8(0);                                   // count==0, next will be error code
        data << uint8(0);                                   // "Vendor has no inventory"
        SendPacket(&data);
        return;
    }

    uint8 customitems = vItems ? vItems->GetItemCount() : 0;
    uint8 numitems = customitems + (tItems ? tItems->GetItemCount() : 0);

    uint8 count = 0;

    WorldPacket data(SMSG_LIST_INVENTORY, (8 + 1 + numitems * 7 * 4));
    data << ObjectGuid(vendorguid);

    size_t count_pos = data.wpos();
    data << uint8(count);

    float discountMod = _player->GetReputationPriceDiscount(pCreature);

    for (int i = 0; i < numitems; ++i)
    {
        VendorItem const* crItem = i < customitems ? vItems->GetItem(i) : tItems->GetItem(i - customitems);

        if (crItem)
        {
            uint32 itemId = crItem->item;
            ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId);
            if (pProto)
            {
                if (!_player->isGameMaster())
                {
                    // class wrong item skip only for bindable case
                    if ((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP)
                        continue;

                    // race wrong item skip always
                    if ((pProto->AllowableRace & _player->getRaceMask()) == 0)
                        continue;

                    // when no faction required but rank > 0 will be used faction id from the vendor faction template to compare the rank
                    if (!pProto->RequiredReputationFaction && pProto->RequiredReputationRank > 0 &&
                            ReputationRank(pProto->RequiredReputationRank) > _player->GetReputationRank(pCreature->getFactionTemplateEntry()->faction))
                        continue;

                    if (crItem->conditionId && !sObjectMgr.IsPlayerMeetToCondition(crItem->conditionId, _player, pCreature->GetMap(), pCreature, CONDITION_FROM_VENDOR))
                        continue;
                }

                ++count;

                // reputation discount
                uint32 price = uint32(floor(pProto->BuyPrice * discountMod));

                data << uint32(count);
                data << uint32(itemId);
                data << uint32(pProto->DisplayInfoID);
                data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem));
                data << uint32(price);
                data << uint32(pProto->MaxDurability);
                data << uint32(pProto->BuyCount);
            }
        }
    }

    if (count == 0)
    {
        data << uint8(0);                                   // "Vendor has no inventory"
        SendPacket(&data);
        return;
    }

    data.put<uint8>(count_pos, count);
    SendPacket(&data);
}
    void DoIntro()
    {
        Creature *pMadrigosa = (Creature*)me->GetUnit(pInstance->GetData64(DATA_MADRIGOSA));
        if (!pMadrigosa)
            return;

        switch (IntroPhase)
        {
        case 0:
            DoScriptText(YELL_MADR_ICE_BARRIER, pMadrigosa);
            pMadrigosa->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            for (uint8 i = 0; i < 8; ++i)
                pMadrigosa->SetSpeed(UnitMoveType(i), 2.5);

            pMadrigosa->GetMotionMaster()->MovePoint(1, MADRI_FLY_X, MADRI_FLY_Y, MADRI_FLY_Z);
            IntroPhaseTimer = 6500;
            ++IntroPhase;
            break;
        case 1:
            pInstance->SetData(DATA_BRUTALLUS_INTRO_EVENT, IN_PROGRESS);
            pMadrigosa->SetLevitate(false);
            pMadrigosa->SetWalk(true);
            pMadrigosa->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
            IntroPhaseTimer = 2500;
            ++IntroPhase;
            break;
        case 2:
            pMadrigosa->SendHeartBeat();
            DoScriptText(YELL_MADR_INTRO, pMadrigosa);
            IntroPhaseTimer = 5000;
            ++IntroPhase;
            break;
        case 3:
            float x, y, z;
            pMadrigosa->GetMap()->CreatureRelocation((Creature*)pMadrigosa, MADRI_FLY_X, MADRI_FLY_Y, MADRI_FLY_Z, me->GetOrientation());
            me->SetInFront(pMadrigosa);
            pMadrigosa->SetInFront(me);
            DoScriptText(YELL_INTRO, me);
            IntroPhaseTimer = 6000;
            ++IntroPhase;
            break;
        case 4:
            pMadrigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            DoStartMovement(pMadrigosa);
            pMadrigosa->GetMotionMaster()->MoveChase(me);
            me->Attack(pMadrigosa, true);
            pMadrigosa->Attack(me, true);
            IntroPhaseTimer = 7000;
            ++IntroPhase;
            break;
        case 5:
            pMadrigosa->CastSpell(me, SPELL_INTRO_FROST_BREATH, false);
            me->CastSpell(me, SPELL_INTRO_FROST_BREATH, true);
            IntroPhaseTimer = 2500;
            ++IntroPhase;
            break;
        case 6:
            me->GetMotionMaster()->MoveIdle();
            pMadrigosa->SetLevitate(true);
            pMadrigosa->GetPosition(x, y, z);
            pMadrigosa->GetMotionMaster()->MovePoint(2, x, y, z+15);
            pMadrigosa->setHover(true);
            IntroPhaseTimer = 4500;
            ++IntroPhase;
        case 7:
            pMadrigosa->SetInFront(me);
            pMadrigosa->CastSpell(me, SPELL_INTRO_FROST_BLAST, false);
            me->CastSpell(me, SPELL_INTRO_FROST_BLAST, true);
            DoScriptText(YELL_MADR_ICE_BLOCK, pMadrigosa);
            IntroFrostBoltTimer = 500;
            IntroPhaseTimer = 10000;
            ++IntroPhase;
            break;
        case 8:
            DoScriptText(YELL_INTRO_BREAK_ICE, me);
            IntroPhaseTimer = 2000;
            ++IntroPhase;
            break;
        case 9:
            me->GetMotionMaster()->MoveIdle();
            me->AttackStop();
            pMadrigosa->setHover(false);
            pMadrigosa->SetLevitate(false);
            pMadrigosa->SetWalk(true);
            pMadrigosa->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
            pMadrigosa->SendHeartBeat();
            IntroPhaseTimer = 1000;
            ++IntroPhase;
            break;
        case 10:
            pMadrigosa->GetMotionMaster()->MoveIdle();
            IntroPhaseTimer = 2500;
            ++IntroPhase;
            break;
        case 11:
            pMadrigosa->GetMap()->CreatureRelocation((Creature*)pMadrigosa, MADRI_FLY_X, MADRI_FLY_Y, MADRI_FLY_Z, me->GetOrientation());
            pMadrigosa->GetMotionMaster()->MoveIdle();
            IntroPhaseTimer = 2000;
            ++IntroPhase;
            break;
        case 12:
            me->GetMotionMaster()->MoveIdle();
            pMadrigosa->CastSpell(me, SPELL_INTRO_ENCAPSULATE, false);
            DoScriptText(YELL_MADR_TRAP, pMadrigosa);
            IntroPhaseTimer = 1000;
            ++IntroPhase;
            break;
        case 13:
            me->GetPosition(x, y, z);
            me->GetMotionMaster()->MovePoint(1, x-6, y-15, z+10);
            me->SetInFront(pMadrigosa);
            IntroPhaseTimer = 8000;
            ++IntroPhase;
            break;
        case 14:
            me->RemoveAurasDueToSpell(44883);
            pMadrigosa->InterruptNonMeleeSpells(false);
            pMadrigosa->GetMotionMaster()->MoveIdle();
            DoScriptText(YELL_INTRO_CHARGE, me);
            me->SetInFront(pMadrigosa);
            me->GetPosition(x, y, z);
            me->GetMotionMaster()->MoveFall();
            IntroPhaseTimer = 3500;
            ++IntroPhase;
            break;
        case 15:
            for(uint8 i = 0; i < 8; ++i)
                me->SetSpeed(UnitMoveType(i), 10.0);
            me->GetMotionMaster()->MoveCharge(MADRI_FLY_X-5, MADRI_FLY_Y-15, MADRI_FLY_Z);
            AddSpellToCast((Unit*)NULL, SPELL_INTRO_CHARGE);
            IntroPhaseTimer = 1000;
            ++IntroPhase;
            break;
        case 16:
            DoScriptText(YELL_MADR_DEATH, pMadrigosa);
            pMadrigosa->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
            pMadrigosa->SetFlag(UNIT_DYNAMIC_FLAGS, (UNIT_DYNFLAG_DEAD | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED));
            pMadrigosa->CombatStop();
            pMadrigosa->DeleteThreatList();
            pMadrigosa->setFaction(35);
            me->CombatStop();
            me->RemoveFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_PVP_ATTACKABLE));
            IntroPhaseTimer = 4000;
            ++IntroPhase;
            break;
        case 17:
            if(pInstance)
                me->SetFacingToObject(GameObject::GetGameObject(*me, pInstance->GetData64(DATA_BRUTALLUS_TRIGGER)));
            for(uint8 i = 0; i < 8; ++i)
                me->SetSpeed(UnitMoveType(i), 2.0);
            IntroPhaseTimer = 6000;
            ++IntroPhase;
            break;
        case 18:
            DoScriptText(YELL_INTRO_KILL_MADRIGOSA, me);
            IntroPhaseTimer = 8000;
            ++IntroPhase;
            break;
        case 19:
            DoScriptText(YELL_INTRO_TAUNT, me);
            AddSpellToCast(me, SPELL_INTRO_BREAK_ICE);
            if(pInstance)
                pInstance->SetData(DATA_BRUTALLUS_INTRO_EVENT, DONE);
            else
                return;
            if(Unit *pTrigger = me->GetUnit(pInstance->GetData64(DATA_BRUTALLUS_TRIGGER)))
                pTrigger->CastSpell((Unit*)NULL, SPELL_INTRO_BREAK_ICE_KNOCKBACK, false);
            IntroPhaseTimer = 2000;
            ++IntroPhase;
            break;
        case 20:
            EnterEvadeMode();
            ++IntroPhase;
            break;
        }
    }
Example #29
0
        void SetData(uint32 type, uint32 data)
        {
            switch (type)
            {
                case DATA_RAGEWINTERCHILLEVENT:
                    m_auiEncounter[0] = data;
                    break;
                case DATA_ANETHERONEVENT:
                    m_auiEncounter[1] = data;
                    break;
                case DATA_KAZROGALEVENT:
                    m_auiEncounter[2] = data;
                    break;
                case DATA_AZGALOREVENT:
                    {
                        m_auiEncounter[3] = data;
                        if (data == DONE)
                        {
                            if (ArchiYell)
                                break;

                            ArchiYell = true;

                            Creature* creature = instance->GetCreature(Azgalor);
                            if (creature)
                            {
                                Creature* unit = creature->SummonCreature(21987, creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000);

                                Map* map = creature->GetMap();
                                if (map->IsDungeon() && unit)
                                {
                                    unit->SetVisible(false);
                                    Map::PlayerList const &PlayerList = map->GetPlayers();
                                    if (PlayerList.isEmpty())
                                         return;

                                    for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                                    {
                                         if (i->getSource())
                                         {
                                            WorldPacket packet(SMSG_MESSAGECHAT, 200);
                                            unit->BuildMonsterChat(&packet, CHAT_MSG_MONSTER_YELL, YELL_EFFORTS, 0, YELL_EFFORTS_NAME, i->getSource()->GetGUID());
                                            i->getSource()->GetSession()->SendPacket(&packet);

                                            WorldPacket data2(SMSG_PLAY_SOUND, 4);
                                            data2 << uint32(10986);
                                            data2 << uint64(unit->GetGUID());
                                            i->getSource()->GetSession()->SendPacket(&data2);
                                         }
                                    }
                                }
                            }
                        }
                    }
                    break;
                case DATA_ARCHIMONDEEVENT:
                    m_auiEncounter[4] = data;
                    break;
                case DATA_RESET_TRASH_COUNT:
                    Trash = 0;
                    break;
                case DATA_TRASH:
                    if (data)
                        Trash = data;
                    else
                        Trash--;
                    DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash);
                    break;
                case TYPE_RETREAT:
                    if (data == SPECIAL)
                    {
                        if (!m_uiAncientGemGUID.empty())
                        {
                            for (std::list<uint64>::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr)
                            {
                                //don't know how long it expected
                                DoRespawnGameObject(*itr, DAY);
                            }
                        }
                    }
                    break;
                case DATA_ALLIANCE_RETREAT:
                    allianceRetreat = data;
                    HandleGameObject(HordeGate, true);
                    SaveToDB();
                    break;
                case DATA_HORDE_RETREAT:
                    hordeRetreat = data;
                    HandleGameObject(ElfGate, true);
                    SaveToDB();
                    break;
                case DATA_RAIDDAMAGE:
                    RaidDamage += data;
                    if (RaidDamage >= MINRAIDDAMAGE)
                        RaidDamage = MINRAIDDAMAGE;
                    break;
                case DATA_RESET_RAIDDAMAGE:
                    RaidDamage = 0;
                    break;
            }

             TC_LOG_DEBUG(LOG_FILTER_TSCR, "Instance Hyjal: Instance data updated for event %u (Data=%u)", type, data);

            if (data == DONE)
            {
                OUT_SAVE_INST_DATA;

                std::ostringstream saveStream;
                saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' '
                    << m_auiEncounter[3] << ' ' << m_auiEncounter[4]
                    << ' ' << allianceRetreat << ' ' << hordeRetreat
                    << ' ' << RaidDamage;

                str_data = saveStream.str();

                SaveToDB();
                OUT_SAVE_INST_DATA_COMPLETE;
            }

        }
void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) const
{
    DEBUG_LOG("WORLD: SendTrainerList");

    Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER);
    if (!unit)
    {
        DEBUG_LOG("WORLD: SendTrainerList - %s not found or you can't interact with him.", guid.GetString().c_str());
        return;
    }

    // trainer list loaded at check;
    if (!unit->IsTrainerOf(_player, true))
        return;

    CreatureInfo const* ci = unit->GetCreatureInfo();
    if (!ci)
        return;

    TrainerSpellData const* cSpells = unit->GetTrainerSpells();
    TrainerSpellData const* tSpells = unit->GetTrainerTemplateSpells();

    if (!cSpells && !tSpells)
    {
        DEBUG_LOG("WORLD: SendTrainerList - Training spells not found for %s", guid.GetString().c_str());
        return;
    }

    uint32 maxcount = (cSpells ? cSpells->spellList.size() : 0) + (tSpells ? tSpells->spellList.size() : 0);
    uint32 trainer_type = cSpells && cSpells->trainerType ? cSpells->trainerType : (tSpells ? tSpells->trainerType : 0);

    WorldPacket data(SMSG_TRAINER_LIST, 8 + 4 + 4 + maxcount * 38 + strTitle.size() + 1);
    data << ObjectGuid(guid);
    data << uint32(trainer_type);

    size_t count_pos = data.wpos();
    data << uint32(maxcount);

    // reputation discount
    float fDiscountMod = _player->GetReputationPriceDiscount(unit);
    bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0;

    uint32 count = 0;

    if (cSpells)
    {
        for (TrainerSpellMap::const_iterator itr = cSpells->spellList.begin(); itr != cSpells->spellList.end(); ++itr)
        {
            TrainerSpell const* tSpell = &itr->second;

            uint32 triggerSpell = sSpellTemplate.LookupEntry<SpellEntry>(tSpell->spell)->EffectTriggerSpell[0];

            uint32 reqLevel = 0;
            if (!_player->IsSpellFitByClassAndRace(tSpell->spell, &reqLevel))
                continue;

            if (tSpell->conditionId && !sObjectMgr.IsPlayerMeetToCondition(tSpell->conditionId, GetPlayer(), unit->GetMap(), unit, CONDITION_FROM_TRAINER))
                continue;

            reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel);

            TrainerSpellState state = _player->GetTrainerSpellState(tSpell, reqLevel);

            SendTrainerSpellHelper(data, tSpell, triggerSpell, state, fDiscountMod, can_learn_primary_prof, reqLevel);

            ++count;
        }
    }

    if (tSpells)
    {
        for (TrainerSpellMap::const_iterator itr = tSpells->spellList.begin(); itr != tSpells->spellList.end(); ++itr)
        {
            TrainerSpell const* tSpell = &itr->second;

            uint32 triggerSpell = sSpellTemplate.LookupEntry<SpellEntry>(tSpell->spell)->EffectTriggerSpell[0];

            uint32 reqLevel = 0;
            if (!_player->IsSpellFitByClassAndRace(tSpell->spell, &reqLevel))
                continue;

            if (tSpell->conditionId && !sObjectMgr.IsPlayerMeetToCondition(tSpell->conditionId, GetPlayer(), unit->GetMap(), unit, CONDITION_FROM_TRAINER))
                continue;

            reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel);

            TrainerSpellState state = _player->GetTrainerSpellState(tSpell, reqLevel);

            SendTrainerSpellHelper(data, tSpell, triggerSpell, state, fDiscountMod, can_learn_primary_prof, reqLevel);

            ++count;
        }
    }

    data << strTitle;

    data.put<uint32>(count_pos, count);
    SendPacket(data);
}