- Joined
- Dec 16, 2007
- Messages
- 252
This is a spell made by Trollvottel, it's a meat hook spell similar to the one in Pudge Wars, it bounces on buildings and end of the map.
Can someone please post me a code where this spell also bounces on a specific terrain type? For example Square Tiles from Citycape.
I think it's this part that bounces on buildings, but I have no idea how to modify it so it will bounce on a specific terrain type.
JASS:
scope MeatHook
// ==================================MEAT HOOK BY TROLLVOTTEL==================================
// || How to import: ||
// || * Copy the systems TT and PUI and the library UsedFuncs into your map ||
// || * Copy this trigger into your map, change it's name to MeatHook ||
// || * Copy the chain dummy and the hookhead dummy into your map ||
// || * Change the values below, the function have an argument (lvl) which refers to the ||
// || * level of the ability for the caster ||
// ============================================================================================
// WHAT IT DOES:
// * It's a meathook quite similar to the one from pudge wars made by me
// * It connects the hook and the caster with chains
// * It is retracted before leaving the playable map area
// * It bounces off buildings.
// * It looks quite nice
// WHAT IS NEEDED:
// * vJass
// * TT (Timer Ticker)
// * PUI (Perfect Unit Indexing)
// * the UsedFuncs library, my personal code collection with useful functions
globals
private constant integer RAWID = 'A000' // Ability id
private constant integer CHAINID = 'h001' // chain dummy id
private constant integer HOOKHEADID = 'h000' // hook head id
private constant real CHAINEVERY = 30. // every X wc3 units a chain link
private constant integer MAXCHAINS = 60 // max amount of chains
private constant real RADIUS = 80. // radius to grab units
endglobals
private function Distance takes integer lvl returns real
return 2000.
endfunction
private function Damage takes integer lvl returns real
return 40.
endfunction
private function Speed takes integer lvl returns real
return 600.
endfunction
//==============================SPELL BEGINS HERE==============================
//------DONT CHANGE ANYTHING BELOW OR ANGELS WILL COME DOWN AND KILL YOU------\\
globals
public boolean array ISHOOKED
endglobals
private struct Meathook
unit array link [MAXCHAINS]
integer len = 0
real movement
unit hooker
unit hookhead
boolean hooked = false
unit hooktarg = null
real directionangle
real angleCos
real angleSin
real dis = 0.
real rangepassed = 0.
real distance = 0.
method launch takes unit which, real direction returns nothing
set .hooker = which
set .directionangle = direction
set .movement = Speed ( GetUnitAbilityLevel( .hooker, RAWID ) ) * TT_PERIOD
set .angleCos = Cos ( direction * DTR ) *.movement
set .angleSin = Sin ( direction * DTR ) *.movement
set .hookhead = CreateUnit( GetOwningPlayer( which ), HOOKHEADID, GetUnitX( which ), GetUnitY( which ), direction)
set .distance = Distance ( GetUnitAbilityLevel( .hooker, RAWID ) )
call TT_Start(function Meathook.fly, this)
endmethod
static method fly takes nothing returns boolean
local Meathook hook = TT_GetData( )
local real cx = GetUnitX ( hook.hooker )
local real cy = GetUnitY ( hook.hooker )
local real nx
local real ny
local real lx
local real ly
local real llx
local real lly
local real angletonext
local real distance
local real angle
local real angle2
local real absmod
local integer index = hook.len
local group g
local unit u
local boolean flag = false
// Chain moving
loop
set lx = GetUnitX(hook.link[index])
set ly = GetUnitY(hook.link[index])
set llx = GetUnitX(hook.link[index-1])
set lly = GetUnitY(hook.link[index-1])
set angletonext = Atan2(ly-lly,lx-llx)
call SetSafeX(hook.link[index],llx+CHAINEVERY * Cos(angletonext))
call SetSafeY(hook.link[index],lly+CHAINEVERY * Sin(angletonext))
call SetUnitFacingTimed(hook.link[index], angletonext * RTD - 180,0)
set index = index - 1
exitwhen index < 1
endloop
set lx = GetUnitX(hook.link[0])
set ly = GetUnitY(hook.link[0])
set llx = GetUnitX(hook.hookhead)
set lly = GetUnitY(hook.hookhead)
set angletonext = Atan2( lly - ly, llx - lx )
set nx = lx + hook.movement * Cos(angletonext)
set ny = ly + hook.movement * Sin(angletonext)
call SetSafeX(hook.link[0],GetUnitX(hook.hookhead))
call SetSafeY(hook.link[0],GetUnitY(hook.hookhead))
call SetUnitFacingTimed(hook.link[0], angletonext, 0)
// Hook forward and avoid leaving the map
set lx = GetUnitX(hook.hookhead)
set ly = GetUnitY(hook.hookhead)
set nx = lx + hook.angleCos
set ny = ly + hook.angleSin
if not IsPointInMap(nx,ny) then
if ny != SafeY(ny) then
set hook.directionangle = -hook.directionangle
else
set hook.directionangle = 180-hook.directionangle
endif
set hook.angleCos = hook.movement * Cos(hook.directionangle * DTR)
set hook.angleSin = hook.movement * Sin(hook.directionangle * DTR)
set nx = lx + hook.angleCos
set ny = ly + hook.angleSin
endif
call SetSafeX(hook.hookhead,nx)
call SetSafeY(hook.hookhead,ny)
// new chain link
set hook.dis = hook.dis + hook.movement
if hook.dis >= CHAINEVERY and hook.len < 2 then
set llx = GetUnitX(hook.link[hook.len-1])
set lly = GetUnitY(hook.link[hook.len-1])
set angletonext = Atan2(cy-lly,cx-llx) * RTD
set hook.link[hook.len] = CreateUnit(GetOwningPlayer(hook.hooker), CHAINID, llx+CHAINEVERY*Cos(angletonext*DTR) , lly+CHAINEVERY*Sin(angletonext*DTR) ,angletonext-180)
set hook.len = hook.len + 1
set hook.dis = 0.
if hook.len > MAXCHAINS-2 then
set flag = true
endif
endif
set lx = GetUnitX(hook.link[hook.len-1])
set ly = GetUnitY(hook.link[hook.len-1])
set distance = SquareRoot(SquareDistance(lx,ly,cx,cy))
if distance >= CHAINEVERY and hook.len > 1 and flag == false then
set hook.dis = 0.
set angletonext = Atan2(cy-ly,cx-lx)
set nx = lx + CHAINEVERY * Cos(angletonext)
set ny = ly + CHAINEVERY * Sin(angletonext)
set hook.link[hook.len] = CreateUnit(GetOwningPlayer(hook.hooker), CHAINID, nx , ny ,angletonext*RTD-180)
set hook.len = hook.len + 1
if hook.len > MAXCHAINS-2 then
set flag = true
endif
endif
set hook.rangepassed = hook.rangepassed + hook.movement
if hook.rangepassed >= hook.distance then
set flag = true
endif
// Getting Units
set lx = GetUnitX(hook.hookhead)
set ly = GetUnitY(hook.hookhead)
set g = CreateGroup()
call GroupEnumUnitsInRange(g,lx,ly,RADIUS,AliveGroundFilter)
loop
set u = FirstOfGroup(g)
call GroupRemoveUnit(g,u)
exitwhen u == null
if hook.hooker != u then
if IsUnitEnemy( u, GetOwningPlayer(hook.hookhead)) then
call UnitDamageTarget(hook.hooker,u, Damage(GetUnitAbilityLevel(hook.hooker, RAWID)), true, false, ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
if ISHOOKED[GetUnitIndex(u)] != true then
set ISHOOKED[GetUnitIndex(u)] = true
set hook.hooked = true
set hook.hooktarg = u
call SetUnitTimeScale(hook.hookhead,0)
else
call CreateTextTagDefault("HEADSHOT!!", "|cffff0000", GetUnitX(hook.hookhead), GetUnitX(hook.hookhead))
call UnitDamageTarget(hook.hooker,u, 1000000000., true, false, ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
set flag = true
exitwhen true
endif
endloop
call DestroyGroup(g)
set g = null
// Bounce off buildings
if flag == false then
set g = CreateGroup()
set lx = GetUnitX(hook.hookhead)
set ly = GetUnitY(hook.hookhead)
set angle = hook.directionangle
call GroupEnumUnitsInRange(g,lx,ly,RADIUS*1.55,AliveBuildingFilter)
loop
set u = FirstOfGroup(g)
exitwhen u == null
call GroupRemoveUnit(g,u)
set llx = GetUnitX(u)
set lly = GetUnitY(u)
set angle2 = ModuloReal(Atan2(ly-lly, lx-llx) * bj_RADTODEG,360)
set absmod = RAbsBJ(angle2 - angle)
if absmod >= 90 and absmod <= 270 then
if ( angle2 > 45 and angle2 < 135 ) or ( angle2 > 225 and angle2 < 315 ) then
set hook.directionangle = -angle
else
set hook.directionangle = 180-angle
endif
set hook.angleSin = Sin( hook.directionangle * DTR ) * hook.movement
set hook.angleCos = Cos( hook.directionangle * DTR ) * hook.movement
endif
set u = null
endloop
call DestroyGroup(g)
set g = null
endif
if flag == true then
call TT_Start(function Meathook.reverse, hook)
endif
return flag
endmethod
static method reverse takes nothing returns boolean
local Meathook hook = TT_GetData()
local real cx = GetUnitX(hook.hooker)
local real cy = GetUnitY(hook.hooker)
local real nx
local real ny
local real lx
local real ly
local real llx
local real lly
local integer index = 0
local real angletonext
local real distance
local group g
local unit u
local boolean flag = false
//link remove
set lx = GetUnitX(hook.link[hook.len-1])
set ly = GetUnitY(hook.link[hook.len-1])
set nx = lx-cx
set ny = ly-cy
set distance = SquareRoot(nx*nx+ny*ny)
if distance <= CHAINEVERY then
call KillUnit(hook.link[hook.len-1])
call ShowUnit(hook.link[hook.len-1],false)
set hook.len = hook.len - 1
if hook.len <= 1 then
set flag = true
endif
else
set angletonext = Atan2(cy-ly,cx-lx)
set nx = lx + hook.movement * Cos(angletonext)
set ny = ly + hook.movement * Sin(angletonext)
call SetSafeX(hook.link[hook.len-1],nx)
call SetSafeY(hook.link[hook.len-1],ny)
call SetUnitFacingTimed(hook.link[hook.len-1], (angletonext)*RTD+180,0)
endif
if hook.len <= 1 then
set flag = true
endif
//chain move
loop
exitwhen index > hook.len - 2
set lx = GetUnitX(hook.link[index])
set ly = GetUnitY(hook.link[index])
set llx = GetUnitX(hook.link[index+1])
set lly = GetUnitY(hook.link[index+1])
set distance = SquareRoot(SquareDistance(lx,ly,llx,lly))
if distance <= CHAINEVERY then
set angletonext = Atan2(lly-ly,llx-lx)
set nx = lx + hook.movement * Cos(angletonext)
set ny = ly + hook.movement * Sin(angletonext)
call SetSafeX(hook.link[index],nx)
call SetSafeY(hook.link[index],ny)
call SetUnitFacing(hook.link[index], (angletonext)*RTD+180)
else
set angletonext = Atan2(ly-lly,lx-llx)
set nx = llx + CHAINEVERY * Cos(angletonext)
set ny = lly + CHAINEVERY * Sin(angletonext)
call SetSafeX(hook.link[index],nx)
call SetSafeY(hook.link[index],ny)
call SetUnitFacing(hook.link[index], (angletonext)*RTD)
endif
set index = index + 1
endloop
//hook move
set lx = GetUnitX(hook.hookhead)
set ly = GetUnitY(hook.hookhead)
set llx = GetUnitX(hook.link[0])
set lly = GetUnitY(hook.link[0])
set angletonext = Atan2(ly-lly,lx-llx)
set nx = llx + CHAINEVERY * Cos(angletonext)
set ny = lly + CHAINEVERY * Sin(angletonext)
call SetSafeX(hook.hookhead,nx)
call SetSafeY(hook.hookhead,ny)
if hook.hooked == true then
call SetSafeX(hook.hooktarg,nx)
call SetSafeY(hook.hooktarg,ny)
else
set g = CreateGroup()
call GroupEnumUnitsInRange(g,nx,ny,RADIUS,AliveGroundFilter)
loop
set u = FirstOfGroup(g)
call GroupRemoveUnit(g,u)
exitwhen u == null
if hook.hooker != u then
if IsUnitEnemy( u, GetOwningPlayer(hook.hookhead)) then
call UnitDamageTarget(hook.hooker,u, Damage(GetUnitAbilityLevel(hook.hooker, RAWID)), true, false, ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
if ISHOOKED[GetUnitIndex(u)] != true then
set ISHOOKED[GetUnitIndex(u)] = true
set hook.hooked = true
set hook.hooktarg = u
call SetUnitTimeScale(hook.hookhead,0)
else
call CreateTextTagDefault("HEADSHOT!!", "|cffff0000", GetUnitX(hook.hookhead), GetUnitY(hook.hookhead))
call UnitDamageTarget(hook.hooker,u, 1000000000., true, false, ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
exitwhen true
endif
endloop
endif
if flag == true then
call hook.destroy()
endif
return flag
endmethod
method onDestroy takes nothing returns nothing
call KillUnit(.hookhead)
call ShowUnit(.hookhead,false)
call KillUnit(.link[0])
call ShowUnit(.link[0],false)
if .hooked == true then
call SetUnitX(.hooktarg,GetUnitX(.hooker))
call SetUnitY(.hooktarg,GetUnitY(.hooker))
set ISHOOKED[GetUnitIndex(.hooktarg)] = false
endif
endmethod
endstruct
private function Actions takes nothing returns nothing
local Meathook hook = Meathook.create()
local unit cast = GetTriggerUnit()
local real cx = GetUnitX(cast)
local real cy = GetUnitY(cast)
local location loc = GetSpellTargetLoc()
local real tx = GetLocationX(loc)
local real ty = GetLocationY(loc)
local real angle = Atan2(ty-cy,tx-cx) * RTD
call RemoveLocation(loc)
set loc = null
call hook.launch(cast,angle)
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == RAWID
endfunction
//===========================================================================
public function InitTrig takes nothing returns nothing
set gg_trg_Snipehook = CreateTrigger ( )
call TriggerRegisterAnyUnitEventBJ ( gg_trg_Snipehook, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction ( gg_trg_Snipehook, function Actions )
call TriggerAddCondition ( gg_trg_Snipehook, Condition(function Conditions) )
endfunction
endscope
Can someone please post me a code where this spell also bounces on a specific terrain type? For example Square Tiles from Citycape.
I think it's this part that bounces on buildings, but I have no idea how to modify it so it will bounce on a specific terrain type.
JASS:
set lx = GetUnitX(hook.hookhead)
set ly = GetUnitY(hook.hookhead)
set g = CreateGroup()
call GroupEnumUnitsInRange(g,lx,ly,RADIUS,AliveGroundFilter)
loop
set u = FirstOfGroup(g)
call GroupRemoveUnit(g,u)
exitwhen u == null
if hook.hooker != u then
if IsUnitEnemy( u, GetOwningPlayer(hook.hookhead)) then
call UnitDamageTarget(hook.hooker,u, Damage(GetUnitAbilityLevel(hook.hooker, RAWID)), true, false, ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
if ISHOOKED[GetUnitIndex(u)] != true then
set ISHOOKED[GetUnitIndex(u)] = true
set hook.hooked = true
set hook.hooktarg = u
call SetUnitTimeScale(hook.hookhead,0)
else
call CreateTextTagDefault("HEADSHOT!!", "|cffff0000", GetUnitX(hook.hookhead), GetUnitX(hook.hookhead))
call UnitDamageTarget(hook.hooker,u, 1000000000., true, false, ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
set flag = true
exitwhen true
endif
endloop
call DestroyGroup(g)
set g = null
// Bounce off buildings
if flag == false then
set g = CreateGroup()
set lx = GetUnitX(hook.hookhead)
set ly = GetUnitY(hook.hookhead)
set angle = hook.directionangle
call GroupEnumUnitsInRange(g,lx,ly,RADIUS*1.55,AliveBuildingFilter)
loop
set u = FirstOfGroup(g)
exitwhen u == null
call GroupRemoveUnit(g,u)
set llx = GetUnitX(u)
set lly = GetUnitY(u)
set angle2 = ModuloReal(Atan2(ly-lly, lx-llx) * bj_RADTODEG,360)
set absmod = RAbsBJ(angle2 - angle)
if absmod >= 90 and absmod <= 270 then
if ( angle2 > 45 and angle2 < 135 ) or ( angle2 > 225 and angle2 < 315 ) then
set hook.directionangle = -angle
else
set hook.directionangle = 180-angle
endif
set hook.angleSin = Sin( hook.directionangle * DTR ) * hook.movement
set hook.angleCos = Cos( hook.directionangle * DTR ) * hook.movement
endif
set u = null
endloop
call DestroyGroup(g)
set g = null
endif
Last edited: