waaaks!
Zinctified
- Reaction score
- 255
UPDATED the code and looks fine, what i need now is leak check that could possibly lag the game
sample usage
JASS:
library ImpaleSystem needs GroupUtils, TimerUtils, AutoIndex
//*******************************************************************************************
//*
//* Impale System
//* v.A
//* By: waaaks!
//*
//*******************************************************************************************
//* INTRODUCTION
//* Having issues with Warcraft III's Impale ability? Want to create abilities based on
//* Impale but looks so wrong? Worry no more, Impale System will do the job for you.
//* A System remaking the normal Warcraft III Impale System which is more flexible
//* and user configurable. With the system you can fully imitate Impale without any
//* Impale-based issues. The Impale ability is one of the most used abilities in
//* Warcraft III, with the use of special effects with the ability, you can create
//* spells like a line stun ability, but Impale cannot Impale units being Impaled or was
//* stunned using Impale.
//*
//* PURPOSE
//* To help users imitate Impale based abilities without the said issues.
//*
//* PROs
//* -Create spells which imitates Impale without the issue.
//* -Choose what ability to be casted on unit land.
//* -Manage wave time.
//* -Add a second wave special effect.
//* -Very usefull on maps that require lots of spells based on Impale.
//* -Removes channeling on Impale which makes the player wait until wave ends.
//*
//* CONs
//* -There is no option to turn of unit tossing.
//* -Units will be damaged half when effect starts and half damage on land.
//* -Impale source will always be on the casting unit.
globals
private constant real FACT = 0.5 //Structure damage factor
private constant real TICK2 = 0.025 //Timer per Tick
private constant integer DUMMY_CASTER = 039;e000039; //Your Dummy Caster
private constant integer FLY = 039;Amrf039; //The Fly Height Enabler ability
private group DUMMY_GROUP = CreateGroup() //Do not touch
private integer array FALL
private integer array ONCE
private boolean array DONE
endglobals
//*******************************************************************************************
//* Please do not touch anything below this line
//*******************************************************************************************
private struct impaleToss
unit cast
unit targ
real dmg
integer dspell
integer splvl
integer sporder
static method impToss takes nothing returns nothing
local timer tim = GetExpiredTimer()
local impaleToss it = GetTimerData(tim)
local real height = GetUnitFlyHeight(it.targ)
//*****************************************************************************
//* the unit has reached the maximum height, make it fall (FALL[unit] = 1, and
//* ONCE[unit] = 1 for conditional uses only)
if height > 500.0 and ONCE[GetUnitId(it.targ)] == 0 then
set FALL[GetUnitId(it.targ)] = 1
set ONCE[GetUnitId(it.targ)] = 1
endif
//*****************************************************************************
//* if unit is not falling then that means it is rising (DUH!), make unit rise
if FALL[GetUnitId(it.targ)] == 0 then
call SetUnitFlyHeight(it.targ,height+40.0,0.0)
call SetUnitPathing(it.targ, false)
call PauseUnit(it.targ,true)
else //make unit fall
call SetUnitFlyHeight(it.targ,height-55.0,0.0)
call PauseUnit(it.targ,true)
call SetUnitPathing(it.targ,false)
endif
//*****************************************************************************
//* if unit is already near land, also ONCE[unit] is used to check if the unit
//* is already damaged or not then do some stuffs
if height <= 15 and ONCE[GetUnitId(it.targ)] == 1 then
call ReleaseTimer(tim)
call it.destroy()
endif
set tim = null
endmethod
private method onDestroy takes nothing returns nothing
local unit dum
call SetUnitFlyHeight(.targ,0.0,0.0)
call UnitDamageTarget(.cast,.targ,0.5*.dmg,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call PauseUnit(.targ,false)
call SetUnitPathing(.targ,true)
set dum = CreateUnit(GetOwningPlayer(.cast),DUMMY_CASTER,GetUnitX(.cast),GetUnitY(.cast),0.0)
call UnitApplyTimedLife(dum,039;BTLF039;,3.0)
call UnitAddAbility(dum,039;Aloc039;)
call UnitAddAbility(dum,.dspell)
call SetUnitAbilityLevel(dum,.dspell,.splvl)
call IssueTargetOrderById(dum,.sporder,.targ)
call UnitShareVision(.targ,GetOwningPlayer(.cast),false)
set FALL[GetUnitId(.targ)] = 0
set ONCE[GetUnitId(.targ)] = 0
set DONE[GetUnitId(.targ)] = false
set dum = null
endmethod
static method create takes unit ccg, unit tcg, real dmg, integer dspell, integer splvl, integer sporder returns impaleToss
local impaleToss it = impaleToss.allocate()
local timer tim = NewTimer()
set it.cast = ccg
set it.targ = tcg
set it.dmg = dmg
set it.dspell = dspell
set it.splvl = splvl
set it.sporder = sporder
call UnitAddAbility(it.targ,FLY)
call UnitRemoveAbility(it.targ,FLY)
call PauseUnit(it.targ,true)
call SetUnitPathing(it.targ,false)
call TimerStart(tim,TICK2,true,function impaleToss.impToss)
call SetTimerData(tim,it)
set tim = null
return it
endmethod
endstruct
struct impaleSystem
public real isRadius = 150.0
public real isOffset = 100.0
public real isDamage = 100.0
public string isSfxTarget = "Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl"
public string isSfxPath1 = "Abilities\\Spells\\Undead\\Impale\\ImpaleMissTarget.mdl"
public string isSfxPath2 = ""
public boolean isAffectStructures = false
public integer isAbilityId = 039;A000039;
public integer isLevel = 1
public integer isOrder = OrderId("thunderbolt")
unit isCaster = null
player isOwningPlayer = Player(15)
real isCasterX = 0.0
real isCasterY = 0.0
real isTargetX = 0.0
real isTargetY = 0.0
real isRange = 600.0
boolean isStacking = true
unit dum
real rx
real ry
static method ImpRun takes nothing returns nothing
local impaleSystem this = GetTimerData(GetExpiredTimer())
local group g = NewGroup()
local unit u
local real x = GetUnitX(.dum)
local real y = GetUnitY(.dum)
local real a = Atan2(.ry-y,.rx-x)
local real px = x + .isOffset * Cos(a)
local real py = y + .isOffset * Sin(a)
local real dx = .rx - x
local real dy = .ry - y
local real dis = SquareRoot(dx*dx+dy*dy)
local impaleToss it
call GroupEnumUnitsInRange(g,x,y,.isRadius,null)
call SetUnitX(.dum,px)
call SetUnitY(.dum,py)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if .isAffectStructures then
if IsUnitEnemy(u,.isOwningPlayer) and GetWidgetLife(u) > 0.405 and not IsUnitInGroup(u,DUMMY_GROUP) then
if IsUnitType(u, UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(.isCaster,u,.isDamage*0.5,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call DestroyEffect(AddSpecialEffect(.isSfxTarget, GetUnitX(u), GetUnitY(u)))
endif
if GetWidgetLife(u) > 0.405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) then
if .isStacking == false then
if DONE[GetUnitId(u)] == false then
set DONE[GetUnitId(u)] = true
set it = impaleToss.create(.isCaster,u,.isDamage,.isAbilityId,.isLevel,.isOrder)
call UnitDamageTarget(.isCaster,u,.isDamage*0.5,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call DestroyEffect(AddSpecialEffect(.isSfxTarget, GetUnitX(u), GetUnitY(u)))
call UnitShareVision(u,.isOwningPlayer,true)
endif
else
set it = impaleToss.create(.isCaster,u,.isDamage,.isAbilityId,.isLevel,.isOrder)
call UnitDamageTarget(.isCaster,u,.isDamage*0.5,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call DestroyEffect(AddSpecialEffect(.isSfxTarget, GetUnitX(u), GetUnitY(u)))
call UnitShareVision(u,.isOwningPlayer,true)
endif
endif
endif
else
if IsUnitEnemy(u,.isOwningPlayer) and GetWidgetLife(u) > 0.405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) and not IsUnitInGroup(u,DUMMY_GROUP) then
if GetWidgetLife(u) > 0.405 then
if .isStacking == false then
if DONE[GetUnitId(u)] == false then
set DONE[GetUnitId(u)] = true
set it = impaleToss.create(.isCaster,u,.isDamage,.isAbilityId,.isLevel,.isOrder)
call UnitDamageTarget(.isCaster,u,.isDamage*0.5,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call DestroyEffect(AddSpecialEffect(.isSfxTarget, GetUnitX(u), GetUnitY(u)))
call UnitShareVision(u,.isOwningPlayer,true)
endif
else
set it = impaleToss.create(.isCaster,u,.isDamage,.isAbilityId,.isLevel,.isOrder)
call UnitDamageTarget(.isCaster,u,.isDamage*0.5,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call DestroyEffect(AddSpecialEffect(.isSfxTarget, GetUnitX(u), GetUnitY(u)))
call UnitShareVision(u,.isOwningPlayer,true)
endif
endif
endif
endif
call GroupAddUnit(DUMMY_GROUP,u)
call GroupRemoveUnit(g,u)
endloop
call ReleaseGroup(g)
if dis <= .isOffset then
call ReleaseTimer(GetExpiredTimer())
call GroupClear(DUMMY_GROUP)
call .destroy()
else
call DestroyEffect(AddSpecialEffect(.isSfxPath1,px,py))
call DestroyEffect(AddSpecialEffect(.isSfxPath2,px,py))
endif
set u = null
endmethod
static method create takes unit cast, real tx, real ty, real range, real wavetime, boolean stacking returns impaleSystem
local impaleSystem is = impaleSystem.allocate()
local timer t = NewTimer()
local location loc = GetUnitLoc(cast)
local real a
set is.isStacking = stacking
set is.isCaster = cast
set is.isOwningPlayer = GetOwningPlayer(cast)
set is.isCasterX = GetLocationX(loc)
set is.isCasterY = GetLocationY(loc)
set is.isTargetX = tx
set is.isTargetY = ty
set is.isRange = range
set a = Atan2(is.isTargetY-is.isCasterY,is.isTargetX-is.isCasterX)
set is.dum = CreateUnit(is.isOwningPlayer,DUMMY_CASTER,is.isCasterX,is.isCasterY,0.0)
call UnitAddAbility(is.dum,039;Aloc039;)
set is.rx = is.isCasterX + is.isRange * Cos(a)
set is.ry = is.isCasterY + is.isRange * Sin(a)
call TimerStart(t,wavetime,true,function impaleSystem.ImpRun)
call SetTimerData(t,is)
call RemoveLocation(loc)
set loc = null
set t = null
return is
endmethod
private method onDestroy takes nothing returns nothing
call KillUnit(.dum)
set .dum = null
endmethod
endstruct
endlibrary
sample usage
JASS:
scope Impale initializer init
private function con takes nothing returns boolean
return GetSpellAbilityId() == 039;A001039;
endfunction
private function act takes nothing returns nothing
local unit cast = GetTriggerUnit()
local location loc = GetSpellTargetLoc()
local real x = GetLocationX(loc)
local real y = GetLocationY(loc)
local impaleSystem is = impaleSystem.create(cast,x,y,700.0,0.08, true)
call RemoveLocation(loc)
set loc = null
set cast = null
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function act)
call TriggerAddCondition(t,Condition(function con))
endfunction
endscope