1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. We have recently started the 16th edition of the Mini Mapping Contest. The theme is mini RPG. Do check it out and have fun.
    Dismiss Notice
  4. Dismiss Notice
  5. The Highway to Hell has been laid open. Come along and participate in the 5th Special Effect Contest.
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Custom Damage/Resist system

Discussion in 'Triggers & Scripts' started by Spartipilo, Sep 20, 2012.

  1. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    Hi!

    I've spent some time doing this. I hope it's good enough for everyone to enjoy. It's fully made in JASS; but it's insanely commented, really easy to understand as well.

    The system allows creating as many Damage types as you want (Fire, Earth, Physical, Pure, Psychic, Magical, Elemental, Nature, Wood, Composite, Magma, Stone, etc.) Also allows easily adding each unit a percentage resistance to each DamageType, and add a fixed resistance to each DamageType. Also allows handling Critical Strike, Critical Ratio, and Evasion.

    Has a Global Boolean called IsHealed you can switch true/false at any time. True will mean that negative damage will heal units; false will make negative damage do nothing.

    Has a Global Boolean called "ShownText" you can swithc true/false at any time. True will make damage popup as a floating text from target unit. If the unit is healed (IsHealed = true) the text will be green and will have a "+" before the amount. If It's false, nothing will be shown.

    It's pretty easy to add a unit data:
    Code (vJASS):
    call SpartDSAddUnitDmg('xxxx', SpartDSFire, 12, 0.15, 6)

    That would add 12 Fire dmg, and 15% Fire resistance, and 6 Fire damage reduction to units of type 'xxxx'
    Code (vJASS):
    call SpartDSAddUnitStat('xxxx', 10, 2, 6)

    That would add all units of type 'xxxx' 10% chance to do Damage*2 and 6% chance to evade.

    It works exactly the same to add data to items.
    Code (vJASS):
    call SpartDSAddItemDmg('ofir', Fire, 22, .1, 0)

    That would add 22 fire damage, 10% fire resistance, 0 fire damage reduction to units that picks an item of type 'ofir'
    Code (vJASS):
    call SpartDSAddItemStat('ofir', 12, 1.2, 0)

    That will give units that pick an item of type 'ofir' a 12% chance to deal 20% more damage on an attack, and 0% chance to evade.

    Item effects are cummulative. If you pick 6 items that give 10% chance to do damage*2, and 5 evasion, the unit will have 60% chance to do Damage*12, and 30% evasion.

    Also, The unit name and all the unit damages/resistances/stats are displayed in a Multiboard (Screenshot at the end). Any selected unit data will be shown in the Multiboard.

    The Path for Damage/Armor icons in the Multiboard is really easy to set
    Code (vJASS):

            set IconPath[SpartDS_Fire] = "ReplaceableTextures\\CommandButtons\\BTNOrbOfFire.blp"
            set IconPath[SpartDS_Water] = "ReplaceableTextures\\CommandButtons\\BTNSummonWaterElemental.blp"
            set IconPath[SpartDS_Wind] = "ReplaceableTextures\\CommandButtons\\BTNCyclone.blp"
            set IconPath[SpartDS_Earth] = "ReplaceableTextures\\CommandButtons\\BTNEarthquake.blp"
            set IconPath[SpartDS_Electric] = "ReplaceableTextures\\CommandButtons\\BTNChainLightning.blp"
     

    And so on, untill all of the Damage Types has their own icon.

    The System is pretty much explained inside the testmap and script comments. In fact, I think there are more comments than system scripts.

    PD: It's the first time is create a system like this one, I didn't find anywhere else to post for review or public check.

    [​IMG]

    << EDIT 22/09/2012 >>

    Changelog

    · Credits to Adiktuz for most suggestion.
    · Added Critical Chance, Critical Ratio, and Evasion.
    · Made all UnitType data be applied to the UnitID when enters the map.
    · Separated most of Core Functions into a library
    · Improved code generally
    · Updated Multiboard to fit new features
     

    Attached Files:

    Last edited: Sep 22, 2012
  2. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    Cannot download the map for now... anyway, seems pretty cool... somehow similar to what I'm currently using...

    btw, I'd rather have the registration as a simple function call...

    Something like

    Code (vJASS):

    //vJASS using structs to save maybe
    call SpartSystem.Register("Fire", "ReplaceableTextures\\CommandButtons\\BTNOrbOfFire.blp")

    //JASS using arrays or hashtables to save
    call SpartSystemRegister("Fire", "ReplaceableTextures\\CommandButtons\\BTNOrbOfFire.blp")
     


    Also, if this doesn't exist yet, it's cool to be able to change the damage values/bonuses dynamically during game time...

    if you finish this up, I might make some custom systems/snippets for it...
     
  3. gorillabull

    gorillabull

    Joined:
    Jul 17, 2011
    Messages:
    1,365
    Resources:
    2
    Spells:
    2
    Resources:
    2
    its kinda slow but i like it this is a good system for ability casters not so much for basic attacks
     
  4. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    actually I'd say it's good for basic attacks since it will allow you to create "elemental" basic attacks... or any other property set for basic attacks... but I'd prefer to also have a fixed reduction alongside the %reduction...
     
  5. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    I was thinking I could match it with Unit Indexer to improve it, since there are so many Hash calls, but i've never worked with UnitIndexer.

    @adiktuz: Thanks! Sadly, i don't know vJASS (I could learn tough)

    It can be done with Items :p I could add abilities aswell. But, what do you mean exactly?

    About Fixed reduction.. well, I could add an boolean to check if the armor is considered as Percent, or as a fixed value. It could be a Global (like IsHealed or ShowText) To make both apply (fixed+%) I would have to add both values to all units/items, plus the boolean (3 more callings, ¡yay!)

    If any of you have better ideas/suggestions to improve efficiency, speed, smoothness, size, user-friendly things, scripts, snippets, etc. i would really appreciate it if you could share them or even help me apply them to this.
     
  6. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    The lower one is a JASS version... :)
    you only need to create the functions, so you can just do it in normal jass
    and you already did it with the AddUnit and AddItem so why not just make the Set-up of "damage-types" to work in the same way?

    I mean changing a unit's damage and everything else during gametime just from a function call... of course maybe we can just re-run the Register function to override the old value but its not a really good idea because we should only change what we need to and not all data... this way the user can easily manipulate things enabling them to make abilities that modify damage etc...

    for the fixed reduction, its better to have both so we could combine reductions... like 30% + 20 damage reduction...

    Also, I'd prefer the heal option to be specific per unit coz it brings up possibilities like for example I would normally just negate negative damage (turn it to 0) then if I cast a certain spell, negative damages will heal me up for the duration of the spell...

    same thing for critical chance and ratio... its better to have it per unit so we can even enable critical without using an ability plus we can modify the chance during gametime...


    so basically, make every modifier linked to the unit... there should be no global modifier... take note, PER UNIT not per UNIT-TYPE...

    and I think it will be a good idea to make this work with Bribe's UnitIndexer + his Damage engine...

    doing that you can let the users create a base table for properties of every unit type, then once a unit gets indexed, you register that unit into your system using the values saved on the base table...

    Why should it be per unit and not per unit-type? Simply because if you add in-game modifying capabilities and system only has a per unit-type setting then all units of that type will be affected... And if you choose not to add that capability, then the usefulness of such a system drops greatly...
     
  7. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    I register the unit data In another table under UnitHandle or in several arrays (one for each damage/resist%/resistfix type) all based on UnitValue?

    Note: This is something I've always tough about Unit Indexer, ir lets us get rid of Hashtables by creating several arrays for each thing, all based on Custom Value, or it still uses Hashtable?
     
  8. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    It depends on you whether you prefer arrays or hashes... though most people use arrays since its faster than hashes... though arrays has an index limit but I don't think you'll reach it anyways... but arrays can be easier to read to as long as you give it a good name...

    If you're gonna use UnitIndexer then you'll save those data for each unit using the UnitValue (Custom Value)... again it's up to you whether you'll use hashes or arrays...

    • Set Unit = (Picked Unit)
    • Custom script: set udg_UnitType = GetUnitTypeId(udg_Unit)
    • Set ID = Custom Value of Unit
    • Set UnitDamage[ID] = BaseDamage[UnitType]


    is easier to read and understand than

    • Set Unit = (Picked Unit)
    • Custom script: set udg_UnitType = GetUnitTypeId(udg_Unit)
    • Set ID = Custom Value of Unit
    • Hashtable - Save (Load StringHash(Damage) of UnitType in Hash) as StringHash(Damage) of ID in Hash


    PS: not sure if I got the hashtable parameters on the right order
     
  9. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    Don't worry, i'm getting it. I would use several global arrays, now...

    How would the user create the globals for each damage, resist type?

    Code (vJASS):

    function SpartDSType requires integer index, string name, string iconpath takes nothing
        globals
            real array name + "Dmg"
            real array name + "Resper"
            real array name + "Resfix"
        endglobals
        set IconPath[index] = iconpath
    endfunction
     
     
  10. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    You're better off using hashes for saving the values...

    Code (vJASS):

    globals
        string array CustomTypeName
        string array CustomTypeIcon
        integer MaxType = 0
    endglobals

    function RegisterType takes string name, string iconpath returns nothing
        set MaxType = MaxType + 1
        set CustomTypeName[MaxType] = name
        set CustomTypeIcon[MaxType] = iconpath
    endfunction

     


    then they just need to remember the sequence that they registered each type since that would correspond to their index

    as for saving the damage values of units per CustomType, then you'd probably be better off with hashtables for that... using the unit's index/customvalue as parent key and the CustomType index as childkey
     
  11. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    But If i'm still going to use Hash, then it's almost the same, instead of using GetHandleId i use the custom value.
     
  12. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    well, for the damage values, you'd really need a hash since you'd need a 2D array... else you can use structs + Bribe's Table (I'd prefer it actually) but since you don't know vJASS yet I cannot suggest it...
     
  13. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    Well.. I can still put clear instructions there to guide the user through the globals creations by himself/herself...
     
  14. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    For the user yes... but that could actually be hard on you... I mean how would your system cope up with the new arrays? because they'll be creating a new array per Custom damage type... you'll really need an array inside an array if you want to make this work, which is why you should just use a hashtable for those values...

    unless you want to burden the user by adding lots of lines to your system's core for each new damage type that he wants to add... and lots of if-then-elses...
     
  15. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    After 10 minutes of thinking.. yeah, I'll stick to Hashtables.
     
  16. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    yeah, you better stick with them...

    anyway, good luck with this...
     
  17. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    Bump. Updated the main post, and uploaded the new system version. It's still based on Hashtables (not table+structs) and still uses Weep's GDD (not Bribe's Damage Engine), but, from my point of view, is still greatly improved, and added several new features.
     
  18. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    -Still has vJASS features with Library and free globals declaration. So why not use Table or Structs? :p

    -Also if you want the critical strike to really copy the WC3 engine it should have some sort of psuedo randomness and also I dont think the object editor can handle certain percentages below 5% or whatever the value is.

    -local real life = GetUnitState(udg_GDD_DamagedUnit, UNIT_STATE_LIFE)

    ->

    local real life = GetWidgetLife(udg_GDD_DamagedUnit)

    -call SetUnitState(udg_GDD_DamagedUnit, UNIT_STATE_LIFE, life+udg_GDD_Damage)

    ->

    call SetWidgetLife(udg_GDD_DamagedUnit, life+udg_GDD_Damage)

    -This is a really bad idea.

    call DisableTrigger(gg_trg_SpartDS_Damage)

    If you're using free global declaration you should create a trigger variable.

    -WEAPON_TYPE_WHOKNOWS -> null (shorter code, faster execution, same function)

    -call TriggerSleepAction(0.00)

    Bad idea, rather the block after it put in a new function, use a timer that has 0. time and just call ResumeTimer(timer) and it will fire it.

    -The items trigger, you should store the GetTriggerUnit() and the item.

    -I heard that this breaks Vex's optimizer (did back in the day at least)

    call ExecuteFunc("SpartDS_MultiboardUpdate")

    -I also wonder, you have some triggers requiring vJASS and the rest is pure JASS. If you want this system in pure JASS, you have to put the function in the mapheader.

    I like where this is going, keep it up.
     
  19. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    I don't know very much about vJASS or JASS differences. I starting improving GUI by removing BJ's, then using locals, then custom functions. I'll follow your suggestions and update the map/post as soon as possible. I know vJASS has some strong poinst that would improve this system speed (most of all) but I have no idea about how to use vJASS.

    I don't aim Critical to mimic Wc3 system. I think that setting a percentaje and a ratio is enough for most users to have control over it.

    I just did the library thing to keep that triggers in hand, and not having to look for them in the Header, wich, sometimes, I forget exists.

    I don't know what you mean :) That's the most popular suggestion I've heard around (disable/enable) what's the other choice... Creating a global variable and check it in the trigger conditions, and set it false/true before/after dealing dmg?

    I tried in several ways, but when the item was being acquire all the Multiboard data was being reset to 0, tough the Multiboard Update was running. I added this function to the Item triggers (without care for leaks, just for testing)

    Code (vJASS):

    function SpartDSItemTimer takes nothing returns nothing
        local timer t = CreateTimer()
        call TimerStart(t, 0, false, function SpartDS_Item_Effect)
    endfunction
     


    It runs the function SpartDS_Item_Effect, but all the multiboard data goes to 0.

    I already did all the other changes you suggested, but these 2 are still left to do.

    << EDIT >>

    I aim to add later the same effect that items have for Abilities, also lifesteal, and some easy way to do magic damage/percentResiste/FixedResist separated from attack damage.
     
  20. TwoVenomous

    TwoVenomous

    Joined:
    Sep 11, 2011
    Messages:
    1,174
    Resources:
    1
    Skins:
    1
    Resources:
    1
    how do we remove the message when attacking? something like "Novice deals 50 natural damage and 100 triggered damage for a total of 150..."

    and also, if we already have a multiboard.. this system doesn't show it's multiboard anymore.. :ogre_frown:

    another thing is, on your screenshot it said "8 natural damages and 32 triggered damages for a total of 41". shouldn't it be 40 ?