Hello Guest, please login or register.
Did you miss your activation email?
Login with username, password and session length.

Pages: [1]   Go Down

Author Topic: Tutorial: Dynamic luck for random items + bouncing items!  (Read 2155 times)

0 Members and 1 Guest are viewing this topic.

Goodnight

Once and future Captain
Tutorial: Dynamic luck for random items + bounci...
« on: January 22, 2007, 08:00:50 pm »
  • With a Capital G
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 706
Ever notice how most Zelda games only drop items from bushes if you've encountered that item before?

- You'll only get Deku seeds if you have the Fairy Slingshot
- You'll only get arrows if you have the Hero's Bow
- You'll only get magic pots if you have the sword-spin attack or a Goddess' spell
etc. etc.

Here's how to do that in Game Maker, and also simplify random-item-dropping in general, using a dynamic luck system. I developed this for Two Swords and just now got the crazy idea to share a version of it. There's no downloadable example here because A) There are too many options you can change as far as available items, and B) You need to understand it to use it.

Let's set it up!

First of all, somewhere around the beginning of the game, set your variables that affect which items will drop from bushes. Then, after those, call a script that's about to be made. Example:
Code: [Select]
global.got_magic=false;
global.got_bow=false;
scrLuckInit();

Now, you need a script to initialize what items are available from bushes, and the "weight" given to each one. Note: weights are not percentages. If you have two items with a weight of 50, then each will have a 50/100 (50%) chance of being dropped. But if you have three items, all weighing 50, then the chance for each will be 50/150 (33.3%). This lets you adjust individual weights without having to fix all the others. Weights should be whole numbers.
Code: [Select]
// scrLuckInit

var i,ii;
i=0;

// random item declaration:
global.luck[i,0]=300; global.luck[i,1]="none"; i+=1;
global.luck[i,0]=50; global.luck[i,1]=objRupeeGreen; i+=1;
global.luck[i,0]=18; global.luck[i,1]=objRupeeBlue; i+=1;
global.luck[i,0]=6; global.luck[i,1]=objRupeeRed; i+=1;
global.luck[i,0]=3; global.luck[i,1]=objRupeeBigGreen; i+=1;
global.luck[i,0]=22; global.luck[i,1]=objHeart; i+=1;
global.luck[i,0]=8; global.luck[i,1]=objHeartPiece; i+=1;

if global.got_magic {
    global.luck[i,0]=15; global.luck[i,1]=objMagic3; i+=1;
}
if global.got_bow {
    global.luck[i,0]=40; global.luck[i,1]=objArrow1; i+=1;
    global.luck[i,0]=16; global.luck[i,1]=objArrow3; i+=1;
}

// random item preparation:
global.luckitems=i;
for (ii=1; ii<i; ii+=1) {
    global.luck[ii,0]+=global.luck[ii-1,0];
    global.lucktotal=global.luck[ii,0];
}
You can have as few or as many of those declaration lines as you like, but I strongly recommend keeping "none" as the first item. Note that the last three fall under conditions, so they'll only be included in the total if you have magic and/or the bow.

The first line of preparation saves the number of different random items (including "none"), since you'll need to know that for later. The loop following that accumulates the weights in a way that:
global.luck[0,0]=300
global.luck[1,0]=50
global.luck[2,0]=18
global.luck[3,0]=6

Becomes:
global.luck[0,0]=300
global.luck[1,0]=350
global.luck[2,0]=368
global.luck[3,0]=374

And so on. This is done to "tier" the items so that you can easily find which range a random number falls between. The last line also records the highest tier number to a global variable, so that a random number can be chosen between 0 and that number.

To make luck dynamic:
At any point in the game where you gain a new item or ability that would change which random items are available, just call the script scrLuckInit() again, and luck will be re-initialized.

So how do we use this?
Ah, I see you're a sharp one, we still need a way to turn a random number into an item. Make a new script called scrLuck. This script will be called from a bush's Destroy event, or any other event where a random item should drop.
Code: [Select]
// scrLuck

