Gw Temp

Menu

Tutorial - 'ABS Tutorial Part 3 - Instant-Effect Spells' by AzureFenrir

An item about RPGMaker 2000 posted on

Blurb

The third installment of AzureFenrir's ABS tutorials, this time discussing different kinds of spells whose effects occur immediately after they are cast.

Download the accompanying demo project for Part 3, 4, and 5 here: http://staff.whahay.net/AzureFenrir/Tutorial/ABSDemo.zip

Body

ABS Tutorial Part 3 - Instant-Effect Spells

I've finally returned to writing the third installment of my ABS tutorials. For those of you who didn't know, my ABS tutorials are entirely independent of each other (even though they have the words "Part X" tagged on them). This means that you can use this tutorial with blue_moogle's tutorial, or mix them with ATARI's tutorials, etc.

This tutorial coves how you can implement many different types of spells and spell targets. Since this is an advanced tutorial, I will use a bit of pseudocode instead of actual RM2K code and won't explain the coding step-by-step (and sometimes I might not show coding at all). Therefore, you should at least have experience with coordinate manipulation (Part 1) before you read this.

So, without further ado, let's get started. Here's what you need to know before you read this tutorial:

THINGS THAT YOU NEED TO KNOW:

Serious experience with and Knowledge of RM2K Commands
Using and Manipulating Switches
Using and Manipulating Variables
Fork Statements
Cycles and Loops
Experience with using/manipulating the RM2K Coordinate System


Let's start off with a few switches and variables. You can reuse the HeroX...WatchY and Temp variables from the last tutorial if you want:

SWITCHES AND VARIABLES:

4 Temporary Variables - "HeroX", "HeroY", "WatchX", "WatchY"
Additional switches and variables vary by spell type.


Before you read any further, add a new event that will detect if the is pressed. It if is, use variable operations to store the Hero's X and Y coordinates in the HeroX and HeroY variables. Do the same for the enemy's coordinates in WatchX and WatchY. This event is where all of your spell effect code will go.

Also, because inflict damage codes can very depending on the style of ABS you are making. Therefore, instead of adding specific damage code, I'll use a simple Damage Enemy: Enemy#. Make sure that you replace the Damage Enemy: Enemy#'s with the appropriate enemy damaging code!

Finally, if you didn't read the directions, this tutorial (and the next two parts of these ABS tutorials) includes a demo project to help you understand code placement, events, etc. The sample project can be found here: http://staff.whahay.net/AzureFenrir/Tutorial/ABSDemo.zip



Target-All Spell

Target-All spells do exactly as their descriptions imply - they damage/affect all enemies on a particular map. These are also the easiest spells to implement. All you really have to do to implement these spells is remove a certain amount from every monster's HP variable, and set them to "dead" if their HP drops down to zero. You don't even need any FORK statements or coordinate stuff :).

This is probably the easiest spell to implement, since all you needed to do was damage every enemy:

RPG Maker 2000 Code:

<>Show Battle Anim: Full-Screen Spell, Hero (W)
<>Damage Enemy: Enemy1
<>Note: Repeat this for every enemy on the map.




Target Radius Spells

Target Radius Spells are spells that target all enemies that are a certain distance away. Target radius spells are usually spells that explode in a circle around the hero (such as exploder/flare spells) and will thus always damage enemies in a circular area.

Target Radius Spells require a bit of coordinate manipulation. Basically, if the hero's distance from the enemy is, say, 5, then the hero's X Distance and the Y Distance from the enemy ADDED TOGETHER should equal seven or less. Which means:

Initialize WatchX and WatchY to Enemy1's coordinates.
Set Variable [TempX] to [HeroX]
Subtract [TempX] by [WatchX]
Set Variable [TempY] to [HeroY]
Subtract [TempY] by [WatchY]
Increase (add) [TempX] by [TempY]
Check if [TempX] is less than or equal to 5.

