• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Need help editing existing triggers

Status
Not open for further replies.
Level 3
Joined
Sep 9, 2022
Messages
10
Hi all, I'm new to all this and would like a bit of help with editing some existing spells if possible (war3 classic). I don't know JASS myself else I wouldn't be here.

For this one the actual issue is that in the game the damage gets applied 1st and the 'call LinearDisplacement' won't be applied if the units dies. I'm figuring the damage gets applied before the linear displacement. Either that or it has to do with some other system elsewhere because this is a consistent issue with other abilities as well, if the damage is enough to kill the unit any displacement the spell has won't trigger. Or maybe it's something about the unit death triggers but anyways I'll post the triggers just in case it's the spell in case anyone can spot anything wrong with it.

JASS:
function Luffy_W takes nothing returns nothing
        local integer Time     = SpellTime( )
        local integer HandleID = MUIHandle( )
        local real DMG

        if Time == 1 then
            set DMG = 175 + 225 * GetInt( "ALvL" )
            if GetUnitTypeId( GetUnit( "Caster" ) ) != 'N002' then
                set DMG = DMG + 125 + 115 * GetInt( "ALvL" )
                call PlaySoundOnUnit( Sounds[ 127 ], 100, GetUnit( "Caster" ) )
            else
                call PlaySoundOnUnit( Sounds[ 123 ], 100, GetUnit( "Caster" ) )
            endif
            call LinearDisplacement( GetUnit( "Target" ), GetUnitsAngle( GetUnit( "Caster" ), GetUnit( "Target" ) ), 200, .01, .01, false, false, "origin", "" )
            call DamageUnit( GetUnit( "Caster" ), GetUnit( "Target" ), DMG, "physical" )
            call CC_Unit( GetUnit( "Target" ), 1.5, "stun", true )
        endif

        if Time == 5 then
            call SetUnitFacing( GetUnit( "Target" ), GetUnitsAngle( GetUnit( "Target" ), GetUnit( "Caster" ) ) )
            call DestroyEffect( AddSpecialEffect( "war3mapImported\\explosion.mdx", GetUnitX( GetUnit( "Target" ) ), GetUnitY( GetUnit( "Target" ) ) ) )
        endif

        if Time == 50 or Stop_Spell( 2 ) then
            call CleanMUI( GetExpiredTimer( ) )
        endif
    endfunction

As for this one, the problem is that it does 0.1 ministuns but there's no wait time in between each one and it acts like a full stun instead.

