Finding the Closest Town Center/Dropoff
by Dave Young · in RTS Starter Kit · 01/30/2006 (1:13 am) · 4 replies
I wanted my peons to be able to take advantage of my building acumen and save themselves a 10 mile hike, so I changed the findTC routine to find the closest townCenter.
In server/scripts/avatars/player.cs:
In function Player::collectResource, the call becomes:
%TC = findTC(%this.client, %this);
from
%TC = findTC(%this.client);
Yeeha!
In server/scripts/avatars/player.cs:
function findTC(%client,%villager){
%tmpClosest = "1000000";
%tmpClosestID = 0;
for(%i = 0; %i < %client.buildings.getCount(); %i++)
{
%bl = %client.buildings.getObject(%i);
if(%bl.getDataBlock().getName() $= "townCenterBlock")
{
%vel = VectorLen(VectorSub(%bl.getPosition(), %villager.getPosition()));
if(%vel < %tmpClosest)
{
%tmpClosest = %vel;
%tmpClosestID = %bl;
}
echo("Distance to TC:" @ %vel);
}
}
if(%tmpClosestID != 0){
echo("Villager is looking for closest drop off point. Found (" @ %tmpClosestID @ ") at (" @ %tmpClosestID.getPosition() @ ")");
return %tmpClosestID;
}
echo("findTC--could not find a TC, HANDLE THIS STATE");
}In function Player::collectResource, the call becomes:
%TC = findTC(%this.client, %this);
from
%TC = findTC(%this.client);
Yeeha!
#2
Why not have them remember the nearest one, and only when one is destroyed or a new one is created do they check again? How often will they be finding a resource halfway between them?
09/14/2006 (7:34 pm)
If you have a lot of villagers working, doesn't that tax your processor needlessly?Why not have them remember the nearest one, and only when one is destroyed or a new one is created do they check again? How often will they be finding a resource halfway between them?
#3
06/01/2008 (7:23 am)
I cant get this to work. The villagers still go straight back to the original TC. any ideas?
#4
02/06/2010 (9:29 pm)
works great for me, just remember to add the variables to each building type.
Torque 3D Owner Dave Young
Dave Young Games
OK, it makes more sense to find the closest dropoff point, where it is a TownCenter, OR one of the various harvesting type buildings.
How it works: when villager has collected the max amount they can carry, they search for the nearest dropoff point. they do this every time they are full, so if you add new dropoff points or Town Centers that are closer, they figure it out. However, if the dropoff point disappears between the time they start wandering there and arrive at the destination, they won't know what to do (thats on the todo list though)
Requires a change to findTC in player.cs, and defining the Collects variable in the datablock for the building type.
Sorry about the debug code, feel free to take it out!
In player.cs:
function findTC(%client,%villager){ %tmpClosest = "1000000"; %tmpClosestID = 0; echo("This villager is trying to drop off some " @ %villager.resourceType); for(%i = 0; %i < %client.buildings.getCount(); %i++) { %bl = %client.buildings.getObject(%i); echo("This building can collect: " @ %bl.getDataBlock().Collects); if(%bl.getDataBlock().getName() $= "townCenterBlock" || %bl.getDataBlock().Collects $= %villager.resourceType) { %vel = VectorLen(VectorSub(%bl.getPosition(), %villager.getPosition())); if(%vel < %tmpClosest) { %tmpClosest = %vel; %tmpClosestID = %bl; } echo("Distance to TC:" @ %vel); } } if(%tmpClosestID != 0){ echo("Villager is looking for closest drop off point. Found (" @ %tmpClosestID @ ") at (" @ %tmpClosestID.getPosition() @ ")"); return %tmpClosestID; } echo("findTC--could not find a TC, HANDLE THIS STATE"); }and in building.cs, add the Collects variable like so:
datablock RTSUnitData(shopBlock : UnitBaseBlock) { shapeFile = "~/data/shapes/shop/shop.dts"; RTSUnitTypeName = "shop"; boundingBox = "10.0 10.0 3.0"; Collects = "Gold"; }; datablock RTSUnitData(farmBlock : UnitBaseBlock) { shapeFile = "~/data/shapes/factory/factory.dts"; RTSUnitTypeName = "farm"; boundingBox = "10.0 10.0 3.0"; Collects = "Food"; };Note that you don't need to define Collects for any building type that won't be collecting, the engine won't complain if it can't find the Collects variable.
Todo
1) Define multiple collect types in the same string, and change from $= to something like InStr(Collects,resourceType) > -1 (If InStr is supported)
2) Have the villager look for another dropoff point if this one dies before they arrive
3) Have the villager look for a dropoff point if there never was one originally, instead of standing idle
Get those peons out there and collecting!