• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] CustomAttack feedback wanted before submitting

Status
Not open for further replies.
Level 31
Joined
Jul 10, 2007
Messages
6,306
Hi all. Before submitting this system, I'd like to polish it off, get some feedback on what could be improved, should be added, removed, and etc : ).

This code should give you an idea as to what it does
JASS:
library tester initializer init uses CustomAttack
    globals
        CustomAttack attack
    endglobals
    
    private function myattack takes nothing returns boolean
        if (CustomAttack.triggerAttack.isHit(false)) then
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, GetUnitName(CustomAttack.triggerAttack.attacker) + " is attacking " + GetUnitName(CustomAttack.triggerAttack.attackedUnit))
        endif
        return false
    endfunction
    
    private function init takes nothing returns nothing
        local unit u = CreateUnit(Player(0), 'hpea', 2000, 1900, 90)
        local unit u2 = CreateUnit(Player(0), 'hpea', 2000, 2000, 0)
        local unit u3 = CreateUnit(Player(0), 'hpea', 2000, 2200, 0)
        set attack = CustomAttack.create()
        set attack.attacker = u
        set attack.maxTargets = -1
        set attack.code = Condition(function myattack)
        set attack.left = 150
        set attack.right = 150
        set attack.back = 60
        set attack.front = 300
        set attack.trigger = CreateTrigger()
        call TriggerRegisterPlayerEvent(attack.trigger, Player(0), EVENT_PLAYER_CHAT)
    endfunction
endlibrary

I create a little diamon with attack.left, attack.right, attack.back, attack.front. I make it so that when I chat, my little unit attacks. maxTargets of -1 makes infinite targets and myattack is the attack code that runs.

Here are some of the main methods so a better understanding can be achieved
public method attackPosition takes real x, real y, real facing returns nothing
public method isInAttackRange takes real x, real y, real facing, unit u returns boolean
public method isHit takes boolean targetSelf returns boolean