var lucknum,i;
lucknum=floor(random(global.lucktotal+argument0)-argument0);

for (i=0; i<global.luckitems; i+=1) {
    if lucknum<global.luck[i,0] {
        if !is_string(global.luck[i,1]) { instance_create(x,y,global.luck[i,1]); }
        break;
    }
}
lucknum is a random whole number, between 0 and (global.lucktotal-1) inclusive. What's argument0 doing there? Just an extra feature I added that I'll explain in a moment.

The loop then checks through each of the random items available, and sees if the random number falls under its tier. If it does, and the item is something other than a string ("none"), then it will be created. The break just ends the loop, since no more checks need to be made.

So don't forget:
scrLuckInit(); at the beginning of the game and any time when different luck items are available.
scrLuck(); any time you want to drop a random item. (it appears at the same position as the object which calls the script)

Back to that "extra feature":
argument0 allows you to offset the random number, making it more or less likely that you'll receive an item. In most cases you won't need to worry about entering an argument, since typing scrLuck(); is the same as typing scrLuck(0);.

The number you enter as argument0 is how much will be added to the first teir of items (this is why I recommended that "none" by the first). In Two Swords, you will be less likely to get a random item if the bush is burned, rather than cut. So if the bush is burned, it's Destroy event will contain: scrLuck(200);, which adds an extra 200 to the weight of "none" (not permanently - only for this random draw). Conversely, if you want to make sure that you always get an item, and the normal weight of "none" is 300, then do: scrLuck(-300);.

So that's about it. I'll post a few mods shortly and answer any questions.

Feel free to use, please give credit, and do me proud!
« Last Edit: February 01, 2007, 06:10:32 pm by Goodnight »
Logged
Re: Tutorial: Dynamic luck for random items
« Reply #1 on: January 22, 2007, 08:10:29 pm »
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6206
That's nicely coded and well explained their are defenitly people who can use this!
Logged
Re: Tutorial: Dynamic luck for random items
« Reply #2 on: January 22, 2007, 08:17:47 pm »
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 647
Nicely explained, clean code, good formatting. What more could you ask? ;) Great job.
Logged
Re: Tutorial: Dynamic luck for random items
« Reply #3 on: January 22, 2007, 08:24:15 pm »
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 413
You. Are. A. God.
Go make a game. Now.
Logged

Goodnight

Once and future Captain
Re: Tutorial: Dynamic luck for random items
« Reply #4 on: January 22, 2007, 08:30:00 pm »
  • With a Capital G
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 706
Ack, I missed 3 replies while typing this. Well thanks, glad you all like it, and I'll be even gladder if you put it to good use.

Sir Cyrus: I have a game being made. Okay, so it hasn't been touched in months, but nobody's counting. ;D


Mod #1 - different sets of luck

You may want to get different items from different pieces of scenery. For example rocks in The Minish Cap usually drop mysterious shells, which don't come from bushes. To do this, enter scrLuckInit and copy the entire code and paste it again below. You may not need to duplicate var i,ii; but you do need i=0;.

In one set, add a prefix to every global variable/array that was to do with luck.
global.luck[] becomes global.bush_luck[]
global.luckitems becomes global.bush_luckitems
global.lucktotal becomes global.bush_lucktotal
Then do the same to the other set, with "rock" instead of "bush". For the second set, edit the declarations however you like.

Now, make a copy of scrLuck. Don't double the contents of the script like you did with scrLuckInit, actually make a duplicate of the script. One will be for bushes, one for rocks. Open both scripts and change the global variable names in the same way you did earlier. Now you've got one script for bushes to call, and one for rocks.


Mod #2 - varying weights

This mod is much easier. Let's say you want weights to change entirely based on certain conditions. For example in Two Swords, Orange Link has better luck than the other characters, meaning he's more likely to get good items, and less likely to get bad items or none. So, scrLuckInit is edited to look something like this:
Code: [Select]
var i,ii;
i=0;

