const int I_PORTAL_CUBE = 150;//ID of item that is needed for Link to teleport between portals.
const int CT_PORTAL = 142; //Combo Type for Portal combos. FFC scripts can recycle blank combo types ans blank flags as long as no two different FFC scripts use the same flag or combo type on the same screen.
const int CF_PORTAL_ONEWAY = 98; //Neither Link, nor enemes are not teleported, if stepped onto portal flagged with this combo flag. Other portal can teleport onto this flagged portal.
const int SFX_PORTAL = 32;//ID of sound that plays when teleporting between portals occurs.
const int SPR_PORTAL_TELEPORT = 22;//Sprite that renders on portals when teleporting occurs.
//Oracle of Hours Portal Cube Portals.
//Appear on screen in pairs of combos of the same CSet. If enemy steps on one of these combos, he will be teleported to other with the same CSet. If Link has Portal Cube, he can use portals to teleport as well.
//Requires ghost.zh
//1. Set up Portal Cube item in Item Editor. No scripts needed.
//2. Set I_PORTAL_CUBE constant to ID of item from step 1.
//3. Set up combo with CT_PORTAL combo type (Script 1 by default).
//4. Check out other constants inside script file.
//5. Import and compile the script. 1 FFC script slot assigned.
//6. Place portal combos from step 3 on screen. Make sure that each pair of portals have unique CSet, and each CSet appears on portal combos exactly twice. For instance there are 2 CSet 5 combos, 2 CSet 7 combos, 2 CSet 8 combos, etc.
//Place invisible FFC on this screen. Assign FFC script to it. Also you need to set D0 argument to define cooldown bwtween enemy teleports.
ffc script PortalCubePortal{
void run(int cooldown){
int cmb = -1; //Combo position on screen used to track enemy or Link position. Combos are listed internally left to right, starting from top-left corner and ending at bottom-right corner.
int dest_pos = -1;//Combo position on screen used to define teleporting destination.
npc n;// This NPC pointer has been declared beforehand to be reused, instead of declaring new pointer every cycle during iterations.
lweapon poof;//Same goes to lweapon pointer used for creating teleporting particle effect (SPR_PORTAL_TELEPORT)
while(true){
if (cooldown>0)cooldown--;//If cooldown timer is not expired, decrement it.
cmb = ComboAt(CenterLinkX(), CenterLinkY()); //Check Link`s combo position via center of his hitbox.
if (Screen->ComboT[cmb]!=CT_PORTAL) dest_pos = -1;//Clear destination position, if Link has stepped onto non-portal combo.
if (Screen->ComboT[cmb]==CT_PORTAL && (Link->Item[I_PORTAL_CUBE] || I_PORTAL_CUBE==0) && cmb!=dest_pos && !ComboFI(cmb, CF_PORTAL_ONEWAY)){
//Teleport only if it`s portal combo, it`s not fglagged as one-way portal exit (CF_PORTAL_ONEWAY) and only if Link has Portal Cube item. Also Link cannot teleport from portal that was used as Link`s recent teleporting destination.
dest_pos = FindAnotherPortal (cmb);//Define teleporting destination. See FindAnotherPortal function.
if (dest_pos>0){//If there is valid teleporting destination, perform the teleportation.
Game->PlaySound(SFX_PORTAL); //Play teleport sound.
poof = CreateLWeaponAt(LW_SPARKLE, Link->X, Link->Y);//
poof->UseSprite(SPR_PORTAL_TELEPORT);// Create particle effect at source position.
poof->CollDetection=false; //
Link->X = ComboX(dest_pos);//Change Link`s coordinates
Link->Y = ComboY(dest_pos);//
poof = CreateLWeaponAt(LW_SPARKLE, Link->X, Link->Y);//
poof->UseSprite(SPR_PORTAL_TELEPORT);// Create particle at destination position.
poof->CollDetection=false;
}
}
if (cooldown==0){//enemy teleporting occurs only if cooldown is 0.
for (int i=1; i<=Screen->NumNPCs();i++){//Iterate all enemies on screen.
n = Screen->LoadNPC(i);//Load enemy data
cmb = ComboAt(CenterX(n), CenterY(n));//Check composition at enemy`s current coordinates.
if (Screen->ComboT[cmb]==CT_PORTAL && !ComboFI(cmb, CF_PORTAL_ONEWAY)){
//Unlike Link, enemies don`t need Portal Cube or similar items to teleport.
dest_pos = FindAnotherPortal (cmb);//Check/define destination position.
if (dest_pos>0){//If there is valid teleporting destination, perform the teleportation.
Game->PlaySound(SFX_PORTAL);//Play teleport sound.
poof = CreateLWeaponAt(LW_SPARKLE, n->X, n->Y);//
poof->UseSprite(SPR_PORTAL_TELEPORT);//Create particle at source position.
poof->CollDetection=false; //
SetEnemyProperty(n, ENPROP_X, ComboX(dest_pos));//Changing enemy coordinates by writing new coordinates directly work well with engine enemies.
SetEnemyProperty(n, ENPROP_Y, ComboY(dest_pos));//But has buggy consequences with "ghosted enemies" that use ghost.zh library for scripted behaviour.
poof = CreateLWeaponAt(LW_SPARKLE, n->X, n->Y);//
poof->UseSprite(SPR_PORTAL_TELEPORT);//Create particle effect at destination position.
poof->CollDetection=false;//
dest_pos=-1;// Clear destination position. Otherwise Link cannot teleport by stepping on portal used by enemy as destination.
cooldown = this->InitD[0];//Set cooldown timer to avoid repeated teleports.
}
}
}
}
Waitframe();
}
}
}
//Returns combo position of another portal with the same CSet as given one. There must be exactly two portal combos with the same CSet.
int FindAnotherPortal (int cmb){
int curcset = Screen->ComboC[cmb];//Get the CSet of the given portal combo.
for (int i=0;i<176;i++){//Iterate all combos.
if (i==cmb) continue;//Don`t count the same combo twice.
if (Screen->ComboT[i]!=CT_PORTAL) continue;//Not a portasl combo. Continue.
if (Screen->ComboC[i]!=curcset) continue;//Different CSet. Skip this one.
return i;//If combo passes all checks, it`s a valis portal teleport destination. Return combo position into main FFC script.
}
return -1;//If no other portal combos with the same CSet as given one, return -1, which will prevent teleportation into The VOID...
}