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

[vJASS] Need advice on custom damage system

Status
Not open for further replies.
Level 5
Joined
Jun 7, 2012
Messages
66
Sorry for my english. If needed I will try to explain more.

I have completely custom damage system and all damage in my map goes through function Damage(). In my map I have custom hero builder, several hundreds of creatures most of which use custom spells, tens of bosses wih 5-20 skills/debuffs/etc. I make everything stack with everything and never know what players will get in 1 game(which combination of abilities etc).

For example I can have debuff "when unit recieves damage he can release 5 fireballs which fly in random directions", so when I only began to work with my "damage system" I would check each time in Damage() function if "unit, recieving damage has debuff, if this damage is not reflected, if this damage is not periodic, if this damage is not coming from unit himself, and if unit has this debuff". But then I added and added, and each time someone strikes unit I need to perform 50-100 similar checks. I tried to optimise it as much as I could, but ultimately it becomes laggy when lot instanses of damage happens simulateonusly.

I decided to change system a little so I started adding "modifiers" to units and then performing checks only on this modifiers.
Code:
nothing DamageInteract9_f(integer mod) {
  real q
  real q2
  if mod>8 then
    if mod>12 then
      if mod>14 then
        if mod==16 then
          //
        elseif mod==15 then
          //
        endif
      elseif mod==14 then
        //
      elseif mod==13 then
        //
      endif
    elseif mod>10 then
      if mod==12 then
        //
      elseif mod==11 && not DMprock && not DMreflected && not DMperiodic && not DMaoe then
        q=GetHeroStatPercent(Vu,HERO_STAT_DISINTEGRATION)
        if q>0. then
          q2=GetWidgetLife(Vtarget)
          if q2>0. then
            q=q*GetWidgetLife(Vu)/q2
            if GetRandomReal(0.,100.)<=q then
              DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayDamage.mdl",Vtarget,"chest"))
              DamageDelayedRemote(Vu,Vtarget,0.05*GetWidgetLife(Vtarget),7,6,0.1)
            endif
          endif
        endif
      endif
    elseif mod==10 && not DMreflected && not DMperiodic then
      q=GetHeroStatPercent(Vu,HERO_STAT_CHARM)
      if q>0. then
        q2=10.
        if DMaoe then
          q2=q2/3.
        endif
        if GetRandomReal(0.,100.)<=q2 then
          Vtimer=UnitAddBuff(Vu,Vtarget,3.,3,5*10000+7,0,0,0,0,234,0,'A062','BHab')
          SaveReal(h,GetHandleId(Vtimer),41,q)
        endif
      endif
    elseif mod==9 && not DMprock && not DMreflected && not DMperiodic then
      q=GetHeroStatPercent(Vu,HERO_STAT_SMITE)
      if q>0. then
        if DMaoe then
          q=q/3.
        endif
        if GetRandomReal(0.,100.)<=q then
          DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl",Vtarget,"origin"))
          UnitStunUnit(Vu,Vtarget,1.,'A05W','BSTN',2,235)
          DamageDelayedRemote(Vu,Vtarget,3.*GetHeroSP(Vu),7,7,0.1)
        endif
      endif
    endif
  elseif mod<=4 then
    if mod<=2 then
      if mod==1 && not DMprock && not DMreflected && not DMperiodic then
        q=GetHeroStatPercent(Vu,HERO_STAT_FREEZE)
        if DMaoe then
          q=q/3.
        endif
        if GetRandomReal(0.,100.)<=q then
          UnitStunUnit(Vu,Vtarget,1.,'A05D','BHds',2,235)
          DamageDelayedRemote(Vu,Vtarget,3.*GetHeroSP(Vu),7,3,0.1)
        endif
      elseif mod==2 && not DMprock && not DMreflected && not DMperiodic then
        q=GetHeroStatPercent(Vu,HERO_STAT_NUMBNESS)
        if DMaoe then
          q=q/3.
        endif
        if GetRandomReal(0.,100.)<=q then
          UnitSlowUnit(Vu,Vtarget,3.,'A05E','BHbd',2,237)
          DamageDelayedRemote(Vu,Vtarget,2.*GetHeroSP(Vu),7,3,0.1)
        endif
      endif
    else
      if mod==3 && not DMreflected && not DMperiodic then
        q=GetHeroStatPercent(Vu,HERO_STAT_VAMPIRISM)
        if DMaoe then
          q=q/3.
        endif
        HealDelayed(Vu,Vu,q*0.01*GetUnitState(Vu,UNIT_STATE_MAX_LIFE),234,6,0.03)
      elseif mod==4 && not DMreflected && not DMprock then
        q=GetHeroStatPercent(Vu,HERO_STAT_DUALITY)
        if DMaoe then
          q=q/3.
        endif
        if GetRandomReal(0.,100.)<=q then
          DamageDelayedRemote(Vu,Vtarget,VdamageZero,7,DMtype,0.5)
        endif
      endif
    endif
  else
    if mod<=6 then
      if mod==5 && not DMreflected && not DMperiodic then
        q=GetHeroStatPercent(Vu,HERO_STAT_COMBUSTION)
        if q>0. && GetRandomReal(0.,100.)<=q then
          UnitAddBuff(Vu,Vtarget,5.,2,0,0,0,0,0,234,0,'A05K','BHbn')
          SimpleDotDamage(Vu,Vtarget,'A05K',4.*GetHeroSP(Vu),5.,2,TYPE_FIRE,null,null)
        endif
      elseif mod==6 && not DMreflected && not DMprock && not DMperiodic then
        q=GetHeroStatPercent(Vu,HERO_STAT_MASSIVENESS)
        if DMaoe then
          q=q/3.
        endif
        if q>0. && GetRandomReal(0.,100.)<=q then
          Vgroup=GetSkillEnemiesInRange(GetUnitX(Vtarget),GetUnitY(Vtarget),180.,Vu)
          q=CountUnitsInGroup(Vgroup)
          loop
            Vu2=GroupPickRandomUnit(Vgroup)
            exitwhen Vu2==null || q<=5.
            q--
            GroupRemoveUnit(Vgroup,Vu2)
          endloop
          Vu2=null
          DamageGroupRemote(Vu,Vgroup,VdamageZero,67,DMtype)
          DestroyGroup(Vgroup)
        endif
      endif
    else
      if mod==7 && not DMaoe && not DMperiodic then
        if GetUnitAbilityLevel(Vu,'A05M')>0 then
          Vtimer=FindBuffAnyTimer(Vu,'A05M')
          if Vtimer!=null then
            Vu2=GetBuffSender(Vtimer)
            DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl",Vtarget,"chest"))
            DamageDelayedRemote(Vu,Vtarget,GetHeroStatPercent(Vu2,HERO_STAT_LETHALITY)*GetHeroAP(Vu2),7,1,0.2)
            UnitRemoveBuffInstance(Vu,Vu2,'A05M')
          endif
        endif
      elseif mod==8 && not DMperiodic && not DMreflected then
        q=GetHeroStatPercent(Vu,HERO_STAT_PILLAGING)
        if q>0. then
          if DMaoe then
            q=q/3.
          endif
          if GetRandomReal(0.,100.)<=q then
            Vitem=CreateItem(GetPillagingItemType(Vu),GetUnitX(Vu),GetUnitY(Vu))
            UnitAddItem(Vu,Vitem)
          endif
        endif
      endif
    endif
  endif
}

So if unit has modifiers 3,5 and 8 my Damage() will call this function 3 times with these parameters, so instead of performing 100-200 checks for each damage source I reduce it to 10-20 checks but it goes through these trees of "ifs".

Now I started to work on new map and decided to encompass lot's of increase/decrease damage in Custom Buffs/Stats which would remove more than half of these checks.

But I still have things like "when unit gets hit release frostbolt with 3% chance", and it needs to prock from spells/melee attack. I've got strange idea of doing ExecuteFunc() or TriggerExecute() and put in these functions/triggers seperate things, so my Damage() won't have to do tons of "if" checks, but I think that it will be less effective.

I think that there might be easier solution but I am not seeing it.

Here is full code of my old damage system if you want to know how bad it gets.
Code:
library DamageMods initializer Init uses Buffs,Hero,DamageDiff

public hashtable HH
private group TempGroup
private unit TempUnit

//private integer array CharMods

nothing UnitAddDamageMod(unit u,integer typ,integer modid) {
  integer uid=GetHandleId(u)
  integer n=LoadInteger(HH,uid,typ*10000)
  integer i=1
  if uid==0 then
    return
  endif
  loop
    exitwhen i>n
    if LoadInteger(HH,uid,typ*10000+i)==modid then
      return
    endif
    i++
  endloop
  SaveInteger(HH,uid,typ*10000+n+1,modid)
  SaveInteger(HH,uid,typ*10000,n+1)
  if typ==1 then
    UnitHandleSave_DamageModCount1[GetUnitUserData(u)]=n+1
  elseif typ==2 then
    UnitHandleSave_DamageModCount2[GetUnitUserData(u)]=n+1
  elseif typ==3 then
    UnitHandleSave_DamageModCount3[GetUnitUserData(u)]=n+1
  elseif typ==4 then
    UnitHandleSave_DamageModCount4[GetUnitUserData(u)]=n+1
  elseif typ==5 then
    UnitHandleSave_DamageModCount5[GetUnitUserData(u)]=n+1
  elseif typ==6 then
    UnitHandleSave_DamageModCount6[GetUnitUserData(u)]=n+1
  elseif typ==7 then
    UnitHandleSave_DamageModCount7[GetUnitUserData(u)]=n+1
  elseif typ==8 then
    UnitHandleSave_DamageModCount8[GetUnitUserData(u)]=n+1
  elseif typ==9 then
    UnitHandleSave_DamageModCount9[GetUnitUserData(u)]=n+1
  elseif typ==10 then
    UnitHandleSave_DamageModCount10[GetUnitUserData(u)]=n+1
  elseif typ==11 then
    UnitHandleSave_DamageModCount11[GetUnitUserData(u)]=n+1
  elseif typ==12 then
    UnitHandleSave_DamageModCount12[GetUnitUserData(u)]=n+1
  elseif typ==13 then
    UnitHandleSave_DamageModCount13[GetUnitUserData(u)]=n+1
  endif
}

nothing UnitAddDamageModCall() {
  UnitAddDamageMod(Remote_u,Remote_typ,Remote_modid)
}

public unit UnitInitDamageMods_Unit
nothing UnitInitDamageMods() {//из типа юнита
  unit u=UnitInitDamageMods_Unit
  integer uid=GetUnitTypeId(u)
  integer n=LoadInteger(HH,uid,0)
  integer q
  if n>0 then
    loop
      exitwhen n<=0
      q=LoadInteger(HH,uid,n)
      UnitAddDamageMod(u,q/10000,ost(q,10000))
      n--
    endloop
  endif
  u=null
}

nothing UnitTypeAddDamageMod(integer uid,integer typ,integer modid) {
  integer n=LoadInteger(HH,uid,0)+1
  SaveInteger(HH,uid,n,typ*10000+modid)
  SaveInteger(HH,uid,0,n)
}

integer GetUnitDamageMod(integer uid,integer typ,integer index) {
  return LoadInteger(HH,uid,typ*10000+index)
}

integer GetUnitDamageModCount(integer uid,integer typ) {
  if uid==0 then
    return 0
  endif
  return LoadInteger(HH,uid,typ*10000)
}

nothing DamageGroupDelayed_f() {
    ExecuteFunc("DamageGroupDelayed_r")
}

