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

[Solved] Prevent upgrade from increasing unit's current mana?

Level 2
Joined
Nov 1, 2023
Messages
8
This topic has come up once before, but got no clear answer. And on my own research, I'm finding it particularly difficult to resolve. The goal here is simple - I want a building that has an arbitrary amount of mana to be able to upgrade into one with a higher maximum mana, but without changing the actual mana it has at the time of upgrade. (Retaining the old amount is crucial to how this system's supposed to work.) However, by default, the building always leaps to the new max mana as soon as the upgrade begins.

Scouring the unit fields, I cannot find anything to control what mana it has upon upgrading, as my default value is '0', yet that's clearly not what I get upon upgrade. I cannot find any constant that changes this behavior. And for the life of me, I can't find any object exposed to the trigger system to catch what the mana value was before. Thus far, the only possible solutions I can find would be to apply a dummy ability that performs all the checks of a normal upgrade command, but replaces the building with a new one instead and sets the mana manually; or to prevent the building from upgrading without hitting maximum mana, and then resetting its mana via triggers to the previous maximum upon starting the upgrade. I can probably run either version if I have to, but both would generate an enormous headache for me and some gameplay dynamics that would make the experience of playing it moderately worse.

I apologize for bringing this up after someone else already had, especially as I doubt there will have been any radical discoveries in the past couple years. But given how significant this is to my project, I wished to make as certain as I could before committing to less desirable options. Does anyone know any way to change upgrade behavior when it comes to mana values, or any way to capture a unit or building's mana values prior to starting the upgrade?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
So how does Mana work exactly in your map? The solution could be easier if I knew what you were trying to do with it.

