/* 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; }
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); }
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(); }
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); }
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 }
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); } }
bool Monster::isHostile() const { if (hasController()) { auto controller = getController()->getMonster(); if (controller != nullptr) { return controller->isHostile(); } return false; } return _type->isHostile; }
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; }
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; }
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); }
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; }
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); }
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); }
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; }
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 };
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(); } }
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 }
/// 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; }