nothing DamageGroupDelayed(unit u,group g,real damage,integer modif,integer typ,integer dodgetype,string eff,string attach,real time) {
    timer t=CreateTimer()
    integer tid=GetHandleId(t)
    SaveUnitHandle(udg_h,tid,1,u)
    SaveGroupHandle(udg_h,tid,2,g)
    SaveReal(udg_h,tid,3,damage)
    SaveInteger(udg_h,tid,4,modif)
    SaveInteger(udg_h,tid,5,typ)
    SaveInteger(udg_h,tid,6,dodgetype)
    SaveStr(udg_h,tid,7,eff)
    SaveStr(udg_h,tid,8,attach)
    TimerStart(t,time,false,function DamageGroupDelayed_f)
    t=null
}

nothing DamageInteract1_f(integer mod) {
  integer tempi
  real tempr
  if mod>2 then//3-4
    if mod==4 then//100% меткость бафф
      if GetUnitAbilityLevel(Vu,'B02A')>0 then
        DMcrit=true
      endif
    elseif mod==3 then//искусство вампиров:П1
      if not DMreflected && not DMperiodic && not DMaoe && GetHeroSpellbookLevel(Vu,'A0CL')>=3 then
        Vdamage=Vdamage+0.1*GetHeroDMG(Vu)*GetHeroMasteryMultiplier(Vu)
        DamageLib_Ha=0.12*GetHeroDMG(Vu)*GetHeroMasteryMultiplier(Vu)
        DamageLib_Hu=Vu
        ExecuteFunc("HeroVampiricHeal")
      endif
    endif
  elseif mod==2 then//воздаяние:П1
    if not DMreflected && not DMperiodic && GetHeroSpellbookLevel(Vu,'A0GB')>=3 then
      tempr=25.*GetHeroMasteryMultiplier(Vu)
      if DMaoe then
        tempr=tempr/3.
      endif
      if GetRandomReal(0.,100.)<=tempr then
        Vdamage=Vdamage+0.75*GetHeroDMG(Vu)
      endif
    endif
  elseif mod==1 then//Мастер оружия:П1
    if not DMreflected && not DMperiodic && GetHeroSpellbookLevel(Vu,'A052')>=3 then
      if DMaoe then
        Vdamage=Vdamage*(1.+0.1*GetHeroMasteryMultiplier(Vu))
      else
        tempi=LoadInteger(udg_h,GetHandleId(Vu),61)+1
        if tempi>=3 then
          tempi=0
          DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\GryphonRiderMissile\\GryphonRiderMissile.mdl",Vtarget,"chest"))
          Vdamage=Vdamage+0.7*GetHeroDMG(Vu)
        endif
        SaveInteger(udg_h,GetHandleId(Vu),61,tempi)
      endif
    endif
  endif
}

nothing DamageInteract3_f(integer mod) {
  if mod==1 then //каменная кожа
    if GetUnitAbilityLevel(Vtarget,'A0TF')>0 && not DMperiodic then
      Vdamage-=100.//RoolsRoom
      if Vdamage<0. then
        Vdamage=0.
      endif
    endif
  endif
}

nothing DamageInteract4_f(integer mod) {
  if mod>4 then//5-8
    if mod>6 then//7-8
   
    else//5-6
      if mod==6 then//божественный щит
        if GetUnitAbilityLevel(Vtarget,'B029')>0 then
          Vdamage=0.
        endif
      elseif mod==5 then//танкоезд:непробиваемый щит
        if GetUnitAbilityLevel(Vtarget,'Bdvv')>0 then
          Vdamage=0.
        endif
      endif
    endif
  elseif mod>2 then//3-4
    if mod==4 then//временная неуязвимость
      if GetUnitAbilityLevel(Vtarget,'BOww')>0 then
        Vdamage=0.
      endif
    elseif mod==3 then//растворение в тенях
      if GetUnitAbilityLevel(Vtarget,'B00P')>0 then
        Vdamage=0.
      endif
    endif
  elseif mod==2 then//воу воу полехче
    if GetUnitAbilityLevel(Vtarget,'Bpos')>0 then
      Vdamage=0.
    endif
  elseif mod==1 then//бафф Гранитная кожа
    if GetUnitAbilityLevel(Vtarget,'B00E')>0 then//гранитная кожа
      if not DMreflected then
        if not DMperiodic then
          DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\RockBoltMissile\\RockBoltMissile.mdl",Vu,"chest"))
        endif
        if Vdamage>0.5*GetUnitState(Vu,UNIT_STATE_MAX_LIFE) then
          Vdamage=0.5*GetUnitState(Vu,UNIT_STATE_MAX_LIFE)
        endif
        DamageDelayedRemote(Vtarget,Vu,Vdamage,DMG_REFLECT,TYPE_NATURE,0.1)
      endif
      Vdamage=0.
    endif
  endif
}

nothing DamageInteract5_f(integer mod) {
  integer tempi
  unit tempu
  real tempr
  if mod>16//17-32
    if mod>24 then//25-32
   
    elseif mod>20//21-24
      if mod>22 then//23-24
     
      else//21-22
        if mod==22 then//22
       
        else//21
       
        endif
      endif
    elseif mod>18//19-20
      if mod==20 then//20 Брутальные удары(сектор приз)
        if GetUnitAbilityLevel(Vu,'B027')>0 && not IsUnitType(Vtarget,UNIT_TYPE_HERO) then 
          Vdamage=Vdamage*(1.+TalentBonus1[1])
          tempr=TalentBonus2[1]
          if not DMperiodic && Vdamage>=0.05*GetWidgetLife(Vtarget) then
            if DMaoe then
              tempr=tempr/3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Orc\\OrcLargeDeathExplode\\OrcLargeDeathExplode.mdl",Vtarget,"origin"))
              Vdamage=Vdamage*10.
            endif
          endif
        endif
      else//19
        if GetUnitAbilityLevel(Vu,'B01L')>0 then//мораль
          Vdamage=Vdamage*1.1
        elseif GetUnitAbilityLevel(Vu,'B01M')>0 then//высокая мораль
          Vdamage=Vdamage*1.2
        elseif GetUnitAbilityLevel(Vu,'B01N')>0 then//максимальная мораль
          Vdamage=Vdamage*1.3
        elseif GetUnitAbilityLevel(Vu,'B01O')>0 then//низкая мораль
          Vdamage=Vdamage*0.9
        endif
      endif
    elseif mod==18//18 талант: жертвы во благо
      if GetUnitAbilityLevel(Vu,'A0Y6')>0 then
        Vdamage=Vdamage*(1.+GetHeroIdTalentBonus1(Vuid,8))
      elseif GetUnitAbilityLevel(Vu,'A0Y5')>0 then
        Vdamage=Vdamage*(1.+GetHeroIdTalentBonus2(Vuid,8))
      endif
    else//17
      if GetUnitAbilityLevel(Vu,'A0Y4')>0 then//мясо педокапканчика
        Vdamage=Vdamage*1.35
      endif
    endif
  elseif mod>8 then//9-16
    if mod>12 then//13-16
      if mod>14 then//15-16
        if mod==16 then//талант:Уничтожитель бессмертных
          if GetUnitAbilityLevel(Vu,'A0Y2')>0 then
            Vdamage=Vdamage*(1.+GetHeroIdTalentBonus1(Vuid,5))
          endif
        elseif mod==15 then
          if GetUnitAbilityLevel(Vu,'BHav')>0 and DMautoattack and not DMaoe then
            tempi=LoadInteger(udg_h,Vuid,35)-1
            if tempi<=0 then
              UnitRemoveBuff(Vu,'A01H')
            else
              SaveInteger(udg_h,Vuid,35,tempi)
            endif
          endif
        endif
      else//13-14
        if mod==14 then//каменные кулаки:босс 16 лвла
          if DMautoattack and GetUnitAbilityLevel(Vu,'B00D')>0 then
            Vdamage=Vdamage*2.
          endif
        elseif mod==13 then//кровожад:П1
          if not DMaoe && not DMreflected && not DMperiodic then 
            tempi=GetHeroSpellbookLevel(Vu,'A03T')
            if tempi>=3 then
              tempu=LoadUnitHandle(udg_h,GetHandleId(Vu),58)
              if Vtarget==tempu then
                tempi=LoadInteger(udg_h,GetHandleId(Vu),59)+1
                if tempi<=3 then
                  SaveInteger(udg_h,GetHandleId(Vu),59,tempi)
                else
                  tempi=4
                endif
                tempi=tempi-1
              else
                SaveUnitHandle(udg_h,GetHandleId(Vu),58,Vtarget)
                SaveInteger(udg_h,GetHandleId(Vu),59,1)
                tempi=0
              endif
              Vdamage=Vdamage*(1.+0.05*tempi*GetHeroMasteryMultiplier(Vu))
              tempu=null
            endif
          endif
        endif
      endif
    else//9-12
      if mod>10 then//11-12
        if mod==12 then//каменные перчатки
          if DMmelee && GetUnitAbilityLevel(Vu,'Bdtb')>0 then
            Vdamage=Vdamage*1.25
          endif
        elseif mod==11 then//благословение могущества
          if GetUnitAbilityLevel(Vu,'BUim')>0 then
            Vdamage=Vdamage*1.12
          endif
        endif
      else//9-10
        if mod==10 then//тело бессмертного
          if GetHeroSpellbookLevel(Vu,'A09G')>=3 && DMautoattack then
            Vdamage=Vdamage*(1.+0.3*GetHeroMasteryMultiplier(Vu))
          endif
        elseif mod==9 then//контроль разума П1
          if GetHeroSpellbookLevel(Vu,'A0UL')>=3 then
            if GetUnitState(Vu,UNIT_STATE_MANA)>GetUnitState(Vtarget,UNIT_STATE_MANA) then
              Vdamage=Vdamage*(1.+0.16*GetHeroMasteryMultiplier(Vu))
            endif
          endif
        endif
      endif
    endif
  elseif mod>4 then//5-8
    if mod>6 then//7-8
      if mod==8 then//герои:статы/бонусы/таланты
        Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,1) //скрытый бонус 1
        if GetUnitLifePercent(Vtarget)<=30. then
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,3) //скрытый бонус 3
        endif
        if GetUnitLifePercent(Vtarget)>=80. && DMcrit then//талант 2 Инициация
          Vdamage=Vdamage*(1.+GetHeroIdTalentBonus2(Vuid,2))
        endif
        if not CompareTimeDiff(Vu,302,4.) then //повышенный урон в теч. 4 секунд после прыжка
          Vdamage=Vdamage*(1.+GetHeroDamageAfterJumpBonus(Vu))
        endif
        if DMcrit then 
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,4)//скрытый бонус 4
          Vdamage=Vdamage*(1.+0.01*GetHeroBaseCritDamageBonusPercent(Vu))//бонусный урон критов от меткости
          if GetRandomReal(0.,100.)<=5. then
            tempr=1.+2.*GetHeroIdTalentBonus1(Vuid,29)
            if tempr>1. then
              Vdamage=Vdamage*tempr
            endif
          endif
        endif
        if DMaoe then //скрытый бонус 6
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,6)
        else  //скрытый бонус 7
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,7)
        endif
        if DMperiodic then //скрытый бонус 8
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,8)
        endif
        if DMreflected then //скрытый бонус 22
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,22)
        endif
        if DMautoattack then //скрытый бонус 35
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,35)
        endif
        if GetUnitAbilityLevel(Vtarget,'A0PP')>0 || GetUnitAbilityLevel(Vtarget,'A01W')>0 then //скрытый бонус 37
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,37)
        endif
        if not IsUnitType(Vtarget,UNIT_TYPE_HERO) then 
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vuid,38)//скрытый бонус 38
          tempr=GetHeroIdTalentBonus1(Vuid,1)//ТАЛАНТ 1: СОКРУШИТЕЛЬ
          if tempr>0. then
            Vdamage=Vdamage*(1.+tempr)
            tempr=GetHeroIdTalentBonus2(Vuid,1)
            if not DMperiodic && Vdamage>=0.05*GetWidgetLife(Vtarget) then
              if DMaoe then
                tempr=tempr/3.
              endif
              if GetRandomReal(0.,100.)<=tempr then
                DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Orc\\OrcLargeDeathExplode\\OrcLargeDeathExplode.mdl",Vtarget,"origin"))
                Vdamage=Vdamage*10.
              endif
            endif
          endif
        endif
        if IsUnitUnderAnyControl(Vtarget) || LoadInteger(udg_h,Vtid,320)>0 then
          Vdamage=Vdamage*(1.+0.01*GetHeroFreezeBonusDamagePercent(Vu))
        endif
      elseif mod==7 then//мясо педокапкана:+наносимый урон
        if GetUnitAbilityLevel(Vu,'B008')>0 then
          Vdamage=Vdamage*5.
        endif
      endif
    else//5-6
      if mod==6 then//кулаки бессмертного      
        if GetUnitAbilityLevel(Vu,'BOhx')>0 and DMautoattack then 
          if not DMaoe then
            tempi=LoadInteger(udg_h,GetHandleId(Vu),64)-1
            if tempi>0 then
              SaveInteger(udg_h,GetHandleId(Vu),64,tempi)
            else
              UnitRemoveBuff(Vu,'A09E')
            endif
          endif
          Vdamage=Vdamage*1.6
        endif
      elseif mod==5 then//сжигатель маны
        if GetUnitAbilityLevel(Vu,'A0I6')>0 then
          Vdamage=Vdamage*(0.25+0.75*GetUnitManaPercent(Vtarget)*0.01)
        endif
      endif
    endif
  elseif mod>2 then//3-4
    if mod==4 then//ярость x10 урон
      if GetUnitAbilityLevel(Vu,'BUav')>0 then
        Vdamage=Vdamage*10.
      endif
    elseif mod==3 then
      if GetUnitAbilityLevel(Vu,'BNhs')>0 && DMautoattack then //духовная связь x3 мобы
        Vdamage=Vdamage*3.
      endif
    endif
  elseif mod==2 then//удар в спину x5 мобы
    if GetUnitAbilityLevel(Vu,'Bapl')>0 && DMautoattack && CompareAngles(AngleBetweenUnits(Vu,Vtarget),GetUnitFacing(Vtarget),90.) then
      Vdamage=Vdamage*5.
    endif
  elseif mod==1 then
    Vdamage=Vdamage*(1.+LoadReal(udg_h,GetHandleId(Vu),107))
  endif
}

