• 🏆 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!

[Spell] On-Hit Magic damage (passive)

Status
Not open for further replies.
Level 3
Joined
Sep 7, 2013
Messages
40
So I'm having a bit of trouble triggering the following spell, by which I mean I have no idea what I'm doing-

Dark Expulsion
The Soul Assassin's attacks expel a dark force from her, dealing 16/29/42/55 bonus damage. This damage is dealt as a separate instance, and as magical rather than physical.

So, the first attempt I made, I tried using the Desolate ability from Dota to give me an idea of how to trigger it, but I couldn't find the triggers for that specific spell anywhere.

Second attempt was to base the ability off of Bash with a 100% chance and a 0 second stun - problem is, that was Physical damage, rather than magical.

Last idea, which I haven't attempted yet, is to look at Time Lock, also from Dota, and see how the damage of that was dealt since that is a bash that deals magical damage (obviously, removing the stun).

So, if anyone could link me the coding for Desolate and Time Lock, that'd be really helpful, or tell me how to change the damage from Bash to magical.

Thanks for helping!
 
Level 7
Joined
May 11, 2010
Messages
278
Event
A unit is attacked
Conditions
Unit type of attacking unit equal to Soul Assassin
Actions
Set Variable - Damage = Conversion, INT to Real (3 + (13 * ability level of Dark Expulsion for attacking unit))
Unit - Cause attacking unit to deal Damage damage of type magic to attacked unit.

Something like that should do it.
 
Level 21
Joined
Mar 27, 2012
Messages
3,232
Event
A unit is attacked
Conditions
Unit type of attacking unit equal to Soul Assassin
Actions
Set Variable - Damage = Conversion, INT to Real (3 + (13 * ability level of Dark Expulsion for attacking unit))
Unit - Cause attacking unit to deal Damage damage of type magic to attacked unit.

Something like that should do it.

This is easy to abuse, because it doesn't require the attack to actually happen and thus, repeatedly right-clicking ignores the cooldown.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
That... doesnt work.

You have to catch the takes damage event of the unit that is attacked not the unit that is attacking.

I do have the triggers to catch takes damage event for every unit without the event leak but you should do it via a DDS.

The GUI trigger that is called when a unit takes damage:
  • Unit Takes Damage
    • Events
    • Conditions
    • Actions
      • Game - Display to (All players) the text: (name = + (Name of (Damage source)))
This trigger is the actual stuff:
JASS:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This function is called every time a unit is taking damage.
//  Add whatever code you want to it.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function Taking_Damage takes nothing returns nothing
    //Shiny Effect!
    call TriggerExecute(gg_trg_Unit_Takes_Damage)
endfunction


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  These functions delete the old system,
//  create a clean trigger and add the system to it.
//  Then all units that are in the entire map are added to the system.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function Add_Unit takes nothing returns nothing
    call TriggerRegisterUnitEvent(gg_trg_Taking_Damage, GetEnumUnit(), EVENT_UNIT_DAMAGED)
endfunction

function Init_Damage_System takes nothing returns nothing
    local group g = GetUnitsInRectAll(GetEntireMapRect())
    call DestroyTrigger(gg_trg_Taking_Damage)
    set gg_trg_Taking_Damage = CreateTrigger()
    call ForGroupBJ(g,function Add_Unit)
    call DestroyGroup(g)
    call TriggerAddAction(gg_trg_Taking_Damage, function Taking_Damage)
    
    //This action resets the timer.
    //This is only used in the example map.
    set udg_Timer = 35
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This trigger is called on Map Initialization and runs every 35 seconds.
//  You can change the interval to whatever you want.
//  In most cases an interval of 15 minutes cannot be a problem.
//  This system starts to run slow after 25 seconds so after 75.000 units have been made.
//  Most maps will not even get to that point within 10 hours.
//  Therefor, this whole reset system is almost pointless.
//  But some people hate to see memory leaks and so I made this nice reset function.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function InitTrig_Init_Damage_System takes nothing returns nothing
    set gg_trg_Init_Damage_System = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic(gg_trg_Init_Damage_System, 35)
    call TriggerAddAction(gg_trg_Init_Damage_System, function Init_Damage_System)
endfunction

This trigger adds the units:
JASS:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This trigger detects when a unit is made and adds that unit to the event list of the Taking Damage trigger.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function Add_Units takes nothing returns nothing
    call TriggerRegisterUnitEvent(gg_trg_Taking_Damage, GetEnteringUnit(), EVENT_UNIT_DAMAGED)
endfunction

function InitTrig_Add_Units takes nothing returns nothing
    set gg_trg_Add_Units = CreateTrigger()
    call TriggerRegisterEnterRectSimple(gg_trg_Add_Units, GetEntireMapRect())
    call TriggerAddAction(gg_trg_Add_Units, function Add_Units)
