Jump to content

Photo

My Script Wishlist and Your Script Ideas


  • Please log in to reply
242 replies to this topic

#151 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 19 August 2015 - 08:22 PM

Misc Room Script Flags- I know that they exist and even that there are 5 types. Here's the only one I know of.

Screen->Flags[SF_MISC]&0x008;//Screen flag Script 2
So, what are the other four? How can they be used most effectively?

if ((Screen->Flags[SF_MISC] & 0x02) != 0)
That's how you check those. Some of the parentheses seem redundant but they're actually important. Each category of screen flags is actually a single number, and you need to use bitwise operations to read the individual flags. 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40 are the 7 flags for the Misc. category.

 

Mysterious Script Crashes- Some times, for no apparent reason; scripts activate when they shouldn't. At others, they don't work when they should (and have up to that point). When no change has been made to the scripts in the meantime, how can the source of these errors be discovered?

When you say "crash", do you mean that ZC hangs with music still playing, or does the entire program actually just crash out? The former sounds like an infinite loop lacking a Waitframe, but I couldn't say anything about the latter.
 

Other Movement Patterns- I'm familiar enough with the various Ghost.zh commands to figure out how to use each one. However, other movement patterns have been suggested; for example a sine wave or an infinity loop.  Another pattern I don't know how to mimic is that of the common Wizzrobe. So how can these be done? And what are some other movement patterns?

Any movement pattern you care to create can be made by just directly adjusting Ghost_X and Ghost_Y every frame.
 
Ghost_X = t*Cos(t);
Ghost_Y = t*Sin(t);
t++;
This is a simple spiral outward, for example.

 

Detecting If All Switches/FFCS Have Been Activated- One script that I had provided for me does this. I'm trying to refine another (the one utilized by the script you'll see in the Multiple Songs/Ocarinas topic) where when all of the ffcs running that script are activated; then other secrets, triggers, ffcs or whatever is activated as well.
 
This script is probably one of my most revolutionary designs, since It easily allows you to create up to 8 secrets on screen that can be triggered permanently and 15 others that can be set off temporarily; opens up extra secret flags; bypasses the whole secret combo setup routine and generally allows a greater amount of variety in the puzzle setup available to the player. So, naturally I want it to be the best it can be.

If your secrets/flags are just binary state things, you could fit a lot more of them on a single screen by using bitwise operations. Instead of having 8 Screen->D variables to work with, you could trigger flags in each one, giving you something like 17 * 8 binary toggles.

I don't know much of anything about Tango, sorry.

#152 ywkls

ywkls

    Master

  • Members

Posted 19 August 2015 - 10:49 PM

 

When you say "crash", do you mean that ZC hangs with music still playing, or does the entire program actually just crash out? The former sounds like an infinite loop lacking a Waitframe, but I couldn't say anything about the latter.

 

 

In this case, the script that I was referring to was the one I'm using for the Pegasus Boots. I've have more than one problem with it occur. One time, it seemed to activate before I got the item. (I've never been able to reproduce that, so I don't have a clue why it happened.) Currently, they just seem to have stopped working entirely. I reload my script file, loaded everything back into slots again; but the game ignored it. 

 

The thing is, I've had this code for a while and used it extensively in the game up to this point. So you can imagine my surprise when I loaded the game and equipped them and pressing the button did nothing.

 

Another example of mysterious script crashes was a script I wrote to create an npc who would handle a minigame (without resorting to tango). I used the basic altnpc script I created to start with, then told it to play one message if you talked to it; a second message if you had enough rupees then warp you to the game, a third message if you didn't have enough rupees and a fourth message once you'd beaten the game.

 

Currently, this script warps you instantly when you talk to the guy with enough rupees and plays the right string whenever you've beaten the game. But the other stuff is basically ignored.

 

If I come up with any more examples, I'll post them so I can get some insight on the issue.


Edited by ywkls, 19 August 2015 - 10:49 PM.


#153 ywkls

ywkls

    Master

  • Members

Posted 21 August 2015 - 06:59 PM

Well, I figured out one of my mysterious script crash issues. It was an order of operations thing, where commands set after others weren't being run, even though they were supposed to. This got me thinking about a question I've never been able to pin down...

 

What Commands Disrupt Order of Operations?- I know (generally) how break, continue and Quit() work. I also know that return is designed to create a value that can then be fed into another sections of the program. But what other commands can disrupt your scripts? For example, in this case it was a hole/lava script that warped Link to another screen. It set a global bool to true, but because that was never set back to false until after the warp was over, the game ignored that command.

 

