コード例 #1
7
ファイル: Services.cpp プロジェクト: ronw23/prime-osx
/* Melnorme strategy:
      - Wander around continuously until hero comes near
      - When hero is in room stop and turn purple
      - When hero left the room start to wander and turn green

   Returns ms elapsed, -2 if the monster dies.
*/
int
shMonster::doMelnorme ()
{
    int elapsed;
    int result = -1;
    int retries = 3;
    int myRoom = Level->getRoomID (mX, mY);

    while (-1 == result) {
        if (!retries--) {
            return 200;
        }

        /* Melnorme have no designated shop. They are willing to trade
           if you enter their room. This also allows them to relocate. */
        if (Level->getRoomID (Hero.mX, Hero.mY) == myRoom and
            Level->getRoomID (mX, mY) != 0)
        {
            if (mGlyph.mColor == kGreen and !isHostile ()) {
                /* Greet hero who just entered the room. */
                if (Hero.tryToTranslate (this)) {
                    char *buf = GetBuf ();
                    int rnd;
                    switch (RNG (3)) {
                    case 0: /* hello, heroname/title/racename */
                        rnd = RNG (4);
                        strncpy (buf, rnd == 0 ? Hero.mName :
                                      rnd == 1 ? Hero.mProfession->mName :
                                      rnd == 2 ? Hero.getTitle () :
                                                 Hero.myIlk ()->mName, SHBUFLEN);
                        if (rnd == 0) buf[0] = toupper (buf[0]);
                        break;
                    case 1: /* hello, heroname the Janitor */
                        snprintf (buf, SHBUFLEN, "%s the %s", Hero.mName,
                                  !RNG (3) ? Hero.mProfession->mName :
                                  !RNG (2) ? Hero.getTitle () :
                                             Hero.myIlk ()->mName);
                        buf[0] = toupper (buf[0]);
                        break;
                    case 2: /* hello, earthling Detective */
                        snprintf (buf, SHBUFLEN, "%s %s", Hero.myIlk ()->mName,
                                  !RNG (2) ? Hero.mProfession->mName :
                                             Hero.getTitle ());
                        break;
                    }

                    switch (RNG (4)) {
                    case 0:
                        I->p ("I bid you a formal welcome, %s.", buf); break;
                    case 1:
                        I->p ("Hello, %s.", buf); break;
                    case 2:
                        I->p ("How nice to see you, %s.", buf); break;
                    case 3: /* Use just the capitalized name because
                               greetings could be too long otherwise. */
                        strncpy (buf, Hero.mName, SHBUFLEN);
                        buf[0] = toupper (buf[0]);
                        I->p ("I had itchy pods recently, %s"
                              ", and here you are!", buf);
                        break;
                    }
                } else {
                    I->p ("%s mumbles something in coarse voice.", THE (this));
                }
            }
            mGlyph.mColor = kMagenta;
            mGlyph.mTileX = 3;

            /* Hero was greeted properly. Is this first encounter? */
            if (!Hero.getStoryFlag ("Met Melnorme")) {
                Hero.setStoryFlag ("Met Melnorme", 1);
                I->p ("Press '%s' to request services.",
                    I->getKeyForCommand (shInterface::kPay));
            }
        } else {
            mGlyph.mColor = kGreen;
            mGlyph.mTileX = 2;
        }

        switch (mTactic) {

        case kNewEnemy:
            mStrategy = kWander;
            mTactic = kNewEnemy;
            mGlyph.mColor = kNavy;
            mGlyph.mTileX = 4;
            return doWander ();
        case kMoveTo:
            result = doMoveTo ();
            continue;
        case kReady:
            /* Usually stay where you are but occassionally
               move to new square inside this room. */
            if (myRoom and !RNG (6)) {
                mDestX = RNG (mMelnorme.mSX, mMelnorme.mEX);
                mDestY = RNG (mMelnorme.mSY, mMelnorme.mEY);
                if (!mLevel->isOccupied (mDestX, mDestY)) {
                    elapsed = doQuickMoveTo ();
                    if (-1 == elapsed) elapsed = 800;
                    return elapsed;
                }
                return RNG (600, 1000); /* Path blocked. Wait. */
                /* !myRoom == Warp out of corridors eagerly. */
            } else if ((!myRoom or !RNG (40)) and
                       mGlyph.mColor == kGreen)
            {
                int newx = mX, newy = mY, tries = 3;
                while (tries--) {
                    mLevel->findUnoccupiedSquare (&newx, &newy);
                    if (!mLevel->isOccupied (newx, newy) and
                        !mLevel->isInShop (newx, newy) and
                        /* Do not accept corridors. */
                        (myRoom = Level->getRoomID (newx, newy)))
                    {
                        transport (newx, newy, 100, 1);
                        /* Update location data. */
                        Level->getRoomDimensions (myRoom,
                            &mMelnorme.mSX, &mMelnorme.mSY,
                            &mMelnorme.mEX, &mMelnorme.mEY);
                        /* Exclude walls from room coordinates. */
                        ++mMelnorme.mSX; ++mMelnorme.mSY;
                        --mMelnorme.mEX; --mMelnorme.mEY;
                        return FULLTURN;
                    }
                }
                return FULLTURN;
            } else {
                return FULLTURN;
            }
        default:
            mTactic = kReady;
            debug.log ("Unexpected Melnorme tactic!");
        }
    }

    return FULLTURN;
}
コード例 #2
0
ファイル: Pterodactyl.cpp プロジェクト: Sindorius/ABWD
void Pterodactyl::run(int x, int y) {

	
	if (this->getPositionX() > x && Xvelocity < cap) {
		Xvelocity += acceleration;
		if (isHostile()) {
			setAnim("pteraANGRYleft");
		}
		else {
			setAnim("pteraleft");
		}
	}
	else if (this->getPositionX() < x && Xvelocity > -cap) {
		Xvelocity -= acceleration;
		if (isHostile()) {
			setAnim("pteraANGRYright");
		}
		else {
			setAnim("pteraright");
		}
	}
	if (this->getPositionY() > y && Yvelocity < cap) {
		Yvelocity += acceleration;
	}
	else if (this->getPositionY() < y && Yvelocity > -cap) {
		Yvelocity -= acceleration;
	}

	this->setPositionX(this->getPositionX() - Xvelocity);
	this->setPositionY(this->getPositionY() - Yvelocity);

}
コード例 #3
0
        void BoneSpike()
        {
            switch (RandomUInt(2))
            {
                case 0:
                    _unit->SendScriptTextChatMessage(925);      // Bound by bone!
                    break;
                case 1:
                    _unit->SendScriptTextChatMessage(926);      // Stick around!
                    break;
                case 2:
                    _unit->SendScriptTextChatMessage(927);      // The only escape is death!
                    break;
            }

            std::vector<Player*> TargetTable;
            std::set<Object*>::iterator itr = _unit->GetInRangePlayerSetBegin();

            for (; itr != _unit->GetInRangePlayerSetEnd(); ++itr)
            {
                if (isHostile(_unit, (*itr)))
                {
                    Player* RandomTarget = NULL;
                    RandomTarget = static_cast<Player*>(*itr);
                    if (RandomTarget && RandomTarget->isAlive() && isHostile(_unit, RandomTarget))
                        TargetTable.push_back(RandomTarget);
                }
            }

            if (!TargetTable.size())
                return;

            auto random_index = RandomUInt(0, TargetTable.size() - 1);
            auto random_target = TargetTable[random_index];

            if (random_target == nullptr)
                return;

            _unit->CastSpell(random_target, dbcSpell.LookupEntry(BONE_SPIKE), false);

            TargetTable.clear();

            float dcX = random_target->GetPositionX();
            float dcY = random_target->GetPositionY();
            float dcZ = random_target->GetPositionZ();

            _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_BONE_SPIKE, dcX, dcY, dcZ, 0, true, false, 0, 0);

            TargetTable.clear();
        }
コード例 #4
0
ファイル: actor.cpp プロジェクト: opentibia/server
bool Actor::selectTarget(Creature* creature)
{
#ifdef __DEBUG__
  std::cout << "Selecting target... " << std::endl;
#endif

  if(!isTarget(creature)){
    return false;
  }

  CreatureList::iterator it = std::find(targetList.begin(), targetList.end(), creature);
  if(it == targetList.end()){
    //Target not found in our target list.
#ifdef __DEBUG__
    std::cout << "Target not found in targetList." << std::endl;
#endif
    return false;
  }

  if(isHostile() || isSummon()){
    if(setAttackedCreature(creature) && !isSummon()){
      g_dispatcher.addTask(createTask(
        boost::bind(&Game::checkCreatureAttack, &g_game, getID())));
    }
  }

  return setFollowCreature(creature, true);
}
コード例 #5
0
ファイル: Base.cpp プロジェクト: AegisEmu/AegisEmu
bool ArcScriptCreatureAI::IsValidUnitTarget(Object* pObject, TargetFilter pFilter)
{
	//Make sure its a valid unit
	if( !pObject->IsUnit() ) return false;
	if( pObject->GetInstanceID() != _unit->GetInstanceID() ) return false;
	Unit* UnitTarget = static_cast<Unit*>(pObject);

	//Skip dead, feign death or invisible targets
	if( !UnitTarget->isAlive() ) return false;
	if( UnitTarget->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FEIGN_DEATH) ) return false;
	if( UnitTarget->m_invisible ) return false;

	//Skip units not on threat list
	if( _unit->GetAIInterface()->getThreatByPtr(UnitTarget) == 0 ) return false;

	//Check if we apply target filtering
	if( pFilter != TargetFilter_None )
	{
		//Skip current attacking target if requested
		if( (pFilter & TargetFilter_NotCurrent) && UnitTarget == _unit->GetAIInterface()->GetNextTarget() ) return false;

		//Keep only wounded targets if requested
		if( (pFilter & TargetFilter_Wounded) && UnitTarget->GetHealthPct() >= 99 ) return false;

		//Handle hostile/friendly
		if( pFilter & TargetFilter_Friendly ) 
		{
			if( !UnitTarget->CombatStatus.IsInCombat() ) return false; //Skip not-in-combat targets if friendly
			if( isHostile(_unit, UnitTarget) || _unit->GetAIInterface()->getThreatByPtr(UnitTarget) > 0 ) return false;
		}
	}

	return true; //This is a valid unit target
}
コード例 #6
0
ファイル: perception.cpp プロジェクト: FrostHand/TiGa
void Perception::getHostile(Perception::Units &objects)
{
    for(Observed::iterator it=observed.begin(); it!=observed.end(); ++it)
    {
        Unit *obj=dynamic_cast<Unit *>(*it);
        if(obj && isHostile(obj,unit))
            objects.push_back(obj);
    }
}
コード例 #7
0
ファイル: monster.cpp プロジェクト: novasdream/tyano-core
bool Monster::isHostile() const {
	if (hasController()) {
		auto controller = getController()->getMonster();
		if (controller != nullptr) {
			return controller->isHostile();
		}

		return false;
	}

	return _type->isHostile;
}
コード例 #8
0
ファイル: monster.cpp プロジェクト: alexisjojo/darkkonia
bool Monster::canUseAttack(const Position& pos, const Creature* target) const
{
	if(!isHostile())
		return true;

	const Position& targetPos = target->getPosition();
	for(SpellList::iterator it = mType->spellAttackList.begin(); it != mType->spellAttackList.end(); ++it)
	{
		if((*it).range != 0 && std::max(std::abs(pos.x - targetPos.x), std::abs(pos.y - targetPos.y)) <= (int32_t)(*it).range)
			return g_game.isSightClear(pos, targetPos, true);
	}

	return false;
}
コード例 #9
0
ファイル: monster.cpp プロジェクト: WibbenZ/forgottenserver
bool Monster::canUseAttack(const Position& pos, const Creature* target) const
{
	if (isHostile()) {
		const Position& targetPos = target->getPosition();
		uint32_t distance = std::max<uint32_t>(Position::getDistanceX(pos, targetPos), Position::getDistanceY(pos, targetPos));
		for (const spellBlock_t& spellBlock : mType->info.attackSpells) {
			if (spellBlock.range != 0 && distance <= spellBlock.range) {
				return g_game.isSightClear(pos, targetPos, true);
			}
		}
		return false;
	}
	return true;
}
コード例 #10
0
ファイル: monster.cpp プロジェクト: CaosJunior/DxP
bool Monster::selectTarget(Creature* creature)
{
#ifdef __DEBUG__
	std::cout << "Selecting target... " << std::endl;
#endif
	if(!isTarget(creature))
		return false;
		
	if(!isHostile())
        return false;
        
     std::string value;
     if(getStorage(505, value) && value != "-1") {
       if(creature->isSummon()){
          if(value != creature->getMaster()->getName())
              return false;                     
       }else if(value != creature->getName()) //&& value != "0"){ -- se bugar  
           return false;    
     }   

	CreatureList::iterator it = std::find(targetList.begin(), targetList.end(), creature);
	if(it == targetList.end())
	{
		//Target not found in our target list.
#ifdef __DEBUG__
		std::cout << "Target not found in targetList." << std::endl;
#endif
		return false;
	}

	if((isHostile() || isSummon()) && setAttackedCreature(creature) && !isSummon())
		Dispatcher::getInstance().addTask(createTask(
			boost::bind(&Game::checkCreatureAttack, &g_game, getID())));

	return setFollowCreature(creature, true);
}
コード例 #11
0
ファイル: actor.cpp プロジェクト: opentibia/server
bool Actor::canUseAttack(const Position& pos, const Creature* target) const
{
  if(isHostile()){
    const Position& targetPos = target->getPosition();
    for(SpellList::const_iterator it = cType.spellAttackList().begin(), spell_attack_list_end = cType.spellAttackList().end(); it != spell_attack_list_end; ++it){
      if((*it).range != 0 && std::max(std::abs(pos.x - targetPos.x), std::abs(pos.y - targetPos.y)) <= (int32_t)(*it).range){
        return g_game.isSightClear(pos, targetPos, true);
      }
    }

    return false;
  }

  return true;
}
コード例 #12
0
ファイル: monster.cpp プロジェクト: WibbenZ/forgottenserver
bool Monster::selectTarget(Creature* creature)
{
	if (!isTarget(creature)) {
		return false;
	}

	auto it = std::find(targetList.begin(), targetList.end(), creature);
	if (it == targetList.end()) {
		//Target not found in our target list.
		return false;
	}

	if (isHostile() || isSummon()) {
		if (setAttackedCreature(creature) && !isSummon()) {
			g_dispatcher.addTask(createTask(std::bind(&Game::checkCreatureAttack, &g_game, getID())));
		}
	}
	return setFollowCreature(creature);
}
コード例 #13
0
        void VoidZoneArc()
        {
            ResetTimer(VoidTimer, (RandomUInt(10) + 30) * 1000);

            std::vector<Player*> TargetTable;
            set< Object* >::iterator Itr = _unit->GetInRangePlayerSetBegin();
            for (; Itr != _unit->GetInRangePlayerSetEnd(); Itr++)
            {
                Player* RandomTarget = NULL;
                if (!(*Itr)->IsPlayer())
                    continue;
                RandomTarget = TO< Player* >(*Itr);
                if (RandomTarget && RandomTarget->isAlive() && isHostile(*Itr, _unit))
                    TargetTable.push_back(RandomTarget);
            }

            if (!TargetTable.size())
                return;

            size_t RandTarget = rand() % TargetTable.size();

            Player* RTarget = TargetTable[RandTarget];

            if (!RTarget)
                return;

            float vzX = RandomUInt(5) * cos(RandomFloat(6.28f)) + RTarget->GetPositionX();
            float vzY = RandomUInt(5) * cos(RandomFloat(6.28f)) + RTarget->GetPositionY();
            float vzZ = RTarget->GetPositionZ();
            MoonScriptCreatureAI* VoidZone = SpawnCreature(CN_VOIDZONEARC, vzX, vzY, vzZ);
            VoidZone->GetUnit()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
            VoidZone->GetUnit()->m_noRespawn = true;
            if (!VoidZone->GetUnit()->IsInWorld())
            {
                VoidZone->Despawn();
                return;
            }
            RTarget = NULL;
            VoidZone->Despawn(60000, 0);
        }