nothing DamageInteract6_f(integer mod) {
  integer tempi
  real tempr
  if mod>16 then//17-32
    if mod>24 then//25-32
   
    elseif mod>20 then//21-24
   
    elseif mod>18 then//19-20
      if mod==20 then//20
     
      else//19 Каменный щит
        if DMautoattack && GetUnitAbilityLevel(Vtarget,'B028')>0 then
          Vdamage=Vdamage*0.1
        endif
      endif
    elseif mod==18 then//18 Стальная кожа(игнор урона меньше 10% здоровья героя)
      if GetUnitAbilityLevel(Vtarget,'B026')>0 && Vdamage/GetUnitState(Vtarget,UNIT_STATE_MAX_LIFE)<=0.1 then
        Vdamage=0.
      endif
    else//17 талант Сейвспот(уменьшение урона)
      if GetUnitAbilityLevel(Vtarget,'B01G')>0 then
        Vdamage=Vdamage*(1.-0.4-GetHeroIdTalentBonus2(Vtid,22))
      endif
    endif
  elseif mod>8 then//9-16
    if mod>12 then//13-16
      if mod>14 then//15-16
        if mod==16 then//талант:крепость
          if GetUnitAbilityLevel(Vtarget,'BNmp')>0 then
            Vdamage=Vdamage*(1.-GetHeroIdTalentBonus1(Vtid,14))
          endif
        elseif mod==15 then//барьер демонмена(19 лвл)
          if GetUnitAbilityLevel(Vtarget,'B017')>0 then
            Vdamage=Vdamage*0.2
          endif
        endif
      else//13-14
        if mod==14 then//Буйство(мобы/боссы)
          if GetUnitAbilityLevel(Vtarget,'B016')>0 then
            Vdamage=Vdamage*3.
          endif
        elseif mod==13 then//защитник П1
          tempi=GetHeroSpellbookLevel(Vtarget,'A0DF') 
          if tempi>=3 && GetRandomReal(0.,100.)<=50. then
            Vdamage=Vdamage*(1.-0.24*GetHeroMasteryMultiplier(Vtarget))
          endif
        endif
      endif
    else//9-12
      if mod>10 then//11-12
        if mod==12 then//благословение защищенности
          if GetUnitAbilityLevel(Vtarget,'Babr')>0 then
            Vdamage=Vdamage*0.9
          endif
        elseif mod==11 then//книга камня П1
          tempi=GetHeroSpellbookLevel(Vtarget,'A03D')
          if tempi>=3 && GetRandomReal(0.,100.)<=30.*GetHeroMasteryMultiplier(Vtarget) then
            Vdamage=Vdamage*0.6
          endif
        endif
      else//9-10
        if mod==10 then//мясо педокапкана
          if GetUnitAbilityLevel(Vtarget,'B008')>0 then
            Vdamage=Vdamage*0.2
          endif
        elseif mod==9 then//герой:получающий
          tempr=GetHeroIdTalentBonus1(Vtid,17)
          if tempr>0. && Vdamage/GetUnitState(Vtarget,UNIT_STATE_MAX_LIFE)<=0.1 && GetRandomReal(0.,100.)<=tempr then
            Vdamage=0.
          endif
          if Vdamage/GetUnitState(Vtarget,UNIT_STATE_MAX_LIFE)>=0.2 then
            Vdamage=Vdamage*(1.-0.01*GetHeroReduced20hpDamagePercent(Vtarget))
          endif
          Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,2) //скрытый бонус 2
          if GetUnitLifePercent(Vtarget)<=30. then //скрытый бонус 16
            Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,16)
          endif
          if DMautoattack then //скрытый бонус 17
            Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,17)
          endif
          if DMaoe then //скрытый бонус 18 + бонус уклонения
            Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,18)
            Vdamage=Vdamage*(1.-0.01*GetHeroReducedAoeDamagePercent(Vtarget))
          endif
          if DMreflected then //скрытый бонус 23
            Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,23)
          endif
          if not IsUnitType(Vu,UNIT_TYPE_HERO) then //скрытый бонус 39
            Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,39)
          endif
          if IsUnitUnderAnyControl(Vtarget) then //скрытый бонус 44 + защита под контролем
            Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,44)
            Vdamage=Vdamage*(1.-GetHeroDefenceInControl(Vtarget))
          endif
        endif
      endif
    endif
  elseif mod>4 then//5-8
    if mod>6 then//7-8
      if mod==8 then//глушащий щит
        if GetUnitAbilityLevel(Vtarget,'BUdd')>0 then
          Vdamage=Vdamage*0.2
        endif
      elseif mod==7 then//непробиваемость
        if GetUnitAbilityLevel(Vtarget,'Bprg')>0 then
          Vdamage=Vdamage*0.6
        endif
      endif
    else//5-6
      if mod==6 then//ледяной щит
        if GetUnitAbilityLevel(Vtarget,'BHtc')>0 then
          Vdamage=Vdamage*0.9
        endif
      elseif mod==5 then//раскол брони дебафф x2.5 урона от автоатак
        if GetUnitAbilityLevel(Vtarget,'BIrm')>0 && DMautoattack then
          Vdamage=Vdamage*2.5
        endif
      endif
    endif
  elseif mod>2 then//3-4
    if mod==4 then//дебафф яд на x5 получаемого урона от автоатак
      if GetUnitAbilityLevel(Vtarget,'Bstt')>0 && DMautoattack && udg_time-LoadReal(udg_h,GetHandleId(Vtarget),68)>=2.5 then
        Vdamage=Vdamage*5.
      endif
    elseif mod==3 then
      if GetUnitAbilityLevel(Vtarget,'B00K')>0 && DMmelee then//пролом брони
        Vdamage=Vdamage*1.2
      endif
    endif
  elseif mod==2 then//подкидывание
    if GetUnitAbilityLevel(Vtarget,'B00C')>0 && GetUnitAbilityLevel(Vtarget,'B000')==0 then
      Vdamage=Vdamage*1.3
    endif
  elseif mod==1 then//пассивка саммонов
    if GetUnitAbilityLevel(Vtarget,'A0PP')>0 && Vu!=null then 
      if DMaoe then
        Vdamage=Vdamage/5.
      elseif not IsUnitType(Vu,UNIT_TYPE_HERO) then
        Vdamage=Vdamage/3.
      endif
    endif
  endif
}

