It calculates the position by making an lweapon in front of Link with the inFrontLink() function (I do use the lweapon for the sprite and not just its location btw)... except that it actually appears right behind Link (at his position). Why is this?
//int args[1] = {duration}
//if(!CountFFCsRunning(ffcScriptNum))
//RunFFCScript(ffcScriptNum, args);
const int WPS_ICESPARKLE = 92; //Sprite of ice sparkle
const int WPS_ICEMELT = 106;
const int icicleCombo = 35528; //Icicle combo that forms on land (MUST BE 8-BIT)
const int iceTile = 53256; //Tile to draw over water
const int noIceFlag = 96; //Flag that prevents freezing combos (no enemies)
ffc script iceWall{
void run ( int duration ){
bool onLand = false; //Layer to restore to (0 for ice, 2 for icicle)
int oldCombo; //Data of previous combo
lweapon sparkle = NextToLink(LW_SPARKLE, 0); //Make a sparkle lweapon
Waitframe(); //Wait a frame - if it is out of bounds it will become invalid
if ( !sparkle->isValid() || Screen->isSolid(sparkle->X+8, sparkle->Y+8) || ComboFI(sparkle->X+8, sparkle->Y+8, noIceFlag)) return; //If combo is out of bounds or combo in front of Link is solid or combo has "no ice" flag, quit
int inFront = ComboAt (sparkle->X+8, sparkle->Y+8); //Otherwise find combo under the sparkle
sparkle->UseSprite(WPS_ICESPARKLE);
sparkle->X = ComboX(inFront);
sparkle->Y = ComboY(inFront); //Draw the sparkle on the combo
if(IsPit(inFront)) return; //If it's a pit, exit
if(IsWater(inFront)){ //If sparkle is over water,
oldCombo = Screen->ComboT[inFront]; //Save layer 0 data
Screen->ComboT[inFront] = CT_NONE; //Set combo to walkable ice
}
else{ //Otherwise if on land
oldCombo = GetLayerComboD(1, inFront); //Save layer 2 data
onLand = true;
SetLayerComboD(1, inFront, icicleCombo); //Set layer 2 to icicle
}
Game->Counter[CR_RUPEES] = oldCombo;
Game->PlaySound(SFX_ICE); //Play ice SFX
for (; duration > 0; duration-- ){ //Wait for spell to wear off
if ( (Link->X < 4 && Link->InputLeft)
|| (Link->X > 230 && Link->InputRight)
|| (Link->Y < 4 && Link->InputUp)
|| (Link->Y > 150 && Link->InputDown) //If Link walks towards the edge of the screen
|| !Link->HP //Or dies
|| isWarp(ComboAt(Link->X+8, Link->Y+8)) //Or stands on a warp
|| isWarp(ComboAt(Link->X+8+InFrontX(Link->Dir, 0), Link->Y+8+InFrontY(Link->Dir, 0)))
|| isWarp(ComboAt(Link->X+8+InFrontX(Link->Dir, 4), Link->Y+8+InFrontY(Link->Dir, 4))) //Or is in front of a warp
|| (Link->Dir == DIR_UP && isWarp(ComboAt(Link->X+8, Link->Y+InFrontY(Link->Dir, 4)))) //Or is walking into a house/cave/etc
) duration = -1; //Exit the loop and let the script end
if ( !onLand ) Screen->FastTile(0, ComboX(inFront), ComboY(inFront), iceTile, 7, 128 ); //Draw the ice tile rather than changing combo data - handles different water colors
if ( duration == 10 || duration == -1 ){ //When 10 frames remain or loop quits early
sparkle = CreateLWeaponAt(LW_SPARKLE, ComboX(inFront), ComboY(inFront)); //Make a melting sprite as it is about to vanish
sparkle->UseSprite(WPS_ICEMELT);
}
Waitframe(); //Otherwise continue the game
}
if ( onLand )
SetLayerComboD(1, inFront, oldCombo); //Restore old combo afterwards
else
Screen->ComboT[inFront] = oldCombo;
}
}
bool isWarp(int loc){
int type = Screen->ComboT[loc];
return type == CT_DIVEWARP || type == CT_DIVEWARPB || type == CT_DIVEWARPC || type == CT_DIVEWARPD || type == CT_PIT || type == CT_PITB || type == CT_PITC || type == CT_PITD || type == CT_STAIR || type == CT_STAIRB || type == CT_STAIRC || type == CT_STAIRD || type == CT_STAIRR || type == CT_SWIMWARP || type == CT_SWIMWARPB || type == CT_SWIMWARPC || type == CT_SWIMWARPD;
}
If you help me fix this, I might let you use my script for yourself
UPDATE: It now actually works. It's not perfect yet, though.
UPDATE 2: Has limited checking for exit by warp, and has animations for creating/melting ice
Edited by MoscowModder, 24 May 2012 - 10:18 PM.