So this is the code (some extra stuff in it so that people can see what's going on if they decide to run the above)
JASS:
library CustomAttack uses UnitIndexer, IsPointInTriangle
    struct CustomAttack extends array
        public unit attacker
        
        private static integer instanceCount = 0
        private static integer array recycle
        private static integer recycleCount = 0
        
        private static hashtable attackTable
        
        private static code attackTargetsClear
        private static code attackTargetsAdd
        private static code attackTargetsRemove
        private static boolexpr attackEvent
        private static boolexpr attackTarget
        private trigger attackTrigger
        
        private boolexpr attackFilter
        private boolexpr attackCode
        private boolexpr attackTargetCode
        private trigger attackCodeTrigger
        
        private group targetGroup
        public integer maxTargets
        private integer target_Count
        
        private static group array enumGroup
        private static thistype array triggeringAttack
        private static integer attackCount = 0
        
        //attack max ranges
        public real right
        public real left
        public real front
        public real back
        //attack min ranges
        public real minRight
        public real minLeft
        public real minFront
        public real minBack
        
        //attack rectangle
        private real ax
        private real ay
        private real bx
        private real by
        private real cx
        private real cy
        private real dx
        private real dy
        //non attack rectangle
        private real nax
        private real nay
        private real nbx
        private real nby
        private real ncx
        private real ncy
        private real ndx
        private real ndy
        
        private static real worldMaxX
        private static real worldMaxY
        private static real worldMinX
        private static real worldMinY
        
        public method operator targets takes nothing returns group
            return targetGroup
        endmethod
        
        public method isTarget takes unit u returns boolean
            return IsUnitInGroup(u, targetGroup)
        endmethod
        
        public method addTarget takes unit u returns boolean
            if ((maxTargets < 0 or target_Count < maxTargets) and not IsUnitInGroup(u, targetGroup)) then
                call GroupAddUnit(targetGroup, u)
                set target_Count = target_Count + 1
                return true
            endif
            return false
        endmethod
        
        public method removeTarget takes unit u returns boolean
            if (IsUnitInGroup(u, targetGroup)) then
                call GroupRemoveUnit(targetGroup, u)
                set target_Count = target_Count - 1
                return true
            endif
            return false
        endmethod
        
        public method operator targetCount takes nothing returns integer
            return target_Count
        endmethod
        
        public method operator trigger takes nothing returns trigger
            return attackCodeTrigger
        endmethod
        
        public method operator trigger= takes trigger t returns nothing
            if (attackCodeTrigger != null) then
                call TriggerClearConditions(attackCodeTrigger)
                call RemoveSavedInteger(attackTable, GetHandleId(attackCodeTrigger), 0)
                call DestroyTrigger(attackCodeTrigger)
            endif
            
            set attackCodeTrigger = t
            
            if (t != null) then
                call SaveInteger(attackTable, GetHandleId(t), 0, this)
                call TriggerAddCondition(t, attackEvent)
            endif
        endmethod
        
        public method operator filter takes nothing returns boolexpr
            return attackFilter
        endmethod
        
        public method operator filter= takes boolexpr c returns nothing
            set attackFilter = c
        endmethod
        
        public method operator code takes nothing returns boolexpr
            return attackCode
        endmethod
        
        public method operator code= takes boolexpr c returns nothing
            set attackCode = c
            if (attackTargetCode != null) then
                call DestroyBoolExpr(attackTargetCode)
            endif
            if (c != null) then
                set attackTargetCode = And(attackTarget, c)
            else
                set attackTargetCode = null
            endif
        endmethod
        
        public static method operator attackedUnit takes nothing returns unit
            return GetFilterUnit()
        endmethod
        
        public static method operator triggerAttack takes nothing returns thistype
            return triggeringAttack[attackCount]
        endmethod
        
        public method operator backX takes nothing returns real
            return ax
        endmethod
        
        public method operator backY takes nothing returns real
            return ay
        endmethod
        
        public method operator frontX takes nothing returns real
            return bx
        endmethod
        
        public method operator frontY takes nothing returns real
            return by
        endmethod
        
        public method operator leftX takes nothing returns real
            return cx
        endmethod
        
        public method operator leftY takes nothing returns real
            return cy
        endmethod
        
        public method operator rightX takes nothing returns real
            return dx
        endmethod
        
        public method operator rightY takes nothing returns real
            return dy
        endmethod
        
        public method operator nBackX takes nothing returns real
            return nax
        endmethod
        
        public method operator nBackY takes nothing returns real
            return nay
        endmethod
        
        public method operator nFrontX takes nothing returns real
            return nbx
        endmethod
        
        public method operator nFrontY takes nothing returns real
            return nby
        endmethod
        
        public method operator nLeftX takes nothing returns real
            return ncx
        endmethod
        
        public method operator nLeftY takes nothing returns real
            return ncy
        endmethod
        
        public method operator nRightX takes nothing returns real
            return ndx
        endmethod
        
        public method operator nRightY takes nothing returns real
            return ndy
        endmethod
        
        //width of attack
        public method operator width= takes real val returns nothing
            set right = val/2
            set left = val/2
        endmethod
        
        public method operator width takes nothing returns real
            return left+right
        endmethod
        
        //minimum attack radius
        public method operator minRadius= takes real val returns nothing
            set minRight = val
            set minLeft = val
            set minFront = val
            set minBack = val
        endmethod
        
        public method operator minRadius takes nothing returns real
            return (minRight+minLeft+minFront+minBack)/4
        endmethod
        
        public method isHit takes boolean targetSelf returns boolean
            local real tx
            local real ty
            
            if (targetSelf or GetFilterUnit() != attacker) then
                set tx = GetUnitX(GetFilterUnit())
                set ty = GetUnitY(GetFilterUnit())
                return not (IsPointInTriangle(nax, nay, ncx, ncy, ndx, ndy, tx, ty) or IsPointInTriangle(nbx, nby, ncx, ncy, ndx, ndy, tx, ty)) and (IsPointInTriangle(ax, ay, cx, cy, dx, dy, tx, ty) or IsPointInTriangle(bx, by, cx, cy, dx, dy, tx, ty))
            endif
            return false
        endmethod
        
        public method isInAttackRange takes real x, real y, real facing, unit u returns boolean
            local real yProj
            local real xProj
            local real tx
            local real ty
            set tx = GetUnitX(u)
            set ty = GetUnitY(u)
            
            set facing = facing*bj_DEGTORAD
            set xProj = Cos(facing)
            set yProj = Sin(facing)
            set rs[0] = x - back*xProj
            set rs[1] = x + front*xProj
            set rs[4] = y - back*yProj
            set rs[5] = y + front*yProj
            
            set rs[10] = x - minBack*xProj
            set rs[11] = x + minFront*xProj
            set rs[14] = y - minBack*yProj
            set rs[15] = y + minFront*yProj
            
            set facing = facing + bj_PI/2
            set xProj = Cos(facing)
            set yProj = Sin(facing)
            set rs[2] = x + left*xProj
            set rs[3] = x - right*xProj
            set rs[6] = y + left*yProj
            set rs[7] = y - right*yProj
            
            set rs[12] = x + minLeft*xProj
            set rs[13] = x - minRight*xProj
            set rs[16] = y + minLeft*yProj
            set rs[17] = y - minRight*yProj
            
            return not (IsPointInTriangle(rs[10], rs[14], rs[12], rs[16], rs[13], rs[17], tx, ty) or IsPointInTriangle(rs[11], rs[15], rs[12], rs[16], rs[13], rs[17], tx, ty)) and (IsPointInTriangle(rs[0], rs[4], rs[2], rs[6], rs[3], rs[7], tx, ty) or IsPointInTriangle(rs[1], rs[5], rs[2], rs[6], rs[3], rs[7], tx, ty))
        endmethod
        
        private static real array rs
        public method attackPosition takes real x, real y, real facing returns nothing
            local rect attackRegion
            local real yProj
            local real xProj
            
            local real minX = worldMaxX
            local real minY = worldMaxY
            local real maxX = worldMinX
            local real maxY = worldMinY
            
            local integer i
            
            if (attackTargetCode != null) then 
                set facing = facing*bj_DEGTORAD
                set xProj = Cos(facing)
                set yProj = Sin(facing)
                set rs[0] = x - back*xProj
                set rs[1] = x + front*xProj
                set rs[4] = y - back*yProj
                set rs[5] = y + front*yProj
                
                set rs[10] = x - minBack*xProj
                set rs[11] = x + minFront*xProj
                set rs[14] = y - minBack*yProj
                set rs[15] = y + minFront*yProj
                
                set facing = facing + bj_PI/2
                set xProj = Cos(facing)
                set yProj = Sin(facing)
                set rs[2] = x + left*xProj
                set rs[3] = x - right*xProj
                set rs[6] = y + left*yProj
                set rs[7] = y - right*yProj
                
                set rs[12] = x + minLeft*xProj
                set rs[13] = x - minRight*xProj
                set rs[16] = y + minLeft*yProj
                set rs[17] = y - minRight*yProj
                
                set ax = rs[0]
                set bx = rs[1]
                set cx = rs[2]
                set dx = rs[3]
                set ay = rs[4]
                set by = rs[5]
                set cy = rs[6]
                set dy = rs[7]
                set nax = rs[10]
                set nbx = rs[11]
                set ncx = rs[12]
                set ndx = rs[13]
                set nay = rs[14]
                set nby = rs[15]
                set ncy = rs[16]
                set ndy = rs[17]
                
                set i = 7
                loop
                    if (rs[i] < minX) then
                        set minX = rs[i]
                    elseif (rs[i] > maxX) then
                        set maxX = rs[i]
                    endif
                    if (rs[i] < minY) then
                        set minY = rs[i]
                    elseif (rs[i] > maxY) then
                        set maxY = rs[i]
                    endif
                    set i = i - 1
                    exitwhen i < 0
                endloop
                
                call SetUnitScale(CreateUnit(Player(0), 'hfoo', ax, ay, 0), 1, 1, 1)
                call SetUnitScale(CreateUnit(Player(0), 'hfoo', cx, cy, 0), 1, 1, 1)
                call SetUnitScale(CreateUnit(Player(0), 'hfoo', dx, dy, 0), 1, 1, 1)
                call SetUnitScale(CreateUnit(Player(1), 'hfoo', bx, by, 0), 1, 1, 1)
                call SetUnitScale(CreateUnit(Player(1), 'hfoo', cx, cy, 0), 1, 1, 1)
                call SetUnitScale(CreateUnit(Player(1), 'hfoo', dx, dy, 0), 1, 1, 1)
                
                set attackRegion = Rect(minX, minY, maxX, maxY)
                
                set attackCount = attackCount + 1
                set triggeringAttack[attackCount] = this
                if (enumGroup[attackCount] == null) then
                    set enumGroup[attackCount] = CreateGroup()
                endif
                call GroupEnumUnitsInRect(enumGroup[attackCount], attackRegion, attackFilter)
                if (target_Count != 0) then
                    call ForGroup(targetGroup, attackTargetsClear)
                endif
                if (maxTargets < 0 or target_Count < maxTargets) then
                    call ForGroup(enumGroup[attackCount], attackTargetsAdd)
                elseif (target_Count > maxTargets) then
                    call ForGroup(targetGroup, attackTargetsRemove)
                endif
                call GroupEnumUnitsInRect(enumGroup[attackCount], attackRegion, attackTargetCode)
                call GroupClear(enumGroup[attackCount])
                
                set attackCount = attackCount - 1
                call RemoveRect(attackRegion)
                set attackRegion = null
            endif
        endmethod
        
        private static method attackEventFunc takes nothing returns boolean
            local thistype this = LoadInteger(attackTable, GetHandleId(GetTriggeringTrigger()), 0)
            if (IsUnitIndexed(attacker)) then
                call attackPosition(GetUnitX(attacker), GetUnitY(attacker), GetUnitFacing(attacker))
            endif
            return false
        endmethod
        
        private static method attackTargetsClearFunc takes nothing returns nothing
            if (IsUnitIndexed(GetEnumUnit())) then
                if (not IsUnitInGroup(GetEnumUnit(), enumGroup[attackCount])) then
                    call GroupRemoveUnit(triggeringAttack[attackCount].targetGroup, GetEnumUnit())
                    set triggeringAttack[attackCount].target_Count = triggeringAttack[attackCount].target_Count - 1
                endif
            else
                call GroupRemoveUnit(triggeringAttack[attackCount].targetGroup, GetEnumUnit())
                set triggeringAttack[attackCount].target_Count = triggeringAttack[attackCount].target_Count - 1
            endif
        endmethod
        
        private static method attackTargetsAddFunc takes nothing returns nothing
            if (not IsUnitInGroup(GetEnumUnit(), triggeringAttack[attackCount].targetGroup) and (triggeringAttack[attackCount].maxTargets < 0 or triggeringAttack[attackCount].target_Count < triggeringAttack[attackCount].maxTargets)) then
                call GroupAddUnit(triggeringAttack[attackCount].targetGroup, GetEnumUnit())
                set triggeringAttack[attackCount].target_Count = triggeringAttack[attackCount].target_Count + 1
            endif
        endmethod
        
        private static method attackTargetFunc takes nothing returns boolean
            return IsUnitInGroup(GetFilterUnit(), triggeringAttack[attackCount].targetGroup)
        endmethod
        
        private static method attackTargetsRemoveFunc takes nothing returns nothing
            if (triggeringAttack[attackCount].maxTargets >= 0 and triggeringAttack[attackCount].target_Count > triggeringAttack[attackCount].maxTargets) then
                call GroupRemoveUnit(triggeringAttack[attackCount].targetGroup, GetEnumUnit())
                set triggeringAttack[attackCount].target_Count = triggeringAttack[attackCount].target_Count - 1
            endif
        endmethod
        
        public static method create takes nothing returns thistype
            local thistype this
            if (recycleCount != 0) then
                set recycleCount = recycleCount - 1
                set this = recycle[recycleCount]
            else
                set instanceCount = instanceCount + 1
                set this = instanceCount
            endif
            
            if (targetGroup == null) then
                set targetGroup = CreateGroup()
            endif
            
            return this
        endmethod
        
        public method destroy takes nothing returns nothing
            if (attackTrigger != null) then
                call TriggerClearConditions(attackCodeTrigger)
                call RemoveSavedInteger(attackTable, GetHandleId(attackCodeTrigger), 0)
                call DestroyTrigger(attackCodeTrigger)
                set attackTrigger = null
            endif
            
            if (attackTargetCode != null) then
                set attackCode = null
                call DestroyBoolExpr(attackTargetCode)
                set attackTargetCode = null
            endif
            
            call GroupClear(targetGroup)
            
            set left = 0
            set right = 0
            set front = 0
            set back = 0
            set minLeft = 0
            set minRight = 0
            set minFront = 0
            set minBack = 0
            set target_Count = 0
            set attackFilter = null
            
            set recycle[recycleCount] = this
            set recycleCount = recycleCount + 1
        endmethod
        
        private static method onInit takes nothing returns nothing
            local rect r = GetWorldBounds()
            set worldMaxX = GetRectMaxX(r)
            set worldMaxY = GetRectMaxY(r)
            set worldMinX = GetRectMinX(r)
            set worldMinY = GetRectMinY(r)
            call RemoveRect(r)
            set r = null
            
            set attackTargetsClear = function thistype.attackTargetsClearFunc
            set attackTargetsAdd = function thistype.attackTargetsAddFunc
            set attackTargetsRemove = function thistype.attackTargetsRemoveFunc
            set attackEvent = Condition(function thistype.attackEventFunc)
            set attackTarget = Condition(function thistype.attackTargetFunc)
            
            set attackTable = InitHashtable()
        endmethod
    endstruct
endlibrary

You also need
http://www.hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
http://www.hiveworkshop.com/forums/jass-functions-413/snippet-pointintriangle-180407/

to run it : )