That aside, here's one possible solution I came up with:
  • Upg Order
    • Events
      • Unit - A unit Is issued an order with no target
    • Conditions
      • ((Triggering unit) is A structure) Equal to True
    • Actions
      • Set VariableSet CurrentMana = (Mana of (Triggering unit))
  • Begin Upg
    • Events
      • Unit - A unit Begins an upgrade
    • Conditions
      • ((Triggering unit) is A structure) Equal to True
    • Actions
      • -------- (Triggering unit) is treated as the new Unit-Type (Guard Tower) --------
      • Unit - Set Max Mana of (Triggering unit) to (Unit: (Triggering unit)'s Integer Field: Lumber Bounty Awarded - Base ('ulba'))
      • Unit - Set Unit: (Triggering unit)'s Real Field: Mana Regeneration ('umpr') to Value: 1.00
      • Unit - Set mana of (Triggering unit) to CurrentMana
  • Cancel Upg
    • Events
      • Unit - A unit Cancels an upgrade
    • Conditions
      • ((Triggering unit) is A structure) Equal to True
    • Actions
      • -------- (Triggering unit) is treated as the original Unit-Type (Scout Tower) --------
      • Unit - Set Max Mana of (Triggering unit) to (Unit: (Triggering unit)'s Integer Field: Lumber Bounty Awarded - Base ('ubba'))
      • Unit - Set Unit: (Triggering unit)'s Real Field: Mana Regeneration ('umpr') to Value: 1.00
      • Unit - Set mana of (Triggering unit) to CurrentMana
Now this is a little confusing but it seems to work.

This design takes advantage of a potentially unused field on your Buildings -> Lumber Bounty Awarded - Base.

This value is going to act like a replacement for the Maximum Mana stat for all of your buildings (that use this system). So it's a replacement for the Mana Maximum stat - which should be set to 0. However, your base Building (non-upgraded) should still use the Mana Maximum stat since that works as intended.

This allows us to set the Maximum Mana to the correct value inside of our triggers, which you can see being done in the Begin Upg and Cancel Upg triggers.

I also needed to set the Mana Regeneration to 1.00 because it breaks and resets to 0.00 upon beginning/finishing upgrading. I believe it's due to the fact that the building it's upgrading into has a Maximum Mana value of 0 which seems to enforce a "set mana regen to 0 if max mana is 0" rule.

This design also relies on an Order which is issued right before the Upgrade process starts to cache the Building's current Mana. This cached mana is needed because the Mana gets reset to 0 upon beginning the upgrade (an annoying side effect of having 0 max mana). Luckily, we can restore the mana back to what it was originally by using this variable.

Note that this part may not be MUI friendly due to the order of how things execute. It's a very good idea to make CurrentMana an Array variable and track it using something like Unit Indexing so it's linked to the Unit directly. That or use a Hashtable for the same effect.

Lastly, you may be able to modify this design to rely on the Finishes Upgrade event to get even better results.
 

Attachments

  • Upgrade Mana Fix 1.w3m
    18.4 KB · Views: 3
Last edited:
Level 2
Joined
Nov 1, 2023
Messages
8
I'm not sure how much the other details will help, but wish to explain what I can before going to sleep. To be clear, none of this is soliciting further help; I haven't been able to test your suggestions yet, so this is just an effort to clarify my thoughts for the convenience of others, should anyone be concerned.

The core concept is that I have a 'house' building. Borrowing what I saw from Heroes & Empires, I figured I would use its mana to represent the number of people living there. (Starting value and base regen rate are 0. Amenities such as trade and alcohol, represented as distinct brilliance aura-type abilities from appropriate buildings, are what allows it to "grow.") From there, upon researching some technologies, you can invest a decent chunk of wood into upgrading the buildings to larger, more impressive structures, which can then fit more people in them. The whole thing that makes this complicated is that the map would have different-looking buildings for different factions, so any work that must be unique to a given building will need to be duplicated multiple times for the different styles - hence why I hope to figure out a more unit-neutral solution.

I hadn't considered trying to cache the mana from a more general trigger for non-targeted commands - that sounds promising. (Honestly, if I can catch that mana prior to an upgrade, that's all I'll need right there - I can then just wait for whichever specific part of the upgrade resets the mana, and reset that to the original value.) Either way, I'm definitely giving that file a peek tomorrow, and running everything through a few tests to see if anything works. Fingers crossed that something does.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
I'm not sure how much the other details will help, but wish to explain what I can before going to sleep. To be clear, none of this is soliciting further help; I haven't been able to test your suggestions yet, so this is just an effort to clarify my thoughts for the convenience of others, should anyone be concerned.

The core concept is that I have a 'house' building. Borrowing what I saw from Heroes & Empires, I figured I would use its mana to represent the number of people living there. (Starting value and base regen rate are 0. Amenities such as trade and alcohol, represented as distinct brilliance aura-type abilities from appropriate buildings, are what allows it to "grow.") From there, upon researching some technologies, you can invest a decent chunk of wood into upgrading the buildings to larger, more impressive structures, which can then fit more people in them. The whole thing that makes this complicated is that the map would have different-looking buildings for different factions, so any work that must be unique to a given building will need to be duplicated multiple times for the different styles - hence why I hope to figure out a more unit-neutral solution.

I hadn't considered trying to cache the mana from a more general trigger for non-targeted commands - that sounds promising. (Honestly, if I can catch that mana prior to an upgrade, that's all I'll need right there - I can then just wait for whichever specific part of the upgrade resets the mana, and reset that to the original value.) Either way, I'm definitely giving that file a peek tomorrow, and running everything through a few tests to see if anything works. Fingers crossed that something does.
It sounds like you can use my example minus the Mana Regeneration stuff. Also, if you're fine with the current mana increasing while the building is upgrading, then you can rely on the CurrentMana variable to reset it to the proper amount upon finishing the upgrade, like you were talking about.

At least I think that should work fine, remember that there may be a frame delay between the Order being issued and the Upgrade beginning, in which case relying on a single global variable is no longer safe. But like I said before, you can fix this by storing the CurrentMana on a per unit basis.

What's nice about my design is it allows the mana regen to continue to flow naturally as the building upgrades. You'll see that the current mana no longer adjusts to compensate for a new maximum mana since I'm avoiding the whole "scale current mana based on percentage of max mana" design that is hardcoded into the game.

In other words, if the building has 5/50 mana (10%), and you begin upgrading to one that has 100 max mana, it won't jump to 10/100 (10%) as expected. Instead, it'll remain at 5/100, which sounds like the ideal situation for your map since the number of occupants (mana) probably shouldn't increase unexpectedly.
 
Last edited:
Level 2
Joined
Nov 1, 2023
Messages
8
Unfortunately, I can't find a native way to retrieve a unit's id, nor can I read the file provided. For the record, I'm working with the classic editor, so if it's for Reforged, that's likely to be the problem. That said, some preliminary testing has already solved a good bit of my troubles. I captured the mana through a command event as suggested, and then reset it upon starting an upgrade. Since I couldn't use ids, I used custom values instead. I keep a running integer for "next house id", assign it to the last house built, then increment it. Thankfully, houses are just about the only building that won't need to use that value for something else.

Unfortunately, while it works perfectly for initial upgrades, it doesn't seem to perform ideally for subsequent upgrades. (It seems to reset to somewhere beneath the last building's max or so, even if that's several mana points above where it was before.) I'm nowhere near stuck yet, though. I'll do a little more debugging to root out exactly what's going on and, if it's not a simple problem, I'll try using "point value" to store the desired max mana, then set that upon upgrade. (I do intend to give some units the pillage upgrade, so suspect the lumber stat won't be desirable. That said, I don't care about the integrity of the score screen, so point value should work just fine.)

If I end up needing further help, I'll post the relevant triggers here.
 
Level 2
Joined
Nov 1, 2023
Messages
8
Oh wow, I was dumb. The trigger had a specific unit condition left over from a previous attempt at getting this working. Removing that condition was all I needed. Now it works exactly as it's supposed to. Thanks a lot!
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
I have it working for a Scout Tower -> Guard Tower -> Cannon Tower. I image you forgot to set the fields in the Object Editor properly.

And yeah, patch 1.31 added the option to get most of the Object Editor data fields at runtime with the use of the Trigger Editor. What you're seeing with the Lumber Bounty Award - Base is one of the new functions. But like you know, you can pull this information from any data that's suitable, I chose that Lumber value because it was likely unused but Point Value would work as well.

That being said, the best method is to use a Hashtable to store endless amounts of data about your towers. It's extra work but it would most likely save you time and headaches in the future. This is extremely useful if you want to retain the "one trigger works for all" design pattern.


Here's some examples of storing Unit-Types and data associated with them into a Hashtable:

You're basically creating your own Object Editor fields but through triggers. You use the Unit-Type id, which a unique Integer that each Unit-Type in the game has, as an [Index] to different types of data. In this case you could store the Tower gold cost, lumber cost, maximum mana, etc... Anything you can think of.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Oh and I highly suggest using a Unit Indexer if you're messing around with Custom Value. It gives you infinite Custom Values per unit in the form of Variable Arrays. It also allows you to store ANY type of data, not just Integers. So you could do something like this:
  • Unit - Create 1 Scout Tower...
  • // the unit indexer intervenes here and applies a unique custom value to the scout tower //
  • Set Variable CV = (Custom value of (Last created unit))
  • Set Variable Tower_Gold_Cost[CV] = 1000
  • Set Variable Tower_Lumber_Cost[CV] = 500
  • Set Variable Tower_Attack_Range[CV] = 600.00
  • Set Variable Tower_Description[CV] = "The scout tower is pretty crappy..."
All of those variable arrays can contain data for each and every single tower. All you have to do is plug in the unit's custom value to retrieve that specific unit' data. This works because the Unit Indexer system assigns each unit a unique custom value.

But this example is a little poor, since a Unit Indexer is more useful for tracking data that changes rather than these constant values. The Hashtable method works best for constant data, such as the data in the Object Editor. Use both of them in combination to have absolute control over all of your data.
 
Last edited:
Top