Я решил модифицировать вурдалаков, теперь это снорки, ы
Перепрыгивают через препятствия, приоритетная для них цель с самым низким хп, если хп у всех одинаковое, то прыгает на ближайшего
Однако эта системка не поддерживает громадное кол-во вурдалаков, оно начнёт подлагивать, лимиты я не проверял и утечек вроде нет. Начинает лагать с того момента, как юниты уже сами по себе двигаются рывками. Вурдалаки паузятся во время полёта, так что их вроде нельзя продамажить и что-то вообще сделать, в своей карте паузу заменю на морф через руну в стража и отниму абилку атаковать (потом верну на свои места само собой)
Карта с видосом в комментах
Перепрыгивают через препятствия, приоритетная для них цель с самым низким хп, если хп у всех одинаковое, то прыгает на ближайшего
Однако эта системка не поддерживает громадное кол-во вурдалаков, оно начнёт подлагивать, лимиты я не проверял и утечек вроде нет. Начинает лагать с того момента, как юниты уже сами по себе двигаются рывками. Вурдалаки паузятся во время полёта, так что их вроде нельзя продамажить и что-то вообще сделать, в своей карте паузу заменю на морф через руну в стража и отниму абилку атаковать (потом верну на свои места само собой)
Карта с видосом в комментах
код
library mylib initializer init{
private hashtable H = InitHashtable()
private location LFZ = Location(0,0)
private group TempG = CreateGroup()
private group TempG1 = CreateGroup()
private bool IsUnitDead(unit u){
return IsUnitType(u,UNIT_TYPE_DEAD) || GetUnitTypeId(u) < 1
}
function DistanceBetweenCoordinates takes real x, real y, real x1, real y1 returns real
return SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1))
endfunction
private real GetLocZ(real x, real y){
MoveLocation(LFZ,x,y); return GetLocationZ(LFZ)
}
function ParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)
endfunction
private bool jump1_cond(){
bj_lastReplacedUnit = GetFilterUnit()
return !IsUnitDead(bj_lastReplacedUnit) && IsUnitEnemy(bj_lastReplacedUnit,bj_groupEnumOwningPlayer)
}
private void jump1(){
unit u = GetEnumUnit(), u1, u2
real r, hp, hp1, d, x = GetUnitX(u), y = GetUnitY(u)
bj_groupEnumOwningPlayer = GetOwningPlayer(u)
GroupEnumUnitsInRange(TempG,x,y,500,Condition(function jump1_cond))
bj_groupEnumOwningPlayer = null
if FirstOfGroup(TempG) != null{
r = 501; hp = 999999
while FirstOfGroup(TempG) != null{
u1 = FirstOfGroup(TempG)
d = DistanceBetweenCoordinates(x,y,GetUnitX(u1),GetUnitY(u1))
hp1 = GetWidgetLife(u1)
if d < r && hp1 <= hp{
r = d; hp = hp1; u2 = u1
}
GroupRemoveUnit(TempG,u1); u1 = null
}
IssueTargetOrder(u,"thunderbolt",u2); u2 = null
}
u = null
}
private bool vurd(){
bj_lastReplacedUnit = GetFilterUnit(); bj_lastCreatedUnit = null
/*
bj_groupEnumOwningPlayer = GetOwningPlayer(bj_lastReplacedUnit)
GroupEnumUnitsInRange(TempG,GetUnitX(bj_lastReplacedUnit),GetUnitY(bj_lastReplacedUnit),500,Condition(function jump1_cond))
bj_groupEnumOwningPlayer = null
bj_lastCreatedUnit = FirstOfGroup(TempG)
if bj_lastReplacedUnit != null{GroupClear(TempG)}*/ // Попытка оптимизации
return GetUnitTypeId(bj_lastReplacedUnit) == 'u000' && !IsUnitDead(bj_lastReplacedUnit)// && bj_lastReplacedUnit != null
}
private void jump(){
GroupEnumUnitsInRect(TempG1,bj_mapInitialPlayableArea,Condition(function vurd))
if FirstOfGroup(TempG1) != null{
ForGroup(TempG1,function jump1)
GroupClear(TempG1)
}
}
//==========
private void init_act1(){
timer t = GetExpiredTimer(); int i = GetHandleId(t), tf = 0
unit u = LoadUnitHandle(H,i,0)
real s = LoadReal(H,i,4), a = LoadReal(H,i,5), x = GetUnitX(u)+s*Cos(a), y = GetUnitY(u)+s*Sin(a),/*
*/d = LoadReal(H,i,2)-s, d1, x1, y1
if IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY){
x1 = x; y1 = y; d1 = d; tf = 1
while d1 > 0 && tf == 1{
x1 = x1+s*Cos(a); y1 = y1+s*Sin(a); d1 = d1-s
if !IsTerrainPathable(x1,y1,PATHING_TYPE_WALKABILITY){tf = 0}
}
}
if tf == 1 || d+s <= 0 || IsUnitDead(u){
SetUnitFlyHeight(u,0,500)
if !IsUnitDead(u){
PauseUnit(u,false); UnitRemoveAbility(u,'Arav')
unit u1 = LoadUnitHandle(H,i,1)
if !IsUnitDead(u1){
IssueTargetOrder(u,"attack",u1)
DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Critters\\Albatross\\CritterBloodAlbatross.mdl",u1,"chest"))
UnitDamageTarget(u,u1,GetRandomReal(15,20),true,false,ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WOOD_MEDIUM_BASH)
}
u1 = null
}
PauseTimer(t); DestroyTimer(t); FlushChildHashtable(H,i)
}else{
SetUnitX(u,x); SetUnitY(u,y)
SetUnitFlyHeight(u,ParabolaZ(100,LoadReal(H,i,3),d)+(LoadReal(H,i,6)-GetLocZ(x,y)),0)
SaveReal(H,i,2,d)
}
t = null; u = null
}
private void init_act(){
timer t = CreateTimer(); int i = GetHandleId(t)
unit u = GetSpellAbilityUnit(), u1 = GetSpellTargetUnit()
real x = GetUnitX(u), y = GetUnitY(u), x1 = GetUnitX(u1), y1 = GetUnitY(u1), a = Atan2(y1-y,x1-x),/*
*/d = DistanceBetweenCoordinates(x,y,x1,y1)+50
SetUnitFacing(u,a*bj_RADTODEG)
UnitAddAbility(u,'Arav')
PauseUnit(u,true)
SaveUnitHandle(H,i,0,u); SaveUnitHandle(H,i,1,u1)
SaveReal(H,i,2,d); SaveReal(H,i,3,d)
SaveReal(H,i,4,(GetUnitMoveSpeed(u)*.01)+10)
SaveReal(H,i,5,a)
SaveReal(H,i,6,GetLocZ(x,y))
TimerStart(t,.01,true,function init_act1)
t = null; u = null; u1 = null
}
private bool init_cond(){return GetSpellAbilityId() == 'A000'}
private void init(){
trigger t = CreateTrigger(); int i = 0
while i < 16{
TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
i++
}
TriggerAddCondition(t,Condition(function init_cond))
TriggerAddAction(t,function init_act)
t = null; t = CreateTrigger()
TriggerRegisterTimerEvent(t,.5,true)
TriggerAddAction(t,function jump)
t = null
}
}
Карта не планируется для импорта, поэтому никаких настроек я не оставлял, я просто захотел проверить идею, возникшую в моей голове
Ред. rsfghd
видео со старой версии
FFF
да и вообще абсолютно каждый спелл бы свой переделал, но такой завал по жизни что попросту нет времени
спасибо, что интересуешься моими ресурсами, приятно на душе