So yea.. I'm hoping this will change the way ORPGs, RPGs, arenas, and etc are created ; P. Manual attacking with targeting or super custom attacks on auto attack ; D.

The next script to do this sort of thing, if anyone is interested, is CustomMotionAttack, which adds motion to the above (like swing a sword along an arc). This will make attacks much more realistic and will damage units more the more exposed they are to an attack ; ).

After that I'll work on CustomDefend and CustomMotionDefend.


CustomAttack can be used for spells, projectiles, melee attacks, or anything else you want.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Where is unit indexer used?
JASS:
//
        private static method attackEventFunc takes nothing returns boolean
            local thistype this = LoadInteger(attackTable, GetHandleId(GetTriggeringTrigger()), 0)
            if (IsUnitIndexed(attacker)) then
                call attackPosition(GetUnitX(attacker), GetUnitY(attacker), GetUnitFacing(attacker))
            endif
            return false
        endmethod

        private static method attackTargetsClearFunc takes nothing returns nothing
            local boolean b
            if (IsUnitIndexed(GetEnumUnit())) then
                if (not IsUnitInGroup(GetEnumUnit(), enumGroup[attackCount])) then
                    call GroupRemoveUnit(triggeringAttack[attackCount].targetGroup, GetEnumUnit())
                    set triggeringAttack[attackCount].target_Count = triggeringAttack[attackCount].target_Count - 1
                else
                    set b = UnitAlive(GetEnumUnit())
                    if ((triggeringAttack[attackCount].targetDead != b) or (triggeringAttack[attackCount].targetLiving != b)) then
                        call GroupRemoveUnit(triggeringAttack[attackCount].targetGroup, GetEnumUnit())
                        set triggeringAttack[attackCount].target_Count = triggeringAttack[attackCount].target_Count - 1
                    endif
                endif
            else
                call GroupRemoveUnit(triggeringAttack[attackCount].targetGroup, GetEnumUnit())
                set triggeringAttack[attackCount].target_Count = triggeringAttack[attackCount].target_Count - 1
            endif
        endmethod

