HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Add/Subtract hero experience with triggers?

07-17-2011, 09:23 PM#1
Xindaris
I had an idea I wanted to use for a custom hero, with trigger-driven abilities that temporarily add or subtract XP from the target hero. I tried putting it together myself and testing it, but it didn't work. Here are the triggers in question (all abilities are dummy hero abilities, level up and level down are targeted and the boost abilities are passive):
Hidden information:
Trigger:
Leveler Level Up
Collapse Events
Unit - A unit Begins casting an ability
Collapse Conditions
(Ability being cast) Equal to Level Up
Collapse Actions
Set LevelUpPower = (((Level of Level Up for (Triggering unit)) x 1000) + ((Level of XP Boost for (Casting unit)) x 500))
Set LevelerTarget = (Target unit of ability being cast)
Hero - Add LevelUpPower experience to LevelerTarget, Show level-up graphics
Set LevelUpDuration = (((Level of Level Up for (Triggering unit)) x 20) + ((Level of Length Boost for (Casting unit)) x 10))
Wait (Real(LevelUpDuration)) seconds
Game - Display to (All players) for 30.00 seconds the text: Level Up Over!
Hero - Set LevelerTarget experience to ((Hero experience of LevelerTarget) - LevelUpPower), Hide level-up graphics
Unit - Reset ability cooldowns for (Casting unit)

Trigger:
Leveler Level Down
Collapse Events
Unit - A unit Begins casting an ability
Collapse Conditions
(Ability being cast) Equal to Level Down
Collapse Actions
Set LevelDownPower = (1000 + ((Level of XP Boost for (Casting unit)) x 1000))
Set LevelerTarget = (Target unit of ability being cast)
Hero - Set LevelerTarget experience to ((Hero experience of LevelerTarget) - LevelUpPower), Hide level-up graphics
Set LevelDownDuration = (30 + ((Level of Length Boost for (Casting unit)) x 10))
Wait (Real(LevelDownDuration)) seconds
Hero - Add LevelDownPower experience to LevelerTarget, Show level-up graphics
Unit - Reset ability cooldowns for (Casting unit)


In particular, the line that does not appear to be working is whenever I say "Set LevelerTarget experience to (current XP - Variable)". Is there some other way, or no way at all, to directly subtract experience?


On a related note, I set the Level Up and Level Down spells to have a very long cooldown and work on the same order, since I wanted the triggers to handle the cooldowns instead, and for both abilities to have the same cooldown. But if both abilities are learned, it seems to always cast Level Down, and the cooldown doesn't seem to start where it's supposed to, instead starting with just a sliver of the black stuff that says the ability is cooling down.
07-17-2011, 10:56 PM#2
Anitarf
A simple test shows that it is not possible to decrease a hero's experience directly. The native functions simply refuse to set a hero's experience to a new value if it is lower than the hero's current experience. The same is true for trying to set a hero's level, however the BJ function suggests there is a way:

Collapse JASS:
function SetHeroLevelBJ takes unit whichHero, integer newLevel, boolean showEyeCandy returns nothing
    local integer oldLevel = GetHeroLevel(whichHero)

    if (newLevel > oldLevel) then
        call SetHeroLevel(whichHero, newLevel, showEyeCandy)
    elseif (newLevel < oldLevel) then
        call UnitStripHeroLevel(whichHero, oldLevel - newLevel)
    else
        // No change in level - ignore the request.
    endif
endfunction

The UnitStripHeroLevel function lets you reduce a hero's level. You could use it to reduce the hero's level until his current experience is less than the target experience, then add the difference to reach the target.

The problem is that UnitStripHeroLevel seems to have some unavoidable side effects. It will automatically unlearn abilities when the hero goes down a level. You can avoid this by adding a skill point to the hero before reducing his level, but in some cases an ability will still get unlearned so doing this is pointless. One case is if you already have all your abilities learned since in that case you can't add any more skill points to the hero. Another case is when the hero's level is reduced below the level skip requirements of an already learned ability.

There's even a bug here that can cause your hero to loose skill points in some ability level requirements configurations. For example, if your hero can learn multiple abilities at level 1 that each have a 3 level skip requirement (WC3's default is 2), then if you save up your skill points you can get two abilities to level 2 once your hero hits level 4. If the level is decreased back to 3, both abilities will have their level decreased to 1, but the hero won't get one skill point back like he should (since he only went down one level, but had two skills deleveled). This is luckily not a problem with the default WC3 hero skill setup where you can't save up skill points in this way.