nothing DamageInteract7_f(integer mod) {
  real tempr
  real tempr2
  unit tempu
  integer tempi
  if mod>16 then//17-32
    if mod>24 then//25-32
   
    elseif mod>20 then//21-24
   
    elseif mod>18 then//19-20
   
    elseif mod==18 then//18
   
    elseif mod==17 then//17 Адаптация: П1
      if GetHeroSpellbookLevel(Vtarget,'A103')>=3 && GetRandomReal(0.,100.)<=9.*GetHeroMasteryMultiplier(Vtarget) then
        tempr=2.*GetHeroDMG(Vtarget)
        if Vdamage<tempr then
          tempr=Vdamage
          Vdamage=0.
        else
          Vdamage=Vdamage-tempr
        endif
        DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",Vtarget,"overhead"))
        HealDelayedRemote(Vtarget,Vtarget,tempr,0.05)
      endif
    endif
  elseif mod>8 then//9-16
    if mod>12 then//13-16
      if mod>14 then//15-16
        if mod==16 then//надприродные шипы
          if GetUnitAbilityLevel(Vtarget,'B02C')>0 then
            tempr=0.75*Vdamage
            Vdamage=Vdamage-tempr
            DamageDelayedRemote(Vtarget,Vu,tempr,13,TYPE_NATURE,0.1)
          endif
        else//15 самобичевание
          if GetUnitAbilityLevel(Vu,'B01W')>0 then
            tempr=0.3*Vdamage
            Vdamage=Vdamage-tempr
            DamageDelayedRemote(Vu,Vu,tempr,13,DMtype,0.1)
          endif
        endif
      elseif mod==14//14 Яд(сборщик хлама)
        if DMmelee && not DMperiodic && not DMreflected && GetUnitAbilityLevel(Vtarget,'B01U')>0 then
          tempi=GetUnitBuffDataInteger(Vtarget,'A0ZD',1)
          if tempi<5 && GetUnitAbilityLevel(Vu,'Binv')==0 then
            SetUnitBuffDataInteger(Vtarget,'A0ZD',1,tempi+1)
            PoisoningRemote(Vtarget,Vu,7*GetHeroDMG(Vtarget),20.)
          endif
        endif
      else//13 Огненный щит(сборщик хлама)
        if DMmelee && not DMperiodic && GetUnitAbilityLevel(Vtarget,'B01R')>0 then
          AddSpecialEffectTargetTimed("Abilities\\Spells\\Other\\ImmolationRed\\ImmolationRedDamage.mdl",Vtarget,"chest",2.)
          DamageDelayedRemote(Vtarget,Vu,GetHeroDMG(Vtarget),13,TYPE_FIRE,0.1)
        endif
      endif
    else//9-12
      if mod>10 then//11-12
        if mod==12 then
          if GetUnitAbilityLevel(Vu,'Bpxf')>0 && not DMperiodic && not DMreflected then
            tempr=RMaxBJ(Vdamage,VdamageZero)
            BurningRemote(Vu,Vtarget,tempr*0.2,3.)
          endif
        elseif mod==11 then
          if DMmelee && not DMperiodic && GetUnitAbilityLevel(Vtarget,'BCbf')>0 then//взрывоопасная мазь
            DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\GyroCopter\\GyroCopterMissile.mdl",Vtarget,"chest"))
            DamageDelayedRemote(Vtarget,Vu,0.75*GetHeroDMG(Vtarget),13,TYPE_FIRE,0.1)
          endif
        endif
      else
        if mod==10 then  //аура шипов
          if not DMperiodic && GetUnitAbilityLevel(Vtarget,'BEim')>0 then
            tempu=LoadUnitHandle(udg_h,GetHandleId(Vtarget),306)
            DamageDelayedRemote(Vtarget,Vu,1.*GetHeroDMG(tempu),13,TYPE_NATURE,0.1)
            tempu=null
          endif
        elseif mod==9 then//каменная кожа: мобы
          if GetUnitAbilityLevel(Vtarget,'A0TF')>0 && not DMperiodic && not DMreflected then
            tempr=150.
            DamageDelayedRemote(Vtarget,Vu,tempr,13,TYPE_NATURE,0.1)
          endif
        endif
      endif
    endif
  elseif mod>4 then//5-8
    if mod>6 then//7-8
      if mod==8 && not DMperiodic then//модификаторы всех героев:стат Шипы
        if DMmelee || GetRandomReal(0.,100.)<=GetHeroRangedSpikesPercent(Vtarget) then
          tempr=GetHeroSpikesDamage(Vtarget)
          if DMaoe then
            tempr=tempr/3.
          elseif CompareTimeDiffAndChange(Vtarget,301,4.) then
            tempr=tempr*(1.+0.01*GetHeroSpikes4secBonusPercent(Vtarget))
          endif
          if tempr>0. then
            DamageDelayedRemote(Vtarget,Vu,tempr,DMG_REFLECT,TYPE_PHISIC,0.1)
          endif
        endif
      elseif mod==7 then//лед: П1
        if GetHeroSpellbookLevel(Vtarget,'A04D')>=3 then
          tempr=33.*GetHeroMasteryMultiplier(Vtarget)
          if DMaoe then
            tempr=tempr/3.
          endif
          if GetRandomReal(0.,100.)<=tempr then
            DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostArmor\\FrostArmorDamage.mdl",Vu,"chest"))
            DamageDelayedRemote(Vtarget,Vu,GetHeroDMG(Vtarget),DMG_REFLECT,TYPE_FROST,0.1)
          endif
        endif
      endif
    elseif mod==6 then//природа: П1
      if GetHeroSpellbookLevel(Vtarget,'A08T')>=3 && not DMperiodic then
        tempr=25.*GetHeroMasteryMultiplier(Vtarget)
        if DMaoe then
          tempr=tempr/3.
        endif
        if GetRandomReal(0.,100.)<=tempr && Vu!=null then
          UnitStrainUnitNormal(Vtarget,Vu,0.3,'A091','BOvd')
          DamageDelayedRemote(Vtarget,Vu,1.5*GetHeroDMG(Vtarget),3,TYPE_NATURE,0.1)
        endif
      endif
    elseif mod==5 then//зеркало: П1
      if GetHeroSpellbookLevel(Vtarget,'A06P')>=3 && GetRandomReal(0.,100.)<=10.*GetHeroMasteryMultiplier(Vtarget) then
        tempr=3.*GetHeroDMG(Vtarget)
        if Vdamage<tempr then
          tempr=Vdamage
          Vdamage=0.
        else
          Vdamage=Vdamage-tempr
        endif
        if Vu!=null then
          DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",Vu,"overhead"))
          DamageDelayedRemote(Vtarget,Vu,tempr,3,TYPE_ARCANE,0.1)
        endif
      endif
    endif
  elseif mod>2 then//3-4
    if mod==4 then//папенькины сынки отражение 500%
      if GetUnitAbilityLevel(Vtarget,'A0FS')>0 && Vu!=null then
        DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",Vu,"overhead"))
        DamageDelayedRemote(Vtarget,Vu,5.*Vdamage,136,TYPE_NATURE,0.1)
      endif
    elseif mod==3 then//саморазрушение
      if GetUnitAbilityLevel(Vtarget,'Bmil')>0 then
        tempr=LoadReal(udg_h,Vtid,62)
        tempr2=tempr-Vdamage
        if tempr2<=0. then
          tempr2=tempr
          UnitRemoveBuff(Vtarget,'A07E')
        else
          SaveReal(udg_h,Vtid,62,tempr2)
          tempr=Vdamage
        endif
        TempGroup=GetSkillEnemiesInRange(GetUnitX(Vtarget),GetUnitY(Vtarget),300.,Vtarget)
        loop
          TempUnit=FirstOfGroup(TempGroup)
          exitwhen TempUnit==null
          GroupRemoveUnit(TempGroup,TempUnit)
          DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",TempUnit,"overhead"))
          DamageDelayedRemote(Vtarget,TempUnit,tempr,136,TYPE_ARCANE,0.1)
        endloop
        DestroyGroup(TempGroup)
        TempGroup=null
      endif
    endif
  elseif mod==2 then//25% аое рефлект
    if Vdamage>0. && GetUnitAbilityLevel(Vtarget,'A0JA')>0 then
      tempr=0.25*Vdamage
      TempGroup=GetSkillEnemiesInRange(GetUnitX(Vtarget),GetUnitY(Vtarget),250.,Vtarget)
      loop
        TempUnit=FirstOfGroup(TempGroup)
        exitwhen TempUnit==null
        GroupRemoveUnit(TempGroup,TempUnit)
        DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",TempUnit,"overhead"))
        DamageDelayedRemote(Vtarget,TempUnit,tempr,136,TYPE_DARK,0.1)
      endloop
      DestroyGroup(TempGroup)
      TempGroup=null
    endif
  elseif mod==1 then//Lundy отражение дебафф
    if Vdamage>0. && GetUnitAbilityLevel(Vu,'BEah')>0 && not DMperiodic && Vu!=null then
      DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",Vu,"overhead"))
      DamageDelayedRemote(Vtarget,Vu,Vdamage,13,TYPE_DARK,0.1)
    endif
  endif
}

nothing DamageInteract8_f(integer mod) {
  real tempr
  if mod>2 then//3-4
    if mod==4 then//4

    else//3 Взрывной щит
      if GetUnitAbilityLevel(Vtarget,'B01Z')>0 then
        SaveReal(udg_h,Vtid,500,LoadReal(udg_h,Vtid,500)+Vdamage)
        Vdamage=0.
      endif
    endif
  elseif mod==2 then//"Сейвспот" абсорб
    if GetUnitAbilityLevel(Vtarget,'B01H')>0 then
      tempr=GetUnitBuffDataReal(Vtarget,'A0YM',1)
      Vdamage=Vdamage-tempr
      if Vdamage<0. then
        tempr=-Vdamage
        SetUnitBuffDataReal(Vtarget,'A0YM',1,tempr)
        Vdamage=0.
      else
        UnitRemoveBuff(Vtarget,'A0YM')
      endif
    endif
  else//1 свет: щит света
    if GetUnitAbilityLevel(Vtarget,'B00Q')>0 then
      tempr=LoadReal(udg_h,Vtid,308)
      Vdamage=Vdamage-tempr
      if Vdamage<0. then
        tempr=-Vdamage
        SaveReal(udg_h,Vtid,308,tempr)
        Vdamage=0.
      else
        RemoveSavedReal(udg_h,Vtid,308)
        UnitRemoveBuff(Vtarget,'A0U1')
      endif
    endif
  endif
}

