PDA

View Full Version : Playtime-based scripts?



En Passant
08-04-2014, 12:40 AM
I know that there's a Quest Rule that will show the playtime on the subscreen, which means it can be tracked, so I was wondering if it's possible to make scripts that activate once the clock hits a certain value. The biggest use for this would be creating an automatic day-night cycle that would change the CSet or palette (and maybe the music too?) at set intervals.

CaRmAgE
08-05-2014, 10:10 AM
Do you want your script to activate after set intervals from the beginning of the game, or set intervals since loading/DMap change?

En Passant
08-05-2014, 10:27 AM
From the beginning of the game. Time waits for no one, after all.

CaRmAgE
08-05-2014, 03:37 PM
int startTime = 0; // Game->Time when last event was triggered

global script Time{
void run(){
bool timeValid = Game->TimeValid; // Make sure the time quest rule is enabled
while(true){
if(timeValid && (Game->Time-startTime)*500/3 >= 300){ // Time converted to seconds; trigger event after 300 seconds elapse
startTime = Game->Time; // Set startTime for the next interval
// Do stuff here...
}
Waitframe();
}
}
}

Some notes:

1. That timeValid check is just a sanity check. If you don't think you'll ever disable that time quest rule, you can safely delete that part of the check.
2. If you want to measure time in minutes, use the fraction 25/9 instead of 500/3.
3. The global script does not run while the subscreen is open. That is the reason for the >=, so if the interval is passed while the subscreen is open, the inner script will trigger as soon as the subscreen closes. If you want a timer that only counts while the subscreen is closed, let me know and I'll write a script up for that.

Also, I have zero scripting experience with combos and csets, so if you also want help with a day/night script, you'll have to wait for someone else to reply.

P.S. The ZC Wiki is deceptive. The Time entry is written as if a Game->Time of 1 is equal to 1/60 seconds, when, in reality, a Game->Time of 0.0001 is equal to 1/60 seconds. That's why it took me so long, so sorry about the wait.

En Passant
08-05-2014, 06:27 PM
Wow, thanks! Admittedly, the script is kind of simple so I'm a bit sad that I hadn't thought of it myself. Oh well, maybe I'll take a try at the day/night switches.
EDIT: Duh, changing the DMap would cover the color and music changes. Unfortunately, there's no SetCurDMap command, so I'm not sure how to go about doing that.

