void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature) { float respX, respY, respZ, respO, wander_distance; creature.GetRespawnCoord(respX, respY, respZ, &respO, &wander_distance); const float angle = rand_norm_f() * (M_PI_F*2.0f); const float range = rand_norm_f() * wander_distance; float destX = respX + range * cos(angle); float destY = respY + range * sin(angle); float destZ = creature.GetPositionZ(); creature.UpdateAllowedPositionZ(destX, destY, destZ); creature.addUnitState(UNIT_STAT_ROAMING_MOVE); Movement::MoveSplineInit init(creature); init.MoveTo(destX, destY, destZ, true); init.SetWalk(true); init.Launch(); if (creature.CanFly()) i_nextMoveTime.Reset(0); else i_nextMoveTime.Reset(urand(500, 10000)); }
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature) { const float angle = rand_norm_f() * (M_PI_F*2.0f); const float range = rand_norm_f() * i_radius; float destX,destY,destZ; creature.GetNearPoint(&creature, destX, destY, destZ, creature.GetObjectBoundingRadius(), range, angle); creature.UpdateAllowedPositionZ(destX, destY, destZ); float dx = i_x - destX; float dy = i_y - destY; // TODO: Limitation creatutre travel range. if (sqrt((dx*dx) + (dy*dy)) > i_radius) { destX = i_x; destY = i_y; destZ = i_z; } creature.addUnitState(UNIT_STAT_ROAMING_MOVE); Movement::MoveSplineInit init(creature); init.MoveTo(destX, destY, destZ, true); init.SetWalk(true); init.Launch(); if (creature.CanFly()) i_nextMoveTime.Reset(0); else i_nextMoveTime.Reset(urand(500, 10000)); }
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature) { const float angle = rand_norm_f() * (M_PI_F * 2.0f); const float range = rand_norm_f() * i_radius; const float maxPathRange = range * 1.5f; float destX = i_x + range * cos(angle); float destY = i_y + range * sin(angle); float destZ = i_z + frand(-1, 1) * i_verticalZ; creature.UpdateAllowedPositionZ(destX, destY, destZ); creature.addUnitState(UNIT_STAT_ROAMING_MOVE); Movement::MoveSplineInit init(creature); init.MoveTo(destX, destY, destZ, true, false, maxPathRange); init.SetWalk(true); init.Launch(); if (creature.CanFly()) { i_nextMoveTime.Reset(0); } else { if (roll_chance_i(MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK)) i_nextMoveTime.Reset(50); else i_nextMoveTime.Reset(urand(3000, 10000)); // keep a short wait time } }
void ConfusedMovementGenerator<T>::Initialize(T &unit) { const float wander_distance=11; float x,y,z; x = unit.GetPositionX(); y = unit.GetPositionY(); z = unit.GetPositionZ(); TerrainInfo const* map = unit.GetTerrain(); i_nextMove = 1; bool is_water_ok, is_land_ok; _InitSpecific(unit, is_water_ok, is_land_ok); for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx) { const float wanderX=wander_distance*rand_norm_f() - wander_distance/2; const float wanderY=wander_distance*rand_norm_f() - wander_distance/2; i_waypoints[idx][0] = x + wanderX; i_waypoints[idx][1] = y + wanderY; // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]); MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]); // check LOS if(!unit.IsWithinLOS(i_waypoints[idx][0], i_waypoints[idx][1], z)) { i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; } bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z); // if generated wrong path just ignore if ((is_water && !is_water_ok) || (!is_water && !is_land_ok) || !map->IsNextZcoordOK(i_waypoints[idx][0], i_waypoints[idx][1], z)) // check if not under map { i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; } unit.UpdateAllowedPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z); i_waypoints[idx][2] = z; } unit.StopMoving(); unit.addUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE); }
void SpawnerSummon(Creature* pSummoner) { if (m_uiRitualPhase > 7) { pSummoner->SummonCreature(NPC_PLAGUEMAW_THE_ROTTING, pSummoner->GetPositionX(), pSummoner->GetPositionY(), pSummoner->GetPositionZ(), pSummoner->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); return; } for(int i = 0; i < 4; ++i) { uint32 uiEntry = 0; // ref TARGET_RANDOM_CIRCUMFERENCE_POINT float angle = 2.0f * M_PI_F * rand_norm_f(); float fX, fZ, fY; pSummoner->GetClosePoint(fX, fZ, fY, 0.0f, 2.0f, angle); switch(i) { case 0: case 1: uiEntry = NPC_WITHERED_BATTLE_BOAR; break; case 2: uiEntry = NPC_WITHERED_QUILGUARD; break; case 3: uiEntry = NPC_DEATHS_HEAD_GEOMANCER; break; } pSummoner->SummonCreature(uiEntry, fX, fZ, fY, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); } }
bool ConfusedMovementGenerator<T>::Update(T& unit, const uint32& diff) { // ignore in case other no reaction state if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED)) return true; if (i_nextMoveTime.Passed()) { // currently moving, update location unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); if (unit.movespline->Finalized()) i_nextMoveTime.Reset(urand(800, 1500)); } else { // waiting for next move i_nextMoveTime.Update(diff); if (i_nextMoveTime.Passed()) { // start moving unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); float x = i_x + 10.0f * (rand_norm_f() - 0.5f); float y = i_y + 10.0f * (rand_norm_f() - 0.5f); float z = i_z; unit.UpdateAllowedPositionZ(x, y, z); PathFinder path(&unit); path.setPathLengthLimit(30.0f); path.calculate(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) { i_nextMoveTime.Reset(urand(800, 1000)); return true; } Movement::MoveSplineInit init(unit); init.MovebyPath(path.getPath()); init.SetWalk(true); init.Launch(); } } return true; }
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature) { const float angle = rand_norm_f() * (M_PI_F * 2.0f); const float range = rand_norm_f() * i_radius; float destX = i_x + range * cos(angle); float destY = i_y + range * sin(angle); float destZ = i_z + frand(-1, 1) * i_verticalZ; creature.UpdateAllowedPositionZ(destX, destY, destZ); creature.addUnitState(UNIT_STAT_ROAMING_MOVE); Movement::MoveSplineInit init(creature); init.MoveTo(destX, destY, destZ, true); init.SetWalk(true); init.Launch(); if (creature.CanFly()) i_nextMoveTime.Reset(0); else i_nextMoveTime.Reset(urand(500, 10000)); }
bool ConfusedMovementGenerator<T>::Update(T& unit, const uint32& diff) { // ignore in case other no reaction state if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED)) return true; if (i_nextMoveTime.Passed()) { // currently moving, update location unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); if (unit.movespline->Finalized()) i_nextMoveTime.Reset(urand(800, 1500)); } else { // waiting for next move i_nextMoveTime.Update(diff); if (i_nextMoveTime.Passed()) { // start moving unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); WorldLocation destLoc; unit.GetFirstCollisionPosition(destLoc, 10.0f*(rand_norm_f() - 0.5f), unit.GetOrientation()); PathFinder path(&unit); path.setPathLengthLimit(30.0f); path.calculate(destLoc.coord_x, destLoc.coord_y, (destLoc.coord_z + unit.GetObjectScale())); if (path.getPathType() & PATHFIND_NOPATH) { i_nextMoveTime.Reset(urand(800, 1000)); return true; } Movement::MoveSplineInit init(unit); init.MovebyPath(path.getPath()); init.SetWalk(true); init.Launch(); } } return true; }
bool FleeingMovementGenerator<T>::_setMoveData(T& owner) { float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z); if (i_to_distance_from_caster > 0.0f) { if ((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) || // if we reach lower distance (i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) || // if we can't be close (i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) || // if we reach bigger distance (cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far (i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE)) // if we leave 'quiet zone' { // we are very far or too close, stopping i_to_distance_from_caster = 0.0f; i_nextCheckTime.Reset(urand(500, 1000)); return false; } else { // now we are running, continue i_last_distance_from_caster = cur_dist_xyz; return true; } } float cur_dist; float angle_to_caster; if (Unit* fright = owner.GetMap()->GetUnit(i_frightGuid)) { cur_dist = fright->GetDistance(&owner); if (cur_dist < cur_dist_xyz) { i_caster_x = fright->GetPositionX(); i_caster_y = fright->GetPositionY(); i_caster_z = fright->GetPositionZ(); angle_to_caster = fright->GetAngle(&owner); } else { cur_dist = cur_dist_xyz; angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI_F; } } else { cur_dist = cur_dist_xyz; angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI_F; } // if we too close may use 'path-finding' else just stop i_only_forward = cur_dist >= MIN_QUIET_DISTANCE / 3; //get angle and 'distance from caster' to run float angle; if (i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time { angle = rand_norm_f() * (1.0f - cur_dist / MIN_QUIET_DISTANCE) * M_PI_F / 3 + rand_norm_f() * M_PI_F * 2 / 3; i_to_distance_from_caster = MIN_QUIET_DISTANCE; i_only_forward = true; } else if (cur_dist < MIN_QUIET_DISTANCE) { angle = M_PI_F / 6 + rand_norm_f() * M_PI_F * 2 / 3; i_to_distance_from_caster = cur_dist * 2 / 3 + rand_norm_f() * (MIN_QUIET_DISTANCE - cur_dist * 2 / 3); } else if (cur_dist > MAX_QUIET_DISTANCE) { angle = rand_norm_f() * M_PI_F / 3 + M_PI_F * 2 / 3; i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm_f() * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); } else { angle = rand_norm_f() * M_PI_F; i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm_f() * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); } int8 sign = rand_norm_f() > 0.5f ? 1 : -1; i_cur_angle = sign * angle + angle_to_caster; // current distance i_last_distance_from_caster = cur_dist; return true; }
/// Calculate the new weather bool Weather::ReGenerate() { if (!m_weatherChances) { m_type = WEATHER_TYPE_FINE; m_grade = 0.0f; return false; } /// Weather statistics: ///- 30% - no change ///- 30% - weather gets better (if not fine) or change weather type ///- 30% - weather worsens (if not fine) ///- 10% - radical change (if not fine) uint32 u = urand(0, 99); if (u < 30) return false; // remember old values WeatherType old_type = m_type; float old_grade = m_grade; //78 days between January 1st and March 20nd; 365/4=91 days by season // season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html time_t gtime = sWorld.GetGameTime(); struct tm * ltime = localtime(>ime); uint32 season = ((ltime->tm_yday - 78 + 365)/91)%4; static char const* seasonName[WEATHER_SEASONS] = { "spring", "summer", "fall", "winter" }; DEBUG_FILTER_LOG(LOG_FILTER_WEATHER, "Generating a change in %s weather for zone %u.", seasonName[season], m_zone); if ((u < 60) && (m_grade < 0.33333334f)) // Get fair { m_type = WEATHER_TYPE_FINE; m_grade = 0.0f; } if ((u < 60) && (m_type != WEATHER_TYPE_FINE)) // Get better { m_grade -= 0.33333334f; return true; } if ((u < 90) && (m_type != WEATHER_TYPE_FINE)) // Get worse { m_grade += 0.33333334f; return true; } if (m_type != WEATHER_TYPE_FINE) { /// Radical change: ///- if light -> heavy ///- if medium -> change weather type ///- if heavy -> 50% light, 50% change weather type if (m_grade < 0.33333334f) { m_grade = 0.9999f; // go nuts return true; } else { if (m_grade > 0.6666667f) { // Severe change, but how severe? uint32 rnd = urand(0,99); if (rnd < 50) { m_grade -= 0.6666667f; return true; } } m_type = WEATHER_TYPE_FINE; // clear up m_grade = 0; } } // At this point, only weather that isn't doing anything remains but that have weather data uint32 chance1 = m_weatherChances->data[season].rainChance; uint32 chance2 = chance1+ m_weatherChances->data[season].snowChance; uint32 chance3 = chance2+ m_weatherChances->data[season].stormChance; uint32 rnd = urand(0, 99); if (rnd <= chance1) m_type = WEATHER_TYPE_RAIN; else if (rnd <= chance2) m_type = WEATHER_TYPE_SNOW; else if (rnd <= chance3) m_type = WEATHER_TYPE_STORM; else m_type = WEATHER_TYPE_FINE; /// New weather statistics (if not fine): ///- 85% light ///- 7% medium ///- 7% heavy /// If fine 100% sun (no fog) if (m_type == WEATHER_TYPE_FINE) { m_grade = 0.0f; } else if (u < 90) { m_grade = rand_norm_f() * 0.3333f; } else { // Severe change, but how severe? rnd = urand(0, 99); if (rnd < 50) m_grade = rand_norm_f() * 0.3333f + 0.3334f; else m_grade = rand_norm_f() * 0.3333f + 0.6667f; } // return true only in case weather changes return m_type != old_type || m_grade != old_grade; }
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature) { float respX, respY, respZ, respO, currZ, destX, destY, destZ, wander_distance, travelDistZ; creature.GetRespawnCoord(respX, respY, respZ, &respO, &wander_distance); currZ = creature.GetPositionZ(); TerrainInfo const* map = creature.GetTerrain(); // 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_f() * (M_PI_F*2.0f); const float range = rand_norm_f() * wander_distance; const float distanceX = range * cos(angle); const float distanceY = range * sin(angle); destX = respX + distanceX; destY = respY + distanceY; // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(destX); MaNGOS::NormalizeMapCoord(destY); travelDistZ = distanceX*distanceX + distanceY*distanceY; if (is_air_ok) // 3D system above ground and above water (flying mode) { // Limit height change const float distanceZ = rand_norm_f() * sqrtf(travelDistZ)/2.0f; destZ = respZ + distanceZ; float levelZ = map->GetWaterOrGroundLevel(destX, destY, destZ-2.0f); // Problem here, we must fly above the ground and water, not under. Let's try on next tick if (levelZ >= destZ) return; } //else if (is_water_ok) // 3D system under water and above ground (swimming mode) else // 2D only { destZ = respZ; if(!map->IsNextZcoordOK(destX, destY, destZ, travelDistZ)) return; // let's forget this bad coords where a z cannot be find and retry at next tick creature.UpdateGroundPositionZ(destX, destY, destZ, travelDistZ); } Traveller<Creature> traveller(creature); creature.SetOrientation(creature.GetAngle(destX, destY)); i_destinationHolder.SetDestination(traveller, destX, destY, destZ); creature.addUnitState(UNIT_STAT_ROAMING_MOVE); if (is_air_ok) { i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7); } //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.AddSplineFlag(SPLINEFLAG_WALKMODE); } }
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_f()*(M_PI_F*2.0f); const float range = rand_norm_f()*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) { // Limit height change const float distanceZ = rand_norm_f() * sqrtf(dist)/2.0f; 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_MOVE); if (is_air_ok && !(creature.canWalk() && creature.IsAtGroundLevel(nx, ny, nz))) { i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7); } //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.AddSplineFlag(SPLINEFLAG_WALKMODE); } }
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature) { float respX, respY, respZ, respO, currZ, destX, destY, destZ, wander_distance, travelDistZ; creature.GetRespawnCoord(respX, respY, respZ, &respO, &wander_distance); currZ = creature.GetPositionZ(); TerrainInfo const* map = creature.GetTerrain(); // 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_f() * (M_PI_F*2.0f); const float range = rand_norm_f() * wander_distance; const float distanceX = range * cos(angle); const float distanceY = range * sin(angle); destX = respX + distanceX; destY = respY + distanceY; // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(destX); MaNGOS::NormalizeMapCoord(destY); travelDistZ = distanceX*distanceX + distanceY*distanceY; if (is_air_ok) // 3D system above ground and above water (flying mode) { // Limit height change const float distanceZ = rand_norm_f() * sqrtf(travelDistZ)/2.0f; destZ = respZ + distanceZ; float levelZ = map->GetWaterOrGroundLevel(destX, destY, destZ-2.0f); // Problem here, we must fly above the ground and water, not under. Let's try on next tick if (levelZ >= destZ) return; } //else if (is_water_ok) // 3D system under water and above ground (swimming mode) else // 2D only { // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) travelDistZ = travelDistZ >= 100.0f ? 10.0f : sqrtf(travelDistZ); // 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. destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, false); if (fabs(destZ - respZ) > travelDistZ) // Map check { // Vmap Horizontal or above destZ = map->GetHeight(destX, destY, respZ - 2.0f, true); if (fabs(destZ - respZ) > travelDistZ) { // Vmap Higher destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, true); // let's forget this bad coords where a z cannot be find and retry at next tick if (fabs(destZ - respZ) > travelDistZ) return; } } } Traveller<Creature> traveller(creature); creature.SetOrientation(creature.GetAngle(destX, destY)); i_destinationHolder.SetDestination(traveller, destX, destY, destZ); creature.addUnitState(UNIT_STAT_ROAMING_MOVE); if (is_air_ok) { i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); creature.AddSplineFlag(SPLINEFLAG_FLYING); } //else if (is_water_ok) // Swimming mode to be done with more than this check else { i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime() + urand(500, 10000)); creature.AddSplineFlag(SPLINEFLAG_WALKMODE); } }
bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff) { if(!&unit) return true; // ignore in case other no reaction state if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED)) return true; if (i_nextMoveTime.Passed()) { // currently moving, update location unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); Traveller<T> traveller(unit); if (i_destinationHolder.UpdateTraveller(traveller, diff, false)) { if (!IsActive(unit)) // force stop processing (movement can move out active zone with cleanup movegens list) return true; // not expire now, but already lost if (i_destinationHolder.HasArrived()) { // arrived, stop and wait a bit unit.StopMoving(); i_nextMoveTime.Reset(urand(800, 1500)); } } } else { // waiting for next move i_nextMoveTime.Update(diff); if(i_nextMoveTime.Passed()) { // start moving unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); float x = i_x + 10.0f*(rand_norm_f() - 0.5f); float y = i_y + 10.0f*(rand_norm_f() - 0.5f); float z = i_z; unit.UpdateAllowedPositionZ(x, y, z); Traveller<T> traveller(unit); PathInfo path(&unit, x, y, z); if(!(path.getPathType() & PATHFIND_NORMAL)) { i_nextMoveTime.Reset(urand(800, 1000)); return true; } PointPath pointPath = path.getFullPath(); float speed = traveller.Speed() * 0.001f; // in ms uint32 traveltime = uint32(pointPath.GetTotalLength() / speed); SplineFlags flags = (unit.GetTypeId() == TYPEID_UNIT) ? ((Creature*)&unit)->GetSplineFlags() : SPLINEFLAG_WALKMODE; unit.SendMonsterMoveByPath(pointPath, 1, std::min<uint32>(pointPath.size(), 5), flags, traveltime); PathNode p = pointPath[std::min<uint32>(pointPath.size()-1, 4)]; // we do not really need it with mmaps active unit.UpdateAllowedPositionZ(p.x, p.y, p.z); i_destinationHolder.SetDestination(traveller, p.x, p.y, p.z, false); } } return true; }
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_f()*(M_PI_F*2.0f); const float range = rand_norm_f()*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) { // Limit height change const float distanceZ = rand_norm_f() * sqrtf(dist)/2.0f; 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 { nz = Z; if (!map->IsNextZcoordOK(nx, ny, nz, dist)) return; // let's forget this bad coords where a z cannot be find and retry at next tick creature.UpdateGroundPositionZ(nx, ny, nz, dist); } Traveller<Creature> traveller(creature); creature.SetOrientation(creature.GetAngle(nx, ny)); i_destinationHolder.SetDestination(traveller, nx, ny, nz); creature.addUnitState(UNIT_STAT_ROAMING_MOVE); if (is_air_ok && !(creature.canWalk() && creature.IsAtGroundLevel(nx, ny, nz))) { i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7); } //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.AddSplineFlag(SPLINEFLAG_WALKMODE); } }
void ConfusedMovementGenerator<T>::Initialize(T &unit) { const float wander_distance=11; float x,y,z; unit.GetPosition(x,y,z); //Get the nearest point i_nextMove = urand(1,MAX_CONF_WAYPOINTS); i_nextMoveTime.Reset(1); bool is_water_ok, is_land_ok; _InitSpecific(unit, is_water_ok, is_land_ok); uint32 mapId = unit.GetMapId(); if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); float ox=x; float oy=y; float oz=z; dtPolyRef originPoly; mmap->GetNearestValidPosition(&unit,3,3,5,ox,oy,oz,&originPoly); i_waypoints[0][0] = ox; i_waypoints[0][1] = oy; i_waypoints[0][2] = oz; for (int i = 1; i < MAX_CONF_WAYPOINTS+1;i++) { const float wanderX=wander_distance*rand_norm_f() - wander_distance/2; const float wanderY=wander_distance*rand_norm_f() - wander_distance/2; float toX = ox + wanderX; float toY = oy + wanderY; float toZ = oz; if (mmap->DrawRay(&unit,originPoly,ox,oy,oz,toX,toY,toZ)) { i_waypoints[i][0] = toX; i_waypoints[i][1] = toY; i_waypoints[i][2] = toZ; } else { i_waypoints[i][0] = ox; i_waypoints[i][1] = oy; i_waypoints[i][2] = oz; } } } else { TerrainInfo const* map = unit.GetTerrain(); for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx) { const float wanderX=wander_distance*rand_norm_f() - wander_distance/2; const float wanderY=wander_distance*rand_norm_f() - wander_distance/2; i_waypoints[idx][0] = x + wanderX; i_waypoints[idx][1] = y + wanderY; // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]); MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]); bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z); // if generated wrong path just ignore if ((is_water && !is_water_ok) || (!is_water && !is_land_ok)) { i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; } unit.UpdateAllowedPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z); i_waypoints[idx][2] = z; } } unit.StopMoving(); unit.addUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE); }