• 🏆 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!

Weird extra damage bug.

Status
Not open for further replies.
Level 17
Joined
Jun 2, 2009
Messages
1,137
Hello everyone. Before the start let me tell you i don't have any knowledge about Jass coding. One of my friends gave me to this trigger.

Now let me tell you what is going on there.

This spell casts powerful version of Fire, Frost and Lightning spells of the hero
Fire, Frost and Lightning spells are level 1 spells.
Elemental Hit is the level 6 spell.
When you cast Elemental Hit, it cast powerful version of last element of it's used.

JASS:
scope Elementalist

globals
    private constant integer DUMMY_ID = 'e006' // JFA caster dummy
   
    private constant integer FIRE_PROJECTILE = 'A0AC'
    private constant integer FROST_PROJECTILE = 'A0EM'
    private constant integer LIGHT_PROJECTILE = 'A0B0'
   
    private constant integer FIRE_ULTIMATE = 'A091'
    private constant integer FROST_ULTIMATE = 'A092'
    private constant integer LIGHT_ULTIMATE = 'A093'
   
    private constant integer FIRE_HERO = 'A0D6'
    private constant integer FROST_HERO = 'A0DI'
    private constant integer LIGHT_HERO = 'A0E9'

    private constant integer ULTIMATE_ID = 'A094'
   
    private constant integer FIRE_BONUS = 'A0KL'
    private constant integer FROST_BONUS = 'A0KJ'
    private constant integer LIGHT_BONUS = 'A0KK'
   
    private constant integer BONUS_BOOK_ID = 'A0KM'
   
    private constant integer FIRE_BUFF = 'B039'
    private constant integer FROST_BUFF = 'B037'
    private constant integer LIGHT_BUFF = 'B038'
endglobals

function ElementalistCastCons takes nothing returns boolean
    return GetSpellAbilityId() == FIRE_HERO or GetSpellAbilityId() == FROST_HERO or GetSpellAbilityId() == LIGHT_HERO or GetSpellAbilityId() == -1
endfunction
 
function ElementalistUltiCons takes nothing returns boolean
    return GetSpellAbilityId() == ULTIMATE_ID
endfunction
 
function ElementalistCastAct takes nothing returns nothing
    local integer id = GetSpellAbilityId()
    local unit caster = GetTriggerUnit()
    local player p = GetOwningPlayer(caster)
  
    // Bonus abilities
    call SetPlayerAbilityAvailable(p, FROST_BONUS, false)
    call SetPlayerAbilityAvailable(p, LIGHT_BONUS, false)
    call SetPlayerAbilityAvailable(p, FIRE_BONUS, false)
    call SetPlayerAbilityAvailable(p, -1, false)
  
    // Missile Abilities
    call UnitRemoveAbility(caster, FIRE_PROJECTILE)
    call UnitRemoveAbility(caster, FROST_PROJECTILE)
    call UnitRemoveAbility(caster, LIGHT_PROJECTILE)
    call UnitRemoveAbility(caster, -1)
    //call SetPlayerAbilityAvailable(p, FIRE_PROJECTILE, false)
    //call SetPlayerAbilityAvailable(p, FROST_PROJECTILE, false)
    //call SetPlayerAbilityAvailable(p, LIGHT_PROJECTILE, false)
    //call SetPlayerAbilityAvailable(p, -1, false)
  
  
    if id == FIRE_HERO then
        // Fire cast
        call SetPlayerAbilityAvailable(p, FIRE_BONUS, true)
        call SetPlayerAbilityAvailable(p, FIRE_PROJECTILE, true)
        call SetUnitAbilityLevel(caster, FIRE_BONUS, GetUnitAbilityLevel(caster, id))
        call UnitAddAbility(caster, FIRE_PROJECTILE)
        call UnitRemoveAbility(caster, FROST_BUFF) // remove frost bonus
        call UnitRemoveAbility(caster, LIGHT_BUFF) // remove lightning bonus
        call UnitRemoveAbility(caster, -1) // remove wind bonus
      
    elseif id == FROST_HERO then
        // Frost cast
        call SetPlayerAbilityAvailable(p, FROST_BONUS, true)
        call SetPlayerAbilityAvailable(p, FROST_PROJECTILE, true)
        call SetUnitAbilityLevel(caster, FROST_BONUS, GetUnitAbilityLevel(caster, id))
        call UnitAddAbility(caster, FROST_PROJECTILE)
        call UnitRemoveAbility(caster, FIRE_BUFF) // remove fire bonus
        call UnitRemoveAbility(caster, LIGHT_BUFF) // remove lightning bonus
        call UnitRemoveAbility(caster, -1) // remove wind bonus
      
    elseif id == LIGHT_HERO then
        // Lightning cast
        call SetPlayerAbilityAvailable(p, LIGHT_BONUS, true)
        call SetPlayerAbilityAvailable(p, LIGHT_PROJECTILE, true)
        call SetUnitAbilityLevel(caster, LIGHT_BONUS, GetUnitAbilityLevel(caster, id))
        call UnitAddAbility(caster, LIGHT_PROJECTILE)
        call UnitRemoveAbility(caster, FROST_BUFF) // remove frost bonus
        call UnitRemoveAbility(caster, FIRE_BUFF) // remove fire bonus
        call UnitRemoveAbility(caster, -1) // remove wind bonus
      
    elseif id == 0 then
        // Air cast
        call SetPlayerAbilityAvailable(p, -1, true)
        call SetPlayerAbilityAvailable(p, -1, true)
        call SetUnitAbilityLevel(caster, -1, GetUnitAbilityLevel(caster, id))
        call UnitAddAbility(caster, -1)
        call UnitRemoveAbility(caster, FROST_BUFF) // remove frost bonus
        call UnitRemoveAbility(caster, LIGHT_BUFF) // remove lightning bonus
        call UnitRemoveAbility(caster, FIRE_BUFF) // remove frost bonus
      
    endif
  
    set caster = null
    set p = null