nothing DamageInteract9_f(integer mod) {
  integer tempi
  group tempg
  unit tempu
  real tempr
  if mod>16 then//17-32
    if mod>24 then//25-32
   
    else//17-24
      if mod>20 then//21-24
        if mod>22 then//23-24
          if mod==24 then//24
         
          elseif GetUnitAbilityLevel(Vu,'B02D')>0//23 Поглощение крови 100% вампиризма
            DamageLib_Ha=Vdamage
            DamageLib_Hu=Vu
            ExecuteFunc("HeroVampiricHeal")
          endif
        else//21-22
          if mod==22 && not DMperiodic && not DMreflected && not DMaoe && GetUnitAbilityLevel(Vu,'BNpa')>0 then//печать прозрения
            tempu=GetSkillRandomAllyIncludeSelf(GetUnitX(Vtarget),GetUnitY(Vtarget),400,Vu)
            if tempu!=null then
              DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl",tempu,"origin"))
              HealDelayedRemote(Vu,tempu,0.3*GetHeroDMG(Vu),0.1)
              tempu=null
            endif
          elseif mod==21 && not DMperiodic && not DMreflected && not DMaoe && GetUnitAbilityLevel(Vu,'BNbr')>0 then//печать праведности
            tempi=5
            tempg=GetSkillEnemiesInRange(GetUnitX(Vtarget),GetUnitY(Vtarget),300,Vu)
            tempr=0.3*GetHeroDMG(Vu)
            tempu=Vtarget
            loop
              exitwhen tempi<=0 || tempu==null
              GroupRemoveUnit(tempg,tempu)
              tempi--
              //DestroyEffect(AddSpecialEffectTarget("anufisrpg\\effect\\Judgement1.mdx",tempu,"origin"))
              DamageDelayedRemote(Vu,tempu,tempr,DMG_AOE,TYPE_HOLY,0.1)
              tempu=GroupPickRandomUnit(tempg)
            endloop
            DestroyGroup(tempg)
            tempg=null
            tempu=null
          endif
        endif
      else//17-20
        if mod>18 then//19-20
          if mod==20 && DMautoattack && not DMperiodic && not DMreflected && not DMaoe then//ветер:П1
            if GetHeroSpellbookLevel(Vu,'A032')>=3 and DMautoattack  then
              tempr=40.*GetHeroMasteryMultiplier(Vu)
              if GetRandomReal(0.,100.)<=tempr then
                DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Tornado\\Tornado_Target.mdl",Vu,"chest"))
                UnitAddBuffAttackSpeed(Vu,1,5.)
              endif
            endif
          elseif mod==19 && not DMperiodic && not DMreflected then//книга теней
            if GetHeroSpellbookLevel(Vu,'A02D')>=3 then
              tempr=30.
              if DMaoe then
                tempr/=3.
              endif
              if GetRandomReal(0.,100.)<=tempr then
                tempg=LoadGroupHandle(udg_h,GetHandleId(Vu),52)
                if tempg==null then
                  tempg=CreateGroup()
                  SaveGroupHandle(udg_h,GetHandleId(Vu),52,tempg)
                endif
                tempu=CreateUnit(GetOwningPlayer(Vu),'h008',GetUnitX(Vu),GetUnitY(Vu),GetUnitFacing(Vu))
                GroupAddUnit(tempg,tempu)
                SetOwner(tempu,Vu)
                SaveReal(udg_h,GetHandleId(tempu),54,udg_time)
                MobStartAI(tempu,function AIShadowSummon,1.)
                tempg=null
                tempu=null
              endif
            endif
          endif
        else//17-18
          if mod==18 && not DMperiodic && not DMreflected then//Воинское искусство:пассивка
            if GetHeroSpellbookLevel(Vu,'A02L')>=3 then
              tempr=22.*GetHeroMasteryMultiplier(Vu)
              if DMaoe then
                tempr/=3.
              endif
              if GetRandomReal(0.,100.)<=tempr then
                BleedingRemote(Vu,Vtarget,GetHeroDMG(Vu),4.)
              endif
            endif
          elseif mod==17 && not DMperiodic && not DMreflected && not DMaoe then//Некромантия П1
            if GetHeroSpellbookLevel(Vu,'A0PQ')>=3  && CompareTimeDiff(Vu,116,12.) && GetUnitLifePercent(Vtarget)<=40. then
              CompareTimeDiffChange(Vu,116,12.)
              AddCooldownTrack(GetOwningPlayer(Vu),7,"Жнец душ",12.)
              NecromancyP1(Vu,Vtarget)
            endif
          endif
        endif
      endif
    endif
  elseif mod>8 then//9-16
    if mod>12 then//13-16
      if mod>14 then//15-16
        if mod==16 && not DMperiodic && not DMreflected then//Берсерк П1
          if GetHeroSpellbookLevel(Vu,'A0MT')>=3 && not DMaoe then
            UnitAddRage(Vu,10.*GetHeroMasteryMultiplier(Vu))
          endif
        elseif mod==15 && not DMperiodic && not DMreflected then//яростные удары
          if GetUnitAbilityLevel(Vu,'BIrg')>0 && DMautoattack && not DMaoe then
            tempi=LoadInteger(udg_h,Vuid,109)-1
            UnitAddRage(Vu,10.)
            if tempi<=0 then
              RemoveSavedInteger(udg_h,Vuid,109)
              UnitRemoveBuff(Vu,'A0N7')
            else
              SaveInteger(udg_h,Vuid,109,tempi)
            endif
          endif
        endif
      else//13-14
        if mod==14 && not DMperiodic && not DMreflected then//Живая кровь П1
          if GetHeroSpellbookLevel(Vu,'A0MD')>=3 then
            tempr=30.
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              LiveBloodRemote(Vu,Vtarget,10.*GetHeroMasteryMultiplier(Vu))
            endif
          endif
        elseif mod==13 && not DMperiodic && not DMreflected then//Яд в теле П1
          if GetHeroSpellbookLevel(Vu,'A0DU')>=3 then
            tempr=0.25*GetHeroDMG(Vu)*GetHeroMasteryMultiplier(Vu)
            if DMaoe then
              tempr/=3.
            endif
            PoisoningRemote(Vu,Vtarget,tempr,2.)
          endif
        endif
      endif
    else//9-12
      if mod>10 then//11-12
        if mod==12 && not DMperiodic && not DMreflected then//Книга огня:пассивка
          if GetHeroSpellbookLevel(Vu,'A00U')>=3 then
            tempr=22.*GetHeroMasteryMultiplier(Vu)
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              BurningRemote(Vu,Vtarget,GetHeroDMG(Vu),4.)
            endif
          endif
        elseif mod==11 && not DMperiodic && not DMreflected then//Подрывник:пассивка
          if GetHeroSpellbookLevel(Vu,'A0BA')>=3 then
            tempr=15.*GetHeroMasteryMultiplier(Vu)
            if DMaoe then
              tempr=tempr/3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              DemolishionP1(Vu,Vtarget)
            endif
          endif
        endif
      else//9-10
        if mod==10 && not DMperiodic && not DMreflected then//Болезненность:пассивка
          if GetHeroSpellbookLevel(Vu,'A0VE')>=3 then
            tempr=15.
            if DMaoe then
              tempr=tempr/3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              PlagueRemote(Vu,Vtarget,0.75*GetHeroDMG(Vu)*GetHeroMasteryMultiplier(Vu),3.)
            endif
          endif
        elseif mod==9 && not DMperiodic && not DMreflected then
          tempr=GetHeroIdTalentBonus1(Vuid,15)
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              Talent15_SpawnBloodSphere(GetOwningPlayer(Vu),Vtarget)
            endif
          endif
          tempr=GetHeroIdHiddenBonus(Vuid,41)*100. //41 скрытая характеристика
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              UnitStunUnitNormal(Vu,Vtarget,1.,'A01C','B001')
              DamageDelayedRemote(Vu,Vtarget,0.5*GetHeroDMG(Vu),0,TYPE_PHISIC,0.05)
            endif
          endif
          tempr=GetHeroIdHiddenBonus(Vuid,10) //10 скрытая характеристика
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            SetUnitState(Vu,UNIT_STATE_MANA,GetUnitState(Vu,UNIT_STATE_MANA)+tempr)
          endif
          tempr=GetHeroManaLeech(Vu)
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            SetUnitState(Vu,UNIT_STATE_MANA,GetUnitState(Vu,UNIT_STATE_MANA)+tempr)
          endif
          tempr=GetHeroFreezePercent(Vu) //стат:заморозка
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              UnitStunUnitNormal(Vu,Vtarget,1.,'A00B','BHds')
            endif
          endif
          tempr=GetHeroIdHiddenBonus(Vuid,12) //12 скрытая характеристика
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              UnitCharmUnitSimpleNormal(Vu,Vtarget,1.)
            endif
          endif
          tempr=GetHeroIdHiddenBonus(Vuid,13) //13 скрытая характеристика
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              UnitFearUnitSimpleNormal(Vu,Vtarget,1.)
            endif
          endif
          tempr=GetHeroIdHiddenBonus(Vuid,29)
          if tempr>0. and DMautoattack then
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Tornado\\Tornado_Target.mdl",Vu,"chest"))
              UnitAddBuffAttackSpeed(Vu,1,5.)
            endif
          endif
          /*tempr=GetHeroIdTalentBonus1(Vuid,3) //Талант 3 (5%)
          if tempr>0. then
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              Talent3_Summon(Vu)
            endif
          endif*/
        endif
      endif
    endif
  elseif mod>4 then//5-8
    if mod>6 then//7-8
      if mod==8 then//пет:сожжение 4 маны
        if not DMperiodic && not DMreflected && GetUnitAbilityLevel(Vu,'A0RS')>0 then
          UnitManaDrainUnitNormal(Vu,Vtarget,4.)
        endif
      elseif mod==7 then//ПУСТОТА МОЖНО ЗАПОЛНИТЬ

      endif
    else
      if mod==6 then//аура льда
        if GetUnitAbilityLevel(Vu,'Bply')>0 && not DMperiodic && not DMreflected then
          UnitOkochenenieUnitNormal(Vu,Vtarget,4.)
          tempr=33.
          if DMaoe then
            tempr/=3.
          endif
          if GetRandomReal(0.,100.)<=tempr then
            UnitStunUnitNormal(Vu,Vtarget,1.,'A00B','BHds')
          endif
        endif
      elseif mod==5 then//денди:кровотечение
        if GetUnitAbilityLevel(Vu,'A0H8')>0 && DMautoattack then
          BleedingDENDYRemote(Vu,Vtarget,30.,5.)
        endif
      endif
    endif
  elseif mod>2 then//3-4
    if mod==4 then  //устрашение:сущность призрака
      if GetUnitAbilityLevel(Vu,'Brpb')>0 && DMmelee && GetRandomReal(0.,100.)<=10. then
        UnitFearUnitNormal(Vu,Vtarget,1.,'A00D','BHbd')
      endif
    elseif mod==3 then//проклятие агонии
      if GetUnitAbilityLevel(Vu,'Bpsh')>0 && DMmelee && not DMaoe then
        SaveInteger(udg_h,Vuid,90,-1+LoadInteger(udg_h,Vuid,90))
      endif
    endif
  elseif mod==2 then//корни 100% 3-4сек
    if GetUnitAbilityLevel(Vu,'A0LE')>0 && DMautoattack then
      if GetUnitTypeId(Vu)=='h0DL' then
        UnitStrainUnitNormal(Vu,Vtarget,4.,'A02J','Bdcl')
      else
        UnitStrainUnitNormal(Vu,Vtarget,3.,'A091','BOvd')
      endif
    endif
  elseif mod==1 then//контроль разума:разрушительная эмпатия
    if GetUnitAbilityLevel(Vu,'B00T')>0 && DMautoattack then
      tempi=GetHandleId(Vu)
      tempg=LoadGroupHandle(udg_h,tempi,311)
      if tempg!=null then
        loop
          tempu=FirstOfGroup(tempg)
          exitwhen tempu==null
          GroupRemoveUnit(tempg,tempu)
          DamageGroupDelayed(tempu,GetSkillEnemiesInRange(GetUnitX(Vu),GetUnitY(Vu),400.,tempu),0.75*GetHeroDMG(tempu),6,TYPE_DARK,0,"Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl","overhead",0.1)
        endloop
        DestroyGroup(tempg)
        RemoveSavedHandle(udg_h,tempi,311)
        tempg=null
      endif
      UnitRemoveBuff(Vu,'A0UW')
    endif
  endif
}

nothing DamageInteract10_f(integer mod) {
  real tempr
  unit tempu
  if mod>8 then//9-16
    if mod>12 then//13-16
   
    else//9-12
      if mod>10 then//11-12
        if mod==12 then//12
       
        elseif mod==11 then//11 адаптация-2
          if GetUnitAbilityLevel(Vtarget,'B02E')>0 then
            SaveReal(udg_h,Vtid,506,LoadReal(udg_h,Vtid,506)+Vdamage)
          endif
        endif
      else//9-10
        if mod==10 then//Elbowjoinpanic
          if GetUnitAbilityLevel(Vtarget,'A024')>0 and not DMperiodic and not DMaoe and not DMreflected then
            ElbowjointPanicP1(Vu,Vtarget)
          endif
        elseif mod==9 && not DMperiodic and not DMreflected then//Демонология П1
          if GetHeroSpellbookLevel(Vtarget,'A0RI')>=3 then 
            tempr=10.*GetHeroMasteryMultiplier(Vtarget)
            if DMaoe then
              tempr/=3.
            endif
            if GetRandomReal(0.,100.)<=tempr then
              if CompareTimeDiffAndChange(Vtarget,305,1.) then
                ExecuteFunc("SetNextHealUncontrollable")
                HealRemote(Vtarget,Vtarget,0.09*GetUnitState(Vtarget,UNIT_STATE_MAX_LIFE))
              endif
              if Vu!=null then
                UnitCharmUnitSimpleNormal(Vtarget,Vu,2.)
              endif
            endif
          endif
        endif
      endif
    endif
  elseif mod>4 then//5-8
    if mod>6 then//7-8
      if mod==8 && not DMperiodic and not DMreflected then
        if GetUnitAbilityLevel(Vtarget,'B010')>0 && CompareTimeDiffAndChange(Vtarget,315,1.25) then//17 уровень - всплеск крови
          tempu=SpawnAI('h02D',GetUnitX(Vtarget),GetUnitY(Vtarget),true)
          DestroyEffect(AddSpecialEffectTarget("anufisrpg\\effect\\LiveBlood2.mdl",tempu,"chest"))
          tempu=SpawnAI('h02D',GetUnitX(Vtarget),GetUnitY(Vtarget),true)
          DestroyEffect(AddSpecialEffectTarget("anufisrpg\\effect\\LiveBlood2.mdl",tempu,"chest"))
          tempu=null
        endif
      elseif mod==7 && not DMperiodic && not DMreflected then
        tempr=GetHeroIdHiddenBonus(Vtid,11) //11 скрытая характеристика
        if tempr>0. then
          if DMaoe then
            tempr/=3.
          endif
          SetUnitState(Vtarget,UNIT_STATE_MANA,GetUnitState(Vtarget,UNIT_STATE_MANA)+tempr)
        endif
        tempr=GetHeroHorrorPercent(Vtarget)
        if tempr>0. && Vu!=null then
          if DMaoe then
            tempr/=3.
          endif
          if GetRandomReal(0.,100.)<=tempr then
            UnitFearUnitNormal(Vtarget,Vu,1.,'A0TR','BHbd')
          endif
        endif
      endif
    else//5-6
      if mod==6 then//ледяной щит:наложение дебаффа
        if DMmelee && not DMperiodic && not DMreflected && GetUnitAbilityLevel(Vtarget,'BHtc')>0 && Vu!=null then
          UnitOkochenenieUnitNormal(Vtarget,Vu,3.)
        endif
      elseif mod==5 then//дебафф Сон снятие
        if GetUnitAbilityLevel(Vtarget,'Bdtl')>0 and not DMperiodic then
          UnitRemoveBuff(Vtarget,'A02U')
        endif
      endif
    endif
  elseif mod>2 then//3-4
    if mod==4 then//отдых(херовый)
      if GetUnitAbilityLevel(Vtarget,'Bmlc')>0 and not DMperiodic then
        UnitRemoveBuff(Vtarget,'A06O')
        UnitStunUnitNormal(Vtarget,Vtarget,3.,'A01C','B001')
      endif
    elseif mod==3 then//невидимость:снять
      if GetUnitAbilityLevel(Vtarget,'Bspl')>0 && not DMreflected then
        UnitRemoveBuff(Vtarget,'A0EU')
        UnitRemoveAbility(Vtarget,'Apiv')
      endif
    endif
  elseif mod==2 then//глушащий щит
    if GetUnitAbilityLevel(Vtarget,'BUdd')>0 && DMmelee && not DMaoe && Vu!=null && CompareAngles(AngleBetweenUnits(Vtarget,Vu),GetUnitFacing(Vtarget),90.) then
      UnitStunUnitNormal(Vtarget,Vu,1.,'A01C','B001')
    endif
  elseif mod==1 then//возвращение урона хозяину от призванного существа
    if GetUnitAbilityLevel(Vtarget,'A0PP')>0 then //возвращение урона хозяину от призванного существа
      tempr=LoadReal(udg_h,GetHandleId(Vtarget),115)
      if tempr>0. then
        tempu=GetOwner(Vtarget)
        if Vdamage<=GetWidgetLife(Vtarget) then
          tempr=tempr*Vdamage
        else
          tempr=tempr*GetWidgetLife(Vtarget)
        endif
        if tempr>0. then
          //SummonReflectDamage(tempu,r) пока что дропнутый функционал
        endif
        tempu=null
      endif
    endif
  endif
}

