///////////////////////////////////
//Alternative Timers Library v1.1//
///////////////////////////////////
//import "std.zh"
//import "string.zh"
//These constants determine timer states. Don`t change them.
const int TIMER_STATE_STOPPED = 0; //Timer is stopped
const int TIMER_STATE_COUNTING_UP = 1; //Timer is counting up
const int TIMER_STATE_COUNTING_DOWN = 2; //Timer is counting down
const int TIMER_STATE_PAUSED_COUNTUP = 3; //The timer counting up is paused
const int TIMER_STATE_HIT_ZERO = 4; //The countdown timer has just recently hit 0
const int TIMER_STATE_PAUSED_COUNTDOWN = 5; //The timer counting down is paused
//Main timer global arrays. Expand as you want. But make sure, that all 4 arrays have the same size.
int TimerSeconds[5];
int TimerFrames[5];
int TimerState[5];
//You can set any of booleans of this array to "FALSE" to prevent UpdateTimers() command from affecting specific timers.
bool GlobalTimer[5];
//Example of how the global script should be combined with other global scripts.
global script Timers{
void run(){
while (true){
UpdateTimers();
Waitdraw();
Waitframe();
}
}
}
//Timers initialization routine. Put this into your "init" global script.
void InitTimers(){
int numtimers = SizeOfArray(TimerSeconds);
for (int i=0; i<=numtimers; i++){
TimerSeconds[i]=0;
TimerFrames[i]=0;
TimerState[i]=0;
GlobalTimer[i]=true;
}
}
//Main timer update function. Must be placed in before Waitdraw() command in the main loop
//of global script.
void UpdateTimers(){
int NumTimers = SizeOfArray(TimerState);
for (int i=0; i<NumTimers; i++){
if (!GlobalTimer[i]) continue;
if (TimerState[i]==TIMER_STATE_STOPPED) continue;
if (TimerState[i]==TIMER_STATE_PAUSED_COUNTUP) continue;
if (TimerState[i]==TIMER_STATE_PAUSED_COUNTDOWN) continue;
if (TimerState[i]==TIMER_STATE_HIT_ZERO){
TimerSeconds[i]=0;
TimerFrames[i]=0;
TimerState[i]=TIMER_STATE_STOPPED;
}
if (TimerState[i]==TIMER_STATE_COUNTING_UP){
TimerFrames[i]++;
if (TimerFrames[i]>=60){
TimerSeconds[i]++;
TimerFrames[i]=0;
}
}
if (TimerState[i]==TIMER_STATE_COUNTING_DOWN){
TimerFrames[i]--;
if (TimerFrames[i]<0){
TimerSeconds[i]--;
TimerFrames[i]=59;
}
if (TimerSeconds[i]<0){
TimerFrames[i] = 0;
TimerSeconds[i] = 0;
TimerState[i]=TIMER_STATE_HIT_ZERO;
}
}
}
}
//Local version of timer updating. Best used in FFC scripts, if you don`t want to combine global scripts.
void UpdateTimer(int timer, int speed){
if (TimerState[timer]==TIMER_STATE_STOPPED) return;
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTUP) return;
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTDOWN) return;
if (TimerState[timer]==TIMER_STATE_HIT_ZERO){
TimerSeconds[timer]=0;
TimerFrames[timer]=0;
TimerState[timer]=TIMER_STATE_STOPPED;
}
if (TimerState[timer]==TIMER_STATE_COUNTING_UP){
TimerFrames[timer]+=speed;
if (TimerFrames[timer]>=60){
TimerSeconds[timer]++;
TimerFrames[timer]=0;
}
}
if (TimerState[timer]==TIMER_STATE_COUNTING_DOWN){
TimerFrames[timer]-=speed;
if (TimerFrames[timer]<0){
TimerSeconds[timer]--;
TimerFrames[timer]=59;
}
if (TimerSeconds[timer]<0){
TimerFrames[timer] = 0;
TimerSeconds[timer] = 0;
TimerState[timer]=TIMER_STATE_HIT_ZERO;
}
}
}
//Sets the timer, regardless of it`s previous state.
void SetTimer (int timer, int Seconds, int Frames){
TimerFrames[timer] = Frames;
TimerSeconds[timer] = Seconds;
}
//Adds or removes value (seconds and fractions of seconds) from timer.
//Use negative values to reduce time. "AllowNegative" boolean, when
//set to "false" prevents timer from going into negative value.
void AddToTimer(int timer, int Seconds, int Frames, bool AllowNegatives){
TimerFrames[timer] += Frames;
TimerSeconds[timer] += Seconds;
if (TimerFrames[timer]>= 60){
while (TimerFrames[timer]>= 60){
TimerSeconds[timer] ++;
TimerFrames[timer] -= 60;
}
}
if (TimerFrames[timer]<= 0){
while (TimerFrames[timer]<= 60){
TimerSeconds[timer] --;
TimerFrames[timer] += 60;
}
}
if (!AllowNegatives){
if (TimerSeconds[timer]<= 0)TimerSeconds[timer] = 0;
}
}
//Fast-forwards timer by adding or removing value/s, depending on timer state.
void FastForwardTimer(int timer, int Seconds, int Frames){
if (TimerState[timer]==TIMER_STATE_COUNTING_UP) AddToTimer(timer, Seconds, Frames, false);
if (TimerState[timer]==TIMER_STATE_COUNTING_DOWN) AddToTimer(timer, (-(Seconds)),(-(Frames)), false);
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTUP) AddToTimer(timer, Seconds, Frames, false);
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTDOWN) AddToTimer(timer, (-(Seconds)),(-(Frames)), false);
}
//Rewinds timer by adding or removing value/s, depending on timer state.
void RewindTimer(int timer, int Seconds, int Frames){
if (TimerState[timer]==TIMER_STATE_COUNTING_UP) AddToTimer(timer, (-(Seconds)),(-(Frames)), false);
if (TimerState[timer]==TIMER_STATE_COUNTING_DOWN) AddToTimer(timer, Seconds, Frames, false);
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTUP) AddToTimer(timer, (-(Seconds)),(-(Frames)), false);
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTDOWN) AddToTimer(timer, Seconds, Frames, false);
}
//Launch timer counting up.
void StartCountingUp(int timer){
TimerState[timer] = TIMER_STATE_COUNTING_UP;
}
//Launch timer countdown.
void StartCountingDown(int timer){
TimerState[timer] = TIMER_STATE_COUNTING_DOWN;
}
//Pauses the given timer.
void PauseTimer(int timer){
if (TimerState[timer]==TIMER_STATE_COUNTING_UP) TimerState[timer] = TIMER_STATE_PAUSED_COUNTUP;
if (TimerState[timer]==TIMER_STATE_COUNTING_DOWN) TimerState[timer] = TIMER_STATE_PAUSED_COUNTDOWN;
}
//Resumes the paused timer.
void ResumeTimer(int timer){
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTUP) TimerState[timer] = TIMER_STATE_COUNTING_UP;
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTDOWN) TimerState[timer] = TIMER_STATE_COUNTING_DOWN;
}
//Stops and resets the given timer.
void StopTimer(int timer){
TimerFrames[timer] = 0;
TimerSeconds[timer] = 0;
TimerState[timer] = TIMER_STATE_STOPPED;
}
//Sets countdown timer, so the desired events will be triggered instantly, as if timer hits 0.
//Just like cutting wrong wire on time bomb causing it to explode immediately.
//"detonatepaused", if set to TRUE, also allow detonation of paused timer.
void DetonateInstantly(int timer, bool detonatepaused){
if ((TimerState[timer]==TIMER_STATE_PAUSED_COUNTDOWN)&&(!detonatepaused)) return;
if (TimerState[timer] != TIMER_STATE_COUNTING_DOWN) return;
TimerFrames[timer] = 0;
TimerSeconds[timer] = 0;
}
//Use this function to prevent countdown timer from going beyond desired value.
//Just like preventing fuel tank from overfilling with added fuel.
void SetMaxCountdowntimer(int timer, int Seconds, int Frames){
if ((TimerState[timer] != TIMER_STATE_COUNTING_DOWN)&&
(TimerState[timer]!=TIMER_STATE_PAUSED_COUNTDOWN)) return;
if(TimerSeconds[timer] > Seconds){
TimerSeconds[timer] = Seconds;
TimerFrames [timer] = Frames;
}
else if (TimerSeconds[timer] == Seconds){
if (TimerFrames [timer] > Frames) TimerFrames [timer] = Frames;
}
}
//Returns TRUE if the timer is still active (either running or paused).
bool TimerIsActive(int timer){
if (TimerState[timer]==TIMER_STATE_STOPPED) return false;
return true;
}
//Returns TRUE if the timer is running.
bool TimerIsRunning (int timer){
if (TimerState[timer]==TIMER_STATE_COUNTING_UP) return true;
if (TimerState[timer]==TIMER_STATE_COUNTING_DOWN) return true;
return false;
}
//Returns TRUE if the timer is paused.
bool TimerIsPaused (int timer){
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTUP) return true;
if (TimerState[timer]==TIMER_STATE_PAUSED_COUNTDOWN) return true;
return false;
}
//Returns TRUE if timer has reached specific threshold, depending on it`s state.
bool TimerReachValue(int timer, int Seconds, int Frames){
if (TimerState[timer]==TIMER_STATE_COUNTING_UP){
if(TimerSeconds[timer] > Seconds) return true;
if(TimerSeconds[timer] < Seconds) return false;
if(TimerFrames [timer] >= Frames) return true;
return false;
}
if (TimerState[timer]==TIMER_STATE_COUNTING_DOWN){
if(TimerSeconds[timer] < Seconds) return true;
if(TimerSeconds[timer] > Seconds) return false;
if(TimerFrames [timer] <= Frames) return true;
return false;
}
return false;
}
//Draws the given timer onto screen. Format is similar to Draw functions.
//"layer", "x", "y", "font", "color", & "opacity" arguments are similar to other drawing functions.
//"DrawFrames" boolean draws fractions of second, if TRUE
//"DrawMinutes" boolean converts timer into "mmm:ss:(ff)" format from "ssssss:(ff)".
void DrawTimer(int layer, int x, int y, int font, int color, int timer, bool drawframes, bool drawminutes, int opacity){
int frames = TimerFrames[timer];
int seconds = TimerSeconds[timer];
int curseconds = seconds%60;
int minutes = Floor(seconds/60);
int source[24] = "%d:0%d:0%d";
int string[256];
if (drawframes){
if (drawminutes){
if (curseconds>9) remnchr(source, 3, 1);
if (frames>9){
int remchar = 7;
if (curseconds>9) remchar = 6;
remnchr(source, remchar, 1);
}
sprintf(string, source, minutes, curseconds, frames);
}
else{
int newstr[] ="%d:0%d";
if (frames>9) remnchr(newstr, 3, 1);
strcpy(source, newstr);
sprintf(string, source, seconds, frames);
}
}
else {
if (drawminutes){
int newstr[] ="%d:0%d";
if (curseconds>9) remnchr(newstr, 3, 1);
strcpy(source, newstr);
sprintf(string, source, minutes, curseconds);
}
else{
int newstr[] ="%d";
strcpy(source, newstr);
sprintf(string, source, seconds);
}
}
Screen->DrawString(layer, x, y, font, color, -1, TF_NORMAL, string, opacity);
}
//Test script. Creates generic time bomb. When timer expires, bomb explodes.
//Stepping on bomb results in an instant explosion.
//Set the combo to look like bomb.
// D0: "Seconds" part of init timer.
// D1: "Frames" part of init timer.
// D2: Damage dealt to Link if he was too close to bomb, when it goes boom.
ffc script TimerTest{
void run(int seconds, int frames, int damage){
if (!TimerIsActive(0))SetTimer (0, seconds, frames);
StartCountingDown(0);
while (true){
if (LinkCollision(this)) DetonateInstantly(0, true);
if(TimerState[0]==TIMER_STATE_HIT_ZERO){ //KA-BOOM!!
eweapon explosion = Screen->CreateEWeapon(EW_BOMBBLAST);
explosion->X=this->X;
explosion->Y=this->Y;
explosion->Damage = damage;
if (damage==0) explosion->CollDetection=false;
this->Data=0;
Quit();
}
int drawx = this->X - 16;
int drawy = this->Y - 16;
DrawTimer(0, drawx, drawy, 0, 1, 0, true, true, OP_OPAQUE);
Waitframe();
}
}
}