Copy to Clipboard Test

Evil Cursor Code

const int CF_CURSOR_CHANGEABLE=98; //Combo Flag to define combos that Evil Cursoe can change

//Evil Cursor

//An enemy that looks like Windows mouse cursor. Once upon time it "selects" (via drag) a portion of the screen. And every combo in selection will either fire eweapon at Link, or change to given one(if allowed), or both.

//Hunger and Homing fastor used. Step Speed defines number of frames (speed value/10) used to draw selection. 

ffc script EvilCursor{
	void run(int enemyID){
		npc ghost = Ghost_InitAutoGhost(this, enemyID);
		
		int HF = ghost->Homing;
		int HR = ghost->Haltrate;
		int RR = ghost->Rate;
		int HNG = ghost->Hunger;
		int SPD = ghost->Step;
		int WPND = ghost->WeaponDamage;
		
		int cursorx = Ghost_GetAttribute(ghost,0, 2);//Selection X size
		int cursory = Ghost_GetAttribute(ghost,1, 2);//Selection Y size
		int delay = Ghost_GetAttribute(ghost,2, 90);//Wait time between moving, in frames
		int WPNS = Ghost_GetAttribute(ghost,3, -1);//Eweapon sprite
		int combochange = Ghost_GetAttribute(ghost,4, 0);//ID of combo used to replace changeable combos. <0 - Use next combo in table.
		int enID = Ghost_GetAttribute(ghost,5, 0);//ID of enemy to spawn on each selected space.
		int continiouscombochange = Ghost_GetAttribute(ghost,6, 0);//>0 - Enemy can change the same combo on screen multiple times.
		
		ghost->Extend=3;
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_SetFlag(GHF_NO_FALL);
		Ghost_SetFlag(GHF_IGNORE_ALL_TERRAIN);
		Ghost_SetFlag(GHF_IGNORE_NO_ENEMY);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int statecounter = delay;
		int haltcounter = -1;
		int origx = Ghost_X;
		int origy = Ghost_Y;
		int targpos=0;
		int targx = 0;
		int targy = 0;
		int cmb = ComboAt(Ghost_X +1, Ghost_Y+1);
		int temp=0;
		int list[8];
		for (int i=0;i<8;i++){
			list[i]=0;
		}
		
		int combl=0;
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		while(true){
			if (State==0){
				statecounter--;
				if (statecounter<=0){
					for (int i=0;i<176;i++){
						if (Screen->ComboS[i]>0)continue;
						if (ComboFI(i, CF_NOENEMY))continue;
						if (!CursorLeaperMoveAdjacent(i, cmb, cursorx, cursory)) continue;
						list[combl]=i;
						combl++;
					}
					if (Rand(4)<HNG && NumLWeaponsOf(LW_BAIT)){
						for (int i=1;i<=Screen->NumLWeapons();i++){
							lweapon l =Screen->LoadLWeapon(i);
							if (l->ID!=LW_BAIT)continue;
							int p = ComboAt(CenterX(l),CenterY(l));
							targpos = Cursor_ClosestToPos(list, p);
						}
					}
					else if (Rand(256)<HF){
						int p = ComboAt(CenterLinkX(),CenterLinkY());
						targpos = Cursor_ClosestToPos(list, p);
					}
					else {
						targpos = Rand(combl);						
						targpos = list[targpos];
					}
					targx = ComboX(targpos);
					targy = ComboY(targpos);
					statecounter = SPD/10;
					combl=0;
					State=1;
				}
			}
			if (State==1){
				statecounter--;
				Ghost_X = Lerp(targx, origx, statecounter*10/SPD);
				Ghost_Y = Lerp(targy, origy, statecounter*10/SPD);
				Screen->Rectangle(2, Ghost_X, Ghost_Y, origx, origy,1, 1, 0, 0, 0,false, OP_OPAQUE);
				if (statecounter<=0){
					if (targx<origx){
						temp=targx;
						targx=origx;
					origx=temp;
					}if (targy<origy){
						temp=targy;
						targy=origy;
						origy=temp;
					}					
					// Screen->Rectangle(2, Ghost_X, Ghost_Y, origx, origy,1, 1, 0, 0, 0,false, OP_OPAQUE);
					for (int i=0;i<176;i++){
						if (Screen->ComboS[i]>0)continue;
						if (ComboFI(i, CF_NOENEMY))continue;
						if (!RectCollision(origx, origy,targx, targy, ComboX(i)+1, ComboY(i)+1, ComboX(i)+15, ComboY(i)+15)) continue;
						if (combochange>0 && ComboFI(i,CF_CURSOR_CHANGEABLE)){
							Screen->ComboD[i]=combochange;
							if (continiouscombochange==0)Screen->ComboF[i]=0;
						}
						if (combochange<0 && ComboFI(i,CF_CURSOR_CHANGEABLE)){
							Screen->ComboD[i]++;
							if (continiouscombochange==0)Screen->ComboF[i]=0;
						}
						if (WPND>0){
							eweapon e = FireAimedEWeapon(ghost->Weapon, ComboX(i), ComboY(i), 0, Cond(ghost->Weapon==EW_BOMBBLAST||ghost->Weapon==EW_SBOMBBLAST, 0, 200), WPND, WPNS, -1, EWF_ROTATE);
						}
						if (enID>0){
							npc n = CreateNPCAt(enID, ComboX(i), ComboY(i));
							lweapon e = CreateLWeaponAt(LW_SPARKLE, ComboX(i), ComboY(i));
							e->UseSprite(22);//Use Misc Spawn for spawn effect.
							e->CollDetection=false;
						}
					}
					cmb = ComboAt(Ghost_X +1, Ghost_Y+1);
					origx = ComboX(cmb);
					origy = ComboY(cmb);
					Ghost_X = origx;
					Ghost_Y = origy;
					// for (int i=0;i<8;i++){
					// list[i]=0;
					// }
					statecounter=delay;
					State=0;
				}
			}
			Ghost_Waitframe(this, ghost);
		}
	}
}

int Cursor_ClosestToPos(int list, int pos){
	int dist = 9999;
	int ret = 0;
	int pos2 = 0;
	int dist2 = 0;
	for (int i = 0; i<SizeOfArray(list);i++){
		if (list[i]==0)continue;
		pos2 = list[i];
		dist2 = Distance(ComboX(pos2), ComboY(pos2), ComboX(pos), ComboY(pos));
		if (dist2<dist)dist=dist2;
		else continue;
		ret=pos2;
	}
	return ret;
}

// Returns TRUE, if two given combos are within move of leaping chess piece.
bool CursorLeaperMoveAdjacent(int cmb1, int cmb2, int l1, int l2){
	int r1 = ComboY (cmb1);
	int r2 = ComboY (cmb2);
	int f1 = ComboX (cmb1);
	int f2 = ComboX (cmb2);
	if ((Abs(r1-r2)/16)==l1){
		if ((Abs(f1-f2)/16)==l2) return true;
	}
	if ((Abs(r1-r2)/16)==l2){
		if ((Abs(f1-f2)/16)==l1) return true;
	}
	return false;
}