Как то делал способность, которая похищает % атаки у врагов поблизости на несколько секунд, используя мемхак. Способность так то вроде не сложная в реализации, но вот про новичков наверное не по адресу, ибо написано на vjass. Если интересно прокоментирую код и обьясню что и зачем:
код
globals
integer HASH_EXTRA_DAMAGE_INDEX = 5
integer array abilityAddDamageLvl //Массив способностей для увеличения дополнительного урона
endglobals
function GetUnitExtraDamage takes unit u returns integer
local integer iD = GetHandleId( u )
local integer ammount
set ammount = LoadInteger( gg_htb_HashData, iD, HASH_EXTRA_DAMAGE_INDEX )
return ammount
endfunction
function SetUnitExtraDamage takes unit u, integer ammount returns nothing
local integer iD = GetHandleId( u )
local integer power = 12
local integer index = 0
local integer rest
if ammount > 8191 then
set ammount = 8191
endif
loop
call UnitRemoveAbility( u, abilityAddDamageLvl[index] )
exitwhen index == 12
set index = index + 1
endloop
if ammount > 0 then
set rest = ammount
loop
exitwhen rest <= 0
if R2I( Pow( 2, power ) ) > rest then
set power = power - 1
elseif R2I( Pow( 2, power ) ) <= rest then
call UnitAddAbility( u, abilityAddDamageLvl[power] )
call UnitMakeAbilityPermanent( u, true, abilityAddDamageLvl[power] )
set rest = rest - R2I( Pow( 2, power ) )
set power = power - 1
endif
endloop
call SaveInteger( gg_htb_HashData, iD, HASH_EXTRA_DAMAGE_INDEX, ammount )
endif
endfunction
function Only_Alive_Player_No_Dummy_No_Ward_Filter takes nothing returns boolean
set bj_lastFilterUnit = GetFilterUnit( )
return not ( IsUnitDead( bj_lastFilterUnit ) or IsUnitWard( bj_lastFilterUnit ) or IsUnitType( bj_lastFilterUnit, UNIT_TYPE_MECHANICAL ) or IsUnitIllusion( bj_lastFilterUnit ) or IsUnitHidden( bj_lastFilterUnit ) )
endfunction
function Group_Remove_Damage_Enum takes nothing returns nothing
local unit ally = GetEnumUnit( )
local TriggerData dd = bj_forceRandomConsidered
local integer bonus = R2I( GetUnitExtraDamage( ally ) - dd.dmg )
call UnitRemoveAbility( ally, 'B00H' )
call UnitRemoveAbility( ally, 'A0DV' )
call SetUnitExtraDamage( ally, bonus )
call SaveInteger( gg_htb_HashData, GetHandleId(ally), HASH_EXTRA_DAMAGE_INDEX, bonus )
call RemoveSavedHandle( gg_htb_HashData, ExSpeedSteal, GetHandleId(ally) )
set ally = null
endfunction
function Group_Add_Damage_Enum takes nothing returns nothing
local TriggerData dd = bj_forceRandomConsidered
local unit ally = GetEnumUnit( )
local integer bonus = 0
local integer pBuff
call TriggerRegisterDeathEvent( dd.trg, ally )
call SaveTriggerHandle( gg_htb_HashData, ExSpeedSteal, GetHandleId(ally), dd.trg )
call SetUnitExtraDamage( ally, R2I( GetUnitExtraDamage( ally ) + dd.dmg ) )
call UnitAddAbility( ally, 'A0DV' )
call UnitMakeAbilityPermanent( ally, true, 'A0DV' )
call UnitAddAbility( ally, 'A03W' )
set pBuff = GetUnitAbility( ally, 'B00H' )
if pBuff < 1 then
call BJDebugMsg(DEBUG+" "+ GetAbilityEffectById( 'A0DV', EFFECT_TYPE_SPECIAL, 1 ) )
call BJDebugMsg(INFO)
return
endif
set dd.c = TimerGetElapsed( DispTimer )
call SetBuffLevel( pBuff, dd.id )
call WMem( RMem( pBuff + 0x90 ) + 0x4, mR2I( dd.c + 15.10 ) )
call WMem( RMem( pBuff + 0x90 ) + 0x8, mR2I( dd.c + 10.408 ) )
call UnitRemoveAbilityTimed( ally, 'A03W', 0.00 )
set ally = null
endfunction
function Speed_Steal_damage_enemy takes nothing returns nothing
set TempDamage = TempDamage + GetUnitBaseDamage( GetEnumUnit( ) )
endfunction
function Trig_Speed_Steal_Buff_Expires_Conditions takes nothing returns boolean
local TriggerData dd
local unit dies
if ( GetTriggerEventId() == EVENT_WIDGET_DEATH ) then
set dd = GetDataBX( GetTriggeringTrigger( ) )
set dies = GetDyingUnit( )
if IsUnitInGroup( dies, dd.grp ) then
call GroupRemoveUnit( dd.grp, dies )
call SetUnitExtraDamage( dies, 0 )
call RemoveSavedHandle( gg_htb_HashData, ExSpeedSteal, GetHandleId(dies) )
call RemoveSavedInteger( gg_htb_HashData, GetHandleId(dies), HASH_EXTRA_DAMAGE_INDEX )
call UnitRemoveAbility( dies, 'A0DV' )
endif
set dies = null
return false
elseif ( GetTriggerEventId() != EVENT_GAME_TIMER_EXPIRED ) then
set dd = GetDataBX( GetTriggeringTrigger( ) )
set dies = bj_lastReplacedUnit
call GroupRemoveUnit( dd.grp, dies )
call SetUnitExtraDamage( dies, R2I( GetUnitExtraDamage( dies ) - dd.dmg ) )
call SaveInteger( gg_htb_HashData, GetHandleId(dies), HASH_EXTRA_DAMAGE_INDEX, R2I( GetUnitExtraDamage( dies ) - dd.dmg ) )
call RemoveSavedHandle( gg_htb_HashData, ExSpeedSteal, GetHandleId(dies) )
call UnitRemoveAbility( dies, 'A0DV' )
set dies = null
return false
endif
return true
endfunction
function Trig_Speed_Steal_Buff_Expires_Actions takes nothing returns nothing
local TriggerData dd = GetDataBX( GetTriggeringTrigger() )
call DisableTrigger( dd.trg )
set bj_forceRandomConsidered = dd
call ForGroup( dd.grp, function Group_Remove_Damage_Enum )
call ReleaseGroup( dd.grp )
call RemoveDataBX( dd.trg )
call dd.RemoveTrigger( )
call dd.destroy( )
endfunction
function Trig_Speed_Steal_Actions takes nothing returns nothing
local unit Runner = GetSpellAbilityUnit( )
local integer Level = GetUnitAbilityLevel( Runner, 'A03Q' )
local real CX = GetUnitX( Runner )
local real CY = GetUnitY( Runner )
local player pl = GetOwningPlayer( Runner )
local TriggerData dd
call GroupClear( gg_grp_TempGroup )
set bj_groupEnumOwningPlayer = pl
call GroupEnumUnitsInRange( gg_grp_TempGroup, CX, CY, 500.00, OnlyEnemy )
if FirstOfGroup( gg_grp_TempGroup ) != null then
set TempDamage = 0.00
call ForGroup( gg_grp_TempGroup, function Speed_Steal_damage_enemy )
if TempDamage > 1.00 then
set dd = TriggerData.create()
set dd.trg = CreateTrigger( )
set dd.trc = TriggerAddCondition( dd.trg, Condition( function Trig_Speed_Steal_Buff_Expires_Conditions ) )
set dd.tra = TriggerAddAction( dd.trg, function Trig_Speed_Steal_Buff_Expires_Actions )
set dd.grp = NewGroup()
set dd.dmg = ( 0.15 * Level ) * TempDamage
set dd.id = Level
call SetDataBX( dd.trg, dd )
call GroupEnumUnitsOfPlayer( dd.grp, pl, Condition( function Only_Alive_Player_No_Dummy_No_Ward_Filter ) )
set bj_forceRandomConsidered = dd
call ForGroup( dd.grp, function Group_Add_Damage_Enum )
call TriggerRegisterTimerEvent( dd.trg, 15.00, false )
endif
endif
set Runner = null
endfunction
function Init_ExtraDamageSystem takes nothing returns nothing
if abilityAddDamageLvl[0] > 0 then
return
endif
set abilityAddDamageLvl[0] = 'A0DS'
set abilityAddDamageLvl[1] = 'A0DA'
set abilityAddDamageLvl[2] = 'A0DK'
set abilityAddDamageLvl[3] = 'A0DL'
set abilityAddDamageLvl[4] = 'A0DM'
set abilityAddDamageLvl[5] = 'A0DN'
set abilityAddDamageLvl[6] = 'A0DO'
set abilityAddDamageLvl[7] = 'A0DP'
set abilityAddDamageLvl[8] = 'A0DQ'
set abilityAddDamageLvl[9] = 'A0DR'
set abilityAddDamageLvl[10] = 'A0DJ'
set abilityAddDamageLvl[11] = 'A0DT'
set abilityAddDamageLvl[12] = 'A0DU'
set bj_lastCreatedUnit = CreateUnit( Player( 15 ), 'hpea', 4435.41, 4295.44, 270.00 )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[0] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[1] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[2] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[3] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[4] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[5] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[6] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[7] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[8] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[9] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[10] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[11] )
call UnitAddAbility( bj_lastCreatedUnit, abilityAddDamageLvl[12] )
call ShowUnit( bj_lastCreatedUnit, false )
call KillUnit( bj_lastCreatedUnit )
endfunction
Пока юнит разлагается и ты видишь на земле труп, юнит занимает место в памяти, если же юнит разложился -то его уже нет и память он не занимает.
Разумеется в картах типа товер дефенсов имеет смысл сокращать время сокращения или делать суммонами, чтобы после смерти они исчезали не оставляя трупы - вспомните что происходит с духами волков после их убийства. Но тут палка о двух концах, юниты могут наносить урон и убивать других юнитов - так вот если какой нить самон плюнет во врага и сдохет, а тычка долетит до цели через некоторое время и убьет - убивший юнит будет равен null, в доте есть такой баг, змейки веномансера имеют ядовитую атаку и часто обеспечивают суецид врагам, не давая бабки за фраг их хозяину.
А их нету, есть скрипты для melee AI где просто тактика и экономика, никакого микроконтроля и расположения зданий. Все микро, стройка и прочее описано в движке игры, так что разрабатываем самостоятельно методом тыка.
Light Strike Array - A027
EMP - Z609
Как бы очевидно что ищут ID в файлах игры, стан лины - сделан из огненного голема, следовательно ищем его в Neutral Ability String.txt ну а emp на канале, в common ability func. Ну а в целом карту восстановили для открывания в редакторе и смотрим в чем проблема то?
Vipas1707, своих написать, бот если что то не улучшает - это не значит что он тупит, быть может в записаной для него тактике это бесполезно, бот просто разыгрывает шаблонный бой, где он либо выиграл - либо проиграл, причем не умер от тебя - а просто не успел убить тебя за определенное время - ты впереди по развитию, он считай сдался - на про уровне обычно сразу выходят в таком случае - ибо соперник шанса тебе не оставит.
Я думаю никакого чуда нет, просто у есть дезасамблированный Game.dll и когда ты в этом постоянно копаешся, в голове откладываются эти самые оффсеты, что куда, откуда - и становится очевидно что фатальнуло, интерфейс, жасс код, или чего еще.
Взять за основу способность со снарядом - к примеру кислотную бомбу, убрать все уроны и замедления, при касте абилки - создавать новый триггер который ждет пока цель каста получит ровно 0.00 урона и бафф кислотной бомбы, время вышло или цель умерла. При любом из событий триггер выключается и удаляется, если юнит получил бафф и 0 урона от кастера - внего прилетел снаряд, снимаем бафф и хилим или дамажим. Просто.
Ну так нужно вручать юниту пустышку с прикрепленным спецэффектом, к примеру абилку предмета - кольцо защиты +1, бонус защиты на 0 ставим и в настройках способности выбираем нужный спецэффект и точку крепления. Вручаем и удаляем эту абилку юниту, делаем абилку перманентной функцией UnitMakeAbilityPermanent (или как то так).
Есть такая вещь как лимит операций, уже не помню сколько 30 ли 40 тысяч опкодов, это не твоих действий, а как их видит виртуальная жасс машина.
Но по достижению их лимита, будет обрыв потока, движок просто перестанет выполнять функцию, на деле сложно представить себе такой триггер. Насчёт тяжести операций для движка игры, тут все индивидуально, есть и тяжолое функции которые сильнее нагрудают движок игры, а есть и очень лёгкие, которые заметно меньше нагрудают движок, к примеру 10000 вызовов - get unit ability level будет незначительно быстрее 10000 обращений к хештаблице, 6 мс и 6.5 мс соответственно, а к примеру 10000 вызовов execute func - 24мс,примерно в 4 раза тяжелее.
» WarCraft 3 / деБафф плейсеры
» WarCraft 3 / Как называется анимация брызгов крови в редакторе?
Ред. quq_CCCP
» WarCraft 3 / Как создать подсчёт урона юнитов в области?
» WarCraft 3 / Фатал при загрузке сейва
» WarCraft 3 / Помогите найти карты детства
Exota
» WarCraft 3 / Как сделать скилл, как у тролля в доте?
» WarCraft 3 / this application has encountered a critical error FATAL ERROR
» WarCraft 3 / Утечки памяти от юнитов
Разумеется в картах типа товер дефенсов имеет смысл сокращать время сокращения или делать суммонами, чтобы после смерти они исчезали не оставляя трупы - вспомните что происходит с духами волков после их убийства. Но тут палка о двух концах, юниты могут наносить урон и убивать других юнитов - так вот если какой нить самон плюнет во врага и сдохет, а тычка долетит до цели через некоторое время и убьет - убивший юнит будет равен null, в доте есть такой баг, змейки веномансера имеют ядовитую атаку и часто обеспечивают суецид врагам, не давая бабки за фраг их хозяину.
» WarCraft 3 / Поделитесь кто нибудь фаилами ИИ на основные расы режима Melee
» WarCraft 3 / CustomKeys – DotA v6.74e LoD – Помогите найти последние два ID
EMP - Z609
Как бы очевидно что ищут ID в файлах игры, стан лины - сделан из огненного голема, следовательно ищем его в Neutral Ability String.txt ну а emp на канале, в common ability func. Ну а в целом карту восстановили для открывания в редакторе и смотрим в чем проблема то?
» WarCraft 3 / По поводу мемхака и изменению параметров способностей.
» WarCraft 3 / По поводу мемхака и изменению параметров способностей.
» WarCraft 3 / "Перемещение юнита при определённым % здоровья
» WarCraft 3 / Как сделать, чтобы компьютер сильный, всегда улучшал ратушу?
» WarCraft 3 / Горючая смесь
» WarCraft 3 / Как правильно анализировать фаталы?
» WarCraft 3 / Триггерный урон от способности
» WarCraft 3 / Проблемы с морфом
» WarCraft 3 / Курьер как в доте
» WarCraft 3 / Загруженность триггера
Но по достижению их лимита, будет обрыв потока, движок просто перестанет выполнять функцию, на деле сложно представить себе такой триггер. Насчёт тяжести операций для движка игры, тут все индивидуально, есть и тяжолое функции которые сильнее нагрудают движок игры, а есть и очень лёгкие, которые заметно меньше нагрудают движок, к примеру 10000 вызовов - get unit ability level будет незначительно быстрее 10000 обращений к хештаблице, 6 мс и 6.5 мс соответственно, а к примеру 10000 вызовов execute func - 24мс,примерно в 4 раза тяжелее.
» WarCraft 3 / Как узнать id всех предметов, юнитов, абилок
» WarCraft 3 / Slk на рефоргете?
» WarCraft 3 / Slk на рефоргете?
» WarCraft 3 / Slk на рефоргете?
» WarCraft 3 / Приказ юнита не срабатывает