if global.P1character=5 {      // this means Player 1 is Orange Link

    // lucky declarations go here

} else {

    // normal declarations go here

}

// preparations go here


Mod #3 - bouncing items

This is what you really wanted, right? This code doesn't modify the dynamic luck code in any way, but goes hand-in-hand with it.

In the Create event of any item that you want to bounce, add this:
Code: [Select]
height=0;
timeline_index=tmlItemFall;
timeline_position=0;
You also may want to set the timeline_speed to something a bit higher than 1, as this bouncing animation turned out a little bit slow when I first made it (and it was designed for a high room_speed).

In the item's Draw event, make the item drawn at (x,y-height). This makes the sprite move along with the "height" variable, to give the appearance that the object is bouncing when it's actually staying in place.
Code: [Select]
draw_sprite(sprite_index,-1,x,y-height)
Now make a new Time Line called tmlItemFall. Add the following steps and codes:
Step 0: height=4
Steps 1, 2, 3, 4, 5, 6, 8, 11: height+=1;
Steps 15, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29: height-=1;
Steps 30, 31, 32, 33, 35, 38: height+=1;
Steps 42, 45, 47, 48, 49, 50: height-=1;
Steps 51, 52, 54, 57: height+=1;
Steps 59, 60, 61, 62: height-=1;
Steps 63, 64, 65: height+=1;
Steps 66, 67: height-=1;
Step 68: height-=1; timeline_index=-1;

And that should do it!
« Last Edit: January 22, 2007, 08:32:23 pm by Goodnight »
Logged
Re: Tutorial: Dynamic luck for random items + bo...
« Reply #5 on: January 24, 2007, 02:42:35 am »
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 4588
Wow, nice. Very efficient. I would have done something totally different, (and uneffcient in comparison to yours) so good work.
Logged
the a o d c

Antidote

>.>
Re: Tutorial: Dynamic luck for random items + bo...
« Reply #6 on: January 31, 2007, 10:40:53 pm »
  • In all seriousness who's serious?
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 1485
*pulls out car jack and fixes mouth* O_O nice scripts Goodnight, quality as always =D
Logged
  • Axiomatic Data Laboratories

Goodnight

Once and future Captain
Re: Tutorial: Dynamic luck for random items + bo...
« Reply #7 on: February 01, 2007, 06:09:26 pm »
  • With a Capital G
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 706
Thanks all, but I guess nobody's used this yet, because thanks to Antidote bumping, I found a major bug. See, I was modifying these scripts while extracting them from my game, and overlooked something.

Instead of checking if the random item chosen is not "none", you should just check if it's not a string. Because if it's not a string then GM can't compare it to the string "none" and error'z. :-[

Fixed scrLuck in the first post.
Logged
Re: Tutorial: Dynamic luck for random items + bo...
« Reply #8 on: February 06, 2007, 03:00:49 am »
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 1635
Interesting. Depending on how many items I had, I might just store "got_magic" or "got_arrow" in an array, each index representing a differnet item. I'd come up with a naming scheme that matches my objects. THen, I'd use iterate through all the arrays and execute_string to create the object based on the current array if the luck is above some number. Basicaly, like you did, except iterate through everything a bit differently.
Logged
Re: Tutorial: Dynamic luck for random items + bo...
« Reply #9 on: February 10, 2007, 06:43:00 pm »
  • Don't Worry Sir, I'm From The Internet.
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 2339
Very nice, I'll definetly be using this in my game, thank you very much. This is much better than the old one i had.
Logged
Grimace is the demiurge, the creator. From him all things in McDonaldland have sprung. He is not a sin, he's not a menu item, he's just Grimace. He exists. He rolls his lidless eyes and flaps his lipless mouth, formless and terrible, a protean idiot thing from the depths of pre-history.
Pages: [1]   Go Up

 


Contact Us | Legal | Advertise Here
2013 © ZFGC, All Rights Reserved



Page created in 0.334 seconds with 54 queries.