That seems easy enough...but what if the enemy is ten spaces to the right of the hero? Then, TempX will equal -10, which causes this algorithm to end up with a negative value...which means the enemy will be damaged even though he's not in the target range!

To fix that problem, we need to make sure that both TempX and TempY results in a positive value (absolute value). That would take two more FORK statements:

RPG Maker 2000 Code:

<>Variable Ch:[0003:WatchX] Set, Enemy1 X pos
<>Variable Ch:[0004:WatchY] Set, Enemy1 Y pos

<>Variable Ch:[0009:TempX] Set, Var.[0001:HeroX] val.
<>Variable Ch:[0009:TempX] -, Var.[0003:WatchX] val.
<>FORK Optn:Varbl[0009:TempX]-0 less than
    <>Variable Ch:[0009:TempX] *, -1
    <>
: END Case


<>Variable Ch:[0010:TempY] Set, Var.[0002:HeroY] val.
<>Variable Ch:[0010:TempY] -, Var.[0004:WatchY] val.
<>FORK Optn:Varbl[0010:TempY]-0 less than
    <>Variable Ch:[0010:TempY] *, -1
    <>
: END Case


<>Variable Ch:[0009:TempX] +, Var.[0010:TempY] val.
<>FORK Optn:Varbl[0009:TempX]-5 less than
    <>Damage Enemy: Enemy1
: END Case


As you can see, we added in the two FORK statements to check whether TempX and TempY is negative. If any of them are, then we multiply them by -1 to make them positive. It's kind of like an Absoulte Value function.

Obviously, repeat this code for evey additional enemy. Make sure that you set WatchX and WatchY to the right enemy's coordinates!



Target Random Location Spells

A target random location spell will target random locations on the map and do damage if enemies are there. These spells aren't very popular in ABSes (they usually do not hit the enemy, so players thus rarely use them), but might still be an interesting twist to add to an ABS.