endfunction
 
function ElementalistUltiAct takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    set bj_lastCreatedUnit = CreateUnit(GetTriggerPlayer(), DUMMY_ID, 0, 0, 0)
    call SetUnitX(bj_lastCreatedUnit, GetUnitX(caster))
    call SetUnitY(bj_lastCreatedUnit, GetUnitY(caster))
    call UnitApplyTimedLife(bj_lastCreatedUnit, 'BTLF', 3.00)
    if GetUnitAbilityLevel(caster, FIRE_PROJECTILE) > 0 then
      
        // Fire ulti
        call UnitAddAbility(bj_lastCreatedUnit, FIRE_ULTIMATE)
        call SetUnitAbilityLevel(bj_lastCreatedUnit, FIRE_ULTIMATE, GetUnitAbilityLevel(caster, FIRE_HERO))
        call IssueTargetOrder(bj_lastCreatedUnit, "firebolt", GetSpellTargetUnit())
  
    elseif GetUnitAbilityLevel(caster, FROST_PROJECTILE) > 0 then
      
        // Frost ulti
        call UnitAddAbility(bj_lastCreatedUnit, FROST_ULTIMATE)
        call SetUnitAbilityLevel(bj_lastCreatedUnit, FROST_ULTIMATE, GetUnitAbilityLevel(caster, FROST_HERO))
        call IssueTargetOrder(bj_lastCreatedUnit, "frostnova", GetSpellTargetUnit())
  
    elseif GetUnitAbilityLevel(caster, LIGHT_PROJECTILE) > 0 then
      
        // Lightning ulti
        call UnitAddAbility(bj_lastCreatedUnit, LIGHT_ULTIMATE)
        call SetUnitAbilityLevel(bj_lastCreatedUnit, FIRE_ULTIMATE, GetUnitAbilityLevel(caster, LIGHT_HERO))
        call IssueTargetOrder(bj_lastCreatedUnit, "chainlightning", GetSpellTargetUnit())
  
    elseif GetUnitAbilityLevel(caster, -1) > 0 then
      
        // Wind ulti
        call UnitAddAbility(bj_lastCreatedUnit, -1)
        call SetUnitAbilityLevel(bj_lastCreatedUnit, -1, GetUnitAbilityLevel(caster, -1))
        call IssueTargetOrder(bj_lastCreatedUnit, null, GetSpellTargetUnit())
  
    endif
  
    set caster = null
endfunction
 