So, the solution described earlier would need to save the ability levels of all hero skills on the hero (this means you'd need a database of all heroes and their skills). This is because the experience reduction we are aiming for will not necessarily take him down a level, so once we add the experience back to the hero to get the target reduction, the hero will gain the level back and get a skill point to spend. That'll look weird if you don't automatically spend it for him on the same ability that was lost when deleveling the hero, but to know which ability that was you need the database mentioned earlier.
07-18-2011, 12:45 PM#3
Fledermaus
You can subtract experience, you just can't make a hero lose a level this way. Didn't read what Ani said but it's probably helpful, just wanted to add that.
07-19-2011, 04:38 AM#4
Xindaris
Well, it's at least as bad as I thought. I did figure out how exactly the experience required is calculated, but I'm not entirely sure it's worth the trouble to work all those calculations into a trigger. I do know that setting levels lower is possible, and I'm fairly familiar with it, since it exists in RP maps, which I used to play a fair amount of. If I remember right, a hero past the point of learning skills (i.e. a hero with 10 possible skill points at level 15) won't lose any skills as long as they don't level down past the last time they would have learned an ability (in this case, 10).

I actually was okay with the hero unlearning spells when they leveled back down for the "Level Up" power, since those heroes are player-controlled and I figure any player should be able to remember or easily figure out what skill they would like to re-add when the power is reapplied or the hero naturally levels again. The big problem I haven't addressed at all (I wanted to work out the possibility/impossibility of the whole idea first) is that the enemy units are computer-controlled, so I would probably have to do the database thing if I really wanted them to relearn whatever abilities they had.

To be honest, I'm not totally sure of the tactical usefulness of the Leveler hero to begin with, since literally all of this hero's skills are dedicated to leveling up/down other heroes.
07-19-2011, 10:55 AM#5
Anitarf
Quote:
Originally Posted by Fledermaus
You can subtract experience, you just can't make a hero lose a level this way. Didn't read what Ani said but it's probably helpful, just wanted to add that.
I tried that too, I tried only subtracting 50 experience from my hero which wouldn't have lowered his level yet, but it didn't work.

Quote:
Well, it's at least as bad as I thought. I did figure out how exactly the experience required is calculated, but I'm not entirely sure it's worth the trouble to work all those calculations into a trigger.
You don't really have to remember that. You just decrease the hero's level by 1 in a loop, stopping once the experience is lower than the target experience. No need to actually know how much experience is required for each level.

Quote:
I actually was okay with the hero unlearning spells when they leveled back down for the "Level Up" power, since those heroes are player-controlled and I figure any player should be able to remember or easily figure out what skill they would like to re-add when the power is reapplied or the hero naturally levels again.
Sure, the hero getting his experience back at a later time is one thing. However, I was talking about a situation where the hero gets his level back immediately. Say you have a level 3 hero at 700xp and you want to decrease it by 100. With 600xp, the hero will still be at level 3, however to get there you must first reduce his level to 2, then increase his experience from 200 to 600, which levels him up again. It would seem odd for the hero to have to relearn a skill in such a situation.
Quote:
The big problem I haven't addressed at all (I wanted to work out the possibility/impossibility of the whole idea first) is that the enemy units are computer-controlled, so I would probably have to do the database thing if I really wanted them to relearn whatever abilities they had.
Well, how do the enemy heroes learn their skills to begin with? If the AI does it automatically, then it'll do it in this case as well.
07-19-2011, 01:13 PM#6
Fledermaus
I just tested AddHeroXP(someUnit, -100, false) and it worked. It even made the exp go below the required amount for level 2 (and below 0 too :o). SetHeroXP doesn't seem to be able to lower exp though.
07-19-2011, 01:37 PM#7
Anitarf
You're right, I only tested SetHeroXP. How foolish of me to expect some consistency out of Blizzard's natives.
07-19-2011, 04:11 PM#8
Bribe
Subtracting hero XP is also pretty ugly as a consequence. I've used it
before in my maps and it doesn't usually fit well.