• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS] bug with an ability being overwritten

Level 2
Joined
Apr 29, 2024
Messages
8
Hello, I have a problem with my super nova ability, its supposed to fall towards the ground and then explode and deal damage overtime. But there is a problem if another spell is cast during its landing the supernova ability disappears. Another problem is if the supernova has already landed, and another spell is being used. The supernova will stop dealing damage completely, though the animation of the nuke will still continue. I attached two video files, one with the bug happening and other how the spell acts normally. I dont know what is interfering/overwriting the ability.
Code:
function Trig_Super_Nova_Func027001003 takes nothing returns boolean
return(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit()))==true)
endfunction
function Trig_Super_Nova_Func027A takes nothing returns nothing
call UnitDamageTargetBJ(GetSpellAbilityUnit(),GetEnumUnit(),(I2R(GetHeroStatBJ(bj_HEROSTAT_INT,GetSpellAbilityUnit(),false))*(I2R(GetUnitAbilityLevelSwapped('A06E',GetSpellAbilityUnit()))*1.50)),ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL)
endfunction
function Trig_Super_Nova_Func030001003 takes nothing returns boolean
return(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit()))==true)
endfunction
function Trig_Super_Nova_Func030A takes nothing returns nothing
call UnitDamageTargetBJ(GetSpellAbilityUnit(),GetEnumUnit(),(I2R(GetHeroStatBJ(bj_HEROSTAT_INT,GetSpellAbilityUnit(),false))*(I2R(GetUnitAbilityLevelSwapped('A06E',GetSpellAbilityUnit()))*1.50)),ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL)
endfunction
function Trig_Super_Nova_Func033001003 takes nothing returns boolean
return(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit()))==true)
endfunction
function Trig_Super_Nova_Func033A takes nothing returns nothing
call UnitDamageTargetBJ(GetSpellAbilityUnit(),GetEnumUnit(),(I2R(GetHeroStatBJ(bj_HEROSTAT_INT,GetSpellAbilityUnit(),false))*(I2R(GetUnitAbilityLevelSwapped('A06E',GetSpellAbilityUnit()))*1.50)),ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL)
endfunction
function Trig_Super_Nova_Actions takes nothing returns nothing
local player p = GetTriggerPlayer()
set udg_DeathBallPoint=GetSpellTargetLoc()
set udg_Loc=GetUnitLoc(GetSpellAbilityUnit()) 
set udg_Caster[GetConvertedPlayerId(GetTriggerPlayer())] = GetTriggerUnit()
call CreateNUnitsAtLocFacingLocBJ(1,'h045',p,udg_Loc,udg_Loc)
call SetUnitTimeScalePercent(GetLastCreatedUnit(),150.00)
call SetUnitVertexColorBJ(GetLastCreatedUnit(),100,70.00,0.00,0)
call UnitApplyTimedLifeBJ(1.00,'BTLF',GetLastCreatedUnit())
call SetUnitAnimation(GetTriggerUnit(),"Spell Channel")
call CreateNUnitsAtLocFacingLocBJ(1,'h044',p,udg_Loc,udg_DeathBallPoint)
call IssuePointOrderLoc(GetLastCreatedUnit(),"move",udg_DeathBallPoint)
set udg_deathballreqs[1]=GetLastCreatedUnit()
call EnableTrigger(gg_trg_falling_nova)
call IssuePointOrderLoc(udg_deathballreqs[1],"move",udg_DeathBallPoint)
call RemoveLocation(udg_Loc)
loop
call BJDebugMsg("loop")
exitwhen((GetUnitFlyHeight(udg_deathballreqs[1])<=10.00))
call TriggerSleepAction(RMaxBJ(bj_WAIT_FOR_COND_MIN_INTERVAL,0.10))
endloop
call BJDebugMsg("end loop")
call DisableTrigger(gg_trg_falling_nova)
call RemoveUnit(udg_deathballreqs[1])
call CreateNUnitsAtLoc(1,'h03R',p,udg_DeathBallPoint,bj_UNIT_FACING)
call UnitApplyTimedLifeBJ(5.00,'BTLF',GetLastCreatedUnit())
call CreateNUnitsAtLoc(1,'h02L',p,udg_DeathBallPoint,bj_UNIT_FACING)
call SetUnitScalePercent(bj_lastCreatedUnit,(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)),(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)),(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)))
call SetUnitTimeScalePercent(bj_lastCreatedUnit,50.00)
call SetUnitAnimation(GetLastCreatedUnit(),"birth")
call CreateNUnitsAtLoc(1,'h02W',p,udg_DeathBallPoint,bj_UNIT_FACING)
call SetUnitFlyHeightBJ(GetLastCreatedUnit(),3000.00,100.00)
call UnitApplyTimedLifeBJ(2.00,'BTLF',GetLastCreatedUnit())
set bj_wantDestroyGroup=true
call ForGroupBJ(GetUnitsInRangeOfLocMatching(700.00,udg_DeathBallPoint,Condition(function Trig_Super_Nova_Func027001003)),function Trig_Super_Nova_Func027A)
call TriggerSleepAction(1.00)
set bj_wantDestroyGroup=true
call ForGroupBJ(GetUnitsInRangeOfLocMatching(700.00,udg_DeathBallPoint,Condition(function Trig_Super_Nova_Func030001003)),function Trig_Super_Nova_Func030A)
call TriggerSleepAction(1.00)
set bj_wantDestroyGroup=true
call ForGroupBJ(GetUnitsInRangeOfLocMatching(700.00,udg_DeathBallPoint,Condition(function Trig_Super_Nova_Func033001003)),function Trig_Super_Nova_Func033A)
call RemoveLocation(udg_DeathBallPoint)
endfunction
 

