View Single Post
  #3  
Old 03-23-2002, 02:58 PM
Malevolent
Hill Giant
 
Join Date: Mar 2002
Posts: 171
Default Code Snippets

According to my tests, stuff moves across the screen. While a bit rough, it gets the job done (for now). This will put together a data structure that allows one to setup a way to move npc types around a zone. Currently, the data is not persistent and only loads the points when the zone is booted. Is there really a good reason to make persistent pathing points? Anyway, here is the code, hope it helps!

database structure:

Code:
CREATE TABLE path_points(
  id int(11) NOT NULL auto_increment,
  npctypeid int(11) NOT NULL default '0',	//from table npc_types, using key (id)
  zone varchar(16) NOT NULL default '',		//short zone name
  x float NOT NULL default '0',
  y float NOT NULL default '0',
  z float NOT NULL default '0',
  MoveRate float NOT NULL default '0',		//float representing how fast the critter needs to move
  step int NOT NULL default '0',		//what step in the linear sequence are we?
  primary key (id)
 );

insert into path_points(npctypeid,zone,x,y,z,MoveRate,step) values ('4057','misty',-200,-200,0,1.00,0);
insert into path_points(npctypeid,zone,x,y,z,MoveRate,step) values ('4057','misty',-100,-100,0,1.00,1);
Changes to zone.h
Code:
///////////////////////
//Malevolent:
//Data structure that contains information about a zone's pathing points
struct PathPoint {
	float x;
	float y;
	float z;
	int step;
	float movement_increment; //float value to increase movement value by
	int NPC_TypeID;	  //maybe make this an array of ints, so more than 1 npc can use a path?
};


Public:

LinkedList<PathPoint*> PathPointsList; //Malevolent: pathing points collection
Changes to zone.cpp
Code:
///////////////////////////////
//Malevolent: PathPoint, load data
bool Database::PopulateZonePathPoint(char* zone_name, LinkedList<PathPoint*> &PathPointsList, int32 repopdelay) {
	//, LinkedList<PathPoint*> &PathPointsList, int32 repopdelay
	
	char errbuf[MYSQL_ERRMSG_SIZE];
	char* query = 0;
	MYSQL_RES *result;
	MYSQL_ROW row;

	MakeAnyLenString(&query, "SELECT x, y, z, zone, npctypeid, MoveRate FROM path_points WHERE zone='%s'", zone_name);

	if (RunQuery(query, strlen(query), errbuf, &result))
	{
		delete[] query;
		while(row = mysql_fetch_row(result))
		{
			PathPoint* pp = new PathPoint;
			
			ZonePoint* zp = new ZonePoint;
			pp->x = atof(row[0]);			//x coordinate to move to
			pp->y = atof(row[1]);			//y coordinate to move to
			pp->z = atof(row[2]);		 //z coordinate currently not used
			pp->movement_increment = atof(row[5]);	//movement incremental value (how far to move the critter)
			pp->NPC_TypeID = atoi(row[4]);	//the *npc_type* to move...todo: make it the spawn id
			
			PathPointsList.Insert(pp);

		}
		mysql_free_result(result);
	}
	else
	{
		cerr << "Error in PopulateZonePathPoints query '" << query << "' " << errbuf << endl;
		delete[] query;
		return false;
	}

	return true;
}

Changes to npc.cpp

Code:
//////////////////////////////
//Malevolent:
//Walk npc to one of the pathpoints setup for it in db
void NPC::PathPointSendTo()
{

	//Build list
	LinkedListIterator<PathPoint*> iterator(zone->PathPointsList);	
	iterator.Reset();

	while(iterator.MoreElements())	
	{

		PathPoint* pp = iterator.GetData();
			
		if (this->GetPathPointStep() == pp->step)	/// are we on the right step? 
		if (this->GetNPCTypeID() == pp->NPC_TypeID)	///make sure that the npc matches
		{

			//todo: find a better way to get there--maybe add a flag to use different pathfinding techniques?

			if (pp->x > this->GetX())
			{			
				this->x_pos=this->GetX()+pp->movement_increment;
			}

			if (pp->y > this->GetY())
			{			
				this->y_pos=this->GetY()+pp->movement_increment;			
			}

			//what's a good way to check for optimal z coordinate?
			this->z_pos=0;
			
			//lastly, check to ensure that we haven't completed out objective
			//and if so, then increase the step value
			if ((pp->x < this->GetX()) && pp->y < this->GetY())
				this->SetPathPointStep(this->GetPathPointStep()+1);

			//Update spawn position. Don't use fale as it kills performance
			SendPosUpdate(true);

			//todo some way to reset the step counter (after respawn or after ticks, or maybe just let it loop, /shrug?)
		
		} //end if 

		iterator.Advance();		
		
	}//end while
	
}
npc.cpp, within ::Process() right before the final return true;

Code:
	//Malevolent
	//Walk through the zone pathing points
	//if the target is not engaged and if the movement timer says its ok
	if(!this->IsEngaged()&&movement_timer->Check())
	{
	this->PathPointSendTo();
		return true;
	}
npc.cpp in npc::npc
Code:
    SetPathPointStep(0); //always start out at step 0 for a new npc
npc.h
Code:
public:
	void PathPointSendTo();
	uint32	GetPathPointStep()		{ return PathPointStep; }
	void    SetPathPointStep(int step_value);
Protected:
	uint32  PathPointStep;

--MV

(formerly known as ScotchTape)
Reply With Quote