Copy to Clipboard Test

Wheel of Fortune/Death Code

const int SFX_ROULETTE_SPIN = 17; //Sound to play during roulette spinning

const int ROULETTE_RENDER_TRUE_RESULTS = 0; //Set to >0 - render exact angle wheel is, when not spinning.
const int ROULETTE_LOCK_HIGHLIGHT_CORRECT_LANDING = 0;//Set to >0 - outline rectangle around lock wheel, when the pointer is in target sector.

//Roulette wheel. Step on FFC and press EX1 to spin it. You need to meet counter requirements to do this. Roulette itself 
//is d360 and does not do anything, only set it`s InitD[7] to result angle. While roulette is spinning, InitD[7] is set to -1. You need
//other scripts that can read FFC`s InitD[7] to determine and resolve various events depending on wheel spin result.

//Requires ghost.zh

//Place FFC on the at activation button.
//D0 - combo position where the wheel will be located. Size is 3*3.
//D1 - combo used to render roulette wheel
//D2 - counter required to spin the wheel
//    #####.____ - counter ID;
//    _____.#### - counter cost, not subtracted on spin.
//D3 - if > 0 - subtract cost.
ffc script RouletteWheel{
	void run (int pos, int cmb, int req, int sub){
		int xpos = ComboX(pos);
		int ypos = ComboY(pos);
		int angle = Rand(360);
		int rnd[3] = {0,0,0};
		this->InitD[7] = 0;
		bool spin = false;
		int origdata = this->Data;
		int counter = Abs(GetHighFloat(req));
		int cost = GetLowFloat(req);
		int rat = Div(angle, 10);
		while (true){
			if (!spin){
				if (RectCollision(Link->X+7, Link->Y+7, Link->X+8, Link->Y+8, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
					if ((Game->Counter[counter]>=cost)&&(Link->PressEx1)){
						//angle = Rand(360);
						rat = Div(angle, 10);
						rnd[0] = 120 + Rand(120);
						rnd[1] = 60;
						rnd[2] = 60 + Rand(3);;
						this->InitD[7]=-1;
						this->Data++;
						if (sub>0) Game->DCounter[counter] -=cost;
						spin = true;
					}
				}
			}
			else{
				NoAction();
				angle%=360;
				if (Div(angle, 10)==rat){
					Game->PlaySound(SFX_ROULETTE_SPIN);
					rat++;
					if (rat>=36) rat=0;
				}
				if (rnd[0]>0){
					angle+=3;
					rnd[0]--;
				}
				else if (rnd[1]>0){
					angle+=2;
					rnd[1]--;
				}
				else if (rnd[2]>0){
					angle++;
					rnd[2]--;
				}
				else{
					this->Data=origdata;
					this->InitD[7]=angle;
					spin = false;
				}
			}
			Screen->DrawCombo(2, xpos, ypos,cmb, 3, 3, this->CSet, -1, -1, xpos, ypos, angle, 0, 0,true, OP_OPAQUE);
			if (!spin && (ROULETTE_RENDER_TRUE_RESULTS>0)) Screen->DrawInteger(2, xpos, ypos,0, 1,0, -1, -1, angle, 0, OP_OPAQUE);
			Waitframe();
		}
	}
}


//Roulette wheel event resolver. Has up 4 events, one of them can happen after spinning the wheel. Each event has minimum angle value (0-359) 
//that roullete must stop at for event to happen. Only 1 event happens per spin. Each event is evaluated in sequence, in order: D1, D3, D5, D7.
//So for 4th event to happen, the following inequality must be true: D1 > D3 > D5 > D7. If Roulette result is lower than D7, in that instance, 
//nothing happens.
//Place invisible FFC anywhere in the screen.
// D1, D3, D5, D7 - angles used to determine event chances.
// D0, D2, D4, D6 - events to occur
// #####.[0-31] - counter affected, in positive or negative way. #####.____ amount, _____.#### - counter to affect.
// _____.0033 - Trigger permanent screen secrets
// #####.0034 - Spawn 1 enemy. High value - Enemy ID.
// #####.0035 - Positive - give Link item #####. Negative - take away item ##### from Link`s inventory.
ffc script DiceEvent{
	void run(int event1, int chance1, int event2, int chance2, int event3,int chance3, int event4, int chance4){
		int str[] = "RouletteWheel";
		int scr = Game->GetFFCScript(str);
		ffc r;
		int events[4] = {event1, event2, event3, event4};
		int chance[4] = {chance1, chance2, chance3, chance4};
		int eventpower[4];
		int eventtype[4];
		int origdata = this->Data;
		for (int i=0;i<4; i++){
			eventpower[i] = GetHighFloat(events[i]);
			eventtype[i] = GetLowFloat(events[i]);
			eventtype[i]=Abs(eventtype[i]); 
		}
		bool spin = false;
		for (int i=1; i<=33; i++){
			if (i==33){
				int error[] = "Roulette not found. Use RouletteWheel FFC script";
				TraceS(error);
				Quit();
			}
			r = Screen->LoadFFC(i);
			if (r->Script!=scr) continue;
			else break;
		}
		while (true){
			if (spin){
				if (r->InitD[7]>0){
					int res = r->InitD[7];
					for (int i = 0; i<=3; i++){
						if (res>=chance[i]){
							//Trace(eventpower[i]);
							//Trace(eventtype[i]);
							if (eventtype[i]>=0 && eventtype[i]<32){
								int cr = eventtype[i];
								Game->DCounter[cr] += eventpower[i];
							}
							if (eventtype[i]==33){
								Game->PlaySound(SFX_SECRET);
								Screen->TriggerSecrets();
								Screen->State[ST_SECRET]=true;
							}
							if (eventtype[i]==34){
								npc en = SpawnNPC(eventpower[i]);								
							}
							if (eventtype[i]==35){
								int itm = Abs(eventpower[i]);
								if (eventpower[i]>0){
									item it = CreateItemAt(itm, Link->X, Link->Y);
									it->Pickup=2;
								}
								else {
									Game->PlaySound(SFX_OUCH);
									Link->Item[itm] = false;
								}
							}							
							spin=false;
							break;
						}
					}
					//Trace(r->InitD[7]);
				}
			}
			else{
				if (r->InitD[7]<0) spin=true;
			}
			Waitframe();
		}
	}
}

//Roulette wheel combination lock. Keep spinning wheel until it lands on correct angle or within tolerance sector to open secrets.
//Unlike normal roulette wheel, it does not cause Link to freeze in place until spinning wheel stops.
//Place FFC on the at activation button.
//D0 - combo position where the wheel will be located. Size is 3*3.
//D1 - combo used to render roulette wheel
//D2 - counter required to spin the wheel
//    #####.____ - counter ID;
//    _____.#### - counter cost, not subtracted on spin.
//D3 - target angle, or bisect of target sector.
//D4 - Tolerance value. Higher the value, the wider is target sector to land into and open secrets.
//D5 - if > 0 - subtract cost per spin.

ffc script RouletteWheelLock{
	void run (int pos, int cmb, int req, int targangle, int tolerance, int sub){
		int str[] = "RouletteWheelLock";
		int scr = Game->GetFFCScript(str);
		int xpos = ComboX(pos);
		int ypos = ComboY(pos);
		int angle = Rand(360);
		int rnd[3] = {0,0,0};
		this->InitD[7] = 0;
		this->InitD[6] = 0;
		bool spin = false;
		int origdata = this->Data;
		int counter = GetHighFloat(req);
		int cost = GetLowFloat(req);
		int rat = Div(angle, 10);
		while (true){
			if (!spin){
				if (RectCollision(Link->X+7, Link->Y+7, Link->X+8, Link->Y+8, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
					if ((Game->Counter[counter]>=cost)&&(Link->PressEx1)){
						if (sub>0) Game->DCounter[counter] -=cost;
						this->Data++;
						rat = Div(angle, 10);
						rnd[0] = 120 + Rand(120);
						rnd[1] = 60;
						rnd[2] = 60+ Rand(3);
						this->InitD[7]=-1;
						spin = true;
					}
				}
			}
			else{
				//NoAction();
				angle%=360;
				if (Div(angle, 10)==rat){
					Game->PlaySound(SFX_ROULETTE_SPIN);
					rat++;
					if (rat>=36) rat=0;
				}
				if (rnd[0]>0){
					angle+=3;
					rnd[0]--;
				}
				else if (rnd[1]>0){
					angle+=2;
					rnd[1]--;
				}
				else if (rnd[2]>0){
					angle++;
					rnd[2]--;
				}
				else{
					this->InitD[7]=angle;
					this->Data=origdata;
					int rangeleft = targangle - tolerance + 360;
					int rangeright = targangle + tolerance + 360;
					int checkangle = angle + 360;
					//Trace(rangeleft);
					//Trace(rangeright);
					//Trace(checkangle);
					if (checkangle>= rangeleft && checkangle<= rangeright){
						this->InitD[6]=1;
						for (int i = 1; i<= 33; i++){
							if (Screen->State[ST_SECRET]) break;
							if (i==33 && !Screen->State[ST_SECRET]){
								Game->PlaySound(SFX_SECRET);
								Screen->TriggerSecrets();
								Screen->State[ST_SECRET]=true;
								break;
							}
							ffc f = Screen->LoadFFC(i);
							if (f->Script != scr) continue;
							if (f->InitD[6]==0) break;
						}
					}
					else this->InitD[6] = 0;
					spin = false;
				}
			}
			Screen->DrawCombo(2, xpos, ypos,cmb, 3, 3, this->CSet, -1, -1, xpos, ypos, angle, 0, 0,true, OP_OPAQUE);
			if (!spin && (ROULETTE_RENDER_TRUE_RESULTS>0)) Screen->DrawInteger(2, xpos, ypos,0, 1,0, -1, -1, angle, 0, OP_OPAQUE);
			if ((this->InitD[6]>0)&&(ROULETTE_LOCK_HIGHLIGHT_CORRECT_LANDING>0)) Screen->Rectangle(2, xpos, ypos, xpos+47, ypos+47, 1, -1, 0, 0, 0, false, OP_OPAQUE);
			Waitframe();
		}
	}
}

//Returns a pointer of 1st FFC that runs roulete wheel script. Yields eror message, if none found.
ffc FindRouletteWheel(){
	ffc r;
	int str[] = "RouletteWheel";
	int scr = Game->GetFFCScript(str);
	for (int i=1; i<=33; i++){
		if (i==33){
			int error[] = "Roulette not found. Use RouletteWheel FFC script";
			TraceS(error);
			return r;
		}
		r = Screen->LoadFFC(i);
		if (r->Script!=scr) continue;
		else return r;
	}
}