Attachments

  • Warcraft III Reforged 2024.04.29 - 00.58.41.04.mp4
    17.9 MB
  • Warcraft III Reforged 2024.04.29 - 00.57.43.03.mp4
    15.4 MB
Level 39
Joined
Feb 27, 2007
Messages
5,054
Is this entire trigger converted to JASS just so you could use a raw loop..endloop? If so you can in the future just include those as custom script lines wherever you need in a GUI trigger. Converted triggers like this are very difficult to read and advise because of the way GUI nests functions and the lack of formatting.

For GUI use this: How To Post Your Trigger, and for JASS use [code=jass][/code] tags to get syntax coloring for readability. For myself and anyone else who comes to read this thread:
JASS:
function Trig_Super_Nova_Func027001003 takes nothing returns boolean
  return(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit()))==true)
endfunction

function Trig_Super_Nova_Func027A takes nothing returns nothing
  call UnitDamageTargetBJ(GetSpellAbilityUnit(),GetEnumUnit(),(I2R(GetHeroStatBJ(bj_HEROSTAT_INT,GetSpellAbilityUnit(),false))*(I2R(GetUnitAbilityLevelSwapped('A06E',GetSpellAbilityUnit()))*1.50)),ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL)
endfunction

function Trig_Super_Nova_Func030001003 takes nothing returns boolean
  return(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit()))==true)
endfunction

function Trig_Super_Nova_Func030A takes nothing returns nothing
  call UnitDamageTargetBJ(GetSpellAbilityUnit(),GetEnumUnit(),(I2R(GetHeroStatBJ(bj_HEROSTAT_INT,GetSpellAbilityUnit(),false))*(I2R(GetUnitAbilityLevelSwapped('A06E',GetSpellAbilityUnit()))*1.50)),ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL)
endfunction

function Trig_Super_Nova_Func033001003 takes nothing returns boolean
  return(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetSpellAbilityUnit()))==true)
endfunction

function Trig_Super_Nova_Func033A takes nothing returns nothing
  call UnitDamageTargetBJ(GetSpellAbilityUnit(),GetEnumUnit(),(I2R(GetHeroStatBJ(bj_HEROSTAT_INT,GetSpellAbilityUnit(),false))*(I2R(GetUnitAbilityLevelSwapped('A06E',GetSpellAbilityUnit()))*1.50)),ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL)
endfunction

