Jump to content

Photo

Combining global script issues


  • Please log in to reply
7 replies to this topic

#1 HylianGlaceon

HylianGlaceon

    Magus

  • Members
  • Location:Whatever dimension is between Sinnoh and Hyrule...

Posted 07 March 2011 - 02:07 AM

Basically I need to combine this:

CODE
global script ActiveScript
{
    void run()
    {
        while(true)
        {
            for(int i = 1; i <= Screen->NumLWeapons(); i++)
            {
                lweapon lwp = Screen->LoadLWeapon(i);
                if(lwp->Misc[CUSTOMBOMB_MISC] == 1)
                {
                    Link->InputB = false;
                    if(lwp->ID == LW_BOMBBLAST && Screen->ComboF[ComboAt(lwp->X,lwp->Y)] == CUSTOMBOMB_SECRETFLAG)
                        Screen->TriggerSecrets();
                }
            }
            Waitframe();
        }
    }
}


With this:

CODE
global script Slot_2{
    void run(){
        while(true){
            //Call Bombchu functions
            if(UseBChu > 0) Bombchu();
            if(UseBombArrow > 0) BombArrow();
                        if(PegasusDash) PegasusBoots();
            
            StoreHP = Link->HP;
        Waitframe();
        }
    }


And have it not crash the game when it loads. Anyone have any clue on how to combine these? I've tried a bunch of times and it will not work at all..

#2 Gleeok

Gleeok

    It's dangerous to dough alone, bake this.

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

Posted 07 March 2011 - 02:29 AM

[quote name='HylianGlaceon' date='Mar 6 2011, 11:07 PM' post='695237']
Basically I need to combine this:

CODE

void doThing1()
{
            for(int i = 1; i <= Screen->NumLWeapons(); i++)
            {
                lweapon lwp = Screen->LoadLWeapon(i);
                if(lwp->Misc[CUSTOMBOMB_MISC] == 1)
                {
                    Link->InputB = false;
                    if(lwp->ID == LW_BOMBBLAST && Screen->ComboF[ComboAt(lwp->X,lwp->Y)] == CUSTOMBOMB_SECRETFLAG)
                        Screen->TriggerSecrets();
                }
            }
}

void doThing2()
{
            //Call Bombchu functions
            if(UseBChu > 0) Bombchu();
            if(UseBombArrow > 0) BombArrow();
                        if(PegasusDash) PegasusBoots();
            
            StoreHP = Link->HP;

}


global script globalScriptSlot2
{
    void run()
    {
        while(true)
        {
            doThing1();
            doThing2();
            Waitframe();
        }
    }
}


Try this.
If you posted the global scripts in their entirety this should work fine, if not then it likely won't.


#3 symbiote01

symbiote01

    Doyen(ne)

  • Members
  • Real Name:Doug
  • Location:WA

Posted 07 March 2011 - 02:49 AM

Assuming you have all the variables and such set up, this is what you need, right?
CODE
global script Slot_2{
    void run(){
        while(true){
        //Call Bombchu function
            if(UseBChu > 0) Bombchu();
        //Call BombArrow function
            if(UseBombArrow > 0) BombArrow();
        //Call PegasusDash function
            if(PegasusDash) PegasusBoots();
        //Custom Bomb check for secrets
            for(int i = 1; i <= Screen->NumLWeapons(); i++){
                lweapon lwp = Screen->LoadLWeapon(i);
                if(lwp->Misc[CUSTOMBOMB_MISC] == 1){
                    Link->InputB = false;
                    if(lwp->ID == LW_BOMBBLAST && Screen->ComboF[ComboAt(lwp->X,lwp->Y)] == CUSTOMBOMB_SECRETFLAG) Screen->TriggerSecrets();
                }
            }
        //Other functions
            StoreHP = Link->HP;
            Waitframe();
        }
    }
}


You know, I get error messages from allegro.log when there's no lweapon on the screen with this script (or something similar). My solution is to add another tier, making it only check if there is actually a lweapon on the screen, like this:
CODE
//Custom Bomb check for secrets
if(Screen->NumLWeapons() > 0){
    for(int i = 1; i <= Screen->NumLWeapons(); i++){
        lweapon lwp = Screen->LoadLWeapon(i);
        if(lwp->Misc[CUSTOMBOMB_MISC] == 1){
            Link->InputB = false;
            if(lwp->ID == LW_BOMBBLAST && Screen->ComboF[ComboAt(lwp->X,lwp->Y)] == CUSTOMBOMB_SECRETFLAG) Screen->TriggerSecrets();
        }
    }
}

Edited by symbiote01, 07 March 2011 - 03:03 AM.


#4 HylianGlaceon

HylianGlaceon

    Magus

  • Members
  • Location:Whatever dimension is between Sinnoh and Hyrule...

Posted 08 March 2011 - 03:19 AM

Gleeok: Yes, it works perfectly now, I'm testing and all the functions work too, so I should be able to use this, thanks!!

symbiote01: What exactly does the tiered script do? lucas92 made the whole custom bomb thing in the other topic. Right now the only downside I have is that the properties of the bomb is pre-set (like if I wanted to change the speed or frames of the bomb), but it's still very usable for me. There's also an Item Script attached to the global script I didn't post for it to work in the other topic.

#5 symbiote01

symbiote01

    Doyen(ne)

  • Members
  • Real Name:Doug
  • Location:WA

Posted 08 March 2011 - 10:20 AM

QUOTE(HylianGlaceon @ Mar 8 2011, 12:19 AM) View Post

symbiote01: What exactly does the tiered script do? lucas92 made the whole custom bomb thing in the other topic. Right now the only downside I have is that the properties of the bomb is pre-set (like if I wanted to change the speed or frames of the bomb), but it's still very usable for me. There's also an Item Script attached to the global script I didn't post for it to work in the other topic.

The differences between Gleeok's and my versions are essentially unimportant. He turned your two global scripts (global script ActionScript and global script slot_2) into two functions (doThing1 and doThing2), then created a third script (global script globalScriptSlot2) and called his two functions. The advantage to his method is that if you ever needed the script to run either of those two functions somewhere else, you'd just have to call the function. In function doThing1() this makes sense, as it deals with one thing- checking the custom bomb (that you have an item script for, I'm sure) to see if it blew up on a specific tile flag. In function doThing2(), however, it makes less sense, as it handles a bunch of other items mostly with other function calls (Bombchu(),BombArrow(), and PegasusBoots()), and one integer (StoreHP).

My method just shuffled the two scripts together, though I did take some time to organize and annotate it a little. The only thing my 'tiered script' (which should replace the section in the other script annotated '//Custom bomb check for secrets') does is keep Allegro.log happy when there are no lweapons on the screen. In the original version, whenever the for(i = 1; i <= Screen->NumLWeapons(); i++) loop is called and there are no lweapons on the screen, it would produce an error in Allegro.log. What that for() loop is actually saying is, "some number 'i' starts at one; 'i' is less than or equal to the number of lweapons on the screen; 'i' increments up by one every time this loop repeats." As long as all of that is true, it continues to run the loop.

The error happens because the value of 'i' in the loop (Screen->LoadLWeapon(i)) would be zero if there were no lweapons on the screen, which breaks the loop, which assumes that there is always at least one lweapon present (i = 1).
My fix is to only run the function if there is actually an lweapon on the screen, thus preventing the error. It also keeps the script from running when it doesn't need to- in frames where there are no lweapons on the screen, it skips the check.
The other way to fix it is to start the for() loop with 'i = 0', which would always be true (there are always zero or more lweapons on the screen). The downsides of this method: one more repeat of the loop (to account for i=0) every time it runs, and the fact that it now has to run every frame of the game. It's a tiny, miniscule, insignificant burden, but if you put enough tiny burdens on the system, starts to add up.

Edited by symbiote01, 08 March 2011 - 10:27 AM.


#6 Gleeok

Gleeok

    It's dangerous to dough alone, bake this.

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

Posted 10 March 2011 - 09:11 PM

QUOTE(symbiote01 @ Mar 8 2011, 07:20 AM) View Post

The error happens because the value of 'i' in the loop (Screen->LoadLWeapon(i)) would be zero if there were no lweapons on the screen, which breaks the loop, which assumes that there is always at least one lweapon present (i = 1).
My fix is to only run the function if there is actually an lweapon on the screen, thus preventing the error. It also keeps the script from running when it doesn't need to- in frames where there are no lweapons on the screen, it skips the check.
The other way to fix it is to start the for() loop with 'i = 0', which would always be true (there are always zero or more lweapons on the screen). The downsides of this method: one more repeat of the loop (to account for i=0) every time it runs, and the fact that it now has to run every frame of the game. It's a tiny, miniscule, insignificant burden, but if you put enough tiny burdens on the system, starts to add up.


This shouldn't be necessary. The evaluation of a for loop happens before it is run so if there are no weapons it should break.

Also since you brought up optimizing, icon_wink.gif

The normal approach is to use a function call once, then just look up whatever value that amounted to from the local stack. ie:

CODE

for(int i = 1; i <= Screen->NumLWeapons(); i++) //iteration evaluation results in a function call
//...

for(int i = Screen->NumLWeapons(); i > 0; --i) //comparision of 'i' and constant each iter.


edit: you can also do this:
CODE

int numlw = Screen->NumLWeapons();
for(int i = 1; i <= numlw; i++)
//..durp



#7 Saffith

Saffith

    IPv7 user

  • Members

Posted 11 March 2011 - 01:46 AM

QUOTE(Gleeok @ Mar 10 2011, 09:11 PM) View Post
edit: you can also do this:
CODE

int numlw = Screen->NumLWeapons();
for(int i = 1; i <= numlw; i++)
//..durp

I wonder if that really is faster, with the way built-in functions work... Screen->NumLWeapons() becomes simply LWPNCOUNT in ASM, and that's just a single line to interpret.

#8 Gleeok

Gleeok

    It's dangerous to dough alone, bake this.

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

Posted 11 March 2011 - 02:38 AM

QUOTE(Saffith @ Mar 10 2011, 10:46 PM) View Post

I wonder if that really is faster, with the way built-in functions work... Screen->NumLWeapons() becomes simply LWPNCOUNT in ASM, and that's just a single line to interpret.


Doesn't get_arg() or whatever get to case: LWPNCOUNT and call something like x[]->get_num_of_weapons() (I forget the exact name icon_razz.gif) which is stored in a std::map? ..

Hmm.. I guess if both LWPNCOUNT returned a simple container->size(), and the compiler inlines it (like it should) then there wouldn't be much of a difference besides a safety check. I do know that there is tons of room for optimization in the generated bytecode though.

Maybe zc 3.0 gets a JIT compiler! :-P


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users