System Damage

Discussion in 'Systems and Snippets' started by Jesus4Lyf, Jul 6, 2009.

  1. W!†A_cRaft

    W!†A_cRaft Ultra Cool Member

    +28 / 0 / -0
    i think i need to learn a lil more about JASS before understanding what you just said :)

    dont really get the whole scope thing
  2. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    +216 / 0 / -0
    It is vJass.
  3. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    Convert any GUI trigger with an event into JASS. At the bottom, you will see the trigger get created, and an event gets registered. Replace that register with Damage_RegisterEvent(...) where the ... is simply the trigger. That will cause the trigger to fire every time any unit takes damage. Use conditions or if statements to narrow down when you want things to take place, and you can do damage blocking inside it. :)
  4. SanKakU

    SanKakU Member

    +21 / 0 / -0
    what jesus4lyf mentioned is the starters in using jass...that's not really explaining vjass...and i see how kingking's post could've been confusing.

    scopes are used to make things easier or more difficult to access, with ease. you don't have to have things named really bonkers names like what happens when you convert to custom text. so every function in a scope, if labeled private, will not be accessible outside of the scope. this means you can copy and past large chunks of code without bothering to rename so much of it. you just put it in a scope and keep changing the scope names.

    same thing with local variables in functions, they are not accessible outside of the function.

    scope whatever initializer I

    kingking might've confused you with those < and > characters. scope name is whatever and initializer anme is I. a lot of folks make initializer be named Init, but really, you can name it whatever you want.

    the initializer is where you have the trigger's event registered and where you give it conditions and actions.

    i recommend reading cohadar's vjass tutorial. that is what really helped me. that, and just importing lots of systems into your map and checking them out. that, and examining how other maps work, assuming they don't lock up their code.
  5. AoW_Hun7312

    AoW_Hun7312 I'm a magic man, I've got magic hands.

    +76 / 0 / -0
    Is there anyway to get the damage amount using this system? If not, could you add it? If someone receives negative damage, it still triggers the damage event.
  6. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    • Like Like x 1
  7. W!†A_cRaft

    W!†A_cRaft Ultra Cool Member

    +28 / 0 / -0
    If i made a function like this:

    function irrelevant takes nothing returns nothing
            local trigger threat T
            set threatT = CreateTrigger()
            call Damage_RegisterEvent(threatT)

    Now this should register a "any unit takes damage" event to the trigger? Am I correct?

    Now if lets say I use a "summoning spell" or use some different trigger to create additional units, will they be registered with into this trigger as well?

    The basic question is: "Does this register only the units preset in the map at the moment of it's activation, or all units in general?"
  8. jrhetf4xb

    jrhetf4xb Member

    +12 / 0 / -0
    You've got a syntax error but I guess it's just a quickly written example.
    It registers all units in general. And also you'd have to add a condition/action but you probably know that already. :)
    • Like Like x 1
  9. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    All units in general. Every unit that is created will also trigger that event, even if it was not made when the trigger had the event registered. :)
  10. Bribe

    Bribe vJass errors are legion

    +67 / 0 / -0
    Damage_Pure must have use ATTACK_TYPE_CHAOS and not DAMAGE_TYPE_NORMAL, because only chaos damage can affect divine armour for those cases, even though you are using DAMAGE_TYPE_UNIVERSAL. Needs a fix.
  11. Weep

    Weep Godspeed to the sound of the pounding

    +400 / 0 / -0
    Well, to be very specific, chaos damage has a 1x multiplier for every armor type by default, but that's changeable in the map configuration so there's no guarantee. It might be wise to list "1x multiplier for chaos damage" as a system requirement.

    I agree it ought to be chaos type.

    I was also curious recently about illusions with non-1x damage multiplier (or units with Berserk) - in the case of triggering crit. strike, the damage will be multiplied before detection, and again upon the bonus being dealt, thus affecting it twice (although, somehow, when I tried, it only happened with damage decreases). It's something to keep in mind...
  12. Bribe

    Bribe vJass errors are legion

    +67 / 0 / -0
    You're right :O

    But how to detect...
  13. Switch33

    Switch33 New Member

    +12 / 0 / -0
    The only sane way is to just trigger all the damage. Change all the data table ratios to 1.0 in the map. Then assign a single attack type and defense type to each unit. And when units attack get their attack type and the defending unit's defense type so you can look up the correct value to multiply.

    As for critical strike/evasion it only makes sense to trigger that as well. That way you know when a critical strike occurred or an unit missed etc.

    As for illusions you check for the unit being of type illusion and always set it to 1.0 for their damage and damage they recieve as you can modify it in triggers.

    It's pointless trying to keep wc3 as wc3 if you really want to control it. You gotta trigger somethings completely.
  14. Bribe

    Bribe vJass errors are legion

    +67 / 0 / -0
    And just throw spirit link/berserk out the window I suppose.
  15. Nestharus

    Nestharus o-o

    +83 / 0 / -0
    This is kind of inferior to the new stuff-

    A similar library is at wc3c that uses all of the wc3c stuff (though it still needs to be fixed). TH is the only site that doesn't have one atm =).

    Yea, with these new libs, Damage is kinda useless ;P.

    One of the really nice things is that you can use SetWidgetLife on these libs, so you can apply direct damage ^_^.
  16. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    No, with Damage, making these new libs, is kinda useless.

    Believe it or not, your opinion with no evidence is still what it always has been: worthless, and commonly proved to be wrong at a later date. :p

    You can use Damage_Pure to achieve said objective.

    Anyway, philosophy behind Damage systems are very subjective, so I'd appreciate no absolutes on such things in this thread. Things like should you be able to add bonus damage without retriggering the event, etc. Everyone has their own way of doing stuff..

    I still haven't seen a system that works as flawlessly as this one.
  17. Nestharus

    Nestharus o-o

    +83 / 0 / -0
    Yea, there are many philosophies on damage detection systems and manipulating damage and so on.

    Here is just some food for thought.

    What a lot of people strive for now when making systems isn't super customization, like custom projectile systems and custom this and custom that, but rather working off of wc3 systems already in place, like warcraft 3 projectiles, warcraft 3 damage, and etc.

    There are also lots of questions floating around on how to implement pure damage that completely ignores armor (armor type and value) regardless of the map while giving the killer bounty.

    Newer systems work with any other system that don't override wc3 damage, meaning that users don't have to use a special damage function in order to see an attack's general type (physical, spell, or jass). Well, the latest at wc3c can only detect physical atm, and it does so with bugs.

    If a system runs on a timer and always applies bonus life to a unit, then a user can use SetWidgetLife to deal pure damage, something that a lot of people have been waiting for and only one system can do at the moment. There is not one system online besides 1 that can deal pure damage regardless of armor and the map settings. Actually, I take that back, if you set all of the armor types to take 0% damage, then all units will be immortal as bounty can only be done via UnitDamageTarget, so I guess that's still a problem.

    It may be a different philosophy, but one method has less limitations than another method, more features, and is just as bugless. Originally, the idea with always applying bonus life and using a timer was bugged as it ruined artillery type attacks (attacks that explode units). There was also a problem with buffs for detecting physical attacks. All of the bugs are solved now, so there is no reason not to get on the bandwagon. You can even now detect whether a damage was a non splash attack, a missile splash attack, or an artillery attack, and whether damage marks the unit to explode or not.

    Now, if you just need base damage with total amounts (all damage dealt), I think your library would actually be the best as others are bogged down with other features, but yours still has the issue of applying pure damage.

    You may say that Damage makes making other new libs bad, but the fact is that it can't do this w/o specifically working through it, something that a lot more people are finding useful (hence why the people at wc3c are now trying to get on board with their own stuff)

    *Detect the major damage type (was it physical, spell, or jass)

    Also, yours can't deal out pure damage, something that a lot of people have been asking about (yes, I've seen a lot of questions on how to deal pure damage on all the major wc3 modding sites).

    Just recently, someone at THW was asking how to detect physical attacks only (just regular wc3 physical attacks).

    You can say my opinions are irrelevant, but that doesn't change the facts ;P.

    If you want any sort of shield (remember that most shields don't block all attacks, they typically either block physical or spell attacks), then I'm afraid your system will be pretty useless.

    I'm just recommending that you update it to use some of the newer techniques. Since I solved the explosion bug with detecting physical attacks, there is no reason not to update it now. I posted the solution at wc3c under the PhysicalAttack thread.

    There are 3 forums with 3 different standard resources, meaning 1 main type of system for each forum ; \. I'm just saying that the DDS at TH is falling behind the ones at wc3c and THW now, and if you say it isn't, I need only point to the hard facts of what your system can't do and the others can do and how those features are extremely useful in most every situation. I have never ever needed to block plain damage that could have come from anywhere, nor have I ever heard of a mapper that actually needed that. Most people coming on forums asking about DDS always ask about blocking physical damage or blocking spell damage. I haven't even seen anyone asking about how to block damage in general, it's always one or the other (yes, never seen anyone asking about blocking general JASS damage either, lol..).

    I also wrote a little mini tut on LUA_FILE_HEADER if you want to make your object generation safe. There are plenty of example scripts around if you know where to look. Here is one from Purge for his ReviveUnit script

    //! externalblock extension=lua ObjectMerger $FILENAME$
        //! runtextmacro LUA_FILE_HEADER()
        //! i dofile("GetVarObject")
        //! i local rez = getvarobject("AHre", "abilities", "ABILITIES_REVIVE_UNIT_RESURRECTION", true)
            //! i createobject("AHre",rez)
            //! i makechange(current,"anam","DumResurrection")
            //! i makechange(current,"aher","0")
            //! i makechange(current,"acat","")
            //! i makechange(current,"atat","")
            //! i makechange(current,"Hre1","1","1")
            //! i makechange(current,"aare","1","0")
            //! i makechange(current,"aran","1","0")
            //! i makechange(current,"acdn","1","0")
            //! i makechange(current,"amcs","1","0")
            //! i makechange(current,"atar","1","Air,Dead,Enemy,Friend,Ground,Neutral")
        //! i local dummy = getvarobject("ushd", "units", "UNITS_REVIVE_UNIT_DUMMY", true)
            //! i createobject("ushd",dummy)
            //! i makechange(current,"unam","Dummy")
            //! i makechange(current,"uabi",rez .. ",Aloc,Avul")
            //! i makechange(current,"ucbs","0")
            //! i makechange(current,"ucpt","0")
            //! i makechange(current,"umdl","none.mdl")
            //! i makechange(current,"usca","0.01")
            //! i makechange(current,"ushu","None")
            //! i makechange(current,"umvh","0")
            //! i makechange(current,"umvs","0")
            //! i makechange(current,"ufoo","0")
            //! i makechange(current,"umpi","100000")
            //! i makechange(current,"umpm","100000")
            //! i makechange(current,"umpr","1000")
            //! i updateobjects()
    //! endexternalblock

    Once you get the hang of how to use it, it's really pretty easy =P.
  18. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    Way too long, man. Got bored reading. Got better things to do.

    From what I managed to read:

    Pure damage with Damage:
    function OMG4REALZ takes unit source, unit target, real amount returns nothing
        if amount>GetWidgetLife(target) then
            call Damage_Pure(source, target, 99999999)
            call SetWidgetLife(target, GetWidgetLife(target)-amount)

    I am considering updating the Damage_Pure function to do this, but I dunno. Seems pretty simple, right?

    >Well, the latest at wc3c can only detect physical atm, and it does so with bugs.
    Same old, same old, Damage just works. :thup:

    Damage is really cool. It supports Damage_Block(amount). :p

    Also, stop spamming your object generation script in all my threads. I got the point the first time, ok? I'll think about letting you make a version which uses it, which I'd then let you submit in a post in the thread already existing, and I could link directly to said post. Still thinking about it. :)
  19. Nestharus

    Nestharus o-o

    +83 / 0 / -0
    ->Same old, same old, Damage just works
    So does AdvDamageEvent ;P, and almost any system, as I said, needs to detect either physical or spell damage, so you should really work at updating ;p.

    Information and Solution
            if (UnitAlive(GetUnitById(targetId))) then
                if (GetUnitAbilityLevel(GetUnitById(targetId), DUMMY_BUFF) > 0) then
                    //was a physical attack
                    if (ec[eventCount]) then
                        //initial splash (runs through w/ only splash abils on splash attack)
                            set eventType[i] = PHYSICAL
                            set es[i] = 0
                            set i = i - 1
                            exitwhen not ec[i] or es[i] != sourceId
                            set ec[i] = false
                        //not splash (doesn't run w/ splash abil no non splash attack)
                        set eventCount = eventCount + 1
                        set eventType[eventCount] = PHYSICAL
                        set update = true
                elseif (ls == sourceId and eventType[eventCount] == PHYSICAL) then
                    //this will only run with non-splash abil and splash abil on splash attack
                    //first the 0 dmg runs, then the actual damage runs, alternates
                    if (ec[eventCount]) then
                        set ec[eventCount] = false
                        set eventCount = eventCount + 1
                        set eventType[eventCount] = PHYSICAL
                        set ec[eventCount] = true
                        set update = true
                elseif (hooked[sourceId] > 0) then
                    //JASS attack
                    set hooked[sourceId] = hooked[sourceId] - 1
                    set eventCount = eventCount + 1
                    set eventType[eventCount] = JASS
                    set update = true
                elseif (overType != 0) then
                    //known attack
                    set eventType[eventCount] = overType
                    set overType = 0
                    set update = true
                    //unknown attack
                    //will initially run for all splash attacks
                    //artillery attacks won't be known until after timer
                    set eventCount = eventCount + 1
                    set eventType[eventCount] = 0
                    set update = true
                    set ec[eventCount] = true
                    set es[eventCount] = sourceId
                //for chaining attacks together, last source = current source
                set ls = sourceId
                //if update (didn't skip), then add to timer stack
                if (update) then
                    set eventSourceId[eventCount] = sourceId
                    set eventTargetId[eventCount] = targetId
                    set eventDamage[eventCount] = amount
                    //if haven't saved the unit, add life abil to save it
                    if (saved[targetId] == 0) then
                        set life = GetWidgetLife(GetUnitById(targetId))
                        call UnitAddAbility(GetUnitById(targetId), ADV_DAMAGE_EVENT_SAVE_UNIT_ABILITY)
                        call SetWidgetLife(GetUnitById(targetId), life+500000)
                    //always increase the save count so life ability is removed at right time
                    set saved[targetId] = saved[targetId] + 1
                    //start the timer to actually handle (only needed because of artillery attacks)
                    //artillery attacks are *never* known until after timer
                    call TimerStart(eventTimer, 0, false, function thistype.handleEvent)

    ->Here is the final step inside of the timer method for retrieving type
                    if (type == 0) then
                        if (GetUnitAbilityLevel(target, DUMMY_BUFF) > 0) then
                            set type = PHYSICAL
                            set explode = true
                            set type = SPELL
                            set explode = false
                        set explode = false
                    if (type == PHYSICAL) then
                        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "PHYSICAL")
                        call UnitRemoveAbility(target, DUMMY_BUFF)
                    call Event(type).fire()

    ->And killing
                    set life = GetWidgetLife(target)-500000
                    set saved[targetId] = saved[targetId] - 1
                    if (life < .405) then
                        call SetUnitExploded(target, explode)
                        set saved[targetId] = 0
                        call SetWidgetLife(target, .5)
                        call disable()
                        call UnitDamageTarget(GetUnitById(sourceId), GetUnitById(targetId), 100, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
                        call enable()
                    elseif (saved[targetId] == 0) then
                        call UnitRemoveAbility(GetUnitById(targetId), ADV_DAMAGE_EVENT_SAVE_UNIT_ABILITY)
                        call SetWidgetLife(target, life)

    Also, you can't add the ability all willy nilly or you'll ruin explosions with artillery attacks, so detecting between dif types of physical attacks is kind of a necessity to fix the explosion bug.
  20. Dinowc

    Dinowc don't expect anything, prepare for everything

    +223 / 0 / -0
    is there a way to block percent of damage taken? if not, why don't you replace this:
    public function BlockAll takes nothing returns nothing
        set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+GetEventDamage()

    with this:
    public function BlockPercent takes real percent returns nothing
        set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel] + GetEventDamage()*percent

    percent being any number between 0 and 1

    I've changed it like that for my map (hope you don't mind) and it works

Share This Page