I present to you: The instant resource counter!
Woo! So what is it? Basically, it sets your resources to an absurd amount by using the formula that the game uses for the resource tally animation, and then changes it back to the expected amount on the next trigger cycle, when the resource view is approximately the same number that you want to set it to.
i.e. You set the minerals from 0 to 9000 with a trigger. The system detects the change, and saves the amount you set it to. It then sets your minerals to 51113. The tally counter then tries to match this value by animating your minerals up. When the next trigger cycle happens, the animated counter is at about 9000, and triggers restore the correct mineral amount (9000). Now there is little difference between the animated value and actual value, and thus no animation needs to take place.
Application Overview
Let N be the powers of 2 you're willing to support. Note: Do not use "subtract". The equations are expected to go negative, i.e. use "add -1".
We then have:
BEFORE all triggers
- N triggers to restore saved resource from previous trigger cycle [if dc2 != 0 then ore = dc3]
- N triggers for storing the old value [dc1 = ore]
DURING your triggers
No special changes needed!
AFTER all triggers
- N triggers for storing new value (dc2, dc3 = ore)
- N triggers for subtract (dc2 -= dc1) (Note the result can be negative)
- 1 trigger for correction (if -4 <= dc2 <= 4 then dc2 = 0)
- N*2 triggers for multiply (if dc2 != 0 then ore += dc2*3375/721) (Note x2 for negative values)
- 2 triggers for add/sub conditional (if dc2 < 0 then ore += 16; if dc2 > 0 then ore -= 16)
Multiplication Table
This is for calculating 3375/721 for each power of 2, rounded to the nearest whole number.
Code
29: 268435456-> X 1256545997
28: 134217728-> 628272999
27: 67108864 -> 314136499
26: 33554432 -> 157068250
25: 16777216 -> 78534125
24: 8388608 -> 39267062
23: 4194304 -> 19633531
22: 2097152 -> 9816766
21: 1048576 -> 4908383
20: 524288 -> 2454191
19: 262144 -> 1227096
18: 131072 -> 613548
17: 65536 -> 306774
16: 32768 -> 153387
15: 16384 -> 76693
14: 8192 -> 38347
13: 4096 -> 19173
12: 2048 -> 9587
11: 1024 -> 4793
10: 512 -> 2397
9: 256 -> 1198
8: 128 -> 599
7: 64 -> 300
6: 32 -> 150
5: 16 -> 75
4: 8 -> 37
3: 4 -> 19
2: 2 -> 9
1: 1 -> 5
28: 134217728-> 628272999
27: 67108864 -> 314136499
26: 33554432 -> 157068250
25: 16777216 -> 78534125
24: 8388608 -> 39267062
23: 4194304 -> 19633531
22: 2097152 -> 9816766
21: 1048576 -> 4908383
20: 524288 -> 2454191
19: 262144 -> 1227096
18: 131072 -> 613548
17: 65536 -> 306774
16: 32768 -> 153387
15: 16384 -> 76693
14: 8192 -> 38347
13: 4096 -> 19173
12: 2048 -> 9587
11: 1024 -> 4793
10: 512 -> 2397
9: 256 -> 1198
8: 128 -> 599
7: 64 -> 300
6: 32 -> 150
5: 16 -> 75
4: 8 -> 37
3: 4 -> 19
2: 2 -> 9
1: 1 -> 5
Sample Map
TODO
Notes
- If you want to support negative resource values, you will need to (almost) double the triggers.
- If you want to support both ore AND gas, you will need to double the triggers.
- You can make it explicit instead of automatic by introducing another death count.
Limitations
- Lag can mess it up.
- Non-Fastest speed will mess it up.
- You can only support values up to about 200-300 million or so.
- Players may not have enough resources if they built something during these frames. In this case you could activate it only when the diff is above some threshold for which they can't possibly get an error.
- Players can actually use the resources during the 2 frames that it is activated, and it won't be counted against them.
- Players gathering resources or cancelling units/structures will lose them within the 2 frames this is active.
TODO: It's possible to fix the triggers so that it accounts for resource changes within the 2 frames that it's been activated (mitigating 2 of the major limitations).
Maths
The animation function's next resource value is defined as:
Code
f(n+1) = f(n) + 1 + floor((target - f(n))/16) { if f(n) < target
f(n+1) = f(n) + 1 + floor((target - f(n))/16) { if f(n) > target
Where f(1) = current minerals
target = target minerals
f(n+1) = f(n) + 1 + floor((target - f(n))/16) { if f(n) > target
Where f(1) = current minerals
target = target minerals
We will focus on f(n) < target for now, but it's essentially the same process for the other one.
We know that:
- This update is run approximately every 20ms real time. (take my word for it)
- The game runs at 42ms/frame on fastest.
- Triggers execute on every other frame.
Hence we should calculate f(4), since 20ms*4 = 80 is roughly equal to one trigger cycle (84).
Since we can use an approximation instead of the real formula, we can eliminate the floor from the equation. It follows that:
Code
f(n+1) = f(n) + 1 + (target - f(n))/16
Let a = old mineral amount
Let b = new/target mineral amount
f(1) = a
f(2) = a + 1 + (b - a)/16
f(3) = a + 1 + (b - a)/16 + 1 + (b - (a + 1 + (b - a)/16))/16
f(4) = a + 1 + (b - a)/16 + 1 + (b - (a + 1 + (b - a)/16))/16 + 1 + (b - (a + 1 + (b - a)/16 + 1 + (b - (a + 1 + (b - a)/16))/16))/16
Let a = old mineral amount
Let b = new/target mineral amount
f(1) = a
f(2) = a + 1 + (b - a)/16
f(3) = a + 1 + (b - a)/16 + 1 + (b - (a + 1 + (b - a)/16))/16
f(4) = a + 1 + (b - a)/16 + 1 + (b - (a + 1 + (b - a)/16))/16 + 1 + (b - (a + 1 + (b - a)/16 + 1 + (b - (a + 1 + (b - a)/16))/16))/16
Since we want our next resource value to be our mineral target amount, we set
Code
f(4) = new mineral amount
a = old mineral amount
solve for b
a = old mineral amount
solve for b
We can plug it into WolframAlpha, and get the equation:
Code
b = -(3375 a)/721 + (4096 z)/721 - 16
Where z = f(4).
Where z = f(4).
Note that values in which the difference is at most 4 will be incorrect (and it will iterate all 4 over the 4 view updates anyway). Rearranging the equation, and considering special conditions, we get
Code
Let b = amount to set.
Let t = target amount
Let a = old amount.
b = t + (t - a)*3375/721 - 16 { if a + 4 < t
b = t + (t - a)*3375/721 + 16 { if a - 4 > t
b = t { if abs(t-a) <= 4
Let t = target amount
Let a = old amount.
b = t + (t - a)*3375/721 - 16 { if a + 4 < t
b = t + (t - a)*3375/721 + 16 { if a - 4 > t
b = t { if abs(t-a) <= 4
Post has been edited 1 time(s), last time on Oct 2 2017, 9:10 am by Heinermann.