Does it make sense?
JASS:
        //attack rectangle
        private real ax
        private real ay
        private real bx
        private real by
        private real cx
        private real cy
        private real dx
        private real dy
        //non attack rectangle
        private real nax
        private real nay
        private real nbx
        private real nby
        private real ncx
        private real ncy
        private real ndx
        private real ndy

Above coords are hit zones and non hit zones. They are rectangles that are rotated to face the same direction as unit facing or w/e so they form diamonds.

Hit rectangle is the hit zone, where units can be damaged.
Non hit rectangle is the no hit zone, where no units can be damaged.

With both of them, a path is formed where units can be hit that is in the shape of a diamond.

Like the red little diamonds in this picture
http://www.theconcentrium.com/mike/Comm/Sunlightheart/15.jpg

where the unit is standing inside of the diamonds somewhere


The coords are also known as backX, backY, frontX, frontY, leftX, leftY, rightX, rightY, nBackX, nBackY, nFrontX, nFrontY, nLeftX, nLeftY, nRightX, nRightY
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ah, didn't see that, but CustomAttack is the perfect name for this sadly ; ).

It features its own multi targeting system, attack path system, filtering system, and so on... it really is a full blown custom attack that can be applied to anything >.<.

I'll tell you one thing... the targeting thing was a pain : P.

