| 12-13-2010, 06:27 AM | #1 |
Im having trouble with this my minions acting properly. Its not particularly robust system but it's just something to start with for me. What happens is that occasionally a minion gets stuck pathing back and forth between two of the points in their path. I'm not sure where its going wrong. Using GroupUtils for the ENUM_GROUP since it is used elsewhere in the map Zinc://! zinc library Minions requires GroupUtils { constant real SPAWN_INTERVAL = 30.0; constant real MOVE_INTERVAL = 3.0; constant real CHECK_RANGE = 200.0; point tempPoint; public struct point { //array of a singly linked list of points per player static point list[12]; player owner; real x; real y; point next = 0; static method create(real x, real y, integer pid) -> point { point p = point.allocate(); point i = list[pid]; p.x = x; p.y = y; p.owner = Player(pid); //Add the new point to the beginning of the list if its the new one else add it to the end of the list if (i == 0) { list[pid] = p; } else { while (i.next != 0) { i = i.next; } i.next = p; } return p; } static method onInit() { //Init the list array integer i; for (0 <= i < 12) { list[i] = 0; } } } public function Path_AddPoint(real x, real y, integer pid) { point.create(x, y, pid); //test code if (pid == 6) { SetUnitColor(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'ewsp', x, y, 0.0), GetPlayerColor(Player(6))); } else { SetUnitColor(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'ewsp', x, y, 0.0), GetPlayerColor(Player(2))); } } function timerElapse() { integer i; point p; unit u; for(0 <= i < 12) { p = point.list[i]; if (p != 0) { while (p.next != 0) { //BJDebugMsg("X:"+R2S(p.x)+" Y:"+R2S(p.y)+" PID:"+I2S(GetPlayerId(p.owner))); //BJDebugMsg("X:"+R2S(p.next.x)+" Y:"+R2S(p.next.y)+" PID:"+I2S(GetPlayerId(p.next.owner))); tempPoint = p; //Get units in range belonging to the player the point belongs to and force them to attack move to the next point GroupEnumUnitsInRange(ENUM_GROUP, p.x, p.y, CHECK_RANGE, function() -> boolean { if (GetOwningPlayer(GetFilterUnit()) == tempPoint.owner) { IssuePointOrderById(GetFilterUnit(), 851983, tempPoint.next.x, tempPoint.next.y); } return false; }); p = p.next; } } } } function onInit() { TimerStart(CreateTimer(), MOVE_INTERVAL, true, function timerElapse); TimerStart(CreateTimer(), SPAWN_INTERVAL, true, function() { //Suffice w/ simple static spawns for now CreateUnit(Player(2), 'h001', -3796, -3122, 0.0); CreateUnit(Player(2), 'h001', -3796, -3122, 0.0); CreateUnit(Player(2), 'h000', -3796, -3122, 0.0); CreateUnit(Player(6), 'u002', 3290, -3090, 0.0); CreateUnit(Player(6), 'u002', 3290, -3090, 0.0); CreateUnit(Player(6), 'u001', 3290, -3090, 0.0); }); } } //! endzinc EDIT: point is public for now to access it in the test system. |
| 12-13-2010, 11:07 AM | #2 |
Is the first point on the path between the second and the third? In that case, it could intercepts units going to the third and send them back to the second. |
| 12-13-2010, 02:50 PM | #3 |
Nope. I just put the system in a blank map and it seems to be working just fine. The points are all more than CHECK_RANGE*2 units apart EDIT: Some further poking at the system and fiddling with MOVE_INTERVAL it seems that when the units reach their next point before the next move update they start to run back to the point them came from. The strange part is that this doesn't occur in the test map but in the map that I'm working on. Reducing MOVE_INTERVAL's value to 1.7 catches the units and allows them time to perform their attack animations. I'll look through the other systems that are in the map for now but I don't think I have anything else that affects units movement |
| 12-14-2010, 12:22 PM | #4 |
Zinc:
static method onInit()
{
//Init the list array
integer i;
for (0 <= i < 12)
{
list[i] = 0;
}
}
This is unneeded. Arrays do not need to be initialised to 0 because they do that automatically. (list[i] = list[i] + 1) == 1 works just fine, even when list[i] was never inititalised. It is not like uninitialised integer i = i + 1, which does actually need an initialisation. Zinc:
while (i.next != 0)
{
i = i.next;
}
i.next = p;
If you had a "prev" variable, you could just replace this with point(0).prev.next = p. I highly recommend it. |
| 12-14-2010, 02:41 PM | #5 | ||
Quote:
Okay thanks I did not know that. Quote:
So your suggesting that I use a doubly linked list? Zinc:if (i == 0) { list[pid] = p; list[pid].next = p; list[pid].prev = p } else { list[pid].prev.next = p list[pid].prev = p } Like that? |
| 12-15-2010, 03:16 PM | #6 |
The best use of a doubly linked list: allocate: set thistype(0).next.prev=this set this.next=thistype(0).next set thistype(0).next=this set this.prev=thistype(0) deallocate: set this.prev.next=this.next set this.next.prev=this.prev This is from Jesus4Lyf's Timer32; http://www.thehelper.net/forums/showthread.php?t=132538 |
| 12-15-2010, 04:03 PM | #7 |
I dont think this helps as there are more than one list of type point |