endfunction

This trigger is modified by the other triggers:
JASS:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This trigger is modified in the Init Damage System Trigger.
//  Modifying this trigger in here has no effect.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function InitTrig_Taking_Damage takes nothing returns nothing
    set gg_trg_Taking_Damage = CreateTrigger()
endfunction
 

Attachments

  • Damage Detection System v1.w3x
    18.2 KB · Views: 87
Level 4
Joined
Jan 3, 2013
Messages
69
yes it does, it works for my map, you can adapt it like this
  • Trigger
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Attacking unit) Equal to "Your_Hero"
      • (Level of "Your_Skill" for "Your_Hero") Not equal to 0
    • Actions
      • Trigger - Add to Trigger Check <gen> the event (Unit - (Attacked unit) Takes damage)
      • Trigger - Turn on Trigger Check <gen>
And then, you make the damage for the group around the hero in Trigger Check <gen>
 
Level 4
Joined
Jan 3, 2013
Messages
69
Then you must add the attacking unit to a group instead.
If the unit was not in the group before then add the event otherwise you get doubled events... I think that wc3 does double the action if a doubled event is used.

I'm not getting you here, could you show me the trigger you would use?
PD: Btw, Trigger Check <gen> shouldn't have any events at all
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
I'm not getting you here, could you show me the trigger you would use?
PD: Btw, Trigger Check <gen> shouldn't have any events at all

  • Trigger - Add to Trigger Check <gen> the event (Unit - (Attacked unit) Takes damage)

Trigger "Check" does have events.

Lets give this example:
You have your unit with the ability and everything set up straight.
Then you have 1 opponent (with enough health to survive a while)
You attack him -> new event created (Unit takes damage).
Then you attack him again -> new event created (Unit takes damage).
Then you attack him again -> new event created (Unit takes damage).
Then you attack him again -> new event created (Unit takes damage).

Now when that unit takes damage, the trigger "Check" runs 4 times.
So the unit is taking 400 damage instead of 100... this could be a nice idea for another spell but in this case you dont want it.

You want something that you can see if the event already exists. So you put all units that have the event in a unit group:
  • Is Attacked
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • And - All (Conditions) are true
        • Conditions
          • (Level of Bash for (Attacking unit)) Greater than 0
          • ((Triggering unit) is in Unit_Group) Equal to False
    • Actions
      • Unit Group - Add (Triggering unit) to Unit_Group
      • Trigger - Add to Takes Damage <gen> the event (Unit - (Triggering unit) Takes damage)
  • Takes Damage
    • Events
    • Conditions
      • (Level of Bash for (Damage source)) Greater than 0
    • Actions
      • Unit - Cause (Damage source) to damage (Triggering unit), dealing 100.00 damage of attack type Magic and damage type Magic
  • Dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is in Unit_Group) Equal to True
    • Actions
      • Unit Group - Remove (Triggering unit) from Unit_Group
If you want to do it perfectly, you have to re-initialize the trigger Takes damage.
Because every unit that dies still has the event "(Unit) takes damage"
For this, you require JASS knowledge and advanced trigger knowledge and it will only give a little perfection.
Like my system that has one event for every unit on the map will run slow when it passes somewhere at 70.000 units... if you want a game where 70.000 units have been created (and died), you need a really long game.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
There might be one problem.
When you do the action "deal damage to unit", the event "unit takes damage" is executed again.
This will probably result in an infinite loop and you should turn the trigger off at the start and turn it on just after the deal damage action.

I am not sure though if it is neccessary.
 
Level 4
Joined
Jan 3, 2013
Messages
69
Yes it is, you turn off Trigger Check <gen> at the beggining of this, and you turn it on at the end of Trigger <gen>
 
Here's http://www.hiveworkshop.com/forums/...a-231846/?prev=d=list&r=20&u=looking_for_help which is the ultimate method of recently for all GUI'ers and even JASS'ers. It is easy and you would have to be pretty lacking in some area's not to be able to use this. It lets you detect physical AND magical damage... That's not it, you can even add your own universal damage that is through either dummy units to apply one of the two types or use the third type which is code damage which is easy to use as long as you don't have many different instances/types of it which must be used inside the OnDamage trigger/s.

This way you don't have to deal with event leaks or infinite loops/crashes or even making anything complex... All you have to do is set stuff up and you have a perfectly working EPICly done damage detect/do system unlike the one ages ago, GDD/others made by weep/others which took a lot of effort/work to get working to what you wanted if it was complex. It's never been easier before now for mapmakers.
 
Status
Not open for further replies.
Top