->Also it would be cool if you could create templates for unit types which are automatically applied through UnitIndexer.

I'll get to templates and what not eventually. I was actually thinking of templates for items, not units ; ). I was also thinking about dual wielding and crap since you can have infinite attacks with infinite triggers per unit or w/e.

So you could have a dagger in one hand, a sword in another, 2 hot keys (abilities that are added to unit on equip), and then go all out. I'm thinking of a cooldown system similar to the one found in Dark Alliance 2, save that it'd be one bar per attack thingie. Obviously, that'd be built on top of this (separate thing). The things you can do with this are infinite. The thing I mentioned is just my own personal vision ; P.

Another thing you can do is make regular attacks cooler... for example, when an attacker hits a unit (attacked), you attack the attacked unit's position instead of applying damage, meaning you get the same custom attacks with the auto attack stuff that wc3 has in it (easy auto attack/AI).

For player controlled units, you can have manual control only.

I have other sorts of visions too..

The only problem with this is I don't know how much it can handle in wc3 before lagging. I haven't stress tested it.

The current code is set up to show all the triangles and crap (creates footmen at the corners) so you can see what's going on, so I'd remove the CreateUnit lines before stress testing.

Anyways, any other thoughts?


And also, before I make any of these higher level resources, I need to make CustomMotionAttack, CustomDefend, and CustomMotionDefend. The defense stuff will actually be 100% not connected to the attack stuff, you'll need another resource to link them together, which will probably be CustomCombat or some crap,
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
You wanna add such things too?