Knowing this would help prevent these script conflicts and allow me to more easily resolve issues of this sort on my own.

 

Second point, Screen->D register carryover. I know about the command, Game->SetDMapScreenD(Dmap, screen, register, value) but I'm having some trouble implementing it. Here's the script in question I'm trying to incorporate it into.

// Section 16. Permanent Tiered Secrets by Moosh

//Permanent Tiered Secrets Script
//D0: The Screen->D (0-7) to use to store the number of triggered secrets on the screen
//D1: If you want to use a layered combo to detect secrets being triggered, set this to the layer number
//D2: In an infinite looping tiered secret, set this to the number of states the secret can have
ffc script PermanentTieredSecrets{
	void run(int D, int Layer, int NumStates, bool carryover, int Dmap, int screen){
		//Triggers the number of screen secrets stored in Screen->D when you enter the screen
		if(Screen->D[D]>0){
			for(int i=0; i<Screen->D[D]; i++){
				Screen->TriggerSecrets();
			}
		}
		//Saves the combo position and combo under the FFC
		int ComboPos = ComboAt(this->X+8, this->Y+8);
		int Combo;
		if(Layer>0)
			Combo = GetLayerComboD(Layer, ComboPos);
		else if(Layer==0)
			Combo = Screen->ComboD[ComboPos];
		while(true){
			//Detects if the combo under the FFC changes and increases Screen->D
			if(Layer>0&&GetLayerComboD(Layer, ComboPos)!=Combo){
				Combo = GetLayerComboD(Layer, ComboPos);
				Screen->D[D]++;
			}
			else if(Layer==0&&Screen->ComboD[ComboPos]!=Combo){
				Combo = Screen->ComboD[ComboPos];
				Screen->D[D]++;
			}
			//Wraps Screen->D if NumStates is set, otherwise caps Screen->D at 100
			if(NumStates>0&&Screen->D[D]>=NumStates)
				Screen->D[D] -= NumStates;
			else if(NumStates==0&&Screen->D[D]>100){
				Screen->D[D] = 100;
			}
                        if(carryover)Game->SetDMapScreenD(Dmap, screen, D, Screen->D[D]);
			Waitframe();
		}
	}
}

Basically, the original script allowed you to permanently set screen secrets. But the adjusted version doesn't seem to want to carryover the correct value. Is this because I have the order of the arguments wrong? One explanation I read suggested that it should be Game->SetDMapScreenD(Dmap, screen, Screen->D[D], D).

 

Also, the screen number; I know it has to be decimal... but is that the decimal notation on the DMap or the overall map?

 

Example: In dmap, screen number to be adjusted is 27 but in overall map, it is 2F.

 

Then there are also some relatively simplistic scripts that don't seem to work at all for me. For example, I set up one script that was just supposed to tell if a normal or locked chest had been opened on that screen; then increase a counter. But it doesn't seem to do anything. Another was supposed to add to a counter when I got an item and a message played, but occasionally; it had added more than one to this counter even though I only got one item!

 

Each and every time I think I've gotten this whole scripting thing down, I encounter something of this sort that shows that I still have plenty of blind spots. I've looked over all of the tutorials that I can find rather extensively and finally broke down and read through Zscript.txt, but I still have trouble grasping things others find easy.

 

So, I'm going to continue posting here from time to time as I resolve these issues (or don't) and develop new scripts.


Edited by ywkls, 06 September 2015 - 09:51 PM.


#154 ywkls

ywkls

    Master

  • Members

Posted 21 August 2015 - 10:19 PM

This is why I'm glad I read Zscript.txt- the trace function makes resolving my issues phenomenally easier. Now, I've seen several requests for a way to do this; so I'm going to post my results here so anybody who wants to do this can.

 

Carryover Permanent Tiered Secrets- based on script by Moosh

And many people said it couldn't be done...


Edited by ywkls, 06 September 2015 - 09:29 PM.


#155 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 21 August 2015 - 10:47 PM

What Commands Disrupt Order of Operations?- I know (generally) how break, continue and Quit() work. I also know that return is designed to create a value that can then be fed into another sections of the program. But what other commands can disrupt your scripts? For example, in this case it was a hole/lava script that warped Link to another screen. It set a global bool to true, but because that was never set back to false until after the warp was over, the game ignored that command.

FFC scripts stop running as soon as you leave the screen it's on. So you need to be careful with warps. Another one that isn't obvious is that item scripts will never run for more than 1 frame. If you attempt to put a Waitframe in one, it's the same as if you had just called Quit().
 

