Эль_Кин, ахаха, спасибо))
На самом деле на этот прогресс ушло куда больше времени и недоскиллов, но я всё равно не доволен результатом. Типо всё что в этой карте - банальщина, видели миллион раз, так оно ещё и криво написано)
Думаю мне просто нужна конструктивная критика с предложениями как можно сделать лучше
Librarian, а, ресурсы в инвентарь в виде предметов кладутся? С зарядами? Я уже делал нечто подобное, но честно говоря, я не помню как и что там устроено)
Могу наклепать позже, если никто не преуспеет
Вот, вместо переменной LastCaster можно использовать юнита триггера, а в качестве целей - источник повреждения (искл. прыжок, там только кастер), думаю теперь чуть больше возможностей открылось. Однако для этого в триггер нужно зарегистрировать событие, что юниты получают урон
Простите за абилки, я переделаю под получение юнитом урона, урон можно будет самому настраивать непосредственно при получении нулевого урона, перед нанесением будет выставлено определенное число глобальной переменной, никакого даммикаста, проверять нужно будет только эту целочисленную
Я в математике не силен, но попробуй сначала разницу уровней вычитать, если она минусовая, то 1 опыта дать, если плюсовая, то сделать вот ту твою фигню с Pow
Готово. Можно было бы ещё добавить деформацию ланда для ульты, но на больших картах оно лагает. Повторюсь, это не для импорта, ибо никаких настроек по использованию и разбора кода я не оставлял. Просто посмотреть на возможности джасса если кому интересно. Мотивация так сказать хотя кого это говнище мотивировать будет, лол) upd в видео музыка
library mylib initializer init
private hashtable H = InitHashtable()
private trigger trg = CreateTrigger()
private group TempG = CreateGroup()
private group TempG1 = CreateGroup()
private unit CUEX = null
private real TempR
private real TempR1
private real TempR2
private real TempR3
private real TempX
private real TempY
private integer TF = 0
private integer TF1 = 0
private boolean FireID
private damagetype DamageType
// Переменные быстрого доступа управления полётом апокалиптического дождя
private constant real RainFly = 600
private constant real RainFlyD = 100
// Воспомогательные функции
private function Kill takes nothing returns nothing
call KillUnit(GetEnumUnit())
endfunction
private function IsUnitDead takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction
private function CreateUnitEx takes player id, integer unitid, real x, real y, real face returns unit
set CUEX = CreateUnit(id,unitid,x,y,face)
call SetUnitPathing(CUEX,false)
call SetUnitX(CUEX,x)
call SetUnitY(CUEX,y)
return CUEX
endfunction
private function li takes nothing returns boolean
return not IsUnitDead(GetFilterUnit()) and GetUnitTypeId(GetFilterUnit()) != 'u000'
endfunction
private function DBC takes real x, real y, real x1, real y1 returns real
return SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1))
endfunction
private function IsPointInSector takes real x1, real y1, real x2, real y2, real orientation, real width, real radius returns boolean
local real lenght = DBC(x1,y1,x2,y2)
local real angle = Acos(Cos(orientation*bj_DEGTORAD)*(x1-x2)/lenght+Sin(orientation*bj_DEGTORAD)*(y1-y2)/lenght )*bj_RADTODEG
return angle<=width and lenght<=radius
endfunction
private function SetUnitPositionEx takes unit u, real x, real y returns nothing
local item i = CreateItem('spsh',x,y)
set TempX = GetItemX(i)
set TempY = GetItemY(i)
set TempR = DBC(x,y,TempX,TempY)
if TempR > 10 then
call SetUnitX(u,TempX)
call SetUnitY(u,TempY)
else
call SetUnitX(u,x)
call SetUnitY(u,y)
endif
call RemoveItem(i)
set i = null
endfunction
//===================================================
// Пламя преисподней
private function UnderworldFlamesDMG takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer timerH=GetHandleId(t)
local unit caster=LoadUnitHandle(H,timerH,1)
local unit target=LoadUnitHandle(H,timerH,2)
local integer casterH=GetHandleId(caster)
local integer targetH=GetHandleId(target)
local integer level=LoadInteger(H,timerH,3)
local integer counter=LoadInteger(H,targetH,casterH)
local real dmg = LoadReal(H,timerH,0)
call SaveInteger(H,targetH,casterH,counter-1)
set TF = 1
call UnitDamageTarget(caster,target,dmg,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_FIRE,null)
set TF = 0
if counter == 1 or IsUnitDead(target) or GetUnitAbilityLevel(target,'B000') < 1 then
call UnitRemoveAbility(target,'A000')
call UnitRemoveAbility(target,'B000')
call RemoveSavedInteger(H,targetH,casterH)
call FlushChildHashtable(H,timerH)
call PauseTimer(t)
call DestroyTimer(t)
endif
set t=null
set caster=null
set target=null
endfunction
private function UnderworldFlames takes unit u, unit u1 returns nothing
local integer casterH=GetHandleId(u)
local integer targetH=GetHandleId(u1)
local integer lvl=GetUnitAbilityLevel(u,'A005')
local integer timerH
local integer counter=LoadInteger(H,targetH,casterH)
local integer tm
local timer t
local real dmg
if lvl == 1 then
set dmg = 5.
set tm = 3
elseif lvl == 2 then
set dmg = 15.
set tm = 5
elseif lvl == 3 then
set dmg = 20.
set tm = 6
endif
set dmg = dmg+(GetHeroInt(u,true)*.1)
if counter == 0 then
call UnitAddAbility(u1,'A000')
set t = CreateTimer()
set timerH = GetHandleId(t)
call SaveReal(H,timerH,0,dmg)
call SaveUnitHandle(H,timerH,1,u)
call SaveUnitHandle(H,timerH,2,u1)
call SaveInteger(H,timerH,3,lvl)
call TimerStart(t,1.,true,function UnderworldFlamesDMG)
set t=null
endif
call SaveInteger(H,targetH,casterH,tm)
endfunction
// Планетарное разрушение
private function PlanetaryDestructionCond takes nothing returns boolean
set bj_lastReplacedUnit = GetFilterUnit()
return not IsUnitDead(bj_lastReplacedUnit) and not IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_MAGIC_IMMUNE) and IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit)) and not IsUnitInGroup(bj_lastReplacedUnit,TempG1)
endfunction
private function PlanetaryDiscarding takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,0)
local real a = LoadReal(H,i,2)
local real s = LoadReal(H,i,6)
local real tm = LoadReal(H,i,4)+.02
call SetUnitPositionEx(u,GetUnitX(u)+s*Cos(a),GetUnitY(u)+s*Sin(a))
if TempR > 10 and not IsUnitDead(u) then
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",GetUnitX(u),GetUnitY(u)))
set TF = 1
call UnitDamageTarget(LoadUnitHandle(H,i,3),u,LoadReal(H,i,1),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_SONIC,null)
set TF = 0
if not IsUnitDead(u) then
call CreateUnitEx(Player(15),'u007',GetUnitX(u),GetUnitY(u),0)
call UnitAddAbility(CUEX,'A008')
call IssueTargetOrder(CUEX,"thunderbolt",u)
call UnitApplyTimedLife(CUEX,'BTLF',1)
endif
endif
if TempR > 10 or tm > LoadReal(H,i,5) or GetUnitTypeId(u) < 1 then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
else
call SaveReal(H,i,4,tm)
endif
set t = null
set u = null
endfunction
private function PlanetaryDestructionDmg takes nothing returns nothing
local unit u = GetEnumUnit()
local timer t
local integer i
local real x
local real y
local real dc
local real tm
call UnitDamageTarget(bj_lastCreatedUnit,u,TempR1,false,false,ATTACK_TYPE_MAGIC,DamageType,null)
if not IsUnitDead(u) then
set x = GetUnitX(u)
set y = GetUnitY(u)
call CreateUnitEx(Player(15),'u007',x,y,0)
if TF1 == 0 then
call UnitAddAbility(CUEX,'A008')
call IssueTargetOrder(CUEX,"thunderbolt",u)
call UnitApplyTimedLife(CUEX,'BTLF',1)
else
call UnitAddAbility(CUEX,'A009')
call IssueTargetOrder(CUEX,"slow",u)
call UnitApplyTimedLife(CUEX,'BTLF',1)
set t = CreateTimer()
set i = GetHandleId(t)
call SaveUnitHandle(H,i,0,u)
call SaveReal(H,i,1,TempR1*.5)
call SaveReal(H,i,2,Atan2(y-TempR3,x-TempR2))
call SaveUnitHandle(H,i,3,bj_lastCreatedUnit)
if GetUnitAbilityLevel(u,'A002') > 0 then
set tm = .1
set dc = 7.5
elseif GetUnitAbilityLevel(u,'A003') > 0 then
set tm = .5
set dc = 10.
else
set tm = .5
set dc = 15.
endif
call SaveReal(H,i,5,tm)
call SaveReal(H,i,6,dc)
call TimerStart(t,.02,true,function PlanetaryDiscarding)
set t = null
endif
if FireID then
call UnderworldFlames(bj_lastCreatedUnit,u)
endif
call GroupAddUnit(TempG1,u)
endif
set u = null
endfunction
private function PlanetaryDestructionAct takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,1)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real dmg = LoadReal(H,i,4)
set FireID = LoadBoolean(H,i,3)
if FireID then
call KillUnit(CreateUnitEx(Player(15),'u00A',x,y,GetRandomReal(0,360)))
endif
set TempR1 = dmg*2
set TempR2 = x
set TempR3 = y
set TF = 1
set DamageType = DAMAGE_TYPE_DEMOLITION
set bj_lastCreatedUnit = LoadUnitHandle(H,i,0)
call GroupEnumUnitsInRange(TempG,x,y,200,Condition(function PlanetaryDestructionCond))
call ForGroup(TempG,function PlanetaryDestructionDmg)
call GroupClear(TempG)
set TempR1 = dmg
set TF1 = 1
set DamageType = DAMAGE_TYPE_SONIC
call GroupEnumUnitsInRange(TempG,x,y,500,Condition(function PlanetaryDestructionCond))
call ForGroup(TempG,function PlanetaryDestructionDmg)
call GroupClear(TempG)
call GroupClear(TempG1)
set TF = 0
set TF1 = 0
call KillUnit(CreateUnitEx(Player(15),'u003',x,y,GetRandomReal(0,360)))
call KillUnit(CreateUnitEx(Player(15),'u00C',x,y,GetRandomReal(0,360)))
call KillUnit(CreateUnitEx(Player(15),'u00B',x,y,GetRandomReal(0,360)))
call KillUnit(CreateUnitEx(Player(15),'u009',x,y,GetRandomReal(0,360)))
call KillUnit(CreateUnitEx(Player(15),'u008',x,y,GetRandomReal(0,360)))
call KillUnit(u)
call KillUnit(LoadUnitHandle(H,i,2))
call DestroyFogModifier(LoadFogModifierHandle(H,i,5))
call DestroyTimer(t)
call FlushChildHashtable(H,i)
set bj_lastCreatedUnit = null
set t = null
set u = null
endfunction
private function PlanetaryDestruction takes nothing returns nothing
local timer t = CreateTimer()
local integer i = GetHandleId(t)
local unit u = GetTriggerUnit()
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()
local real dmg = 300+(GetHeroInt(u,true))
set FireID = GetUnitAbilityLevel(u,'B001') > 0
if FireID then
set dmg = dmg+(dmg*(.05*GetUnitAbilityLevel(u,'A005')))
endif
set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
set bj_lastCreatedFogModifier = CreateFogModifierRadius(bj_groupEnumOwningPlayer,FOG_OF_WAR_VISIBLE,x,y,1000, true, false)
call FogModifierStart(bj_lastCreatedFogModifier)
call SaveUnitHandle(H,i,0,u)
call SaveUnitHandle(H,i,1,CreateUnitEx(bj_groupEnumOwningPlayer,'u006',x,y,bj_RADTODEG*Atan2(y-GetUnitY(u),x-GetUnitX(u))))
call SaveUnitHandle(H,i,2,CreateUnitEx(bj_groupEnumOwningPlayer,'u006',x,y,bj_RADTODEG*Atan2(y-GetUnitY(u),x-GetUnitX(u))))
call SaveBoolean(H,i,3,FireID)
call SaveReal(H,i,4,dmg)
call SaveFogModifierHandle(H,i,5,bj_lastCreatedFogModifier)
call TimerStart(t,.9,false,function PlanetaryDestructionAct)
set u = null
set t = null
endfunction
// Огненный дождь
private function FieryRainDmgCond takes nothing returns boolean
set bj_lastReplacedUnit = GetFilterUnit()
return not IsUnitDead(bj_lastReplacedUnit) and not IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_MAGIC_IMMUNE) and IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit))
endfunction
private function FieryRainDmg1 takes nothing returns nothing
call UnitDamageTarget(bj_lastCreatedUnit,GetEnumUnit(),TempR,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_FIRE,null)
if FireID then
call UnderworldFlames(bj_lastCreatedUnit,GetEnumUnit())
endif
endfunction
private function FieryRainDmg takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,0)
set bj_lastCreatedUnit = LoadUnitHandle(H,i,1)
if GetUnitTypeId(bj_lastCreatedUnit) > 0 then
call GroupEnumUnitsInRange(TempG,GetUnitX(u),GetUnitY(u),LoadReal(H,i,3),Condition(function FieryRainDmgCond))
set FireID = GetUnitTypeId(u) == 'u004'
set TempR = LoadReal(H,i,2)
set TF = 1
call ForGroup(TempG,function FieryRainDmg1)
set TF = 0
call GroupClear(TempG)
endif
call KillUnit(u)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
set u = null
set t = null
endfunction
private function FieryRainAct takes nothing returns nothing
local timer t = GetExpiredTimer()
local timer t1
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,0)
local integer count = LoadInteger(H,i,4)
local integer count1 = LoadInteger(H,i,5)-1
local integer count2 = count
local integer id = LoadInteger(H,i,1)
local integer i1
local real a = GetRandomReal(0,360)
local real x = LoadReal(H,i,7)
local real y = LoadReal(H,i,8)
local real sc = LoadReal(H,i,9)
local real maxr = LoadReal(H,i,3)
local real minr
local real ranr
local real fly
local real dmg = LoadReal(H,i,2)
local real rad = LoadReal(H,i,10)
set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
loop
exitwhen count <= 0
set minr = GetRandomReal(0,maxr*.2)
set ranr = GetRandomReal(minr,maxr)
call CreateUnitEx(bj_groupEnumOwningPlayer,id,x+ranr*Cos(a*bj_DEGTORAD),y+ranr*Sin(a*bj_DEGTORAD),GetRandomReal(0,360))
set fly = GetRandomReal(RainFly-RainFlyD,RainFly+RainFlyD)
call UnitAddAbility(CUEX,'Arav')
call SetUnitFlyHeight(CUEX,fly,0)
call SetUnitFlyHeight(CUEX,0,RainFly)
call SetUnitScale(CUEX,sc,sc,sc)
set t1 = CreateTimer()
set i1 = GetHandleId(t1)
call SaveUnitHandle(H,i1,0,CUEX)
call SaveUnitHandle(H,i1,1,u)
call SaveReal(H,i1,2,dmg)
call SaveReal(H,i1,3,rad)
call TimerStart(t1,fly/RainFly,false,function FieryRainDmg)
set a = a+(360/count2)
set count = count-1
endloop
set t1 = null
if count1 <= 0 or GetUnitTypeId(u) < 1 then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
else
call SaveInteger(H,i,5,count1)
call TimerStart(t,LoadReal(H,i,6),false,function FieryRainAct)
endif
set u = null
set t = null
endfunction
private function FieryRain takes nothing returns nothing
local timer t = CreateTimer()
local integer i = GetHandleId(t)
local unit u = GetTriggerUnit()
local integer lvl = GetUnitAbilityLevel(u,GetSpellAbilityId())
local integer id
local integer count
local integer count1
local real dmg
local real scale
local real radius
local real radius1
local real periodic
set FireID = GetUnitAbilityLevel(u,'B001') > 0
if FireID then
set id = 'u004'
else
set id = 'u005'
endif
if lvl == 1 then
set dmg = 25.
set scale = 1.
set radius = 400.
set radius1 = 80.
set count = 15
set count1 = 5
set periodic = 1.
elseif lvl == 2 then
set dmg = 40.
set scale = 1.25
set radius = 600.
set radius1 = 100.
set count = 20
set count1 = 7
set periodic = 1.
elseif lvl == 3 then
set dmg = 70.
set scale = 1.5
set radius = 1000.
set radius1 = 120.
set count = 30
set count1 = 10
set periodic = 1.
endif
set dmg = dmg+(GetHeroInt(u,true)*.4)
if FireID then
set dmg = dmg+(dmg*(.05*GetUnitAbilityLevel(u,'A005')))
endif
call SaveUnitHandle(H,i,0,u)
call SaveInteger(H,i,1,id)
call SaveReal(H,i,2,dmg)
call SaveReal(H,i,3,radius)
call SaveInteger(H,i,4,count)
call SaveInteger(H,i,5,count1)
call SaveReal(H,i,6,periodic)
call SaveReal(H,i,7,GetSpellTargetX())
call SaveReal(H,i,8,GetSpellTargetY())
call SaveReal(H,i,9,scale)
call SaveReal(H,i,10,radius1)
call TimerStart(t,0.,false,function FieryRainAct)
set u = null
set t = null
endfunction
// Огненная стена
private function FireWallCond takes nothing returns boolean
set bj_lastReplacedUnit = GetFilterUnit()
return not IsUnitDead(bj_lastReplacedUnit) and not IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitInGroup(bj_lastReplacedUnit,TempG1) and IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit))
endfunction
private function FireWallDamageEx takes nothing returns nothing
local unit u = GetEnumUnit()
call UnitDamageTarget(bj_lastCreatedUnit,u,TempR,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_FIRE,null)
if not IsUnitDead(u) and FireID then
call UnderworldFlames(bj_lastCreatedUnit,u)
endif
call GroupAddUnit(TempG1,u)
set u = null
endfunction
private function FireWallDamage takes nothing returns nothing
local unit u = GetEnumUnit()
call GroupEnumUnitsInRange(TempG,GetUnitX(u),GetUnitY(u),TempR1,Condition(function FireWallCond))
call ForGroup(TempG,function FireWallDamageEx)
call GroupClear(TempG)
set u = null
endfunction
private function FireWallDmg takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local group g = LoadGroupHandle(H,i,1)
local real tm = LoadReal(H,i,2)-.25
set bj_lastCreatedUnit = LoadUnitHandle(H,i,0)
set TempR = LoadReal(H,i,3)
set FireID = LoadBoolean(H,i,4)
set TempR1 = 100.
set TF = 1
call ForGroup(g,function FireWallDamage)
call GroupClear(TempG1)
set TF = 0
if tm <= 0. then
call ForGroup(g,function Kill)
call GroupClear(g)
call DestroyGroup(g)
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
else
call SaveReal(H,i,2,tm)
endif
set bj_lastCreatedUnit = null
set g = null
set t = null
endfunction
private function FireWall takes nothing returns nothing
local timer t = CreateTimer()
local integer i = GetHandleId(t)
local unit u = GetTriggerUnit()
local integer lvl = GetUnitAbilityLevel(u,GetSpellAbilityId())
local integer id
local boolean b = GetUnitAbilityLevel(u,'B001') > 0
local group g = CreateGroup()
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()
local real a = bj_RADTODEG*Atan2(y-GetUnitY(u),x-GetUnitX(u))
local real d
local real d1
local real dmg
local real dmg1
local real sc
local real tm
if lvl == 1 then
set dmg1 = 80.
set dmg = 25.
set d = 300.
set tm = 5.
set sc = .5
elseif lvl == 2 then
set dmg1 = 150.
set dmg = 40.
set d = 400.
set tm = 7.
set sc = .75
elseif lvl == 3 then
set dmg1 = 225.
set dmg = 70.
set d = 500.
set tm = 10.
set sc = 1.
endif
set dmg = dmg+(GetHeroInt(u,true)*.5)
set dmg1 = dmg1+(GetHeroInt(u,true)*.65)
if b then
set id = 'u002'
set dmg = dmg+(dmg*(.05*GetUnitAbilityLevel(u,'A005')))
set dmg1 = dmg1+(dmg1*(.05*GetUnitAbilityLevel(u,'A005')))
else
set id = 'u001'
endif
set d1 = d/2
set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
call GroupAddUnit(g,CreateUnitEx(bj_groupEnumOwningPlayer,id,x,y,GetRandomReal(0,360)))
call KillUnit(CreateUnitEx(bj_groupEnumOwningPlayer,'u000',x,y,GetRandomReal(0,360)))
call SetUnitScale(CUEX,sc,sc,sc)
if b then
call SetUnitVertexColor(CUEX,0,255,255,100)
endif
call KillUnit(CreateUnitEx(bj_groupEnumOwningPlayer,'u000',x+d1*Cos((a-90)*bj_DEGTORAD),y+d1*Sin((a-90)*bj_DEGTORAD),GetRandomReal(0,360)))
call SetUnitScale(CUEX,sc,sc,sc)
if b then
call SetUnitVertexColor(CUEX,0,255,255,100)
endif
call KillUnit(CreateUnitEx(bj_groupEnumOwningPlayer,'u000',x+d1*Cos((a+90)*bj_DEGTORAD),y+d1*Sin((a+90)*bj_DEGTORAD),GetRandomReal(0,360)))
call SetUnitScale(CUEX,sc,sc,sc)
if b then
call SetUnitVertexColor(CUEX,0,255,255,100)
endif
loop
exitwhen d1 <= 0.
call GroupAddUnit(g,CreateUnitEx(bj_groupEnumOwningPlayer,id,x+d1*Cos((a-90)*bj_DEGTORAD),y+d1*Sin((a-90)*bj_DEGTORAD),GetRandomReal(0,360)))
set d1 = d1-20.
endloop
set d1 = d/2
loop
exitwhen d1 <= 0.
call GroupAddUnit(g,CreateUnitEx(bj_groupEnumOwningPlayer,id,x+d1*Cos((a+90)*bj_DEGTORAD),y+d1*Sin((a+90)*bj_DEGTORAD),GetRandomReal(0,360)))
set d1 = d1-20.
endloop
set bj_lastCreatedUnit = u
set TempR = dmg1
set FireID = b
set TempR1 = 200.
set TF = 1
call ForGroup(g,function FireWallDamage)
call GroupClear(TempG1)
set TF = 0
call SaveUnitHandle(H,i,0,u)
call SaveGroupHandle(H,i,1,g)
call SaveReal(H,i,2,tm)
call SaveReal(H,i,3,dmg)
call SaveBoolean(H,i,4,b)
call TimerStart(t,.25,true,function FireWallDmg)
set g = null
set t = null
set u = null
endfunction
// Отталкивание юнитов с руки
private function PassiveCond takes nothing returns boolean
set bj_lastReplacedUnit = GetFilterUnit()
return IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit)) and not IsUnitDead(bj_lastReplacedUnit) and IsPointInSector(GetUnitX(bj_lastReplacedUnit),GetUnitY(bj_lastReplacedUnit),GetUnitX(bj_lastCreatedUnit),GetUnitY(bj_lastCreatedUnit),TempR3,80,300.)
endfunction
private function PassiveMove takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,0)
local real tm = LoadReal(H,i,4)+.02
local real dc = LoadReal(H,i,1)
local real a = LoadReal(H,i,2)
call SetUnitPositionEx(u,GetUnitX(u)+dc*Cos(a),GetUnitY(u)+dc*Sin(a))
call IssueImmediateOrder(u,"stop")
if GetUnitTypeId(u) < 1 or tm >= LoadReal(H,i,3) or TempR > 10 then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
else
call SaveReal(H,i,4,tm)
endif
set t = null
set u = null
endfunction
private function PassiveAct takes nothing returns nothing
local unit u = GetEnumUnit()
local timer t
local integer i
local real tm1
local real dc
if u != bj_lastLoadedUnit then
call UnitDamageTarget(bj_lastCreatedUnit,u,TempR2,false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,null)
endif
if not IsUnitDead(u) then
set t = CreateTimer()
if GetUnitAbilityLevel(bj_lastCreatedUnit,'B001') > 0 and not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)then
call UnderworldFlames(bj_lastCreatedUnit,u)
endif
if GetUnitAbilityLevel(u,'A002') > 0 then
call DestroyTimer(t)
set t = null
elseif GetUnitAbilityLevel(u,'A003') > 0 then
set tm1 = .05
set dc = 5.
else
set tm1 = .1
set dc = 10.
endif
if t != null then
set i = GetHandleId(t)
call SaveUnitHandle(H,i,0,u)
call SaveReal(H,i,1,dc)
call SaveReal(H,i,2,Atan2(GetUnitY(u)-TempR1,GetUnitX(u)-TempR))
call SaveReal(H,i,3,tm1)
call TimerStart(t,.02,true,function PassiveMove)
set t = null
endif
endif
set u = null
endfunction
private function Passive takes nothing returns nothing
set bj_lastLoadedUnit = GetTriggerUnit()
set bj_lastCreatedUnit = GetEventDamageSource()
set TempR = GetUnitX(bj_lastCreatedUnit)
set TempR1 = GetUnitY(bj_lastCreatedUnit)
set TempR2 = GetEventDamage()
set TempR3 = Atan2(GetUnitY(bj_lastLoadedUnit)-TempR1,GetUnitX(bj_lastLoadedUnit)-TempR)*bj_RADTODEG
call GroupEnumUnitsInRange(TempG,TempR,TempR1,300.,Condition(function PassiveCond))
set TF = 1
call ForGroup(TempG,function PassiveAct)
set TF = 0
call GroupClear(TempG)
set bj_lastReplacedUnit = null
set bj_lastLoadedUnit = null
endfunction
//=== Каст спеллов ===
private function SpellsCond takes nothing returns boolean
local integer i = GetSpellAbilityId()
if i == 'A001' then
call ExecuteFunc(SCOPE_PRIVATE+"FireWall")
elseif i == 'A006' then
call ExecuteFunc(SCOPE_PRIVATE+"FieryRain")
elseif i == 'A007' then
call ExecuteFunc(SCOPE_PRIVATE+"PlanetaryDestruction")
endif
return false
endfunction
//Показ урона + взаимодействие с уроном
private function trgact takes nothing returns nothing
local unit u = GetEventDamageSource()
local unit u1 = GetTriggerUnit()
local texttag tt = CreateTextTag()
call SetTextTagText(tt,I2S(R2I(GetEventDamage())),.0276)
call SetTextTagPosUnit(tt,GetTriggerUnit(),0)
call SetTextTagColor(tt,255,0,255,0)
call SetTextTagVelocity(tt,.05325*Cos(1.570788),.05325*Sin(1.570788))
call SetTextTagPermanent(tt,false)
call SetTextTagLifespan(tt,.5)
call SetTextTagFadepoint(tt,.0)
set tt = null
if TF == 0 and GetUnitAbilityLevel(u,'A004') > 0 then
call ExecuteFunc(SCOPE_PRIVATE+"Passive")
endif
set u = null
set u1 = null
endfunction
//===================================================
//---Регистрация события получения урона---
private function trgcond takes nothing returns boolean
return GetEventDamage() > 1.
endfunction
private function eve takes nothing returns nothing
call TriggerRegisterUnitEvent(trg,GetEnumUnit(),EVENT_UNIT_DAMAGED)
endfunction
private function initcond takes nothing returns boolean
local integer i = GetUnitTypeId(GetTriggerUnit())
if i != 'u000' and i != 'u001' and i != 'u002' and i != 'u004' and i != 'u005' and i != 'u00C'/*
*/ and i != 'u003' and i != 'u00B' and i != 'u009' and i != 'u008' and i != 'u00A' and i != 'u006' and i != 'u007' then
call TriggerRegisterUnitEvent(trg,GetTriggerUnit(),EVENT_UNIT_DAMAGED)
endif
return false
endfunction
//Пересборка триггера
private function reset takes nothing returns nothing
call DestroyTrigger(trg)
set trg = CreateTrigger()
call TriggerAddCondition(trg,Condition(function trgcond))
call TriggerAddAction(trg,function trgact)
call GroupEnumUnitsInRect(TempG,bj_mapInitialPlayableArea,Condition(function li))
call ForGroup(TempG,function eve)
call GroupClear(TempG)
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local region r = CreateRegion()
local integer i = 0
//Preload
call RemoveUnit(CreateUnit(Player(15),'u00C',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u003',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u00B',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u009',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u008',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u00A',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u006',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u000',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u001',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u002',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u004',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u005',0,0,0))
call RemoveUnit(CreateUnit(Player(15),'u007',0,0,0))
call RegionAddRect(r,bj_mapInitialPlayableArea)
call TriggerRegisterEnterRegion(t,r,null)
call TriggerAddCondition(t,Condition(function initcond))
set t = null
set r = null
call reset()
set t = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i = i+1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(t,Condition(function SpellsCond))
set t = null
call TimerStart(CreateTimer(),600.,true,function reset)
endfunction
endlibrary
//Счётчик
library HC initializer init
private leaderboard HB
private function HCU takes nothing returns nothing
local integer i = 0
local integer id
local location array P
local real result = 0
loop
exitwhen i >= 50
set i = i+1
set P[i] = Location(0,0)
set id = GetHandleId(P[i])
set result = result+(id-0x100000)
endloop
set result = result/i-i/2
loop
call RemoveLocation(P[i])
set P[i] = null
exitwhen i <= 1
set i = i-1
endloop
call LeaderboardSetItemValue(HB,0,R2I(result))
endfunction
private function HCA takes nothing returns nothing
set HB = CreateLeaderboard()
call LeaderboardSetLabel(HB,"Handle Counter")
call PlayerSetLeaderboard(GetLocalPlayer(),HB)
call LeaderboardDisplay(HB,true)
call LeaderboardAddItem(HB,"Handles",0,Player(0))
call LeaderboardSetSizeByItemCount(HB,1)
call HCU()
call TimerStart(GetExpiredTimer(),.05,true,function HCU)
endfunction
private function init takes nothing returns nothing
call TimerStart(CreateTimer(),0,false,function HCA)
endfunction
endlibrary
Поддерживаю комментатора выше. Можно было бы создавать/удалять юнита если у игрока есть тот или иной ресурс, место, где должны были быть предметы - юниты пустышки, при найме которых выдавать соответствующий предмет герою. У этих юнитов указать, что им нужен юнит-ресурс
возможно в предметах тоже можно указать требования и не извращаться с юнитами, я не особо много работал с ними
Заказчик: Roy Mustang Способность: Captain's pressence Выполнено: Да
Может есть какие-то баги или недоработки у системы, но я не обнаружил
Инструкция по импорту:
Просто копируешь либу mylib, можно прямо в шапку карты. Если есть библиотека с таким названием, то можешь переименовать мою
Скопируй способности и установи нужные уровни. Тебе нужно Благословение Элуны и Предмет: повышение защиты с нужным количеством уровней (пользуйся автозаполнением)
Поместить эти абилки в книгу заклинаний, с остальным я думаю сам разберёшься. Я не тестировал эту систему при большом кол-ве юнитов, так что возможны подлаги, снизить их периодичность можно будет таймером. Если рядом 2 юнита с аурой и у одного бафф будет более высокого уровня, то предпочтение отдастся ему Если нужно что-то переделать или доделать - пиши
Код
library mylib initializer init
private constant integer DummyID = 'hfoo' // Юнит для прелоада способностей
private constant integer AbilityID = 'A000' // Благословение Элуны
private constant integer AbilityID1 = 'A002' // Способность предмета на защиту
private constant integer AbilityID2 = 'A001' // Спеллбук со способностями выше
private constant integer AbilityID3 = 'A003' // Аура
private constant integer AbilityID4 = 'BOae' // Заклинание ауры
private constant integer DefenseLvl = 1 // Фактор константы повышения уровня защиты (+1 защита за уровень)
private constant integer AbilityIDMaxLvl = 10 // Максимальный уровень ауры
private constant integer AbilityID1MaxLvl = 100 // Максимальный уровень способности предмета на защиту
private constant real Radius = 725 // Максимальный радиус для поиска ауры
private constant real AuraPeriodic = 0.25 // Периодичность проверки аур
private integer TempI = 0
private group TempG = CreateGroup()
private group TempG1 = CreateGroup()
private function AuraCond2 takes nothing returns boolean
set bj_lastReplacedUnit = GetFilterUnit()
return not (IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_DEAD) or GetUnitTypeId(bj_lastReplacedUnit) < 1) and GetUnitAbilityLevel(bj_lastReplacedUnit,AbilityID3) > 0 and IsUnitAlly(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit))
endfunction
private function AuraCond takes nothing returns boolean
return GetUnitAbilityLevel(GetFilterUnit(),AbilityID4) > 0
endfunction
private function SetMaxUnitAura takes nothing returns nothing
if GetUnitAbilityLevel(GetEnumUnit(),AbilityID3) > TempI then
set TempI = GetUnitAbilityLevel(GetEnumUnit(),AbilityID3)
endif
endfunction
private function AddSetBuffs takes nothing returns nothing
set bj_lastCreatedUnit = GetEnumUnit()
call GroupEnumUnitsInRange(TempG1,GetUnitX(bj_lastCreatedUnit),GetUnitY(bj_lastCreatedUnit),Radius,Condition(function AuraCond2))
call ForGroup(TempG1,function SetMaxUnitAura)
call GroupClear(TempG1)
if GetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID2) < 1 then
call UnitAddAbility(bj_lastCreatedUnit,AbilityID2)
endif
if TempI == 0 or GetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID) > TempI then
call UnitRemoveAbility(bj_lastCreatedUnit,AbilityID2)
call UnitRemoveAbility(bj_lastCreatedUnit,AbilityID4)
else
call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID,TempI)
call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID1,TempI*DefenseLvl)
endif
set TempI = 0
endfunction
private function Aura takes nothing returns nothing
call GroupEnumUnitsInRect(TempG,bj_mapInitialPlayableArea,Condition(function AuraCond))
call ForGroup(TempG,function AddSetBuffs)
call GroupClear(TempG)
endfunction
private function CloseAbility takes nothing returns nothing
call SetPlayerAbilityAvailable(GetEnumPlayer(),AbilityID2,false)
endfunction
private function init takes nothing returns nothing
set bj_lastCreatedUnit = CreateUnit(Player(15),DummyID,0,0,0)
call UnitAddAbility(bj_lastCreatedUnit,AbilityID2)
call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID1,AbilityID1MaxLvl)
call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID,AbilityIDMaxLvl)
call UnitAddAbility(bj_lastCreatedUnit,AbilityID3)
call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID3,AbilityIDMaxLvl)
call ForForce(bj_FORCE_ALL_PLAYERS,function CloseAbility)
call RemoveUnit(bj_lastCreatedUnit)
set bj_lastCreatedUnit = null
call TimerStart(CreateTimer(),AuraPeriodic,true,function Aura)
endfunction
endlibrary
Заказчик: Obelick Способность: Притягивание Выполнено: Да
Код
function Trig_huk_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A000' and udg_Int[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] == 0
endfunction
function DBC takes real x, real y, real x1, real y1 returns real
return SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1))
endfunction
function IsUnitDead takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction
function Move takes nothing returns nothing
local integer ForLoop = 1
local integer i = 0
local real speed = 10
local real radius = 50
local real a
local real x
local real y
local real x1
local real y1
loop
exitwhen ForLoop > udg_Count
if not IsUnitDead(udg_Target[ForLoop]) and not IsUnitDead(udg_Caster[ForLoop]) then
set x = GetUnitX(udg_Target[ForLoop])
set y = GetUnitY(udg_Target[ForLoop])
set x1 = GetUnitX(udg_Caster[ForLoop])
set y1 = GetUnitY(udg_Caster[ForLoop])
set a = Atan2(y1-y,x1-x)
call SetUnitX(udg_Target[ForLoop],x+speed*Cos(a))
call SetUnitY(udg_Target[ForLoop],y+speed*Sin(a))
if DBC(x1,y1,x+speed*Cos(a),y+speed*Sin(a)) < radius then
set i = 1
endif
else
set i = 1
endif
if i == 1 then
set udg_Int[GetPlayerId(GetOwningPlayer(udg_Caster[ForLoop]))] = 0
if udg_Count > 1 then
set udg_Caster[ForLoop] = udg_Caster[udg_Count]
set udg_Target[ForLoop] = udg_Target[udg_Count]
set ForLoop = ForLoop - 1
else
call PauseTimer(udg_Timer)
endif
call PauseUnit(udg_Target[udg_Count],false)
set udg_Caster[udg_Count] = null
set udg_Target[udg_Count] = null
set udg_Count = udg_Count - 1
set i = 0
endif
set ForLoop = ForLoop + 1
endloop
endfunction
function Trig_huk_Actions takes nothing returns nothing
if udg_Count == 0 then
call TimerStart(udg_Timer,0.03,true,function Move)
endif
set udg_Count = udg_Count + 1
set udg_Caster[udg_Count] = GetTriggerUnit()
set udg_Target[udg_Count] = GetSpellTargetUnit()
call PauseUnit(udg_Target[udg_Count],true)
set udg_Int[GetPlayerId(GetOwningPlayer(udg_Caster[udg_Count]))] = 1
endfunction
//===========================================================================
function InitTrig_huk takes nothing returns nothing
set gg_trg_huk = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_huk, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_huk, Condition( function Trig_huk_Conditions ) )
call TriggerAddAction( gg_trg_huk, function Trig_huk_Actions )
endfunction
Заказчик: Roy Mustang Способность: Дикий Рывок Выполнено: Да
Инструкция по импорту
Либо счётчик прикалывался, либо я просто не смог найти что у меня там утекает
Копируешь либу mylib в свою карту, если у тебя уже есть библиотека с таким названием - то переименовываешь мою
Дальность применения и перезарядка могут быть любыми, спелл муи, но может произойти перезапись переменной последнего кастера для гуи (ты поймёшь о чем я, когда глянешь как на гуи урон наносится в канал4)
Всё в библиотеке приватное за исключением функции WildDash
Первый раз пролагивает из-за абилок и эффектов, поэтому советую использовать прелоад
Если какие-то абилки тебе не нужны, то можешь выставить 0 и не создавать абилку
Большая часть настроек на гуи, остальные вверху библиотеки
Я так же сделал отдельную переменную где записывается достижение максимальной скорости кастера, ты можешь использовать её, например, для дополнительного урона (я оставил пример)
Если у тебя уже используется название этой переменной, то можешь воспользоваться дефайном и закинуть туда название (я оставил пример)
С последним кастером так же
Расскажу коротко о том, как работает переменная LastCaster. Перед любым нанесением урона, а так же при дамми-касте абилок для гуишных действий, эта переменная выставляется на кастера. Перезапись очень вероятна для гуишных действий (потому что даммикаст с задержкой), поэтому советую пользоваться с осторожностью. На моём примере с гуи уроном толкать юнитов может один кастер, а дамажить в итоге другой, но по коду с ней всё нормально и там есть специальная переменная для настройки урона при расталкивании, стоит на 0.00, если перенесёшь урон туда, то каждый кастер будет именно свои цели дамажить
Если что-то нужно доделать или переделать - пиши
Код
library mylib
private hashtable H = InitHashtable()
//define private H = udg_Hash // если у тебя уже есть хэш-таблица, разкомменти эту строку вписав вместо udg_Hash название своей хэш-таблицы и удали предыдущую строку, если названия совпадают - удали обе строки
//define private udg_CasterSpeed = название твоей переменной
//define private udg_LastCaster = название твоей переменной
private constant attacktype AttackType = ATTACK_TYPE_MAGIC // Тип атаки
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL // Тип урона
private constant integer DummyID = 'u000' // Дамми-юнит для каста способностей
private constant integer ItemID = 'I000' // Предмет для проверки проходимости местности
private constant integer AbilityID = 'A001' // Способность при завершении разбега (для своих действий)
private constant integer AbilityID1 = 'A002' // Способность при столкновении кастера с препятствием
private constant integer AbilityID2 = 'A003' // Способность при столкновении цели с препятствием
private constant integer AbilityID3 = 'A004' // Способность при расталкивании юнитов
private constant integer AbilityID4 = 'A005' // Способность при завершении разбега если был задет таргет, применяемая на кастера
private constant integer AbilityID5 = 'A006' // Способность при завершении разбега если был задет таргет, применяемая на таргета
// Приказ каждой способности должен быть "channel"
//=============================================================================================
private group TempG = CreateGroup()
private real TempR = 0.
private real TempR1 = 0.
private real TempR2 = 0.
private real TempX = 0.
private real TempY = 0.
private timer TempT = null
private function DBC takes real x, real y, real x1, real y1 returns real
return SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1))
endfunction
private function IsUnitDead takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction
private function SetUnitPositionEx takes unit u, real x, real y returns nothing
local item i = CreateItem(ItemID,x,y)
set TempR = DBC(GetItemX(i),GetItemY(i),x,y)
if TempR > 10 then
call SetUnitX(u,GetItemX(i))
call SetUnitY(u,GetItemY(i))
else
call SetUnitX(u,x)
call SetUnitY(u,y)
endif
call RemoveItem(i)
set i = null
endfunction
private function SetAnim takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
call SetUnitAnimationByIndex(LoadUnitHandle(H,i,0),LoadInteger(H,i,1))
call DestroyTimer(t)
call FlushChildHashtable(H,i)
set t = null
endfunction
private function CastAbil takes unit u, integer i returns nothing
local unit u1 = CreateUnit(Player(15),DummyID,GetUnitX(u),GetUnitY(u),GetUnitFacing(u))
if i != 0 then
call UnitAddAbility(u1,i)
call IssueTargetOrder(u1,"channel",u)
endif
call UnitApplyTimedLife(u1,'BTLF',1.)
set u1 = null
endfunction
private function Dmg takes nothing returns nothing
local unit u = GetEnumUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real a = Atan2(y-TempY,x-TempX)
call SetUnitPositionEx(u,x+TempR1*Cos(a),y+TempR1*Sin(a))
call CastAbil(u,AbilityID3)
if TempR2 != 0. then
call UnitDamageTarget(udg_LastCaster,GetEnumUnit(),TempR2,false,false,AttackType,DamageType,null)
endif
set u = null
endfunction
private function Discarding takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,0)
local real s = LoadReal(H,i,1)
local real d = LoadReal(H,i,2)
local real a = LoadReal(H,i,4)
local real x = GetUnitX(u)+s*Cos(a)
local real y = GetUnitY(u)+s*Sin(a)
local real dd = LoadReal(H,i,6)+s
call SetUnitPositionEx(u,x,y)
if TempR > 10 then
set udg_LastCaster = LoadUnitHandle(H,i,5)
call CastAbil(u,AbilityID2)
call UnitDamageTarget(udg_LastCaster,u,LoadReal(H,i,3),false,false,AttackType,DamageType,null)
endif
if dd >= d or TempR > 10 or GetUnitTypeId(u) < 1 then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
else
call SaveReal(H,i,6,dd)
endif
set t = null
set u = null
endfunction
private function Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,0)
local unit u1 = LoadUnitHandle(H,i,1)
local real r = LoadReal(H,i,4)
local real a = Atan2(GetUnitY(u1)-GetUnitY(u),GetUnitX(u1)-GetUnitX(u))
local real a1 = Atan2(GetUnitY(u)-GetUnitY(u1),GetUnitX(u)-GetUnitX(u1))
local real ss = LoadReal(H,i,16)
local real s = LoadReal(H,i,6)+ss
local real x = GetUnitX(u)+s*Cos(a)
local real y = GetUnitY(u)+s*Sin(a)
local real x1 = GetUnitX(u1)+r*Cos(a1)
local real y1 = GetUnitY(u1)+r*Sin(a1)
local integer i2 = 0
local integer i1
set udg_LastCaster = u
call SetUnitFacing(u,a*bj_RADTODEG)
if DBC(x,y,x1,y1)-(r/2) < s then
call SetUnitPositionEx(u,x1,y1)
call UnitDamageTarget(u,u1,LoadReal(H,i,2),false,false,AttackType,DamageType,null)
set TempT = CreateTimer()
set i1 = GetHandleId(TempT)
call SaveUnitHandle(H,i1,0,u1)
call SaveReal(H,i1,1,LoadReal(H,i,11))
call SaveReal(H,i1,2,LoadReal(H,i,12))
call SaveReal(H,i1,3,LoadReal(H,i,2))
call SaveReal(H,i1,4,Atan2(GetUnitY(u1)-GetUnitY(u),GetUnitX(u1)-GetUnitX(u)))
call SaveUnitHandle(H,i1,5,u)
call TimerStart(TempT,LoadReal(H,i,10),true,function Discarding)
set TempT = null
set i2 = 2
else
call SetUnitPositionEx(u,x,y)
if TempR > 10 then
call CastAbil(u,AbilityID1)
set i2 = 1
endif
endif
set TempR2 = LoadReal(H,i,3)
set TempR1 = LoadReal(H,i,14)
set TempX = GetUnitX(u)
set TempY = GetUnitY(u)
call GroupEnumUnitsInRange(TempG,TempX,TempY,r,LoadBooleanExprHandle(H,i,13))
call ForGroup(TempG,function Dmg)
call GroupClear(TempG)
if i2 == 1 then
set udg_LastCaster = u
set TempR2 = LoadReal(H,i,7)
call GroupEnumUnitsInRange(TempG,TempX,TempY,LoadReal(H,i,8),LoadBooleanExprHandle(H,i,13))
call ForGroup(TempG,function Dmg)
call GroupClear(TempG)
endif
if i2 == 1 or i2 == 2 or IsUnitDead(u) or IsUnitDead(u1) then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
call CastAbil(u,AbilityID)
if i2 == 2 then
call CastAbil(u,AbilityID4)
call CastAbil(u1,AbilityID5)
endif
set udg_CasterSpeed = s
else
call SaveReal(H,i,16,ss+LoadReal(H,i,5))
endif
set u = null
set u1 = null
set t = null
endfunction
function WildDash takes unit caster, unit target, integer animation, real dmg, real dmg1, real radius, real sspeed, real speed, real dmg2, real radius1, real tmper, real dcper, real dc, real dd, real dc1, boolexpr b returns nothing
local timer t = CreateTimer()
local integer i = GetHandleId(t)
call SaveUnitHandle(H,i,0,caster)
call SaveUnitHandle(H,i,1,target)
call SaveReal(H,i,2,dmg)
call SaveReal(H,i,3,dmg1)
call SaveReal(H,i,4,radius)
call SaveReal(H,i,5,sspeed)
call SaveReal(H,i,6,speed)
call SaveReal(H,i,7,dmg2)
call SaveReal(H,i,8,radius1)
call SaveReal(H,i,9,tmper)
call SaveReal(H,i,10,dcper)
call SaveReal(H,i,11,dc)
call SaveReal(H,i,12,dd)
call SaveBooleanExprHandle(H,i,13,b)
call SaveReal(H,i,14,dc1)
call TimerStart(t,tmper,true,function Move)
set t = CreateTimer()
call SaveUnitHandle(H,GetHandleId(t),0,caster)
call SaveInteger(H,GetHandleId(t),1,animation)
call TimerStart(t,0.00,false,function SetAnim)
set t = null
endfunction
endlibrary
Заказчик: Roy Mustang Способность: Прыжок Выполнено: Да
Инструкция по импорту:
Просто импортируешь либу mylib в свою карту (можно прямо в шапку)
Дальность применения и перезарядка могут быть любыми, спелл муи
Копируй все созданные на гуи переменные
Сам спелл юзается через функцию
function Jump takes unit caster, unit target, real dmg, real speed, real height, real tmper, boolexpr b, real radius, real dbtm returns nothing
Ты увидишь её на кастомскрипте, всё что тебе там в принципе можно поменять это периодичность таймера и названия переменных на свои
Замедление реализовано через ауру, чтобы с другими твоими замедлениями не конфликтовать
Ты можешь использовать свою хэш-таблицу, не создавая новой (их лимит 255 по моему), но учти, ради ауры мне пришлось взять одну ячейку юнита, то бишь если ты там что-то записываешь в юнита и не помнишь последнюю свободную ячейку, то лучше новую хэш-таблицу создать, чтобы спелл тебе ничего там не сломал. Ах да, использовать свою хэш-таблицу нужно через дефайн, я оставил там комментарии, но опять же, дефайн может вызвать какие-то непонятки и конфликтовать с кодом других людей. Если название твоей хэш-таблицы соответствует моей и ты хочешь её подставить, то просто удали private hashtable H = InitHashtable()
По коду лишь пару переменных тебе нужно изменить:
private constant attacktype AttackType = ATTACK_TYPE_MAGIC // Тип атаки
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL // Тип урона
private constant integer AbilityID = 'A001' // Равкод ауры замедления
private constant integer AbilityID1 = 'Basl' // Равкод заклинания из ауры замедления
private constant integer UnitH = 0 // Свободная ячейка юнита для ауры
private constant integer ItemID = 'I000' // Получение предмета после завершения прыжка для своих действий
Я добавил показательный триггер пример, где юнит после приземления создаёт кратер, там можешь делать свои действия на гуи. Например выбрать всех юнитов вокруг юнита и повесить спецэффект. Ах да, если тебе не нужно замедление именно с ауры и ты предпочтёшь какой-нибудь даммикаст, то можешь в коде указать равкод ауры 0.
Всё в либе приватное и не должно конфликтовать с чужим кодом, исключение сама функция Jump. Если нужно что-то переделать или доделать, то пиши
Код
library mylib initializer init
private hashtable H = InitHashtable()
//define private H = udg_Hash // если у тебя уже есть хэш-таблица, разкомменти эту строку вписав вместо udg_Hash название своей хэш-таблицы и удали предыдущую строку
//Внимание! Используется ячейка юнита в хэш-таблице, чтобы не сбивались ауры, если ты записывал какие-то значения в юнита и не помнишь ячейку, лучше создать ещё одну хэш-таблицу
private constant attacktype AttackType = ATTACK_TYPE_MAGIC // Тип атаки
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL // Тип урона
private constant integer AbilityID = 'A001' // Равкод ауры замедления
private constant integer AbilityID1 = 'Basl' // Равкод заклинания из ауры замедления
private constant integer UnitH = 0 // Свободная ячейка юнита для ауры
private constant integer ItemID = 'I000' // Получение предмета после завершения прыжка для своих действий
private location LFZ = Location(0,0)
private group TempG = CreateGroup()
private group DebuffG = CreateGroup()
private real TempR = 0.
private real TempR1 = 0.
private timer DebuffT = CreateTimer()
private function DBC takes real x, real y, real x1, real y1 returns real
return SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1))
endfunction
private function ParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)
endfunction
private function GetLocZ takes real x, real y returns real
call MoveLocation(LFZ,x,y)
return GetLocationZ(LFZ)
endfunction
private function RemoveF takes nothing returns nothing
local unit u = GetEnumUnit()
local integer i = GetHandleId(u)
local real r = LoadReal(H,i,UnitH)-.01
if r <= 0. then
call RemoveSavedReal(H,i,UnitH)
call GroupRemoveUnit(DebuffG,u)
call UnitRemoveAbility(u,AbilityID)
call UnitRemoveAbility(u,AbilityID1)
else
call SaveReal(H,i,UnitH,r)
endif
set u = null
endfunction
private function Remove takes nothing returns nothing
call ForGroup(DebuffG,function RemoveF)
endfunction
private function Dmg takes nothing returns nothing
local unit u = GetEnumUnit()
call UnitDamageTarget(bj_lastCreatedUnit,GetEnumUnit(),TempR,false,false,AttackType,DamageType,null)
if not IsUnitType(u,UNIT_TYPE_DEAD) then
if LoadReal(H,GetHandleId(u),UnitH) <= 0. and AbilityID != 0 then
set bj_groupCountUnits = 0
call ForGroup(DebuffG,function CountUnitsInGroupEnum)
call GroupAddUnit(DebuffG,u)
call UnitAddAbility(u,AbilityID)
if bj_groupCountUnits == 0 then
call TimerStart(DebuffT,.01,true,function Remove)
endif
endif
call SaveReal(H,GetHandleId(u),UnitH,TempR1)
endif
set u = null
endfunction
private function Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = LoadUnitHandle(H,i,0)
local real s = LoadReal(H,i,2)
local real a = LoadReal(H,i,4)
local real x = GetUnitX(u)+s*Cos(a)
local real y = GetUnitY(u)+s*Sin(a)
local real d = LoadReal(H,i,5)-s
local real d1 = LoadReal(H,i,9)+s
local real d2 = LoadReal(H,i,7)
call SetUnitX(u,x)
call SetUnitY(u,y)
call SetUnitFlyHeight(u,LoadReal(H,i,12)+ParabolaZ(LoadReal(H,i,6),d2,d)+(LoadReal(H,i,8)-GetLocZ(x,y)),0)
if d2-d1 < s then
set s = d2-d1
set x = GetUnitX(u)+s*Cos(a)
set y = GetUnitY(u)+s*Sin(a)
call SetUnitX(u,x)
call SetUnitY(u,y)
call SetUnitFlyHeight(u,LoadReal(H,i,12),0)
call PauseUnit(u,false)
call SetUnitPathing(u,true)
call UnitRemoveAbility(u,'Arav')
set bj_lastCreatedUnit = u
set TempR = LoadReal(H,i,1)
set TempR1 = LoadReal(H,i,13)
call GroupEnumUnitsInRange(TempG,x,y,LoadReal(H,i,10),LoadBooleanExprHandle(H,i,11))
call ForGroup(TempG,function Dmg)
call GroupClear(TempG)
call DestroyBoolExpr(LoadBooleanExprHandle(H,i,11))
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H,i)
call UnitAddItem(u,CreateItem(ItemID,0,0))
else
call SaveReal(H,i,5,d)
call SaveReal(H,i,9,d1)
endif
set u = null
set t = null
endfunction
function Jump takes unit caster, unit target, real dmg, real speed, real height, real tmper, boolexpr b, real radius, real dbtm returns nothing
local timer t = CreateTimer()
local integer i = GetHandleId(t)
local real d = DBC(GetUnitX(caster),GetUnitY(caster),GetUnitX(target),GetUnitY(target))
call SaveUnitHandle(H,i,0,caster)
call SaveReal(H,i,1,dmg)
call SaveReal(H,i,2,speed)
call SaveReal(H,i,3,tmper)
call SaveReal(H,i,4,Atan2(GetUnitY(target)-GetUnitY(caster),GetUnitX(target)-GetUnitX(caster)))
call SaveReal(H,i,5,d)
call SaveReal(H,i,6,height)
call SaveReal(H,i,7,d)
call SaveReal(H,i,8,GetLocZ(GetUnitX(caster),GetUnitY(caster)))
call SaveReal(H,i,10,radius)
call SaveBooleanExprHandle(H,i,11,b)
call SaveReal(H,i,12,GetUnitFlyHeight(caster))
call SaveReal(H,i,13,dbtm)
call TimerStart(t,tmper,true,function Move)
call UnitAddAbility(caster,'Arav')
call SetUnitPathing(caster,false)
call PauseUnit(caster,true)
set t = null
endfunction
private function Res takes nothing returns nothing
set bj_groupCountUnits = 0
call ForGroup(DebuffG,function CountUnitsInGroupEnum)
if bj_groupCountUnits == 0 then
call PauseTimer(DebuffT)
endif
endfunction
private function init takes nothing returns nothing
call TimerStart(CreateTimer(),1,true,function Res)
endfunction
endlibrary
» Блог им. rsfghd / Спеллпак Приватника Ада
На самом деле на этот прогресс ушло куда больше времени и недоскиллов, но я всё равно не доволен результатом. Типо всё что в этой карте - банальщина, видели миллион раз, так оно ещё и криво написано)
Думаю мне просто нужна конструктивная критика с предложениями как можно сделать лучше
» WarCraft 3 / Система создания предметов
Могу наклепать позже, если никто не преуспеет
» WarCraft 3 / Не срабатывает событие на изменение real var. Игнор строки кода.
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
https://www.xgm.guru/files/100/123666/comments/468725/Jump_[re]....
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
Ред. rsfghd
» WarCraft 3 / Странное поведение функции
Ред. rsfghd
» WarCraft 3 / Странное поведение функции
» WarCraft 3 / Странное поведение функции
Ред. rsfghd
» Блог им. rsfghd / Спеллпак Приватника Ада
хотя кого это говнище мотивировать будет, лол)
upd в видео музыка
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
» WarCraft 3 / Тригерное получение золота после атаки
map_maiker, сорян)
» WarCraft 3 / Тригерное получение золота после атаки
Если ты про 1.26, то тут событие срабатывает только после получения урона. На рефе есть _DAMAGING, вот оно до урона срабатывает
» WarCraft 3 / Даммикаст предметом
» WarCraft 3 / Тригерное получение золота после атаки
ssbbssc, думаю мы все бы учли этот факт и уведомили автора об неправильном событии, но у него всё норм)
» WarCraft 3 / Даммикаст предметом
» WarCraft 3 / Тригерное получение золота после атаки
» WarCraft 3 / Система создания предметов
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
Заклинание готово!
Способность: Captain's pressence
Выполнено: Да
Скопируй способности и установи нужные уровни. Тебе нужно Благословение Элуны и Предмет: повышение защиты с нужным количеством уровней (пользуйся автозаполнением)
Поместить эти абилки в книгу заклинаний, с остальным я думаю сам разберёшься. Я не тестировал эту систему при большом кол-ве юнитов, так что возможны подлаги, снизить их периодичность можно будет таймером. Если рядом 2 юнита с аурой и у одного бафф будет более высокого уровня, то предпочтение отдастся ему
Если нужно что-то переделать или доделать - пиши
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
Заказ принят
Способность: Captain's pressence
Примерные сроки исполнения: завтра (16.05.21)
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
Заклинание готово!
Способность: Притягивание
Выполнено: Да
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
Заклинание готово!
Способность: Дикий Рывок
Выполнено: Да
Копируешь либу mylib в свою карту, если у тебя уже есть библиотека с таким названием - то переименовываешь мою
Дальность применения и перезарядка могут быть любыми, спелл муи, но может произойти перезапись переменной последнего кастера для гуи (ты поймёшь о чем я, когда глянешь как на гуи урон наносится в канал4)
Всё в библиотеке приватное за исключением функции WildDash
Первый раз пролагивает из-за абилок и эффектов, поэтому советую использовать прелоад
Если какие-то абилки тебе не нужны, то можешь выставить 0 и не создавать абилку
Большая часть настроек на гуи, остальные вверху библиотеки
Я так же сделал отдельную переменную где записывается достижение максимальной скорости кастера, ты можешь использовать её, например, для дополнительного урона (я оставил пример)
Если у тебя уже используется название этой переменной, то можешь воспользоваться дефайном и закинуть туда название (я оставил пример)
С последним кастером так же
Расскажу коротко о том, как работает переменная LastCaster. Перед любым нанесением урона, а так же при дамми-касте абилок для гуишных действий, эта переменная выставляется на кастера. Перезапись очень вероятна для гуишных действий (потому что даммикаст с задержкой), поэтому советую пользоваться с осторожностью. На моём примере с гуи уроном толкать юнитов может один кастер, а дамажить в итоге другой, но по коду с ней всё нормально и там есть специальная переменная для настройки урона при расталкивании, стоит на 0.00, если перенесёшь урон туда, то каждый кастер будет именно свои цели дамажить
Если что-то нужно доделать или переделать - пиши
» WarCraft 3 / Даммикаст предметом
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
Заклинание готово!
Способность: Прыжок
Выполнено: Да
Дальность применения и перезарядка могут быть любыми, спелл муи
Копируй все созданные на гуи переменные
Сам спелл юзается через функцию
Замедление реализовано через ауру, чтобы с другими твоими замедлениями не конфликтовать
Ты можешь использовать свою хэш-таблицу, не создавая новой (их лимит 255 по моему), но учти, ради ауры мне пришлось взять одну ячейку юнита, то бишь если ты там что-то записываешь в юнита и не помнишь последнюю свободную ячейку, то лучше новую хэш-таблицу создать, чтобы спелл тебе ничего там не сломал. Ах да, использовать свою хэш-таблицу нужно через дефайн, я оставил там комментарии, но опять же, дефайн может вызвать какие-то непонятки и конфликтовать с кодом других людей. Если название твоей хэш-таблицы соответствует моей и ты хочешь её подставить, то просто удали private hashtable H = InitHashtable()
По коду лишь пару переменных тебе нужно изменить:
Всё в либе приватное и не должно конфликтовать с чужим кодом, исключение сама функция Jump.
Если нужно что-то переделать или доделать, то пиши
» WarCraft 3 / Не считывает строку в условие
Ред. rsfghd
» WarCraft 3 / Способности и алгоритмы на заказ
Заказ принят
Способность: Прыжок
Примерный срок выполнения: Спелл закину сегодня ближе к вечеру
Заказ принят
Способность: Дикий Рывок
Примерный срок выполнения: Либо вместе с предыдущей абилкой, либо на следующий день