Jump to content

Photo

ffcscript.zh


  • Please log in to reply
26 replies to this topic

#1 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 30 June 2011 - 04:28 PM

As of RC2, ffc->Script is writable. I made a header file with a few functions to take advantage of this. Specifically, these are for using FFCs as generic script vehicles. Nothing fancy, but I figure it'll be handy.

ffcscript.zh 1.1.1


The most obvious use of this is for items; most of them can launch an FFC script now instead of having to be worked into the global script. As an example, here's a simple item that homes in on a random enemy and explodes when it gets close enough or the item is used again:

 


item script HomingBomb_item
{
    void run(int sprite)
    {
        int ffcScriptName[]="HomingBomb_ffc";
        int ffcScriptNum=Game->GetFFCScript(ffcScriptName);
        int ffcID=FindFFCRunning(ffcScriptNum);
        
        if(ffcID==0) // No bombs active
        {
            if(Screen->NumNPCs()==0)
                Quit();
            
            int args[]={this->Power, sprite};
            RunFFCScript(ffcScriptNum, args);
        }
        else // Detonate
        {
            ffc f=Screen->LoadFFC(ffcID);
            f->Misc[0]=1;
        }
    }
}

ffc script HomingBomb_ffc
{
    void run(int damage, int sprite)
    {
        if(Screen->NumNPCs()==0)
            Quit();
        
        // Create the bomb, pick a random target
        lweapon bomb=Screen->CreateLWeapon(LW_SCRIPT1);
        npc target=Screen->LoadNPC(Rand(Screen->NumNPCs())+1);
        
        bomb->X=Link->X;
        bomb->Y=Link->Y;
        bomb->CollDetection=false;
        bomb->UseSprite(sprite);
        bomb->Angular=true;
        bomb->Step=200;
        
        // Aim toward the enemy; detonate the bomb when it reaches the enemy,
        // the enemy dies, or this->Misc[0] is set
        while(target->isValid() && this->Misc[0]==0 && !Collision(bomb, target))
        {
            bomb->Angle=ArcTan(target->X-bomb->X, target->Y-bomb->Y);
            Waitframe();
        }
        
        // Detonate
        lweapon blast=Screen->CreateLWeapon(LW_BOMBBLAST);
        blast->Damage=damage;
        blast->X=bomb->X;
        blast->Y=bomb->Y;
        bomb->DeadState=0;
    }
}


#2 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 01 July 2011 - 08:29 AM

QUOTE(Saffith @ Jun 30 2011, 03:28 PM) View Post

As of RC2, ffc->Script is writable. I made a header file with a few functions to take advantage of this. Specifically, these are for using FFCs as generic script vehicles. Nothing fancy, but I figure it'll be handy.

Download
The most obvious use of this is for items; most of them can launch an FFC script now instead of having to be worked into the global script. As an example, here's a simple item that homes in on a random enemy and explodes when it gets close enough or the item is used again:

CODE
item script HomingBomb_item
{
    void run(int ffcScriptNum, int sprite)
    {
        int ffcID=FindFFCRunning(ffcScriptNum);
        
        if(ffcID==0) // No bombs active
        {
            if(Screen->NumNPCs()==0)
                Quit();
            
            int args[8]={this->Power, sprite};
            RunFFCScript(ffcScriptNum, args);
        }
        else // Detonate
        {
            ffc f=Screen->LoadFFC(ffcID);
            f->Misc[0]=1;
        }
    }
}

ffc script HomingBomb_ffc
{
    void run(int damage, int sprite)
    {
        if(Screen->NumNPCs()==0)
            Quit();
        
        // Create the bomb, pick a random target
        lweapon bomb=Screen->CreateLWeapon(LW_SCRIPT1);
        npc target=Screen->LoadNPC(Rand(Screen->NumNPCs())+1);
        
        bomb->X=Link->X;
        bomb->Y=Link->Y;
        bomb->CollDetection=false;
        bomb->UseSprite(sprite);
        bomb->Angular=true;
        bomb->Step=200;
        
        // Aim toward the enemy; detonate the bomb when it reaches the enemy,
        // the enemy dies, or this->Misc[0] is set
        while(target->isValid() && this->Misc[0]==0 && !Collision(bomb, target))
        {
            bomb->Angle=ArcTan(target->X-bomb->X, target->Y-bomb->Y);
            Waitframe();
        }
        
        // Detonate
        lweapon blast=Screen->CreateLWeapon(LW_BOMBBLAST);
        blast->Damage=damage;
        blast->X=bomb->X;
        blast->Y=bomb->Y;
        bomb->DeadState=0;
    }
}



So just what is this for then? I don't understand.

#3 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 01 July 2011 - 09:56 AM

Simply put, it's for making one script run another script. An item can run an FFC script instead of being integrated with the global script. The global script can set up FFCs automatically whenever certain things appear on the screen. FFCs can start up helper scripts automatically, even deciding which one to use at run time.

#4 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 01 July 2011 - 11:37 AM

QUOTE(Saffith @ Jul 1 2011, 08:56 AM) View Post

Simply put, it's for making one script run another script. An item can run an FFC script instead of being integrated with the global script. The global script can set up FFCs automatically whenever certain things appear on the screen. FFCs can start up helper scripts automatically, even deciding which one to use at run time.


Got it, thanks.

