Need help with creating a custom Area of Effect ability (AOE)

Hey! I’m looking for help that could help to create an custom ability with an area of effect (AOE). I’ve been racking my brain and I might be way overthinking it, thinking in the wrong direction, or it may not be possible. So, I’m hoping someone could guide me on the right track.

I’m creating a boss game that has AOE effects. Generally speaking, this is easy enough to make for a single hero but I come into a problem making it work with multiple heroes independently (two or more enemies), when there are multiple instances of abilities, with their own separate checks and cool downs, and stacking multiple effects.

What I’m looking for in the AoE ability

  • Activates from a trigger. (This could be damage received, using button or ability, a timer etc.)
  • Creates a fixed visual effect and sound from the point a player is standing. (I’m not going to worry about targeting a ranged position so think of this as like Soldier’s AOE heal, once it’s placed it’s fixed. I thought to store these in variables)
  • The AOE should be triggered independently for each individual or specific player or bot when their own conditions are satisfied. (I thought to store these in arrays)

Additional things that I’m stuck with:

  1. A player could create multiple AOEs multiple times so long as conditions are met in succession or the ability calls for multiple effects at once.

Imagine a boss character casting a couple AOE for damaging other players. I thought to store these in arrays.

  1. Each player’s independent AOE cast should have it’s own duration.

The Rules I use seem to wait on each other if you use the Wait action as a duration timer before removing them, thus creating a queue of effects waiting to be removed. This is a problem, and I’m thinking chasing variables might resolve this but I don’t know how to go about it. For example, if I use an AoE and then another 2 seconds later, the 2nd one should run out 2 seconds after the first. But instead they wait for the previous Rule to complete to start it’s own count down.

  1. Each player should be affected by all instances of an AoE they are in, even if overlapped.

For example, if there are two effects stacked or overlapping on top of each other, or the player moves within a second one while in another, if each would heal 20 HPS, then the user should be getting 20 and another 20 HPS from both as long as the player is within the area of both.

Note: It seems that maybe there are limitations that do not allow this on the OW engine or I’m going about it wrong. Through the normal Conditions filtering I can only seem to get one instance of a trigger to occur, this is with sorting, filtering arrays and checking for distances. As long as I’m satisfying one of the conditions, it remains true and can not cause another instance of true even if I move between positions that overlap. I think I need a way to check if it is true for index or array element and applying an action for each true condition.

(idk if I’m explaining this right or if it’s possible)

  1. If a player leaves a particular AOE, it should have it’s own rule for dispelling its effect immediately or over time (whatever I decide it does).

For example, if the AOE is a heal or damage over time (like a “poison”) when a player enters it, it would be applied. If they leave the AOE, the duration of the ability runs out, or it is removed, then there could or could not be a lingering effect. This seems simple enough to say Is poisoned and manage that single state, but it becomes complicated with two or more instances of poison (which maybe I shouldn’t do this or it is limited).

TL;DR
It seems like a lot to unpack but I want to make what I thought to be a pretty basic AOE. Think of it as like Soldier 76’s healing station that can be spammed multiple times and stacks its effects. I think I’m having trouble figuring out handling the duration for multiple abilities, stacking effects of each ability from the same or multiple casters, and using the right Conditions check for each item in an array, that’s about it. If anyone has info, advice, code I could dissect, or toss me random links, any help to this goal would be greatly appreciated. Thanks!

Amazingly written post, was really helpful.

So far I’ve managed to do everything but problem number 3. But I think I could solve this problem if I had a bit more time but I can’t right now, I will try to finish it by tomorrow tho

For the AoE effect just put it the first subroutine named “AoE effect” with “Currently_in_AoE” as an array with all players currently in an AoE

Here’s the code of what I have done so far KZHCT. It’s not very optimised for it might cause crashes with a bigger script

2 Likes

I think, the best solution is to store the time stamp of AOEs with the same duration into an array. Imagine you have one array for all the AOEs center positions, one array for all the effect IDs, etc.
Code example (parts between stars are placeholders for actual values):

rule "create AOE"
ongoing each player

condition:
- *the conditions to trigger the AOE creation*

action:
- modify global variable(centerPos, append to array, *center position of the AOE*)
- create effect(...)
- modify global variable(effectID, append to array, last created entity)
- modify global variable(aoeOwner, append to array, event player)
- modify global variable(timestamp, append to array, total time elapsed)
rule "AOE times out"
ongoing global

condition:
- count of(global.timestamp) >= 1
- total time elapsed - first of(global.timestamp) >= *the duration of the AOE in seconds*

action:
- destroy effect(first of(global.effectID))
- modify global variable(centerPos, remove from array by index, 0)
- modify global variable(effectID, remove from array by index, 0)
- modify global variable(aoeOwner, remove from array by index, 0)
- modify global variable(timestamp, remove from array by index, 0)

You can do this by filtering for AOE with distance between event player < radius, then counting the array size:

rule "player in aoe"
ongoing each player

condition:
- is true for any(global.centerPos, distance between(event player, current array element) <= *radius*) == true

action:
- event player.insideAOEs = filtered array(global.centerPos, distance between(event player, current array element) <= *radius*)
- for player variable(loopCounter, 0, count of(event player.insideAOEs))
- heal(event player, global.aoeOwner[index of array value(global.centerPos, event player.insideAOEs[event player.loopCounter])]), 20)
- end

Edit: Mareaucanard sneaked in there XD But I got problem number 3 done, so I was at least a little helpful :slight_smile:

3 Likes

You bringed some very good concept and ideas, I really like it!
I don’t think what I have done is as optimized as what you did tho, is it okay if I take inspiration from that?

1 Like

Of course. When we combine our ideas, we can achieve the best results :slight_smile:

1 Like

This is tremendous help! Way more elegantly written than whatever I fiddled around with to come up with lol. Here’s my ugly set up I did last night H8KAN

I managed to make something that could detect multiple people, check for multiple stacked areas, prevent from repeating on others when another entered and triggered (store, damage non-saved, save etc). Although, I couldn’t get my condition to trigger when someone was already spawned in the created area and check for entry, it was one or the other for some reason. I’ll test these conditions and see if these will work out. Both of these timers look great too, very smart solutions. I will probably have to dissect them and combine them to complete what works best for me. I might not use the targeting thing for now but down the line it will be great because I could do some fun little fireball stuff with it. I’m still amateurish with coding so its cool to read and learn. Thanks!

Feel free to suggest more ideas, this might be great reference for the forum! :smiley:

2 Likes

I’m a little confused on the Healer part, would you mind explaining how to input this in the workshop?

The idea is to reference each AOE by its current index i. So the center position is at global.centerPos[i], the owner is at global.aoeOwner[i], etc.
In this case, I want to get the Owner of AOE i, so I can input him as healer, but I can’t just use the current index in this loop-iteration (event player.loopCounter), because the array event player.insideAOEs (the array of AOEs the event player is currently inside) is in a different order than the other arrays.
So in order to get the current i, I need to find out wich center position the current array element is and wich index it has in the array global.centerPos.

In workshop you create it like this:

value in array(
array - global.aoeOwner
index - index of array value(
        array - global.centerPos
        value - value in array(
                array - event player.insideAOEs
                index - event player.loopCounter
                )
        )
)
1 Like

Awesome, thank you for the explanation :slightly_smiling_face:

Just a note for reference, for Shanalotte’s version of cool down managing, I added a Loop If Condition Is True with the shortest Wait time before it to deal with the simultaneous creation of two areas of effect by 2 or more players (bots) triggered by the same source. It could be done another way but for now this works for what I need.

2 Likes