Page 1 of 1

Re: Zone help

Posted: Wed Feb 25, 2015 11:59 pm
by perrinoia
The code you are modifying is using the word "zone" incorrectly. Those 2 dimensional coordinates are actually spawn points for the drones, and nothing more. In this case, the 3rd coordinate defined later, using getLOSInfo to find the height of the terrain at the 2 dimensional location. Once the bots are spawned, they can go where ever they are programmed to go.

When using 2 dimensional coordinates, I recommend using waypoints, instead of world coordinates.

For instance, WaypointToWorld("512 512") will always be dead center of the command map. WaypointToWorld("0 0") will always be the southwest corner of the command map. Etc...

AI follow a path comprised of 3d world coordinates, but they ignore the z coordinate. If you knock a bot off of the catwalks in botpractice MK III, they'll continue running around their circles back and forth on the ground floor.

This is the command that builds a bot's path:

Code: Select all

AI::DirectiveWaypoint( %aiName, %position, %orderNumber );
The first argument is the name of the bot. It needs to be unique or you'll be instructing multiple bots simultaneously.
The second argument is the position (again, they'll ignore the z coordinate and run to the x and y).
Last is the order number (0-100).

There are 2 path types. linear, (0-100, then 100-0, then 0-100, etc...) or circular (0-100. then 0-100, then 0-100, etc...).

If you continuously assign order number 0, it will move on command rather than predetermined paths.

Bottom line, AI don't care about boundaries... They care about paths.

Re: Zone help

Posted: Thu Feb 26, 2015 10:10 am
by perrinoia
Allow me to rephrase my previous response.

function Zone::GetCenterPos(%zonenum) does not return the center pos of the zone, because the math is all wrong. If you want to get the center point of a zone, you must first define the boundaries, then subtract the smaller numbers from the larger, divide by 2, and add the smaller number back (for each axis)... This function adds them together, then divides by 2, and that's all it does... This may result in a coordinate between the other coordinates, but not if the coordinates are the ones that you are using.

I'm not sure what the fuck function Zone::GetMeanDistance(%zonenum) does, but it has very little to do with the name of the function, as it's math is all wrong, too.

function Zone::SpawnCreature(%zonenum) also has some funky math shit going on... Frankly, I would delete all of this code and start from scratch, if I was you.

Here's some helpful functions I've written, that might be useful to you.

Code: Select all

// Defines the boundaries of a zone, one marker at a time.
function PathMarker::addToZone(%this)
{
	%p = GameBase::getPosition(%this));
	%x = getWord(%p, 0);
	%y = getWord(%p, 1);
	%z = getGroup(%this);
	%z.east = getWord(%z.east @" "@ %x, %z.east < %x);
	%z.north = getWord(%z.north @" "@ %y, %z.north < %y);
	%z.south = getWord(%z.south @" "@ %y, %y < %z.south);
	%z.west = getWord(%z.west @" "@ %x, %x < %z.west);
}

// Feeds all of the markers to the function that defines the zone boundaries.
Group::iterateRecurisve(MissionGroup, GameBase::virtual, "addToZone");
This code will define the boundaries of a zone, by saving the smallest and largest numbers on each axis (x and y only) in a variable array as properties of the marker's group.

Code: Select all

// Returns true (1) if the object is inside the zone, false (0) if not. What you do with that information is up to you.
function Zone::isInside(%this, %object)
{
	%p = GameBase::getPosition(%object);
	%x = getWord(%p, 0);
	%y = getWord(%p, 1);
	return (%this.West < %x && %x < %this.East && %this.South < %y && %y < %this.North);
}
This function determines if an object is inside or outside of a zone. You can choose to destroy, teleport, bounce, or whatever you want, with this info.

Code: Select all

// Terrain Elevation Detail, returns a position on top of the terrain, building, and other objects...
function ted(%pos)
{
	if(getLOSInfo(Vector::add(%pos, "0 0 10000"), Vector::sub(%pos, "0 0 10000"), 1))
		return $LOS::Position;
	else
		return %pos;
}
I wrote this function a long time ago, and have used it for many applications. I've used it for spawning zombies that pop out of the terrain, teleporting flags used as waypoints in race missions, marking boundaries on the terrain with beacons, etc...

Code: Select all

// Generates a random coordinate on top of terrain, buildings, and other objects...
function Zone::getRandomPos(%this)
{
	return ted(%this.west + floor(getRandom() * (%this.east - %this.west)) @" "@ %this.south + floor(getRandom() * (%this.north - %this.south)) @" 0");
}
This function gets a random position inside a zone, which would be useful for spawning your burly bots.

Code: Select all

// Periodically instructs the bot to go to a random coordinate within it's zone.
function AI::periodicWaypoint(%aiName)
{
	AI::directiveWaypoint(%aiName, Zone::getRandomPos(AI::getID(%aiName).zone), 1);
}
You'll need to set AI::getID(%aiName).zone to equal the group ID of the markers that define the zone, to make this work.