- Joined
- Oct 28, 2008
- Messages
- 40
I am having some major issues with a little code snippet I am trying to write. Basically, it is supposed to replace a hero with another when leveling up - just like in Creep Wars. My problem is that I am not simply replacing the unit, but also setting the new unit to the same level as the original. I have discovered that using SetHeroXP() or AddHeroXP() will crash the game unless I use this exact code; I cannot even replace one of my own variables with a build-in variable without it crashing.
I want this to use locals anyway so multiple heroes can evolve at the same time, but I cannot seem to make anything but this code work. This is my first "custom" Jass trigger, but I have read through and experimented with hundreds of others. If you all don't mind, a nice description of the problem would also be helpful; I want to know why the problem exists, not just how to fix it.
Just in case, this is the original code I had. This should replicate the problem.
Now, I also want to explain why I am doing (or not doing) certain things here. I am not replacing the original unit with the ReplaceUnitBJ() function because it also causes a crash, but the working code is basically a working hybrid between my original code and the ReplaceUnitBJ(). I also have the unit types in as literals right now, but I will put in an array of units for it to loop through for readability when I have other unit types created. The last major thing I can think of is that I am using custom values to ensure the new unit doesn't go through this trigger and create an infinite loop when it levels up, but I know there was some talk about it leaking. I am very interested in hearing about alternatives.
I want this to use locals anyway so multiple heroes can evolve at the same time, but I cannot seem to make anything but this code work. This is my first "custom" Jass trigger, but I have read through and experimented with hundreds of others. If you all don't mind, a nice description of the problem would also be helpful; I want to know why the problem exists, not just how to fix it.
JASS:
function Trig_Determine_Eligibility_Func007C takes nothing returns boolean
if ( ( GetHeroLevel(GetLevelingUnit()) == 10 ) ) then
return true
endif
if ( ( GetHeroLevel(GetLevelingUnit()) == 20 ) ) then
return true
endif
if ( ( GetHeroLevel(GetLevelingUnit()) == 30 ) ) then
return true
endif
if ( ( GetHeroLevel(GetLevelingUnit()) == 40 ) ) then
return true
endif
return false
endfunction
function Trig_Determine_Eligibility_Conditions takes nothing returns boolean
if ( not Trig_Determine_Eligibility_Func007C() ) then
return false
endif
if (GetUnitUserData(GetLevelingUnit()) == 1) then
return false
endif
return true
endfunction
function Trig_Determine_Eligibility_Func005001001 takes nothing returns boolean
return ( GetPlayerController(GetFilterPlayer()) == MAP_CONTROL_USER )
endfunction
function Trig_Determine_Eligibility_Actions takes nothing returns nothing
local boolean oldUnitSelected = IsUnitSelected(GetLevelingUnit(), GetOwningPlayer(GetLevelingUnit()))
local integer oldExperience = GetHeroXP(GetLevelingUnit())
local player oldPlayer = GetOwningPlayer(GetLevelingUnit())
local location oldPosition = GetUnitLoc(GetLevelingUnit())
local real oldRotation = GetUnitFacing(GetLevelingUnit())
local integer oldUnitType = GetUnitTypeId(GetLevelingUnit())
local unit newUnit
local unit oldUnit = GetLevelingUnit()
call ShowUnitHide( oldUnit )
if ( ( oldUnitType == 'H009' ) == true ) then
set newUnit = CreateUnitAtLoc( oldPlayer, 'H00A', oldPosition, oldRotation )
else
set newUnit = CreateUnitAtLoc( oldPlayer, 'H00A', oldPosition, oldRotation )
endif
call SetUnitUserData( newUnit, 1 )
call AddHeroXP( newUnit, oldExperience, true )
call SetUnitUserData( newUnit, 0 )
if ( oldUnitSelected == true) then
call SelectUnitForPlayerSingle( newUnit, oldPlayer )
endif
call RemoveUnit( oldUnit )
endfunction
//===========================================================================
function InitTrig_Determine_Eligibility takes nothing returns nothing
set gg_trg_Determine_Eligibility = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Determine_Eligibility, EVENT_PLAYER_HERO_LEVEL )
call TriggerAddCondition( gg_trg_Determine_Eligibility, Condition( function Trig_Determine_Eligibility_Conditions ) )
call TriggerAddAction( gg_trg_Determine_Eligibility, function Trig_Determine_Eligibility_Actions )
endfunction
Just in case, this is the original code I had. This should replicate the problem.
JASS:
function Trig_Determine_Eligibility_Func007C takes nothing returns boolean
if ( ( GetHeroLevel(GetLevelingUnit()) == 10 ) ) then
return true
endif
if ( ( GetHeroLevel(GetLevelingUnit()) == 20 ) ) then
return true
endif
if ( ( GetHeroLevel(GetLevelingUnit()) == 30 ) ) then
return true
endif
if ( ( GetHeroLevel(GetLevelingUnit()) == 40 ) ) then
return true
endif
return false
endfunction
function Trig_Determine_Eligibility_Conditions takes nothing returns boolean
if ( not Trig_Determine_Eligibility_Func007C() ) then
return false
endif
return true
endfunction
function Trig_Determine_Eligibility_Func005001001 takes nothing returns boolean
return ( GetPlayerController(GetFilterPlayer()) == MAP_CONTROL_USER )
endfunction
function Trig_Determine_Eligibility_Actions takes nothing returns nothing
local boolean oldUnitSelected = IsUnitSelected(GetLevelingUnit(), GetOwningPlayer(GetLevelingUnit()))
local integer oldExperience = GetHeroXP(GetLevelingUnit())
local player oldPlayer = GetOwningPlayer(GetLevelingUnit())
local location oldPosition = GetUnitLoc(GetLevelingUnit())
local real oldRotation = GetUnitFacing(GetLevelingUnit())
local integer oldUnitType = GetUnitTypeId(GetLevelingUnit())
local unit newUnit
call RemoveUnit( oldUnit )
if ( ( oldUnitType == 'H009' ) == true ) then
set newUnit = CreateUnitAtLoc( oldPlayer, 'H00A', oldPosition, oldRotation )
else
set newUnit = CreateUnitAtLoc( oldPlayer, 'H00A', oldPosition, oldRotation )
endif
call AddHeroXP( newUnit, oldExperience, true )
if ( oldUnitSelected == true) then
call SelectUnitForPlayerSingle( newUnit, oldPlayer )
endif
endfunction
//===========================================================================
function InitTrig_Determine_Eligibility takes nothing returns nothing
set gg_trg_Determine_Eligibility = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Determine_Eligibility, EVENT_PLAYER_HERO_LEVEL )
call TriggerAddCondition( gg_trg_Determine_Eligibility, Condition( function Trig_Determine_Eligibility_Conditions ) )
call TriggerAddAction( gg_trg_Determine_Eligibility, function Trig_Determine_Eligibility_Actions )
endfunction
Now, I also want to explain why I am doing (or not doing) certain things here. I am not replacing the original unit with the ReplaceUnitBJ() function because it also causes a crash, but the working code is basically a working hybrid between my original code and the ReplaceUnitBJ(). I also have the unit types in as literals right now, but I will put in an array of units for it to loop through for readability when I have other unit types created. The last major thing I can think of is that I am using custom values to ensure the new unit doesn't go through this trigger and create an infinite loop when it levels up, but I know there was some talk about it leaking. I am very interested in hearing about alternatives.