Game Development Community

Master 'Cancel ALL Schedules' command??

by Nicolai Dutka · in Torque Game Builder · 04/03/2008 (3:57 pm) · 16 replies

I need a command to quickly and easily "Cancel ALL Schedules".

I have a game in which the levels are entirely scripted through schedules and when the players die and screen changes to end game stuff, all the schedules keep running, so when they start a new game, they get dumped on....

I KNOW how to cancel a schedule, but I have a possible 10-20 schedules going on at once and I don't know which ones have completed.

I just wanna say:
cancelAllSchedules();

I also don't want to have to add in new resources or write 1000 lines of code to do this! Isn't there something built in to the engine? I thought I recall seeing something to 'deleteAllVariables' (something like that) so why not a master schedule canceller?

#1
04/03/2008 (4:07 pm)
I would recommend keeping track of the schedules in a list somewhere and explicitly cancelling each one.
you might find this script array resource handy.
#2
04/03/2008 (4:11 pm)
EDIT: The "solution" below does not work. I've only left it in place so that the rest of the thread makes sense.

The reason it does not work is that Events are derived from ConsoleObject directly, not SimObject, so they cannot interact with SimSets (Events do not ever register with the simulation itself, which is a requirement to be part of a SimSet).

Every time you make a schedule, save the returned objectID, and add it to a set:

// put this line before your game starts up, early in the standup sequence:

$Game::Events::PendingSet = new SimSet(PendingEventsSet);

// example of a game schedule already in your game:
%myEventID = schedule(100, 0, myFunction);

// put this line after each one of the schedules in your game
PendingEventsSet.add(%myEventID);

// put this function anywhere you like (as long as it's exec'd)

function cancelAllPendingEvents()
{
  %numPendingEvents = PendingEventsSet.getCount();
  for (%index = %numPendingEvents; %index > 0; %index--)
  {
    %pendingEvent = PendingEventsSet.getObject(0);
    %pendingEvent.cancel();
  }
}

That's from memory and will probably need some tweaking, but should accomplish exactly what you want.
#3
04/03/2008 (4:13 pm)
Mmmm, nice'n'short! Thanks a bunch!
#4
04/03/2008 (4:16 pm)
Looks like the $myEventID needs to be added to the PendingEventsSet somehow.

Maybe:
PendingEventsSet.add($myEventID);

Would that do it?
#5
04/03/2008 (4:19 pm)
Actually you might not have to cancel them, you could try this:

new ScriptObject(gScheduleObj);

Whenever you make a schedule, always make gScheduleObj the %refObj.

Like:
schedule( 100, gScheduleObj, myFunction );

Then to cancel all schedules...

gScheduleObj.delete();

If you need to have other objects as the %ref object this you couldn't use this trick.
#6
04/03/2008 (4:21 pm)
Yes, you're right, I missed one line. Editing original post now.
#7
04/03/2008 (4:25 pm)
Wait, does that work? Schedule-ids are considered SimObjects and can be added to SimSets?

I think you need to cancel a schedule like:
cancel(%schID);

Rather than :
%schID.cancel();
#8
04/03/2008 (4:39 pm)
Ya, that didn't work. I didn't get any errors, but my schedules did not stop.
#9
04/03/2008 (4:41 pm)
It's like James said, the schedule ID I pass to the SimSet is not an object, just an ID. Then, in the cancel function, we are trying to get and cancel objects, but we never had an object, we only had an ID.
#10
04/03/2008 (4:49 pm)
I would do something like this:

// Usage: addEvent(%myObj.schedule(timeToExpiry, myFunction));
function addEvent(%eventId)
{
    $Game::EventList = trim($Game::EventList SPC %eventId);
    return (%eventId);
}
 
function cancelAllEvents()
{
    %eventList = $Game::EventList;
    for (%i = 0; %i < getWordCount(%eventList); %i++)
    {
        %eventId = getWord(%eventList, %i);
        if (isEventPending(%eventId))
            cancel(%eventId);
    }
 
    $Game::EventList = "";
}

But that is just me ;)
#11
04/03/2008 (4:51 pm)
What if:

%event = schedule(13000,0,spawnEnemies);
    %obj = new simObject();
    %obj.id = %event;
    PendingEventsSet.add(%obj);


function cancelEvents()
{  
  %numPendingEvents = PendingEventsSet.getCount();
  for (%index = %numPendingEvents; %index > 0; %index--)
  {    
    %event = PendingEventsSet.getObject(0).id;
    cancel(%event);
  }
}

I tried this and it said something about:

Set::add: Object "29" doesn't exist.
#12
04/03/2008 (5:02 pm)
Stephen's method should work, except he doesn't remove the object from the SimSet.

The way that it works is different from how it *should* work. Event id's are indexed in the same manner object id's are. As long as object 0, 1 ... X exist, they will be able to be added to the SimSet (but the SimObject will be added to the SimSet and not the event, as the event is not a SimObject). When they don't exist, you will get errors.

I think the simplest method is the one I described above. Short and sweet.
#13
04/03/2008 (5:03 pm)
You guys caught me (was unintentional, I promise :( )--I had forgotten that Events are actually not derived from SimObject but come directly from ConsoleObject, and therefore cannot be added to sets. My solution above does not work.

Phillip's solution is much better, and should work. It does however have an issue with that string becoming very very large over time, since they will not be removed automatically when the event itself is triggered normally.

I'll think about this for a bit and see if there is a strong overall solution.

We all blew past it, but James Ford's solution will actually work in effect (it doesn't actually cancel the events, but when they attempt to mature and their reference object is gone, they will do nothing at all, and then be deleted as normal). It's not elegant (no insult intended, the system doesn't seem to actually let us be elegant), but it will work for schedules that aren't already tied to reference objects.
#14
04/03/2008 (5:07 pm)
I am using the last method suggested by Phillip. I really like the way it looks and it seems to be working great!

Now, I have a finaly issue to take care of, but I think I'll start a new thread for it.

I need to clear cloned objects from the scene...
#15
04/03/2008 (5:09 pm)
This business of making a script object to hold an integer ID just so you can put them in a simSet seems a bit awkward.

Phillip's idea of making a space-delimited list of them seems good,
as does James's clever idea of attaching them all to an object and then deleting the object,
or with the script-based array thing i mentioned, it would look somerhing like

$gScheduleArray = "";

function create()
{
   %scheduleID = schedule( .. params .. );
   
   if (!isObject($gScheduleArray))
   {
      $gScheduleArray = new_ScriptArray("");
   }
   
   $gScheduleArray.append(%scheduleID);
}

function cancelAll()
{
   if (!isObject($gScheduleArray))
      return;
   
   for (%n = $gScheduleArray.size() - 1; %n >= 0; %n--)
   {
      cancel($gScheduleArray.get(%n));
   }
   
   $gScheduleArray.delete();
   $gScheduleArray = "";   
}
#16
04/04/2008 (6:03 am)
Here's the solution I ended up with when I needed this functionality. Ramen-sama provided the initial solution and I tweaked a little to handle a certain error case. It requires the script array resource as well.