For the final post of the night, I'll be giving an example of how I plan to handle attacks in my game. Thanks to the help I've already received, I'm able to conquer roadblocks that have stopped me in the past. However, one seemingly minor detail still stands in the way: factoring in the chance to critically hit. At first, I thought "of course, that's easy, all I have to do is use an "X chances out of Y" condition such as "<crit chance> chances out of 1" (1 = 1.00 = 100%). Unfortunately it's not quite that easy, because I cannot find a way to perform an action when that chance *FAILS*. It'll be more obvious as I show how I plan to make this work.
Legend:
<> = Fastloop
--> = "then" (as in, "if then" statement)
[] = Input (from the player)
{} = Perform an action
& = Signifies another condition or action
Bold Letters = This line represents a GROUP of events
Normal Letters = This line represents an EVENT
Italic Letters = This term represents a scripted (or soon to be scripted) part of the code, such as a targeted enemy or a player's critical chance.
PS: I'm using "smash" as an example for the name of the ability.
This following code represents the original way I planned to handle critical hits, but I will point out the flaw afterwards if you do not spot it yourself.
[B]Inputs[/B]
- [B]Ability Input[/B]
- [B]Smash Input[/B]
- 1 [Smash Icon Click] --> Trigger <Smash> & {Play "Click" Sound}
- 1 [Smash Hotkey Press] --> Trigger <Smash>
- [B]Ability Input[/B]
- [B]Ability Input[/B]
[B]Lifecycle[/B]
- [B]Ability Lifecycle[/B]
- [B]Smash Lifecycle[/B]
- 1 If <Smash> --> {Play Animation "Smash"}
- 2 If Animation Smash is playing & Animation Frame is equal to 3 & Only one action when event loops --> {Play "Whoosh" Sound}
- 2 If Animation Smash is playing & Animation Frame is equal to 8 & Only one action when event loops --> {Play "Smash" Sound} & Trigger <Smash_Output>
- [B]Ability Lifecycle[/B]
- [B]Ability Lifecycle[/B]
[B]Outputs[/B]
- [B]Ability Output[/B]
- [B]Smash Output[/B]
- 1 If <Smash_Output> & [I]Crit Chance[/I] chances out of 100* --> {Turn on Flag 0**} & Trigger <Smash_Output_BC>***
- 2 If <Smash_Output_BC> & Flag 0** is off --> {deal [I]damage[/I] to [I]targeted enemy[/I]} & Trigger <Smash_Output_AC>***
- 2 If <Smash_Output_BC> & Flag 0** is on --> {deal [I]crit damage[/I] to [I]targeted enemy[/I]} & Trigger <Smash_Output_AC>***
- 3 If <Smash_Output_AC> & [I]Proc Chance[/I] chances out of 100* --> {Apply [I]effect[/I]****}
- 3 If <Smash_Output_AC> & [I]Proc Chance[/I] chances out of 100* --> {Apply [I]effect[/I]****}
- 3 If <Smash_Output_AC> & [I]Proc Chance[/I] chances out of 100* --> {Apply [I]effect[/I]****}
- [B]Ability Output[/B]
- [B]Ability Output[/B]
* or 1, as the case may be. Technically it'd be 1, since the Critical Chance will be a percentage such as 22%, which translates to .22. Therefore it would be a 1 so that it is .22 chances out of 1, or 22 chances out of 100.
** Flag 0 of whatever object would've dealt with such things. Most likely, I would have made one object to hold all of the flags (one for each attack).
*** BC stands for Before Crit, whereas AC stands for After Crit.
**** This effect could be a buff or a debuff, to oneself, to an enemy target, or to a friendly target. Interaction with friendly targets will come later, though.
Display More
As mentioned, interaction with friendly targets (buffs, healing, CONVERSATIONS (bane of my existence!), etc.) will come later. For now I'm primarily concerned just with combat with enemies. Once I have a good base code for abilities including damage, cooldown, procs, and other stuff like that, making new abilities will pretty much be smooth sailing. Just copy and paste, change the names, sounds, values, and it's done.
Two points I want to make. First, since I haven't used the term 'proc' yet, I just want to make sure the meaning is reasonably clear. Let's say your character has a 30% chance to activate a DoT when using a certain attack. You use the attack, the DoT activates. You have 'procced' the DoT. The chance to activate that DoT is referred to as the 'proc chance'. The DoT itself which has been activated is also sometimes referred to as a 'proc', and (though I haven't used the term yet) people sometimes refer to the random chance involved in that proc as 'RNG', which means "random number generator". It refers to the chance involved in percent-possibilities to proc something. For example, you have an attack which hits three times over the span of three seconds. Each time it hits, it has a 60% chance to proc an effect. You use the ability, go through all three ticks, and don't get the proc. That could be referred to as having "bad RNG".
The second point I want to make is the fundamental flaw in the above code, the fact that my handling of Critical Chance is wrong. At first glance it might look totally fine, but if you think about it for a second, it goes a little something like this. First, you activate your ability, either by clicking on the icon or by pressing a hotkey. The ability is now activated, and runs the fastloop <Ability>. The fastloop <Ability> activates an animation, and when that animation reaches a certain frame, it activates <Ability_Output>. Okay, up until now, we're totally fine. Now comes the problem. I say that if <Ability_Output> is activated, and if Crit Chance chances out of 1, then activate Flag 0 and run fastloop <Ability_Output_BC>. The problem comes when the ability does not critically hit. This event only fires if <Ability_Output> is activated and the Crit Chance chances out of 1 succeeds. What if it doesn't? Well, obviously, Flag 0 is not turned on. However... since it's the same command, that also means <Ability_Output_BC> is never activated. It only activates if the ability critically hits.
This comes down to a bigger problem which concerns the "X chances out of Y" condition. This event only tests whether it succeeds. If it succeeds, then do action A B and C. But there's no way to test what happens when it doesn't succeed. If you copy and paste the event, and invert the condition (if that's possible, which it probably is) it's not going to have the same random number selected as the other event. Also, as a side-note, I really don't like the idea of activating a flag if it succeeds at the crit roll, then testing for that flag and using separate events to deal damage depending on whether or not that flag is off or on. I couldn't think of a better way to do it, but this method (obviously) was not a satisfactory solution either.
I'm curious how I could factor a critical chance into the damage dealt. If it was a simple 50% chance, I could use (Base Damage) + (Random(2) * (Crit Damage)), so it would have a 50% chance to deal the crit damage (and my crit damage will be more complicated than a simple static value). Unfortunately, this is reality, and my crit chance will not be a nice neat 50% chance (nor should it). So with that said, I'm open to any ideas related to a variable percent chance to apply a variable percent bonus to a base damage value.
PS: Is there an expression in the Special (first "object" in the list) category for this, just like there is for the "X chances out of Y" condition? I could see that solving the problem. I'd have a single command, and run the crit roll right inside of the equation, applying it if it wins, and ignoring it if it loses.