コード例 #14
0
ファイル: monster.cpp プロジェクト: novasdream/tyano-core
bool Monster::isEnemy(const Creature& creature) const {
	if (hasMaster()) {
		return _master->isEnemy(creature);
	}

	if (!isHostile()) {
		return false;
	}

	PlayerPC controller = creature.getController();
	if (controller == nullptr) {
		return false;
	}

	if (controller->hasFlag(PlayerFlag_IgnoredByMonsters)) {
		return false;
	}

	if (controller->hasCondition(CONDITION_GAMEMASTER, GAMEMASTER_SNEAKY, false)) {
		return false;
	}

	return true;
}
コード例 #15
0
ファイル: Base.cpp プロジェクト: Refuge89/Hearthstone
bool MoonScriptCreatureAI::IsValidUnitTarget( Object *pObject, TargetFilters pFilter, float pMinRange, float pMaxRange )
{
	//Make sure its a valid unit
	if ( !pObject->IsUnit() )
		return false;
	if ( pObject->GetInstanceID() != _unit->GetInstanceID() )
		return false;

	Unit *UnitTarget = TO_UNIT( pObject );
	//Skip dead ( if required ), feign death or invisible targets
	if ( pFilter & TargetFilter_Corpse )
	{
		if ( UnitTarget->isAlive() || !UnitTarget->IsCreature() || TO_CREATURE( UnitTarget )->creature_info->Rank == ELITE_WORLDBOSS )
			return false;
	}
	else if ( !UnitTarget->isAlive() )
		return false;

	if ( UnitTarget->IsPlayer() && TO_PLAYER( UnitTarget )->m_isGmInvisible )
		return false;
	if ( UnitTarget->HasFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_FEIGN_DEATH ) )
		return false;

	//Check if we apply target filtering
	if ( pFilter != TargetFilter_None )
	{
		//Skip units not on threat list
		if ( ( pFilter & TargetFilter_Aggroed ) && _unit->GetAIInterface()->getThreatByPtr( UnitTarget ) == 0 )
			return false;

		//Skip current attacking target if requested
		if ( ( pFilter & TargetFilter_NotCurrent ) && UnitTarget == _unit->GetAIInterface()->GetNextTarget() )
			return false;

		//Keep only wounded targets if requested
		if ( ( pFilter & TargetFilter_Wounded ) && UnitTarget->GetHealthPct() >= 99 )
			return false;

		//Skip targets not in melee range if requested
		if ( ( pFilter & TargetFilter_InMeleeRange ) && GetRangeToUnit( UnitTarget ) > _unit->GetAIInterface()->_CalcCombatRange( UnitTarget, false ) )
			return false;

		//Skip targets not in strict range if requested
		if ( ( pFilter & TargetFilter_InRangeOnly ) && ( pMinRange > 0 || pMaxRange > 0 ) )
		{
			float Range = GetRangeToUnit( UnitTarget );
			if ( pMinRange > 0 && Range < pMinRange )
				return false;
			if ( pMaxRange > 0 && Range > pMaxRange )
				return false;
		};

		//Skip targets not in Line Of Sight if requested
		if ( ( ~pFilter & TargetFilter_IgnoreLineOfSight ) && !_unit->IsInLineOfSight( UnitTarget ) )
			return false;

		//Handle hostile/friendly
		if ( ( ~pFilter & TargetFilter_Corpse ) && ( pFilter & TargetFilter_Friendly ) ) 
		{
			if ( !UnitTarget->CombatStatus.IsInCombat() )
				return false; //Skip not-in-combat targets if friendly
			if ( isHostile( _unit, UnitTarget ) || _unit->GetAIInterface()->getThreatByPtr( UnitTarget ) > 0 )
				return false;
		};
	};

	return true; //This is a valid unit target
};
コード例 #16
0
	void CastSpellOnRandomTarget(uint32 i, float mindist2cast, float maxdist2cast, int minhp2cast, int maxhp2cast)
	{
		if (!maxdist2cast) maxdist2cast = 100.0f;
		if (!maxhp2cast) maxhp2cast = 100;

		if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
        {
			std::vector<Unit*> TargetTable;		/* From M4ksiu - Big THX to Capt who helped me with std stuff to make it simple and fully working <3 */
												/* If anyone wants to use this function, then leave this note!										 */
			InrangeLoopExitAutoCallback AutoLock;
			for(InRangeSetRecProt::iterator itr = _unit->GetInRangeSetBegin( AutoLock ); itr != _unit->GetInRangeSetEnd(); ++itr) 
			{ 
				if (((spells[i].targettype == TARGET_RANDOM_FRIEND && isFriendly(_unit, (*itr))) || (spells[i].targettype != TARGET_RANDOM_FRIEND && isHostile(_unit, (*itr)) && (*itr) != _unit)) && ((*itr)->GetTypeId()== TYPEID_UNIT || (*itr)->GetTypeId() == TYPEID_PLAYER) && (*itr)->GetInstanceID() == _unit->GetInstanceID()) // isAttackable(_unit, (*itr)) && 
				{
					Unit* RandomTarget = NULL;
					RandomTarget = (Unit*)(*itr);

					if (RandomTarget->isAlive() && _unit->GetDistance2dSq(RandomTarget) >= mindist2cast*mindist2cast && _unit->GetDistance2dSq(RandomTarget) <= maxdist2cast*maxdist2cast && ((RandomTarget->GetHealthPct() >= minhp2cast && RandomTarget->GetHealthPct() <= maxhp2cast && spells[i].targettype == TARGET_RANDOM_FRIEND) || (_unit->GetAIInterface()->getThreatByPtr(RandomTarget) > 0 && isHostile(_unit, RandomTarget))))
					{
						TargetTable.push_back(RandomTarget);
					} 
				} 
			}

			if (_unit->GetHealthPct() >= minhp2cast && _unit->GetHealthPct() <= maxhp2cast && spells[i].targettype == TARGET_RANDOM_FRIEND)
				TargetTable.push_back(_unit);

			if (!TargetTable.size())
				return;

			size_t RandTarget = rand()%TargetTable.size();

			Unit * RTarget = TargetTable[RandTarget];

			if (!RTarget)
				return;

			switch (spells[i].targettype)
			{
			case TARGET_RANDOM_FRIEND:
			case TARGET_RANDOM_SINGLE:
				_unit->CastSpell(RTarget, spells[i].info, spells[i].instant); break;
			case TARGET_RANDOM_DESTINATION:
				_unit->CastSpellAoF(RTarget,RTarget->GetPositionX(), RTarget->GetPositionY(), RTarget->GetPositionZ(), spells[i].info, spells[i].instant); break;
			}

			TargetTable.clear();
		}
	}