nothing DamageInteract11_f(integer mod) {
  if mod==2 then//талант:отрицание геноцида
    if Vdamage>GetWidgetLife(Vtarget) && GetUnitAbilityLevel(Vtarget,'Bssd')>0 then
      Vdamage=GetWidgetLife(Vtarget)-1.
    endif
  elseif mod==1 then//статы героев
    if GetRandomReal(0.,100.)<=GetHeroIdHiddenBonus(Vtid,40)*100. && CompareTimeDiff(Vtarget,136,10.) then
      CompareTimeDiffChange(Vtarget,136,10.)
      UnitAddBuff2(Vtarget,'A09F','BOww',2.)
      UnitAddDamageMod(Vtarget,4,4)
      Vdamage=0.
    endif
    if Vdamage>0.25*GetUnitState(Vtarget,UNIT_STATE_MAX_LIFE) then
      Vdamage=Vdamage*GetHeroIdHiddenBonus(Vtid,45)
    endif
    if Vdamage>GetWidgetLife(Vtarget) && GetRandomReal(0.,100.)<=100.*GetHeroIdHiddenBonus(Vtid,36) then //скрытый бонус 36
      Vdamage=0.
      FlyText(Vtarget,"Выживание",1)
    endif
  endif
}

nothing DamageInteract12_f(integer mod) {
  real tempr
  if mod==2 then
 
  elseif mod==1 then//талант Идиотическая удача(3 сущности)
    if GetRandomReal(0.,100.)<=10.*GetHeroIdTalentBonus1(Vuid,29) && LoadInteger(udg_h,Vuid,502)<10 then
      Talent29_Effect1(Vu,GetUnitX(Vtarget),GetUnitY(Vtarget))
    endif
  endif
}

nothing DamageInteract13_f(integer mod) {
  integer tempi
  group tempg
  unit tempu
  if mod==2 then//овечка(сборщик хлама)-смерть
    tempi=GetRandomInt(2,8)
    loop
      exitwhen tempi<=0
      tempi--
      CreateItem('I1HR',GetUnitX(Vtarget),GetUnitY(Vtarget))
    endloop
  elseif mod==1 then//талант:жертвы во благо и Отрицание геноцида
    if GetUnitAbilityLevel(Vtarget,'AIsr')>0 then
      tempi=1
    else
      tempi=2
    endif
    tempg=GetSkillAlliesInRange(GetUnitX(Vtarget),GetUnitY(Vtarget),1800.,Vtarget)
    GroupRemoveUnit(tempg,Vtarget)
    loop
      tempu=FirstOfGroup(tempg)
      exitwhen tempu==null
      GroupRemoveUnit(tempg,tempu)
      if GetUnitAbilityLevel(tempu,'AIsr')>0 then
        if GetHeroTalentLevel(tempu,8)>0 then
          if tempi==1 then
            UnitAddBuffSimple(tempu,'A0Y6','BNht',30.)
          else
            UnitAddBuffSimple(tempu,'A0Y5','BNrt',10.)
          endif
          UnitAddDamageMod(tempu,5,18)
        endif
        if tempi==1 && GetHeroTalentLevel(tempu,21)>0  && GetRandomReal(0.,100.)<=GetHeroIdTalentBonus2(GetHandleId(tempu),21) then
          UnitAddBuffSimple(tempu,'A0YL','Bssd',GetHeroIdTalentBonus1(GetHandleId(tempu),21))
          UnitAddDamageMod(tempu,11,2)
          DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\Resurrect\\ResurrectCaster.mdl",tempu,"origin"))
        endif
      endif
    endloop
    DestroyGroup(tempg)
    tempg=null
  endif
}

private nothing Init() {
  HH=InitHashtable()
  UnitTypeAddDamageMod('H0BJ',7,9)//RoolsRoom
  UnitTypeAddDamageMod('H0BJ',3,1)
  UnitTypeAddDamageMod('h08L',9,2)//энт
  UnitTypeAddDamageMod('h0DL',9,2)//тварь из теней
  UnitTypeAddDamageMod('H066',9,5)//dendy-кровотечение
  UnitTypeAddDamageMod('h0BG',9,8)//адская гончая(игроки)
  UnitTypeAddDamageMod('H0AC',10,10)//Elbowjointpanic
  UnitTypeAddDamageMod('h08I',5,2)//верный тигр
  UnitTypeAddDamageMod('h06N',5,5)//адский зверь
}

endlibrary

Code:
library DamageLib initializer Init uses Misc,DamageMods

integer DMtype=0
boolean DMcrit=false
//boolean DMnotscale=false //1
//boolean DMperiodic=false //2
//boolean DMreflected=false //3
//boolean DMautoattack=false //4
//boolean DMmelee=false //5
//boolean DMaoe=false //6
//boolean DMmobcast=false //7
//boolean DMprock=false //8 прок дамага

boolean array DM
boolean array DT

define DMnotscale=DM[1]
define DMperiodic=DM[2]
define DMreflected=DM[3]
define DMautoattack=DM[4]
define DMmelee=DM[5]
define DMaoe=DM[6]
define DMmobcast=DM[7]
define DMprock=DM[8]

boolean DTunknown=false //0
boolean DTphisic=false //1
boolean DTfire=false //2
boolean DTfrost=false //3
boolean DTnature=false //4
boolean DTarcane=false //5
boolean DTdark=false //6
boolean DTholy=false //7

real Vdamage=0.
real VdamageZero=0.
unit Vu=null
unit Vtarget=null
integer Vuud=0//user data хранит ссылку на юнита в UnitHandleSave
integer Vtud=0//user data хранит ссылку на юнита в UnitHandleSave
integer Vuid=0
integer Vtid=0
boolean Vu_char=false//наносящий дамаг - чарактер
boolean Vt_char=false//огребающий - чарактер
group Vgroup=null
unit Vu2=null
timer Vtimer=null
item Vitem=null

private real HealNerfing
public unit Hu
public real Ha

define DMG_NOTSCALE=1
define DMG_REFLECT=3
define DMG_MELEE=5
define DMG_MELEE_NOSCALE=15
define DMG_MELEE_AOE=56
define DMG_MOB_AOE=16
define DMG_AOE=6
define DMG_AOE_NOSCALE=16
define DMG_AOE_PERIODIC=26
define TYPE_PHISIC=1
define TYPE_FIRE=2
define TYPE_FROST=3
define TYPE_NATURE=4
define TYPE_ARCANE=5
define TYPE_DARK=6
define TYPE_HOLY=7

/*
связь идет:
хэндл юнита-этап взаимодействия*10000+0..9999

этапы взаимодействия:
1-увеличение/уменьшение на фиксированную величину(наносящий)
2-модификаторы уровня
3-увеличение/уменьшение на фиксированную величину(получающий)
4-иммунитет к урону(получающий)
5-процентное увеличение/уменьшение урона(наносящий)
6-процентное увеличение/уменьшение урона(получающий)
7-процентное отражение урона
8-щитование урона
9-постэффекты(наносящий)
10-постэффекты(получающий)
11-выживание
12-смертельный урон(наносящий)
13-смертельный урон(получающий)
*/

private boolean crit100=false
nothing Crit100() {
  crit100=true
}

nothing Damage_ClearVars() {
   //DMnotscale=false
   //DMperiodic=false
   //DMreflected=false
   //DMautoattack=false
   //DMmelee=false
   //DMaoe=false
   //DMmobcast=false
   //DMprock=false
   DM[1]=false
   DM[2]=false
   DM[3]=false
   DM[4]=false
   DM[5]=false
   DM[6]=false
   DM[7]=false
   DM[8]=false
   //
   DTunknown=false
   DTphisic=false
   DTfire=false
   DTfrost=false
   DTnature=false
   DTarcane=false
   DTdark=false
   DTholy=false
}

nothing DamageInteract1() {//1-увеличение/уменьшение на фиксированную величину(наносящий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount1[Vuud]//GetUnitDamageModCount(Vuid,1)
  if DMautoattack && GetUnitAbilityLevel(Vu,'Bam2')>0 then
    Vdamage=100.
  endif
  if udg_TestMode && DMautoattack && Vu_char then
    Vdamage=Vdamage+3000.
  endif
  loop
    exitwhen i>n
    DamageInteract1_f(GetUnitDamageMod(Vuid,1,i))
    i++
  endloop
}

/*nothing DamageInteract2() {//2-модификаторы уровня
  integer id1=GetPlayerId(GetOwningPlayer(Vu))
  integer id2=GetPlayerId(GetOwningPlayer(Vtarget))
  integer lvl1
  integer lvl2
  if id1<12 && id2>11 then//игрок по мобу
    lvl1=GetEffectiveLevel(Character[id1])
    lvl2=Level*5
    if lvl2>lvl1 then
      Vdamage=Vdamage/(1.+0.05*(lvl2-lvl1))
    endif
  elseif id1>11 && id2<12 then//моб по игроку
    lvl1=Level*5
    lvl2=GetEffectiveLevel(Character[id2])
    if lvl1>lvl2 then
      Vdamage=Vdamage*(1.+0.05*(lvl1-lvl2))
    endif
    if not DMnotscale then
      Vdamage=Vdamage*DamageFactor
    endif
  endif
}*/