Target Random Location spells do not need to use (or initialize) the HeroX and HeroY values at all. Instead, it involves selecting a random location on the map and checking if any enemies are there. To do that, set two new variables, SpellX and SpellY, to random locations on the map by using random numbers (you should be familiar with random numbers, but just in case if you forget, the random number generator is in "Variable Operations). Just set the minimum for both variables to 0 and the maximum to the number of tiles in the horizontal/vertical direction, respectively.

RPG Maker 2000 Code:

<>Variable Ch:[0007:SpellX] Set, Randm[0*19]
<>Variable Ch:[0008:SpellY] Set, Randm[0*14]


Show a battle animation on the area for kicks. To do that, create a new event and call it "RandomHitEvent." Make sure that it has no graphic and does nothing. Then, you can use that event as a positioning event for the battle animation:

RPG Maker 2000 Code:

<>Setup Event's Place: RandomHitEvent, (V[0007:SpellX],V[0008:SpellY])
<>Show Battle Anim.: Thunder Effect, RandomHitEvent


Then, compare the SpellX and SpellY variables with every monster's X and Y coordinates ("WatchX" and "WatchY") If there's a match, subtract a lot from the monster's HP variable. Repeat all of this code a few times with a cycle or label if you want to have the spell "hit" multiple times (e.g. "Thunderstorm"). You can also add sound effects or whatever flashy effects you want:

RPG Maker 2000 Code:

<>Variable Ch:[0003:WatchX] Set, Enemy1 X pos
<>Variable Ch:[0004:WatchY] Set, Enemy1 Y pos

<>FORK Optn:Varbl[0007:SpellX]-V[0003:WatchX] Equivl
    <>FORK Optn:Varbl[0008:SpellY]-V[0004:WatchY] Equivl
        <>Damage Enemy: Enemy1
        <>Play Sound Effect: Damage2
        <>
    : END Case
    <>
: END Case


You can also add a spell radius to each spell hit by using the above "Target Radius" code and changing the [HeroX] and [HeroY] to [SpellX] and [SpellY], respectively.



Target Random Enemy Spells (Roulette)

These spells are much easier than the previous two. Basically, add a new veriable (or use your temporary variables), and set it to a random number. Have the spell damage/effect a certain enemy depending on what number was rolled.

You did make the enemies, so you should easily know which enemies could correspond to what number:

RPG Maker 2000 Code:

<>Variable Ch:[0006:Temp] Set, Random[1*The # of enemies that you have]

<>FORK Optn:Varbl[0006:Temp]-1
    <>Show Battle Animation: Roulette Hit, Enemy1
    <>Damage Enemy: Enemy1
    <>
: END Case


Add more FORK statements fo every enemy on your map.



Flashlight/Triangle Laser Spells


Yes, all of the spiked coordinates are targetted by spell.
Actual squares vary depending on hero direction.

Flashlight spells are spells that target a triangular area in front of the hero. Although it seems like flashlight spells are very difficult to implement, they are in reality just a matter of manipulating a formula.

Do you still remember the second part of my ABS tutorial? Well, if you don't (or never read it), the enemy is in the hero's spell triangle if:

LEFT: TempY < TempX, HeroX < WatchX
RIGHT: TempY < TempX, HeroX > WatchX
UP: TempX < TempY, HeroY < WatchY
DOWN: TempX < TempY, HeroY > WatchY

HeroX/Y and WatchX/Y are simply the hero and enemy in question's X and Y coordinates. TempX and TempY are obtained by the following code:

RPG Maker 2000 Code:

<>Variable Ch:[0003:WatchX] Set, Enemy1 X pos
<>Variable Ch:[0004:WatchY] Set, Enemy1 Y pos

<>Variable Ch:[0009:TempX] Set, Var.[0001:HeroX]val.
<>Variable Ch:[0009:TempX] Set, Var.[0003:WatchX]val.
<>FORK Optn:Varbl[0009:TempX]-0 less then
    <>Variable Ch:[0009:TempX] *, -1
: END Case

<>Variable Ch:[0010:TempY] Set, Var.[0002:HeroY]val.
<>Variable Ch:[0010:TempY] Set, Var.[0004:WatchY]val.
<>FORK Optn:Varbl[0010:TempY]-0 less then
    <>Variable Ch:[0010:TempY] *, -1
: END Case


So, TempX and TempY are basically the absolute value of the Hero and Enemy's coordinates - in other words, their distance. But why are the above four inequalities true (you should understand the last inequality in evey set)? Well, let's look at a diagram:



If you still don't understand, try calculate the TempX and TempY values of every square on that triangle. I could guarantee that if you stay in that triangle, then TempX will always be less than TempY :).

So how would we make this into code? Well:

RPG Maker 2000 Code:

<>FORK Optn:Hero - Up Face Direct
    <>FORK Optn:Varbl[0010:TempY]-V[0009:TempX] more than
        <>FORK Optn:Varbl[0002:HeroY]-V[0004:WatchY] less than
            <>FORK Optn:Varbl[0010:TempY]-5less
                <>Damage Enemy: Enemy1
                <>Play SE: Damage2
            : END Case
        : END Case
    : END Case
: END Case
<>FORK Optn:Hero - Down Face Direct
    <>FORK Optn:Varbl[0010:TempY]-V[0009:TempX] more than
        <>FORK Optn:Varbl[0002:HeroY]-V[0004:WatchY] less than
            <>FORK Optn:Varbl[0010:TempY]-5less
                <>Damage Enemy: Enemy1
                <>Play SE: Damage2
            : END Case
        : END Case
    : END Case
: END Case
<>FORK Optn:Hero - Left Face Direct
    <>FORK Optn:Varbl[0010:TempY]-V[0009:TempX] less than
        <>FORK Optn:Varbl[0001:HeroX]-V[0003:WatchX] more than
            <>FORK Optn:Varbl[0009:TempX]-5less
                <>Damage Enemy: Enemy1
                <>Play SE: Damage2
            : END Case
        : END Case
    : END Case
: END Case
<>FORK Optn:Hero - Right Face Direct
    <>FORK Optn:Varbl[0010:TempY]-V[0009:TempX] less than
        <>FORK Optn:Varbl[0001:HeroX]-V[0003:WatchX] less than
            <>FORK Optn:Varbl[0009:TempY]-5less
                <>Damage Enemy: Enemy1
                <>Play SE: Damage2
            : END Case
        : END Case
    : END Case
: END Case


Obviously, you have to repeat all of this (including the above code that sets the WatchX/Y and TempX/Y variables), but it's mostly "copy and paste"-compatible :).



Target Screen Spells

Target Screen spells are spells that will target and effect all enemies that are in the player's viewing area. Unlike Target All spells, Target Screen will not effect enemies in distant areas on a large map, and thus is probably more realistic.

Target Screen spells make use of a pair of rarely-used variable operation values: Hero Scene X and Hero Scene Y. These values will give the position of any event relative to the screen. However, this event reports this location in PIXELS, which means we have to convert it to tile coordinates in order for this info to be useful to us.

First of all, we need to store the hero's curent SceneX and SceneY in two temporary variables:

RPG Maker 2000 Code:

<>Variable Ch:[0009:TempX] Set, Hero Pics X
<>Variable Ch:[0010:TempY] Set, Hero Pics Y


This will give you the location of the center of the hero's feet, which is 8 pixels to the left and 16 pixels below the upper-left corner of the tile. So...to properly convert this into coordinates, we must first subtract these extraneous values from the temporary variables:

RPG Maker 2000 Code:

<>Variable Ch:[0009:TempX] -, 8
<>Variable Ch:[0010:TempY] -, 16


Finally, divide the two variables by 16 (each tile in RM2K is 16x16) to obtain the hero's coordinates reletive to the upper-left corner of the screen:

RPG Maker 2000 Code:

<>Variable Ch:[0009:TempX] /, 16
<>Variable Ch:[0010:TempY] /, 16


So...now we have this information, but how do we use it? Well, we need to know the coordinates of the tile in the upper-left corner of the current screen, right? So, if we know the hero's screen position:



We can get that tile's coordinates by subtracting the hero's actual coordinates by his screen coordinates!

RPG Maker 2000 Code:

<>Variable Ch:[0029:ScreenLeftX] Set, Hero X pos
<>Variable Ch:[0030:ScreenTopY] Set, Hero Y pos
<>Variable Ch:[0029:ScreenLeftX] -, Var.[0009:TempX] val.
<>Variable Ch:[0030:ScreenTopY] -, Var.[0010:TempY] val.


Then, the other corner of the screen is just a matter of adding 14 and 19 to the two variables that we've obtained:

RPG Maker 2000 Code:

<>Variable Ch:[0031:ScreenRightX] Set, Var.[0029:ScreenLeftX] val.
<>Variable Ch:[0032:ScreenBottomY] Set, Var.[0030:ScreenTopY] val.
<>Variable Ch:[0031:ScreenRightX] +, 19
<>Variable Ch:[0032:ScreenBottomY] +, 14


Now, we can detect if the enemy's coordinates is within that range, and if it is, then DESTROY HIM!!! MWAHAHAHAHA!

RPG Maker 2000 Code:

<>Variable Ch:[0003:WatchX] Set, Enemy1 X pos
<>Variable Ch:[0004:WatchY] Set, Enemy1 Y pos

<>FORK Optn:Varbl[0029:ScreenLeftX]-V[0003:WatchX] less
    <>FORK Optn:Varbl[0031:ScreeRightX]-V[0003:WatchX] above
        <>FORK Optn:Varbl[0030:ScreenTopY]-V[0004:WatchY] less
            <>FORK Optn:Varbl[0032:ScreeBottomY]-V[0004:WatchY] above
                <>Damage Enemy: Enemy1
                <>Play Sound Effect: Damage2
                <>
            : END Case
            <>
        : END Case
    : END Case
    <>
: END Case



So...next ABS tutorial, projectiles, need to type it, must hurry, no time for grammar or conclusion, bye :P.