Добавлен , опубликован
Здесь лягут все системы, которые есть в каждой моей карте, благо они весьма хороши.

один спойлер - одна библиотека, первый спойлер это дефайны. Библиотеки довольно-таки универсальны, поэтому имеют неиспользуемые функции.
Defines
define
{
    lib         =   library
    init        =   initializer
    void        =   nothing
    bool        =   boolean
    int         =   integer
    exit        =   exitwhen
    stop        =   exitwhen true
    break       =   return
    GetHp(u)    =   GetWidgetLife(u, UNIT_STATE_LIFE)
    GetMp(u)    =   GetUnitState (u, UNIT_STATE_MANA)
    IfDead(u)   =   GetWidgetLife(u, UNIT_STATE_LIFE) <= .405
    sqrt(a)     =   SquareRoot(a)
}


bool        Spellcast   = false             //Становится true во время нанесения урона способностью.
boolexpr    VoidExpr    = Condition(null)   //Пустое условие, во избежание утечек условий.
Math
Всякие математические функции.
lib Match
{
    real rabs(real a)       //модуль действ. числа
    {
        if(a<0)
        {
            return -a
        }
        return a
    }

    int iabs(int  a)        //модуль целого числа
    {
        if(a<0)
        {
            return -a
        }
        return a
    }

    int integral(real a)    //математическое округление
    {
        if(a>=0)
        {
            return(R2I(a+.5))
        }
        if(a <0)
        {
            return(R2I(a-.5))
        }
        return R2I(a)
    }

    real rzeroing(real a)   //сведение действ. числа к нулю, если оно меньше 0
    {
        if(a<0)
        {
            return 0
        }
        return a
    }

    int izeroing(int a)     //сведение целого числа к нулю, если оно меньше 0
    {
        if(a<0)
        {
            return 0
        }
        return a
    }
    
    int iborder(int a, int val, int b)      //ограничение числа с двух сторон
    {
        if(val<a)
        {
            return a
        }
        if(val>b)
        {
            return b
        }
        return val
    }
}
ArmorDB
База данных по физической защите юнитов.
Броня юнита узнаётся через функцию
real GetUnitArmor(unit u)
lib ArmorDB init Init uses Match
{
    private int array UnitID
    private real array UnitAM
    private int MaxUID = 0
    private int array ItemID
    private real array ItemAM
    private int MaxIID = 0
    private int array AbilID
    private real array AbilAM[1000][4]
    private int MaxAID = 0
    private constant real ArmorPerAgility = 0.3     //from constants
    private constant real ArmorPenAgility = -2.0    //from constants
    
    define private AddUnitDB(a,b)={UnitID[MaxUID]=a;UnitAM[MaxUID]=b;MaxUID++}
    define private AddItemDB(a,b)={ItemID[MaxIID]=a;ItemAM[MaxIID]=b;MaxIID++}
    define private AddAbilDB(a,b,c,d,e)={AbilID[MaxAID]=a;AbilAM[MaxAID][1]=b;AbilAM[MaxAID][2]=c;AbilAM[MaxAID][3]=d;AbilAM[MaxAID][4]=e;MaxAID++}
    define private AddAbilDB(a,b,c,d)={AbilID[MaxAID]=a;AbilAM[MaxAID][1]=b;AbilAM[MaxAID][2]=c;AbilAM[MaxAID][3]=d;AbilAM[MaxAID][4]=0;MaxAID++}
    define private AddAbilDB(a,b,c)={AbilID[MaxAID]=a;AbilAM[MaxAID][1]=b;AbilAM[MaxAID][2]=c;AbilAM[MaxAID][3]=0;AbilAM[MaxAID][4]=0;MaxAID++}
    define private AddAbilDB(a,b)={AbilID[MaxAID]=a;AbilAM[MaxAID][1]=b;AbilAM[MaxAID][2]=0;AbilAM[MaxAID][3]=0;AbilAM[MaxAID][4]=0;MaxAID++}
    
    //HERE EVERY ITEM, WHICH HAVE ARMOR
    //AND EVERY UNIT
    //AND EVERY ABILITY WITH ARMOR
    private void BaseSet()
    {
        AddUnitDB('zero',0) //id = 0
        AddItemDB('zero',0) //id = 0
        AddAbilDB('zero',0,0,0,0) //id = 0
        
        //units         for heroes it is armor which set in object editor
        AddUnitDB('Hpal',2)
        AddUnitDB('Hmkg',1)
        
        AddUnitDB('hfoo',2)
        
        //items
        AddItemDB('rde1',2)
        AddItemDB('rde2',3)
        AddItemDB('rde3',4)
    
        //abilities
        AddAbilDB('AHad',1.5,3.0,4.5)
    }

    private int GetIID(int RCode)
    {
        int i = 0
        loop
        {
            if(ItemID[i]==RCode)
            {
                return i
            }
            exit i==MaxIID
            i++
        }
        return 0
    }

    private int GetAID(int RCode)
    {
        int i = 0
        loop
        {
            if(AbilID[i]==RCode)
            {
                return i
            }
            exit i==MaxAID
            i++
        }
        return 0
    }

    private int GetUID(int RCode)
    {
        int i = 0
        loop
        {
            if(UnitID[i]==RCode)
            {
                return i
            }
            exit i==MaxUID
            i++
        }
        return 0
    }

    private real GetUnitArmorEx(unit u)
    {
        return UnitAM[GetUID(GetUnitTypeId(u))]
    }

    private real GetItemArmorEx(item u)
    {
        return ItemAM[GetIID(GetItemTypeId(u))]
    }

    private real GetUnitArmorByAbils(unit u)
    {
        int i = 1
        real s = 0
        loop
        {
            if(GetUnitAbilityLevel(u, AbilID[i])>0)
            {
                s = s + AbilAM[i][GetUnitAbilityLevel(u, AbilID[i])]
            }
            exit i==MaxAID
            i++
        }
        return s
    }

    real GetUnitArmor(unit u)
    {
        real am = 0
        int i = 0
        real byabil = GetUnitArmorByAbils(u)
        if(IsHeroUnitId(GetUnitTypeId(u)))
        {
            loop
            {
                if(UnitItemInSlot(u,i)!=null)
                {
                    am = am + GetItemArmorEx(UnitItemInSlot(u,i))
                }
                exit i == 6
                i++
            }
            return integral(GetUnitArmorEx(u) + ArmorPenAgility + GetHeroAgi(u,false)*ArmorPerAgility) + am + (GetHeroAgi(u,true)-GetHeroAgi(u,false))*ArmorPerAgility + byabil
        }
        return GetUnitArmorEx(u) + byabil
    }
    
    private void Init()
    {
        BaseSet()
    }
}
MresDB
База данных по магической защите войск. В силу того, что я использую полностью кастомный урон заклинаниями, совершенно не зависит от "родного" магического сопротивления.
Сопротивление юнита узнаётся через функцию
real GetUnitMres(unit u)
Используется через стандартную формулу понижения урона от защиты юнита.
lib MresDB init Init uses Match
{
    private int array UnitID
    private real array UnitMR
    private int MaxUID = 0
    private int array ItemID
    private real array ItemMR
    private int MaxIID = 0
    private int array AbilID
    private real array AbilMR[1000][4]
    private int MaxAID = 0
    private constant real MresPerInt = 0.8
    private constant real MresPenInt = -5.0
    
    define private AddUnitDB3(a,b)={UnitID[MaxUID]=a;UnitMR[MaxUID]=b;MaxUID++}
    define private AddItemDB3(a,b)={ItemID[MaxIID]=a;ItemMR[MaxIID]=b;MaxIID++}
    define private AddAbilDB3(a,b,c,d,e)={AbilID[MaxAID]=a;AbilMR[MaxAID][1]=b;AbilMR[MaxAID][2]=c;AbilMR[MaxAID][3]=d;AbilMR[MaxAID][4]=e;MaxAID++}
    define private AddAbilDB3(a,b,c,d)={AbilID[MaxAID]=a;AbilMR[MaxAID][1]=b;AbilMR[MaxAID][2]=c;AbilMR[MaxAID][3]=d;AbilMR[MaxAID][4]=0;MaxAID++}
    define private AddAbilDB3(a,b,c)={AbilID[MaxAID]=a;AbilMR[MaxAID][1]=b;AbilMR[MaxAID][2]=c;AbilMR[MaxAID][3]=0;AbilMR[MaxAID][4]=0;MaxAID++}
    define private AddAbilDB3(a,b)={AbilID[MaxAID]=a;AbilMR[MaxAID][1]=b;AbilMR[MaxAID][2]=0;AbilMR[MaxAID][3]=0;AbilMR[MaxAID][4]=0;MaxAID++}

    //HERE EVERY ITEM, WHICH HAVE MRESIST
    //AND EVERY UNIT
    //AND EVERY ABILITY WITH MRESIST
    private void BaseSet()
    {
        AddUnitDB3('zero',0) //id = 0
        AddItemDB3('zero',0) //id = 0
        AddAbilDB3('zero',0,0,0,0) //id = 0
        
        //units
        AddUnitDB3('Hpal',5)
        AddUnitDB3('Hmkg',1)
        
        //items
        AddItemDB3('rde1',15)
        AddItemDB3('rde2',15)
        AddItemDB3('rde3',15)
    
        //abilities
        AddAbilDB3('AHad',3,6,9)
    }

    private int GetIID(int RCode)
    {
        int i = 0
        loop
        {
            if(ItemID[i]==RCode)
            {
                return i
            }
            exit i==MaxIID
            i++
        }
        return 0
    }

    private int GetAID(int RCode)
    {
        int i = 0
        loop
        {
            if(AbilID[i]==RCode)
            {
                return i
            }
            exit i==MaxAID
            i++
        }
        return 0
    }

    private int GetUID(int RCode)
    {
        int i = 0
        loop
        {
            if(UnitID[i]==RCode)
            {
                return i
            }
            exit i==MaxUID
            i++
        }
        return 0
    }

    private real GetUnitMresEx(unit u)
    {
        return UnitMR[GetUID(GetUnitTypeId(u))]
    }

    private real GetItemMresEx(item u)
    {
        return ItemMR[GetIID(GetItemTypeId(u))]
    }

    private real GetUnitMresByAbils(unit u)
    {
        int i = 1
        real s = 0
        loop
        {
            if(GetUnitAbilityLevel(u, AbilID[i])>0)
            {
                s = s + AbilMR[i][GetUnitAbilityLevel(u, AbilID[i])]
            }
            exit i==MaxAID
            i++
        }
        return s
    }

    real GetUnitMres(unit u)
    {
        real am = 0
        int i = 0
        real byabil = GetUnitMresByAbils(u)
        if(IsHeroUnitId(GetUnitTypeId(u)))
        {
            loop
            {
                if(UnitItemInSlot(u,i)!=null)
                {
                    am = am + GetItemMresEx(UnitItemInSlot(u,i))
                }
                exit i == 6
                i++
            }
            return integral(GetUnitMresEx(u) + MresPenInt + GetHeroInt(u,false)*MresPerInt) + am + (GetHeroInt(u,true)-GetHeroInt(u,false))*MresPerInt + byabil
        }
        return GetUnitMresEx(u) + byabil
    }
    
    private void Init()
    {
        BaseSet()
    }
}
DealDamage
Наносит урон посредством функции
void DealDmg(unit Caster, unit Target, bool MDmg, real Dmg)
Учитывает защиту/сопротивление магии цели, вампиризм от предметов (как физический, так и магический).
В силу того, что у меня способности могут наносить физический урон, эта функция используется только при уроне способностями, что позволяет определить, с руки урон, или от заклинания.
lib DealDamage init Init uses ArmorDB, MresDB
{
    //for magic spells
    private int array MageVamp      //база итемов
    private int array MageVampN     //база вампиризма по итемам
    private int       MageVampNr = 0//количество различных итемов в базе
    //for physical spells
    private int array PhysVamp
    private int array PhysVampN
    private int       PhysVampNr = 0
    
    define private AddPVamp(a,b)={PhysVamp[PhysVampNr]=a;PhysVampN[PhysVampNr]=b;PhysVampNr++}
    define private AddMVamp(a,b)={MageVamp[MageVampNr]=a;MageVampN[MageVampNr]=b;MageVampNr++}
    
    private void ItemsSet()
    {
        AddMVamp('none',15)
        AddMVamp('none',25)
    
        AddPVamp('none',15)
        AddPVamp('none',10)
    }
    
    private real GetVamp(unit Caster, bool MDmg)
    {
        int i=0,j=0,ID
        real k = 0
        if MDmg
        {
            loop
            {
                ID = GetItemTypeId(UnitItemInSlot(Caster,i))
                loop
                {
                    if(ID == MageVamp[j])
                    {
                        k = k + MageVampN[j]
                    }
                    j++
                    exit j == MageVampNr
                }
                j = 0
                i++
                exit i == 6
            }
        }
        else
        {
            loop
            {
                ID = GetItemTypeId(UnitItemInSlot(Caster,i))
                loop
                {
                    if(ID == PhysVamp[j])
                    {
                        k = k + PhysVampN[j]
                    }
                    j++
                    exit j == PhysVampNr
                }
                j = 0
                i++
                exit i == 6
            }
        }
        return k/100
    }

    define DealMagicDamage(a,b,c) = DealDmg(a,b,true,c)
    define DealPhysicDamage(a,b,c) = DealDmg(a,b,false,c)

    void DealDmg(unit Caster, unit Target, bool MDmg, real Dmg)
    {
        real PMultipler = 1-(0.06*GetUnitArmor(Target)/(1+(0.06*GetUnitArmor(Target))))
        real MMultipler = 1-(0.06*GetUnitMres(Target)/(1+(0.06*GetUnitMres(Target))))
        Spellcast = true
        if(!MDmg)
        {
            UnitDamageTarget(Caster,Target,PMultipler*Dmg,true,true,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
            SetUnitState(Caster,UNIT_STATE_LIFE,GetUnitState(Caster,UNIT_STATE_LIFE)+GetVamp(Caster,false)*PMultipler*Dmg)
        }
        else
        {
            UnitDamageTarget(Caster,Target,MMultipler*Dmg,true,true,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
            SetUnitState(Caster,UNIT_STATE_LIFE,GetUnitState(Caster,UNIT_STATE_LIFE)+GetVamp(Caster, true)*MMultipler*Dmg)
        }
        Spellcast = false
    }

    private void Init()
    {
        ItemsSet()
    }
}

В добавок ко всему, я вброшу системку, позволяющую узнать точный физический урон каждого юнита.
MainStatDB
База по основным характеристикам героев.
Узнать основную характеристику можно через функцию
int GetHeroMainStat(unit u)
здесь 1 = agil, 2 = str, 3 = int.
lib MainStatDB init Init 
{
    private int array HeroID
    private int array StatID    //1 = agil, 2 = str, 3 = int
    private int StatIDMax =0
    
    define private AddStatRow(a,b)={HeroID[StatIDMax]=a;StatID[StatIDMax]=b;StatIDMax++}
    
    private void SetDB()
    {
        AddStatRow('Hpal',2)
    }

    int GetHeroMainStat(unit h)
    {
        int i = 0
        loop
        {
            if(HeroID[i]==GetUnitTypeId(h))
            {
                return StatID[i]
            }
            exit i == StatIDMax
            i++
        }
        return 0
    }

    private void Init()
    {
        SetDB()
    }
}
DamageDB
База данных по урону, учитывает все модификаторы, внесённые в неё.
Урон узнаётся через функцию
real GetUnitDamage(unit u)
У юнитов с некоторым разбросом урона выводится среднее значение.
lib DamageDB init Init uses MainStatDB, Match
{
    private int array UnitID
    private real array UnitDM
    private int MaxUID = 0
    private int array ItemID
    private real array ItemDM
    private int MaxIID = 0
    private int array AbilID
    private real array AbilDM[1000][4]
    private int MaxAID = 0
    private constant real DamagePerPoint = 1  //for main state

    define private AddUnitDB2(a,b)={UnitID[MaxUID]=a;UnitDM[MaxUID]=b;MaxUID++}
    define private AddItemDB2(a,b)={ItemID[MaxIID]=a;ItemDM[MaxIID]=b;MaxIID++}
    define private AddAbilDB2(a,b,c,d,e)={AbilID[MaxAID]=a;AbilDM[MaxAID][1]=b;AbilDM[MaxAID][2]=c;AbilDM[MaxAID][3]=d;AbilDM[MaxAID][4]=e;MaxAID++}
    define private AddAbilDB2(a,b,c,d)={AbilID[MaxAID]=a;AbilDM[MaxAID][1]=b;AbilDM[MaxAID][2]=c;AbilDM[MaxAID][3]=d;AbilDM[MaxAID][4]=0;MaxAID++}
    define private AddAbilDB2(a,b,c)={AbilID[MaxAID]=a;AbilDM[MaxAID][1]=b;AbilDM[MaxAID][2]=c;AbilDM[MaxAID][3]=0;AbilDM[MaxAID][4]=0;MaxAID++}
    define private AddAbilDB2(a,b)={AbilID[MaxAID]=a;AbilDM[MaxAID][1]=b;AbilDM[MaxAID][2]=0;AbilDM[MaxAID][3]=0;AbilDM[MaxAID][4]=0;MaxAID++}
    
    private void BaseSet()
    {
        AddUnitDB2('zero',0) //id = 0
        AddItemDB2('zero',0) //id = 0
        AddAbilDB2('zero',0,0,0,0) //id = 0
        
        AddUnitDB2('Hpal',1)
    }

    private int GetIID(int RCode)
    {
        int i = 0
        loop
        {
            if(ItemID[i]==RCode)
            {
                return i
            }
            exit i==MaxIID
            i++
        }
        return 0
    }

    private int GetAID(int RCode)
    {
        int i = 0
        loop
        {
            if(AbilID[i]==RCode)
            {
                return i
            }
            exit i==MaxAID
            i++
        }
        return 0
    }

    private int GetUID(int RCode)
    {
        int i = 0
        loop
        {
            if(UnitID[i]==RCode)
            {
                return i
            }
            exit i==MaxUID
            i++
        }
        return 0
    }

    private real GetUnitDamageEx(unit u)
    {
        return UnitDM[GetUID(GetUnitTypeId(u))]
    }

    private real GetItemDamageEx(item u)
    {
        return ItemDM[GetIID(GetItemTypeId(u))]
    }

    private real GetUnitDamageByAbils(unit u)
    {
        int i = 1
        real s = 0
        loop
        {
            if(GetUnitAbilityLevel(u, AbilID[i])>0)
            {
                s = s + AbilDM[i][GetUnitAbilityLevel(u, AbilID[i])]
            }
            exit i==MaxAID
            i++
        }
        return s
    }


        real GetUnitDamage(unit u)
    {
        real dm = 0
        int i = 0
        real byabil = GetUnitDamageByAbils(u)
        if(IsHeroUnitId(GetUnitTypeId(u)))
        {
            loop
            {
                if(UnitItemInSlot(u,i)!=null)
                {
                    dm = dm + GetItemDamageEx(UnitItemInSlot(u,i))
                }
                exit i == 6
                i++
            }
            if(GetHeroMainStat(u) == 1)
            {
                return dm + GetUnitDamageEx(u) + GetHeroAgi(u, true)*DamagePerPoint
            }
            elseif(GetHeroMainStat(u) == 2)
            {
                return dm + GetUnitDamageEx(u) + GetHeroStr(u, true)*DamagePerPoint
            }
            elseif(GetHeroMainStat(u) == 3)
            {
                return dm + GetUnitDamageEx(u) + GetHeroInt(u, true)*DamagePerPoint
            }
        }
        return GetUnitDamageEx(u) + byabil
    }


    private void Init()
    {
       BaseSet()
    }
}

Ну и на закуску системка, определяющая факт нанесения урона.
UnitDamaged
Регистирует факт получения урона юнитом.
Инициализируется функцией
void AnyUnitDamagedEvent(trigger trg)
library UnitDamaged initializer InitRect
{
    private region      Region
    private group       Group
    private int         TrigsNum = 0
    private trigger     array Trigger
    private boolexpr    Cond

    private void Adder()
    {
        int i = 0
        loop
        {
            TriggerRegisterUnitEvent(Trigger[i],GetEnteringUnit(),EVENT_UNIT_DAMAGED)
            exitwhen i==TrigsNum
            i++
        }
        GroupAddUnit(Group,GetEnteringUnit())
    }

    private void Registrator()
    {
        TriggerRegisterUnitEvent(Trigger[TrigsNum],GetEnumUnit(),EVENT_UNIT_DAMAGED)
    }

    void AnyUnitDamagedEvent(trigger trg)
    {
        Trigger[TrigsNum]=trg
        TriggerAddCondition(Trigger[TrigsNum],Cond)
        ForGroup(Group,function Registrator)
        TrigsNum++
    }

    private bool IsntZero()
    {
        return GetEventDamage() > 0
    }

    private void InitRect()
    {
        trigger trg = CreateTrigger()
        Cond = Condition(function IsntZero)
        Group = CreateGroup()
        Region = CreateRegion()
        GroupEnumUnitsInRect(Group,bj_mapInitialPlayableArea,null)
        RegionAddRect(Region, bj_mapInitialPlayableArea)
        TriggerRegisterEnterRegion(trg,Region,null)
        TriggerAddAction(trg,function Adder)
    }
}
`
ОЖИДАНИЕ РЕКЛАМЫ...