#5 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 03 July 2011 - 07:25 AM

So, Saffith, do we need to include ZH files not included in zc with or quest or what?

#6 MoscowModder

MoscowModder

    Sometimes lurking. Rarely posting.

  • Members
  • Location:Wisconsin

Posted 03 July 2011 - 08:57 AM

No. The ZH files referenced in the script files are included in the quest file itself. No need to make all your players get a copy of this file.

#7 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 03 July 2011 - 09:07 AM

I don't understand how the run RunFFCScript function works. Can someone explain that one to me?

EDIT: Took me two hours but I figured out eventually.

Edited by blackbishop89, 03 July 2011 - 11:56 AM.


#8 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 09 July 2011 - 11:01 AM

QUOTE(blackbishop89 @ Jul 3 2011, 08:07 AM) View Post

I don't understand how the run RunFFCScript function works. Can someone explain that one to me?

EDIT: Took me two hours but I figured out eventually.


Is there anyway to recycle the ffcs that are not in use?

#9 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 13 July 2011 - 12:29 AM

It'll reuse FFCs whose scripts have finished if you don't change their combos. I didn't include a function to find a free FFC, but if you want to do that:

if(theFFC->Script==0 && (theFFC->Data==0 || theFFC->Data==FFCS_INVISIBLE_COMBO))

If that's true, the FFC isn't in use.

#10 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 16 August 2011 - 02:03 PM

Saffith how come you use integer arrays instead of float arrays? InitD is a float array which is why I'm asking.

#11 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 12 June 2012 - 08:23 AM

Any chance you could update this so the argument array for RunFFCScript() uses floats instead of integers. icon_smile.gif

#12 Gleeok

Gleeok

    It's dangerous to dough alone, bake this.

  • Members
  • Real Name:Pillsbury
  • Location:Magical Land of Dough

Posted 12 June 2012 - 06:25 PM

QUOTE(blackbishop89 @ Jun 12 2012, 06:23 AM) View Post

Any chance you could update this so the argument array for RunFFCScript() uses floats instead of integers. icon_smile.gif


In Zscript there are no real "real" numbers; instead they all have 4 decimal places of precision, so floats and integers are exactly the same. Not my design call, but that's how it works. icon_smile.gif

#13 Mero

Mero

    Touch Fluffy Tail

  • Banned
  • Real Name:Tamamo No Mae
  • Location:Rainbow Factory

Posted 12 June 2012 - 06:28 PM

QUOTE(Gleeok @ Jun 12 2012, 05:25 PM) View Post

In Zscript there are no real "real" numbers; instead they all have 4 decimal places of precision, so floats and integers are exactly the same. Not my design call, but that's how it works. icon_smile.gif


You are the bringer of good news. Gleeok, you truly are. icon_smile.gif

#14 ShadowTiger

ShadowTiger

    The Doctor Is In

  • Members

Posted 04 December 2012 - 05:02 PM

Strictly for the sake of education and theory, how would one duplicate the effect of a red potion using this script, please? I am quite intrigued by its use, though mystified, and not necessarily in all the fun ways. Always an adventure, really.

#15 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 04 December 2012 - 06:15 PM

That's either easy or nearly impossible, depending on whether you want to freeze the screen and what would need frozen if so.

Restoring HP and adding a replacement item is simple enough:
CODE
item script Potion_item
{
    void run(int scriptID, int replacementItem)
    {
        if(CountFFCsRunning(scriptID)>0)
            return;
        RunFFCScript(scriptID, NULL);
        Link->Item[replacementItem]=true;
    }
}

ffc script Potion_ffc
{
    void run()
    {
        while(Link->HP<Link->MaxHP)
        {
            Link->HP++;
            Waitframe();
        }
        
        this->Data=0;
    }
}

You could do pretty much the same thing with Game->DCounter[CR_LIFE], though.

If you also want to freeze the screen while it's running, that may be difficult or impossible depending on what else is going on. It would almost certainly be easier to use the global script instead.

What you'd have to do is set the FFC to a screen freeze combo. Thing is, you can only use the non-FFC freeze, or the script won't run. Any other FFCs will keep going, and even using an FFC freeze combo wouldn't stop the global script. Of course, if there are no other scripts to worry about, that'll do it. Otherwise, you need a way to suspend the others. You could do that with a blocking Waitframe replacement, something like this:
CODE
bool suspendScripts;

void BlockingWaitframe()
{
    do
    {
        Waitframe();
    } while(suspendScripts);
}

void SuspendScripts()
{
    suspendScripts=true;
}

void ResumeScripts()
{
    suspendScripts=false;
}

You'd have to replace every Waitframe in every script with BlockingWaitframe, except you'd use just Waitframe in between calls to SuspendScripts and ResumeScripts. You'd also want to put a call to ResumeScripts at the start of the active global script.

The potion script, then:
CODE
const int C_SCREENFREEZE=12345;

ffc script Potion_ffc
{
    void run()
    {
        this->Data=C_SCREENFREEZE;
        SuspendScripts();
        while(Link->HP<Link->MaxHP)
        {
            Link->HP++;
            Waitframe();
        }
        ResumeScripts();
        this->Data=0;
    }
}


But even doing all that won't stop non-scripted FFC movement. To deal with that, you'd have to use the global script to prevent it, possibly by remembering each one's position and restoring it each frame.


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users