Shop Price by Variable

● ARCHIVED · READ-ONLY
Started by Jonruy 9 posts View original ↗
  1. I'm working on a game where the player interacts with multiple different factions, and those factions approval of the player is measured by different variables. I want to use those variables to affect the prices of the items they sell. Using Archeia's handy-dandy Script Call Collection I was able to assemble this:

    goods = [[0,11,1,20*(1-$game_variables[1]/40)], [0,14,1,20*(1-$game_variables[1]/40)], [0,44,1,10*(1-$game_variables[1]/40)], [0,48,1,10*(1-$game_variables[1]/40)]]SceneManager.call(Scene_Shop)SceneManager.scene.prepare(goods, true)I chose that formula because it would result in a 25% fluctuation in price when the approval rating maxes out at +10 or -10. It all works out in theory, but when I actually run this the prices never change, even after leaving and reentering the map. Can anyone tell me why that is?
  2. What's in $game_variables[1]?

    Are the prices you see in the shop exactly the same as what you set in the database?

    Do you have any other scripts that affect shop processing?

    Without knowing any of the answers, here's what I THINK is probably happening:

    $game_variables[1] is less than 40.

    $game_variables[1]/40 results in 0 (because the result will be an integer so any fractional portion will be truncated)

    1 - 0 is 1

    20 * 1 is 20

    10 * 1 is 10

    Your items are set up to have 20 and 10 in the database, and that's what's showing on the shop screen.

    Try this instead:

    Code:
    goods = [[0,11,1,(20*(1-$game_variables[1]/40.0)).to_i],         [0,14,1,(20*(1-$game_variables[1]/40.0)).to_i],         [0,44,1,(10*(1-$game_variables[1]/40.0)).to_i],         [0,48,1,(10*(1-$game_variables[1]/40.0)).to_i]]SceneManager.call(Scene_Shop)SceneManager.scene.prepare(goods, true)
  3. You're right, $game_variables[1] is an integer with a value from -10 to +10, and there are no other scripts affecting how shops function. I know that the goods variable is at least being picked up properly, because those items have a default cost of 0 in the database.

    Your solution was spot on! It looks like the program was calculating $game_variables[1] as an integer when I was intending for it to be calculated as a decimal (a hazard of not enforcing data types), and kept being rounded to 0. It seems a little odd to me how the 40 needs a decimal but the other numbers don't. I fiddled around with it, and concluded that a more intuitive solution would be to use a script to modify the game variables using a decimal value. Using .to_i is still the key, but I don't have to figure out what numbers need or don't need decimals.

    Also, fun fact: Shops are perfectly capable of functioning with items whose costs include decimals.
  4. not exactly - the program considers all values to be integers by default, until it encounters the first non-integer value. After encountering a non-integer (in this case 40.0) it will calculate with float until either told otherwise (.to_i, which is neccessary for later calculations in the shop area) or until a new formula is started.


    you probably could have used (1.0-$game_variables[1]/40) as well - important is that the eval is forced to switch to float before the division result is stored.
  5. Jonruy said:
    It looks like the program was calculating $game_variables[1] as an integer when I was intending for it to be calculated as a decimal (a hazard of not enforcing data types), and kept being rounded to 0.
    a / b will return an integer if both a and b are integers.


    40 / 3 will return 13.


    2 / 3 will return 0.
  6. Andar said:
    not exactly - the program considers all values to be integers by default, until it encounters the first non-integer value. After encountering a non-integer (in this case 40.0) it will calculate with float until either told otherwise (.to_i, which is neccessary for later calculations in the shop area) or until a new formula is started.

    you probably could have used (1.0-$game_variables[1]/40) as well - important is that the eval is forced to switch to float before the division result is stored.

    Tsukihime said:
    a / b will return an integer if both a and b are integers.

    40 / 3 will return 13.

    2 / 3 will return 0.
    Again, these concept all require me to stop and analyze the equation - what's being calculated where and when and which values are integers and which ones are floats. That's precious seconds that could be spent staring at the screen, attempting to debug some other convoluted script I cobbled together. While good to know, I think that just using a script to set a variable to a float beforehand will be a good rule of thumb.
  7. Jonruy said:
    Again, these concept all require me to stop and analyze the equation - what's being calculated where and when and which values are integers and which ones are floats.
    While this is true, there is a good reason why this approach was choosen.
    In most RPGs (especially JRPGs) the player handles only integers, and integers are faster to calculate than floats.


    By assuming that everything is integer (instead of the "only" 99%), the game engine can speed up it's processing - and speed was the big problem with the engine for a long time, because basically it uses a doublestage Ruby interpreter, and all interpreters are slow.


    On current machines, that's not as bad than on older machines - but even now, a poorly written parallel process can lag even the most powerfull PC. It just doesn't happen as often as a with the computers a few years back.


    Defaulting to integer calculations helps a lot here, especially as most calculations don't require floats - and even the cases where it needs floats, a few very simple formula changes are all that is needed to get the correct solution.
  8. Unfortunately, if you start doing floating-point arithmetics with your parameters and other values like gold, you're going to end up with decimals in your window rather than nice, rounded integers.
  9. Jonruy said:
    While good to know, I think that just using a script to set a variable to a float beforehand will be a good rule of thumb.
    Well, yes. It doesn't matter whether you convert the variable to a float or the 40 to a float - either way you're telling the engine you want the RESULT to be a float. Then you need to convert it back to an integer so it displays correctly and deducts gold correctly - otherwise you're looking at more script changes to stop it displaying something like 15.73948273 Gold.


    I'm not sure if Andar's suggestion of 1.0 would work - order of operations would do the division first and then the subtraction, so maybe putting 1.0 might NOT make it detect the conversion first. I would have to do a test to see the results, and I don't have Ace with me right now.


    If you want to convert the variable to a float instead of putting 40.0, you just do $game_variables[1].to_f/40 - it's probably more efficient to do 40.0 because .to_f would be calling a method which would waste precious milliseconds while 40.0 would not. But really I don't think there's any need to be concerned about the time necessary for such a conversion when you're only talking about half a dozen items.