Добавлен noyl,
опубликован
» Способ реализации: Lua
» Тип: Способность, пак
» Версия Warcraft: 1.31+
» MUI: да
» Импорт: нет
» Тип: Способность, пак
» Версия Warcraft: 1.31+
» MUI: да
» Импорт: нет
Пак способностей Орна из лиги.
Вулканический разлом [Q]
Орн бьет по земле, создавая в ней трещину, которая наносит врагам физический урон и замедляет их. После небольшой задержки в области поражения поднимается столп магмы, который стоит стеной в течение нескольких секунд.
do
local SPELL_ID = FourCC('A000')
local MDX = "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl"
local SCALE = 1.28
local DISTANCE = 800.0
local INTERVAL = 0.03125
local MOVE_TIME = 1.5
local DAMAGE = {20, 45, 70, 95, 120}
local BONUS_DAMAGE = 1.1
local AOE = 128.0
--
local WALL_ID = FourCC('h001')
local WALL_DIST = 160.0
--
local ATTACK_TYPE = ATTACK_TYPE_HERO
local DAMAGE_TYPE = DAMAGE_TYPE_FIRE
local WEAPON_TYPE = nil
--
local DUMMY_ID = FourCC('e000')
--
local GROUP = CreateGroup()
local trg = CreateTrigger()
for i = 0, bj_MAX_PLAYER_SLOTS do
TriggerRegisterPlayerUnitEvent(trg, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
end
TriggerAddCondition(trg, Condition(function() return GetSpellAbilityId() == SPELL_ID end))
TriggerAddAction(trg, function()
local caster = GetTriggerUnit()
local player = GetTriggerPlayer()
local level = GetUnitAbilityLevel(caster, SPELL_ID)
--
local speed = 2 * DISTANCE / ((MOVE_TIME / INTERVAL) + 1)
local now_distance = 0
local x = GetUnitX(caster)
local y = GetUnitY(caster)
local angle = Atan2(GetSpellTargetY() - y, GetSpellTargetX() - x)
--
local effect = AddSpecialEffect(MDX, x, y)
--
local dmg = DAMAGE[level] + (BlzGetUnitBaseDamage(caster, 0) * BONUS_DAMAGE)
--
local gr = CreateGroup()
local hit = false
--
TimerStart(CreateTimer(), INTERVAL, true, function()
now_distance = now_distance + speed
x = x + speed * Cos(angle)
y = y + speed * Sin(angle)
z = GetTerrainZ(x, y) + 8.0
if(now_distance >= DISTANCE or hit or not InMap(x, y))then
if(hit)then
x = x + WALL_DIST * Cos(angle)
y = y + WALL_DIST * Sin(angle)
end
bj_lastCreatedUnit = CreateUnit(player, WALL_ID, x, y, 90.0)
DestroyGroup(gr)
DestroyEffect(effect)
DestroyTimer(GetExpiredTimer())
else
BlzSetSpecialEffectPosition(effect, x, y, z)
BlzSetSpecialEffectScale(effect, SCALE)
GroupEnumUnitsInRange(GROUP, x, y, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(Condition(target, player) and not IsUnitInGroup(target, gr))then
if(IsUnitType(target, UNIT_TYPE_HERO))then hit = true end
UnitDamageTarget(caster, target, dmg, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
GroupAddUnit(gr, target)
bj_lastCreatedUnit = CreateUnit(player, DUMMY_ID, x, y, 0.0)
IssueTargetOrder(bj_lastCreatedUnit, "slow", target)
end
GroupRemoveUnit(GROUP, target)
end
end
end)
end)
end
Дыхание вулкана [W]
Орн становится неудержимым, закрывается щитом и извергает пламя. Пламя наносит магический урон, размер которого зависит от текущего запаса здоровья противника. Враги, объятые последней порцией пламени, становятся хрупкими. Автоатаки Орна отбрасывают хрупкие цели.
do
local SPELL_ID = FourCC('A002')
local ATTACK_ID = FourCC('Abun')
local MDX = "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl"
local SCALE = 1.5
local DURATION = 0.75
local INTERVAL = 0.05
local DAMAGE = {0.12, 0.13, 0.14, 0.15, 0.16}
local AOE = 200.0
local STEP = 15.0
local RAGE = true
--
local ATTACK_TYPE = ATTACK_TYPE_MAGIC
local DAMAGE_TYPE = DAMAGE_TYPE_FIRE
local WEAPON_TYPE = nil
--
local BLOCK = CreateTrigger()
local BLOCK_GROUP = CreateGroup()
local SHIELD = {}
--
local BRITTLE_ID = FourCC('A003')
local BUFF_ID = FourCC('B001')
local BRITTLE = CreateTrigger()
local BRITTLE_GROUP = CreateGroup()
local BRITTLE_INTERVAL = 0.03125
local BRITTLE_DISTANCE = 200.0
local BRITTLE_TIME = 1.0
local BRITTLE_ARC = 0.5
--
local DUMMY_ID = FourCC('e000')
local GROUP = CreateGroup()
local trg = CreateTrigger()
for i = 0, bj_MAX_PLAYER_SLOTS do
TriggerRegisterPlayerUnitEvent(trg, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
end
TriggerAddCondition(trg, Condition(function() return GetSpellAbilityId() == SPELL_ID end))
TriggerAddAction(trg, function()
local caster = GetTriggerUnit()
local key = GetHandleId(caster)
local player = GetTriggerPlayer()
local level = GetUnitAbilityLevel(caster, SPELL_ID)
--
local x, y, angle
local now_duration = 0.0
local animation_speed = (STEP * 2) * INTERVAL
--
SHIELD[key] = GetUnitState(caster, UNIT_STATE_MAX_LIFE) * DAMAGE[level]
if not IsUnitInGroup(caster, BLOCK_GROUP) then
TriggerRegisterUnitEvent(BLOCK, caster, EVENT_UNIT_DAMAGING)
GroupAddUnit(BLOCK_GROUP, caster)
end
--
if(RAGE)then
PauseUnit(caster, true)
UnitAddAbility(caster, ATTACK_ID)
SetUnitTimeScale(caster, animation_speed)
end
--
TimerStart(CreateTimer(), INTERVAL, true, function()
now_duration = now_duration + INTERVAL
angle = GetUnitFacing(caster) * (bj_PI / 180)
x = GetUnitX(caster) + STEP * Cos(angle)
y = GetUnitY(caster) + STEP * Sin(angle)
SetUnitPosition(caster, x, y)
SetUnitAnimation(caster, "walk")
local effect = AddSpecialEffect(MDX, x, y)
BlzSetSpecialEffectScale(effect, SCALE)
DestroyEffect(effect)
GroupEnumUnitsInRange(GROUP, x, y, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(Condition(target, player))then
local dmg = DAMAGE[level] * GetUnitState(target, UNIT_STATE_MAX_LIFE) * INTERVAL
UnitDamageTarget(caster, target, dmg, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
end
GroupRemoveUnit(GROUP, target)
end
--
if(now_duration >= DURATION)then
if(RAGE)then
PauseUnit(caster, false)
SetUnitAnimation(caster, "stand")
SetUnitTimeScale(caster, 1)
UnitRemoveAbility(caster, ATTACK_ID)
end
SHIELD[key] = 0.0
GroupEnumUnitsInRange(GROUP, x, y, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(Condition(target, player))then
local dmg = DAMAGE[level] * GetUnitState(target, UNIT_STATE_MAX_LIFE) * INTERVAL
UnitDamageTarget(caster, target, dmg, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
bj_lastCreatedUnit = CreateUnit(player, DUMMY_ID, x, y, 0.0)
IssueTargetOrder(bj_lastCreatedUnit, "bloodlust", target)
if not IsUnitInGroup(target, BRITTLE_GROUP) then
TriggerRegisterUnitEvent(BRITTLE, target, EVENT_UNIT_DAMAGING)
GroupAddUnit(BRITTLE_GROUP, target)
end
end
GroupRemoveUnit(GROUP, target)
end
DestroyTimer(GetExpiredTimer())
end
--
end)
end)
TriggerAddAction(BLOCK, function()
local unit = GetTriggerUnit()
local dmg = GetEventDamage()
local key = GetHandleId(unit)
SHIELD[key] = SHIELD[key] - dmg
if(SHIELD[key] > 0.0)then
BlzSetEventDamage(0)
end
end)
local function BrittleFunc(target, speed, angle)
local x = GetUnitX(target)
local y = GetUnitY(target)
local zs = GetTerrainZ(x, y)
local xe = x + BRITTLE_DISTANCE * Cos(angle)
local ye = y + BRITTLE_DISTANCE * Sin(angle)
local ze = GetTerrainZ(xe, ye)
local now_distance = BRITTLE_DISTANCE
UnitAddAbility(target, FourCC('Arav'))
PauseUnit(target, true)
TimerStart(CreateTimer(), BRITTLE_INTERVAL, true, function()
x = x + speed * Cos(angle)
y = y + speed * Sin(angle)
now_distance = now_distance - speed
z = Parabola(zs, ze, BRITTLE_DISTANCE * BRITTLE_ARC, BRITTLE_DISTANCE, BRITTLE_DISTANCE - (BRITTLE_DISTANCE - now_distance))
SetUnitX(target, x)
SetUnitY(target, y)
SetUnitFlyHeight(target, z, 0)
if(now_distance <= 0)then
UnitRemoveAbility(target, FourCC('Arav'))
PauseUnit(target, false)
SetUnitFlyHeight(target, 0, 0)
DestroyTimer(GetExpiredTimer())
end
end)
end
TriggerAddAction(BRITTLE, function()
local unit = GetTriggerUnit()
local attacker = GetEventDamageSource()
local speed = 2 * BRITTLE_DISTANCE / ((BRITTLE_TIME / BRITTLE_INTERVAL) + 1)
if(GetUnitAbilityLevel(unit, BUFF_ID) > 0)then
UnitRemoveAbility(unit, BUFF_ID)
BrittleFunc(unit, speed, GetUnitFacing(attacker) * (bj_PI / 180))
end
end)
end
Обжигающий рывок [E]
Орн делает рывок и наносит урон всем врагам на своем пути. Если Орн сталкивается с препятствием, возникает ударная волна, которая наносит урон и подбрасывает врагов. Умение уничтожает препятствия, созданные игроками.
do
local SPELL_ID = FourCC('A004')
local WALL_ID = FourCC('h001')
local MDX = "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl"
local SCALE = 0.5
local DAMAGE = {80, 125, 170, 215, 260}
local BONUS_DAMAGE = 0.4
local AOE = 150.0
local MOVE_TIME = 1.25
local DISTANCE = 800.0
local INTERVAL = 0.03125
--
local ATTACK_TYPE = ATTACK_TYPE_HERO
local DAMAGE_TYPE = DAMAGE_TYPE_FIRE
local WEAPON_TYPE = nil
--
local DURATION = 1.0
local HEIGHT = 400.0
--
local GROUP = CreateGroup()
local function Fly(target)
local now_duration = 0
local now_height = 0
local back = DURATION / 2
local speed = 2 * HEIGHT / ((DURATION / INTERVAL) + 1)
UnitAddAbility(target, FourCC('Arav'))
PauseUnit(target, true)
TimerStart(CreateTimer(), INTERVAL, true, function()
now_duration = now_duration + INTERVAL
if(now_duration >= DURATION)then
SetUnitFlyHeight(target, 0, 0)
UnitRemoveAbility(target, FourCC('Arav'))
PauseUnit(target, false)
DestroyTimer(GetExpiredTimer())
else
if(now_duration >= back)then
now_height = now_height - speed
SetUnitFlyHeight(target, now_height, 0)
else
now_height = now_height + speed
SetUnitFlyHeight(target, now_height, 0)
end
end
end)
end
local trg = CreateTrigger()
for i = 0, bj_MAX_PLAYER_SLOTS do
TriggerRegisterPlayerUnitEvent(trg, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
end
TriggerAddCondition(trg, Condition(function() return GetSpellAbilityId() == SPELL_ID end))
TriggerAddAction(trg, function()
local caster = GetTriggerUnit()
local player = GetTriggerPlayer()
local level = GetUnitAbilityLevel(caster, SPELL_ID)
local effect = AddSpecialEffectTarget(MDX, caster, "chset")
--
local x = GetUnitX(caster)
local y = GetUnitY(caster)
local angle = Atan2(GetSpellTargetY() - y, GetSpellTargetX() - x)
local now_distance = 0
local speed = 2 * DISTANCE / ((MOVE_TIME / INTERVAL) + 1)
local dmg = DAMAGE[level] + BlzGetUnitArmor(caster) * BONUS_DAMAGE
--
local dash = false
local gr = CreateGroup()
--
PauseUnit(caster, true)
TimerStart(CreateTimer(), INTERVAL, true, function()
x = x + speed * Cos(angle)
y = y + speed * Sin(angle)
now_distance = now_distance + speed
if(now_distance >= DISTANCE or dash)then
if(dash)then
local boom = AddSpecialEffect(MDX, x, y)
BlzSetSpecialEffectScale(boom, 3.0)
DestroyEffect(boom)
GroupEnumUnitsInRange(GROUP, x, y, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(Condition(target, player))then
Fly(target)
end
GroupRemoveUnit(GROUP, target)
end
end
DestroyGroup(gr)
DestroyEffect(effect)
PauseUnit(caster, false)
DestroyTimer(GetExpiredTimer())
else
if(not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))then
SetUnitX(caster, x)
SetUnitY(caster, y)
else
dash = true
end
GroupEnumUnitsInRange(GROUP, x, y, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(Condition(target, player) and not IsUnitInGroup(target, gr))then
UnitDamageTarget(caster, target, dmg, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
GroupAddUnit(gr, target)
end
if(GetUnitTypeId(target) == WALL_ID)then
KillUnit(target)
dash = true
end
GroupRemoveUnit(GROUP, target)
end
end
end)
end)
end
Зов бога-кузнеца [R]
Орн призывает в выбранную точку огромного огненного элементаля, который движется к нему навстречу с нарастающей скоростью. Пораженные элементалем враги получают магический урон и становятся хрупкими.
Орн может применить умение повторно, чтобы сделать рывок вперед. Столкнувшись с элементалем во время рывка, он отправит его в другую сторону. На обратном пути элементаль наносит такой же урон, как и в первый раз, подбрасывает всех пораженных врагов и делает их хрупкими.
do
local SPELL_ID = FourCC('A005')
local SECOND_ID = FourCC('A006')
local SLOW_ID = FourCC('A001')
local GOD_DUMMY_ID = FourCC('h002')
local SECOND_DUR = 5.0
local DISTANCE = 1500.0
local SECOND_DIST = 250.0
local AOE = 375.0
local MOVE_TIME = 1.0
local GOD_MOVE_TIME = 4.2
local INTERVAL = 0.03125
local DAMAGE = {125, 175, 225}
local BONUS_DAMAGE = 0.2
--
local DURATION = 1.5
local HEIGHT = 600.0
--
local ATTACK_TYPE = ATTACK_TYPE_MAGIC
local DAMAGE_TYPE = DAMAGE_TYPE_FIRE
local WEAPON_TYPE = nil
--
local DUMMY_ID = FourCC('e000')
local GROUP = CreateGroup()
--
local GOD_DUMMY = {}
local SHOOT = {}
local trg = CreateTrigger()
for i = 0, bj_MAX_PLAYER_SLOTS do
TriggerRegisterPlayerUnitEvent(trg, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
end
TriggerAddCondition(trg, Condition(function() return GetSpellAbilityId() == SPELL_ID end))
TriggerAddAction(trg, function()
local caster = GetTriggerUnit()
local player = GetTriggerPlayer()
local key = GetHandleId(caster)
local level = GetUnitAbilityLevel(caster, SPELL_ID)
local dmg = DAMAGE[level] + BONUS_DAMAGE * BlzGetUnitBaseDamage(caster, 0)
local speed = 2 * DISTANCE / ((GOD_MOVE_TIME / INTERVAL) + 1)
local now_distance = DISTANCE
local x = GetUnitX(caster)
local y = GetUnitY(caster)
local angle_create = Atan2(GetSpellTargetY() - y, GetSpellTargetX() - x)
local angle = Atan2(y - GetSpellTargetY(), x - GetSpellTargetX())
local xg = x + DISTANCE * Cos(angle_create)
local yg = y + DISTANCE * Sin(angle_create)
local dummy = CreateUnit(player, GOD_DUMMY_ID, xg, yg, angle * bj_RADTODEG)
GOD_DUMMY[key] = dummy
SHOOT[key] = false
SetUnitTimeScale(dummy, 0.3)
BlzUnitHideAbility(caster, SPELL_ID, true)
UnitAddAbility(caster, SECOND_ID)
SetUnitAbilityLevel(caster, SECOND_ID, level)
local gr = CreateGroup()
TimerStart(CreateTimer(), INTERVAL, true, function()
now_distance = now_distance - speed
xg = xg + speed * Cos(angle)
yg = yg + speed * Sin(angle)
GroupEnumUnitsInRange(GROUP, xg, yg, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(Condition(target, player) and not IsUnitInGroup(target, gr))then
UnitDamageTarget(caster, target, dmg, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
GroupAddUnit(gr, target)
bj_lastCreatedUnit = CreateUnit(player, DUMMY_ID, x, y, 0.0)
SetUnitAbilityLevel(bj_lastCreatedUnit, SLOW_ID, level)
IssueTargetOrder(bj_lastCreatedUnit, "slow", target)
end
GroupRemoveUnit(GROUP, target)
end
if(now_distance <= -50.0)then
if(GetUnitAbilityLevel(caster, SECOND_ID) > 0)then
UnitRemoveAbility(caster, SECOND_ID)
BlzUnitHideAbility(caster, SPELL_ID, false)
end
if(not SHOOT[key])then
RemoveUnit(dummy)
end
DestroyGroup(gr)
DestroyTimer(GetExpiredTimer())
else
SetUnitX(dummy, xg)
SetUnitY(dummy, yg)
end
end)
end)
local function Fly(target)
local now_duration = 0
local now_height = 0
local back = DURATION / 2
local speed = 2 * HEIGHT / ((DURATION / INTERVAL) + 1)
UnitAddAbility(target, FourCC('Arav'))
PauseUnit(target, true)
TimerStart(CreateTimer(), INTERVAL, true, function()
now_duration = now_duration + INTERVAL
if(now_duration >= DURATION)then
SetUnitFlyHeight(target, 0, 0)
UnitRemoveAbility(target, FourCC('Arav'))
PauseUnit(target, false)
DestroyTimer(GetExpiredTimer())
else
if(now_duration >= back)then
now_height = now_height - speed
SetUnitFlyHeight(target, now_height, 0)
else
now_height = now_height + speed
SetUnitFlyHeight(target, now_height, 0)
end
end
end)
end
trg = CreateTrigger()
for i = 0, bj_MAX_PLAYER_SLOTS do
TriggerRegisterPlayerUnitEvent(trg, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
end
TriggerAddCondition(trg, Condition(function() return GetSpellAbilityId() == SECOND_ID end))
TriggerAddAction(trg, function()
local caster = GetTriggerUnit()
local player = GetTriggerPlayer()
local key = GetHandleId(caster)
local level = GetUnitAbilityLevel(caster, SECOND_ID)
local x = GetUnitX(caster)
local y = GetUnitY(caster)
local angle = GetUnitFacing(caster)
GroupEnumUnitsInRange(GROUP, x, y, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(target == GOD_DUMMY[key])then
local dummy = GOD_DUMMY[key]
SHOOT[key] = true
UnitRemoveAbility(caster, SECOND_ID)
BlzUnitHideAbility(caster, SPELL_ID, false)
local dmg = DAMAGE[level] + BONUS_DAMAGE * BlzGetUnitBaseDamage(caster, 0)
local speed = 2 * DISTANCE / ((GOD_MOVE_TIME / INTERVAL) + 1)
local now_distance = 0
local xg = x + speed * Cos(angle * (bj_PI / 180))
local yg = y + speed * Sin(angle * (bj_PI / 180))
SetUnitFacing(dummy, angle)
local gr = CreateGroup()
TimerStart(CreateTimer(), INTERVAL, true, function()
now_distance = now_distance + speed
xg = xg + speed * Cos(angle * (bj_PI / 180))
yg = yg + speed * Sin(angle * (bj_PI / 180))
GroupEnumUnitsInRange(GROUP, xg, yg, AOE, nil)
local target
while true do
target = FirstOfGroup(GROUP)
if target == nil then break end
if(Condition(target, player) and not IsUnitInGroup(target, gr))then
UnitDamageTarget(caster, target, dmg, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
Fly(target)
GroupAddUnit(gr, target)
end
GroupRemoveUnit(GROUP, target)
end
if(now_distance >= DISTANCE or not InMap(xg, yg))then
DestroyGroup(gr)
RemoveUnit(dummy)
DestroyTimer(GetExpiredTimer())
else
SetUnitX(dummy, xg)
SetUnitY(dummy, yg)
end
end)
end
GroupRemoveUnit(GROUP, target)
end
end)
end
Перенос в свою карту
Скопировать триггер: Function
Скопировать юнита: Dummy Caster
Скопировать способности: Slow, Brittle
Скопировать заклинание: Brittle
Вулканический разлом
Скопировать триггер: VOLCANIC RUPTURE
Скопировать способность: VOLCANIC RUPTURE
Скопировать юнита: Wall
Дыхание вулкана
Скопировать триггер: BELLOWS BREATH
Скопировать способность: BELLOWS BREATH
Обжигающий рывок
Скопировать триггер: SEARING CHARGE
Скопировать способность: SEARING CHARGE
Зов бога-кузнеца
Скопировать триггер: CALL OF THE FORGE GOD
Скопировать способности: CALL OF THE FORGE GOD(first call), CALL OF THE FORGE
GOD(second call)
Скопировать юнита: The Forge God
Скопировать юнита: Dummy Caster
Скопировать способности: Slow, Brittle
Скопировать заклинание: Brittle
Вулканический разлом
Скопировать триггер: VOLCANIC RUPTURE
Скопировать способность: VOLCANIC RUPTURE
Скопировать юнита: Wall
Дыхание вулкана
Скопировать триггер: BELLOWS BREATH
Скопировать способность: BELLOWS BREATH
Обжигающий рывок
Скопировать триггер: SEARING CHARGE
Скопировать способность: SEARING CHARGE
Зов бога-кузнеца
Скопировать триггер: CALL OF THE FORGE GOD
Скопировать способности: CALL OF THE FORGE GOD(first call), CALL OF THE FORGE
GOD(second call)
Скопировать юнита: The Forge God
P.S
Не всё работает как в LoL'e.
Нет пассивной способности.
Во время W вы не можете двигаться.
Во время второго использования R вы не совершаете рывок.
Нет пассивной способности.
Во время W вы не можете двигаться.
Во время второго использования R вы не совершаете рывок.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован prog
Отредактирован nazarpunk
Отредактирован prog