Basically, the original script allowed you to permanently set screen secrets. But the adjusted version doesn't seem to want to carryover the correct value. Is this because I have the order of the arguments wrong? One explanation I read suggested that it should be Game->SetDMapScreenD(Dmap, screen, Screen->D[D], D).
 
Also, the screen number; I know it has to be decimal... but is that the decimal notation on the DMap or the overall map?
 
Example: In dmap, screen number to be adjusted is 27 but in overall map, it is 2F.

The order of arguments is exactly as it is in zscript.txt. Your problem is that the screen number does indeed have to be the adjusted screen number. The DMap alignment thing is a huge pain the butt. Here's a test script so you can see if your D values are doing what they should (DMap and screen are hardcoded into it, so change those as necessary).
 
ffc script DDebug
{
	void run()
	{
		int register;
		int color;
		
		while (true)
		{
			if (Link->PressEx1)
			{
				Game->SetDMapScreenD(2, 0x01, register, Game->GetDMapScreenD(2, 0x01, register) + 1);
			}
			if (Link->PressEx2)
			{
				Game->SetDMapScreenD(2, 0x01, register, Game->GetDMapScreenD(2, 0x01, register) - 1);
			}
			if (Link->PressEx3)
			{
				register = (register + 1) % 8;
			}
			for (int i = 0; i < 8; i++)
			{
				if (i == register)
				{
					color = 0x06;
				}
				else
				{
					color = 0x01;
				}
				Screen->DrawInteger(6, 0, i * 16, FONT_Z1, color, 0x07, 0, 0, Game->GetDMapScreenD(2, 0x01, i), 0, OP_OPAQUE);
			}
			
			Waitframe();
		}
	}
}


Then there are also some relatively simplistic scripts that don't seem to work at all for me. For example, I set up one script that was just supposed to tell if a normal or locked chest had been opened on that screen; then increase a counter. But it doesn't seem to do anything. Another was supposed to add to a counter when I got an item and a message played, but occasionally; it had added more than one to this counter even though I only got one item!

Are you checking (Screen->State[ST_CHEST] || Screen->State[ST_LOCKEDCHEST])? I don't know what's happening with the item that adds to a counter, though, without seeing it.

#156 ywkls

ywkls

    Master

  • Members

Posted 21 August 2015 - 10:59 PM

Here's the code for those.

 

Item Counter and Chest Counter Code

I think that what's happening is that the trade sequence is increasing the counter twice. (Since this error usually occurs on screens where that happens.) However, this is not the case in all occasions so I really couldn't say if that's the source of the problem.; 


Edited by ywkls, 06 September 2015 - 09:30 PM.


#157 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 21 August 2015 - 11:24 PM

Do any of your strings for that item increase the counter themselves? That can be done with string control codes, and you might have something like that left over without realizing it. The Chest_Secret script doesn't work because the condition is flawed. It will always evaluate to true because you aren't going to have more than one type of chest in a room, so it just does Waitframe forever. Just replace that || with && and it should work.

#158 ywkls

ywkls

    Master

  • Members

Posted 23 August 2015 - 03:34 PM

