Shop Price by Variable

Jonruy

Villager
Member
Joined
Sep 16, 2013
Messages
16
Reaction score
0
First Language
English
Primarily Uses
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?
 

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,098
Reaction score
13,704
First Language
English
Primarily Uses
RMMV
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)
 

Jonruy

Villager
Member
Joined
Sep 16, 2013
Messages
16
Reaction score
0
First Language
English
Primarily Uses
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.
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
31,365
Reaction score
7,674
First Language
German
Primarily Uses
RMMV
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

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
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.
 
Last edited by a moderator:

Jonruy

Villager
Member
Joined
Sep 16, 2013
Messages
16
Reaction score
0
First Language
English
Primarily Uses
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.
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.
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
31,365
Reaction score
7,674
First Language
German
Primarily Uses
RMMV
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.
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
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.
 

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,098
Reaction score
13,704
First Language
English
Primarily Uses
RMMV
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.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.
Do you Find Tilesetting or Looking for Tilesets/Plugins more fun? Personally I like making my tileset for my Game (Cretaceous Park TM) xD
How many parameters is 'too many'??

Forum statistics

Threads
105,860
Messages
1,017,040
Members
137,569
Latest member
Shtelsky
Top