I need a Jass code for "Meat Hook" from DotA. My problem is that i can´t use the GUI Hook from this site, because I want to use this spell for a multiplayer map where all heros have the hook ability.
I would appreciate it if you could post a map with the hole spell.
Here is your code: It is a single trigger, which you should name "MH Cast".
function Trig_MH_Retract_Actions takes integer mH_Links,unit mH_Unit1,unit mH_Unit2 returns boolean
local boolean stop = false
local location mH_LinkPos = GetUnitLoc(udg_MH_Link[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))+4+mH_Links])
call SetUnitPositionLoc(mH_Unit2,mH_LinkPos)
call RemoveUnit(udg_MH_Link[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))+4+mH_Links])
set mH_Links = mH_Links - 1
if mH_Links == 0 then
set mH_Unit1 = null
set mH_Unit2 = null
set stop = true
endif
call FlushStoredInteger(udg_Cache,"mH_Values",I2S(GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))) + "Links")
call StoreInteger(udg_Cache,"mH_Values",I2S(GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))) + "Links",mH_Links)
call RemoveLocation(mH_LinkPos)
set mH_LinkPos = null
return stop
endfunction
function Trig_MH_Extend_Condition takes nothing returns boolean
return GetUnitState(GetFilterUnit(),ConvertUnitState(0)) > 0
endfunction
function Trig_MH_Extend_Actions takes integer mH_Level,unit mH_Unit1,location mH_Unit1Pos,real mH_Angle returns boolean
local boolean stop = false
local integer mH_Links = GetStoredInteger(udg_Cache,"mH_Values",I2S(GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))) + "Links")
local location mH_LinkPos
local group tempGroup
local unit mH_Unit2
local timer mH_ExtendTimer = CreateTimer()
if mH_Links < 5 + 6 * mH_Level then
set mH_Links = mH_Links + 1
set udg_MH_Link[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))+4+mH_Links] = CreateUnitAtLocSaveLast(GetOwningPlayer(mH_Unit1),'u005',PolarProjectionBJ(mH_Unit1Pos,I2R(40 * mH_Links),mH_Angle),mH_Angle)
set mH_LinkPos = GetUnitLoc(udg_MH_Link[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))+4+mH_Links])
set tempGroup = GetUnitsInRangeOfLocMatching(115.00,mH_LinkPos,Condition(function Trig_MH_Extend_Condition))
if mH_Links > 3 then
set mH_Unit2 = GroupPickRandomUnit(tempGroup)
if not IsUnitAlly(mH_Unit2,GetOwningPlayer(mH_Unit1)) then
call UnitDamageTargetBJ(mH_Unit1,mH_Unit2,100.00 * I2R(mH_Level),ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL)
endif
endif
if mH_Unit2 != null then
loop
call TimerStart(mH_ExtendTimer,0.1,false,null)
if TimerGetElapsed(mH_ExtendTimer) >= 0.04 then
call PauseTimer(mH_ExtendTimer)
call ResumeTimer(mH_ExtendTimer)
exitwhen Trig_MH_Retract_Actions(mH_Links,mH_Unit1,mH_Unit2)
endif
endloop
set stop = true
endif
call FlushStoredInteger(udg_Cache,"mH_Values",I2S(GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))) + "Links")
call StoreInteger(udg_Cache,"mH_Values",I2S(GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))) + "Links",mH_Links)
call RemoveLocation(mH_LinkPos)
call DestroyGroup(tempGroup)
set mH_LinkPos = null
set udg_Temp_Group = null
else
loop
call TimerStart(mH_ExtendTimer,0.1,false,null)
if TimerGetElapsed(mH_ExtendTimer) >= 0.04 then
call PauseTimer(mH_ExtendTimer)
call ResumeTimer(mH_ExtendTimer)
exitwhen Trig_MH_Retract_Actions(mH_Links,mH_Unit1,mH_Unit2)
endif
endloop
set stop = true
endif
call DestroyTimer(mH_ExtendTimer)
set mH_ExtendTimer = null
return stop
endfunction
function Trig_MH_Cast_Actions takes nothing returns nothing
local integer mH_Level = 0
local unit mH_Unit1
local location mH_Unit1Pos
local location mH_SpellPos
local real mH_Angle = 0
local timer mH_CastTimer
if GetSpellAbilityId() == 'A00F' then
set mH_Level = GetUnitAbilityLevelSwapped('A00F',GetTriggerUnit())
set mH_Unit1 = GetTriggerUnit()
set mH_Unit1Pos = GetUnitLoc(mH_Unit1)
set mH_SpellPos = GetSpellTargetLoc()
set mH_Angle = 180/3.14159 * Atan2(GetLocationY(mH_SpellPos) - GetLocationY(mH_Unit1Pos), GetLocationX(mH_SpellPos) - GetLocationX(mH_Unit1Pos))
set mH_CastTimer = CreateTimer()
loop
call TimerStart(mH_CastTimer,0.1,false,null)
if TimerGetElapsed(mH_CastTimer) >= 0.04 then
call PauseTimer(mH_CastTimer)
call ResumeTimer(mH_CastTimer)
exitwhen Trig_MH_Extend_Actions(mH_Level,mH_Unit1,mH_Unit1Pos,mH_Angle)
endif
endloop
call RemoveLocation(mH_Unit1Pos)
call RemoveLocation(mH_SpellPos)
call DestroyTimer(mH_CastTimer)
set mH_Unit1 = null
set mH_Unit1Pos = null
set mH_SpellPos = null
set mH_CastTimer = null
endif
endfunction
function InitTrig_MH_Cast takes nothing returns nothing
set gg_trg_MH_Cast = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(0),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(1),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(2),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(3),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(4),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(5),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(6),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(7),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(8),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(9),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(10),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(11),EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerAddAction(gg_trg_MH_Cast,function Trig_MH_Cast_Actions)
endfunction
Now, that is what you need to make it work:
- the ability to throw the hook.
You have to replace "A00F" in function "Trig_MH_Cast_Actions" with it's id. It must not have more than four levels! Else my left global is beeing messed up. ^^
- a unit, which can learn the ability
- a dummy unit
You have to replace "u005" in function "Trig_MH_Extend_Actions" with it's id. This one has to be identical to u005 ("Chain Link") in the map you refered to.
- a global variable
It's type has to be "unit array" and it's name "MH_Link".
...
So, now it "should" work... If not, do not hesitate to tell me and I will look over it again.
Ok thank you very much. But if I paste it into the editor and change the ID´s I get an error.. Do I have to maintain the structure of the code or can I also just paste it and its there in three long lines? Because one error was "End of line expected" (I dont know how it is exactly because I have the german editor)
local integer index = 0
loop
call TriggerRegisterPlayerUnitEvent(gg_trg_MH_Cast,Player(index),ConvertPlayerUnitEvent(273),null)
set index = index + 1
endloop
also, why are u using ConvertPlayerUnitEvent? use the PlayerUnitEvent globals, as they run faster, since they have already executed the function.
As long as I know exactly, how often my task has to be executed, writing it as often is better (because faster) then using a loop. Remember: "loop" is a reserved word, that causes nothing else then executing a list of operations similar to a function. So with an "exitwhen", you got two additional "calls" per event check. Also, you got four more bites for your local variable and another operation to do for increasing the value.
~~ But you are right about the player events. As they are constants, the functions to determine their values are executed on start of the map and not furthermore. I change that.
... But there is something else, I worry about. Take a look at the if-structures, I used to avoid "TriggerSleepAction" and you will know, what I mean, I suppose.
@Mordred:
German version? So may it be, that you are yourself a "german version"? May it mean, that you understand was ich hier schreibe? That whould make things easier, I think.
Okay, first of all: Sorry, I forgot something to tell you. To make it work, you also need a game cache with reference from a global variable called "Cache".
Now to your compilation errors... Yes, it is right. In difference to Java (for example), JASS needs the lines as indicators for where a task ends. So you have to use exactly the same paragraphs as I used. If more errors occur, it lightens my life if you write exactly, what the editor told you. Do not worry about versions - the compiler is the same for English as for German as probably for any other game language.