@Lejes- I've checked those strings and they don't affect the counter. (I do have a few strings that are supposed to affect counters, but even they don't entirely work.) Chest_Secret has been corrected as you suggested; though I haven't tested it yet. Now here's one that is currently baffling me.

Target Game NPC

When you speak with the Npc, he warps you at once if you have enough rupees without playing any message at all. I have the 'messages freeze all action' and 'messages disappear' flags checked; but these messages never play. However, the one that is supposed to show up when you win does.

 

@Everyone Else- The following is my Grim Reaper from Enemy of the Month #12, revised so it isn't a whirling storm of nearly instant death. Gabriel Baron specifically expressed interest in it, so there may be others who'd like to use it.

Grim Reaper Revised

The main boss is still 2 x 2 and should have combos set up in the order up, down, left and right. The scythe is 1 x 2 and should be invulnerable to everything. Also, if you want his defenses to be correct; the defenses of the main boss should be invulnerable to everything but arrows, sword beams and the sword with the arrows doing quarter damage and the beams doing half damage.

 

I may upload this to the database later, so people can get a better look at it.


Edited by ywkls, 06 September 2015 - 09:46 PM.


#159 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 23 August 2015 - 04:02 PM

Try putting a Waitframe before you change this->Data to an autowarp combo.
  • ywkls likes this

#160 ywkls

ywkls

    Master

  • Members

Posted 23 August 2015 - 04:39 PM

Try putting a Waitframe before you change this->Data to an autowarp combo.

 
As it turned out, I needed two Waitframe() commands, one after either message. And now, we've come to what may have me banging my head against the wall for all time... the script that is quite literally the central mechanic for my game has stopped working. I've been using this script constantly,  for almost 6 and a half hours in the game. So, needless to say; having it suddenly go kaput is a major deal.
 
Here's the script I'm referring to.
 

// Section 3. Modified Day/Night Script
// OoA style multiple Time Period dmap warping
 
const int TS_NUM_TIMEPERIODS = 4;     //Set this to the number of time periods.  I.e. Past/Present/Future = 3
 
//Set any combination of these for how you want to designate a TimeWarp combo.  Leave at -1 if not using.  At least one needs to not be -1.
const int TS_TIMEWARPCOMBO = -1;   // use a specific Combo#
const int TS_TIMEWARPTYPE  = -1;   // use a specific ComboType
const int TS_TIMEWARPFLAG  = 99;   // use a specific ComboFlag - placed or inherent doesn't matter
 
int TS_DMaps[3] = {0, 4,32};   //This array tells the script which DMaps are involved in the Time System. 
                            //Put the first DMap of every set of time periods separated by a comma inside the {}. 
                            //Put the number of things inside the {} inside the []. 
                            //****You'll want to make a new save file every time you change this.
 
int TS_CurrentState = 0;  //tracks which time period you are in
 
 
// handles actually changing the Time Period dmap 
void TS_CheckandWarp(){
   int curDMap = Game->GetCurDMap();
 
   for(int i=0; i<SizeOfArray(TS_DMaps); i++){
      if(curDMap >= TS_DMaps[i] && curDMap < TS_DMaps[i]+TS_NUM_TIMEPERIODS){
         if(TS_DMaps[i] + TS_CurrentState != curDMap){
            Link->PitWarp(TS_DMaps[i] + TS_CurrentState, Game->GetCurDMapScreen());
            return;
         }
      }
   }
}

void TimeWarp(){
    closingWipe(60);
    TS_CheckandWarp();
    openingWipe(60);
    IsTimeWarping = false;
}
 
// put this on any Time Period screens where you return from a warp, script run on screen init
ffc script FFC_TS_WarpReturnCheck{
   void run(){
      TS_CheckandWarp();
   }
}


 
// D0 = select time period.  Between 0 and TS_NUM_TIMEPERIODS.
//      Set to -1 to cycle in reverse, set to TS_NUM_TIMEPERIODS+1 if you want to cycle forwards
// D1 = if setting the time period above (not cycling), and already in the D0 time period, warp to this instead.
 
item script I_ACT_TS_TimeChange{
   void run(int TS_SelectTP, int TS_WarpBack){
      if(isTimeWarp( ComboAt(Link->X+8,Link->Y+12)) ){
         if(TS_SelectTP < 0){
            TS_CurrentState--;
            if(TS_CurrentState<=0) TS_CurrentState = TS_NUM_TIMEPERIODS;
         }
         else if(TS_SelectTP > TS_NUM_TIMEPERIODS){
            TS_CurrentState++;
            if(TS_CurrentState>=TS_NUM_TIMEPERIODS) TS_CurrentState = 0;
         }
         else if(TS_CurrentState == TS_SelectTP) TS_CurrentState = TS_WarpBack;
         else TS_CurrentState = TS_SelectTP;
         IsTimeWarping = true;
      }  
   }
}

bool IsTimeWarping = false;
 
// Section 1. Global Script
// The Main Global Loop
global script globalScript{ 
    void run(){
        while(true){
            Waitdraw();
            if (IsTimeWarping) TimeWarp();              
            Waitframe();
        }//!End while(true)
    }//!End void run()
}//!End global script

The only real change I've made recently was a minor rewrite to one of my boss scripts.
 
Just in case one of my other scripts is causing this, here's a link to the entire script file.
 

(Link removed since error wasn't caused by scripts.)
Passage.z- my entire script file
 
The boss I recently changed was Bongo Bongo.


Edited by ywkls, 30 August 2015 - 12:26 AM.


#161 ywkls

ywkls

    Master

  • Members

Posted 04 September 2015 - 04:45 PM

Okay, this sounds like a simple enough idea, but this script is giving me all sorts of weird behavior.

 

Here's the script.

Big Stalfos

When it changes form, the sprite is the wrong color; the thing still seems to move (even though step is zero and the movement code shouldn't be running) and it never switches back to the other mode. I've tried several different variations on this, without success. Additionally, this one seems to cause the game to slow down for some reason.

 

Another note, is there an explanation of how these flags work somewhere?

const int GHF_KNOCKBACK          = 0000000000000001b;
const int GHF_KNOCKBACK_4WAY     = 0000000000000011b;
const int GHF_REDUCED_KNOCKBACK  = 0000000000000101b;
const int GHF_STUN               = 0000000000001000b;
const int GHF_CLOCK              = 0000000000010000b;
const int GHF_NO_FALL            = 0000000000100000b;
const int GHF_SET_DIRECTION      = 0000000001000000b;
const int GHF_SET_OVERLAY        = 0000000010000000b;
const int GHF_4WAY               = 0000000100000000b;
const int GHF_8WAY               = 0000001000000000b;
const int GHF_IGNORE_SOLIDITY    = 0000010000000000b;
const int GHF_IGNORE_WATER       = 0000100000000000b;
const int GHF_IGNORE_PITS        = 0001000000000000b;
const int GHF_MOVE_OFFSCREEN     = 0010000000000000b;
const int GHF_FAKE_Z             = 0100000000000000b;
const int GHF_FULL_TILE_MOVEMENT = 1000000000000000b;

// Combined old flags
const int GHF_NORMAL             = 0000000001011001b;
const int GHF_IGNORE_ALL_TERRAIN = 0001110000000000b;

// New flags - Set individually, identified as new by 17th bit
const int GHF_FLYING_ENEMY    = 0x10000;
const int GHF_IGNORE_NO_ENEMY = 0x10001;
const int GHF_WATER_ONLY      = 0x10002;
const int GHF_DEEP_WATER_ONLY = 0x10003;
const int GHF_STATIC_SHADOW   = 0x10

I know I can set these with Ghost_SetFlag() and clear them with Ghost_UnsetFlag() and Ghost_ClearFlags(). But what exactly setting them does isn't clear in some cases.


Edited by ywkls, 06 September 2015 - 09:50 PM.


#162 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 04 September 2015 - 07:37 PM

You need to set Ghost_HP, not n->HP. The change to n->HP is getting immediately overwritten by Ghost_Waitframe. And for future reference, you can't write to n->Step, only read it. The movement function isn't being called anyway while the Stalfos is collapsed, but still.

 

The full explanations of what the flags do are found in ghost.txt, which came with your download of the header.


  • ywkls likes this

#163 ywkls

ywkls

    Master

  • Members

Posted 04 September 2015 - 09:24 PM

For some strange reason, ghost.txt wasn't included in my download of ghost.zh; though I do have it. (Just had to do a little digging to find my copy.) Setting the Stalfos script where n->HP is replaced by Ghost_HP in every instance still produces the same results (though there isn't slowdown anymore). The second form never shifts back to the first. 

 

As for changing the value of n->Step. that's good to know. I've been doing it for a while and it does seem to work for the most part (for example, scripts that increase the speed of an enemy) so I'm not certain how it can be affected.

 

Now, for a slightly more experimental (much more complicated and not working) idea.

 

This is based on the Armos Knights script by Saffith.

Wood Warden

It creates the 4 enemies in the right spots and makes them invulnerable and not damage Link, but none of them come to life when you get close.


Edited by ywkls, 06 September 2015 - 09:50 PM.


#164 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 04 September 2015 - 10:12 PM

For some strange reason, ghost.txt wasn't included in my download of ghost.zh; though I do have it. (Just had to do a little digging to find my copy.) Setting the Stalfos script where n->HP is replaced by Ghost_HP in every instance still produces the same results (though there isn't slowdown anymore). The second form never shifts back to the first. 

 

You never shift the tilewidth and tileheight back to their original numbers. That might be it. I looked at what the combo numbers are doing and they look fine.



#165 ywkls

ywkls

    Master

  • Members

Posted 04 September 2015 - 11:46 PM

On the Stalfos, the problem seems to have been that the counter for it to have the collapsed form was being reset every frame as long as it was in that mode. Once a bool was added to have the counter activate only when entering that form and set to false once it was supposed to return to normal; the problems vanished.

 

On the Wood Warden, I think I'm going to have to rewrite that from scratch since what I want to have happen is so vastly different from the Armos Knights script that I can't really combine the two.

 

As always, thanks for your assistance.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users