Hexing вдохновил на создание своего "спелл пака" =) Опишу только действие способностей без данных, так как сделал упрощенные(на мой взгляд) надстройки по данным 1)Цель: Не позволяет окружающим героям, уйти от цели, на n дистанцию 2)Цель: Парализует цель на время (чтоб не был банальный стан добавил паузу анимации) -- на мой взгляд хорошо для связки 1 спелла 3)Цель: Получаемый урон перенаправляет на цель 4)Радиус: Увеличивает получаемый урон всех в области При обнаружении ошибок, проблеме копирования или незначительном изменении спелла(которое не присутствует) пишем в ЛС Для критиков кто смотрел код - не надо фанатизма оптимизации и указывайте только грубые ошибки http://rghost.ru/33328761
Первое, что очень ужасно бьет по глазам - плохая читаемость кода. Плохой тон - не разграничивать заголовок / конец ф-ции и ее тело. Монотонный текст. Отсутствие пробелов добивает... Иду дальше... Бж на подсчет юинтов в группе... Убило... Раскрываем через фильтр или луп (кто как хочет). Ах да, если ты используешь глобалки для константных значений, то либо пиши им constant, или делай как тру кодеры:
Code
constant function AbilityId takes nothing returns integer return 'A001' endfunction
вот так тру, если хочется юзать константы Полярные смещения лучше вынеси в переменные - чуток, но выиграешь в скорости. Вместо GetSpellAbilityUnit() юзай getTriggerUnit() - опять же выиграешь в скорости. Можно было не создавать группу g, если в начале ты ее просто сохраняешь в хэш, лучше писать call SaveAgent(udg_H,id,1,CreateGroup) вот я и досмотрел первый спелл до конца. Дальше погляжу, но выводы сделай самое главное - отступы
Code
globals integer idSpellChain ='A001'//id Cпособности "Chain" real PickRadius =700.//Радиус в котором находит цели real RadiusPerLvl =0.//Прирост на уровень real TargetDistTarget =300.//Максимальная дистанция, на которую может убежать окружающие, от цели real DecrDistPerLvl =0.//Уменьшение на уровень real TimeChain =7.//Время действия real TimeChainPerLvl =0.//Прирост на уровень string EffectChain ="Abilities\\Spells\\Orc\\Voodoo\\VoodooAuraTarget.mdl"//отображаемый спецэфект string AttachPointChain ="overhead"//к какой точке юнита он крепится endglobals
function Trig_Chain_Conditions takes nothing returns boolean return GetSpellAbilityId()==idSpellChain endfunction
function FilterHero takes nothing returns boolean return IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)==true and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit())) and GetWidgetLife(GetFilterUnit())>0. and GetFilterUnit()!=GetSpellTargetUnit() endfunction
function GinG takes nothing returns nothing call GroupAddUnit(LoadGroupHandle(udg_H,GetHandleId(GetExpiredTimer()),5),GetEnumUnit()) endfunction
function DistHero takes nothing returns nothing local timer t=GetExpiredTimer() local integer id=GetHandleId(t) local group glh=LoadGroupHandle(udg_H,id,1) local unit u=LoadUnitHandle(udg_H,id,2) local unit ut=LoadUnitHandle(udg_H,id,3) local real x1=GetWidgetX(ut) local real y1=GetWidgetY(ut) local real x local real y local group g local unit e local lightning lig local real a call SaveGroupHandle(udg_H,id,5,CreateGroup()) set g=LoadGroupHandle(udg_H,id,5) call ForGroup(glh,function GinG) if TimerGetRemaining(LoadTimerHandle(udg_H,id,4))<=0. or CountUnitsInGroup(g)<=0 then loop set e=FirstOfGroup(g) exitwhen e==null call DestroyLightning(LoadLightningHandle(udg_H,id,GetHandleId(e))) call DestroyEffect(LoadEffectHandle(udg_H,GetHandleId(e),6)) call GroupRemoveUnit(g,e) endloop call DestroyEffect(LoadEffectHandle(udg_H,GetHandleId(ut),6)) call DestroyGroup(glh) call PauseTimer(t) call DestroyTimer(t) call DestroyTimer(LoadTimerHandle(udg_H,id,4)) call FlushChildHashtable(udg_H,id) else loop set e=FirstOfGroup(g) set x=GetWidgetX(e) set y=GetWidgetY(e) set lig=LoadLightningHandle(udg_H,id,GetHandleId(e)) set a=Atan2(y1-y,x1-x) exitwhen e==null call MoveLightning(lig,true,x,y,x1,y1) if DistanceBetweenCoords(x,y,x1,y1)>=TargetDistTarget-DecrDistPerLvl*GetUnitAbilityLevel(u,idSpellChain) then call SetUnitX(e,x+12.*Cos(a)) call SetUnitY(e,y+12.*Sin(a)) call MoveLightning(lig,true,x,y,x1,y1) endif call GroupRemoveUnit(g,e) endloop endif call DestroyGroup(g) set t=null set glh=null set g=null set u=null set ut=null set e=null set lig=null endfunction
function Trig_Chain_Actions takes nothing returns nothing local unit u=GetSpellAbilityUnit() local unit ut=GetSpellTargetUnit() local timer t=CreateTimer() local timer tend=CreateTimer() local integer id=GetHandleId(t) local group g=CreateGroup() local group gds=CreateGroup() local lightning lig local unit e call GroupEnumUnitsInRange(gds,GetWidgetX(ut),GetWidgetY(ut),PickRadius+RadiusPerLvl*GetUnitAbilityLevel(u,idSpellChain),function FilterHero) loop set e=FirstOfGroup(gds) exitwhen e==null set lig=AddLightning("MFPB",true,GetWidgetX(ut),GetWidgetY(ut),GetWidgetX(e),GetWidgetY(e)) call GroupAddUnit(g,e) call SaveEffectHandle(udg_H,GetHandleId(e),6,AddSpecialEffectTarget(EffectChain,e,AttachPointChain)) call GroupRemoveUnit(gds,e) call SaveLightningHandle(udg_H,id,GetHandleId(e),lig) endloop call SaveGroupHandle(udg_H,id,1,g) call SaveUnitHandle(udg_H,id,2,u) call SaveUnitHandle(udg_H,id,3,ut) call SaveTimerHandle(udg_H,id,4,tend) call SaveEffectHandle(udg_H,GetHandleId(ut),6,AddSpecialEffectTarget(EffectChain,ut,AttachPointChain)) call TimerStart(t,.03,true,function DistHero) call TimerStart(tend,TimeChain+TimeChainPerLvl*GetUnitAbilityLevel(u,idSpellChain),false,null) call DestroyGroup(gds) set u=null set ut=null set t=null set g=null set gds=null set lig=null set e=null endfunction
//=========================================================================== function InitTrig_Chain takes nothing returns nothing local integer index=0 set gg_trg_Chain=CreateTrigger() loop call TriggerRegisterPlayerUnitEvent(gg_trg_Chain, Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT, null) set index=index+1 exitwhen index==bj_MAX_PLAYER_SLOTS endloop call TriggerAddCondition(gg_trg_Chain,Condition(function Trig_Chain_Conditions)) call TriggerAddAction(gg_trg_Chain,function Trig_Chain_Actions) endfunction
Code
globals integer idSpellChain ='A001'//id Cпособности "Chain" real PickRadius =700.//Радиус в котором находит цели real RadiusPerLvl =0.//Прирост на уровень real TargetDistTarget =300.//Максимальная дистанция, на которую может убежать окружающие, от цели real DecrDistPerLvl =0.//Уменьшение на уровень real TimeChain =7.//Время действия real TimeChainPerLvl =0.//Прирост на уровень string EffectChain ="Abilities\\Spells\\Orc\\Voodoo\\VoodooAuraTarget.mdl"//отображаемый спецэфект string AttachPointChain ="overhead"//к какой точке юнита он крепится endglobals
function Trig_Chain_Conditions takes nothing returns boolean return GetSpellAbilityId()==idSpellChain endfunction
function FilterHero takes nothing returns boolean return IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)==true and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit())) and GetWidgetLife(GetFilterUnit())>0. and GetFilterUnit()!=GetSpellTargetUnit() endfunction
function GinG takes nothing returns nothing call GroupAddUnit(LoadGroupHandle(udg_H,GetHandleId(GetExpiredTimer()),5),GetEnumUnit()) endfunction
function DistHero takes nothing returns nothing local timer t=GetExpiredTimer() local integer id=GetHandleId(t) local group glh=LoadGroupHandle(udg_H,id,1) local unit u=LoadUnitHandle(udg_H,id,2) local unit ut=LoadUnitHandle(udg_H,id,3) local real x1=GetWidgetX(ut) local real y1=GetWidgetY(ut) local real x local real y local group g local unit e local lightning lig local real a call SaveGroupHandle(udg_H,id,5,CreateGroup()) set g=LoadGroupHandle(udg_H,id,5) call ForGroup(glh,function GinG) if TimerGetRemaining(LoadTimerHandle(udg_H,id,4))<=0. or CountUnitsInGroup(g)<=0 then loop set e=FirstOfGroup(g) exitwhen e==null call DestroyLightning(LoadLightningHandle(udg_H,id,GetHandleId(e))) call DestroyEffect(LoadEffectHandle(udg_H,GetHandleId(e),6)) call GroupRemoveUnit(g,e) endloop call DestroyEffect(LoadEffectHandle(udg_H,GetHandleId(ut),6)) call DestroyGroup(glh) call PauseTimer(t) call DestroyTimer(t) call DestroyTimer(LoadTimerHandle(udg_H,id,4)) call FlushChildHashtable(udg_H,id) else loop set e=FirstOfGroup(g) set x=GetWidgetX(e) set y=GetWidgetY(e) set lig=LoadLightningHandle(udg_H,id,GetHandleId(e)) set a=Atan2(y1-y,x1-x) exitwhen e==null call MoveLightning(lig,true,x,y,x1,y1) if DistanceBetweenCoords(x,y,x1,y1)>=TargetDistTarget-DecrDistPerLvl*GetUnitAbilityLevel(u,idSpellChain) then call SetUnitX(e,x+12.*Cos(a)) call SetUnitY(e,y+12.*Sin(a)) call MoveLightning(lig,true,x,y,x1,y1) endif call GroupRemoveUnit(g,e) endloop endif call DestroyGroup(g) set t=null set glh=null set g=null set u=null set ut=null set e=null set lig=null endfunction
function Trig_Chain_Actions takes nothing returns nothing local unit u=GetSpellAbilityUnit() local unit ut=GetSpellTargetUnit() local timer t=CreateTimer() local timer tend=CreateTimer() local integer id=GetHandleId(t) local group g=CreateGroup() local group gds=CreateGroup() local lightning lig local unit e call GroupEnumUnitsInRange(gds,GetWidgetX(ut),GetWidgetY(ut),PickRadius+RadiusPerLvl*GetUnitAbilityLevel(u,idSpellChain),function FilterHero) loop set e=FirstOfGroup(gds) exitwhen e==null set lig=AddLightning("MFPB",true,GetWidgetX(ut),GetWidgetY(ut),GetWidgetX(e),GetWidgetY(e)) call GroupAddUnit(g,e) call SaveEffectHandle(udg_H,GetHandleId(e),6,AddSpecialEffectTarget(EffectChain,e,AttachPointChain)) call GroupRemoveUnit(gds,e) call SaveLightningHandle(udg_H,id,GetHandleId(e),lig) endloop call SaveGroupHandle(udg_H,id,1,g) call SaveUnitHandle(udg_H,id,2,u) call SaveUnitHandle(udg_H,id,3,ut) call SaveTimerHandle(udg_H,id,4,tend) call SaveEffectHandle(udg_H,GetHandleId(ut),6,AddSpecialEffectTarget(EffectChain,ut,AttachPointChain)) call TimerStart(t,.03,true,function DistHero) call TimerStart(tend,TimeChain+TimeChainPerLvl*GetUnitAbilityLevel(u,idSpellChain),false,null) call DestroyGroup(gds) set u=null set ut=null set t=null set g=null set gds=null set lig=null set e=null endfunction
//=========================================================================== function InitTrig_Chain takes nothing returns nothing local integer index=0 set gg_trg_Chain=CreateTrigger() loop call TriggerRegisterPlayerUnitEvent(gg_trg_Chain, Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT, null) set index=index+1 exitwhen index==bj_MAX_PLAYER_SLOTS endloop call TriggerAddCondition(gg_trg_Chain,Condition(function Trig_Chain_Conditions)) call TriggerAddAction(gg_trg_Chain,function Trig_Chain_Actions) endfunction
Code
globals integer idExchangeEssence='A004'//id Cпособности "Exchange of the essence" real TimeExEssence=4. //время перенаправления урона real TimeExEssencePerLvl=.5 //прирост времени на уровень real ExchangerDamage=1. //% перенаправляемого урона real ExchangerDamagePerLvl=0. // прирост на уровень string EffectExEssence ="AntiGravityTarget_Portrait.mdl"//отображаемый спецэфект string AttachPointExEssence ="chest"//к какой точке юнита он крепится boolean ExEssBool =true//true = эффект виден только самому герою //false = виден всем endglobals function Trig_ExchangeEssence_Conditions takes nothing returns boolean return GetLearnedSkill()==idExchangeEssence and GetUnitAbilityLevel(GetTriggerUnit(),idExchangeEssence)==1 endfunction
function EotEFilterSpell takes nothing returns boolean return GetSpellAbilityId()==idExchangeEssence endfunction
function EotEOffSpell takes nothing returns nothing local timer t=GetExpiredTimer() local integer id=GetHandleId(LoadUnitHandle(udg_H,GetHandleId(t),1)) call SaveBoolean(udg_H,id,1,false) call DestroyEffect(LoadEffectHandle(udg_H,GetHandleId(t),2)) call DestroyTimer(t) call FlushChildHashtable(udg_H,GetHandleId(t)) set t=null endfunction
function EotECastSpell takes nothing returns nothing local timer t=CreateTimer() local unit u=GetTriggerUnit() local integer id=GetHandleId(u) local string eff call SaveBoolean(udg_H,id,1,true) call SaveUnitHandle(udg_H,id,2,GetSpellTargetUnit()) call SaveUnitHandle(udg_H,GetHandleId(t),1,u) if GetLocalPlayer()==GetTriggerPlayer() and ExEssBool==true then set eff=EffectExEssence endif call SaveEffectHandle(udg_H,GetHandleId(t),2,AddSpecialEffectTarget(eff,u,AttachPointExEssence)) call TimerStart(t,TimeExEssence+ TimeExEssencePerLvl*GetUnitAbilityLevel(u,idExchangeEssence),false,function EotEOffSpell) set eff=null set t=null set u=null endfunction
function EotEDamgeTake takes nothing returns nothing local unit u=GetTriggerUnit() local integer id=GetHandleId(u) local unit ut=LoadUnitHandle(udg_H,id,2) local real dm=GetEventDamage() local real dmm=ExchangerDamage+ExchangerDamagePerLvl*GetUnitAbilityLevel(u,idExchangeEssence) if LoadBoolean(udg_H,id,1)==true and dm>=1 then call SetWidgetLife(u,GetWidgetLife(u)+dm*dmm) call UnitDamageTarget(u,ut,dm*ExchangerDamage,true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_UNIVERSAL,null) endif set u=null set ut=null endfunction
function Trig_ExchangeEssence_Actions takes nothing returns nothing local trigger dam=CreateTrigger() local trigger cast=CreateTrigger() call SaveBoolean(udg_H,GetHandleId(GetTriggerUnit()),1,false) call TriggerRegisterUnitEvent(dam,GetTriggerUnit(),EVENT_UNIT_DAMAGED) call TriggerAddAction(dam,function EotEDamgeTake) call TriggerRegisterUnitEvent(cast,GetTriggerUnit(),EVENT_UNIT_SPELL_EFFECT) call TriggerAddCondition(cast,Condition(function EotEFilterSpell)) call TriggerAddAction(cast,function EotECastSpell) set dam=null set cast=null endfunction
//=========================================================================== function InitTrig_ExchangeEssence takes nothing returns nothing set gg_trg_ExchangeEssence=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(gg_trg_ExchangeEssence,EVENT_PLAYER_HERO_SKILL) call TriggerAddCondition(gg_trg_ExchangeEssence,Condition(function Trig_ExchangeEssence_Conditions)) call TriggerAddAction(gg_trg_ExchangeEssence,function Trig_ExchangeEssence_Actions) endfunction
Code
//Настройки на нанесение дополнительного урона, времени и эффектов //в способности "DestructionMolecules" globals integer idDestructionMolecules='A005'//id Cпособности "Destruction of the molecules" integer idBerserk='A006'//id Cпособности "DestructionMolecules" real RadiusDesMolecules=300.//радиус на нанесение дополнительного урона real RadDesMoleculesPerLvl=0.//прирост на уровень endglobals
function Trig_DestructionMolecules_Conditions takes nothing returns boolean return GetSpellAbilityId()==idDestructionMolecules endfunction
function DotMFilterUnit takes nothing returns boolean return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit()))==true and IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)==false and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE)==false endfunction
function Trig_DestructionMolecules_Actions takes nothing returns nothing local group g=CreateGroup() local unit e call GroupEnumUnitsInRange(g,GetSpellTargetX(),GetSpellTargetX(),RadiusDesMolecules+RadDesMoleculesPerLvl*GetUnitAbilityLevel(GetTriggerUnit(),id DestructionMolecules),function DotMFilterUnit) loop set e=FirstOfGroup(g) exitwhen e==null call UnitAddAbility(e,idBerserk) call SetUnitAbilityLevel(e,idBerserk,GetUnitAbilityLevel(GetTriggerUnit(),idDestructionMolecules)) call IssueImmediateOrderById(e,852100) call UnitRemoveAbility(e,idBerserk) call GroupRemoveUnit(g,e) endloop call DestroyGroup(g) set g=null set e=null endfunction
//=========================================================================== function InitTrig_DestructionMolecules takes nothing returns nothing set gg_trg_DestructionMolecules=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(gg_trg_DestructionMolecules,EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(gg_trg_DestructionMolecules,Condition(function Trig_DestructionMolecules_Conditions)) call TriggerAddAction(gg_trg_DestructionMolecules,function Trig_DestructionMolecules_Actions) endfunction
Причем последний спелл у меня не работает. И третий вроде тоже
constant function AbilityId takes nothing returns integer return 'A001' endfunction
скажи нет оптимизации? : / это чисто для читабельности кода, но лично я против ваших
Code
constant function AbilityDmg takes nothing returns integer if(lvl == 1) then return 500. elseif(...) ... endfunction
как читабельноть кода улучшит что-либо в игре? только замедлит работу кода - лишняя функа=лишний поток, хоть и почти мгновенный
Quote (Ty3uK)
Вместо GetSpellAbilityUnit() юзай getTriggerUnit() - опять же выиграешь в скорости.
Хватит всех убеждать в этом, во первых это -читабельность кода, во вторых никто не доказывал что это работает быстрее(кроме SirNickolas намёк которого был очень тонок и не указывал на все ситуации)...
Вот такто Ватсон
p.s. ща гляну спеллпак, по описанию видно что автор пытается сделать чтото оригинальное)))
Добавлено (06 Декабрь 2011, 15:50:29) --------------------------------------------- кстати почему файл называется "LichUpgrade"???
Добавлено (06 Декабрь 2011, 15:54:17) --------------------------------------------- скачал, жму сохранить - пишет 2 ошибки
DragoN, разве? я считал что ExecFunc как раз и не выз... а ну да вы правы, это я загнул) просто читал недавно на хгм статью про редактирование памяти и лимит в 20 потоков, так вдохновило...
Пауза выглядет прикольно, но както слишком глухо... добавь какиенибудь спецэффекты или аое дебаффы Перенаправлялка - вообще без эффектов... трудно понять что урон не проходит))) остальные не видел ибо с ошибками код
Хватит всех убеждать в этом, во первых это -читабельность кода, во вторых никто не доказывал что это работает быстрее(кроме SirNickolas намёк которого был очень тонок и не указывал на все ситуации)...
Холмс ты наш, посчитай символы. GetSpellAbilityUnit - 19 GetTriggerUnit - 14 Профит от триггерюнита. Плюс ко всему, этот тип обобщённый. Истинный кодер должен рвать и бросать его читабельность в топку, если от неё страдает скорость кода.
Quote (Hexing)
как читабельноть кода улучшит что-либо в игре? только замедлит работу кода - лишняя функа=лишний поток, хоть и почти мгновенный
И сам себе противоречишь. Красиво!
Quote (DragoN)
единственный способ запустит функцию в мнимом потоке(эмуляция потока) - ExecFunc()
И здравствуй, краш карты... Надо писать ExecuteFunc() Ребята, вы прямо напомнили спеллмодераторов Хайва - один говорит, что группу надо в циклы ставить и не утверждает ресурс, а второй - что надо делать в фильтрфунке и тоже не утверждает. И между собой они вообще не договорятся.
Hexing, Ты мне не поверил. Давай тогда докажу тебе, почему GetTriggerUnit гораздо лучше. Погуглив каждую из этих нативок, могу привести такие доводы:
1. GetTriggerUnit является локальной native-функцией, то есть создающейся для каждого инстанса триггера. 2. Функции вида GetXXXUnit с юнитом, ориентированным на событие, являются наследниками от GetTriggerUnit. То есть вызывается на функцию больше.
а ну да вы правы, это я загнул) просто читал недавно на хгм статью про редактирование памяти и лимит в 20 потоков
ну это правильно так-то. варе работает до 20 общих потоков(именно потоков)
Quote (|DUОS|)
И здравствуй, краш карты... Надо писать ExecuteFunc()
я сократил, ибо давно не кодил - точное название не помню думаю Hexing парень толковый, так что и так всё понял => профит получен краша не будет - компилятор пробубник про несуществующую функцию(даже если в ExecuteFunc() не вписать аргумент - не факт что будет фатал, это в патчах после 1.24 вроде как пофиксили )
точно подметел, лень было объясняться перед дуосом, ибо тут итак злой холивар, а с ним трудно спорить
Quote (DragoN)
он и кушают пару килобайт, лол
не) байт - английские символы записываются как байт а учитывая что
Quote
Анализ дампов памяти, созданных предыдущими примерами, показал, что каждая целочисленная переменная занимает целых 40 байт памяти, лишь 4 из которых содержат число. Ещё 8 указывают тип переменной. Например, целочисленный тип описывается так:
относится ко всем типам переменных, длинна функции в целом ну совсем низначительно влияет на код.
Quote (|DUОS|)
1. GetTriggerUnit является локальной native-функцией, то есть создающейся для каждого инстанса триггера. 2. Функции вида GetXXXUnit с юнитом, ориентированным на событие, являются наследниками от GetTriggerUnit. То есть вызывается на функцию больше.
в этом есть доля логики, хотя в целом идея обсурдна, ведь если рассмотеть язык jass - то он не расчитан на опимальность никаким боком... я лучше просто буду писать код, не задумываясь о 2 чарах, кстати вроде ты гдето писал что лучше создавать много хт чем кидать всё в одну - так нет, хт жрёт дофигище памяти, а даже пустые ячейки жрут столькоже памяти, и не надо создавать много хт - одной хт на мапу вполне хватит... я даже не уверен что если создавать много хт, они будут быстрее работать, ведь поиск идёт независимо от значений - по списку?