HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

impale system glitches and stuffs like that

05-24-2009, 12:48 PM#1
Sinnergy
UPDATED the code and looks fine, what i need now is leak check that could possibly lag the game

Collapse 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 = 'e000'                  //Your Dummy Caster
    private constant integer FLY  = 'Amrf'                          //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,'BTLF',3.0)
        call UnitAddAbility(dum,'Aloc')
        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 = 'A000'
    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,'Aloc')
        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
Collapse JASS:
scope Impale initializer init

private function con takes nothing returns boolean
    return GetSpellAbilityId() == 'A001'
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
05-24-2009, 07:51 PM#2
Mr.Malte
Why don't you use a Jump System?
And please replace PUI with AutoIndex.

You could do this:
On create:
Collapse JASS:
if Jumping[GetUnitId(u)] == true then
return
endif
set Jumping[GetUnitId(u)] = true

and if the jump ends:
set Jumping[GetUnitId(u)] = false
05-25-2009, 02:52 AM#3
Sinnergy
Quote:
Originally Posted by Mr.Malte
Why don't you use a Jump System?
like parabolaZ? this is only a horizontal jump, not a forward jump, i dont think i need some jump system for this
Quote:
Originally Posted by Mr.Malte
And please replace PUI with AutoIndex.
later
Quote:
Originally Posted by Mr.Malte
You could do this:
On create:
Collapse JASS:
if Jumping[GetUnitId(u)] == true then
return
endif
set Jumping[GetUnitId(u)] = true

and if the jump ends:
set Jumping[GetUnitId(u)] = false
im going to try this after i get into my computer

thanks
06-02-2009, 02:02 PM#4
Sinnergy
bump, updated the thread, now i need something like improving the code and some leak check that could possibly lag the game, especially the part when the unit starts jumping, i wanted to use some sort of smooth jumping for this, also i dont know how to initialize the off1 to something like 60 in autoindex (while pui has PUI_PROPERTY), so that i can decrement it, and then increment it when the unit starts falling (to add velocity), which will be useful for smooth jumping

-now replaced PUI with autoindex