nothing DamageInteract2() {//2-модификаторы уровня
    real temp
    if DMaoe and GetUnitAbilityLevel(Vtarget,'A0PP')>0 then//тотемы
      Vdamage=Vdamage*0.1
    endif
    if Vu==null then
      return
    endif
    if GetPlayerId(GetOwningPlayer(Vu))>11 then
      if not DMnotscale then
        Vdamage=Vdamage*udg_DamageFactor
      endif
      if GLO_RandomMode then
        Vdamage=Vdamage*RandomDamageBonus
      endif
    endif
    if GetPlayerId(GetOwningPlayer(Vtarget))>11 then
      if GetPlayerController(GetOwningPlayer(Vu))==MAP_CONTROL_USER and udg_Level>0 then
        temp=I2R((udg_Level-2)*5)-GetHeroIE(PlayerCharacter(GetOwningPlayer(Vu)))
        if temp>5. then
          temp=5.
        endif
        if temp>0. then
          Vdamage=Vdamage*(1.-0.05*temp)
        endif
      endif
    endif
    if udg_Level>0 then
      if GetPlayerId(GetOwningPlayer(Vtarget))<12 then
        temp=GetHeroIE(PlayerCharacter(GetOwningPlayer(Vtarget)))
        temp=((temp-1.)*0.03+1.)/((udg_Level-1.)*5.*0.03+1.)
        if temp>1. then
         Vdamage=Vdamage*temp
        endif
      elseif GetPlayerId(GetOwningPlayer(Vu))<12 then
        temp=GetHeroIE(PlayerCharacter(GetOwningPlayer(Vu)))
        temp=((temp-1.)*0.03+1)/((udg_Level-1)*5*0.03+1)
        if temp>1. then
          HealNerfing=HealNerfing*temp
          Vdamage=Vdamage/temp
        endif
      endif
    endif
}

nothing DamageInteract3() {//3-увеличение/уменьшение на фиксированную величину(получающий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount3[Vtud]//GetUnitDamageModCount(Vtid,3)
  if not DMreflected && not DMperiodic && Vt_char then
    if DMaoe then
      Vdamage=Vdamage-GetHeroHorrorDamageReduction(Vtarget)/3.
    else
      Vdamage=Vdamage-GetHeroHorrorDamageReduction(Vtarget)
    endif
    if Vdamage<0. then
      Vdamage=0.
    endif
  endif
  loop
    exitwhen i>n
    DamageInteract3_f(GetUnitDamageMod(Vtid,3,i))
    i++
  endloop
}

boolean Damage2_notkill=false

nothing DamageInteract4() {//4-иммунитет к урону(получающий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount4[Vtud]//GetUnitDamageModCount(Vtid,4)
  real tempr
  if Damage2_notkill then
    Damage2_notkill=false
    if Vdamage>GetUnitState(Vtarget,UNIT_STATE_LIFE) then
      Vdamage=GetUnitState(Vtarget,UNIT_STATE_LIFE)-1.5
    endif
  endif
  if IsUnitInvulnerable(Vtarget) then
    FlyText(Vtarget,"Неуязвимость",1)
    Vdamage=0.
    if GetUnitAbilityLevel(Vu,'AIsr')>0 then
      tempr=GetHeroIdTalentBonus1(Vuid,5)
      if tempr>0. then
        UnitAddBuffSimple(Vu,'A0Y2','B019',6.)
        UnitAddDamageMod(Vu,5,16)
      endif
    endif
  endif
  loop
    exitwhen i>n || Vdamage<=0.
    DamageInteract4_f(GetUnitDamageMod(Vtid,4,i))
    i++
  endloop
  if Vt_char then
    tempr=GetHeroIdTalentBonus1(Vtid,20)//заторможенная реакция
    if tempr>0. && GetRandomReal(0.,100.)<=tempr then
      TalentSlowpokeDotRemote(Vtarget,Vdamage,6.)
      Vdamage=0.
    endif
  endif
}

nothing DamageInteract5() {//5-процентное увеличение/уменьшение урона(наносящий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount5[Vuud]//GetUnitDamageModCount(Vuid,5)
  if GetUnitAbilityLevel(Vu,'Binf')>0 then //книга света: П1
    Vdamage=Vdamage*(1.+HolyPassive1_bonus)
  endif
  //
  loop
    exitwhen i>n
    DamageInteract5_f(GetUnitDamageMod(Vuid,5,i))
    i++
  endloop
}

nothing DamageInteract6() {//6-процентное увеличение/уменьшение урона(получающий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount6[Vtud]//GetUnitDamageModCount(Vtid,6)
  if Vt_char then
    if Vu==null then
      if not DMperiodic then
        Vdamage=Vdamage*(1.-GetHeroPeriodicDefence(Vtarget))
      endif
      Vdamage=Vdamage*GetHeroHiddenBonus(Vtarget,24) //24 скрытый бонус
    endif
    if IsBlock(Vu,Vtarget) then
      if GetUnitLifePercent(Vtarget)<=35. && GetRandomReal(0.,100.)<=50. then
        Vdamage=0.
      else
        Vdamage=Vdamage*0.5
      endif
    endif
    if not DMperiodic then
      Vdamage=Vdamage*(1.-GetHeroDefence(Vtarget))
    else
      Vdamage=Vdamage*(1.-GetHeroPeriodicDefence(Vtarget))
    endif
    if udg_time-LoadReal(udg_h,Vtid,50)<=GLO_AutoattackDefenceTime && GetHeroLevel(Vtarget)>=5 then
      Vdamage=Vdamage*0.7
    endif
  endif
  //
  loop
    exitwhen i>n
    DamageInteract6_f(GetUnitDamageMod(Vtid,6,i))
    i++
  endloop
}

nothing DamageInteract7() {//7-процентное отражение урона(получающий/наносящий)
  integer i=1
  integer n
  //if DMreflected then//пропускаем отраженный урон(чтоб не отражать обратно)
  //  return
  //endif
  n=UnitHandleSave_DamageModCount7[Vtud]//GetUnitDamageModCount(Vtid,7)
  loop
    exitwhen i>n || Vdamage<=0.
    DamageInteract7_f(GetUnitDamageMod(Vtid,7,i))
    i++
  endloop
  i=1
  n=UnitHandleSave_DamageModCount7[Vuud]//GetUnitDamageModCount(Vuid,7)
  loop
    exitwhen i>n || Vdamage<=0.
    DamageInteract7_f(GetUnitDamageMod(Vuid,7,i))
    i++
  endloop
}

nothing DamageInteract8() {//8-щитование урона(получающий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount8[Vtud]//GetUnitDamageModCount(Vtid,8)
  real tempr
  real tempr2
  loop
    exitwhen i>n
    DamageInteract8_f(GetUnitDamageMod(Vtid,8,i))
    i++
  endloop
  if Vt_char && GetUnitLifePercent(Vtarget)>=99.99 then
    tempr=GetHeroIdTalentBonus1(Vtid,18)*GetHeroDMG(Vtarget)
    if tempr>0. then
      tempr2=0.1*Vdamage
      Vdamage=Vdamage-tempr
      if Vdamage<tempr2 then
        Vdamage=tempr2
      endif
    endif
  endif
}

nothing DamageInteract9() {//9-постэффекты(наносящий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount9[Vuud]//GetUnitDamageModCount(Vuid,9)
  real tempr
  if Vu_char then
    tempr=GetHeroVampiric(Vu)
    tempr=tempr*(1.+(1.-GetUnitLifePercent(Vtarget)*0.01)*GetHeroLowHpVampiricPercent(Vu)*0.01)
    if GetUnitLifePercent(Vtarget)<=30. then
      tempr=tempr+GetHeroHiddenBonus(Vu,9) //9 скрытый бонус
    endif
    Ha=tempr*Vdamage*HealNerfing*GetHealingFromDamageCoefficient(Vu)
    if DMaoe then
      Ha=Ha/3.
    endif
    Hu=Vu
    if Ha>0. then
      ExecuteFunc("HeroVampiricHeal")
    endif
  endif
  loop
    exitwhen i>n
    DamageInteract9_f(GetUnitDamageMod(Vuid,9,i))
    i++
  endloop
}

nothing DamageInteract10() {//10-постэффекты(получающий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount10[Vtud]//GetUnitDamageModCount(Vtid,10)
  loop
    exitwhen i>n
    DamageInteract10_f(GetUnitDamageMod(Vtid,10,i))
    i++
  endloop
}

nothing DamageInteract11() {//11-выживание(получающий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount11[Vtud]//GetUnitDamageModCount(Vtid,11)
  loop
    exitwhen i>n || Vdamage<=0.
    DamageInteract11_f(GetUnitDamageMod(Vtid,11,i))
    i++
  endloop
}

nothing DamageInteract12() {//12-смертельный урон(наносящий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount12[Vuud]//GetUnitDamageModCount(Vuid,12)
  loop
    exitwhen i>n
    DamageInteract12_f(GetUnitDamageMod(Vuid,12,i))
    i++
  endloop
}

nothing DamageInteract13() {//13-смертельный урон(получающий)
  integer i=1
  integer n=UnitHandleSave_DamageModCount13[Vtud]//GetUnitDamageModCount(Vtid,13)
  loop
    exitwhen i>n
    DamageInteract13_f(GetUnitDamageMod(Vtid,13,i))
    i++
  endloop
}

private nothing BlockDamage_f() {
    timer t=GetExpiredTimer()
    integer id=GetHandleId(t)
    unit u=LoadUnitHandle(udg_h,id,1)
    real d=LoadReal(udg_h,id,2)
    SetWidgetLife(u,GetWidgetLife(u)+d)
    FlushChildHashtable(udg_h,id)
    DestroyTimer(t)
    t=null
    u=null
}

private nothing BlockDamage_f2() {
    timer t=GetExpiredTimer()
    integer id=GetHandleId(t)
    unit u=LoadUnitHandle(udg_h,id,1)
    UnitRemoveAbility(u,'Avul')
    SetUnitState(u,UNIT_STATE_LIFE,GetUnitState(u,UNIT_STATE_LIFE)-LoadReal(udg_h,id,2))
    FlushChildHashtable(udg_h,id)
    DestroyTimer(t)
    t=null
    u=null
}

public nothing BlockDamage(unit u,real amount,real dmg) {
    timer t
    integer id
    if dmg>GetUnitState(u,UNIT_STATE_LIFE) then
      t=CreateTimer()
      id=GetHandleId(t)
      SaveUnitHandle(udg_h,id,1,u)
      SaveReal(udg_h,id,2,dmg-amount)
      UnitAddAbility(u,'Avul')
      TimerStart(t,0.00,false,function BlockDamage_f2)
      t=null
    else
      if GetUnitState(u,UNIT_STATE_LIFE)+amount>GetUnitState(u,UNIT_STATE_MAX_LIFE) then
        t=CreateTimer()
        id=GetHandleId(t)
        SaveUnitHandle(udg_h,id,1,u)
        SaveReal(udg_h,id,2,amount)
        TimerStart(t,0.00,false,function BlockDamage_f)
        t=null
      else
        SetWidgetLife(u,GetWidgetLife(u)+amount)
      endif
    endif
}

real GetUnitCritChance(unit u) {
  real chance=0.
  if GetUnitAbilityLevel(u,'AIsr')>0 then
    chance=GetHeroBaseCritPercent(u)
  elseif GetUnitAbilityLevel(u,'A0GW')>0 then
    chance=15.
  elseif GetUnitAbilityLevel(u,'A0Y9')>0 then
    chance=30.
  endif
  return chance
}

boolean Damage_Crit(unit u,unit target) {
  real chance=GetUnitCritChance(u)
  timer t
  integer tarid
  if GetUnitAbilityLevel(u,'AIsr')>0 then
    if CompareAngleFromUnitToUnit(u,target,90.) then
      chance=chance+GetHeroHiddenBonus(u,5)
    endif
    if GetUnitLifePercent(target)>=80. then
      chance=chance+GetHeroIdTalentBonus1(GetHandleId(u),2)
    endif
    if GetUnitAbilityLevel(u,'A0Y1')>0 then//берсерк(талант)
      chance=chance+GetHeroIdTalentBonus1(GetHandleId(u),4)
    endif
    if GetUnitAbilityLevel(u,'B022')>0 then//точность(сектор приз)
      chance=chance+20.
    endif
  endif
  if crit100 then
    crit100=false
    return true
  endif
  if GetRandomReal(0.,100.)<=chance then
    return true
  endif
  return false
}