Well, those things go on top as separate resources.

I did only the filtering + targeting on purpose ; P

This is more an attack handler as an attack system itself.

Should I call it something like CustomAttackHandler then or CustomHitter or CustomTargeter or something?

Possible combat handler suite-
CustomAttackHandler
CustomMotionAttackHandler
CustomDefendHandler
CustomMotionDefendHandler

CustomStaticDamageHandler (doesn't work with motion at all)
CustomStaticDefendHandler (doesn't work with motion at all)
CustomMotionDamageHandler
CustomMotionDefendHandler

CustomCooldownDamage
CustomCooldownDefend

tx for feedback ;o


btw, what do you think of the filtering/targeting? =)
 
Call this library CustomAttackTargeter, bonus modules CustomAttackMissile, CustomAttackDamage, CustomAttackBlock, CustomAttackMultiplier, CustomAttackEvade, ... etc.

About the targeting: I don't like it at all. It requires way to much calculations to be useful at all. It's just a nice-to-have things, and I am quite sure most people do not care about it at all.

What people are actually looking for is a library that allow them to change attackranges ingame without removing any of the attack functionality that brings wc3 with us.

What you did is creating an engine that checks the range of the attack only. You see why this shouldn't be "CustomAttack", but more like an addon? This library for itself seems to be pretty useless, but with nice addons it can become something great.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Hmmmm... well without the targeting you can't control how many targets you hit and you end up hitting multiple targets >.<. Target control, to me, seems crucial. I just couldn't figure out a good way to do it /cry.

You see why this shouldn't be "CustomAttack", but more like an addon? This library for itself seems to be pretty useless, but with nice addons it can become something great.

Separate resources entirely, they don't need to be add-ons : P
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
edit
After some thought, I realize I can't do the targeting thing as a separate resource... it has to be where it's at or it will have like !iterations.

What I can do is add a targeting boolean, which will enable/disable target tracking

So if targeting is enabled, it'll do it like it is

If it's disabled, it'll use And(filter, attack) in an EnumGroupCounted where count is max targets allowed if max targets >= 0. If max targets < 0, it'll just do EnumGroup.


Sound good?

Also, as a part of my suite, imma include a bundle of damaging stuff. Damage will be a culmination of different sub damages.

For example, an attack might be 10 fire, 30 ice, 60 physical, 60 psychic. The damage will be (1-resistanceOfType)*damageOfType

For example, resistance of 1 will reduce damage to 0. Resistance of 0 will be 100% damage. Negative resistance increases damage and resistance above 100 heals from damage, like the fire elementals healing from fire attacks in Final Fantasy.

The current triangles that this thing calculates are the building blocks for any sort of attack, so anything from an ellipsoid to a regular triangle thingie can be used in the filter. I'll be adding new shape filters that'll take the 4 triangles and convert them into a twisted shape : P. Really, it is either a polygon (current diamond) or an ellipsoid, so I really only need to write a little bit more code for that ; ).

My my.. so much to do..

For the targeting system, I'm trying to figure out a way to track targets without a hashtable and without 1000 group enums...

If anyone has any ideas on how to do it, please let me know.
 
Last edited:
Just make one public filter and renew him in addons, like
JASS:
set this.filter = Condition(function thistype.validateAttack)
and in addons
JASS:
set this.filter = And(this.filter, this.newFilter)

that will do the magic.

For the targeting system, I'm trying to figure out a way to track targets without a hashtable and without 1000 group enums...
What kind of targeting system do you mean?

And btw2: No problem, you can use CustomAttack if you want. I will most likely not release any version of my CustomAttack system at all to the public.
 
Last edited:
Status
Not open for further replies.
Top