void SummonCreature() { uint32 random = rand()%2; float X = SpawnLocations[random].x; float Y = SpawnLocations[random].y; // max of 6 sorcerers can be summoned if ((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7)) { Creature* Sorcerer = me->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0); if (Sorcerer) { CAST_AI(mob_ashtongue_sorcerer::mob_ashtongue_sorcererAI, Sorcerer->AI())->ShadeGUID = me->GetGUID(); Sorcerer->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); Sorcerer->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); Sorcerer->SetTarget(me->GetGUID()); Sorcerers.push_back(Sorcerer->GetGUID()); --DeathCount; ++SorcererCount; } } else { for (uint8 i = 0; i < 3; ++i) { Creature* Spawn = me->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); if (Spawn) { Spawn->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z); Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); Spawn->AI()->AttackStart(target); } } } }
void HomeMovementGenerator<Creature>::Initialize(Creature & owner) { float x, y, z; owner.GetHomePosition(x, y, z, ori); owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); owner.AddUnitState(UNIT_STAT_EVADE); _setTargetLocation(owner); }
void CreatureGroup::LeaderMoveTo(float x, float y, float z) { if (!m_leader) return; float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x); for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { Creature* member = itr->first; if (member == m_leader || !member->isAlive() || member->getVictim()) continue; float angle = itr->second->follow_angle; float dist = itr->second->follow_dist; float dx = x + cos(angle + pathangle) * dist; float dy = y + sin(angle + pathangle) * dist; float dz = z; Trinity::NormalizeMapCoord(dx); Trinity::NormalizeMapCoord(dy); member->UpdateGroundPositionZ(dx, dy, dz); if (member->IsWithinDist(m_leader, dist + MAX_DESYNC)) member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags()); else member->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); member->GetMotionMaster()->MovePoint(0, dx, dy, dz); member->SetHomePosition(dx, dy, dz, pathangle); } }
void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) { uint32 random = rand()%4; float SpawnLoc[3]; float AttackLoc[3]; for(uint8 i = 0; i < 3; ++i) { SpawnLoc[i] = Base[random][i]; AttackLoc[i] = AttackArea[Faction][i]; } Creature* pCreature = m_creature->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); if(pCreature) { EnemyCount++; // Increment Enemy Count to be used in World States pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); pCreature->GetMotionMaster()->MovePoint(0, AttackLoc[0],AttackLoc[1],AttackLoc[2]); pCreature->AddThreat(m_creature, 1.0f); DoZoneInCombat(pCreature); // Check if creature is a boss. if(pCreature->GetCreatureInfo()->rank == 3) { if(!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); else BossGUID[1] = pCreature->GetGUID(); CheckBossTimer = 5000; } } }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (ShadowboltTimer <= diff) { Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) me->CastSpell( pTarget, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); ShadowboltTimer = 10000; } else ShadowboltTimer -= diff; if (!Skeletons) { if ((SummonSkeletonsTimer <= diff)) { Creature* Skeleton; DoScriptText(SAY_SKELETONS, me); for (uint8 i = 0; i < 5; ++i) { Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1], SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); if (Skeleton) { Skeleton->RemoveUnitMovementFlag( MOVEMENTFLAG_WALKING); Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); Skeleton->AddThreat(me->getVictim(), 0.0f); DoZoneInCombat(Skeleton); } } Skeletons = true; } else SummonSkeletonsTimer -= diff; } if (FrostTombTimer <= diff) { if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) if (pTarget->isAlive()) { //DoCast(pTarget, SPELL_FROST_TOMB_SUMMON, true); if (Creature *pChains = me->SummonCreature(CREATURE_FROSTTOMB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) { CAST_AI(mob_frost_tomb::mob_frost_tombAI, pChains->AI())->SetPrisoner( pTarget); pChains->CastSpell(pTarget, SPELL_FROST_TOMB, true); DoScriptText(SAY_FROST_TOMB, me); } } FrostTombTimer = 15000; } else FrostTombTimer -= diff; DoMeleeAttackIfReady(); }
void WaypointMovementGenerator<Creature>::InitTraveller(Creature &unit, const WaypointData &node) { node.run ? unit.RemoveUnitMovementFlag(MOVEFLAG_WALK_MODE): unit.AddUnitMovementFlag(MOVEFLAG_WALK_MODE); unit.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); unit.SetUInt32Value(UNIT_FIELD_BYTES_1, 0); unit.addUnitState(UNIT_STAT_ROAMING); }
void SummonCreature() { uint32 random = rand()%2; float X = SpawnLocations[random].x; float Y = SpawnLocations[random].y; // max of 6 sorcerers can be summoned if ((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7)) { Creature* Sorcerer = me->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0); if (Sorcerer) { CAST_AI(mob_ashtongue_sorcererAI, Sorcerer->AI())->ShadeGUID = me->GetGUID(); Sorcerer->RemoveUnitMovementFlag(MOVEFLAG_WALK_MODE); Sorcerer->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); Sorcerer->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); Sorcerers.push_back(Sorcerer->GetGUID()); --DeathCount; ++SorcererCount; } } //else //{ for (uint8 pos = 0; pos < 2; ++pos) { X = SpawnLocations[pos].x; Y = SpawnLocations[pos].y; for (uint8 i = 0; i < 3; ++i) { Creature* Spawn = me->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); if (Spawn) { Spawn->RemoveUnitMovementFlag(MOVEFLAG_WALK_MODE); Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z); Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); Spawn->AI()->AttackStart(pTarget); DoZoneInCombat(Spawn); } } } //} }
void WaypointMovementGenerator<Creature>::InitTraveller(Creature &unit, const WaypointData &node) { node.run ? unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING): unit.AddUnitMovementFlag(MOVEMENTFLAG_WALKING); unit.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); unit.SetUInt32Value(UNIT_FIELD_BYTES_1, 0); // TODO: make this part of waypoint node, so that creature can walk when desired? if (unit.canFly()) unit.SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02); unit.AddUnitState(UNIT_STAT_ROAMING); }
bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 diff) { if (creature.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) { i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer creature.ClearUnitState(UNIT_STAT_ROAMING); return true; } i_nextMoveTime.Update(diff); if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) creature.ClearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_MOVE); if (!i_destinationHolder.HasArrived() && creature.IsStopped()) creature.AddUnitState(UNIT_STAT_ROAMING); CreatureTraveller traveller(creature); if (i_destinationHolder.UpdateTraveller(traveller, diff, true)) { if (i_nextMoveTime.Passed()) { if (irand(0, RUNNING_CHANCE_RANDOMMV) > 0) creature.AddUnitMovementFlag(MOVEMENTFLAG_WALKING); _setRandomLocation(creature); } else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f)) { creature.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); _setRandomLocation(creature); } } return true; }
void HomeMovementGenerator<Creature>::Initialize(Creature & owner) { owner.RemoveUnitMovementFlag(MOVEFLAG_WALK_MODE); _setTargetLocation(owner); }
void UpdateAI(const uint32 diff) { if (!me->isInCombat()) return; if (IsBanished) { // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check if (me->getThreatManager().getThreatList().size() < 2) { EnterEvadeMode(); return; } if (DefenderTimer <= diff) { uint32 ran = rand()%2; Creature* Defender = me->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); if (Defender) { Defender->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); bool move = true; if (AkamaGUID) { if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) { float x, y, z; Akama->GetPosition(x, y, z); // They move towards AKama Defender->GetMotionMaster()->MovePoint(0, x, y, z); Defender->AI()->AttackStart(Akama); } else move = false; } else move = false; if (!move) Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z); } DefenderTimer = 15000; } else DefenderTimer -= diff; if (SummonTimer <= diff) { SummonCreature(); SummonTimer = 35000; } else SummonTimer -= diff; if (DeathCount >= 6) { if (AkamaGUID) { Creature* Akama = Unit::GetCreature((*me), AkamaGUID); if (Akama && Akama->isAlive()) { IsBanished = false; me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MoveChase(Akama); Akama->GetMotionMaster()->Clear(); // Shade should move to Akama, not the other way around Akama->GetMotionMaster()->MoveIdle(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // Crazy amount of threat me->AddThreat(Akama, 10000000.0f); Akama->AddThreat(me, 10000000.0f); me->Attack(Akama, true); Akama->Attack(me, true); } } } } else // No longer banished, let's fight Akama now { if (ReduceHealthTimer <= diff) { if (AkamaGUID) { Creature* Akama = Unit::GetCreature((*me), AkamaGUID); if (Akama && Akama->isAlive()) { //10 % less health every few seconds. me->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); ReduceHealthTimer = 12000; } } } else ReduceHealthTimer -= diff; if (HasKilledAkama) { if (!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug { HasKilledAkamaAndReseting = true; me->RemoveAllAuras(); me->DeleteThreatList(); me->CombatStop(); //me->SetFullHealth(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->GetMotionMaster()->MoveTargetedHome(); } if (ResetTimer <= diff) { EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama return; } else ResetTimer -= diff; } DoMeleeAttackIfReady(); } }
void HomeMovementGenerator<Creature>::Initialize(Creature & owner) { owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); owner.AddUnitState(UNIT_STATE_EVADE); _setTargetLocation(owner); }
void CreatureGroup::LeaderMoveTo(float x, float y, float z, bool run) { //! To do: This should probably get its own movement generator or use WaypointMovementGenerator. //! If the leader's path is known, member's path can be plotted as well using formation offsets. if (!m_leader) return; uint8 groupAI = sFormationMgr->CreatureGroupMap[m_leader->GetDBTableGUIDLow()]->groupAI; if (groupAI == 5) return; float pathDist = m_leader->GetExactDist(x, y, z); float pathAngle = m_leader->GetAngle(x, y); for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { Creature* member = itr->first; if (member == m_leader || !member->IsAlive() || member->GetVictim()) continue; // Xinef: If member is stunned / rooted etc don't allow to move him if (member->HasUnitState(UNIT_STATE_NOT_MOVE)) continue; // Xinef: this should be automatized, if turn angle is greater than PI/2 (90°) we should swap formation angle if (M_PI - fabs(fabs(m_leader->GetOrientation() - pathAngle) - M_PI) > M_PI*0.50f) { // pussywizard: in both cases should be 2*M_PI - follow_angle // pussywizard: also, GetCurrentWaypointID() returns 0..n-1, while point_1 must be > 0, so +1 // pussywizard: db table waypoint_data shouldn't have point id 0 and shouldn't have any gaps for this to work! // if (m_leader->GetCurrentWaypointID()+1 == itr->second->point_1 || m_leader->GetCurrentWaypointID()+1 == itr->second->point_2) itr->second->follow_angle = Position::NormalizeOrientation(itr->second->follow_angle + M_PI); //(2 * M_PI) - itr->second->follow_angle; } float followAngle = itr->second->follow_angle; float followDist = itr->second->follow_dist; float dx = x + cos(followAngle + pathAngle) * followDist; float dy = y + sin(followAngle + pathAngle) * followDist; float dz = z; Trinity::NormalizeMapCoord(dx); Trinity::NormalizeMapCoord(dy); member->UpdateGroundPositionZ(dx, dy, dz); member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags()); // pussywizard: setting the same movementflags is not enough, spline decides whether leader walks/runs, so spline param is now passed as "run" parameter to this function if (run && member->IsWalking()) member->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); else if (!run && !member->IsWalking()) member->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); // xinef: if we move members to position without taking care of sizes, we should compare distance without sizes // xinef: change members speed basing on distance - if too far speed up, if too close slow down UnitMoveType mtype = Movement::SelectSpeedType(member->GetUnitMovementFlags()); member->SetSpeedRate(mtype, m_leader->GetSpeedRate(mtype) * member->GetExactDist(dx, dy, dz) / pathDist); member->GetMotionMaster()->MovePoint(0, dx, dy, dz); member->SetHomePosition(dx, dy, dz, pathAngle); } }
void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) { uint32 random = rand()%4; float SpawnLoc[3]; for (uint8 i = 0; i < 3; ++i) { SpawnLoc[i] = Base[random][i]; } Creature* creature = NULL; switch (entry) { case 17906: //GARGOYLE if (!FirstBossDead && (WaveCount == 1 || WaveCount == 3)) { //summon at tower creature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0]+irand(-20, 20), SpawnPointSpecial[SPAWN_NEAR_TOWER][1]+irand(-20, 20), SpawnPointSpecial[SPAWN_NEAR_TOWER][2]+irand(-10, 10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); if (creature) CAST_AI(hyjal_trashAI, creature->AI())->useFlyPath = true; } else { //summon at gate creature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_GARG_GATE][0]+irand(-10, 10), SpawnPointSpecial[SPAWN_GARG_GATE][1]+irand(-10, 10), SpawnPointSpecial[SPAWN_GARG_GATE][2]+irand(-10, 10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); } break; case 17907: //FROST_WYRM, if (FirstBossDead && WaveCount == 1) //summon at gate creature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_WYRM_GATE][0], SpawnPointSpecial[SPAWN_WYRM_GATE][1], SpawnPointSpecial[SPAWN_WYRM_GATE][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); else { creature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0], SpawnPointSpecial[SPAWN_NEAR_TOWER][1], SpawnPointSpecial[SPAWN_NEAR_TOWER][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); if (creature) CAST_AI(hyjal_trashAI, creature->AI())->useFlyPath = true; } break; case 17908: //GIANT_INFERNAL ++InfernalCount; if (InfernalCount > 7) InfernalCount = 0; creature = me->SummonCreature(entry, InfernalPos[InfernalCount][0], InfernalPos[InfernalCount][1], InfernalPos[InfernalCount][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); break; default: creature = me->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); break; } if (creature) { // Increment Enemy Count to be used in World States and instance script ++EnemyCount; creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); creature->setActive(true); switch (entry) { case NECROMANCER: case ABOMINATION: case GHOUL: case BANSHEE: case CRYPT_FIEND: case GARGOYLE: case FROST_WYRM: case GIANT_INFERNAL: case FEL_STALKER: case RAGE_WINTERCHILL: case ANETHERON: case KAZROGAL: case AZGALOR: CAST_AI(hyjal_trashAI, creature->AI())->IsEvent = true; break; } if (instance) { if (instance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE) creature->SetDisableReputationGain(true);//no repu for solo farming } // Check if Creature is a boss. if (creature->isWorldBoss()) { if (!FirstBossDead) BossGUID[0] = creature->GetGUID(); else BossGUID[1] = creature->GetGUID(); CheckTimer = 5000; } } }