コード例 #17
0
bool AIInterface::IsValidUnitTarget( Object *pObject, uint32 pFilter, float pMinRange, float pMaxRange )
{
	// Make sure its a valid unit
	if (!pObject->IsUnit() )
		return false;

	Unit *UnitTarget = TO_UNIT( pObject );
	if ( UnitTarget->GetInstanceID() != m_Unit->GetInstanceID() )
		return false;

//	if ( !m_is_in_instance ) // skip instance check for spell casting
	if ( m_outOfCombatRange )
		if ( UnitTarget->GetDistanceSq( GetReturnPos() ) > m_outOfCombatRange )
			return false;
	float dist = m_Unit->CalcDistance( UnitTarget );
	if ( UnitTarget != m_nextTarget )
		if ( dist > _CalcAggroRange( UnitTarget ) )
			return false;

	if ( pFilter & TargetFilter_Corpse )
	{	//Skip dead ( if required ), feign death or invisible targets
		if ( UnitTarget->isAlive() || !UnitTarget->IsCreature() || TO_CREATURE( UnitTarget )->creature_info->Rank == ELITE_WORLDBOSS )
			return false;
	}
	else if ( !UnitTarget->isAlive() )
		return false;

	if ( UnitTarget->IsPlayer() && TO_PLAYER( UnitTarget )->m_isGmInvisible )
		return false;
	if ( UnitTarget->HasFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_FEIGN_DEATH ) )
		return false;

	//Check if we apply target filtering
	if ( pFilter != TargetFilter_None )
	{
		//Skip units not on threat list
		if ( ( pFilter & TargetFilter_Aggroed ) && getThreatByPtr( UnitTarget ) == 0 )
			return false;

		//Skip current attacking target if requested
		if ( ( pFilter & TargetFilter_NotCurrent ) && UnitTarget == GetNextTarget() )
			return false;

		//Keep only wounded targets if requested
		if ( ( pFilter & TargetFilter_Wounded ) && UnitTarget->GetHealthPct() >= 99 )
			return false;

		//Skip targets not in melee range if requested
		if ( ( pFilter & TargetFilter_InMeleeRange ) && dist > _CalcCombatRange( UnitTarget, false ) )
			return false;

		//Skip targets not in strict range if requested
		if ( ( pFilter & TargetFilter_InRangeOnly ) && ( pMinRange > 0 || pMaxRange > 0 ) )
		{
			if ( pMinRange > 0 && dist < pMinRange )
				return false;
			if ( pMaxRange > 0 && dist > pMaxRange )
				return false;
		}

		//Skip targets not in Line Of Sight if requested
		if ( ( ~pFilter & TargetFilter_IgnoreLineOfSight ) && !m_Unit->IsInLineOfSight( UnitTarget ) )
			return false;

		//Handle hostile/friendly
		if ( ( ~pFilter & TargetFilter_Corpse ) && ( pFilter & TargetFilter_Friendly ) ) 
		{
			if ( !UnitTarget->CombatStatus.IsInCombat() )
				return false; //Skip not-in-combat targets if friendly
			if ( isHostile( m_Unit, UnitTarget ) || getThreatByPtr( UnitTarget ) > 0 )
				return false;
		}
	}

	return true; //This is a valid unit target
}
コード例 #18
0
/// Where we check if we object A can attack object B. This is used in many feature's
/// Including the spell class and the player class.
bool isAttackable(Object* objA, Object* objB, bool CheckStealth)// A can attack B?
{
	if(!objA || !objB )
		return false;

	if ( !objA->IsInWorld() || !objB->IsInWorld() )  // pending or ...?
		return false;

	if(objA == objB)
		return false;   // can't attack self.. this causes problems with buffs if we don't have it :p

	if( !(objA->m_phase & objB->m_phase) ) //What you can't see, you can't attack either...
		return false;

	if(objA->GetTypeId() == TYPEID_CORPSE)
		return false;

	if(objB->GetTypeId() == TYPEID_CORPSE)
		return false;

	// Players in feign death flags can't be attacked (where did you get this information from?)
	// Changed by Supa: Creatures cannot attack players with feign death flags.
	/*if(!objA->IsPlayer())
		if(objA->HasFlag(UNIT_FIELD_FLAGS_2, 0x00000001))
			return false;
	if(!objB->IsPlayer())
		if(objB->HasFlag(UNIT_FIELD_FLAGS_2, 0x00000001))
			return false;*/

	// Checks for untouchable, unattackable
	if(objA->IsUnit() && objA->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNTED_TAXI | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DEAD))
		return false;
	if(objB->IsUnit())
	{
		if(objB->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNTED_TAXI | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DEAD))
			return false;

		/// added by Zack : 
        /// we cannot attack shealthed units. Maybe checked in other places too ?
		/// !! warning, this presumes that objA is attacking ObjB
        /// Capt: Added the possibility to disregard this (regarding the spell class)
		if(static_cast<Unit *>(objB)->IsStealth() && CheckStealth)
			return false;
	}

	int ret = isBgEnemy(objA, objB);
	if (ret != -1) return ret == 1;

	if(objA->IsPlayer() && objB->IsPlayer())
	{
		if(
			static_cast< Player* >( objA )->DuelingWith == static_cast< Player* >(objB) && 
			static_cast< Player* >( objA )->GetDuelState() == DUEL_STATE_STARTED
			)
		return true;

		//players in same group should not attack each other. Required for arenas with mixed groups
		if( static_cast< Player* >( objA )->GetGroup() && static_cast< Player* >( objA )->GetGroup() == static_cast< Player* >( objB )->GetGroup() )
			return false;

		if(objA->HasFlag(PLAYER_FLAGS,PLAYER_FLAG_FREE_FOR_ALL_PVP) && objB->HasFlag(PLAYER_FLAGS,PLAYER_FLAG_FREE_FOR_ALL_PVP))
		{
			if(static_cast< Player* >( objA )->m_bg != NULL && static_cast< Player* >( objB )->m_bg != NULL)
				if(static_cast< Player* >( objA )->m_bgTeam == static_cast< Player* >( objB )->m_bgTeam)
					return false;

			if( static_cast< Player* >( objA )->m_bg != NULL )
				if( static_cast< Player* >( objA )->GetGroup() == static_cast< Player* >( objB )->GetGroup() )
					return false;

			return true;		// can hurt each other in FFA pvp
		}
	}
	
	// handle for pets in duel
	if(objA->IsPet())
	{
		if(objB->IsPlayer())
		{
			if(
				static_cast<Pet *>(objA)->GetPetOwner() )
			{
				if(	static_cast<Pet *>(objA)->GetPetOwner()->DuelingWith == static_cast< Player* >(objB) && 
					static_cast<Pet *>(objA)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED )
					return true;
				if(	static_cast<Pet *>(objA)->GetPetOwner()->m_bg &&
					static_cast<Pet *>(objA)->GetPetOwner()->m_bgTeam != static_cast< Player* >(objB)->m_bgTeam	)
					return true;
				//players in same group should not attack each other. Required for arenas with mixed groups
				if( static_cast<Player *>(objB)->GetGroup() && 
					static_cast<Pet *>(objA)->GetGroup() == static_cast< Player* >( objB )->GetGroup() )
					return false;
			}
		}
		else if(objB->IsPet())
		{
			if(static_cast<Pet *>(objA)->GetPetOwner() && static_cast<Pet *>(objB)->GetPetOwner())
			{
				if(	static_cast<Pet *>(objA)->GetPetOwner()->DuelingWith == static_cast<Pet *>(objB)->GetPetOwner() && 
				static_cast<Pet *>(objA)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED
				)
					return true;
				if(	static_cast<Pet *>(objA)->GetPetOwner()->m_bg &&
					static_cast<Pet *>(objA)->GetPetOwner()->m_bgTeam != static_cast<Pet *>(objB)->GetPetOwner()->m_bgTeam )
					return true;
				//players in same group should not attack each other. Required for arenas with mixed groups
				if( static_cast<Pet *>(objA)->GetGroup() && 
					static_cast<Pet *>(objA)->GetGroup() == static_cast<Pet *>(objB)->GetGroup() )
					return false;
			}
		}
	}
	if(objB->IsPet())
	{
		if(objA->IsPlayer())
		{
			if( static_cast<Pet*>(objB)->GetPetOwner() )
			{
				if(	static_cast<Pet *>(objB)->GetPetOwner()->DuelingWith == static_cast< Player* >(objA) && 
					static_cast<Pet *>(objB)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED )
				return true;
				//players in same group should not attack each other. Required for arenas with mixed groups
				if( static_cast<Player *>(objA)->GetGroup() && 
					static_cast<Pet *>(objB)->GetGroup() == static_cast< Player* >( objA )->GetGroup() )
					return false;
			}
		}
		//we already made this check a few lines before : if A -> B
/*		else if(objA->IsPet())
		{
			if(static_cast<Pet*>(objA)->GetPetOwner() && static_cast<Pet *>(objB)->GetPetOwner() &&
				static_cast<Pet*>(objB)->GetPetOwner() &&
				static_cast<Pet *>(objB)->GetPetOwner()->DuelingWith == static_cast<Pet *>(objA)->GetPetOwner() && 
				static_cast<Pet *>(objB)->GetPetOwner()->GetDuelState() == DUEL_STATE_STARTED
				)
				return true;
		}*/
	}

	// handle for totems
	if( objA->IsCreature() && static_cast<Creature *>(objA)->IsTotem() ) 
	{
		if(objB->IsPlayer())
		{
			if( static_cast<Creature *>(objA)->GetTotemOwner() &&
				static_cast<Creature *>(objA)->GetTotemOwner()->DuelingWith == static_cast< Player* >(objB) && 
				static_cast<Creature *>(objA)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
				)
				return true;
			if( static_cast<Creature *>(objA)->GetTotemOwner()->m_bg &&
				static_cast<Creature *>(objA)->GetTotemOwner()->m_bgTeam != static_cast< Player* >(objB)->m_bgTeam )
				return true;
			//players in same group should not attack each other. Required for arenas with mixed groups
			if( static_cast<Player *>(objB)->GetGroup() && 
				static_cast<Creature *>(objA)->GetGroup() == static_cast< Player* >( objB )->GetGroup() )
				return false;
		}
		if( static_cast<Creature *>(objA)->GetTotemOwner() )
		{
			if( objB->IsPet() )
			{
				if(	static_cast<Creature *>(objA)->GetTotemOwner()->DuelingWith == static_cast<Pet *>(objB)->GetPetOwner() && 
					static_cast<Creature *>(objA)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
					)
					return true;
				//players in same group should not attack each other. Required for arenas with mixed groups
				if( static_cast<Pet *>(objB)->GetGroup() && 
					static_cast<Creature *>(objA)->GetGroup() == static_cast<Pet *>(objB)->GetGroup() )
					return false;
			}
			else if( objB->IsCreature() && static_cast<Creature *>(objB)->IsTotem() )
			{
				if(	static_cast<Creature *>(objA)->GetTotemOwner()->DuelingWith == static_cast<Creature *>(objB)->GetTotemOwner() && 
					static_cast<Creature *>(objA)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
					)
					return true;
				//players in same group should not attack each other. Required for arenas with mixed groups
				if( static_cast<Creature *>(objA)->GetGroup() && 
					static_cast<Creature *>(objA)->GetGroup() == static_cast<Creature *>(objB)->GetGroup() )
					return false;
			}
		}
		
	}
	if( objB->IsCreature() && static_cast<Creature *>(objB)->IsTotem() ) // must be creature
	{
		if(objA->IsPlayer() && static_cast<Creature *>(objB)->GetTotemOwner())
		{
			if( static_cast<Creature *>(objB)->GetTotemOwner()->DuelingWith == static_cast< Player* >(objA) && 
				static_cast<Creature *>(objB)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED )
				return true;
			//players in same group should not attack each other. Required for arenas with mixed groups
			if( static_cast<Player *>(objA)->GetGroup() && 
				static_cast<Creature *>(objB)->GetGroup() == static_cast< Player* >( objA )->GetGroup() )
				return false;
		}
		if(objA->IsPet() && static_cast<Creature *>(objB)->GetTotemOwner() )
		{
			if( static_cast<Creature *>(objB)->GetTotemOwner()->DuelingWith == static_cast<Pet *>(objA)->GetPetOwner() && 
			static_cast<Creature *>(objB)->GetTotemOwner()->GetDuelState() == DUEL_STATE_STARTED
			)
				return true;
			//players in same group should not attack each other. Required for arenas with mixed groups
			if( static_cast<Creature *>(objB)->GetGroup() && 
				static_cast<Creature *>(objB)->GetGroup() == static_cast< Pet* >( objA )->GetGroup() )
				return false;
		}
	}

	// do not let people attack each other in sanctuary
	// Dueling is already catered for
	AreaTable *atA = NULL;
	AreaTable *atB = NULL;

	// cebernic: don't forget totem

	if ( objA->IsCreature() )
	{
		if( static_cast<Creature *>(objA)->IsTotem() && static_cast< Creature* >( objA )->GetTotemOwner() )
			atA = dbcArea.LookupEntry( static_cast< Creature* >( objA )->GetTotemOwner()->GetAreaID() );
		else
		if( objA->IsPet() && static_cast< Pet* >( objA )->GetPetOwner() )
			atA = dbcArea.LookupEntry( static_cast< Pet* >( objA )->GetPetOwner()->GetAreaID() );
	}
	
	if ( objB->IsCreature() )
	{
		if( static_cast<Creature *>(objB)->IsTotem() && static_cast< Creature* >( objB )->GetTotemOwner() )
			atB = dbcArea.LookupEntry( static_cast< Creature* >( objB )->GetTotemOwner()->GetAreaID() );
		else if( objB->IsPet() && static_cast< Pet* >( objB )->GetPetOwner() )
			atB = dbcArea.LookupEntry( static_cast< Pet* >( objB )->GetPetOwner()->GetAreaID() );
/*		if ( atB== NULL ) {
			Unit *_creator = objB->GetMapMgr()->GetUnit( objB->GetUInt64Value( UNIT_FIELD_CREATEDBY ) );
			if( _creator!= NULL && _creator->IsCreature() && _creator->GetMapMgr() ){
//				printf("%s\n",__ansi(static_cast< Creature* >( _creator )->GetCreatureInfo()->Name ));
				atB = dbcArea.LookupEntry( _creator->GetMapMgr()->GetAreaID(_creator->GetPositionX(),_creator->GetPositionY())  );	
			}*/
//		}
	}			
		
	if( objA->IsPlayer() )
		atA = dbcArea.LookupEntry( static_cast< Player* >( objA )->GetAreaID() );

	if( objB->IsPlayer() )
		atB = dbcArea.LookupEntry( static_cast< Player* >( objB )->GetAreaID() );

	// We have the area codes
	// We know they aren't dueling
	if( ( atA && atA->AreaFlags & 0x800) || (atB && atB->AreaFlags & 0x800) ) // cebernic: fix older logic error
		return false;

	if(objA->m_faction == objB->m_faction)  // same faction can't kill each other unless in ffa pvp/duel
		return false;

	bool attackable = isHostile(objA, objB); // B is attackable if its hostile for A
	/*if((objA->m_faction->HostileMask & 8) && (objB->m_factionDBC->RepListId != 0) && 
		(objB->GetTypeId() != TYPEID_PLAYER) && objB->m_faction->Faction != 31) // B is attackable if its a neutral Creature*/

	// Neutral Creature Check
	if(objA->IsPlayer() || objA->IsPet())
	{
		if(objB->m_factionDBC->RepListId == -1 && objB->m_faction->HostileMask == 0 && objB->m_faction->FriendlyMask == 0)
		{
			attackable = true;
		}
	}
	else if(objB->IsPlayer() || objB->IsPet())
	{
		if(objA->m_factionDBC->RepListId == -1 && objA->m_faction->HostileMask == 0 && objA->m_faction->FriendlyMask == 0)
		{
			attackable = true;
		}
	}

	return attackable;
}