예제 #1
0
bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target)
{
    if (!spellId)
        return false;

    if (!target)
        target = bot;

    Pet* pet = bot->GetPet();
    if (pet && pet->HasSpell(spellId))
    {
        pet->ToggleAutocast(spellId, true);
        TellMaster("My pet will auto-cast this spell");
        return true;
    }

    aiObjectContext->GetValue<LastSpellCast&>("last spell cast")->Get().Set(spellId, target->GetObjectGuid(), time(0));
    aiObjectContext->GetValue<LastMovement&>("last movement")->Get().Set(NULL);

    const SpellEntry* const pSpellInfo = sSpellStore.LookupEntry(spellId);

    MotionMaster &mm = *bot->GetMotionMaster();
    if (bot->isMoving() && GetSpellCastTime(pSpellInfo, NULL))
    {
        return false;
    }

    if (bot->IsTaxiFlying())
        return false;

    bot->clearUnitState( UNIT_STAT_CHASE );
    bot->clearUnitState( UNIT_STAT_FOLLOW );

    ObjectGuid oldSel = bot->GetSelectionGuid();
    bot->SetSelectionGuid(target->GetObjectGuid());

    Spell *spell = new Spell(bot, pSpellInfo, false);

    SpellCastTargets targets;
    targets.setUnitTarget(target);
    WorldObject* faceTo = target;

    if (pSpellInfo->Targets & TARGET_FLAG_ITEM)
    {
        spell->m_CastItem = aiObjectContext->GetValue<Item*>("item for spell", spellId)->Get();
        targets.setItemTarget(spell->m_CastItem);
    }

    if (pSpellInfo->Effect[0] == SPELL_EFFECT_OPEN_LOCK ||
        pSpellInfo->Effect[0] == SPELL_EFFECT_SKINNING)
    {
        LootObject loot = *aiObjectContext->GetValue<LootObject>("loot target");
        if (!loot.IsLootPossible(bot))
            return false;

        GameObject* go = GetGameObject(loot.guid);
        if (go && go->isSpawned())
        {
            WorldPacket* const packetgouse = new WorldPacket(CMSG_GAMEOBJ_USE, 8);
            *packetgouse << loot.guid;
            bot->GetSession()->QueuePacket(packetgouse);
            targets.setGOTarget(go);
            faceTo = go;
        }
        else
        {
            Unit* creature = GetUnit(loot.guid);
            if (creature)
            {
                targets.setUnitTarget(creature);
                faceTo = creature;
            }
        }
    }


    if (!bot->IsInFront(faceTo, sPlayerbotAIConfig.sightDistance))
    {
        bot->SetFacingTo(bot->GetAngle(faceTo));
        SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown);
        return false;
    }

    WaitForSpellCast(spellId);

    spell->prepare(&targets);
    bot->SetSelectionGuid(oldSel);

    LastSpellCast& lastSpell = aiObjectContext->GetValue<LastSpellCast&>("last spell cast")->Get();
    return lastSpell.id == spellId;
}
예제 #2
0
void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data )
{
    CHECK_PACKET_SIZE(recv_data,8);

    uint64 guid;
    uint32 spellId = OPEN_CHEST;
    const GameObjectInfo *info;

    recv_data >> guid;

    sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", guid);
    GameObject *obj = ObjectAccessor::GetGameObject(*_player, guid);

    if(!obj) return;
    //obj->SetUInt32Value(GAMEOBJECT_FLAGS,2);
    //obj->SetUInt32Value(GAMEOBJECT_FLAGS,2);

    // default spell caster is player that use GO
    Unit* spellCaster = GetPlayer();
    // default spell target is player that use GO
    Unit* spellTarget = GetPlayer();

    if (Script->GOHello(_player, obj))
        return;

    switch(obj->GetGoType())
    {
        case GAMEOBJECT_TYPE_DOOR:                          //0
            obj->SetUInt32Value(GAMEOBJECT_FLAGS,33);
            obj->SetUInt32Value(GAMEOBJECT_STATE,0);        //open
            //obj->SetUInt32Value(GAMEOBJECT_TIMESTAMP,0x465EE6D2); //load timestamp

            obj->SetLootState(GO_CLOSED);
            obj->SetRespawnTime(5);                         //close door in 5 seconds
            return;

        case GAMEOBJECT_TYPE_BUTTON:                        //1
            obj->SetUInt32Value(GAMEOBJECT_FLAGS,33);
            obj->SetUInt32Value(GAMEOBJECT_STATE,0);        //open
            obj->SetLootState(GO_CLOSED);
            obj->SetRespawnTime(2);                         //close in 1 seconds

            // activate script
            sWorld.ScriptsStart(sButtonScripts, obj->GetDBTableGUIDLow(), spellCaster, obj);
            return;

        case GAMEOBJECT_TYPE_QUESTGIVER:                    //2
            _player->PrepareQuestMenu( guid );
            _player->SendPreparedQuest( guid );
            return;

        //Sitting: Wooden bench, chairs enzz
        case GAMEOBJECT_TYPE_CHAIR:                         //7

            info = obj->GetGOInfo();
            if(info)
            {
                //spellId = info->data0;                   // this is not a spell or offset
                _player->TeleportTo(obj->GetMapId(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(),false,false);
                _player->SetFlag(UNIT_FIELD_BYTES_1,PLAYER_STATE_SIT_LOW_CHAIR); // Using (3 + spellId) was wrong, this is a number of slot for chair/bench, not offset
                _player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR);
                return;
            }
            break;

        //big gun, its a spell/aura
        case GAMEOBJECT_TYPE_GOOBER:                        //10
            info = obj->GetGOInfo();
            spellId = info ? info->data10 : 0;
            break;

        case GAMEOBJECT_TYPE_SPELLCASTER:                   //22

            obj->SetUInt32Value(GAMEOBJECT_FLAGS,2);

            info = obj->GetGOInfo();
            if(info)
            {
                spellId = info->data0;
                if (spellId == 0)
                    spellId = info->data3;

                //guid=_player->GetGUID();
            }

            break;
        case GAMEOBJECT_TYPE_CAMERA:                        //13
            info = obj->GetGOInfo();
            if(info)
            {
                uint32 cinematic_id = info->data1;
                if(cinematic_id)
                {
                    WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4);
                    data << cinematic_id;
                    _player->GetSession()->SendPacket(&data);
                }
                return;
            }
            break;

        //fishing bobber
        case GAMEOBJECT_TYPE_FISHINGNODE:                   //17
        {
            if(_player->GetGUID() != obj->GetOwnerGUID())
                return;

            switch(obj->getLootState())
            {
                case GO_CLOSED:                             // ready for loot
                {
                    // 1) skill must be >= base_zone_skill
                    // 2) if skill == base_zone_skill => 5% chance
                    // 3) chance is linear dependence from (base_zone_skill-skill)

                    int32 skill = _player->GetSkillValue(SKILL_FISHING);
                    int32 zone_skill = _player->FishingMinSkillForCurrentZone();
                    int32 chance = skill - zone_skill + 5;
                    int32 roll = irand(1,100);

                    DEBUG_LOG("Fishing check (skill: %i zone min skill: %i chance %i roll: %i",skill,zone_skill,chance,roll);

                    if(skill >= zone_skill && chance >= roll)
                    {
                        // prevent removing GO at spell cancel
                        _player->RemoveGameObject(obj,false);
                        obj->SetOwnerGUID(_player->GetGUID());

                        //fish catched
                        _player->UpdateFishingSkill();
                        _player->SendLoot(obj->GetGUID(),LOOT_FISHING);
                    }
                    else
                    {
                        // fish escaped
                        obj->SetLootState(GO_LOOTED);       // can be deleted now

                        WorldPacket data(SMSG_FISH_ESCAPED, 0);
                        SendPacket(&data);
                    }
                    break;
                }
                case GO_LOOTED:                             // nothing to do, will be deleted at next update
                    break;
                default:
                {
                    obj->SetLootState(GO_LOOTED);

                    WorldPacket data(SMSG_FISH_NOT_HOOKED, 0);
                    SendPacket(&data);
                    break;
                }
            }

            if(_player->m_currentSpells[CURRENT_CHANNELED_SPELL])
            {
                _player->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
                _player->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
            }
            return;
        }

        case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
        {
            Unit* caster = obj->GetOwner();

            info = obj->GetGOInfo();

            if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
                return;

            // accept only use by player from same group for caster except caster itself
            if(((Player*)caster)==GetPlayer() || !((Player*)caster)->IsInSameGroupWith(GetPlayer()))
                return;

            obj->AddUse(GetPlayer());

            // must 2 group members use GO, or only 1 when it is meeting stone summon
            if(obj->GetUniqueUseCount() < (info->data0 == 2 ? 1 : 2))
                return;

            // in case summoning ritual caster is GO creator
            spellCaster = caster;

            if(!caster->m_currentSpells[CURRENT_CHANNELED_SPELL])
                return;

            spellId = info->data1;

            // finish spell
            caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
            caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();

            // can be deleted now
            obj->SetLootState(GO_LOOTED);

            // go to end function to spell casting
            break;
        }
        case GAMEOBJECT_TYPE_MEETINGSTONE:                  //23
        {
            info = obj->GetGOInfo();

            Player* targetPlayer = ObjectAccessor::FindPlayer(((Player*)spellCaster)->GetSelection());

            // accept only use by player from same group for caster except caster itself
            if(!targetPlayer || targetPlayer == GetPlayer() || !targetPlayer->IsInSameGroupWith(GetPlayer()))
                return;

            //required lvl checks!
            uint8 level = _player->getLevel();
            if (level < info->data0 || level > info->data1)
                return;
            level = targetPlayer->getLevel();
            if (level < info->data0 || level > info->data1)
                return;

            spellId = 23598;

            break;
        }

        case GAMEOBJECT_TYPE_FLAGSTAND:                     // 24
            if(_player->InBattleGround() &&                 // in battleground
                !_player->IsMounted() &&                    // not mounted
                !_player->HasStealthAura() &&               // not stealthed
                !_player->HasInvisibilityAura() &&          // not invisible
                _player->isAlive())                         // live player
            {
                BattleGround *bg = _player->GetBattleGround();
                if(!bg)
                    return;
                // BG flag click
                // AB:
                // 15001
                // 15002
                // 15003
                // 15004
                // 15005
                // WS:
                // 179830 - Silverwing Flag
                // 179831 - Warsong Flag
                // EotS:
                // 184141 - Netherstorm Flag
                info = obj->GetGOInfo();
                if(info)
                {
                    switch(info->id)
                    {
                        case 179830:
                            // check if it's correct bg
                            if(bg->GetTypeID() != BATTLEGROUND_WS)
                                return;
                            // check if flag dropped
                            if(((BattleGroundWS*)bg)->GetFlagState(ALLIANCE) != BG_WS_FLAG_STATE_ON_BASE)
                                return;
                            // check if it's correct flag
                            if(((BattleGroundWS*)bg)->m_bgobjects[BG_WS_OBJECT_A_FLAG] != obj->GetGUID())
                                return;
                            // check player team
                            if(_player->GetTeam() == ALLIANCE)
                                return;
                            spellId = 23335;                // Silverwing Flag
                            break;
                        case 179831:
                            // check if it's correct bg
                            if(bg->GetTypeID() != BATTLEGROUND_WS)
                                return;
                            // check if flag dropped
                            if(((BattleGroundWS*)bg)->GetFlagState(HORDE) != BG_WS_FLAG_STATE_ON_BASE)
                                return;
                            // check if it's correct flag
                            if(((BattleGroundWS*)bg)->m_bgobjects[BG_WS_OBJECT_H_FLAG] != obj->GetGUID())
                                return;
                            // check player team
                            if(_player->GetTeam() == HORDE)
                                return;
                            spellId = 23333;                // Warsong Flag
                            break;
                        case 184141:
                            // check if it's correct bg
                            if(bg->GetTypeID() != BATTLEGROUND_EY)
                                return;
                            spellId = 34976;                // Netherstorm Flag
                            break;
                    }
                }
            }
            break;
        case GAMEOBJECT_TYPE_FLAGDROP:                      // 26
            if(_player->InBattleGround() &&                 // in battleground
                !_player->IsMounted() &&                    // not mounted
                !_player->HasStealthAura() &&               // not stealthed
                !_player->HasInvisibilityAura() &&          // not invisible
                _player->isAlive())                         // live player
            {
                BattleGround *bg = _player->GetBattleGround();
                if(!bg)
                    return;
                // BG flag dropped
                // WS:
                // 179785 - Silverwing Flag
                // 179786 - Warsong Flag
                // EotS:
                // 184142 - Netherstorm Flag
                info = obj->GetGOInfo();
                if(info)
                {
                    switch(info->id)
                    {
                        case 179785:                        // Silverwing Flag
                            // check if it's correct bg
                            if(bg->GetTypeID() != BATTLEGROUND_WS)
                                return;
                            // check if flag dropped
                            if(((BattleGroundWS*)bg)->GetFlagState(ALLIANCE) != BG_WS_FLAG_STATE_ON_GROUND)
                                return;
                            obj->Delete();
                            if(_player->GetTeam() == ALLIANCE)
                            {
                                ((BattleGroundWS*)bg)->EventPlayerReturnedFlag(_player);
                                return;
                            }
                            else
                            {
                                _player->CastSpell(_player, 23335, true);
                                return;
                            }
                            break;
                        case 179786:                        // Warsong Flag
                            // check if it's correct bg
                            if(bg->GetTypeID() != BATTLEGROUND_WS)
                                return;
                            // check if flag dropped
                            if(((BattleGroundWS*)bg)->GetFlagState(HORDE) != BG_WS_FLAG_STATE_ON_GROUND)
                                return;
                            obj->Delete();
                            if(_player->GetTeam() == HORDE)
                            {
                                ((BattleGroundWS*)bg)->EventPlayerReturnedFlag(_player);
                                return;
                            }
                            else
                            {
                                _player->CastSpell(_player, 23333, true);
                                return;
                            }
                            break;
                    }
                }
                obj->Delete();
            }
            break;
        default:
            sLog.outDebug("Unknown Object Type %u\n", obj->GetGoType());
            break;
    }

    if (!spellId) return;

    SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellId );
    if(!spellInfo)
    {
        sLog.outError("WORLD: unknown spell id %u\n", spellId);
        return;
    }

    Spell *spell = new Spell(spellCaster, spellInfo, false, 0);

    SpellCastTargets targets;
    targets.setUnitTarget( spellTarget );

    if(obj)
        targets.setGOTarget( obj );

    spell->prepare(&targets);
}