All pastes #1013607 Raw Copy code Copy link Edit

RandomMovementGenerator patch

public unlisted diff v1 · immutable
#1013607 ·published 2008-05-10 09:27 UTC
rendered paste body
Index: src/game/RandomMovementGenerator.cpp===================================================================--- src/game/RandomMovementGenerator.cpp	(revision 5788)+++ src/game/RandomMovementGenerator.cpp	(working copy)@@ -21,67 +21,134 @@ #include "Opcodes.h" #include "RandomMovementGenerator.h" #include "DestinationHolderImp.h"+#include "VMapFactory.h"+#include "Map.h" -/*-Here interpolation is disabled by default due to it causing crashing-in some compile environments.-If your server can handle the small amount of lag this may cause-and you can build without experiencing a significant increase in crashes-then you may uncomment the following line to have correct random motion.-*/-// uncomment now for wide testing purpose-#define USE_INTERPOLATION+/**+ * Those define the size of the table of the ground/object heights around the spawn point,+ * bigger they are, more time is needed to calculate.+ */+#define ANGLE_PRECISSION 8+#define RANGE_PRECISSION 8  template<> void RandomMovementGenerator<Creature>::Initialize(Creature &creature) {-    float x,y,z,z2, wander_distance;+    float x,y,z,wander_distance;+	float waypoints[(ANGLE_PRECISSION*RANGE_PRECISSION)+1][3];+	int waypoint_count = 1;+     creature.GetRespawnCoord(x, y, z,NULL,&wander_distance);     uint32 mapid=creature.GetMapId(); +	//float go_height[ANGLE_PRECISSION][RANGE_PRECISSION];+     Map const* map = MapManager::Instance().GetBaseMap(mapid);-    // Initialization is done in bulk. Don’t use vamps for that (4. parameter = false). It is too costly when entering a new map grid-    z2 = map->GetHeight(x,y,z, false);                      // use .map base surface height-    if( fabs( z2 - z ) < 5 )-        z = z2; -    i_nextMove = 1;-    i_waypoints[0][0] = x;-    i_waypoints[0][1] = y;-    i_waypoints[0][2] = z;-     bool is_water_ok = creature.isCanSwimOrFly();     bool is_land_ok  = creature.isCanWalkOrFly(); -    for(unsigned int idx=1; idx < MAX_RAND_WAYPOINTS+1; ++idx)-    {-        const float angle = 2*M_PI*rand_norm();-        const float range = wander_distance*rand_norm();+	// We need vmap manager, to make creatures walk properly over the objects+	VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();+	float step = wander_distance/RANGE_PRECISSION; -        i_waypoints[idx][0] = x+ range * cos(angle);-        i_waypoints[idx][1] = y+ range * sin(angle);+	waypoints[0][0] = x;+	waypoints[0][1] = y;+	waypoints[0][2] = z;+	// Build the table of ground/object heights around spawn point+	for(int a = 0; a < ANGLE_PRECISSION; a++)+	{+		float angle = (2*M_PI/ANGLE_PRECISSION) * (float)a;+		// We use the previous Z value as a reference point to find out the map height+		float last_z = z;+		for(int r = 0; r < RANGE_PRECISSION; r++)+		{+			float range = step * ((float) r + 1.0);+			// Calculate the test around the spawn point+			float px = x + range * cos(angle);+			float py = y + range * sin(angle);+			MaNGOS::NormalizeMapCoord(px);+			MaNGOS::NormalizeMapCoord(py);+			float map_height = map->GetHeight(px, py , last_z, true);+			float obj_height; -        // prevent invalid coordinates generation-        MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]);-        MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]);+			// Calculate the object height			+			vmgr->getObjectHitPos(mapid, +				px, py, last_z + 2.0f,+				px, py, ((map_height!=VMAP_INVALID_HEIGHT_VALUE) ? (map_height) : (last_z-2.0f)),+				px, py, obj_height,+				0.0f); -        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] = i_waypoints[idx-1][0];-            i_waypoints[idx][1] = i_waypoints[idx-1][1];-            i_waypoints[idx][2] = i_waypoints[idx-1][2];-            continue;-        }+			float pz = VMAP_INVALID_HEIGHT_VALUE;+			if(obj_height>last_z-2.0f)+			{+				// Z value in the map will be the bigger of the two: map or object+				pz = (((map_height) > (obj_height)) ? (map_height) : (obj_height)); +			} -        // Initialization is done in bulk. Don’t use vamps for that (4. parameter = false).-        // It is too costly when entering a new map grid, use .map base surface height-        z2 = map->GetHeight(i_waypoints[idx][0],i_waypoints[idx][1],z, false);-        if( fabs( z2 - z ) < 5 )-            z = z2;-        i_waypoints[idx][2] =  z;+			if(pz!=VMAP_INVALID_HEIGHT_VALUE)+			{+				bool is_water = map->IsInWater(px,py,pz);	+				// If it is bad place for the creature (water for non water creature, ect), just mark it as invalid.+				if(is_water && !is_water_ok || !is_water && !is_land_ok)+				{				+					pz = VMAP_INVALID_HEIGHT_VALUE;+				}++				// If point is not invalid, add to possible walk points+				if(pz!=VMAP_INVALID_HEIGHT_VALUE)+				{+					last_z = pz;+					waypoints[waypoint_count][0] = px;+					waypoints[waypoint_count][1] = py;+					waypoints[waypoint_count][2] = pz;+					waypoint_count++;+				}+			}+		}+	}	++	// Here, we calculate the walk points+	i_nextMove = 1;+	// First waypoint is always a spawn point, easy here.+    i_waypoints[0][0] = x;+    i_waypoints[0][1] = y;+    i_waypoints[0][2] = z;	    ++    for(unsigned int idx=1; idx < MAX_RAND_WAYPOINTS+1; ++idx)+    {+		bool goodPoint = false;+		int r = urand(0, waypoint_count-1);+		while(!goodPoint)+		{+			float dx = waypoints[r][0];+			float dy = waypoints[r][1];+			float dz = waypoints[r][2];+			// And check LOS+			vmgr->getObjectHitPos(mapid, +				i_waypoints[0][0], i_waypoints[0][1], i_waypoints[0][2] + creature.GetObjectSize()/2.0f,+				dx, dy, dz + creature.GetObjectSize()/2.0f,+				i_waypoints[idx][0], i_waypoints[idx][1], i_waypoints[idx][2],+				creature.GetObjectSize()*2.0);+			i_waypoints[idx][2] = i_waypoints[idx][2]- creature.GetObjectSize()/2.0f;+			float x_dx = i_waypoints[idx][0] - i_waypoints[idx-1][0];+			float x_dy = i_waypoints[idx][1] - i_waypoints[idx-1][1];+			float x_dist = sqrt((x_dx*x_dx) + (x_dy*x_dy));+			float x_dz = i_waypoints[idx][2]-i_waypoints[idx-1][2];+			// Check if creature is not attempting to do >45 deg. walk+			if(abs(x_dz)<=x_dist)+			{+				goodPoint = true;+			} else {+				// If yes, try next point+				r = r + 1;+				if(r==waypoint_count)+				{+					r = 0;+				}+			}+		}     }     i_nextMoveTime.Reset(urand(0, 10000-1));                // TODO: check the lower bound (it is probably too small)     creature.StopMoving();@@ -105,10 +172,8 @@     if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))         return true;     i_nextMoveTime.Update(diff);-    #ifdef USE_INTERPOLATION     CreatureTraveller traveller(creature);     i_destinationHolder.UpdateTraveller(traveller, diff, false);-    #endif     if( i_nextMoveTime.Passed() )     {         if( creature.IsStopped() )@@ -120,9 +185,7 @@             creature.addUnitState(UNIT_STAT_ROAMING);             CreatureTraveller traveller(creature);             i_destinationHolder.SetDestination(traveller, x, y, z);-            #ifndef USE_INTERPOLATION             traveller.Relocation(x,y,z);-            #endif             i_nextMoveTime.Reset( i_destinationHolder.GetTotalTravelTime() );         }         else