//===========================================================================
function InitTrig_Elementalist_All takes nothing returns nothing
    local trigger cast = CreateTrigger()
    local trigger ulti = CreateTrigger()
    local integer i = 0
    local player p
    loop
        exitwhen i == 16
        set p = Player(i)
        call TriggerRegisterPlayerUnitEvent(cast, p, EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        call TriggerRegisterPlayerUnitEvent(ulti, p, EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        call SetPlayerAbilityAvailable(p, BONUS_BOOK_ID, false)
      
        // Disable bonuses
        call SetPlayerAbilityAvailable(p, FROST_BONUS, false)
        call SetPlayerAbilityAvailable(p, LIGHT_BONUS, false)
        call SetPlayerAbilityAvailable(p, FIRE_BONUS, false)
        call SetPlayerAbilityAvailable(p, -1, false)
      
        // Disable missiles
        call SetPlayerAbilityAvailable(p, FIRE_PROJECTILE, false)
        call SetPlayerAbilityAvailable(p, FROST_PROJECTILE, false)
        call SetPlayerAbilityAvailable(p, LIGHT_PROJECTILE, false)
        call SetPlayerAbilityAvailable(p, -1, false)
      
        set i = i + 1
    endloop
    call TriggerAddCondition(cast, Condition(function ElementalistCastCons))
    call TriggerAddCondition(ulti, Condition(function ElementalistUltiCons))
    call TriggerAddAction(cast, function ElementalistCastAct)
    call TriggerAddAction(ulti, function ElementalistUltiAct)
    set cast = null
    set ulti = null
    set p = null
endfunction

endscope

Now here it comes the mysterious bug.

Elemental Hit deals 300/400/500 damage when last element is Fire.

When you enter the game and level up your Fire and Elemental Hit you deal 300 damage as expected. Because Elemental Hit Dummy spell damage 300/400/50

But if you level up your Fire ability to Level 2, Elemental Hit deals 400 damage
When you level up Fire ability to Level 3 or Level 4, Elemental Hit deals 500 damage.

Question: Why skill level of Elemental Hit increases with Fire ability.
It should be increase on Level 6, Level 11 and Level 16 (as it should be when you level up your skill)
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
...the level of the dummy ability is set to the level of FIRE_HERO not ULTIMATE_ID. That should literally have been the first thing you checked because it's exactly what the issue you described is. "The ability is being cast at the wrong level. Should I check to make sure it's being set to the correct level? Nah."
JASS:
//These lines....
call SetUnitAbilityLevel(bj_lastCreatedUnit, FIRE_ULTIMATE, GetUnitAbilityLevel(caster, FIRE_HERO))
call SetUnitAbilityLevel(bj_lastCreatedUnit, FROST_ULTIMATE, GetUnitAbilityLevel(caster, FROST_HERO))
call SetUnitAbilityLevel(bj_lastCreatedUnit, FIRE_ULTIMATE, GetUnitAbilityLevel(caster, LIGHT_HERO))  //NOTE THAT THIS LINE ALSO HAS ANOTHER ERROR AND USES FIRE_ULTIMATE WHERE IT SHOULD USE LIGHT_ULTIMATE

//Should look like this instead:
call SetUnitAbilityLevel(bj_lastCreatedUnit, FIRE_ULTIMATE, GetUnitAbilityLevel(caster, ULTIMATE_ID))
call SetUnitAbilityLevel(bj_lastCreatedUnit, FROST_ULTIMATE, GetUnitAbilityLevel(caster, ULTIMATE_ID))
call SetUnitAbilityLevel(bj_lastCreatedUnit, LIGHT_ULTIMATE, GetUnitAbilityLevel(caster, ULTIMATE_ID))

Also these lines all actually do nothing and could introduce something weird (no idea what happens when you give negative integers to something like this when it expects an positive ability code). They should be removed:
JASS:
call SetPlayerAbilityAvailable(p, -1, false)
call UnitRemoveAbility(caster, -1)
call UnitRemoveAbility(caster, -1) // remove wind bonus
call SetPlayerAbilityAvailable(p, -1, true)
call SetPlayerAbilityAvailable(p, -1, true)
call SetUnitAbilityLevel(caster, -1, GetUnitAbilityLevel(caster, id))
call UnitAddAbility(caster, -1)
call SetUnitAbilityLevel(bj_lastCreatedUnit, -1, GetUnitAbilityLevel(caster, -1))
... or GetSpellAbilityId() == -1
 
Status
Not open for further replies.
Top