Tutorial Title: How to create respawning resource nodes
Brief Description: This tutorial will teach you how to implement a system of harvestable resource nodes which replenish themselves on a timer without the need for many game variables or huge nests of conditional branches.
Requirements: None, though a basic familiarity with Javascript would be a bonus for understanding the script we'll be writing.
Tutorial Body:
We're going to look at how to create mining nodes for stone, but these concepts can be modified to apply to basically anything harvestable; plants, ore, fish, you name it. Due to how the data will be stored, it may not be entirely suitable for a full-on farming system where you'll have a lot of crops growing at once, but for all I know it'll work for that too. Feel free to experiment.
IMPORTANT: Any time I refer to "variable" in the tutorial, if it's prefaced with "[JS]" I mean a JavaScript variable (the kind you create in a script command) and it it's prefaced with "[RM]" I mean the built-in RPG Maker game variables (the ones you manipulate with the Control Variables command, which can also be manipulated in code using $gameVariables.value(x) to get a variable's value, and $gameVariables.setValue(x, value) to set it)
So first things first, let's create a rock event. The main contents of the event, such as animations, text, item gain etc. can be anything you want; the only important part is the script at the end, and turning on self switch A to activate page 2, which has the graphic of the empty node. My event looks like this:
Let's break down that script and look at what it's doing:
JavaScript:
if ($gameVariables.value(1) === 0) $gameVariables.setValue(1, []); $gameVariables.value(1).push([this._mapId, this._eventId, 500]);
If [RM]variable 1 is equal to 0, set it to an empty array.
Then push to that array another array consisting of the current map ID, the current event ID, and the value 500.
The first line is to ensure that the [RM]variable we're using becomes an array before we try to store multiple values in it, otherwise we'll get an error. The second line is storing an array of data identifying this particular node event and the number of frames it'll take to respawn. So in this case, 500 frames, or just over 8 seconds.
this._mapId and this._eventId will already return whatever the current map is, and the ID of the event the code is running inside, so you don't need to change this, it'll work as-is with any event you paste it into.
It should hopefully go without saying, but the [RM]variable ID used must be one you're not using elsewhere in the game.
And now, let's look at our common event (these are created in the "Common Events" tab of the database):
This will be a parallel process event. Parallel process events never just run by themselves with no input; they always require a specified switch to be turned on before they'll start, so you'll need to make sure its activation switch is turned on at some point. Usually for things like this I have an autorun event at the start of the game which does setup like this and then either erases itself or turns on a self switch to move to a non-autorun page, but the exact method of turning on the switch is up to you.
Note from this point that any time I refer to the "1" in $gameVariables.value or $gameVariables.setValue, you must ensure that you use the same [RM]variable ID as you used for the event step above. Everything else can be copied as-is.
The conditional branch script condition, $gameVariables.value(1) !== 0, is just making sure the [RM]variable's value is not 0. This is to ensure that we don't waste time running the inner code if the player has never interacted with a node. As soon as they do, the line from the event which turns the [RM]variable into an array and then pushes an array into it will cause this condition to be true, and start running the rest of the code:
JavaScript:
for (const oreData of $gameVariables.value(1)) { oreData[2]--; if (oreData[2] === 0) { $gameSelfSwitches.setValue([oreData[0], oreData[1], 'A'], false); $gameVariables.value(1).remove(oreData); } }
So what's happening here is that we're running a loop that goes through each element of [RM]variable 1's value, which as mentioned before is an array of arrays (an array just being a [JS]variable that can hold more than one value inside it). Each time we loop, we'll store the current element in a [JS]variable called oreData. It doesn't have to be oreData, you can call it anything you like as long as it starts with a letter, underscore or dollar sign. The important thing is that every occurrence here of "oreData" must be exactly the same name or the script won't work.
First, we reduce the value of oreData's third element (index 2) by 1. Then, if that value is equal to 0, we turn off a self switch, using oreData's first element as the map ID, its second element as the event ID, and 'A' as the self switch letter. Finally, we remove the oreData element from the [RM]variable.
Let's work through this with an example which will hopefully make the mechanism clearer. Let's say I've mined a stone node that's on map 2, event 9.
The code in that event is going to change [RM]variable 1's value from 0 to [], and then push [2, 9, 500] to it. So variable 1 now contains [[2, 9, 500]].
The common event now sees that [RM]variable 1 is not equal to 0, so it starts the loop. In the first iteration, oreData is [2, 9, 500]. oreData[2] is 500, and it's reduced by 1 to become 499. Its value is not 0, so that's all the loop does for now.
Once the loop has run 500 times, the value of that oreData[2] will be 0. At that point, we'll set the value of the self switch with key [2, 9, 'A'] to false, which turns off self switch A for event 9 on map 2. And then oreData will be removed from the array, meaning it will now have a value of [].
Now that self switch A is off for that event, it will turn back to page 1, allowing the player to harvest from it again and starting the process over.
And that's all there is to it! You can copy that event around as many locations and maps as you wish. There shouldn't be much if any lag from the common event, as it only ever needs to run through the nodes the player has harvested from which haven't respawned yet, and as soon as they do respawn the event stops looking at them.
Please feel free to post any thoughts, feedback or suggestions you have below, and I wish you all happy harvesting!
本贴来自国际rpgmaker官方论坛作者:Trihan处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:
https://forums.rpgmakerweb.com/threads/how-to-create-respawning-resource-nodes-using-a-single-variable-and-a-common-event.144193/