Добавлен MpW,
опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
Lua
Тип:
Наработка
Версия Warcraft:
1.32
Решил доработать существующий BonusMod на Lua ссылка
Автор недоработал до конца, поэтому что-то не работает неправильно или совсем не работает. Пример, функция UnitGetBonus работала неправильно. Где-то в условиях неправильно работает итд.
Автор недоработал до конца, поэтому что-то не работает неправильно или совсем не работает. Пример, функция UnitGetBonus работала неправильно. Где-то в условиях неправильно работает итд.
Улучшения:
- Увеличено размер с 4096 до 131072. Можно изменять бонусы +- 131072 Абилки скопированы из Jass Custom Stat System v1.5g (CCS), который является абсолютной копией.
- добавлен параметр скорости атаки. Эта модификация атаки и раньше существовала в других системах, но теперь можно вычислить и базовую скорость атаки. Путем метода расчета можно подсчитать текущую AS. ссылка Очень важный параметр близзард забыли добавить. Хорошо, что есть attack cooldawn
- юнит умирал от отрицательного параметра силы/запаса хп. Исправлен баг.
- добавлена возможность изменять базовые характеристики. В рефордже открыты некоторые нативки по чтению / изменению характеристик базовых юнита. Однако, работают они не так как хотелось бы. Обычно суммарное значение какого-то параметра может быть из несколько составляющих: базовый (стартовый в ро), бонус (от предметов и абилок), и значения от атрмбутов героя (базовые/бонусные). А нативки у каждого параметра работают по-разному: пример функция armor изменяет общий, у атаки в расчете исключен бонус от предметов.
Типы праметров (модификаторов):
- 1 Сила
- 2 Ловкость
- 3 Интеллект
- 4 Урон
- 5 Броня
- 6 Регенерация здоровья
- 7 Регенерация маны
- 8 Модификатор видимости
- 9 скорость атаки
- 10 макс запас здоровья
- 11 макс запас маны
- 12 скорость передваижение (только базовый параметр изменять можно)
- 13 дистанция получения приказа
В рефордже добавлено много всяких функции. Есть нативки, которые предоставляют прямой доступ к данным. А также существуют нативки для работы с филдами (полями) => чтение и изменение данных полей. Однако, для большинства полей можно только прочитать, а вот изменить практически нельзя (кроме регена хп и маны и др). Ничего просто не изменится. Безопасный способ использовать нативки с приставкой Blz
нативки рефорджа (не все)
native GetUnitFacing takes unit whichUnit returns real
native SetUnitFacing takes unit whichUnit, real facingAngle returns nothing
native GetUnitMoveSpeed takes unit whichUnit returns real
native GetUnitDefaultMoveSpeed takes unit whichUnit returns real
native SetUnitMoveSpeed takes unit whichUnit, real newSpeed returns nothing
native GetUnitAcquireRange takes unit whichUnit returns real
native GetUnitDefaultAcquireRange takes unit whichUnit returns real
native SetUnitAcquireRange takes unit whichUnit, real newAcquireRange returns nothing
native GetUnitTurnSpeed takes unit whichUnit returns real
native GetUnitDefaultTurnSpeed takes unit whichUnit returns real
native SetUnitTurnSpeed takes unit whichUnit, real newTurnSpeed returns nothing
function GetUnitPropWindowBJ takes unit whichUnit returns real
return GetUnitPropWindow(whichUnit) * bj_RADTODEG
endfunction
function GetUnitDefaultPropWindowBJ takes unit whichUnit returns real
return GetUnitDefaultPropWindow(whichUnit)
endfunction
native SetUnitPropWindow takes unit whichUnit, real newPropWindowAngle returns nothing
native GetUnitFlyHeight takes unit whichUnit returns real
native GetUnitDefaultFlyHeight takes unit whichUnit returns real
native SetUnitFlyHeight takes unit whichUnit, real newHeight, real rate returns nothing
native BlzGetLocalUnitZ takes unit whichUnit returns real
native BlzGetUnitZ takes unit whichUnit returns real
native BlzGetUnitArmor takes unit whichUnit returns real --считывает базовый+бонус
native BlzSetUnitArmor takes unit whichUnit, real armorAmount returns nothing
native BlzGetUnitBaseDamage takes unit whichUnit, integer weaponIndex returns integer
native BlzGetUnitDiceNumber takes unit whichUnit, integer weaponIndex returns integer
native BlzGetUnitDiceSides takes unit whichUnit, integer weaponIndex returns integer
native BlzSetUnitBaseDamage takes unit whichUnit, integer baseDamage, integer weaponIndex returns nothing
native BlzSetUnitDiceNumber takes unit whichUnit, integer diceNumber, integer weaponIndex returns nothing
native BlzSetUnitDiceSides takes unit whichUnit, integer diceSides, integer weaponIndex returns nothing
native BlzGetUnitAttackCooldown takes unit whichUnit, integer weaponIndex returns real
native BlzSetUnitAttackCooldown takes unit whichUnit, real cooldown, integer weaponIndex returns nothing
native BlzGetUnitMaxHP takes unit whichUnit returns integer
native BlzSetUnitMaxHP takes unit whichUnit, integer hp returns nothing
native BlzGetUnitMaxMana takes unit whichUnit returns integer
native BlzSetUnitMaxMana takes unit whichUnit, integer mana returns nothing
native BlzUnitHideAbility takes unit whichUnit, integer abilId, boolean flag returns nothing
native BlzGetUnitAbilityManaCost takes unit whichUnit, integer abilId, integer level returns integer
native BlzSetUnitAbilityManaCost takes unit whichUnit, integer abilId, integer level, integer manaCost returns nothing
native BlzGetUnitAbilityCooldown takes unit whichUnit, integer abilId, integer level returns real
native BlzGetUnitAbilityCooldownRemaining takes unit whichUnit, integer abilId returns real
native BlzSetUnitAbilityCooldown takes unit whichUnit, integer abilId, integer level, real cooldown returns nothing
native BlzUnitHideAbility takes unit whichUnit, integer abilId, boolean flag returns nothing
native BlzUnitDisableAbility takes unit whichUnit, integer abilId, boolean flag, boolean hideUI returns nothing
UNIT_RF_CAST_BACK_SWING = ConvertUnitRealField(FourCC('ucbs'))
UNIT_RF_CAST_POINT = ConvertUnitRealField(FourCC('ucpt'))
BlzGetUnitRealField(GetTriggerUnit(), UNIT_RF_CAST_BACK_SWING)
BlzGetUnitRealField(GetTriggerUnit(), UNIT_RF_CAST_POINT)
некоторые параметры уже есть в нативках рефорджа. Правда, они либо выдают/изменяют общий параметр (базовый+бонус) или только базовый. Можно только подсчитать, но для точности подсчета некоторых параметров рекомендуется делать заклинания, где есть баффы/дебаффы, полностью кастомные.
код BonusMod
do
local POWERS = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072 }
local MAX, MIN = POWERS[#POWERS], -POWERS[#POWERS]
local ABILITY = {
--STR: 1 [1-18]
FourCC('ZxF0'), -- +1
FourCC('ZxF1'), -- +2
FourCC('ZxF2'), -- +4
FourCC('ZxF3'), -- +8
FourCC('ZxF4'), -- +16
FourCC('ZxF5'), -- +32
FourCC('ZxF6'), -- +64
FourCC('ZxF7'), -- +128
FourCC('ZxF8'), -- +256
FourCC('ZxF9'), -- +512
FourCC('ZxFa'), -- +1024
FourCC('ZxFb'), -- +2048
FourCC('ZxFc'), -- +4096
FourCC('ZxFd'), -- +8192
FourCC('ZxFe'), -- +16384
FourCC('ZxFf'), -- +32768
FourCC('ZxFg'), -- +65536
FourCC('ZxFh'), -- -131072
-- AGI 2 [18-36]
FourCC('ZxG0'), -- +1
FourCC('ZxG1'), -- +2
FourCC('ZxG2'), -- +4
FourCC('ZxG3'), -- +8
FourCC('ZxG4'), -- +16
FourCC('ZxG5'), -- +32
FourCC('ZxG6'), -- +64
FourCC('ZxG7'), -- +128
FourCC('ZxG8'), -- +256
FourCC('ZxG9'), -- +512
FourCC('ZxGa'), -- +1024
FourCC('ZxGb'), -- +2048
FourCC('ZxGc'), -- +4096
FourCC('ZxGd'), -- +8192
FourCC('ZxGe'), -- +16384
FourCC('ZxGf'), -- +32768
FourCC('ZxGg'), -- +65536
FourCC('ZxGh'), -- -131072
-- INT 3 [36-54]
FourCC('ZxH0'), -- +1
FourCC('ZxH1'), -- +2
FourCC('ZxH2'), -- +4
FourCC('ZxH3'), -- +8
FourCC('ZxH4'), -- +16
FourCC('ZxH5'), -- +32
FourCC('ZxH6'), -- +64
FourCC('ZxH7'), -- +128
FourCC('ZxH8'), -- +256
FourCC('ZxH9'), -- +512
FourCC('ZxHa'), -- +1024
FourCC('ZxHb'), -- +2048
FourCC('ZxHc'), -- +4096
FourCC('ZxHd'), -- +8192
FourCC('ZxHe'), -- +16384
FourCC('ZxHf'), -- +32768
FourCC('ZxHg'), -- +65536
FourCC('ZxHh'), -- -131072
-- DAMAGE 4 [54-72]
FourCC('ZxB0'), -- +1
FourCC('ZxB1'), -- +2
FourCC('ZxB2'), -- +4
FourCC('ZxB3'), -- +8
FourCC('ZxB4'), -- +16
FourCC('ZxB5'), -- +32
FourCC('ZxB6'), -- +64
FourCC('ZxB7'), -- +128
FourCC('ZxB8'), -- +256
FourCC('ZxB9'), -- +512
FourCC('ZxBa'), -- +1024
FourCC('ZxBb'), -- +2048
FourCC('ZxBc'), -- +4096
FourCC('ZxBd'), -- +8192
FourCC('ZxBe'), -- +16384
FourCC('ZxBf'), -- +32768
FourCC('ZxBg'), -- +65536
FourCC('ZxBh'), -- -131072
-- ARMOR 5 [72-90]
FourCC('ZxA0'), -- +1
FourCC('ZxA1'), -- +2
FourCC('ZxA2'), -- +4
FourCC('ZxA3'), -- +8
FourCC('ZxA4'), -- +16
FourCC('ZxA5'), -- +32
FourCC('ZxA6'), -- +64
FourCC('ZxA7'), -- +128
FourCC('ZxA8'), -- +256
FourCC('ZxA9'), -- +512
FourCC('ZxAa'), -- +1024
FourCC('ZxAb'), -- +2048
FourCC('ZxAc'), -- +4096
FourCC('ZxAd'), -- +8192
FourCC('ZxAe'), -- +16384
FourCC('ZxAf'), -- +32768
FourCC('ZxAg'), -- +65536
FourCC('ZxAh'), -- -131072
-- regen HP 6 [90-108]
FourCC('ZxJ0'), -- +1
FourCC('ZxJ1'), -- +2
FourCC('ZxJ2'), -- +4
FourCC('ZxJ3'), -- +8
FourCC('ZxJ4'), -- +16
FourCC('ZxJ5'), -- +32
FourCC('ZxJ6'), -- +64
FourCC('ZxJ7'), -- +128
FourCC('ZxJ8'), -- +256
FourCC('ZxJ9'), -- +512
FourCC('ZxJa'), -- +1024
FourCC('ZxJb'), -- +2048
FourCC('ZxJc'), -- +4096
FourCC('ZxJd'), -- +8192
FourCC('ZxJe'), -- +16384
FourCC('ZxJf'), -- +32768
FourCC('ZxJg'), -- +65536
FourCC('ZxJh'), -- -131072
-- regen MP 7 [108-126]
FourCC('ZxK0'), -- +1
FourCC('ZxK1'), -- +2
FourCC('ZxK2'), -- +4
FourCC('ZxK3'), -- +8
FourCC('ZxK4'), -- +16
FourCC('ZxK5'), -- +32
FourCC('ZxK6'), -- +64
FourCC('ZxK7'), -- +128
FourCC('ZxK8'), -- +256
FourCC('ZxK9'), -- +512
FourCC('ZxKa'), -- +1024
FourCC('ZxKb'), -- +2048
FourCC('ZxKc'), -- +4096
FourCC('ZxKd'), -- +8192
FourCC('ZxKe'), -- +16384
FourCC('ZxKf'), -- +32768
FourCC('ZxKg'), -- +65536
FourCC('ZxKh'), -- -131072
-- SIGHT 8 [126-144]
FourCC('ZxC0'), -- +1
FourCC('ZxC1'), -- +2
FourCC('ZxC2'), -- +4
FourCC('ZxC3'), -- +8
FourCC('ZxC4'), -- +16
FourCC('ZxC5'), -- +32
FourCC('ZxC6'), -- +64
FourCC('ZxC7'), -- +128
FourCC('ZxC8'), -- +256
FourCC('ZxC9'), -- +512
FourCC('ZxCa'), -- +1024
FourCC('ZxCb'), -- +2048
FourCC('ZxCc'), -- +4096
FourCC('ZxCd'), -- +8192
FourCC('ZxCe'), -- +16384
FourCC('ZxCf'), -- +32768
FourCC('ZxCg'), -- +65536
FourCC('ZxCh'), -- -131072
-- AttackSpeed 9 [144-162]
FourCC('ZxI0'), -- +1
FourCC('ZxI1'), -- +2
FourCC('ZxI2'), -- +4
FourCC('ZxI3'), -- +8
FourCC('ZxI4'), -- +16
FourCC('ZxI5'), -- +32
FourCC('ZxI6'), -- +64
FourCC('ZxI7'), -- +128
FourCC('ZxI8'), -- +256
FourCC('ZxI9'), -- +512
FourCC('ZxIa'), -- +1024
FourCC('ZxIb'), -- +2048
FourCC('ZxIc'), -- +4096
FourCC('ZxId'), -- +8192
FourCC('ZxIe'), -- +16384
FourCC('ZxIf'), -- +32768
FourCC('ZxIg'), -- +65536
FourCC('ZxIh'), -- -131072
-- Max Life 10 [162-180]
FourCC('ZxE0'), -- +1
FourCC('ZxE1'), -- +2
FourCC('ZxE2'), -- +4
FourCC('ZxE3'), -- +8
FourCC('ZxE4'), -- +16
FourCC('ZxE5'), -- +32
FourCC('ZxE6'), -- +64
FourCC('ZxE7'), -- +128
FourCC('ZxE8'), -- +256
FourCC('ZxE9'), -- +512
FourCC('ZxEa'), -- +1024
FourCC('ZxEb'), -- +2048
FourCC('ZxEc'), -- +4096
FourCC('ZxEd'), -- +8192
FourCC('ZxEe'), -- +16384
FourCC('ZxEf'), -- +32768
FourCC('ZxEg'), -- +65536
FourCC('ZxEh'), -- -131072
-- Max Mana 11 [180-198]
FourCC('ZxD0'), -- +1
FourCC('ZxD1'), -- +2
FourCC('ZxD2'), -- +4
FourCC('ZxD3'), -- +8
FourCC('ZxD4'), -- +16
FourCC('ZxD5'), -- +32
FourCC('ZxD6'), -- +64
FourCC('ZxD7'), -- +128
FourCC('ZxD8'), -- +256
FourCC('ZxD9'), -- +512
FourCC('ZxDa'), -- +1024
FourCC('ZxDb'), -- +2048
FourCC('ZxDc'), -- +4096
FourCC('ZxDd'), -- +8192
FourCC('ZxDe'), -- +16384
FourCC('ZxDf'), -- +32768
FourCC('ZxDg'), -- +65536
FourCC('ZxDh') -- -131072
}
local TYPES = #ABILITY / #POWERS
---@param target unit
---@param mod integer
function UnitClearBonus (target, mod)
if type(mod) ~= 'number' or mod < 1 or mod > TYPES then
return print('UnitClearBonus: Invalid mod', mod)
elseif GetUnitTypeId (target) == 0 or IsUnitType (target, UNIT_TYPE_DEAD) then
return print('UnitClearBonus: Unit is dead or does not exist')
end
for i = 1, #POWERS do
UnitRemoveAbility(target, ABILITY[(mod - 1) * #POWERS + i])
end
end
---@param target unit
---@param mod integer
---@param ammount integer
---@return boolean
function UnitSetBonus (target, mod, ammount)
if type(mod) ~= 'number' or mod < 1 or mod > TYPES then
print('UnitSetBonus: Invalid mod', mod)
return false
elseif type(ammount) ~= 'number' or ammount < MIN or ammount > MAX then
print('UnitSetBonus: Bonus too high or low', ammount)
return false
elseif GetUnitTypeId (target) == 0 or IsUnitType (target, UNIT_TYPE_DEAD) then
print('UnitSetBonus: Unit is dead or does not exist')
return false
end
if mod > 0 and mod < 4 then
if not IsUnitType(target, UNIT_TYPE_HERO) then
print('UnitSetBonus: you cant give the ability to a non-hero')
return false
end
elseif mod == 9 then
--[[
local agility = GetUnitAgilityBonusIAS(target)*100
if ammount+agility > 400 then
ammount = 400-agility
if ammount < 0 then
ammount = 0
end
elseif ammount+agility < -80 then
ammount = -80-agility
if ammount > 0 then
ammount = 0
end
end
]]
end
local ability
if ammount < 0 then
ammount = MAX + ammount
for i = #POWERS - 1, 1, -1 do
ability = ABILITY[(mod - 1) * #POWERS + i]
if ammount >= POWERS[i] then
UnitAddAbility(target, ability)
UnitMakeAbilityPermanent(target, true, ability)
ammount = ammount - POWERS[i]
else
UnitRemoveAbility(target, ability)
end
end
ability = ABILITY[(mod - 1) * #POWERS + #POWERS]
UnitAddAbility(target, ability)
UnitMakeAbilityPermanent(target, true, ability)
else
ability = ABILITY[(mod - 1) * #POWERS + #POWERS]
UnitRemoveAbility(target, ability)
for i = #POWERS - 1, 1, -1 do
ability = ABILITY[(mod - 1) * #POWERS + i]
if ammount >= POWERS[i] then
UnitAddAbility(target, ability)
UnitMakeAbilityPermanent(target, true, ability)
ammount = ammount - POWERS[i]
else
UnitRemoveAbility(target, ability)
end
end
end
return true
end
---@param target unit
---@param mod integer
---@return integer
function UnitGetBonus (target, mod)
local ammount = 0
if type(mod) ~= 'number' or mod < 1 or mod > TYPES then
print('UnitGetBonus: Invalid mod', mod)
return 0
elseif GetUnitTypeId (target) == 0 or IsUnitType (target, UNIT_TYPE_DEAD) then
print('UnitGetBonus: Unit is dead or does not exist')
return 0
end
if GetUnitAbilityLevel(target, ABILITY[(mod - 1) * #POWERS + #POWERS]) > 0 then
ammount = MIN
end
for i = 1, #POWERS-1 do
if GetUnitAbilityLevel(target, ABILITY[((mod - 1) * #POWERS) + i]) > 0 then
ammount = ammount + POWERS[i]
end
end
return ammount
end
---@param target unit
---@param mod integer
---@param ammount integer
---@return boolean
function UnitAddBonus (target, mod, ammount)
return UnitSetBonus(target, mod,UnitGetBonus(target, mod)+ammount)
end
end
функции
do
local InitGlobalsOrigin = InitGlobals
function InitGlobals()
InitGlobalsOrigin()
--константы
NeedHeroXP = 200
NeedHeroXPFormulaA = 1.00
NeedHeroXPFormulaB = 100
NeedHeroXPFormulaC = 0
AttackSpeedBonusPerAgilityPoint = 0.02
DefenseBonusPerAgilityPoint = 0.3
DefenseBaseValue = -2 --for Agility
HitPointBonusPerStrength = 25
RegenHpBonusPerStrength = 0.05
ManaPointBonusPerInt = 15
RegenManaBonusPerInt = 0.05
Multiplier = 0.060 --for damage and armor
UnitSpeedMax = 400.0
UnitSpeedMin = 150.0
BuildingSpeedMax = 400.0
BuildingSpeedMin = 25.0
--основные характеристики героя ============
--основной атрибут героя (1-str, 3-agi, 2-int). влияет на атаку
function GetHeroPrimaryAttribute(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_PRIMARY_ATTRIBUTE)
end
function SetHeroPrimaryAttribute(hero, value) --установка не работает
BlzSetUnitIntegerField( hero, UNIT_IF_PRIMARY_ATTRIBUTE, value)
end
function GetHeroStrPerLevel(hero)
return BlzGetUnitRealField(hero, UNIT_RF_STRENGTH_PER_LEVEL)
end
function GetHeroAgiPerLevel(hero)
return BlzGetUnitRealField(hero, UNIT_RF_AGILITY_PER_LEVEL)
end
function GetHeroIntPerLevel(hero)
return BlzGetUnitRealField(hero, UNIT_RF_INTELLIGENCE_PER_LEVEL)
end
--стартовые характеристики на 1-ом уровне
function GetBasicParamStr(u)
return math.ceil(GetHeroStr_base(u)-(GetHeroStrPerLevel(u)*(GetHeroLevel(u)-1)))
end
function GetBasicParamAgi(u)
return math.ceil(GetHeroAgi_base(u)-(GetHeroAgiPerLevel(u)*(GetHeroLevel(u)-1)))
end
function GetBasicParamInt(u)
return math.ceil(GetHeroInt_base(u)-(GetHeroIntPerLevel(u)*(GetHeroLevel(u)-1)))
end
--общие параметры атрибутов: базовый+бонус (бонус можно исключить)
function GetHeroAttributeStr(hero, includeBonuses)
return GetHeroStr(hero, includeBonuses)
end
function GetHeroAttributeAgi(hero, includeBonuses)
return GetHeroAgi(hero, includeBonuses)
end
function GetHeroAttributeInt(hero, includeBonuses)
return GetHeroInt(hero, includeBonuses)
end
--базовые атрибуты героя
function GetHeroStr_base(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_STRENGTH)
end
function GetHeroAgi_base(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_AGILITY)
end
function GetHeroInt_base(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_INTELLIGENCE)
end
--бонусные атрибуты героя
function GetHeroStr_bonus(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_STRENGTH_WITH_BONUS)-GetHeroStr_base(hero)
end
function GetHeroAgi_bonus(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_AGILITY_WITH_BONUS)-GetHeroAgi_base(hero)
end
function GetHeroInt_bonus(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_INTELLIGENCE_WITH_BONUS)-GetHeroInt_base(hero)
end
--установить базовые (белые) атрибуты героя
function SetHeroBaseStr(hero, value)
SetHeroStr(hero, value, true)
end
function SetHeroBaseAgi(hero, value)
SetHeroAgi(hero, value, true)
end
function SetHeroBaseInt(hero, value)
SetHeroInt(hero, value, true)
end
--установить бонусные (зеленые) атрибуты героя
function SetHeroBonusStr(hero, value)
UnitSetBonus (hero, 1, value)
end
function SetHeroBonusAgi(hero, value)
UnitSetBonus (hero, 2, value)
end
function SetHeroBonusInt(hero, value)
UnitSetBonus (hero, 3, value)
end
--добавить бонусные (зеленые) атрибуты героя
function AddHeroBonusStr(hero, value)
UnitAddBonus (target, 1, ammount)
end
function AddHeroBonusAgi(hero, value)
UnitAddBonus (target, 2, ammount)
end
function AddHeroBonusInt(hero, value)
UnitAddBonus (target, 3, ammount)
end
--основной атрибут (включая бонус)
function GetHeroGeneralPrimaryAttribute(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(hero) == 1 then --str
return GetHeroAttributeStr(hero, true)
elseif GetHeroPrimaryAttribute(hero) == 2 then --int
return GetHeroAttributeInt(hero, true)
elseif GetHeroPrimaryAttribute(hero) == 3 then --agi
return GetHeroAttributeAgi(hero, true)
end
end
end
--базовый атрибут
function GetHeroBasePrimaryAttribute(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(hero) == 1 then --str
return GetHeroAttributeStr(hero, false)
elseif GetHeroPrimaryAttribute(hero) == 2 then --int
return GetHeroAttributeInt(hero, false)
elseif GetHeroPrimaryAttribute(hero) == 3 then --agi
return GetHeroAttributeAgi(hero, false)
end
end
end
--бонусный атрибут
function GetHeroBonusPrimaryAttribute(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(hero) == 1 then --str
return GetHeroStr_bonus(hero)
elseif GetHeroPrimaryAttribute(hero) == 2 then --int
return GetHeroInt_bonus(hero)
elseif GetHeroPrimaryAttribute(hero) == 3 then --agi
return GetHeroAgi_bonus(hero)
end
end
end
--урон ========================
--bonus damage от абилок-когтей
function UnitGetBonusDamage(unit)
return UnitGetBonus(unit, 4)
end
function UnitSetBonusDamage(unit,value)
UnitSetBonus(unit, 4,value)
end
--суммарный bonus damage (от осного атрибута+от когтей)
function GetUnitBonusDamage(unit)
local bonus = 0
if IsUnitType(unit, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(unit) == 1 then --str
bonus = GetHeroStr_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 2 then --int
bonus = GetHeroInt_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 3 then --agi
bonus = GetHeroAgi_bonus(unit)
end
end
--bonus damage от основного атрибута + bonus damage от когтей
return UnitGetBonusDamage(unit)+ bonus
end
--общий базовый урон с учетом базового атрибута героя
--бонус урона от предметов в функции BlzGetUnitBaseDamage не учитывается, поэтому его в расчетах нет
function GetUnitBaseDamage(unit, index)
local base = 0
local bonus = 0
if IsUnitType(unit, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(unit) == 1 then --str
bonus = GetHeroStr_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 2 then --int
bonus = GetHeroInt_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 3 then --agi
bonus = GetHeroAgi_bonus(unit)
end
end
return(BlzGetUnitBaseDamage(unit,index)-bonus)
end
--изначальный урон (без учета бонусного атрибута)
--короче, это чистый урон без основного атрибута героя
--для обычных (не-героев) эта функция бесполезна, тк равнозначна GetUnitBaseDamage
function GetUnitBasicDamage(unit, index)
if IsUnitType(unit, UNIT_TYPE_HERO) then
return GetUnitBaseDamage(unit, index)-GetHeroBasePrimaryAttribute(unit)
else
return GetUnitBaseDamage(unit, index)
end
end
function GetUnitMinDamage(unit, index)
return (GetUnitBaseDamage(unit,index)+BlzGetUnitDiceNumber(unit,index))
end
function GetUnitMaxDamage(unit, index)
return (GetUnitBaseDamage(unit,index)+BlzGetUnitDiceNumber(unit,index)*BlzGetUnitDiceSides(unit,index))
end
--скорость атаки =====================
--BAS - базовая скорость атаки, показывает кол-во ударов в сек
function GetUnitBaseAttackSpeed(unit, index)
if BlzGetUnitAttackCooldown(unit, index) ~= 0 then
return 1/BlzGetUnitAttackCooldown(unit, index)
else
return 0
end
end
--IAS - показывает %-ый бонус от ловкости героя
function GetUnitAgilityBonusIAS(unit)
if IsUnitType(unit, UNIT_TYPE_HERO) then
return (GetHeroAttributeAgi(unit, true)*AttackSpeedBonusPerAgilityPoint) --0.02% бонуса AS за каждую единицу ловкости
else
return 0
end
end
--IAS - показывает % процентное содержание AS
function GetUnitBaseIAS(unit)
return 1.00 --изначально AS равна 1.00 (100%)
end
--bonus IAS - показывает процент AS от абилок
--делим на 100 тк результат из BonusMod выдают в виде целых чисел
function GetUnitBonusIAS(unit)
return (UnitGetBonus (unit, 9) / 100)
end
function SetUnitBonusIAS(unit,value)
return (UnitSetBonus (unit, 9, R2I(value*100)))
end
--общий бонус. лимитирован от -80% до 400%
function GetGeneralUnitBonusIAS(unit)
local bonus = GetUnitAgilityBonusIAS(unit) + GetUnitBonusIAS(unit)
if bonus > 4.00 then
return 4.00
elseif bonus < -0.80 then
return -0.80
end
return bonus
end
--показывает общий суммарный IAS в %
function GetUnitIncreaseAttackSpeed(unit, includeBonuses)
if includeBonuses then
return GetUnitBaseIAS(unit) + GetGeneralUnitBonusIAS(unit)
else
return GetUnitBaseIAS(unit)
end
end
--текущий AS выдает кол-во ударов в сек
function GetUnitCurrentAttackSpeed(unit, index)
return GetUnitBaseAttackSpeed(unit, index) * GetUnitIncreaseAttackSpeed(unit, true)
end
--текущее время задержки для атаки
function GetUnitCurrentAttackTime(unit, index)
if GetUnitIncreaseAttackSpeed(unit, true) ~= 0 then
return BlzGetUnitAttackCooldown(unit, index) / GetUnitIncreaseAttackSpeed(unit, true)
else
return 0
end
end
--ARMOR ==============================
--base armor от base (белой) agility
function GetHeroBaseArmor(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return (GetHeroAttributeAgi(hero,false)*DefenseBonusPerAgilityPoint)+DefenseBaseValue
else
return 0
end
end
--bonus armor от bonus (зеленой) agility
function GetHeroBonusArmor(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroAgi_bonus(hero)*DefenseBonusPerAgilityPoint
else
return 0
end
end
--bonus armor от способностей
function UnitGetBonusArmor(unit)
return UnitGetBonus (unit, 5)
end
function UnitSetBonusArmor(unit,value)
return UnitSetBonus (unit, 5, value)
end
--суммарный бонус защиты
function GetUnitBonusArmor(unit)
return UnitGetBonusArmor(unit)+GetHeroBonusArmor(unit)
end
--суммарная базовая защита
function GetUnitBaseArmor(unit)
return BlzGetUnitArmor(unit)-GetUnitBonusArmor(unit)
end
--изначальная базовая защита (без учета ловкости)
--дроби базовой защиты пришлось отсекать
--из-за ловкости значения могут не округляться до целых
--пример 28, а получилось 27.99. базовый параметр при расчетах получается не 0, а -0.11
function GetBasicArmor(unit)
local basic = GetUnitBaseArmor(unit)-GetHeroBaseArmor(unit)
if basic>0 then
return math.floor(basic)
elseif basic<0 then
return math.ceil(basic)
else
return basic
end
end
--DamageReduction =======================
--формула снижения армора
--https://xgm.guru/p/wc3/get-unit-armor
function GetDamageReduction(unit)
local armor = BlzGetUnitArmor(unit)
local reduction = 0
if armor>0 then
reduction = Multiplier * armor / (1 + Multiplier * armor)
elseif armor<0 then
reduction = (1 - Multiplier) ^ (-armor) - 1
end
return reduction
end
--HP и MANA =====================
function SetUnitHP(unit,value)
SetUnitState(unit, UNIT_STATE_LIFE, RMaxBJ(0,value))
end
function SetUnitMana(unit,value)
SetUnitState(unit, UNIT_STATE_MANA, RMaxBJ(0,value))
end
--MAX HP и MAX MANA =============
function GetHeroBaseMaxHP(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroStr(hero, true)*HitPointBonusPerStrength
else
return 0
end
end
function GetHeroBaseMaxMana(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroInt(hero, true)*ManaPointBonusPerInt
else
return 0
end
end
function GetUnitBonusMaxHP(unit)
return UnitGetBonus (unit, 10)
end
function GetUnitBaseMaxHP(unit)
return BlzGetUnitMaxHP(unit)-(GetHeroBaseMaxHP(unit)+GetUnitBonusMaxHP(unit))
end
function GetUnitBonusMaxMana(unit)
return UnitGetBonus (unit, 11)
end
function GetUnitBaseMaxMana(unit)
return BlzGetUnitMaxMana(unit)-(GetHeroBaseMaxMana(unit)+GetUnitBonusMaxMana(unit))
end
-- regen hp и regen mana ==================
--bonus regen hp/sec
function GetUnitBonusRegenHP(unit)
return UnitGetBonus (unit, 6)
end
--bonus % увеличение mana regen от base regen
function GetUnitBonusRegenMana(unit)
return UnitGetBonus (unit, 7)
end
--bonus regen hp/sec
function GetUnitBonusRegenHP(unit)
return UnitGetBonus (unit, 6)
end
--bonus regen hp/sec от strength
function GetHeroRegenHP(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroStr(hero, true)*RegenHpBonusPerStrength
else
return 0
end
end
--base regen hp/sec
function GetUnitBaseRegenHP(unit)
return BlzGetUnitRealField(unit, UNIT_RF_HIT_POINTS_REGENERATION_RATE)
end
function SetUnitBaseRegenHP(unit, value)
BlzSetUnitRealFieldBJ( unit, UNIT_RF_HIT_POINTS_REGENERATION_RATE, value )
end
--общий бонус регена (полезен для героев)
function GetUnitGeneralBonusRegenHP(unit)
return GetHeroRegenHP(unit)+GetUnitBonusRegenHP(unit)
end
--общий regen hp/sec
function GetUnitRegenHP(unit)
return GetUnitBaseRegenHP(unit)+GetUnitGeneralBonusRegenHP(unit)
end
--procent от mana regen
function GetUnitBonusProcentRegenMana(unit)
return UnitGetBonus (unit, 7)/100
end
function SetUnitBonusProcentRegenMana(unit,value)
return UnitGetBonus (unit, 7,R2I(value*100))
end
--regen mana/sec от intellect
function GetHeroRegenMana(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroInt(hero, true)*RegenManaBonusPerInt
else
return 0
end
end
--base regen mana/sec
function GetUnitBaseRegenMana(unit)
return BlzGetUnitRealField(unit, UNIT_RF_MANA_REGENERATION)
end
function SetUnitBaseRegenMana(unit, value)
return BlzSetUnitRealField( unit, UNIT_RF_MANA_REGENERATION, value )
end
function GetUnitBonusRegenMana(unit)
return (GetHeroRegenMana(unit)+GetUnitBaseRegenMana(unit))*GetUnitBonusProcentRegenMana(unit)
end
--общий бонус регена (полезен для героев)
function GetUnitGeneralBonusRegenMana(unit)
return GetHeroRegenMana(unit)+GetUnitBonusRegenMana(unit)
end
--общий реген маны
function GetUnitRegenMana(unit)
return GetUnitBaseRegenMana(unit)+GetUnitGeneralBonusRegenMana(unit)
end
--check ATTACK =================
function IsAttackUnitEnabled(unit,index)
return BlzGetUnitWeaponBooleanField(unit, UNIT_WEAPON_BF_ATTACKS_ENABLED,index)
end
-- 0 - normal (skills), 1 - melee, 2 - pierce, 3 - siege, 4 - magic,5 - chaos,6 - hero
function GetUnitAttackType(unit,index)
return BlzGetUnitWeaponIntegerField(unit, UNIT_WEAPON_IF_ATTACK_ATTACK_TYPE, index)
end
-- check type defense ==============
function GetUnitDefenseType(unit)
return BlzGetUnitIntegerField(unit, UNIT_IF_DEFENSE_TYPE)
end
-- AcquisitionRange ===================
function GetUnitAcquisitionRange(unit)
return BlzGetUnitRealField(unit, UNIT_RF_ACQUISITION_RANGE)
end
function SetUnitAcquisitionRange(unit,value)
return BlzSetUnitRealField(unit, UNIT_RF_ACQUISITION_RANGE,value)
end
-- radius sight =====================
function GetUnitSightRadius(unit)
return BlzGetUnitRealField(unit, UNIT_RF_SIGHT_RADIUS)
end
function SetUnitSightRadius(unit, value)
return BlzSetUnitRealField( unit, UNIT_RF_SIGHT_RADIUS, value )
end
function GetUnitBonusSightRadius(unit)
return UnitGetBonus (unit, 8)
end
function SetUnitBonusSightRadius(unit,value)
return UnitSetBonus (unit, 8,value)
end
--макс опыт ====================================
function GetHeroMaxXP(hero)
local level = GetUnitLevel(hero)
local need = 0
for i=1, level do
need = need * NeedHeroXPFormulaA + NeedHeroXPFormulaB * (i+1) + NeedHeroXPFormulaC
end
return need
end
end
end
список функции
характеристики героя
модификаторы атрибута можно вычислить разными способами. Достаточно нативки GetHeroStr/GetHeroAgi/GetHeroInt из варика 1.26. Они еще актуальны. Но я как-то эксперементировал, и проверял на что влияют поля (филды). И как-то у меня по своему получилосб. Короче, что там, что здесь - разницы никакой. Поэтому я не стал прибегать к не нужной проверки UnitGetBonus из BonusMod, где циклом чекает. Не нужно.
определение основного атрибута
--основной атрибут героя (1-str, 3-agi, 2-int). влияет на атаку
function GetHeroPrimaryAttribute(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_PRIMARY_ATTRIBUTE)
end
--установка не работает
function SetHeroPrimaryAttribute(hero, value)
BlzSetUnitIntegerField( hero, UNIT_IF_PRIMARY_ATTRIBUTE, value)
end
определение начисления очков атрибута за каждый уровень
function GetHeroStrPerLevel(hero)
return BlzGetUnitRealField(hero, UNIT_RF_STRENGTH_PER_LEVEL)
end
function GetHeroAgiPerLevel(hero)
return BlzGetUnitRealField(hero, UNIT_RF_AGILITY_PER_LEVEL)
end
function GetHeroIntPerLevel(hero)
return BlzGetUnitRealField(hero, UNIT_RF_INTELLIGENCE_PER_LEVEL)
end
определение: общие параметры атрибутов (дефолтные нативки)
--общие параметры атрибутов: базовый+бонус (бонус можно исключить)
function GetHeroAttributeStr(hero, includeBonuses)
return GetHeroStr(hero, includeBonuses)
end
function GetHeroAttributeAgi(hero, includeBonuses)
return GetHeroAgi(hero, includeBonuses)
end
function GetHeroAttributeInt(hero, includeBonuses)
return GetHeroInt(hero, includeBonuses)
end
определение: базовые атрибуты героя (белые атрибуты)
--базовые атрибуты героя
function GetHeroStr_base(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_STRENGTH)
end
function GetHeroAgi_base(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_AGILITY)
end
function GetHeroInt_base(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_INTELLIGENCE)
end
определение: бонусные атрибуты (зеленые атрибуты)
--бонусные атрибуты героя
function GetHeroStr_bonus(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_STRENGTH_WITH_BONUS)-GetHeroStr_base(hero)
end
function GetHeroAgi_bonus(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_AGILITY_WITH_BONUS)-GetHeroAgi_base(hero)
end
function GetHeroInt_bonus(hero)
return BlzGetUnitIntegerField(hero, UNIT_IF_INTELLIGENCE_WITH_BONUS) - GetHeroInt_base(hero)
end
дополнительные базовые аттрибуты (наскока изменили от дефолта)
поскольку нативок и филдов не обнаружил. и никак не достать. а бесполезную бд вручную делать не хочется. решил написать код заполнения бд при создании юнита. Это сделано специально, для сброса параметров. при создании юнита система записывает стартовые базовые параметры. В игре могу изменять базовые параметры, но и также сбросить. Ну по идее это мб и бесполезной штукой.
заметка: система фиксирует не только при создании юнитов, но и регистрирует тех, что на карте. И не все герои изначально имеют стартовые характеристики, поскольку они уже возросли. Поэтому расчет идет от уровня.
короче, в чем суть этих стартовых функции? в редакторе вы можете поставить героя на карту. Задать уровень герою, у него за каждый уровень соответственно возрастают характеристики. Также, можно и изменить базовые уровни на любой другой прям в редакторе. Но вот наскока изменили это значение можно подсчитать и записать как basic
--GetBasicParam показывает насколько изменилась базовая характеристика по стравнению с дефолтом
function GetBasicParamStr(u)
return math.ceil(GetHeroStr_base(u)-(GetHeroStrPerLevel(u)*(GetHeroLevel(u)-1)))
end
function GetBasicParamAgi(u)
return math.ceil(GetHeroAgi_base(u)-(GetHeroAgiPerLevel(u)*(GetHeroLevel(u)-1)))
end
function GetBasicParamInt(u)
return math.ceil(GetHeroInt_base(u)-(GetHeroIntPerLevel(u)*(GetHeroLevel(u)-1)))
end
основной атрибут
основной атрибут помогает отобразить кол-во атаки. Ведь у героев вся атака строится на основном атрибуте
у меня три функции определения урона: общий, базовый, бонус. Поскольку нужно бывает нужно учитывать только базовый/бонусный урон/или исключить бонусный и др
общий атрибут
--основной атрибут (включая бонус)
function GetHeroGeneralPrimaryAttribute(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(hero) == 1 then --str
return GetHeroAttributeStr(hero, true)
elseif GetHeroPrimaryAttribute(hero) == 2 then --int
return GetHeroAttributeInt(hero, true)
elseif GetHeroPrimaryAttribute(hero) == 3 then --agi
return GetHeroAttributeAgi(hero, true)
end
end
end
базовый основной атрибут
--базовый атрибут
function GetHeroBasePrimaryAttribute(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(hero) == 1 then --str
return GetHeroAttributeStr(hero, false)
elseif GetHeroPrimaryAttribute(hero) == 2 then --int
return GetHeroAttributeInt(hero, false)
elseif GetHeroPrimaryAttribute(hero) == 3 then --agi
return GetHeroAttributeAgi(hero, false)
end
end
end
бонусной основной атрибут
--бонусный атрибут
function GetHeroBonusPrimaryAttribute(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(hero) == 1 then --str
return GetHeroStr_bonus(hero)
elseif GetHeroPrimaryAttribute(hero) == 2 then --int
return GetHeroInt_bonus(hero)
elseif GetHeroPrimaryAttribute(hero) == 3 then --agi
return GetHeroAgi_bonus(hero)
end
end
end
Теперь введем функции на установку параметров. Изначально в варике доступны SetHeroStr/SetHeroAgi/SetHeroInt. Но они меняют только базовые параметры. А вот бонусы придеться добавлять через UnitSetBonus
изменение базовых атрибутов (белых атрибутов)
--установить базовые (белые) атрибуты героя
function SetHeroBaseStr(hero, value)
SetHeroStr(hero, value, true)
end
function SetHeroBaseAgi(hero, value)
SetHeroAgi(hero, value, true)
end
function SetHeroBaseInt(hero, value)
SetHeroInt(hero, value, true)
end
изменение бонусных атрибутов (зеленых атрибутов)
--установить бонусные (зеленые) атрибуты героя
function SetHeroBonusStr(hero, value)
UnitSetBonus (hero, 1, value)
end
function SetHeroBonusAgi(hero, value)
UnitSetBonus (hero, 2, value)
end
function SetHeroBonusInt(hero, value)
UnitSetBonus (hero, 3, value)
end
добавить бонусные атрибуты
короче, функции на добавлении очков модификаторов из BonusMod
--добавить бонусные (зеленые) атрибуты героя
function AddHeroBonusStr(hero, value)
UnitAddBonus (target, 1, ammount)
end
function AddHeroBonusAgi(hero, value)
UnitAddBonus (target, 2, ammount)
end
function AddHeroBonusInt(hero, value)
UnitAddBonus (target, 3, ammount)
end
включена/выключена атака
Перво-наперво нужно проверять есть ли у юнита атака вообще. Это можно сделать с помощью проверки GetUnitAbilityLevel(unit, FourCC('Aatk'))>0
function IsAttackUnitEnabled(unit,index)
return BlzGetUnitWeaponBooleanField(unit, UNIT_WEAPON_BF_ATTACKS_ENABLED,index)
end
урон
в рефордже уже существуют новые нативки для урона
native BlzGetUnitBaseDamage takes unit whichUnit, integer weaponIndex returns integer
native BlzGetUnitDiceNumber takes unit whichUnit, integer weaponIndex returns integer
native BlzGetUnitDiceSides takes unit whichUnit, integer weaponIndex returns integer
native BlzSetUnitBaseDamage takes unit whichUnit, integer baseDamage, integer weaponIndex returns nothing
native BlzSetUnitDiceNumber takes unit whichUnit, integer diceNumber, integer weaponIndex returns nothing
native BlzSetUnitDiceSides takes unit whichUnit, integer diceSides, integer weaponIndex returns nothing
определение: суммарный базовый урон (базовый урон + основной атрибут)
BlzGetUnitBaseDamage определяет суммарный урон (урон из ро + урон от основного базового атрибута). из основного атрибута героя BlzGetUnitBaseDamage учитывает даже бонусный атрибут. Бонусный атрибут прибавляется к бонусному урону, поэтому нас интересует только базовый основной атрибут героя
заметка: BlzGetUnitBaseDamage почему-то не учитывает бонусы урона от предметов. Но зато учитывает урон от основного атрибута, или бонус тоже от основного атрибута.
--общий базовый урон с учетом базового атрибута героя
--бонус урона от предметов в функции BlzGetUnitBaseDamage не учитывается, поэтому его в расчетах нет
function GetUnitBaseDamage(unit, index)
local base = 0
local bonus = 0
if IsUnitType(unit, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(unit) == 1 then --str
bonus = GetHeroStr_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 2 then --int
bonus = GetHeroInt_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 3 then --agi
bonus = GetHeroAgi_bonus(unit)
end
end
return(BlzGetUnitBaseDamage(unit,index)-bonus)
end
бонусный урон
тут функции работают с очкамит модификатора-4 из BonusMod, т.е. из предметов
--bonus damage от абилок-когтей
function UnitGetBonusDamage(unit)
return UnitGetBonus(unit, 4)
end
function UnitSetBonusDamage(unit,value)
UnitSetBonus(unit, 4,value)
end
суммарный бонусный урон (бонусный урон + бонус от основного атрибута)
--суммарный bonus damage (от осного атрибута+от когтей)
function GetUnitBonusDamage(unit)
local bonus = 0
if IsUnitType(unit, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(unit) == 1 then --str
bonus = GetHeroStr_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 2 then --int
bonus = GetHeroInt_bonus(unit)
elseif GetHeroPrimaryAttribute(unit) == 3 then --agi
bonus = GetHeroAgi_bonus(unit)
end
end
--bonus damage от основного атрибута + bonus damage от когтей
return UnitGetBonusDamage(unit)+ bonus
end
Min and Max damage
Вычисляются по такой формуле
Min = Damage Base + Number of Dice (количество костей)
Max = Damage Base + Number of Dice * Sides per Die (кол-во костей*урона с каждой кости)
Min = Damage Base + Number of Dice (количество костей)
Max = Damage Base + Number of Dice * Sides per Die (кол-во костей*урона с каждой кости)
function GetUnitMinDamage(unit, index)
return (GetUnitBaseDamage(unit,index) + BlzGetUnitDiceNumber(unit,index))
end
function GetUnitMaxDamage(unit, index)
return (GetUnitBaseDamage(unit,index) + BlzGetUnitDiceNumber(unit,index) * BlzGetUnitDiceSides(unit,index))
end
защита
в рефордже уже есть две нативки для работы с защитой. Однако, оно выдает инфу или изменяет общий armor. Никак не подразделяет на базовую и бонус
--считывает базовый+бонус
native BlzGetUnitArmor takes unit whichUnit returns real
native BlzSetUnitArmor takes unit whichUnit, real armorAmount returns nothing
базовая защита от базовой ловкости
--константы
DefenseBonusPerAgilityPoint = 0.3
DefenseBaseValue = -2 --for Agility
--base armor от base (белой) agility
function GetHeroBaseArmor(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return (GetHeroAttributeAgi(hero,false) * DefenseBonusPerAgilityPoint) + DefenseBaseValue
else
return 0
end
end
бонусная защита от бонусной ловкости
--bonus armor от bonus (зеленой) agility
function GetHeroBonusArmor(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroAgi_bonus(hero) * DefenseBonusPerAgilityPoint
else
return 0
end
end
бонус защиты от модификатора-5 из BonusMod
--bonus armor от способностей
function UnitGetBonusArmor(unit)
return UnitGetBonus (unit, 5)
end
function UnitSetBonusArmor(unit,value)
return UnitSetBonus (unit, 5, value)
end
суммарный бонус защиты
--суммарный бонус защиты
function GetUnitBonusArmor(unit)
return UnitGetBonusArmor(unit)+GetHeroBonusArmor(unit)
end
суммарная базовая защита
напомню, что BlzGetUnitArmor учитывает общую защиту. и не подразделяет на базовую и бонусную защиту.
--суммарная базовая защита
function GetUnitBaseArmor(unit)
return BlzGetUnitArmor(unit)-GetUnitBonusArmor(unit)
end
изначальная базовая защита
--изначальная базовая защита (без учета ловкости)
--дроби базовой защиты пришлось отсекать
--из-за ловкости значения могут не округляться до целых
--пример 28, а получилось 27.99. базовый параметр при расчетах получается не 0, а -0.11
function GetBasicArmor(unit)
local basic = GetUnitBaseArmor(unit)-GetHeroBaseArmor(unit)
if basic>0 then
return math.floor(basic)
elseif basic<0 then
return math.ceil(basic)
else
return basic
end
end
снижение брони
в подсказках часто вижу описание об этом.
Снижение полученного урона за единицу брони:
Damage Reduction = Multiplier * Armor / (1 + Multiplier * Armor);
где Multiplier - это значение из Gameplay Constants - Combat - Armor Damage Reduction Multiplier, по умолчанию равное 0.06
Damage Reduction = Multiplier * Armor / (1 + Multiplier * Armor);
где Multiplier - это значение из Gameplay Constants - Combat - Armor Damage Reduction Multiplier, по умолчанию равное 0.06
Пришлось повозиться с этой штукой. Эта формула работает только при положительном armor. При отрицательном armor там какая то другая формула. И еще ограничение выпирается до ?1% судя по инфе интерфейса, но так ли не знаю.
--формула снижения армора
--https://xgm.guru/p/wc3/get-unit-armor
function GetDamageReduction(unit)
local armor = BlzGetUnitArmor(unit)
local reduction = 0
if armor>0 then
reduction = Multiplier * armor / (1 + Multiplier * armor)
elseif armor<0 then
reduction = (1 - Multiplier) ^ (-armor) - 1
end
return reduction
end
регенерация здоровья
базовая регенерация здоровья
можно определить базовый реген. и даже изменить его без проблем с помощью поля (филда).
--base regen hp/sec
function GetUnitBaseRegenHP(unit)
return BlzGetUnitRealField(unit, UNIT_RF_HIT_POINTS_REGENERATION_RATE)
end
function SetUnitBaseRegenHP(unit, value)
BlzSetUnitRealFieldBJ( unit, UNIT_RF_HIT_POINTS_REGENERATION_RATE, value )
end
бонусная регенерация здоровья от модификатора-6 из BonusMod
--bonus regen hp/sec
function GetUnitBonusRegenHP(unit)
return UnitGetBonus (unit, 6)
end
function SetUnitBonusRegenHP(unit, value)
return UnitSetBonus (unit, 6, value)
end
регенерация от силы
--константа
RegenHpBonusPerStrength = 0.05
--regen hp/sec от strength
function GetHeroRegenHP(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroStr(hero, true)*RegenHpBonusPerStrength
else
return 0
end
end
ОБЩИЙ РЕГЕН
--общий regen hp/sec
function GetUnitGeneralBonusRegenHP(unit)
return GetUnitBaseRegenHP(unit) + GetHeroRegenHP(unit) + GetUnitBonusRegenHP(unit)
end
регенерация маны
базовая регенерация маны
тоже как и в здоровье можно менять с помощью поля (филда)
--base regen mana/sec
function GetUnitBaseRegenMana(unit)
return BlzGetUnitRealField(unit, UNIT_RF_MANA_REGENERATION)
end
function SetUnitBaseRegenMana(unit, value)
return BlzSetUnitRealField( unit, UNIT_RF_MANA_REGENERATION, value )
end
бонусная регенерация от интеллекта
--константа
RegenManaBonusPerInt = 0.05
--regen mana/sec от intellect
function GetHeroRegenMana(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroInt(hero, true)*RegenManaBonusPerInt
else
return 0
end
end
процентное увеличение регенерации от маски соби
тут модификатор-7 работает на абилках из маски соби
--procent от mana regen
function GetUnitBonusProcentRegenMana(unit)
return UnitGetBonus (unit, 7)/100 --возвращает целые
end
function SetUnitBonusProcentRegenMana(unit,value)
return UnitGetBonus (unit, 7,R2I(value*100))
end
function GetUnitBonusRegenMana(unit)
return (GetHeroRegenMana(unit) + GetUnitBaseRegenMana(unit)) * GetUnitBonusProcentRegenMana(unit)
end
общая регенерация маны
--общий бонус регена (полезен для героев)
function GetUnitGeneralBonusRegenMana(unit)
return GetHeroRegenMana(unit)+GetUnitBonusRegenMana(unit)
end
--общий реген маны
function GetUnitRegenMana(unit)
return GetUnitBaseRegenMana(unit)+GetUnitGeneralBonusRegenMana(unit)
end
радиус обзора
радиус обзора меняется хорошо через нативку филда
function GetUnitSightRadius(unit)
return BlzGetUnitRealField(unit, UNIT_RF_SIGHT_RADIUS)
end
function SetUnitSightRadius(unit, value)
return BlzSetUnitRealField( unit, UNIT_RF_SIGHT_RADIUS, value )
end
function GetUnitBonusSightRadius(unit)
return UnitGetBonus (unit, 8)
end
function SetUnitBonusSightRadius(unit,value)
return UnitSetBonus (unit, 8,value)
end
радиус получения атаки
function GetUnitAcquisitionRange(unit)
return BlzGetUnitRealField(unit, UNIT_RF_ACQUISITION_RANGE)
end
function SetUnitAcquisitionRange(unit,value)
return BlzSetUnitRealField(unit, UNIT_RF_ACQUISITION_RANGE,value)
end
оказывается в редакторе уже существовали нативки. просто нигде у меня не находили свое применение
native GetUnitAcquireRange takes unit whichUnit returns real
native GetUnitDefaultAcquireRange takes unit whichUnit returns real
native SetUnitAcquireRange takes unit whichUnit, real newAcquireRange returns nothing
скорость атаки
в рефордже ввели только нативку по определению/изменению базового времени задержки между атаками. И больше ничего нет. Только от этого можно отталкиваться.
native BlzGetUnitAttackCooldown takes unit whichUnit, integer weaponIndex returns real
native BlzSetUnitAttackCooldown takes unit whichUnit, real cooldown, integer weaponIndex returns nothing
пришлось вычислять. ранее, я не знал как, пока сам не прочитал. вернее, я и раньше знал, но боялся ошибиться в точности, поэтому не брался.
теория
Скорость атаки - это показатель ударов в секунду, или как часто взмахивает оружием ваш герой. Скорость атаки зависит от ловкости, аур, артефактов, скилов. Чем быстрее скорость атаки тем больше урона в определенное время наносит урона герой.
Для вывода формулы будут использованы некоторые понятия:
AS - attack speed - Скорость атаки, кол-во ударов в сек
BAS - basic attack speed - Базовая скорость атаки, кол-во ударов в сек
IAS - increase attack speed дополнительный процент. Складывается из ловкости героя и бонусов скорости атаки. Не может быть выше 400 или ниже -80. Изначально скорость не измерялась в процентах, но так пошло в варкрафте. Понижение и увеличение скорости осуществляется с помощью модификаторов-способностей. А еще дополнительно от ловкости через константы. Изначальная скорость юнитов равно 1.00 (100%). Максимум бонусом можно задать 4.00 (400%). Это в сумме: изначальная + бонусная = 100+400 = 500%. В варкрафте в максимум упирается в в этот потолок, это 5 ударов в сек. больше никак не сделать. ниже 100% нормы - уже скорость идет на понижение. самый минимальный предел = 20%. Ниже 20% никак нельзя поставить.
Складывается из ловкости героя и бонусов скорости атаки. Не может быть выше 400 или ниже -80.
Для вывода формулы будут использованы некоторые понятия:
AS - attack speed - Скорость атаки, кол-во ударов в сек
BAS - basic attack speed - Базовая скорость атаки, кол-во ударов в сек
IAS - increase attack speed дополнительный процент. Складывается из ловкости героя и бонусов скорости атаки. Не может быть выше 400 или ниже -80. Изначально скорость не измерялась в процентах, но так пошло в варкрафте. Понижение и увеличение скорости осуществляется с помощью модификаторов-способностей. А еще дополнительно от ловкости через константы. Изначальная скорость юнитов равно 1.00 (100%). Максимум бонусом можно задать 4.00 (400%). Это в сумме: изначальная + бонусная = 100+400 = 500%. В варкрафте в максимум упирается в в этот потолок, это 5 ударов в сек. больше никак не сделать. ниже 100% нормы - уже скорость идет на понижение. самый минимальный предел = 20%. Ниже 20% никак нельзя поставить.
Складывается из ловкости героя и бонусов скорости атаки. Не может быть выше 400 или ниже -80.
- 0.20 = -80% IAS <= самый минимальный результат. ниже этого нельзя поставить.
- 1.00 = 0% IAS <= изначальную скорость принята считать за 1.00 (100%)
- 2.00 = 100% IAS <= при увеличении AS на 1.00 (100%), скорость увеличилась 2.00
Delay - Базовая задержка между ударами, сек. По-другому, Delay называют базовое время атаки Base attack time, BAT. или AttackCooldown. Можно проверить таймером от замаха до замаха - это будет считаться временем. Начало замаха означает начала атаки.
Time - время задержки после добавления модификации бонусов, сек. Этот параметр добавил специально, чтобы смотреть как меняется время задержки между атаками после добавления модификаторов.
Изначально в механике игры заложен параметр задержка между ударами - Delay, а не скорость атаки.
У подавляющего большинства героев из доты Delay равен 1.7 сек, за исключением:
Magina - The Anti-Mage (Антимаг) – 1.45 сек.
Shandelzare Silkwood - The Vengeful Spirit (Венга) – 1.77 сек.
Balanar - The Night Stalker (Сталкер) – 1.8 сек.
Terrorblade - The Soul Keeper (Террорблейд) – 1.5 сек.
Чтобы рассчитать скорость атаки - AS, нам необходимо знать BAS и IAS героя:
Чтобы вычислить базовую скорость атаки (BAS), нужно количество выстрелов (ударов) разделить на время, за которое они произведены. За основу мы берем единицу, т.е. один удар, которым совершаем атаку за определенное время. То есть мы должны 1 разделить на Delay, так как пауза между выстрелами (ударами) равна 1.7 сек., отсюда: BAS =1/Delay=1/1.7 ≈ 0.6 выстрелов в секунду. Для вышеуказанных героев с отличающимися задержками от стандартной, все рассчитывается точно так же по формуле BAS =1/Delay.
IAS - дополнительный процент – процент увеличения скорости атаки, равен сумме процентов от ловкости, артефактов, умений, наложенных заклинаний и аур.
Измеряется IAS в % и подразделяется как бы на 2е группы:
Time - время задержки после добавления модификации бонусов, сек. Этот параметр добавил специально, чтобы смотреть как меняется время задержки между атаками после добавления модификаторов.
Изначально в механике игры заложен параметр задержка между ударами - Delay, а не скорость атаки.
У подавляющего большинства героев из доты Delay равен 1.7 сек, за исключением:
Magina - The Anti-Mage (Антимаг) – 1.45 сек.
Shandelzare Silkwood - The Vengeful Spirit (Венга) – 1.77 сек.
Balanar - The Night Stalker (Сталкер) – 1.8 сек.
Terrorblade - The Soul Keeper (Террорблейд) – 1.5 сек.
Чтобы рассчитать скорость атаки - AS, нам необходимо знать BAS и IAS героя:
Чтобы вычислить базовую скорость атаки (BAS), нужно количество выстрелов (ударов) разделить на время, за которое они произведены. За основу мы берем единицу, т.е. один удар, которым совершаем атаку за определенное время. То есть мы должны 1 разделить на Delay, так как пауза между выстрелами (ударами) равна 1.7 сек., отсюда: BAS =1/Delay=1/1.7 ≈ 0.6 выстрелов в секунду. Для вышеуказанных героев с отличающимися задержками от стандартной, все рассчитывается точно так же по формуле BAS =1/Delay.
IAS - дополнительный процент – процент увеличения скорости атаки, равен сумме процентов от ловкости, артефактов, умений, наложенных заклинаний и аур.
Измеряется IAS в % и подразделяется как бы на 2е группы:
- IAS от ловкости. Каждая единица ловкости увеличивает IAS на 1%. (Например, у героя ловкость равна 24, тогда IAS от ловкости = 24*1%=24%). (0.01) 1% взят из констант доты. В варкрафте значение это мб другим, оно равно 0.02 за каждую ловкость
- IAS от артефактов, умений, наложенных заклинаний и аур. Сразу указан в % и не тр***ет дополнительных расчетов. Все IAS складываются между собой. (Например, IAS от ловкости = 30%, IAS от Power treads = 30%, следовательно, общий (суммарный) IAS (Σ IAS)) = 60%
Получается вот такая формула подсчета скорости:
AS = BAS* (1 + Σ IAS)=1/Delay*(1 + Σ IAS)
Примеры:
Silencer с ловкостью в 20 ед., тогда:
Σ IAS = 20 * 1% = 20%,
AS = 0.6 * (1+ 20%) ≈ 0,7 выстрелов (ударов) в секунду
Time = Delay / (1+ 20%) = 1.7 / 1.2 % = 1.4 сек - задержка между ударами
Axe с Power treads и MKB, ловкость = 35, тогда:
Σ IAS = 35 * 1% + 30% + 15% = 80%,
AS = 0.6* (1+80%) ≈ 1.1 выстрел (удар) в секунду
Time = Delay / (1+80%) = 1.7 / 1.8 % = 0.94 сек - задержка между ударами
AS = BAS* (1 + Σ IAS)=1/Delay*(1 + Σ IAS)
Примеры:
Silencer с ловкостью в 20 ед., тогда:
Σ IAS = 20 * 1% = 20%,
AS = 0.6 * (1+ 20%) ≈ 0,7 выстрелов (ударов) в секунду
Time = Delay / (1+ 20%) = 1.7 / 1.2 % = 1.4 сек - задержка между ударами
Axe с Power treads и MKB, ловкость = 35, тогда:
Σ IAS = 35 * 1% + 30% + 15% = 80%,
AS = 0.6* (1+80%) ≈ 1.1 выстрел (удар) в секунду
Time = Delay / (1+80%) = 1.7 / 1.8 % = 0.94 сек - задержка между ударами
базовый IAS
изначально равно 100%
--IAS - показывает % процентное содержание AS
function GetUnitBaseIAS(unit)
return 1.00 --изначально AS равна 1.00 (100%)
end
базовая скорость AS (при base IAS = 100%)
тут base AS=1/ base BAT
--BAS - базовая скорость атаки, показывает кол-во ударов в сек
function GetUnitBaseAttackSpeed(unit, index)
if BlzGetUnitAttackCooldown(unit, index) ~= 0 then
return 1/BlzGetUnitAttackCooldown(unit, index)
else
return 0
end
end
bonus IAS от ловкости
--константа
AttackSpeedBonusPerAgilityPoint = 0.02
--IAS - показывает %-ый бонус от ловкости героя
function GetUnitAgilityBonusIAS(unit)
if IsUnitType(unit, UNIT_TYPE_HERO) then
return (GetHeroAttributeAgi(unit, true) * AttackSpeedBonusPerAgilityPoint) --0.02% бонуса AS за каждую единицу ловкости
else
return 0
end
end
IAS от модификатора-9 из BonusMod
--bonus IAS - показывает процент AS от абилок
--делим на 100 тк результат из BonusMod выдают в виде целых чисел
function GetUnitBonusIAS(unit)
return (UnitGetBonus (unit, 9) / 100)
end
function SetUnitBonusIAS(unit,value)
return (UnitSetBonus (unit, 9, R2I(value*100)))
end
общий бонусный IAS (значение этого параметра ограничены от -0.80 до 4.00)
--общий бонус. лимитирован от -80% до 400%
function GetGeneralUnitBonusIAS(unit)
local bonus = GetUnitAgilityBonusIAS(unit) + GetUnitBonusIAS(unit)
if bonus > 4.00 then
return 4.00
elseif bonus < -0.80 then
return -0.80
end
return bonus
end
суммарный IAS (base+bonus)
--показывает общий суммарный IAS в %
function GetUnitIncreaseAttackSpeed(unit, includeBonuses)
if includeBonuses then
return GetUnitBaseIAS(unit) + GetGeneralUnitBonusIAS(unit)
else
return GetUnitBaseIAS(unit)
end
end
AS
--AS выдает кол-во ударов в сек
function GetUnitCurrentAttackSpeed(unit, index)
return GetUnitBaseAttackSpeed(unit, index) * GetUnitIncreaseAttackSpeed(unit, true)
end
AttackTime
--время задержки для атаки
function GetUnitCurrentAttackTime(unit, index)
if GetUnitIncreaseAttackSpeed(unit, true) ~= 0 then
return BlzGetUnitAttackCooldown(unit, index) / GetUnitIncreaseAttackSpeed(unit, true)
else
return 0
end
end
хп/мана
function SetUnitHP(unit,value)
SetUnitState(unit, UNIT_STATE_LIFE, RMaxBJ(0,value))
end
function SetUnitMana(unit,value)
SetUnitState(unit, UNIT_STATE_MANA, RMaxBJ(0,value))
end
макс хп/макс мана
тут в рефордже завезли новые функции на определение/изменение макс запасов хп и маны. так что сами решайте. Можете использовать модификаторы-10 и 11 из BonusMod или этими нативками.
native BlzGetUnitMaxHP takes unit whichUnit returns integer
native BlzSetUnitMaxHP takes unit whichUnit, integer hp returns nothing
native BlzGetUnitMaxMana takes unit whichUnit returns integer
native BlzSetUnitMaxMana takes unit whichUnit, integer mana returns nothing
function GetHeroBaseMaxHP(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroStr(hero, true)*HitPointBonusPerStrength
else
return 0
end
end
function GetHeroBaseMaxMana(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return GetHeroInt(hero, true)*ManaPointBonusPerInt
else
return 0
end
end
function GetUnitBonusMaxHP(unit)
return UnitGetBonus (unit, 10)
end
function GetUnitBaseMaxHP(unit)
return BlzGetUnitMaxHP(unit)-(GetHeroBaseMaxHP(unit)+GetUnitBonusMaxHP(unit))
end
function GetUnitBonusMaxMana(unit)
return UnitGetBonus (unit, 11)
end
function GetUnitBaseMaxMana(unit)
return BlzGetUnitMaxMana(unit)-(GetHeroBaseMaxMana(unit)+GetUnitBonusMaxMana(unit))
end
уровни апгрейдов урона/брони
можно вычислить с помощью фреймов
BlzGetFrameByName("InfoPanelIconLevel",0) - 1 атака
BlzGetFrameByName("InfoPanelIconLevel",1) - 2 атака
BlzGetFrameByName("InfoPanelIconLevel",2) - броня
BlzGetFrameByName("InfoPanelIconLevel",0) - 1 атака
BlzGetFrameByName("InfoPanelIconLevel",1) - 2 атака
BlzGetFrameByName("InfoPanelIconLevel",2) - броня
--пример
if BlzFrameGetText(BlzGetFrameByName("InfoPanelIconLevel",0)))>0 then
end
как определить уровень апгрейда атаки/защиты
такой нативки в рефе к сожалению нет. и филдов тоже не прилагается (искал, но такая информация не является характеристикой юнита, а скорее игрока). Только или костыльным способом или через бд
прочесть из фрейма
можно прочесть из фреймов. Когда вы выделяете юнита, то можете прочесть уровень.
Раньше так я думал, что проще всего для отображения всех данных BonusMode, проверяя работу созданных мной кастомных функции. Честно, апгрейды атаки/защиты ни на что не влияли. Просто показать эффект решил. Хотелось найти идеального и безопасного решения, но так и не нашел тогда. И чтение инфы с фрейма не точная, у вас должен быть видим
Заметка: обращение к данным фрейма не всегда безопасно: там может быть ничего не указано (пример, если выбрать героя, то у него не указаны апгрейды атаки, как у пехотинца), либо фрейм SimpleInfoPanelUnitDetail не видим (достаточно выделить несколько юнитов, и панель SimpleInfoPanelUnitDetail с дочерними фреймами станет невидимым => ничего оттуда не получишь. При выделении несколько юнитов, например, у вас отображается другая панель => групповая, и одиночная панель SimpleInfoPanelUnitDetail будет скрыта ).
Еще помните, что это дочерние фреймы SimpleInfoPanelUnitDetail являются не полноценными simpleframes, т.е. простыми строками string. Игра не любит, если вы используете ниже перечисленнные natives на строках(String) /текстурах(Texture), игра вылетает:
Еще помните, что это дочерние фреймы SimpleInfoPanelUnitDetail являются не полноценными simpleframes, т.е. простыми строками string. Игра не любит, если вы используете ниже перечисленнные natives на строках(String) /текстурах(Texture), игра вылетает:
BlzFrameSetVisible
BlzFrameIsVisible
BlzFrameSetAlpha
BlzFrameSetLevel
BlzFrameIsVisible
BlzFrameSetAlpha
BlzFrameSetLevel
Но зато вы можете получить string с помощью BlzFrameGetText(frame), если есть что прочесть. Но перед этим лучше проверяйте видим ли родитель SimpleInfoPanelUnitDetail. А еще проверить, что в строке есть какая-то запись. Но в основном это не всегда можно получать так информацию.
local syncTrigger_techArmor = CreateTrigger()
for int = 0, bj_MAX_PLAYERS - 1 do
BlzTriggerRegisterPlayerSyncEvent(syncTrigger_techArmor, Player(int), "IsCursorMouseInGameZone", false)
end
TriggerAddAction(syncTrigger_techArmor, function()
local str = BlzGetTriggerSyncPrefix()
local n = BlzGetTriggerSyncData()
local length_str = #str
local start_pos, end_pos = str:find('tech_armor_')
local substring = string.sub(str, end_pos+1)
print('level tech armor: '..substring..' у игрока-'..n)
n = tonumber(n)
local tech_lv_armor = tonumber(substring)
if tech_lv_armor>0 then
--иконка улучшения
infopanel[n].tech_level_armor=tech_lv_armor
--иконка типа армора
infopanel[n].icon_armor = ARMOR_ICON_WITH_UPGRAID[infopanel[n].type_armor]
if GetLocalPlayer()==Player(n) then
--изменяем текстуру
BlzFrameSetTexture(infopanel[n].TextureArmor, infopanel[n].icon_armor,0, true)
--обновляем tech
BlzFrameSetText(infopanel[n].TechArmor, infopanel[n].tech_level_armor)
BlzFrameSetVisible(infopanel[n].TechArmor, true)
end
else
infopanel[n].tech_level_armor=0
infopanel[n].icon_armor = ARMOR_ICON[infopanel[n].type_armor]
if GetLocalPlayer()==Player(n) then
--изменяем текстуру
BlzFrameSetTexture(TextureArmor,infopanel[n].icon_armor,0, true)
--обновляем tech
BlzFrameSetVisible(infopanel[n].TechArmor, false)
end
end
end)
if BlzFrameIsVisible(BlzGetFrameByName("SimpleInfoPanelUnitDetail",0)) then
local tech_lv_armor = BlzFrameGetText(BlzGetFrameByName("InfoPanelIconLevel",2))
if tech_lv_armor then
tech_lv_armor = tonumber(tech_lv_armor)
--в луа проще проверять по типу. тк пустая строка "" и nil => есть отличия.
if type(tech_lv_armor)=='number' then
print(tostring('tech lv armor: '..tech_lv_armor))
if tech_lv_armor>0 then
BlzSendSyncData("tech_armor_"..tech_lv_armor, n)
end
end
end
end
бд
Второй способ это создать бд. Как правило, в механики игры любая технология привязана к игроку. Если изучает красный, все апгрейды будут на юнитах красного игрока действовать. А если передать эти войска синему игроку, который не изучал технологии, то апгрейды с войск сбрасываются.
проще привязать апгрейды игрока к конкретным типам юнитов.
код-1 динамичная бд
do
local real = MarkGameStarted
function MarkGameStarted()
real()
LEVEL_TECH_DAMAGE_OF_UNIT = {}
LEVEL_TECH_ARMOR_OF_UNIT = {}
for a=1,12 do
LEVEL_TECH_DAMAGE_OF_UNIT[a] = {}
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hfoo')]=0
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hrif')]=0
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hmtm')]=0
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hkni')]=0
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hgry')]=0
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('ufro')]=0
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('emtg')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a] = {}
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hfoo')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hrif')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hmtm')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hkni')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hgry')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('ufro')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('emtg')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hbla')]=0
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hhou')]=0
end
trigger_player_research_finish = CreateTrigger()
TriggerAddAction( trigger_player_research_finish, function()
local techid = GetResearched()
local current_lv_tech = GetPlayerTechCount(GetTriggerPlayer(), techid, true)
local max_lv_tech = GetPlayerTechMaxAllowed(GetTriggerPlayer(), techid)
if techid == FourCC('Rhme') then --железные мечи
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hfoo')]=current_lv_tech
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hkni')]=current_lv_tech
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hgry')]=current_lv_tech
elseif techid == FourCC('Rhra') then --черный порох
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hrif')]=current_lv_tech
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('hmtm')]=current_lv_tech
elseif techid == FourCC('Rhar') then --железные щиты
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hfoo')]=current_lv_tech
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hkni')]=current_lv_tech
elseif techid == FourCC('Rhla') then --поклепанная кожа
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hrif')]=current_lv_tech
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hmtm')]=current_lv_tech
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hgry')]=current_lv_tech
elseif techid == FourCC('Rhac') then --каменная укладка
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hbla')]=current_lv_tech
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('hhou')]=current_lv_tech
elseif techid == FourCC('Resw') then --сила леса
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('emtg')]=current_lv_tech
elseif techid == FourCC('Rerh') then --прочные шкуры
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('emtg')]=current_lv_tech
elseif techid == FourCC('Rura') then --атака чудовищ
LEVEL_TECH_DAMAGE_OF_UNIT[a][FourCC('ufro')]=current_lv_tech
elseif techid == FourCC('Rucr') then --броня чудовищ
LEVEL_TECH_ARMOR_OF_UNIT[a][FourCC('ufro')]=current_lv_tech
end
end)
end
end
код-2
или досточно знать на каких юнитов действует апгрейд. Узнаете какая технология улучшит ту или ную характеристику. Пример, урон пехотинца улучшается после изучения железных мечей в кузнице. Можно просто заполнить бд на каждую характеристику. И потом по current_lv_tech = GetPlayerTechCount(GetTriggerPlayer(), techid, true) узнать уровень
TECH_DAMAGE_OF_UNIT = {}
TECH_ARMOR_OF_UNIT = {}
TECH_DAMAGE_OF_UNIT[FourCC('hfoo')]='Rhme' --железные мечи
TECH_DAMAGE_OF_UNIT[FourCC('hkni')]='Rhme'
TECH_DAMAGE_OF_UNIT[FourCC('hgry')]='Rhme'
TECH_DAMAGE_OF_UNIT[FourCC('hrif')]='Rhra' --черный порох
TECH_DAMAGE_OF_UNIT[FourCC('hmtm')]='Rhra'
TECH_DAMAGE_OF_UNIT[FourCC('ufro')]='Rura' --атака чудовищ
TECH_DAMAGE_OF_UNIT[FourCC('emtg')]='Resw' --сила леса
TECH_ARMOR_OF_UNIT[FourCC('hfoo')]='Rhar' --железные щиты
TECH_ARMOR_OF_UNIT[FourCC('hkni')]='Rhar'
TECH_ARMOR_OF_UNIT[FourCC('hrif')]='Rhla' --поклепанная кожа
TECH_ARMOR_OF_UNIT[FourCC('hmtm')]='Rhla'
TECH_ARMOR_OF_UNIT[FourCC('hgry')]='Rhla'
TECH_ARMOR_OF_UNIT[FourCC('ufro')]='Rucr' --броня чудовищ
TECH_ARMOR_OF_UNIT[FourCC('emtg')]='Rerh' --прочные шкуры
TECH_ARMOR_OF_UNIT[FourCC('hbla')]='Rhac' --каменная укладка
TECH_ARMOR_OF_UNIT[FourCC('hhou')]='Rhac'
тип атаки
-- 0 - normal (skills), 1 - melee, 2 - pierce, 3 - siege, 4 - magic,5 - chaos,6 - hero
function GetUnitAttackType(unit,index)
return BlzGetUnitWeaponIntegerField(unit, UNIT_WEAPON_IF_ATTACK_ATTACK_TYPE, index)
end
тип защиты
типы защиты
- 0 - small (легкая)
- 1 - medium (средняя)
- 2 - large (тяжелая)
- 3 - fort (укрепленная)
- 4 norm
- 5 - hero
- 6 - divine
- 7 - None (без брони)
-- defense type
DEFENSE_TYPE_LIGHT = ConvertDefenseType(0)
DEFENSE_TYPE_MEDIUM = ConvertDefenseType(1)
DEFENSE_TYPE_LARGE = ConvertDefenseType(2)
DEFENSE_TYPE_FORT = ConvertDefenseType(3)
DEFENSE_TYPE_NORMAL = ConvertDefenseType(4)
DEFENSE_TYPE_HERO = ConvertDefenseType(5)
DEFENSE_TYPE_DIVINE = ConvertDefenseType(6)
DEFENSE_TYPE_NONE = ConvertDefenseType(7)
function GetUnitDefenseType(unit)
return BlzGetUnitIntegerField(unit, UNIT_IF_DEFENSE_TYPE)
end
макс требуемый опыт для повышения уровня
--константы
NeedHeroXP = 200
NeedHeroXPFormulaA = 1.00
NeedHeroXPFormulaB = 100
NeedHeroXPFormulaC = 0
--макс опыт
function GetHeroMaxXP(hero)
local level = GetUnitLevel(hero)
local need = 0
for i=1, level do
need = need * NeedHeroXPFormulaA + NeedHeroXPFormulaB * (i+1) + NeedHeroXPFormulaC
end
return need
end
Базовые параметры
функции для табличных параметров
были созданы отдельный custom cript, где осуществляется работа полностью с basic и base параметрами. Может быть это бесполезно, но сделан как пример, в base записываются базовые параметры. Изначально только их можно и было использовать. У каждого юнита по каждому параметру (сила, ловкость, интеллект, урон, защита и пр) была своя таблица base, с помощью которой можно было изменять, либо узнавать текущий базовый параметр.
Несмотря на то, что многие параметры итак можно узнать нативным способом, через нативки. Но не у всех, конечно. Некоторые параметры требуют более точного ответа. Хотя я не могу вспомнить зачем, но зачем то я это сделал. Видать мне очень не давало покоя.
В дальнейшем нужно было еще добавить в качестве примера кнопку сброса. Я думал, что круто сбросить параметр к изначальному значению. И в результате появилась, еще одна группа таблиц basic на каждый параметр. Это изначальные значения каждого параметра, заданного в редакторе объектов. Пример, если задать юниту в ро +2 базовая защиты, при создании у него будет изначально +2 базового армора. Я не знал, как вычислить, тк таких нативок нет в рефе. Или они не могут читать данные с ро. не все филды есть, или не работают. Этот армор можно будет изменить в игре через триггеры, тогда как вернуть как было?
Самое простое это забивать бд для каждого юнита каждую характеристику. Это вообще труд. Хотел подобрать набор api функции. придумать адекватную систему для пользователя, чтобы ему не нужно было ничего забивать в BonusMode. Хитрым способом мной был придуман способ: при появлении нового созданного юнита на карте сразу же записываем его характеристики, потом они возможно динамично изменяется игрой.
В результате этого весь расчет идет от basic. Есть зависимость. Теперь, base означает насколько изменилась число по сравнению с basic. Если значение value увеличивается, то прибавляем к base. Если значение value уменьшается, то убавляем base.
Можно add/sub => base param = basic + (base+value)
Можно add/sub => base param = basic + (base+value)
То есть базовый параметр, это сумма base и basic. base изначально равен 0, но если параметр хоть как-то менялся, то он будет не равно ноль.
get => base param = base + basic
get => base param = base + basic
Совсем по-другому будет установить значение set, в отличии от add/sub. Но там другая формула:
base = value-basic
Пример:
basic = 20
установить base 30
base = 30-20 = 10
base = value-basic
Пример:
basic = 20
установить base 30
base = 30-20 = 10
Пример:
basic = 10
установить base 15
base = 10-15 = -5
basic = 10
установить base 15
base = 10-15 = -5
полная формула: base param = basic + (value-basic)
полный код
do
local InitGlobalsOrigin = InitGlobals
function InitGlobals()
InitGlobalsOrigin()
param = {}
--base означает насколько изменилась число по сравнению с basic.
param.base = {}
param.base.str = {} --hero attribute 1-3
param.base.agi = {}
param.base.int = {}
param.base.dmg1 = {} --dmg 4
param.base.dmg2 = {}
param.base.arm = {} --armor 5
param.base.regenhp = {} --regeneration hp 6
param.base.regenmana = {} --regeneration mana 7
param.base.sight = {} --sight 8
param.base.bat1 = {}
param.base.bat2 = {}
param.base.maxhp = {} -- max life 10
param.base.maxmana = {} -- max mana 11
param.base.move = {} -- move speed 12
param.base.acquisition = {}
--basic - стартовые параметры (нужны для сброса)
--поскольку не ко всем полям бд можножно получить, то заводим эти basic. При создании юнита высчитываем изначальный параметр
param.basic = {}
param.basic.str = {} --hero attribute 1-3
param.basic.agi = {}
param.basic.int = {}
param.basic.dmg1 = {}
param.basic.dmg2 = {}
param.basic.arm = {}
param.basic.regenhp = {}
param.basic.regenmana = {}
param.basic.bat1 = {}
param.basic.bat2 = {}
param.basic.maxhp = {}
param.basic.maxmana = {}
param.basic.sight = {}
param.basic.move = {}
param.basic.acquisition = {}
--эти три функции атрибута нужны, чтобы сбросить базовый параметр
--суммарная расчетная базовая сила за каждый уровень
--param.basic.str записан дополнительный атрибут GetBaseParamStr(u), если он есть
function GetBaseParamStr(u)
local h = GetHandleId(u)
if IsUnitType(u, UNIT_TYPE_HERO) then
return param.basic.str[h]+GetHeroStrPerLevel(u)*(GetHeroLevel(u)-1)
else
return 0
end
end
--суммарная расчетная базовая ловкость за каждый уровень
--param.basic.agi записан дополнительный атрибут GetBaseParamAgi(u), если он есть
function GetBaseParamAgi(u)
local h = GetHandleId(u)
if IsUnitType(u, UNIT_TYPE_HERO) then
return param.basic.agi[h]+GetHeroAgiPerLevel(u)*(GetHeroLevel(u)-1)
else
return 0
end
end
--суммарный базовый расчетный интеллект за каждый уровень
--param.basic.int записан дополнительный атрибут GetBaseParamInt(u), если он есть
function GetBaseParamInt(u)
local h = GetHandleId(u)
if IsUnitType(u, UNIT_TYPE_HERO) then
return param.basic.int[h]+GetHeroIntPerLevel(u)*(GetHeroLevel(u)-1)
else
return 0
end
end
--базовый армор от суммарной расчетной базовой ловкости за каждый уровень
function GetHeroBaseParamArmor(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
return (GetBaseParamAgi(hero)*DefenseBonusPerAgilityPoint)+DefenseBaseValue
else
return 0
end
end
--основной базовый аттрибут. тут расчеты каждого атрибута берутся за каждый уровень
function GetHeroBaseParamPrimaryAttribute(hero)
if IsUnitType(hero, UNIT_TYPE_HERO) then
if GetHeroPrimaryAttribute(hero) == 1 then --str
return GetBaseParamStr(hero)
elseif GetHeroPrimaryAttribute(hero) == 2 then --int
return GetBaseParamInt(hero)
elseif GetHeroPrimaryAttribute(hero) == 3 then --agi
return GetBaseParamAgi(hero)
end
else
return 0
end
end
--базовый урон: урон из ро + основный аттрибут. Внимание: апгрейды не учел в param.basic.dmg1 или param.basic.dmg2. Но нужно их тоже засчитать
function GetUnitBasicParamDamage(unit,index)
local h = GetHandleId(unit)
if index == 0 then
return GetHeroBaseParamPrimaryAttribute(unit)+param.basic.dmg1[h]
elseif index == 1 then
return GetHeroBaseParamPrimaryAttribute(unit)+param.basic.dmg2[h]
else
return 0
end
end
--суммарный basic армор: базовый армор от ловкости +армор из ро. Внимание: апгрейды не учел в param.basic.arm. Но нужно их тоже засчитать
function GetUnitBasicParamArmor(unit)
local h = GetHandleId(unit)
return GetHeroBaseParamArmor(unit)+param.basic.arm[h]
end
--базовая аремя атаки юнита изначальная
function GetUnitBasicParamBAT(unit,index)
local h = GetHandleId(unit)
if index == 0 then
return param.basic.bat1[h]
elseif index == 1 then
return param.basic.bat2[h]
else
return 0
end
end
--базовая скорость атаки юнита изначальная
function GetUnitBasicParamAS(unit, index)
local cooldawn = 0
local h = GetHandleId(unit)
if index == 0 then
cooldawn = param.basic.bat1[h]
elseif index == 1 then
cooldawn = param.basic.bat2[h]
end
if cooldawn ~= 0 then
return 1/cooldawn
else
return 0
end
end
--регистрируем на карте имеющих юнитов
local group_param = CreateGroup()
TimerStart(CreateTimer(),0.03,false,function()
GroupEnumUnitsInRect(group_param, bj_mapInitialPlayableArea, nil)
ForGroup(group_param,function()
local u = GetEnumUnit()
local h = GetHandleId(u)
if IsUnitType(u, UNIT_TYPE_HERO) then
param.basic.str[h] = GetBasicParamStr(u)
param.basic.agi[h] = GetBasicParamAgi(u)
param.basic.int[h] = GetBasicParamInt(u)
print(param.basic.str[h])
end
param.basic.dmg1[h]=GetUnitBasicDamage(u,0)
param.basic.dmg2[h]=GetUnitBasicDamage(u,1)
param.basic.arm[h]=GetBasicArmor(u)
param.basic.regenhp[h]= GetUnitBaseRegenHP(u)
param.basic.regenmana[h]= GetUnitBaseRegenMana(u)
param.basic.bat1[h]=BlzGetUnitAttackCooldown(u,0)
param.basic.bat2[h]=BlzGetUnitAttackCooldown(u,1)
param.basic.maxhp[h]=GetUnitBaseMaxHP(u)
param.basic.maxmana[h]=GetUnitBaseMaxMana(u)
param.basic.move[h]=GetUnitDefaultMoveSpeed(u)
param.basic.sight[h] = GetUnitSightRadius(u)
param.basic.acquisition[h]=GetUnitAcquisitionRange(u)
--эти динамичные базовые параметры, которые можно изменить
--показывают сколько вы хотите добавить base очков параметра
param.base.str[h]=0
param.base.agi[h]=0
param.base.int[h]=0
param.base.dmg1[h]=0
param.base.dmg2[h]=0
param.base.arm[h]=0
param.base.regenhp[h] = 0
param.base.regenmana[h] = 0
param.base.bat1[h] = 0
param.base.bat2[h] = 0
param.base.sight[h] = 0
param.base.maxhp[h] = 0
param.base.maxmana[h] = 0
param.base.move[h] = 0
param.base.acquisition[h]=0
end)
print("кол-во юнитов на карте: "..BlzGroupGetSize(general_group))
DestroyTimer(GetExpiredTimer())
end)
--регистрируем триггер на появление юнитов
local trigger = CreateTrigger() --триггер добавления юнитов
TriggerRegisterEnterRectSimple( trigger, bj_mapInitialPlayableArea )
TriggerAddCondition(trigger, Condition( function()
return not IsUnitInGroup(GetTriggerUnit(), group_param)
end) )
TriggerAddAction(trigger,function()
local u = GetTriggerUnit()
local h = GetHandleId(u)
if IsUnitType(u, UNIT_TYPE_HERO) then
param.basic.str[h] = GetBasicParamStr(u)
param.basic.agi[h] = GetBasicParamAgi(u)
param.basic.int[h] = GetBasicParamInt(u)
end
param.basic.dmg1[h]=GetUnitBasicDamage(u,0)
param.basic.dmg2[h]=GetUnitBasicDamage(u,1)
param.basic.arm[h]=GetBasicArmor(u)
param.basic.regenhp[h]= GetUnitBaseRegenHP(u)
param.basic.regenmana[h]= GetUnitBaseRegenMana(u)
param.basic.bat1[h]=BlzGetUnitAttackCooldown(u,0)
param.basic.bat2[h]=BlzGetUnitAttackCooldown(u,1)
param.basic.maxhp[h]=GetUnitBaseMaxHP(u)
param.basic.maxmana[h]=GetUnitBaseMaxMana(u)
param.basic.move[h]=GetUnitDefaultMoveSpeed(u)
param.basic.sight[h] = GetUnitSightRadius(u)
param.basic.acquisition[h]=GetUnitAcquisitionRange(u)
--эти динамичные базовые параметры, которые можно изменить
--инициируем бд для созданного
param.base.str[h]=0
param.base.agi[h]=0
param.base.int[h]=0
param.base.dmg1[h]=0
param.base.dmg2[h]=0
param.base.arm[h]=0
param.base.regenhp[h] = 0
param.base.regenmana[h] = 0
param.base.bat1[h] = 0
param.base.bat2[h] = 0
param.base.sight[h] = 0
param.base.maxhp[h] = 0
param.base.maxmana[h] = 0
param.base.move[h] = 0
param.base.acquisition[h]=0
GroupAddUnit(group_param,u)
end)
--это функция добавления была создана для ввода базового модификатора в чат
--index атаки моэно не прописывать, пример: UnitAddBase(unit,mod,value)
function UnitAddBase(unit,mod,value,index)
if type(mod) ~= 'number' or type(value) ~= 'number' then
return false
elseif (mod == 4 or mod == 9) and type(index) ~= 'number' then
return false
elseif GetUnitTypeId (unit) == 0 or IsUnitType (unit, UNIT_TYPE_DEAD) then
return false
elseif mod > 0 and mod < 4 then
if not IsUnitType(unit, UNIT_TYPE_HERO) then
print('UnitSetBonus: you cant give the ability to a non-hero')
return false
end
end
local h = GetHandleId(unit)
if mod == 1 then
param.base.str[h]=param.base.str[h]+value
SetHeroBaseStr(unit, R2I(RoundEx(GetBaseParamStr(unit)+param.base.str[h])))
elseif mod == 2 then
param.base.agi[h]=param.base.agi[h]+value
SetHeroBaseAgi(unit, R2I(RoundEx(GetBaseParamAgi(unit)+param.base.agi[h])))
elseif mod == 3 then
param.base.int[h]=param.base.int[h]+value
SetHeroBaseInt(unit, R2I(RoundEx(GetBaseParamInt(unit)+param.base.int[h])))
elseif mod == 4 then
if index == 0 then
param.base.dmg1[h]=param.base.dmg1[h]+value
BlzSetUnitBaseDamage(unit,R2I(RoundEx(GetUnitBasicParamDamage(unit,index)+param.base.dmg1[h])),index)
elseif index == 1 then
param.base.dmg2[h]=param.base.dmg2[h]+value
BlzSetUnitBaseDamage(unit,R2I(RoundEx(GetUnitBasicParamDamage(unit,index)+param.base.dmg2[h])),index)
end
elseif mod == 5 then
param.base.arm[h]=param.base.arm[h]+value
BlzSetUnitArmor(unit, GetUnitBasicParamArmor(unit)+param.base.arm[h])
elseif mod == 6 then
param.base.regenhp[h]=param.base.regenhp[h]+value
SetUnitBaseRegenHP(unit, param.basic.regenhp[h]+param.base.regenhp[h])
elseif mod == 7 then
param.base.regenmana[h]=param.base.regenmana[h]+value
SetUnitBaseRegenMana(unit, param.basic.regenmana[h]+param.base.regenmana[h])
elseif mod == 8 then
param.basic.sight[h] = param.basic.sight[h]+value
SetUnitSightRadius(unit,param.basic.sight[h]+param.base.sight[h])
elseif mod == 9 then
if index == 0 then
param.base.bat1[h] = param.base.bat1[h] + value
BlzSetUnitAttackCooldown(unit,param.basic.bat1[h]+param.base.bat1[h],index)
elseif index == 1 then
param.base.bat2[h] = param.base.bat2[h] + value
BlzSetUnitAttackCooldown(unit,param.basic.bat2[h]+param.base.bat2[h],index)
end
elseif mod == 10 then
param.base.maxhp[h]= param.base.maxhp[h]+value
BlzSetUnitMaxHP(unit,R2I(RoundEx(GetHeroBaseMaxHP(unit)+param.basic.maxhp[h]+param.base.maxhp[h])))
elseif mod == 11 then
param.base.maxmana[h]= param.base.maxmana[h]+value
BlzSetUnitMaxMana(unit,R2I(RoundEx(GetHeroBaseMaxMana(unit)+param.basic.maxmana[h]+param.base.maxmana[h])))
elseif mod == 12 then
param.base.move[h] = param.base.move[h] + value
SetUnitMoveSpeed(unit,param.basic.move[h]+param.base.move[h])
elseif mod == 13 then
param.base.acquisition[h]=param.base.acquisition[h] + value
SetUnitAcquisitionRange(unit,param.basic.acquisition[h]+param.base.acquisition[h])
end
end
--эта функция была добавления для задания параметра через чат
--index атаки моэно не прописывать, пример: UnitSetBase(unit,mod,value) base = value-basic
function UnitSetBase(unit,mod,value,index)
if type(mod) ~= 'number' or type(value) ~= 'number' then
return false
elseif (mod == 4 or mod == 9) and type(index) ~= 'number' then
return false
elseif GetUnitTypeId (unit) == 0 or IsUnitType (unit, UNIT_TYPE_DEAD) then
return false
elseif mod > 0 and mod < 4 then
if not IsUnitType(unit, UNIT_TYPE_HERO) then
print('UnitSetBonus: you cant give the ability to a non-hero')
return false
end
end
local h = GetHandleId(unit)
if mod == 1 then
param.base.str[h]=value-GetBaseParamStr(unit)
SetHeroBaseStr(unit,R2I(RoundEx(GetBaseParamStr(unit)+param.base.str[h])))
elseif mod == 2 then
param.base.agi[h]=value-GetBaseParamAgi(unit)
SetHeroBaseAgi(unit,R2I(RoundEx(GetBaseParamAgi(unit)+param.base.agi[h])))
elseif mod == 3 then
param.base.int[h]=value-GetBaseParamInt(unit)
SetHeroBaseInt(unit,R2I(RoundEx(GetBaseParamInt(unit)+param.base.int[h])))
elseif mod == 4 then
if index == 0 then
param.base.dmg1[h]=R2I(RoundEx(value-GetUnitBasicParamDamage(unit,index)))
BlzSetUnitBaseDamage(unit,R2I(RoundEx(GetUnitBasicParamDamage(unit,index)+param.base.dmg1[h])),index)
elseif index == 1 then
param.base.dmg2[h]=R2I(RoundEx(value-GetUnitBasicParamDamage(unit,index)))
BlzSetUnitBaseDamage(unit,R2I(RoundEx(GetUnitBasicParamDamage(unit,index)+param.base.dmg2[h])),index)
end
elseif mod == 5 then
param.base.arm[h]=R2I(RoundEx(value-GetUnitBasicParamArmor(unit)))
BlzSetUnitArmor(unit,param.base.arm[h]+GetUnitBasicParamArmor(unit))
elseif mod == 6 then
param.base.regenhp[h]=R2I(RoundEx(value-param.basic.regenhp[h]))
SetUnitBaseRegenHP(unit, param.base.regenhp[h]+-param.basic.regenhp[h])
elseif mod == 7 then
param.base.regenmana[h]=R2I(RoundEx(value-param.basic.regenmana[h]))
SetUnitBaseRegenMana(unit, param.base.regenmana[h]+param.basic.regenmana[h])
elseif mod == 8 then
param.base.sight[h]=R2I(RoundEx(value-param.basic.sight[h]))
SetUnitSightRadius(unit,param.base.sight[h]+param.basic.sight[h])
elseif mod == 9 then
if index == 0 then
param.base.bat1[h]=R2I(RoundEx(value-param.basic.bat1[h]))
BlzSetUnitAttackCooldown(unit,param.base.bat1[h]+param.basic.bat1[h],index)
elseif index == 1 then
param.base.bat2[h]=R2I(RoundEx(value-param.basic.bat2[h]))
BlzSetUnitAttackCooldown(unit,param.base.bat2[h]+param.basic.bat2[h],index)
end
elseif mod == 10 then
param.base.maxhp[h]=R2I(RoundEx(value-param.basic.maxhp[h])) --требуется проверка, пока неизвестно как работает, возможна нужно с GetHeroBaseMaxHP(unit)
BlzSetUnitMaxHP(unit,R2I(RoundEx(param.base.maxhp[h]+param.basic.maxhp[h])))
elseif mod == 11 then
param.base.maxmana[h]=R2I(RoundEx(value-param.basic.maxmana[h])) --требуется проверка, пока неизвестно как работает, возможна нужно с GetHeroBaseMaxMana(unit)
BlzSetUnitMaxMana(unit,R2I(RoundEx(param.base.maxmana[h]+param.basic.maxmana[h])))
elseif mod == 12 then
param.base.move[h]=value-param.basic.move[h] --требуется проверка
SetUnitMoveSpeed(unit,param.base.move[h]+param.basic.move[h])
elseif mod == 13 then
param.base.acquisition[h]=value-param.basic.acquisition[h]
SetUnitAcquisitionRange(unit,param.base.acquisition[h]+param.basic.acquisition[h])
end
end
--эта функция была добавления для задания параметра через чат
--index атаки моэно не прописывать, пример: UnitClearBase(unit,mod)
function UnitClearBase(unit,mod,index)
if type(mod) ~= 'number' then
return false
elseif (mod == 4 or mod == 9) and type(index) ~= 'number' then
return false
elseif GetUnitTypeId (unit) == 0 or IsUnitType (unit, UNIT_TYPE_DEAD) then
return false
elseif mod > 0 and mod < 4 then
if not IsUnitType(unit, UNIT_TYPE_HERO) then
print('UnitSetBonus: you cant give the ability to a non-hero')
return false
end
end
local h = GetHandleId(unit)
if mod == 1 then
param.base.str[h]=0
SetHeroBaseStr(unit, R2I(RoundEx(GetBaseParamStr(unit)+param.base.str[h])))
elseif mod == 2 then
param.base.agi[h]=0
SetHeroBaseAgi(unit, R2I(RoundEx(GetBaseParamAgi(unit)+param.base.agi[h])))
elseif mod == 3 then
param.base.int[h]=0
SetHeroBaseInt(unit, R2I(RoundEx(GetBaseParamInt(unit)+param.base.int[h])))
elseif mod == 4 then
if index == 0 then
param.base.dmg1[h]=0
BlzSetUnitBaseDamage(unit,R2I(RoundEx(GetUnitBasicParamDamage(unit,index)+param.base.dmg1[h])),index)
elseif index == 1 then
param.base.dmg2[h]=0
BlzSetUnitBaseDamage(unit,R2I(RoundEx(GetUnitBasicParamDamage(unit,index)+param.base.dmg2[h])),index)
end
elseif mod == 5 then
param.base.arm[h]=0
BlzSetUnitArmor(unit, GetUnitBasicParamArmor(unit)+param.base.arm[h])
elseif mod == 6 then
param.base.regenhp[h]=0
SetUnitBaseRegenHP(unit, param.basic.regenhp[h]+param.base.regenhp[h])
elseif mod == 7 then
param.base.regenmana[h]=0
SetUnitBaseRegenMana(unit, param.basic.regenmana[h]+param.base.regenmana[h])
elseif mod == 8 then
param.basic.sight[h] = 0
SetUnitSightRadius(unit,param.basic.sight[h]+param.base.sight[h])
elseif mod == 9 then
if index == 0 then
param.base.bat1[h] = 0
BlzSetUnitAttackCooldown(unit,param.basic.bat1[h]+param.base.bat1[h],index)
elseif index == 1 then
param.base.bat2[h] = 0
BlzSetUnitAttackCooldown(unit,param.basic.bat2[h]+param.base.bat2[h],index)
end
elseif mod == 10 then
param.base.maxhp[h]= 0
BlzSetUnitMaxHP(unit,R2I(RoundEx(GetHeroBaseMaxHP(unit)+param.basic.maxhp[h]+param.base.maxhp[h])))
elseif mod == 11 then
param.base.maxmana[h]= 0
BlzSetUnitMaxMana(unit,R2I(RoundEx(GetHeroBaseMaxMana(unit)+param.basic.maxmana[h]+param.base.maxmana[h])))
elseif mod == 12 then
param.base.move[h] = 0
SetUnitMoveSpeed(unit,param.basic.move[h]+param.base.move[h])
elseif mod == 13 then
param.base.acquisition[h]=0
SetUnitAcquisitionRange(unit,param.basic.acquisition[h]+param.base.acquisition[h])
end
end
end
end
Добавлена возможность прокручивать или уставливать значения прямо в фреймах. Ибо в чатах неудобно всегда тестить.
Заметки:
- скорость атаки. тут теоритически высчитывается. мы можешь узнать дефолтную attack cooldawn. В игре изначально предоставлена базовая attack cooldawn, и только базовая attack cooldawn, и больше ничего нет. И с помощью нее можно вычислить базовую скорость. Но нужно вам знать %, короче наскока изменяется эти базовые attack cooldawn, attack speed. По идее можно вообще обойтись без абилок перчаток, храните инфу в таблицах. изменяем саму attack cooldawn.
- для изменения задержки между ударами таймером - рекомендуется кого-нибудь ударить. На карту я поставил специально ферму с регеном и хп, так сказать грушу для битья
- поставил кузницу, чтобы изменять уровень апгрейда атаки/защиты. на пехотинце тестировалось. отследить можно, берем инфу из фрейма. но в фреймах я не доделал, кому надо - отвечу.
- положил на карту сферы, дабы посмотреть включена/выключена атака. Это похоже работает только у горного гиганта, когда дерево вырывает
- мана реген. модификатора регена маны работает с помощью абилки маски соби. там процентное содержание выдает. процент умножает на общий реген маны. И работает не так как надо. И еще она не работает у обычных юнитов.
Обновление:
- исправлены ошибки в расчетах.
- поработал немного над оформлением фреймов
- добавлена возможность изменять базовые параметры.
Планы:
- продолжить улучшать +много идеи. Хочу реализовать показ данных фрейма при наводке мыши на вражеского юнита: скока возможного урона, может ли атаковать, сильный/слабый юнит. А еще хочу потестить свою агро-систему с отображением радиуса.
- бонус от абилки мана-реген маски соби не работает. тут надо включать другие бонусы, поэтому это не реально посчитать точное.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован MpW
а вот сила/ловкость/интеллект, защита/урон и др => им трудно добавить бонус, тк нативки изменяют только базовый или общий, т.е. белый параметр. нету подразделения четкого. это тогда нужно изменять сам интерфейс. в принципе не сложно добавить зеленку в интерфейс, а все данных в таблицах подразделять: бонус/базовый. Но это уже в след версии. Здесь бонусы добавляются через абилки степени двойки
Отредактирован MpW
Я вроде где-то расписывал это но не помню, но могу сказать что это точно работает
Отредактирован MpW
Предмет: регенерация маны 'AIrm'/Предмет: регенерация маны (малый) 'AIrn' - каждую секунду процентно восстанавливает ману. Процент идет от базового регена + от регена интеллекта героя + другие бонусные регенерации типа чародейская ауры или аура фонтана магии. Эта регенерация работает только у героя, у обычных юнитов что-то не хочет идти.
MANA_REGEN_Common = mana_regen_Intellect + MANA_REGEN_SobiMask + другие бонусы типа чародейской ауры - общий реген (так как у героя работает только реген от инты и от других бонусов, а вот базовый реген не учитывается. Так как базовый реген не работает на герое)
MANA_REGEN_Common = mana_regen_Intellect + MANA_REGEN_SobiMask1 + MANA_REGEN_SobiMask2 + другие бонусы типа чародейской ауры - общий реген ((если абилок от маски соби несколько, они суммируются вот так)
Какие бонусы есть в игре? Это пассивки (чародейская аура, аура фонтана, маска соби не учитывается), активных заклинании с постепенным восстановлением не много (рев, леденящий крик, омоложение не учитывается,
base_mana_regen - базовый реген, который указан в РО юнита "Характеристики - Восстановление маны". Работает только у обычных юнитов, тестировал этот момент у героя. У героя показывает реген от интеллекта (базовый не работает у героя), но когда он одевает маску соби учитывается базовый реген. Благодаря базовому регену, можно сделать героя с уникальным регеном.
mana_regen_Intellect = Intellect * k - реген от интеллекта (где Intellect - кол-во интеллекта героя, k - константа "Характеристики героя: увеличение скорости восстановления за единицу разума", которая за каждую единицу маны восстанавливает заданное число)
p - процент от абилки
Отредактирован MpW