HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Making an "instant attack" spell

02-13-2007, 03:18 AM#1
Castlemaster
I have some abilities in mind that involve doing an extra attack in addition to normal attacks. My question is this: how do I obtain the damage of a unit's standard attack--as an integar--using GUI, so I can make a trigger that will do something like (Damage = attack damage(modified) + ability bonus)? I've thought about using a system where the hero's damage is prestored in a variable that scales with their level, and you simply add their main attribute, but this would fail to account for +dmg effects/items.
02-13-2007, 03:35 AM#2
Ammorth
Why not include + dmg effect items by detecting when an item is gained, and then add the proper amount, and then removing when they lose it?
02-13-2007, 10:01 AM#3
CommanderZ
These abilities are usually built on Searing Arrows (at least in DotA they are) - it means work done for you
02-13-2007, 08:15 PM#4
Castlemaster
hmm, ok I like the searing arrows idea. Thanks for the help.
edit: is there any way I can make an autocast ability NOT autocast when right clicked
02-13-2007, 09:25 PM#5
Anything.
Depends on the spell you need to un-autocast. This is a list which Daelin and I created a while ago.

  • * Slow - Drunken Haze, Acid Bomb, Shadow Strike
    * Faerie Fire - Acid Bomb (no reveal)
    * Curse - Drunken Haze
    * Bloodlust - Cripple (no size change)
    * Frenzy - Berserk
    * Inner Fire - Cripple
    * Essence of Blight - Scroll of Healing
    * Spirit Touch - Scroll of Mana
    * Abolish Magic - Wand of Negation
    * Web - Ensnare
    * Parasite - Doom (a bit different and buggy after Level 1)
    * Heal - Healing Wave (not Holy Light)
    * Kaboom! - Unstable Concoction (bit different, but okay)
    * Frost Armor (auto-castable) - Frost Armor (well, of course...)

If it's not on the list, then you have to use a dummy caster.

Are you trying to make Searing Arrows not autocast..?
02-14-2007, 02:38 AM#6
Av3n
I think using the damage functions is your best way

-Av3n
02-14-2007, 04:42 AM#7
Falitian
I think that WEU has a "Unit Takes Damage" event that you can use to detect when a unit takes damage, then use conditions to detect whether it is the right hero, and then just use triggers to detect the amount of damage, then take that data, and crate a trigger that damages the unit taking damage further depending on your equation using the initial damage taken. That is, of course, if there is a detect amount of damage trigger out there. I could just be crazy. If not, however, I do know that it is possible through Jass, and you could use a few lines of code to set the amount of damage to a variable you can manipulate through GUI if you;re not Jass savy.
02-14-2007, 10:19 AM#8
NmdSnprEnigma
Before venturing a solution, Castlemaster, you're looking for an ability, that, when cast, will simulate an attack, doing the regular attack damage of the unit and yet independent of the unit's normal attack cooldown? Also, would this ability but unit targeted, point targeted or untargeted?

In any event, there may be (to be fair there "is") a pure GUI answer, but the JASS is actually probably simpler. (This is what Falitian was referring to.) If you use Shadow1500's On Damage triggers and add this to where it says "Your Actions Here"

Collapse JASS:
call ConditionalTriggerExecute(gg_trg_On_Damage_GUI)

then you've made a great tool for yourself. What this does is every time a unit takes damage it will Conditionally Execute the Trigger On Damage GUI. So now we just create a trigger called "On Damage GUI" and fill it with whatever we want.

Trigger:
On Damage GUI
Events
Conditions
Collapse Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(Does (Damage source) have Extra Attack) Equal to True
Collapse Then - Actions
Custom script: call AttachReal(GetEventDamageSource(),"lastattackdamage",GetEventDamage())
Else - Actions

This takes the EventDamage the unit just did and saves it onto the DamageSource, under the name "lastattackdamage".

Yes, it is a bit of JASS (mostly copy and pasting), but anything you put in the On Damage GUI Trigger will run, any time any unit takes damage, which means you can use the "Damage Source" and "Damage Taken" freely. Make sense?

The actual spell trigger would just be this.

Trigger:
Extra Attack
Collapse Events
Unit - A unit Starts the effect of an ability
Collapse Conditions
(Ability being cast) Equal to Extra Attack
Collapse Actions
Custom Script: set udg_LastAttackDamage = GetAttachedReal(GetTriggerUnit(),"lastattackdamage")
Unit - Order (Triggering unit) to damage (Target unit of ability being cast) for LastAttackDamage using attack type Hero and damage type Normal.

This loads whatever number is saved on the TriggerUnit (the casting unit) under the name "lastattackdamage" and damages the target of the spell for that much. And you'd just set the animation for the spell to attack in the object editor.

I hope the JASS wasn't too difficult, and just remember, working with GUI is the same as working with JASS, just you get to see the cogs closer up.
02-14-2007, 02:56 PM#9
Castlemaster
Thanks enigma, that helps me alot. I figured I would have to learn some JASS eventually to do what I really want to do with some abilities. I have in mind one other ability that might use something like this. It would "stun" the casting hero for a few seconds(like a channel without losing cast time), and all damage taken during that time would be directed into an AOE blast. I was having trouble figuring out how to store damage recieved into a variable until you mentioned that just now, but I assume that making said ability would involve
1. making a trigger that turns on the effect trigger when the hero begins the effect of his ability
2. the activated trigger will set damagerecieved to 0 and add any damage recieved to the variable when he takes damage (dmgrecievedtotal + dmg recieved=dmgrecievedtotal)
3. Put this variable into a trigger driven spell that will pick units in an area and deal that much dmg to them and add in whatever special effects.