CJC
08-06-2014, 03:26 AM
You could record the player's position on screen and then pit warp to the same screen, but with a different DMap (or if you like, a similar screen with a different DMap, depending on how much day/night difference you want). I know there's a way to warp the player (I don't have the specific command on hand) so that would be one way to change the DMap.

Depending on how different you want day and night to be, you could have one timed warp change dmap but not screen (Dawn/dusk) and another timed warp change the map screen (say from day to night, switching enemies to undead or something and locking doors).

En Passant
08-06-2014, 03:34 PM
How do you warp to the same screen with a different DMap? I was planning on having the cycle be purely aesthetic, as otherwise I'd have to make at least 5 more maps just for minimal changes.

CJC
08-06-2014, 10:03 PM
Two DMaps can point to the same Map in the same way. If you build your DMaps correctly, you can switch DMaps using a warp without actually switching screens.


int thisDMapScreen = Game->GetCurDMapScreen();
int targetDMap = Game->GetCurDMap()+ DUSK;
Link->PitWarp(targetDMap, thisDMapScreen);

Essentially, you'll be setting up four constants: DUSK, NIGHT, DAWN, and DAY

const int DUSK = 1;
const int NIGHT = 2;
const int DAWN = 3;
const int DAY = -3

Then, you make sure every area you make has four DMaps, in order, starting with the Day palette. Day, Dusk, Night, Dawn. By setting up all DMaps in this order you can easily trigger a time shift by adding to or subtracting from the current DMap.
Essentially, the goal is to trigger a DMap shift without actually triggering a screen shift. Thus, you warp to the screen of the different DMap, but since they all point to the same Map you end up unmoved, with the different palettes/music/item restrictions.


We have to do it this way as there is no code that lets you directly set a DMap, you have to go through some manner of warp.

Zim
08-09-2014, 02:15 PM
Just use a draw rectangle over the whole screen with transparency. Search in the forums for and play with zim.qst for an example if you like. I wrote my own clock, time based events, nighttime, clouds, and rain scripts. There is even a lantern that works like lttp in there but it is slightly buggy only because I didn't bother to make special overhead tiles that stay dark because Link is under them at night.

Making extra dmaps is very impractical because then you'd have to write extra scripts that trigger secrets on every map when triggered on one, which is suitable, but so is making a black transparency rectangle over the whole screen.

Search YouTube for Zim Zelda Classic Nighttime for a short video.

CJC
08-09-2014, 02:34 PM
Making extra dmaps is very impractical because then you'd have to write extra scripts that trigger secrets on every map when triggered on one, which is suitable, but so is making a black transparency rectangle over the whole screen.

Wait... I thought secrets were by Map screen, not DMap screen. So if you have two DMap screens pointing to the same Map screen, the secret state is not carried over from one to the other?

I'll have to play around with that.

You're right though, if you want to do a lamp that cuts through darkness then drawing a transparent rectangle with interpolated fading rule set is the best way to do so. I was actually picturing something completely different from darkness (a dungeon with variable heat levels that becomes increasingly orange as the time counter goes on. At the harshest temperature DMap, the player's PASSIVE_Heat Heart Ring is made an active item, causing gradual damage on each screen. I know that's not what Dry Paratroopa was after, but I was thinking setup would be the same.

Zim
08-09-2014, 02:43 PM
Wait... I thought secrets were by Map screen, not DMap screen. So if you have two DMap screens pointing to the same Map screen, the secret state is not carried over from one to the other?

I'll have to play around with that.

You're right though, if you want to do a lamp that cuts through darkness then drawing a transparent rectangle with interpolated fading rule set is the best way to do so. I was actually picturing something completely different from darkness (a dungeon with variable heat levels that becomes increasingly orange as the time counter goes on. At the harshest temperature DMap, the player's PASSIVE_Heat Heart Ring is made an active item, causing gradual damage on each screen. I know that's not what Dry Paratroopa was after, but I was thinking setup would be the same.

I haven't looked in ages but I recall there only being one slot for dmap assignment per map.

Zim
08-09-2014, 02:44 PM
I used scripted quick menus to eliminate the subscreen and turn it into a pause screen also, which effectively gets rid of the stop clock problem also.

En Passant
08-11-2014, 01:57 AM
Just use a draw rectangle over the whole screen with transparency. Search in the forums for and play with zim.qst for an example if you like. I wrote my own clock, time based events, nighttime, clouds, and rain scripts. There is even a lantern that works like lttp in there but it is slightly buggy only because I didn't bother to make special overhead tiles that stay dark because Link is under them at night.

Making extra dmaps is very impractical because then you'd have to write extra scripts that trigger secrets on every map when triggered on one, which is suitable, but so is making a black transparency rectangle over the whole screen.

Search YouTube for Zim Zelda Classic Nighttime for a short video.

The only thing on the forum about zim.qst is this thread (http://armageddongames.net/showthread.php?95748-Zim-qst) where the file was deleted. On YouTube, what appears to be your nighttime blacks out most of the screen, which is not what I want.
EDIT: I can confirm that changing the DMap resets the screen, though.

Zim
08-11-2014, 02:11 AM
I knew that, but what you did ask about us the same thing minus the additional amounts of darkness.
Think about it in terms of the part of the lantern that isn't blacked out all the way..
The screen is only really dark because they are 4 shades of darkness.
That's 4x the same thing you were pondering.
On that same thread there are a few links to a saved version of that quest file that is only slightly outdated.
I would be happy to post it again, but it is already there.

Use the dropbox links to get the file, I just did and they are still there.

CJC
08-11-2014, 12:07 PM
EDIT: I can confirm that changing the DMap resets the screen, though.
Hmmm... did you have any room-state carry-overs set on the screen flags?

EDIT: Nevermind, that wouldn't work, it uses Maps, not DMaps. Damn.

En Passant
08-12-2014, 12:56 AM
Okay, so I tried using what appears to be the rectangle that you were talking about, zim, and it doesn't work.
global script Time{ void run(){
bool timeValid = Game->TimeValid; //Make sure the time quest rule is enabled
while(true){
if(timeValid && (Game->Time-startTime)*25/9 >= 1){ //Event triggers every 60 minutes (edited to 1 for demo purposes)
//int thisDMapScreen = Game->GetCurDMapScreen();
if(!isNight){ //Day to night
//int targetDMap = Game->GetCurDMap()+1; //Night DMaps are always immediately after the Day equivalents
//Link->PitWarp(targetDMap, thisDMapScreen);
Screen->Rectangle(6,0,0,240,0,0,160,240,160,10,true,128);
} else { //Night to day
//int targetDMap = Game->GetCurDMap()-1;
//Link->PitWarp(targetDMap, thisDMapScreen);
}
startTime = Game->Time; //Set startTime for the next interval
isNight = !isNight;
}
Waitframe();
}
}
}

CaRmAgE
08-13-2014, 10:09 AM
Okay, so I tried using what appears to be the rectangle that you were talking about, zim, and it doesn't work.
global script Time{ void run(){
bool timeValid = Game->TimeValid; //Make sure the time quest rule is enabled
while(true){
if(timeValid && (Game->Time-startTime)*25/9 >= 1){ //Event triggers every 60 minutes (edited to 1 for demo purposes)
//int thisDMapScreen = Game->GetCurDMapScreen();
if(!isNight){ //Day to night
//int targetDMap = Game->GetCurDMap()+1; //Night DMaps are always immediately after the Day equivalents
//Link->PitWarp(targetDMap, thisDMapScreen);
Screen->Rectangle(6,0,0,240,0,0,160,240,160,10,true,128);
} else { //Night to day
//int targetDMap = Game->GetCurDMap()-1;
//Link->PitWarp(targetDMap, thisDMapScreen);
}
startTime = Game->Time; //Set startTime for the next interval
isNight = !isNight;
}
Waitframe();
}
}
}


That's because I believe the drawing functions only last for one frame. So, to make the effect last the entire night, add this right before Waitframe():


if(isNight){
Screen->Rectangle(6,0,0,240,0,0,160,240,160,10,true,128);
}


or, even better, call a helper function in the if statement that makes the effect more gradual instead of instantaneous.

Zim
08-17-2014, 03:17 PM
First thing is your booleans and other variables are not declared in this code.

They need to be declared and set to something or they do nothing
Secondly, a bool like isNight won't change by writing isNight=!sNight, you must write isNight= false to set it to false.
isNight=!isNight only passes parsing because !isNight is standalone valid, but meaningless as a set.

Thirdly, carMage is right about the waitframe, the script or function that the draw is in must be in a loop that calls the rectangle draw every frame it is active.rectangle, you would need a 64 on that argument for transparency.

Fourthly, 128 on the transparency argument of the draw function, the last one, would draw a solid.
Lastly, the pit warp is obsolete when using a code like that, we were talking about averting the need for ambiguous screen mimicry.

It would be very simple,





while(true)
{
if(Game->Time==Time interval of some sort)
{Screen-> Rectangle(parameters, parameters, etc.,64);
Waitframe();
}
}

Whereas the time interval variable could be a range of numbers equating to the desired time span
In my quest file hours are their own variable in an array.

En Passant
08-17-2014, 08:14 PM
Yeah, whatever Rectangle was there was completely off, I replaced it with this one:

Screen->Rectangle(6,0,0,256,176,8,1,0,0,0,true,OP_TRANS)

Other than that, the script worked fine with just the Screen->Rectangle being during the loop. The variables were declared before the script started, which worked somehow, but I moved them in just to be safe.

Does ZQuest have switch-cases? The next thing I need to do is add music, and it seems tedious to have to do if statements for every overworld DMap. And how can I set it so that overlays/MIDI changes don't affect the indoors?