JASS:
function Luffy_E takes nothing returns nothing
        local integer Time     = SpellTime( )
        local integer HandleID = MUIHandle( )
        local real DMG

        if Time == 1 then
            if GetUnitTypeId( GetUnit( "Caster" ) ) != 'N002' then
                call PlaySoundOnUnit( Sounds[ 128 ], 100, GetUnit( "Caster" ) )
            else
                call PlaySoundOnUnit( Sounds[ 124 ], 100, GetUnit( "Caster" ) )
            endif
            call SaveReal( HashTable, HandleID, StringHash( "Angle" ), GetUnitFacing( GetUnit( "Caster" ) ) )
            call SaveReal( HashTable, HandleID, StringHash( "CastX" ), NewX( GetUnitX( GetUnit( "Caster" ) ), 200, GetReal( "Angle" ) ) )
            call SaveReal( HashTable, HandleID, StringHash( "CastY" ), NewY( GetUnitY( GetUnit( "Caster" ) ), 200, GetReal( "Angle" ) ) )
        endif

        if Counter( 0, 10 ) then
            set DMG = 100 + 100 * GetInt( "ALvL" )
            call SaveInteger( HashTable, HandleID, StringHash( "Gatling_Hits" ), GetInt( "Gatling_Hits" ) + 1 )
            if GetUnitTypeId( GetUnit( "Caster" ) ) != 'N002' then
                set DMG = DMG + 2 * GetHeroLevel( GetUnit( "Caster" ) ) * GetInt( "ALvL" )
            endif
            call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", GetReal( "CastX" ), GetReal( "CastY" ) ) )
            call DestroyAoEDestruct( GetReal( "CastX" ), GetReal( "CastY" ), 350 )
            call EnumUnitsAOE( SpellGroup, GetReal( "CastX" ), GetReal( "CastY" ), 350 )
            loop
                set SysUnit = FirstOfGroup( SpellGroup )
                exitwhen SysUnit == null
                if UnitLife( SysUnit ) > 0 then
                    if IsUnitEnemyEx( GetUnit( "Caster" ), SysUnit ) then
                        call DamageUnit( GetUnit( "Caster" ), SysUnit, DMG / 10, "physical" )
                        call StunUnit2( GetUnit( "Caster" ),SysUnit, 20 )
                    endif
                endif
                call GroupRemoveUnit( SpellGroup, SysUnit )
            endloop
        endif

        if GetInt( "Gatling_Hits" ) == 50 or Stop_Spell( 0 ) or GetUnitOrder( GetUnit( "Caster" ) ) != "stampede" then
            if GetUnitOrder( GetUnit( "Caster" ) ) == "stampede" then
                call IssueImmediateOrder( GetUnit( "Caster" ), "stop" )
            endif
            call CleanMUI( GetExpiredTimer( ) )
        endif
    endfunction
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,010
Are you using some 3rd party/custom World Editor or have a huge prebuilt codebase for spells/whatnot you just dropped into your map?

The code you have shown here depends on/uses/refers to a whole bunch of other custom functions that are not shown. Without knowing, for example, what the code in LinearDisplacement() does/is, there's no real way to evaluate how to avoid the things you want to avoid. It's like reading a book in a language you sort of understand but not being able to look anything up or use a dictionary--difficult to say the least. These might not all be relevant to what's going on but here is a list of every undefined function I can see being used in these two bits of code:
JASS:
SpellTime
MUIHandle
GetInt
GetUnit
PlaySoundOnUnit
LinearDisplacement
GetUnitsAngle //reasonably self-explanatory but still included for completeness
DamageUnit
CC_Unit
Stop_Spell
CleanMUI

NewX
NewY
GetReal
Counter
DestroyAoEDestruct //probably exactly what I expect
EnumUnitsAOE //same here
UnitLife
IsUnitEnemyEx
StunUnit2
GetUnitOrder
The ones that are most relevant are the ones used in conjunction with the stuff you're trying to resolve. My best guess is simply that LinearDisplacement checks if the unit is dead or not and only moves it if it's alive.
 
Level 3
Joined
Sep 9, 2022
Messages
10
My best guess is simply that LinearDisplacement checks if the unit is dead or not and only moves it if it's alive.
Thank you. I found what was missing due to your suggestion.

As for the 2nd one it's definitely missing some code if I want it to act the way I want it to. I looked everywhere and there's nothing related about a timer or a delay or anything.
 
Last edited:
Level 3
Joined
Sep 9, 2022
Messages
10
JASS:
local integer Time = SpellTime( )
But I have no idea what that does.
I believe that's just about how long certain ability things such as animations should play.

JASS:
function SpellTime takes nothing returns integer
        call SaveInteger( HashTable, MUIHandle( ), StringHash( "SpellTime" ), GetInt( "SpellTime" ) + 1 )
        return GetInt( "SpellTime" )
    endfunction

    function IsUnitIgnored takes unit Target returns boolean
        local integer Index = 0
        if LoadInteger( HashTable, MUIHandle( ), GetHandleId( Target ) ) == 0 then
            set Index = GetInt( "Last_Unit_Index" ) + 1
            call SaveInteger( HashTable, MUIHandle( ), StringHash( "Last_Unit_Index" ), Index )
            call SaveInteger( HashTable, MUIHandle( ), GetHandleId( Target ), Index )
        endif

        if Index != 0 then
            if not LoadBoolean( HashTable, MUIHandle( ), StringHash( "Unit_Damaged_" + I2S( Index ) ) ) then
                call SaveBoolean( HashTable, MUIHandle( ), StringHash( "Unit_Damaged_" + I2S( Index ) ), true )
                return false
            endif
        endif
        return true
    endfunction