Second question: Would the lastattackdamage variable be stored abnormally high if the hero had a spellcast that did alot of damage? Or what if the hero used the instant attack spell and did not attack again until it was cast again? would the "instant attack" spell damage override as the lastattack damage variable?
All help is very appreciated.
02-14-2007, 11:16 PM#10
The)TideHunter(
To be honest, i wouldent do this much work for a little thing.
All you need to do, is create a dummy (which is a exact replica of the attacking unit, same stats, same items, everything), remove its shadow and model, then when the unit attacks, create this dummy, which cant be seen, give it all the atatcking units items, set the level etc and order it to attack, give it a expiration timer of say, 5 seconds to clear it up.
02-16-2007, 04:39 PM#11
NmdSnprEnigma
@Tidehunter: yeah, it may be a lot of stuff for a little thing, but it gives you a framework that is really useful for so many other things when making a map, like

@CastleMaster: Yeah, for the second spell, that's the idea. But as for the instant attack spell, you're right. If the unit had just cast a spell, the Extra attack would duplicate that spell damage. If you used two extra attacks in a row, the second would do the same as the first, and the first did the same as the pervious attack, so you'd just have three attacks in a row for the same amount of damage. If you only want attack damage to count, you might have to invest in an attack detect engine like Vex's. Not that I'm an expert on this stuff myself either, but happy to help.
02-16-2007, 05:18 PM#12
Castlemaster
Here's how I figure I can correct that balance so players dont end up using the attack to make it do exponential damage:
Before the spell is cast, set "lastattackdamage" to two seperate variables. The first one will be used in the attack spell and is added to a % of agility. The second variable will be used after the spell is cast. It will store "lastattackdamage" to what it was before casting the spell. The only problem I forsee with this is when the ability levels up or the hero obtains an item and uses this spell before attacking, which would hinder the strength of the spell to what it was before. But that's something rather subtle and probably not noticed.

While I'm here, I was wondering: to obtain the udg_ used in JASS ("LastAttackDamage"), do I need to make a GUI variable with the exact same name set to (in this case) a real variable in order to use this variable?

I guess I should go ahead and learn some basic JASS so I understand the nature of what I'm doing.
02-16-2007, 06:35 PM#13
The)TideHunter(
Quote:
Originally Posted by Castlemaster
While I'm here, I was wondering: to obtain the udg_ used in JASS ("LastAttackDamage"), do I need to make a GUI variable with the exact same name set to (in this case) a real variable in order to use this variable?

I guess I should go ahead and learn some basic JASS so I understand the nature of what I'm doing.

I don't understand what you mean, if you have your maps .j code, you can freely add globals with whatever name you want, if you create them via GUI (cntl+x), then it will always have udg_ infront of it unless you edit your .j.
Although, with Vex's new vJass, you can add globals in Jass without editing the .j.
02-18-2007, 02:44 PM#14
NmdSnprEnigma
well, yeah, I'm not really sure why I put custom script with udg_ instead of just doing set variable under GUI. But yes, like Tide said, if you create it under GUI it'll have udg_ prefixed to it.

As for the splitting of the lastattackdamage, it shouldn't ever add exponentially, it'll just take the last time the hero dealt damage. It shouldn't add it to anything else, but rather just over write it.

If you want to make sure it doesn't record damage from spells or itself or the like anyway, (so they can't finger of death something and then Instant Attack the next guy for the same amount), there's attack detect systems. (see below) Tide mentioned before though, this is a lot to do for just a little spell. Losing the use of all your orbs and arrows might not be worth it for this, but again, the other side is, this'll make it work a lot better if this'd be an integral part of your map, or if you plan on using all this stuff for other spells or other parts of your map.


------------------------------------------------------------------------


This is the code I use to find not only if damage is caused by an attack, but also if a unit was the main target of the attack. It's Shadow1500's triggers (Well, the first portion of it at least, the rest I left the same) that I talked about before, but I added in Vex's AttackDetection abil and buff. You just change the abils and buff to have no effects, visual or otherwise, but, as Vex mentions in his AttackDetect2 system, it means you can't use orbs or arrows in your map b/c every unit will have the orb of frost abil.
Hidden information:
Collapse JASS:
function AnyUnitTakesDamage takes nothing returns nothing
    local boolean wasattack = GetUnitAbilityLevel(GetTriggerUnit(),'B007')>0
    //    where 'B007' is the Frost Buff rawcode from Item Attack Frost Bonus
    local boolean hasinstant = GetUnitAbilityLevel(GetTriggerUnit(),'A000')>0
    //    where 'A000' is the rawcode for the Instant Attack ability

    if wasattack then
        call UnitRemoveAbility(GetTriggerUnit(),'B007')
        if hasinstant then
            call AttachReal(GetEventDamageSource(),"lastattackdamage",GetEventDamage()) 
        endif
    endif
    

    call ConditionalTriggerExecute(gg_trg_On_Damage_GUI)

endfunction



// part 1
function AddDamageTriggers takes nothing returns nothing
    local trigger takedamage = CreateTrigger()
    call TriggerRegisterUnitEvent(takedamage,GetTriggerUnit(),EVENT_UNIT_DAMAGED)
    call AttachObject(takedamage,"action",TriggerAddAction(takedamage,function AnyUnitTakesDamage))
    call AttachObject(GetTriggerUnit(),"TakeDamageTrigger",takedamage)
//    'A02D' is the Item Attack Frost Bonus ability
    call UnitAddAbility(GetTriggerUnit(),'A02D')
endfunction


Yeah, basic JASS knowledge'd help. It's not hard, you just need a logical mind and to get used to what means what.