void TargetedMovementGenerator<Creature>::Initialize(Creature &owner) { if (owner.HasSearchedAssistance()) owner.AddMonsterMoveFlag(MONSTER_MOVE_WALK); else owner.RemoveMonsterMoveFlag(MONSTER_MOVE_WALK); if (((Creature*)&owner)->canFly()) owner.AddMonsterMoveFlag(MONSTER_MOVE_FLY); _setTargetLocation(owner); }
void RandomMovementGenerator<Creature>::Initialize(Creature &creature) { if (!creature.isAlive()) return; if (creature.canFly()) creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY); else creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK); _setRandomLocation(creature); }
void RandomMovementGenerator<Creature>::Initialize(Creature &creature) { if(!creature.isAlive()) return; if (creature.canFly()) creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY); else if(irand(0,RUNNING_CHANCE_RANDOMMV) > 0) creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK); else creature.RemoveMonsterMoveFlag(MONSTER_MOVE_WALK); // run with 1/RUNNING_CHANCE_RANDOMMV chance _setRandomLocation(creature); }
bool HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff) { CreatureTraveller traveller( owner); i_destinationHolder.UpdateTraveller(traveller, time_diff, false); if (time_diff > i_travel_timer) { owner.AddMonsterMoveFlag(MONSTER_MOVE_WALK); // restore orientation of not moving creature at returning to home if(owner.GetDefaultMovementType()==IDLE_MOTION_TYPE) { if(CreatureData const* data = objmgr.GetCreatureData(owner.GetDBTableGUIDLow())) { owner.SetOrientation(data->orientation); WorldPacket packet; owner.BuildHeartBeatMsg(&packet); owner.SendMessageToSet(&packet, false); } } owner.AI()->JustReachedHome(); return false; } i_travel_timer -= time_diff; return true; }
void UpdateAI(const uint32 diff) { if(Delay<diff) { Delay=0; }else{ Delay-=diff; return; } if (!meteor) { float x,y,z; m_creature->GetPosition(x,y,z); Creature* trigger = m_creature->SummonCreature(NPC_TRIGGER,x+8,y+8,z+25+rand()%10,m_creature->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,1000); if(trigger) { trigger->SetVisibility(VISIBILITY_OFF); trigger->setFaction(m_creature->getFaction()); trigger->AddMonsterMoveFlag(MONSTER_MOVE_LEVITATING); trigger->CastSpell(m_creature,SPELL_METEOR,true); } m_creature->GetMotionMaster()->Clear(); meteor = true; }else if (!CanMove){ if(spawnTimer<diff) { m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, m_creature->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); CanMove = true; /*if (m_creature->getVictim()) m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());*/ if (pInstance) { if (pInstance->GetData(DATA_ANETHERON)) { Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_THRALL)); if (target && target->isAlive()) {m_creature->AddThreat(target,0.0);m_creature->SetActiveObjectState(true);} } } }else spawnTimer -= diff; } if(!CanMove)return; if(!m_creature->SelectHostileTarget() || !m_creature->getVictim() ) return; if(!imol) { DoCast(m_creature,SPELL_IMMOLATION); imol=true; } if(FlameBuffetTimer<diff) { DoCast(m_creature->getVictim(),SPELL_FLAME_BUFFET,true); FlameBuffetTimer = 7000; }else FlameBuffetTimer -= diff; DoMeleeAttackIfReady(); }
void TargetedMovementGenerator<Creature>::Initialize(Creature &owner) { if (owner.isInCombat()) owner.RemoveMonsterMoveFlag(MONSTER_MOVE_WALK); if (((Creature*)&owner)->canFly()) owner.AddMonsterMoveFlag(MONSTER_MOVE_FLY); _setTargetLocation(owner); }
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); if(!i_destinationHolder.HasArrived() && creature.IsStopped()) creature.addUnitState(UNIT_STAT_ROAMING); CreatureTraveller traveller(creature); if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) ) { if(i_nextMoveTime.Passed()) { if (creature.canFly()) creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY); else if(irand(0,RUNNING_CHANCE_RANDOMMV) > 0) creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK); else // run with 1/RUNNING_CHANCE_RANDOMMV chance creature.RemoveMonsterMoveFlag(MONSTER_MOVE_WALK); _setRandomLocation(creature); } else if(creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(),PET_FOLLOW_DIST+2.5f)) { creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK); _setRandomLocation(creature); } } return true; }
void ConfusedMovementGenerator<Creature>::Finalize(Creature &unit) { unit.clearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE); unit.AddMonsterMoveFlag(MONSTER_MOVE_WALK); }
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff) { if(!&creature) return true; // Waypoint movement can be switched on/off // This is quite handy for escort quests and other stuff if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) return true; // prevent a crash at empty waypoint path. if(!i_path || i_path->empty()) return true; // i_path was modified by chat commands for example if(i_path->size() != i_hasDone.size()) i_hasDone.resize(i_path->size()); if(i_currentNode >= i_path->size()) i_currentNode = 0; CreatureTraveller traveller(creature); i_nextMoveTime.Update(diff); i_destinationHolder.UpdateTraveller(traveller, diff, false, true); // creature has been stopped in middle of the waypoint segment if (!i_destinationHolder.HasArrived() && creature.IsStopped()) { if( i_nextMoveTime.Passed()) // Timer has elapsed, meaning this part controlled it { SetStopedByPlayer(false); // Now we re-set destination to same node and start travel creature.addUnitState(UNIT_STAT_ROAMING); if (creature.canFly()) creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY); const WaypointNode &node = i_path->at(i_currentNode); i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z); i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); } else // if( !i_nextMoveTime.Passed()) { // unexpected end of timer && creature stopped && not at end of segment if (!IsStopedByPlayer()) { // Put 30 seconds delay i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER); i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER); SetStopedByPlayer(true); // Mark we did it } } return true; // Abort here this update } if( creature.IsStopped()) { uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1; if (!i_hasDone[idx]) { if (i_path->at(idx).orientation !=100) creature.SetOrientation(i_path->at(idx).orientation); if(WaypointBehavior *behavior = i_path->at(idx).behavior) { if(behavior->emote != 0) creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,behavior->emote); if(behavior->spell != 0) creature.CastSpell(&creature,behavior->spell, false); if(behavior->model1 != 0) creature.SetDisplayId(behavior->model1); if(behavior->textid[0]) { // Not only one text is set if( behavior->textid[1] ) { // Select one from max 5 texts (0 and 1 laready checked) int i = 2; for( ; i < MAX_WAYPOINT_TEXT; ++i ) if( !behavior->textid[i] ) break; creature.Say(behavior->textid[rand() % i], 0, 0); } else creature.Say(behavior->textid[0], 0, 0); } i_hasDone[idx] = true; MovementInform(creature); } // wpBehaviour found } // HasDone == false } // i_creature.IsStopped() if( i_nextMoveTime.Passed() ) // This is at the end of waypoint segment or has been stopped by player { if( creature.IsStopped() ) // If stopped then begin a new move segment { creature.addUnitState(UNIT_STAT_ROAMING); if (creature.canFly()) creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY); const WaypointNode &node = i_path->at(i_currentNode); i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z); i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1; if (i_path->at(idx).orientation !=100) creature.SetOrientation(i_path->at(idx).orientation); if(WaypointBehavior *behavior = i_path->at(idx).behavior ) { i_hasDone[idx] = false; if(behavior->model2 != 0) creature.SetDisplayId(behavior->model2); creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); } } else // If not stopped then stop it and set the reset of TimeTracker to waittime { creature.StopMoving(); SetStopedByPlayer(false); i_nextMoveTime.Reset(i_path->at(i_currentNode).delay); ++i_currentNode; if( i_currentNode >= i_path->size() ) i_currentNode = 0; } } return true; }
void FleeingMovementGenerator<Creature>::Finalize(Creature &owner) { owner.AddMonsterMoveFlag(MONSTER_MOVE_WALK); owner.clearUnitState(UNIT_STAT_FLEEING); }
void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostilTarget() && !m_creature->getVictim()) return; if(StormCount) { Unit* target = Unit::GetUnit(*m_creature, CloudGUID); if(!target || !target->isAlive()) { EnterEvadeMode(); return; } else if(Unit* Cyclone = Unit::GetUnit(*m_creature, CycloneGUID)) Cyclone->CastSpell(target, 25160, true); // keep casting or... if(StormSequenceTimer < diff) { HandleStormSequence(target); }else StormSequenceTimer -= diff; return; } if (Enrage_Timer < diff) { DoYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_ONENRAGE); m_creature->CastSpell(m_creature, SPELL_BERSERK, true); Enrage_Timer = 600000; }else Enrage_Timer -= diff; if (StaticDisruption_Timer < diff) { Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); if(!target) target = m_creature->getVictim(); TargetGUID = target->GetGUID(); m_creature->CastSpell(target, SPELL_STATIC_DISRUPTION, false); m_creature->SetInFront(m_creature->getVictim()); StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s float dist = m_creature->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); if (dist < 5.0f) dist = 5.0f; SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f); }else StaticDisruption_Timer -= diff; if (SDisruptAOEVisual_Timer < diff) { Unit* SDVictim = Unit::GetUnit((*m_creature), TargetGUID); if(SDVictim && SDVictim->isAlive()) SDVictim->CastSpell(SDVictim, SPELL_STATIC_VISUAL, true); SDisruptAOEVisual_Timer = 99999; TargetGUID = 0; }else SDisruptAOEVisual_Timer -= diff; if (GustOfWind_Timer < diff) { Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); if(!target) target = m_creature->getVictim(); DoCast(target, SPELL_GUST_OF_WIND); GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers) } else GustOfWind_Timer -= diff; if (CallLighting_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_CALL_LIGHTNING); CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this } else CallLighting_Timer -= diff; if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000) { SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f); isRaining = true; } if (ElectricalStorm_Timer < diff) { Unit* target = SelectRandomPlayer(50); if(!target) target = m_creature->getVictim(); float x, y, z; target->GetPosition(x, y, z); Creature *Cloud = m_creature->SummonCreature(MOB_TEMP_TRIGGER, x, y, m_creature->GetPositionZ() + 10, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); if(Cloud) { CloudGUID = Cloud->GetGUID(); Cloud->AddMonsterMoveFlag(MONSTER_MOVE_LEVITATING); Cloud->StopMoving(); Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); Cloud->setFaction(35); Cloud->SetMaxHealth(9999999); Cloud->SetHealth(9999999); Cloud->CastSpell(Cloud, 45213, true); // cloud visual m_creature->StopMoving(); Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->CastSpell(Cloud, 43501, false); // siphon soul } Unit *Cyclone = m_creature->SummonCreature(MOB_TEMP_TRIGGER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); if(Cyclone) { Cyclone->CastSpell(Cyclone, 25160, true); // wind visual CycloneGUID = Cyclone->GetGUID(); } ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) StormCount = 1; StormSequenceTimer = 0; } else ElectricalStorm_Timer -= diff; if (SummonEagles_Timer < diff) { DoYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_ONSUMMON); float x, y, z; m_creature->GetPosition(x, y, z); for (uint8 i = 0; i < 6 + rand()%3; i++) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) { x = target->GetPositionX() + 10 - rand()%20; y = target->GetPositionY() + 10 - rand()%20; z = target->GetPositionZ() + 6 + rand()%5 + 10; if(z > 95) z = 95 - rand()%5; } Creature *pCreature = m_creature->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); if (pCreature) { pCreature->AddThreat(m_creature->getVictim(), 1.0f); pCreature->AI()->AttackStart(m_creature->getVictim()); } } SummonEagles_Timer = 999999; } else SummonEagles_Timer -= diff; DoMeleeAttackIfReady(); }
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature) { float X,Y,Z,z,nx,ny,nz,wander_distance,ori,dist; creature.GetRespawnCoord(X, Y, Z, &ori, &wander_distance); z = creature.GetPositionZ(); Map const* map = creature.GetBaseMap(); // For 2D/3D system selection //bool is_land_ok = creature.canWalk(); // not used? //bool is_water_ok = creature.canSwim(); // not used? bool is_air_ok = creature.canFly(); const float angle = rand_norm()*(M_PI*2); const float range = rand_norm()*wander_distance; const float distanceX = range * cos(angle); const float distanceY = range * sin(angle); nx = X + distanceX; ny = Y + distanceY; // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(nx); MaNGOS::NormalizeMapCoord(ny); dist = distanceX*distanceX + distanceY*distanceY; if (is_air_ok) // 3D system above ground and above water (flying mode) { const float distanceZ = rand_norm() * sqrtf(dist)/2;// Limit height change nz = Z + distanceZ; float tz = map->GetHeight(nx, ny, nz-2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height. float wz = map->GetWaterLevel(nx, ny); // Problem here, we must fly above the ground and water, not under. Let's try on next tick if (tz >= nz || wz >= nz) return; } //else if (is_water_ok) // 3D system under water and above ground (swimming mode) else // 2D only { dist = dist >= 100.0f ? 10.0f : sqrtf(dist); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) // The fastest way to get an accurate result 90% of the time. // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. nz = map->GetHeight(nx, ny, Z+dist-2.0f, false); if (fabs(nz-Z) > dist) // Map check { nz = map->GetHeight(nx, ny, Z-2.0f, true); // Vmap Horizontal or above if (fabs(nz-Z) > dist) { // Vmap Higher nz = map->GetHeight(nx, ny, Z+dist-2.0f, true); // let's forget this bad coords where a z cannot be find and retry at next tick if (fabs(nz-Z) > dist) return; } } } Traveller<Creature> traveller(creature); creature.SetOrientation(creature.GetAngle(nx, ny)); i_destinationHolder.SetDestination(traveller, nx, ny, nz); creature.addUnitState(UNIT_STAT_ROAMING); if (is_air_ok) { i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY); } //else if (is_water_ok) // Swimming mode to be done with more than this check else { i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(), 10000+i_destinationHolder.GetTotalTravelTime())); creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK); } }