void RandomMovementGenerator<Creature>::Initialize(Creature &creature) { // sLog.outDebug(" $$ RandomMovementGenerator::Initialize"); uint16 x, y; creature.GetRespawnCoord(x, y); i_nextMove = 1; i_waypoints[0][0] = x; i_waypoints[0][1] = y; for(uint8 idx=1; idx < MAX_RAND_WAYPOINTS+1; ++idx) { i_waypoints[idx][0] = x + (urand(100, 150) * (urand(0,1) * -1)); i_waypoints[idx][1] = y + (urand(100, 150) * (urand(0,1) * -1)); //i_waypoints[idx][0] = x + ((rand() % 3) - 150); //i_waypoints[idx][1] = y + ((rand() % 3) - 150); } i_nextMoveTime.Reset(urand(5000, 6000-1)); creature.StopMoving(); }
void instance_blackfathom_deeps::DoSpawnMobs(uint8 uiWaveIndex) { Creature* pKelris = GetSingleCreatureFromStorage(NPC_KELRIS); if (!pKelris) return; float fX_resp, fY_resp, fZ_resp; pKelris->GetRespawnCoord(fX_resp, fY_resp, fZ_resp); for (uint8 i = 0; i < countof(aWaveSummonInformation); ++i) { if (aWaveSummonInformation[i].m_uiWaveIndex != uiWaveIndex) continue; // Summon mobs at positions for (uint8 j = 0; j < MAX_COUNT_POS; ++j) { for (uint8 k = 0; k < aWaveSummonInformation[i].m_aCountAndPos[j].m_uiCount; ++k) { uint8 uiPos = aWaveSummonInformation[i].m_aCountAndPos[j].m_uiSummonPosition; float fPosX = aSpawnLocations[uiPos].m_fX; float fPosY = aSpawnLocations[uiPos].m_fY; float fPosZ = aSpawnLocations[uiPos].m_fZ; float fPosO = aSpawnLocations[uiPos].m_fO; // Adapt fPosY slightly in case of higher summon-counts if (aWaveSummonInformation[i].m_aCountAndPos[j].m_uiCount > 1) fPosY = fPosY - INTERACTION_DISTANCE / 2 + k * INTERACTION_DISTANCE / aWaveSummonInformation[i].m_aCountAndPos[j].m_uiCount; if (Creature* pSummoned = pKelris->SummonCreature(aWaveSummonInformation[i].m_uiNpcEntry, fPosX, fPosY, fPosZ, fPosO, TEMPSUMMON_DEAD_DESPAWN, 0)) { pSummoned->GetMotionMaster()->MovePoint(0, fX_resp, fY_resp, fZ_resp); m_lWaveMobsGuids[uiWaveIndex].push_back(pSummoned->GetGUIDLow()); } } } } }
void ObjectGridRespawnMover::Visit(CreatureMapType &m) { // creature in unloading grid can have respawn point in another grid // if it will be unloaded then it will not respawn in original grid until unload/load original grid // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn. for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) { Creature * c = iter->getSource(); ++iter; ASSERT(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); Cell const& cur_cell = c->GetCurrentCell(); float resp_x, resp_y, resp_z; c->GetRespawnCoord(resp_x, resp_y, resp_z); CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); Cell resp_cell(resp_val); if (cur_cell.DiffGrid(resp_cell)) { c->GetMap()->CreatureRespawnRelocation(c); // false result ignored: will be unload with other creatures at grid } } }
void HomeMovementGenerator<Creature>::_setTargetLocation(Creature& owner) { if (owner.hasUnitState(UNIT_STAT_NOT_MOVE)) return; Movement::MoveSplineInit<Unit*> init(owner); float x, y, z, o; // at apply we can select more nice return points base at current movegen if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->CurrentMovementGenerator()->GetResetPosition(owner, x, y, z, o)) owner.GetRespawnCoord(x, y, z, &o); init.SetFacing(o); init.MoveTo(x, y, z, true); init.SetSmooth(); // fix broken fly movement for old creatures //init.SetWalk(false); // hack for old creatures with bugged fly animation bool bSetWalk = (owner.GetTypeId() == TYPEID_UNIT && owner.IsLevitating() && owner.GetFloatValue(UNIT_FIELD_HOVERHEIGHT) == 0.0f); init.SetWalk(bSetWalk); init.Launch(); m_arrived = false; owner.clearUnitState(UNIT_STAT_ALL_DYN_STATES); }
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(); uint32 mapid=creature.GetMapId(); Map const* map = MapManager::Instance().GetBaseMap(mapid); // For 2D/3D system selection bool is_land_ok = creature.canWalk(); bool is_water_ok = creature.canSwim(); 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 Trinity::NormalizeMapCoord(nx); Trinity::NormalizeMapCoord(ny); dist = (nx - X)*(nx - X) + (ny - Y)*(ny - Y); 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); if (tz >= nz || wz >= nz) return; // Problem here, we must fly above the ground and water, not under. Let's try on next tick } //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); // Map check if (fabs(nz-Z)>dist) { nz = map->GetHeight(nx,ny,Z-2.0f,true); // Vmap Horizontal or above if (fabs(nz-Z)>dist) { nz = map->GetHeight(nx,ny,Z+dist-2.0f,true); // Vmap Higher if (fabs(nz-Z)>dist) return; // let's forget this bad coords where a z cannot be find and retry at next tick } } } 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.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2); } //else if (is_water_ok) // Swimming mode to be done with more than this check else { i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(),5000+i_destinationHolder.GetTotalTravelTime())); creature.SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); } }
void instance_draktharon_keep::DoSortNovosDummies() { // Sorting once is good enough if (m_lNovosDummyGuids.empty()) return; Creature* pNovos = GetSingleCreatureFromStorage(NPC_NOVOS); if (!pNovos) return; // First sort the Dummies to the Crystals for (uint8 i = 0; i < MAX_CRYSTALS; ++i) { GameObject* pCrystal = instance->GetGameObject(m_aNovosCrystalInfo[i].m_crystalGuid); if (!pCrystal) continue; for (GuidList::iterator itr = m_lNovosDummyGuids.begin(); itr != m_lNovosDummyGuids.end();) { Creature* pDummy = instance->GetCreature(*itr); if (!pDummy) { m_lNovosDummyGuids.erase(itr++); continue; } // Check if dummy fits to crystal if (pCrystal->IsWithinDistInMap(pDummy, INTERACTION_DISTANCE, false)) { m_aNovosCrystalInfo[i].m_channelGuid = pDummy->GetObjectGuid(); m_lNovosDummyGuids.erase(itr); break; } ++itr; } } // Find the crystal channel target (above Novos) float fNovosX, fNovosY, fNovosZ; pNovos->GetRespawnCoord(fNovosX, fNovosY, fNovosZ); for (GuidList::iterator itr = m_lNovosDummyGuids.begin(); itr != m_lNovosDummyGuids.end();) { Creature* pDummy = instance->GetCreature(*itr); if (!pDummy) { m_lNovosDummyGuids.erase(itr++); continue; } // As the wanted dummy is exactly above Novos, check small range, and only 2d if (pDummy->IsWithinDist2d(fNovosX, fNovosY, 5.0f)) { m_novosChannelGuid = pDummy->GetObjectGuid(); m_lNovosDummyGuids.erase(itr); break; } ++itr; } // Summon positions (at end of stairs) for (GuidList::iterator itr = m_lNovosDummyGuids.begin(); itr != m_lNovosDummyGuids.end();) { Creature* pDummy = instance->GetCreature(*itr); if (!pDummy) { m_lNovosDummyGuids.erase(itr++); continue; } // The wanted dummies are quite above Novos if (pDummy->GetPositionZ() > fNovosZ + 20.0f) { m_vSummonDummyGuids.push_back(pDummy->GetObjectGuid()); m_lNovosDummyGuids.erase(itr++); } else ++itr; } // Clear remaining (unused) dummies m_lNovosDummyGuids.clear(); }
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 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); } }
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 RandomCircleMovementGenerator<Creature>::fillSplineWayPoints(Creature &creature) { m_splineMap.clear(); float spawnX, spawnY, spawnZ, spawnO, spawnDist, x, y, z; creature.GetRespawnCoord(spawnX, spawnY, spawnZ, &spawnO, &spawnDist); creature.GetPosition(x,y,z); //Add first waypoint /* SplineWayPointInfo *firstwp = new SplineWayPointInfo(); firstwp->x = x; firstwp->y = y; firstwp->z = z; m_splineMap.insert(std::make_pair<uint32, SplineWayPointInfo*>(0, firstwp)); */ //calculate other ones float m_fDistance = creature.GetDistance2d(spawnX, spawnY); float m_fLenght = 2*M_PI_F*m_fDistance; float m_fAngle = (M_PI_F - ((2*M_PI_F) / m_fLenght)) / 2; if (m_bClockWise) m_fAngle += ((2*M_PI_F) / m_fLenght) + creature.GetAngle(spawnX, spawnY); else m_fAngle = creature.GetAngle(spawnX, spawnY) - m_fAngle - ((2*M_PI_F) / m_fLenght); //because it cant be lower than 0 or bigger than 2*PI m_fAngle = (m_fAngle >= 0) ? m_fAngle : 2 * M_PI_F + m_fAngle; m_fAngle = (m_fAngle <= 2*M_PI_F) ? m_fAngle : m_fAngle - 2 * M_PI_F; float creature_speed = creature.GetSpeed(MOVE_FLIGHT) / 2; float lastx = x; float lasty = y; for(uint32 wpId = 0; wpId < 30; ++wpId) { bool canIncerase = true; bool canDecerase = true; if (m_fDistance > spawnDist) canIncerase = false; if (m_fDistance < 1) canDecerase = false; uint8 tmp = urand(0,2); // 0 nothing, 1 incerase, 2 decerase if (tmp == 1 && canIncerase) m_fDistance += 0.5f; else if (tmp == 2 && canDecerase) m_fDistance -= 0.5f; m_fLenght = 2*M_PI_F*m_fDistance; float m_fRotateAngle = ((2*M_PI_F) / m_fLenght); // Moving by half of speed every 500ms if (m_bClockWise) m_fAngle -= m_fRotateAngle; else m_fAngle += m_fRotateAngle; //because it cant be lower than 0 or bigger than 2*PI m_fAngle = (m_fAngle >= 0) ? m_fAngle : 2 * M_PI_F + m_fAngle; m_fAngle = (m_fAngle <= 2*M_PI_F) ? m_fAngle : m_fAngle - 2 * M_PI_F; lastx += cos(m_fAngle)*creature_speed; lasty += sin(m_fAngle)*creature_speed; MaNGOS::NormalizeMapCoord(lastx); MaNGOS::NormalizeMapCoord(lasty); Position *wp = new Position(); wp->x = lastx; wp->y = lasty; wp->z = z; wp->o = m_fAngle; m_splineMap.insert(std::make_pair<uint32, Position*>(wpId, wp)); } i_nextMoveTime.Reset(500); }