//

private boolean ReturnUnnerfedDamage=false
//

nothing SetReturnUnnerfedDamage() {
  ReturnUnnerfedDamage=true
}

real Dam##age(unit u,unit target,real damage,integer modif,integer typ) {
  integer q
  real temp
  if target==null then
    return 0.
  endif
  Damage_ClearVars()
  DMtype=typ
  DMcrit=Damage_Crit(u,target)
  Vu=u
  Vtarget=target
  Vuid=GetHandleId(u)
  Vtid=GetHandleId(target)
  Vuud=GetUnitUserData(u)
  Vtud=GetUnitUserData(target)
  Vu_char=IsUnitInGroup(u,udg_Characters)
  Vt_char=IsUnitInGroup(target,udg_Characters)
  VdamageZero=damage
  Vdamage=damage
  HealNerfing=1.
  loop
    exitwhen modif==0
    //q=
    //q=ost(modif,10)
    /*if q==1 then
      DMnotscale=true
    elseif q==2 then
      DMperiodic=true
    elseif q==3 then
      DMreflected=true
    elseif q==4 then
      DMautoattack=true
    elseif q==5 then
      DMmelee=true
    elseif q==6 then
      DMaoe=true
    elseif q==7 then
      DMmobcast=true
    elseif q==8 then
      DMprock=true
    endif*/
    DM[modif-(10*(modif/10))]=true
    modif=modif/10
  endloop
  if typ==0 then
    DTunknown=true
  elseif typ==1 then
    DTphisic=true
  elseif typ==2 then
    DTfire=true
  elseif typ==3 then
    DTfrost=true
  elseif typ==4 then
    DTnature=true
  elseif typ==5 then
    DTarcane=true
  elseif typ==6 then
    DTdark=true
  elseif typ==7 then
    DTholy=true
  endif
  //1-увеличение/уменьшение на фиксированную величину(наносящий)
  //ExecuteFunc("DamageInteract1")
  DamageInteract1()
  if DMcrit then
    Vdamage=Vdamage*2.
  endif
  //2-модификаторы уровня
  //ExecuteFunc("DamageInteract2")
  DamageInteract2()
  //3-увеличение/уменьшение на фиксированную величину(получающий)
  //ExecuteFunc("DamageInteract3")
  DamageInteract3()
  //4-иммунитет к урону(получающий)
  //ExecuteFunc("DamageInteract4")
  DamageInteract4()
  //5-процентное увеличение/уменьшение урона(наносящий)
  //ExecuteFunc("DamageInteract5")
  DamageInteract5()
  //6-процентное увеличение/уменьшение урона(получающий)
  //ExecuteFunc("DamageInteract6")
  DamageInteract6()
  //7-отражение урона(получающий/наносящий)
  //ExecuteFunc("DamageInteract7")
  if not DMreflected then//пропускаем отраженный урон(чтоб не отражать обратно)
    DamageInteract7()
  endif
  //8-щитование урона(получающий)
  if Vdamage>0. then
    //ExecuteFunc("DamageInteract8")
    DamageInteract8()
  endif
  //9-постэффекты(наносящий)
  //ExecuteFunc("DamageInteract9")
  DamageInteract9()
  //10-постэффекты(получающий)
  //ExecuteFunc("DamageInteract10")
  DamageInteract10()
  //11-выживание
  //ExecuteFunc("DamageInteract11")
  DamageInteract11()
  //вывод информации в таблицу/экран
  SaveReal(udg_h,Vuid,10,udg_time)
  //12-смертельный урон(наносящий)
  //13-смертельный урон(получающий)
  if Vdamage>GetWidgetLife(target) then
    DamageInteract12()
    DamageInteract13()
  endif
  if DMcrit then
    FlyText2(Vu,Vtarget,I2S(R2I(Vdamage)),3)
  else
    FlyText2(u,target,I2S(R2I(Vdamage)),2)
  endif
  if Vt_char {
    if not DMperiodic && Vdamage>0. then
      SaveReal(udg_h,Vtid,321,udg_time)
    endif
    if udg_Level>0 && Vdamage>GetWidgetLife(target) && not udg_PlayersCanDie && PlayerTakeLife(GetOwningPlayer(target)) then
      Vdamage=0.
      SetUnitState(target,UNIT_STATE_LIFE,GetUnitState(target,UNIT_STATE_MAX_LIFE))
      UnitAddBuff2(target,'A09F','BOww',2.)
      UnitAddDamageMod(target,4,4)
    endif
    q=GetPlayerId(GetOwningPlayer(target))+1
    udg_QDamaged[q]=udg_QDamaged[q]+Vdamage
  }
  if DMautoattack && not DMaoe then
    temp=Vdamage-damage
    if temp>0 then
      SetWidgetLife(target,GetWidgetLife(target)-temp)
    else
      if GetWidgetLife(target)>Vdamage then
        BlockDamage(target,-temp,damage)
        IssueTargetOrder(u,"attack",target)
      endif
    endif
  else
    SetWidgetLife(target,GetWidgetLife(target)-Vdamage)
  endif
  if Vu!=null && GetPlayerId(GetOwningPlayer(Vu))<12 {
      SaveReal(udg_h,Vtid,140,LoadReal(udg_h,Vtid,140)+Vdamage/GetUnitState(target,UNIT_STATE_MAX_LIFE))
      q=GetPlayerId(GetOwningPlayer(Vu))+1
      if Vdamage>GetWidgetLife(target) then
        udg_QDamage[q]=udg_QDamage[q]+GetWidgetLife(target)
      else
        udg_QDamage[q]=udg_QDamage[q]+Vdamage
      endif
      if udg_BossFight then
        if Vdamage>GetWidgetLife(target) then
          udg_QDamageBoss[q]=udg_QDamageBoss[q]+GetWidgetLife(target)
        else
          udg_QDamageBoss[q]=udg_QDamageBoss[q]+Vdamage
        endif
      endif
  }
  if ReturnUnnerfedDamage then
    ReturnUnnerfedDamage=false
    return Vdamage*HealNerfing
  endif
  return Vdamage
}

define Damage(u,target,damage,modif) = Dam##age(u,target,damage,modif,0)
define Damage(u,target,damage,modif,typ) = Dam##age(u,target,damage,modif,typ)

real Dam##age2(unit target,real damage,integer modif,integer typ) {
    return Damage(null,target,damage,modif,typ)
}

define Damage2(target,damage) = Dam##age2(target,damage,0,0)
define Damage2(target,damage,modif,typ) = Dam##age2(target,damage,modif,typ)

nothing DamageLevel(unit target,real dmg,integer modif,integer typ) {
  if udg_Level>0 && IsUnitInForce(target,udg_Players) then
    real temp=GetHeroIE(PlayerCharacter(GetOwningPlayer(target)))
    temp=((temp-1.)*0.03+1.)/((udg_Level-1.)*5.*0.03+1.)
    if temp>1. then
       dmg=dmg*temp
    endif
    if GLO_RandomMode then
      dmg=dmg*RandomDamageBonus
    endif
  endif
  Damage2(target,dmg,modif,typ)
}

nothing DamageDelayed_f() {
    timer t=GetExpiredTimer()
    integer tid=GetHandleId(t)
    unit target=LoadUnitHandle(udg_h,tid,2)
    if GetWidgetLife(target)>0. then
      Damage(LoadUnitHandle(udg_h,tid,1),target,LoadReal(udg_h,tid,3),LoadInteger(udg_h,tid,4),LoadInteger(udg_h,tid,5))
    endif
    FlushChildHashtable(udg_h,tid)
    DestroyTimer(t)
    t=null
    target=null
}

nothing DamageCall() {
    Damage(Remote_u,Remote_target,Remote_damage,Remote_modif,Remote_typ)
}

boolean DamageM##elee(unit u,unit target,real dmg,integer modif,integer typ) {
  if CheckAccuracy(u,target) then
    Damage(u,target,dmg,modif,typ)
    return true
  endif
  return false
}

nothing DamageMeleeCall() {
  DamageMelee(Remote_u,Remote_target,Remote_damage,Remote_modif,Remote_typ)
}

boolean DamageS##pell(unit u,unit target,real dmg,integer modif,integer typ) {
  if not IsEvade(u,target) then
    Damage(u,target,dmg,modif,typ)
    return true
  endif
  return false
}

define DamageSpell(u,target,dmg,modif) = DamageS##pell(u,target,dmg,modif,0)
define DamageSpell(u,target,dmg,modif,typ) = DamageS##pell(u,target,dmg,modif,typ)

define DamageMelee(u,target,dmg,modif) = DamageM##elee(u,target,dmg,modif,0)
define DamageMelee(u,target,dmg,modif,typ) = DamageM##elee(u,target,dmg,modif,typ)

nothing DamageSpellCall() {
  DamageSpell(Remote_u,Remote_target,Remote_damage,Remote_modif,Remote_typ)
}

nothing DamageDelayed(unit u,unit target,real damage,integer modif,integer typ,real time) {
    timer t=CreateTimer()
    integer tid=GetHandleId(t)
    SaveUnitHandle(udg_h,tid,1,u)
    SaveUnitHandle(udg_h,tid,2,target)
    SaveReal(udg_h,tid,3,damage)
    SaveInteger(udg_h,tid,4,modif)
    SaveInteger(udg_h,tid,5,typ)
    TimerStart(t,time,false,function DamageDelayed_f)
    t=null
}

nothing DamageDelayedCall() {
    DamageDelayed(Remote_u,Remote_target,Remote_damage,Remote_modif,Remote_typ,Remote_time)
}

nothing DamageGroupDelayed_r() {
    timer t=GetExpiredTimer()
    integer tid=GetHandleId(t)
    unit u=LoadUnitHandle(udg_h,tid,1)
    group g=LoadGroupHandle(udg_h,tid,2)
    real damage=LoadReal(udg_h,tid,3)
    integer modif=LoadInteger(udg_h,tid,4)
    integer typ=LoadInteger(udg_h,tid,5)
    integer dodgetype=LoadInteger(udg_h,tid,6)
    string eff=LoadStr(udg_h,tid,7)
    string attach=LoadStr(udg_h,tid,8)
    unit u2
    loop
      u2=FirstOfGroup(g)
      exitwhen u2==null
      GroupRemoveUnit(g,u2)
      if eff!=null then
        if attach==null then
          DestroyEffect(AddSpecialEffect(eff,GetUnitX(u2),GetUnitY(u2)))
        else
          DestroyEffect(AddSpecialEffectTarget(eff,u2,attach))
        endif
      endif
      if IsEvadeType(u,u2,dodgetype) then
        Damage(u,u2,damage,modif,typ)
      endif
    endloop
    DestroyGroup(g)
    FlushChildHashtable(udg_h,tid)
    DestroyTimer(t)
    t=null
    u=null
    g=null
}

private nothing Init() {

}

endlibrary
 
Level 7
Joined
Oct 19, 2015
Messages
286
I've got strange idea of doing ExecuteFunc() or TriggerExecute() and put in these functions/triggers seperate things, so my Damage() won't have to do tons of "if" checks, but I think that it will be less effective.
That's not strange, it is the only sane way to do this. It is also likely the most efficient, depending on how many different effects there are to check for and how many of these effects the average unit has attached.

Basically, each unit would have a linked list of functions/triggers attached to it that would be run whenever the unit got damaged. You would update this list as buffs/abilities got applied to or removed from the unit. Most units would likely have nothing attached, so the system would be very efficient on those units - a single check to find out the units function list is empty, zero trigger executions.
 
Status
Not open for further replies.
Top