Item scaling system/Setting a variable to some function

Level 11
Joined
Mar 21, 2008
Messages
354
Some information about my map:
1. Items have levels
2. The attributes of the item, such as damage, scale with its level
3. All items have unique scaling formulae

Since items scale uniquely, I want to be able to set some variable equal to an item's scaling formula for later use. As an example, say an item's damage increased by 3^x, x being its level - wat do

The reason I want to do this is because when you upgrade an item, a prompt shows up which shows the stats that are being changed. This requires use of the item's scaling formula, though. Example:

Shitty upgrade window
3 dmg => 9 dmg

Confirm upgrade:
- Yes
- No
 
Level 15
Joined
Aug 7, 2013
Messages
1,338
Well first of all there isn't a really a question being asked.

If you are asking "how" to implement an item system with levels for each item, then I think there's an easy solution.

Detect when you want to level up the item, then replace it with the the item that is the next level (for each item's level you have to make one for it).

Sorry if this is too brief...
 
Level 11
Joined
Mar 21, 2008
Messages
354
Well first of all there isn't a really a question being asked.

If you are asking "how" to implement an item system with levels for each item, then I think there's an easy solution.

Detect when you want to level up the item, then replace it with the the item that is the next level (for each item's level you have to make one for it).

Sorry if this is too brief...

I'm probably just shit at explaining this clearly

The game uses the item's charges as its level. I am asking where and how I can store a specific item's scaling formula so that I can plug values into it later or something

There's a sword in the game whose damage is determined like this:
  • Set attrbWpnPwr[A] = (7 + (3 x (Charges remaining in (Item being manipulated))))
I need to store this "7 + 3x" somewhere, but iunno how
 
Level 15
Joined
Aug 7, 2013
Messages
1,338
Alright let's get a little low level first.

Give an example of an item you want to scale/level up?

e.g.

Ranged Boots lvl 1 - gives +1 AGI
Ranger boots lvl 2 - give +3 AGI
Ranger boots lvl 3 - gives +5 agi

You would need to make separate item objects for each one. So if an item has 3 levels, you need 3 versions of it.

You then detect when you want to level up the item.

Do they buy the upgrade or does the item level up over time (the more you use it the better it gets?).

Edit: IF you're going to trigger the item bonuses, then that's all you need to do.

Event - Player has item equal to Sword

Actions - Get Charges of Sword
Add (5 x Charges of Sword) damage to player's unit
 
Level 11
Joined
Mar 21, 2008
Messages
354
Edit: IF you're going to trigger the item bonuses, then that's all you need to do.

Event - Player has item equal to Sword

Actions - Get Charges of Sword
Add (5 x Charges of Sword) damage to player's unit

Err, yeah, this is EXACTLY what I did. I already have the whole item level system in place, and I've more or less stated my problem in my previous posts.

I am asking where and how I can store a specific item's scaling formula so that I can plug values into it later

The reason I want to do this is because when you upgrade an item, a prompt shows up which shows the stats that are being changed. This requires use of the item's scaling formula, though.

Going into a bit more detail, let's say a weapon's damage formula is "7x+3"

Upon being upgraded, the prompt shows a comparison between the old damage and the new damage:

7(itemlevel)+3 => 7(itemlevel+1)+3

My problem lies in WHICH formula to use, since all weapons progress differently. And I don't want to do it in an extremely manual, long-winded way either. wut do
 

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,086
JASS does not support function pointers directly. There are a number of work around approaches which give you very similar results to function pointers however.

It is important to note that none of these methods allows you to actually pass arguments to the function. Seeing how WC3 trigger system only ever has 1 active thread this is not really a problem as you can simply use global variables as temporary storage locations for the function arguments. If you do not like writing functions with global arguments or those functions are unsafe with global arguments then you can either copy the globals to locals or use an adapter function which calls your function normally passing it all the global arguments.

Some of these methods may alter local state or start new threads.

1. Triggers. This is the GUI friendly way to do dynamic code. You can use trigger variables to represent pointers to the code the trigger will run. After setting up your global arguments you can run the trigger represented by a trigger variable and it will be equivalent to calling a function from a pointer. This does have the overhead of a trigger and condition or action object but is probably one of the fastest ways to do function pointers (I think this is how vJASS does them).
2. Function Evaluation. There is a native which is passed a string representing a function name and then proceeds to run that function. As such a function pointer becomes as simple as a string variable. All you do is set up the global arguments and then run the function represented by the string variable. What is good about this method is that it has considerably less object overhead than the trigger approach (only a constant String). However I do recall benchmarks saying it is considerably slower than the trigger approach but the main reason people advise against it was due to a bug in older version of WC3 where passing an invalid function name would cause a fatal error (this was fixed ages ago).

Either method works. For GUI I advise using 1 since that can be done without any JASS. For JASS I advise 2 since it avoids the unreadable headache of vJASS and is easier to manage.
 
Level 11
Joined
Mar 21, 2008
Messages
354
JASS does not support function pointers directly. There are a number of work around approaches which give you very similar results to function pointers however.

It is important to note that none of these methods allows you to actually pass arguments to the function. Seeing how WC3 trigger system only ever has 1 active thread this is not really a problem as you can simply use global variables as temporary storage locations for the function arguments. If you do not like writing functions with global arguments or those functions are unsafe with global arguments then you can either copy the globals to locals or use an adapter function which calls your function normally passing it all the global arguments.

Some of these methods may alter local state or start new threads.

1. Triggers. This is the GUI friendly way to do dynamic code. You can use trigger variables to represent pointers to the code the trigger will run. After setting up your global arguments you can run the trigger represented by a trigger variable and it will be equivalent to calling a function from a pointer. This does have the overhead of a trigger and condition or action object but is probably one of the fastest ways to do function pointers (I think this is how vJASS does them).
2. Function Evaluation. There is a native which is passed a string representing a function name and then proceeds to run that function. As such a function pointer becomes as simple as a string variable. All you do is set up the global arguments and then run the function represented by the string variable. What is good about this method is that it has considerably less object overhead than the trigger approach (only a constant String). However I do recall benchmarks saying it is considerably slower than the trigger approach but the main reason people advise against it was due to a bug in older version of WC3 where passing an invalid function name would cause a fatal error (this was fixed ages ago).

Either method works. For GUI I advise using 1 since that can be done without any JASS. For JASS I advise 2 since it avoids the unreadable headache of vJASS and is easier to manage.

uhh o god

I think I understand what you're saying

so for the first method you mentioned, I can do something like this:

  • blah
    • Events
      • Player - Player 1 (Red) types a chat message containing hi as An exact match
    • Conditions
    • Actions
      • Set angle = 0.00
      • Set player_number = (Player number of (Triggering player))
      • Set unit_type = Footman
      • Set loc[0] = (Random point in (Playable map area))
      • Trigger - Run blah2 <gen> (checking conditions)
  • blah2
    • Events
    • Conditions
    • Actions
      • Unit - Create 1 unit_type for (Player(player_number)) at loc[0] facing angle degrees
      • Custom script: call RemoveLocation(udg_loc[0])
if that's what you mean, then in the context of my problem, would I do something like this? I just want to know if I'm doing this the "best way," but this already seems to be working pretty gud

  • promotion stone
    • Events
      • Unit - A unit Uses an item
    • Conditions
      • (Item-type of (Item being manipulated)) Equal to |cffFFD800Promotion Stone|r
    • Actions
      • Set tempUnit[0] = (Triggering unit)
      • Trigger - Run item scaling <gen> (checking conditions)
      • Dialog - Show dialog[1] for (Owner of tempUnit[0])
      • Dialog - Change the title of dialog[1] to ((String(tempInt[0])) + ( => + (String(tempInt[1]))))
  • item scaling
    • Events
    • Conditions
    • Actions
      • Set A = (Charges remaining in equipItemWeapon[(Player number of (Owner of tempUnit[0]))])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Item-type of equipItemWeapon[(Player number of (Owner of tempUnit[0]))]) Equal to |cffFFD800Sword|r
        • Then - Actions
          • -------- old dmg & new dmg --------
          • Set tempInt[0] = ((3 x A) + 7)
          • Set tempInt[1] = ((3 x (A + 1)) + 7)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Item-type of equipItemWeapon[(Player number of (Owner of tempUnit[0]))]) Equal to |cffFFD800Mace|r
        • Then - Actions
          • Set tempInt[0] = ((3 x A) + 17)
          • Set tempInt[1] = ((3 x (A + 1)) + 17)
        • Else - Actions
  • promotion stone confirm
    • Events
      • Dialog - A dialog button is clicked for dialog[1]
    • Conditions
    • Actions
      • Dialog - Hide dialog[1] for (Triggering player)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Clicked dialog button) Equal to dialogbutton[21]
        • Then - Actions
          • -------- this is the "yes" button, saying "no" obviously has no effect --------
          • Item - Set charges remaining in equipItemWeapon[(Player number of (Triggering player))] to ((Charges remaining in equipItemWeapon[(Player number of (Triggering player))]) + 1)
          • Set tempUnit[0] = mainUnit[(Player number of (Triggering player))]
          • Trigger - Run item scaling <gen> (checking conditions)
          • Set attrbWpnPwr[(Custom value of mainUnit[(Player number of (Triggering player))])] = tempInt[0]
        • Else - Actions
of course i'd need to include all weapons in the second trigger but yeah
 

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,086
if that's what you mean, then in the context of my problem, would I do something like this? I just want to know if I'm doing this the "best way," but this already seems to be working pretty gud
No you would have separate item scaling triggers and you would vary the trigger the variables point to based on what items the player owns.
 
Level 25
Joined
Aug 18, 2009
Messages
4,087
You should not directly pass the formula and have your prompt scope parse/evaluate it. Better attach the specific functions containing the formula to the item, invoke them as Dr Super Good described and have those functions return the resulting number/string to your prompt.
 
Top