function Trig_Super_Nova_Actions takes nothing returns nothing
  local player p = GetTriggerPlayer()
  set udg_DeathBallPoint=GetSpellTargetLoc()
  set udg_Loc=GetUnitLoc(GetSpellAbilityUnit())
  set udg_Caster[GetConvertedPlayerId(GetTriggerPlayer())] = GetTriggerUnit()
 
  call CreateNUnitsAtLocFacingLocBJ(1,'h045',p,udg_Loc,udg_Loc)
  call SetUnitTimeScalePercent(GetLastCreatedUnit(),150.00)
  call SetUnitVertexColorBJ(GetLastCreatedUnit(),100,70.00,0.00,0)
  call UnitApplyTimedLifeBJ(1.00,'BTLF',GetLastCreatedUnit())
  call SetUnitAnimation(GetTriggerUnit(),"Spell Channel")
 
  call CreateNUnitsAtLocFacingLocBJ(1,'h044',p,udg_Loc,udg_DeathBallPoint)
  call IssuePointOrderLoc(GetLastCreatedUnit(),"move",udg_DeathBallPoint)
  set udg_deathballreqs[1]=GetLastCreatedUnit()
  call EnableTrigger(gg_trg_falling_nova)
  call IssuePointOrderLoc(udg_deathballreqs[1],"move",udg_DeathBallPoint)
  call RemoveLocation(udg_Loc)
 
  loop
    call BJDebugMsg("loop")
    exitwhen((GetUnitFlyHeight(udg_deathballreqs[1])<=10.00))
    call TriggerSleepAction(RMaxBJ(bj_WAIT_FOR_COND_MIN_INTERVAL,0.10))
  endloop
  call BJDebugMsg("end loop")
 
  call DisableTrigger(gg_trg_falling_nova)
  call RemoveUnit(udg_deathballreqs[1])
  call CreateNUnitsAtLoc(1,'h03R',p,udg_DeathBallPoint,bj_UNIT_FACING)
  call UnitApplyTimedLifeBJ(5.00,'BTLF',GetLastCreatedUnit())
 
  call CreateNUnitsAtLoc(1,'h02L',p,udg_DeathBallPoint,bj_UNIT_FACING)
  call SetUnitScalePercent(bj_lastCreatedUnit,(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)),(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)),(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)))
  call SetUnitTimeScalePercent(bj_lastCreatedUnit,50.00)
  call SetUnitAnimation(GetLastCreatedUnit(),"birth")
  call CreateNUnitsAtLoc(1,'h02W',p,udg_DeathBallPoint,bj_UNIT_FACING)
  call SetUnitFlyHeightBJ(GetLastCreatedUnit(),3000.00,100.00)
  call UnitApplyTimedLifeBJ(2.00,'BTLF',GetLastCreatedUnit())
 
  set bj_wantDestroyGroup=true
  call ForGroupBJ(GetUnitsInRangeOfLocMatching(700.00,udg_DeathBallPoint,Condition(function Trig_Super_Nova_Func027001003)),function Trig_Super_Nova_Func027A)
  call TriggerSleepAction(1.00)
  set bj_wantDestroyGroup=true
  call ForGroupBJ(GetUnitsInRangeOfLocMatching(700.00,udg_DeathBallPoint,Condition(function Trig_Super_Nova_Func030001003)),function Trig_Super_Nova_Func030A)
  call TriggerSleepAction(1.00)
  set bj_wantDestroyGroup=true
  call ForGroupBJ(GetUnitsInRangeOfLocMatching(700.00,udg_DeathBallPoint,Condition(function Trig_Super_Nova_Func033001003)),function Trig_Super_Nova_Func033A)
  call RemoveLocation(udg_DeathBallPoint)
endfunction
Overall this spell cannot be cast more than once simultaneously (usually called MUI - multi unit instanceable) because you are reusing some information stored in global variables that would get overwritten by additional casts. You started making this MPI (multi player instanceable) by using some array variables whose indices correspond to the player id of the caster's owning player, but you didn't fully commit to this idea so some things likely conflict.

Finally, you're not showing us all the triggers. Where is gg_trg_falling_nova?
 
Last edited:
Level 2
Joined
Apr 29, 2024
Messages
8
sorry I am new so I didnt know about the jass convertion. The map is open source, and I saw this bug and I just thought of attempting to fix it. Regarding the ability, theres only one player who can cast this spell. Which is Caster[12]. I tried using playerId, but as u said I didnt fully commit to this. But since theres only one person using this ability using so setting it like this "set udg_Caster[12]=GetTriggerUnit()" would perhaps be smarter option instead of making it MUI. But I am still finding difficulties in making it work, I am kind of stuck.
Here is the gg_trg_falling_nova
JASS:
function InitTrig_Super_Nova takes nothing returns nothing
set gg_trg_Super_Nova=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_Super_Nova,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_Super_Nova,Condition(function Trig_Super_Nova_Conditions))
call TriggerAddAction(gg_trg_Super_Nova,function Trig_Super_Nova_Actions)
endfunction
function Trig_falling_nova_Actions takes nothing returns nothing
call SetUnitFlyHeightBJ(udg_deathballreqs[1],(GetUnitFlyHeight(udg_deathballreqs[1])-25.00),0.00)
endfunction
function InitTrig_falling_nova takes nothing returns nothing
set gg_trg_falling_nova=CreateTrigger()
call DisableTrigger(gg_trg_falling_nova)
call TriggerRegisterTimerEventPeriodic(gg_trg_falling_nova,0.03)
call TriggerAddAction(gg_trg_falling_nova,function Trig_falling_nova_Actions)
endfunction
 
Level 39
Joined
Feb 27, 2007
Messages
5,054
Sorry I took a while to respond; I was being lazy and didn't actually read your code... I just glanced at it. So the issue is simply that the spell as coded cannot support multiple instances (what MUI is). Doesn't matter if it's different units or the same unit multiple times, whenever casts overlap you're overwriting the variables that point to the created units. Disabling the trigger because one cast finished also means the second cast never completes.

This can be overcome by properly something called Dynamic Indexing and is ultimately not that hard to do in GUI. That tutorial is great and should help you to understand what you're doing (giving each cast instance a unique number) and how to achieve it (loop over instances from 1-N and operate on all of them sequentially).

The other, uh... easier way is just to give the spell a cooldown that's longer than its duration. As long as only one unit can cast it like you said, then... problem solved! (But it's still sloppy and unoptimal if you want to improve it :D)

What's going on with the Custom Value stuff in this line?
JASS:
call SetUnitScalePercent(bj_lastCreatedUnit,(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)),(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)),(600.00+(I2R(GetUnitUserData(GetTriggerUnit()))*10.00)))
 
Top