The player has 10 HP and the other party member has 10 HP as well.
However, when I play in-game, the enemy sprite will touch the player and they will die in less than 10 hits! Sometimes it takes 2 hits, other times it's 4 or something. I allowed knockout, so is this the issue? If so, how can I go around that and make it wait until the player has 1 HP before causing knockout?
I can tell you just by looking at it, you're mixing terms that are used separately.
but I'll try and eyeball it from what you explain, and submit you're probably running that -1 in parallel, and parallel processes happen WAY faster than you think.
you see one hit, but the game would run at least at 60FPS, so 60 actual -1's are happening at the same time.
just for the record tho: you're mixing terms.... Sprites (code objects) are one thing, *sprites* (generic graphical icons) are another, and "sprites" (mythic ghosts) are another.
I think I know what you're going for, and that's not handled like that (or, *is*, depending on your battle system)
are you using an action battle system like Zelda or similar?
I can tell you just by looking at it, you're mixing terms that are used separately.
but I'll try and eyeball it from what you explain, and submit you're probably running that -1 in parallel, and parallel processes happen WAY faster than you think.
you see one hit, but the game would run at least at 60FPS, so 60 actual -1's are happening at the same time.
just for the record tho: you're mixing terms.... Sprites (code objects) are one thing, *sprites* (generic graphical icons) are another, and "sprites" (mythic ghosts) are another.
I can tell you just by looking at it, you're mixing terms that are used separately.
but I'll try and eyeball it from what you explain, and submit you're probably running that -1 in parallel, and parallel processes happen WAY faster than you think.
you see one hit, but the game would run at least at 60FPS, so 60 actual -1's are happening at the same time.
just for the record tho: you're mixing terms.... Sprites (code objects) are one thing, *sprites* (generic graphical icons) are another, and "sprites" (mythic ghosts) are another.
I think I know what you're going for, and that's not handled like that (or, *is*, depending on your battle system)
are you using an action battle system like Zelda or similar?
Also, I'm not using any scripts changing the battle system, I just want to avoid going into a default battle and want an enemy that can move on the map itself.
those are events, not sprites.
they were called sprites generically in the days of the Commodore 64
that's where the term "sprite" (the code object) comes from: the image that represents the object.... but these are *event* objects, with the sprite on top, which is a *character* (*itself* a sprite), and the set of instructions within, which is an *interpreter* object.
those are events, not sprites.
they were called sprites generically in the days of the Commodore 64
that's where the term "sprite" (the code object) comes from: the image that represents the object.... but these are *event* objects, with the sprite on top, which is a *character* (*itself* a sprite), and the set of instructions within, which is an *interpreter* object.
not a wait, but maybe an exit event, or a self switch.
the thing is, it's running too fast, at the moment of contact with the player.
I don't remember if exiting the process would cause the event to reset it's touch validation, but the problem can be fixed or at least adjusted..... there are ways around it.
@QueenTeaYT That's more or less the way to go. In case you are wondering why that happens: both player touch and event touch trigger whenever an action that would make the player and the event have the same coordinates is queued (respectively a player action or an event action), even if it cannot be executed because they collide. In this case, while the event chases the player, if the player stands on a tile and the event tries to step on the same tile, the event is triggered.
Executing the event commands, however, only takes a single frame, but in the next frame (it does not actually happen each frame, but it is still very fast), when the event tries to chase the player once again, the same thing happens. This loop only stops when the player coordinates change and the event can move.
To be completely honest, using "Wait" might still lead to nasty issues if not timed properly (the damage might be dealt twice: once when hitting the player, once again as soon as the player moves another step after the wait command ends). The way to time it properly to avoid the aforementioned issue is this:
Code:
pick_a_var = var_id_here # E.g. 12, do not use it in your game for anything else
pick_a_switch = switch_id_here # Read below
cd = set_a_cooldown_for_damage_here # E.g. 30
unless $game_variables[pick_a_var].is_a?(Array)
$game_variables[pick_a_var] = [-1, -1, 0]
end # You can write this in a single line, but it might be too long.
same_x = ($game_variables[pick_a_var][0] == $game_player.x)
same_y = ($game_variables[pick_a_var][1] == $game_player.y)
change_xy = !(same_x && same_y)
cd_expired = ($game_variables[pick_a_var][2] == cd)
if (change_xy || cd_expired)
$game_variables[pick_a_var] = [$game_player.x, $game_player.y, 0]
$game_switches[pick_a_switch] = true
# Alternatively -> $game_self_switches[[$game_map.map_id, @event_id, pick_a_switch]] = true
# If you are using a self switch, pick_a_switch can be 'A', 'B', 'C' or 'D',
# it doesn't make any difference, as long as you use quotation marks.
else
$game_variables[pick_a_var][2] += 1
end
In your event you can then check for the said switch, if it is true, you deal damage, if it is false, you do nothing.
This logic basically checks if you have already dealt damage to the player in that position and prevents your event from dealing damage once again until the player moves or until too many attempts to hurt the player fail (otherwise the player could just stay still in the same place forever and become invulnerable). The amount of failed attempts is up to you, it depends on how many times you want the player to be able to avoid damage while standing, I recommend using a high enough number like 30 or 60. Anyway, if the player moves, the event can deal damage once again.
All this goes in a script call. It basically works in the same way as the Wait command that Shaz suggested, but prevents the nasty interaction that I mentioned above.
EDIT
You could even deal damage within the script call itself, without having to use a switch, but I think that this option should be good enough for you, and it also allows you to control damage easily without having to edit the script call later on.
EDIT 2 @Shaz the reason why I would refrain from using a wait command here is that, if not timed properly, it would also prevent the player from moving smoothly (this is not a parallel process after all).
According to the amount of frames left for the player sprite to complete its movement, the event can wait less than that amount, the same as that amount or more than that amount.
Less
The event deals damage, the player is still moving (thus on the same square) and the event triggers once again. This repeats until the movement is completed. After that you have two different situations:
The player can queue a new action (which means that the wait command expired)
When this is the case, the event still runs once more together with the first frame of the player movement, then the wait command starts counting, but it is irrelevant since the player is already moving.
The player cannot queue a new action (which means that the wait command is still waiting)
If this happens the player can only queue a new action once the wait command stops counting, which leads to the previous point.
Same
The event deals damage, the player ends the movement, and can queue a new action immediately. This, however, is the same as the first point of the previous case, so it is still somewhat incorrect.
More
The event deals damage, the player ends the movement, but no new action can be queued because the wait command is still ongoing. This is the same as the second point of the first case, which means that the player will have to wait before being able to move.
@QueenTeaYT That's more or less the way to go. In case you are wondering why that happens: both player touch and event touch trigger whenever an action that would make the player and the event have the same coordinates is queued (respectively a player action or an event action), even if it cannot be executed because they collide. In this case, while the event chases the player, if the player stands on a tile and the event tries to step on the same tile, the event is triggered.
Executing the event commands, however, only takes a single frame, but in the next frame (it does not actually happen each frame, but it is still very fast), when the event tries to chase the player once again, the same thing happens. This loop only stops when the player coordinates change and the event can move.
To be completely honest, using "Wait" might still lead to nasty issues if not timed properly (the damage might be dealt twice: once when hitting the player, once again as soon as the player moves another step after the wait command ends). The way to time it properly to avoid the aforementioned issue is this:
Code:
pick_a_var = var_id_here # E.g. 12, do not use it in your game for anything else
pick_a_switch = switch_id_here # Read below
cd = set_a_cooldown_for_damage_here # E.g. 30
unless $game_variables[pick_a_var].is_a?(Array)
$game_variables[pick_a_var] = [-1, -1, 0]
end # You can write this in a single line, but it might be too long.
same_x = ($game_variables[pick_a_var][0] == $game_player.x)
same_y = ($game_variables[pick_a_var][1] == $game_player.y)
change_xy = !(same_x && same_y)
cd_expired = ($game_variables[pick_a_var][2] == cd)
if (change_xy || cd_expired)
$game_variables[pick_a_var] = [$game_player.x, $game_player.y, 0]
$game_switches[pick_a_switch] = true
# Alternatively -> $game_self_switches[[$game_map.map_id, @event_id, pick_a_switch]] = true
# If you are using a self switch, pick_a_switch can be 'A', 'B', 'C' or 'D',
# it doesn't make any difference, as long as you use quotation marks.
else
$game_variables[pick_a_var][2] += 1
end
In your event you can then check for the said switch, if it is true, you deal damage, if it is false, you do nothing.
This logic basically checks if you have already dealt damage to the player in that position and prevents your event from dealing damage once again until the player moves or until too many attempts to hurt the player fail (otherwise the player could just stay still in the same place forever and become invulnerable). The amount of failed attempts is up to you, it depends on how many times you want the player to be able to avoid damage while standing, I recommend using a high enough number like 30 or 60. Anyway, if the player moves, the event can deal damage once again.
All this goes in a script call. It basically works in the same way as the Wait command that Shaz suggested, but prevents the nasty interaction that I mentioned above.
EDIT
You could even deal damage within the script call itself, without having to use a switch, but I think that this option should be good enough for you, and it also allows you to control damage easily without having to edit the script call later on.
EDIT 2 @Shaz the reason why I would refrain from using a wait command here is that, if not timed properly, it would also prevent the player from moving smoothly (this is not a parallel process after all).
According to the amount of frames left for the player sprite to complete its movement, the event can wait less than that amount, the same as that amount or more than that amount.
Less
The event deals damage, the player is still moving (thus on the same square) and the event triggers once again. This repeats until the movement is completed. After that you have two different situations:
The player can queue a new action (which means that the wait command expired)
When this is the case, the event still runs once more together with the first frame of the player movement, then the wait command starts counting, but it is irrelevant since the player is already moving.
The player cannot queue a new action (which means that the wait command is still waiting)
If this happens the player can only queue a new action once the wait command stops counting, which leads to the previous point.
Same
The event deals damage, the player ends the movement, and can queue a new action immediately. This, however, is the same as the first point of the previous case, so it is still somewhat incorrect.
More
The event deals damage, the player ends the movement, but no new action can be queued because the wait command is still ongoing. This is the same as the second point of the first case, which means that the player will have to wait before being able to move.
Oh my gosh thank you for this in-depth explanation and for even providing a solution!! You made it really easy to understand and I'm super excited I can do all this without a special script.
In theory, could I do this kind of damage to the event as well? Meaning, could the player "action button" the event and deal damage until the event "dies?"
@QueenTeaYT I am glad to read that you found my explanation useful. Concerning the other matter, as Shaz already said, you cannot have an event that has two different kind of triggers. However, what you can do is using a parallel process event to check if the player is pressing the action button and facing one of those events at the same time. The script call is very simple:
Code:
var_id = your_var_id_here # This is used to store harmful events
$game_variables[var_id] = [0, []] unless $game_variables[var_id].is_a?(Array)
$game_variables[var_id][0] = $game_map.map_id
# You can add as many event IDs as you want in the following line
$game_variables[var_id][1].replace([eventID, anotherEventID, etc])
if (Input.trigger?(:C))
event_hit_id = 0
hit = false
round_x = $game_map.round_x_with_dir($game_player.x, $game_player.direction)
round_y = $game_map.round_y_with_dir($game_player.y, $game_player.direction)
$game_variables[var_id][1].each do |i|
ev = $game_map.events[i]
if ((ev.x == round_x) && (ev.y == round_y))
hit = true
event_hit_id = i
break
end
$game_self_switches[[$game_map.map_id, @event_id, 'A']] = hit
$game_variables[another_variable_id_goes_here] = event_hit_id if hit
end
end
This goes under the assumption that you have no harmful event with the "Through" setting checked. You can then use the self switch containing the hit result and the variable containing the hit event ID to do anything you want in your event. It is pretty basic, but it should be a solid way to build a rudimentary action battle system without using scripts.
I recommend initializing the variable containing their health in a similar way as I initialized the variable containing their ID, it is pretty efficient and also solid and does not lead to memory leaks. When an event health reaches 0, you can then use a self switch to remember that so that it has no effect the next time the player enters the map.
IMPORTANT NOTE
You could achieve the same thing using the built-in method to check if any event is located at the rounded coordinates you obtain, but doing that includes a linear check on each event in the map, even those that are not harmful. Using the code I provided is more efficient than doing that, even if it takes a few more lines of code.
Let me know if it fits your script call box. It can be shortened or split in two if necessary.
@QueenTeaYT I am glad to read that you found my explanation useful. Concerning the other matter, as Shaz already said, you cannot have an event that has two different kind of triggers. However, what you can do is using a parallel process event to check if the player is pressing the action button and facing one of those events at the same time. The script call is very simple:
Code:
var_id = your_var_id_here # This is used to store harmful events
$game_variables[var_id] = [0, []] unless $game_variables[var_id].is_a?(Array)
$game_variables[var_id][0] = $game_map.map_id
# You can add as many event IDs as you want in the following line
$game_variables[var_id][1].replace([eventID, anotherEventID, etc])
if (Input.trigger?(:C))
event_hit_id = 0
hit = false
round_x = $game_map.round_x_with_dir($game_player.x, $game_player.direction)
round_y = $game_map.round_y_with_dir($game_player.y, $game_player.direction)
$game_variables[var_id][1].each do |i|
ev = $game_map.events[i]
if ((ev.x == round_x) && (ev.y == round_y))
hit = true
event_hit_id = i
break
end
$game_self_switches[[$game_map.map_id, @event_id, 'A']] = hit
$game_variables[another_variable_id_goes_here] = event_hit_id if hit
end
end
This goes under the assumption that you have no harmful event with the "Through" setting checked. You can then use the self switch containing the hit result and the variable containing the hit event ID to do anything you want in your event. It is pretty basic, but it should be a solid way to build a rudimentary action battle system without using scripts.
I recommend initializing the variable containing their health in a similar way as I initialized the variable containing their ID, it is pretty efficient and also solid and does not lead to memory leaks. When an event health reaches 0, you can then use a self switch to remember that so that it has no effect the next time the player enters the map.
IMPORTANT NOTE
You could achieve the same thing using the built-in method to check if any event is located at the rounded coordinates you obtain, but doing that includes a linear check on each event in the map, even those that are not harmful. Using the code I provided is more efficient than doing that, even if it takes a few more lines of code.
Let me know if it fits your script call box. It can be shortened or split in two if necessary.
It is a bit info-packed, so I will spend some time using your advice to figure it all out. Thank you so much, I appreciate you going above and beyond my original question to help.
@taarna23's status just made me realise I haven't had any scam calls since that guy who hung up on me before he even began reading his script. How quiet it's been ... they were pretty much the only people who ever called!
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.