JASS:
function MUIHandle takes nothing returns integer
        return GetHandleId( GetExpiredTimer( ) )
    endfunction

But I believe the problem is here. 'call StunUnit2' links to a 'A0E9' stormbolt based dummy in the WE.
JASS:
    if IsUnitEnemyEx( GetUnit( "Caster" ), SysUnit ) then
                        call DamageUnit( GetUnit( "Caster" ), SysUnit, DMG / 10, "physical" )
                        call StunUnit2( GetUnit( "Caster" ),SysUnit, 20 )
StunUnit2:
JASS:
function StunUnit2 takes unit c, unit u, integer lvl returns nothing
        local integer i = GetPlayerId(GetOwningPlayer(c))
        local real x = GetUnitX(DummyPlayer2[i])
        local real y = GetUnitY(DummyPlayer2[i])
        call SetUnitX(DummyPlayer2[i], GetUnitX(u))
        call SetUnitY(DummyPlayer2[i], GetUnitY(u))
        call SetUnitFacingTimed(DummyPlayer2[i],Angle234(DummyPlayer2[i],u),0)
        call SetUnitAbilityLevel(DummyPlayer2[i], 'A0E9', lvl)
        call IssueTargetOrder(DummyPlayer2[i], "thunderbolt", u)
        call SetUnitPosition(DummyPlayer2[i], x, y)
        set i = 0
        set x = 0
        set y = 0
    endfunction

The 'A0E9' is set to a 0.10 Stun.
The problem is that it goes like this in practice 0.10 Stun, 0.10 Stun, ... , 0.10 Stun, 0.10 Stun, for about 3 seconds, which is the ability duration; (in it's given AoE). It needs to go like ' 0.10 Stun, wait 0.30, 0.10 Stun, wait 0.30 ... etc.'
So basically, it's a ministun but because there is no delay in between each proc it acts as a full stun instead. This is my problem with it.

From my understanding I'll either need a dummy that will have this kind of CD incorporated into it either I'm going to need to edit the related JASS, which is why I'm here.
 
Last edited:
Level 3
Joined
Sep 9, 2022
Messages
10
Question.

JASS:
  if IsUnitEnemyEx( GetUnit( "Caster" ), SysUnit ) then
                        call DamageUnit( GetUnit( "Caster" ), SysUnit, DMG / 10, "physical" )
                        call StunUnit3( GetUnit( "Caster" ),SysUnit, 1 )
Is there any way to put this call on a timed ON/OFF toggle?

JASS:
                        call StunUnit3( GetUnit( "Caster" ),SysUnit, 1 )
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,534
Question.

JASS:
  if IsUnitEnemyEx( GetUnit( "Caster" ), SysUnit ) then
                        call DamageUnit( GetUnit( "Caster" ), SysUnit, DMG / 10, "physical" )
                        call StunUnit3( GetUnit( "Caster" ),SysUnit, 1 )
Is there any way to put this call on a timed ON/OFF toggle?

JASS:
                        call StunUnit3( GetUnit( "Caster" ),SysUnit, 1 )
Do you mean like a Boolean variable that you can toggle to true/false?
vJASS:
if YourBoolean == true then
    call StunUnit3( GetUnit( "Caster" ),SysUnit, 1 )
endif
Here's how you would toggle the boolean:
vJASS:
set YourBoolean = true
set YourBoolean = false
You could also add the Boolean check inside of the StunUnit3 function so it applies universally.
 
Status
Not open for further replies.
Top