1.0
22 Dec 2019 00:16
/*
Usage: To schedule a function to be called at some point in the future, call
the TimerV constructor with the desired delay and function as arguments, e.g.:
void myAlert() {
jjAlert("A second has passed.");
}
void onLevelLoad() {
TimerV(70, myAlert); //calls myAlert after one second (70 ticks)
}
Anonymous functions (or delegates) may be used instead:
void onLevelLoad() {
TimerV(70, function(){ jjAlert("A second has passed."); }); //same effect as above
}
For a recurring event, have the called function construct another timer for itself:
void morphEveryone() {
for (int i = 0; i < jjLocalPlayerCount; ++i)
jjLocalPlayers[i].morph(true);
TimerV(5 * 70, morphEveryone);
}
void onLevelLoad() {
morphEveryone(); //morphs all local players every five seconds
}
To pass one or more arguments to the delayed function, use a function that takes a single
dictionary@ as its sole argument, and pass that dictionary@ to the TimerV constructor:
void onFunction0(uint8 triggerID) {
if (!jjTriggers[triggerID]) {
jjTriggers[triggerID] = true;
TimerV( //turns on, then off, whichever trigger was specified by the offset parameter of the Text event
2 * 70,
function(arguments) {
jjTriggers[uint8(arguments["ID"])] = false;
},
dictionary = {{"ID",triggerID}}
);
}
}
Another use of a dictionary argument is to limit the number of times the function is called:
void playSound(dictionary@ arguments) {
jjSamplePriority(SOUND::COMMON_COIN);
int count = int(arguments["count"]) - 1;
if (count > 0) {
arguments["count"] = count;
TimerV(40, playSound, arguments);
}
}
void onLevelLoad() {
playSound(dictionary = {{"count",5}}); //plays the COMMON_COIN sample exactly five times
}
As mentioned, the TimerV lines are actually constructors, not regular functions. If you have any
reason to keep a TimerV object around after its construction, e.g. if there's a possibility you
might need to cancel it, it provides the following API:
const bool Active
true iff this timer is still running
const int Elapsed
How many ticks have passed since the construction, or -1 if Active is false
const int Total
The original time parameter passed to the constructor, as a reminder, or -1 if Active is false
const int Remaining
(Total - Elapsed), or -1 if Active is false
bool Paused
While true, this timer will not advance, though Active will remain true
bool Stop()
Stops the timer early (WITHOUT executing the function) and returns true, or returns false if Active was false
*/
funcdef void TimerVDictionaryFunction(dictionary@);
class TimerV : jjBEHAVIORINTERFACE {
TimerV(int time, jjVOIDFUNC@ callback) {
@_callback = @callback;
_start(time);
}
TimerV(int time, TimerVDictionaryFunction@ callback, dictionary@ arguments) {
@_callbackWithArguments = @callback;
@_arguments = @arguments;
_start(time);
}
bool get_Active() const {
return cast<jjBEHAVIORINTERFACE@>(_object.behavior) is this;
}
int get_Elapsed() const {
if (Active) return _object.age;
return -1;
}
int get_Total() const {
if (Active) return _object.counter;
return -1;
}
int get_Remaining() const {
if (Active) return _object.counter - _object.age;
return -1;
}
bool Stop() {
if (Active && _object.age < _object.counter) {
_object.delete();
return true;
}
return false;
}
bool Paused = false;
private jjVOIDFUNC@ _callback = null;
private TimerVDictionaryFunction@ _callbackWithArguments;
private dictionary@ _arguments;
private jjOBJ@ _object;
private int _startTime;
private void _start(int time) {
if (time > 0) {
@_object = jjObjects[jjAddObject(OBJECT::BEES, -1000, -1000, 0, CREATOR::OBJECT, BEHAVIOR::BEES)];
_object.behavior = this;
_object.counter = time;
_object.age = 0;
_object.playerHandling = HANDLING::PARTICLE;
_object.deactivates = false;
_startTime = jjGameTicks;
} else {
@_object = jjObjects[0]; //avoid null pointer access
_pickCallback();
}
}
private void onBehave(jjOBJ@ obj) {
if (!Paused && jjGameTicks > _startTime && obj is _object && ++_object.age >= _object.counter) {
_pickCallback();
_object.delete();
}
}
private void _pickCallback() {
if (_callback !is null)
_callback();
else
_callbackWithArguments(_arguments);
}
}
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.