1. 100% Orange Juice
  2. News

100% Orange Juice News

100% Orange Juice - Dev Play + Q&A Stream - Bounty Hunt Edition!

It's time for another dev stream + Q&A!

Join the livestream here, and ask questions, cheer for the winner or just chill!

Bounty Hunters Join the New Bounty Hunt!


The time has come! With the big Bounty Hunt game mode rework, we're also launching the first of the "Season 2" event reruns, Bounty Hunters!

[h2]Bounty Hunters[/h2]
The Bounty Hunters rerun is live until August 31! It also comes with new rewards at all milestones, for those who have previously completed the event!

Follow Ellie and Lulu's adventures as you take down the bounties in the event written by Hono and illustrated by Ogipote!

This is the 2nd and final time the event gets run normally; after rerunning them, the season 2 events will all be retired!

[h2]Bounty Hunt Rework![/h2]
The rework follows 2 beta phases and countless development hours, and brings with it a massive amount of changes! We'll only list the big ones here, please see the full patch notes on Steam forums!

[h3]Mirages![/h3]
Addressing one of the game mode's biggest pain points, the bounty locations and shops no longer use the Location Shuffle event to reset. Instead, they stay around until certain conditions are met. A new Mirage effect is always marked on a random panel. Once a location or shop is used up, a new one will instantly spawn on this panel marked with Mirage, and a new Mirage will spawn.

[h3]PvP Bounties![/h3]
A new PvP bounty system has been added, enabling an alternative fame-gathering path. This adds public PvP bounties, which can be seen on the new Bounty Board by hovering over the top edge of the screen, and private PvP bounties, which can be acquired from Homes if you hold the Assassin’s Badge (which also gives the player an extra turn of battle against other players).

[h3]Norma Board Perks![/h3]

A new Norma Board system lets you choose a permanent bonuses on achieving your Norma.
These are presented at random for the player to pick, and will not appear again once picked. These bonuses vary from stat boosts to discounts and unique abilities.

[h3]Improved Inventory![/h3]

The inventory graphics have been improved! In addition, each players' inventory can now be viewed at any time by clicking on the new icon on their character plate. Some items can now be used from this menu during your turn. This change removes the earlier Inventory button during Standby.

[h3]Two New Invaders![/h3]

Two new invaders, Lost Rogue and Dark Chocolate Mousse, have been added and can be chosen from lobby options.

Invaders now also have the ability to apply Curse to contracts, in addition to their main ability. The curse puts completing that contract on a timer before it is removed.

Each invader now drops a special inventory item with a passive effect upon defeat.

[h3]Shady Merchant![/h3]

A new traveling shopkeeper appears - the Shady Merchant runs the Black Market, hosting a plethora of powerful but expensive items; however, you may only buy one Black Market item in a game.

[h3]Several Mechanics Adjusted![/h3]
There are several other specific mechanical issues that have been addressed in various ways: Fish-a-Fish event now grants fame; Wins give stars upon landing on homes, a new catch-up mechanic has been added that gives extra contracts for lower Norma players, Bounties can be re-challenged after a defeat... the list is too long for the announcement, so please make sure to read the patch notes!

We hope you'll enjoy the new and shiny Bounty Hunt mode!

Version 3.21.2 Makes Many Small Improvements and Fixes!

Changes:
  • Updated Moss Golem in normal mode: +3/0/-3, 14 HP (down from +1 DEF). The unit card is also available in the Shop after having played 35 games.
  • Teammates can now see another player's Heart of Resistance target in co-op, and it is permanently visible while active.
  • Added unique indicators for Raging Madness and Heart of Resistance. They no longer overlap.
  • Added co-op version of Flying Castle's unit card: "Cannot counterattack when challenged." This fixes his issues especially as Avenger in co-op.
  • Edited Flying Castle and Immovable Object descriptions to be more accurate. Actual behavior hasn't changed.
  • Game now detects your Steam language for initial startup language selection. It can also be changed from the game's properties. This change only applies to first boot.
  • Added Big Poppo unit card to Binder & Shop. Card is available in the shop after unlocking Cyborg Poppo. If Cyborg Poppo is already unlocked, the unit card will be made available after finishing a game.
  • F10 key now hides the window border for people that may need it (like those under GL build that might want to place it on specific bits of the screen and/or have scarce screen space).
  • Made Mio (Festive) unit card available to players that already unlocked the character by visiting Player Info.


Fixes:
  • Fixed Sweet Indulgence's displayed cost.
  • Fixed QP (Dangerous) going over the battle stat cap.
  • (GL Beta): Fixed Arnelle Hyper's distorted visuals.
  • Fixed Hime (Moonlight)'s turn start Moon not disappearing.
  • Fixed some battle hyper animations running at double speed when there's two running at the same time.
  • Added preventive measures to not allow duplicates of dice and homemarks in selection.
  • Fixed undefined behavior when a unit is spawned into the field which could lead to a game crash.
  • Fixed misaligned player name on last played cards.
  • Various backend optimization that shouldn't affect anything that's visible to players.
  • Fixed damage result not appearing after a successful hit of Gray Whale's attack.
  • Fixed an issue that made pin preview descriptions to go out of the screen.

Let's Play Summer Games!


It's time to play summer games again!

The popular summer event is back with new rewards! Cooperate with other players to take down the dangerous Summer Beast, and unlock swimsuits, costumes and more!

Summer Beast starts with 750.000 HP, and fighting any other co-op boss will contribute to the goal at 50% of the rate. Playing 5 co-op games during the event is required to be eligible for milestone rewards.

Happy beach funsies!

504403158265497090 Points, or A Day in the Life of a Save File - Devlog

We're happy to share with you another devlog by Rapha, this time about the recently implemented big save rework, why it was necessary and what went into it! Hope you enjoy reading it.

[h2]The Perils of Binary[/h2]

In the realm of video game development, preserving a player's progress is paramount. This is where game saves come in, capturing the state of a game so it can be resumed later. However, the methods used to store these save games can significantly impact their susceptibility to corruption, be it by external or internal factors.

[h2]The problem
[/h2]
100% Orange Juice since time immemorial used binary storage, it used to be the go to for this kind of data when processing power and storage space weren't plenty available. It's more efficient to write, to read, and uses less space in disk. But this efficiency comes at a cost, it's easy to mess up. It's why we've added more and more ways the game backups your saves at various points over time, to make sure players have some backup to return to if their save with years of progress gets corrupted.

Now let's imagine a theoretical game, Poppo Saves The World! Let's imagine it as a beat-em-up, where you go around fighting enemies, one after the other, until you win and save the world. Lets supposed you have the following section of data that needs to be saved:

- Wins

- Points

- Last stage cleared

Lets supposed you have 10 victories, 393939 points and the last stage cleared as stage 7. Let's imagine you used 64 bit values for everything. So:

|Data | Explanation|

|--|--|

|0A 00 00 00 00 00 00 00 | 10 in hex padded to 64 bits|

|D3 02 06 00 00 00 00 00 | 393939 in hex padded to 64 bits |

|07 00 00 00 00 00 00 00 | 07 in hex padded to 64 bits |

In the file would be:

    0A 00 00 00 00 00 00 00 D3 02 06 00 00 00 00 00 07 00 00 00 00 00 00 00

But then you introduce abilities to the game, you decide to store it as a single byte, that will keep if you have each of the 8 abilities available unlocked, one in each bit.

|8|7|6|5|4|3|2|1|

|--|--|--|--|--|--|--|--|

|0|0|0|0|0|0|0|0|

Let's suppose your player unlocked only the first one so it's a 1, so in binary:

|8|7|6|5|4|3|2|1|

|--|--|--|--|--|--|--|--|

|0|0|0|0|0|0|0|1|

You inadvertently decided to write it between wins and points, so you would have the new binary:

|Data | Explanation|

|--|--|

|0A 00 00 00 00 00 00 00 | 10 in hex padded to 64 bits|

|01 | 01 in hex, it's a single byte |

|D3 02 06 00 00 00 00 00 | 393939 in hex padded to 64 bits |

|07 00 00 00 00 00 00 00 | 07 in hex padded to 64 bits |

In the file would be:

    0A 00 00 00 00 00 00 00 01 D3 02 06 00 00 00 00 00 07 00 00 00 00 00 00 00

And as logically implied, you would change your reading code to expect that too! But then comes the problem! Your old save doesn't agree. Let's see what your game would read from an old save.

    0A 00 00 00 00 00 00 00 D3 02 06 00 00 00 00 00 07 00 00 00 00 00 00 00

It expects 8 bytes for the Wins, so it reads 8 bytes:

    0A 00 00 00 00 00 00 00

That reads to 10! Seems ok! Up until now everything have gone correctly.

But then it tries to read the byte for abilities...

    D3

D3 is byte, your game doesn't know if it is valid or not, it's binary, it believes in the binary. Let's look at it for a bit, in binary:

|8|7|6|5|4|3|2|1|

|--|--|--|--|--|--|--|--|

|1|1|0|1|0|0|1|1|

So not only the first, but the second, fifth, seventh and eighth abilities are unlocked?!? Wow! That's a problem.

Let's continue, more 8 bytes:

    02 06 00 00 00 00 00 07

That's 504403158265497090 points... That's definitely not what was written originally. By reading that byte that wasn't there, you misaligned the whole thing, and now your player has more points than literally the universe has seconds of life. And then you continue, last 8 bytes:

    00 00 00 00 00 00 00

But that's not 8, you only got 7! If you really try to read that, you will get an unexpected behavior. What happens depends on what system, what processor and what contingencies are in place. In some systems you may read a byte from memory that has nothing to do with your save, in others you may read some leftover on the memory bus, in some you will crash... The ideal behavior would be the crashing.

But lets supposed it didn't. It loaded.

Now you have:

10 victories

5 abilities unlocked

504403158265497090 points

And never cleared a single stage

If this happens to your user, they won't understand a single bit of what's happening, will they?

[h2]The conclusion[/h2]

You must be thinking now, "Well, that's easy, just don't mess up". Yeah, but that's easier said than done, with less than a dozen of information to save, and total control over it you can't commit this mistake.

But what about having 200000 different bits of data that need to be read and written correctly, by code written over 15 years, written by different people, with different designs in mind, written by functions in different files, some keeping proper spacing between data, with spare data for future use, some not. That was our situation! Years of updates adding numerous incongruities that we didn't account for, despite fighting against it all day.

Yeah, that's a design flaw, and that's why we are fixing it, starting with this step! 100% Orange Juice is a bigger game than one might imagine, and such huge code base being kept alive by less than 10 people is nothing less than a miracle driven by passion and willpower over the years.

[h2]The solution[/h2]

We won't enter into detail, because our new save system not only is 100% reliable but has a good number of protection layers against people editing it. But firstly, if your save was changed externally, it won't load.

This is to avoid the game crashing if your storage is faulty and some bit flipped. That's why the backups are now more important than ever, if your main save corrupted, it won't load, no one will be able to restore it, its gone forever. The game won't even try to read it.

But not only that, now generally speaking, each bit of data inside the save games has a proper name to address them.

Let's bring the example from before:

  • Wins
  • Points
  • Last stage cleared


Now we build a database in memory, naming each value in a proper structure before writing it to the save. So it would be something like this:

    wins: 10, points: 393939, last_stage_cleared: 7

For reading, you simply search for the value name and loads the value attributed to it: wins → 10, points → 393939, and it goes on.

If you add a new value:

    wins: 10, abilities: 1, points: 393939, last_stage_cleared: 7

It doesn't matter, you aren't reading in sequence, you have a proper system to encode and decode the values and search them by name. If abilities doesn't exist on the save, you load the default value and go on.

This basically clears the future from unwanted data changes, but nothing in life is a perfect solution. We still need to load the old save, and if that's corrupted, the new one will be too, as the old save system trusted above everything else what was written, in the exact order it was.

The game also may after some update write something wrong, that's a bug, it can happen, it doesn't mean the save is corrupted stricto sensu, but in lato sensu the data was handled wrongly, so that's still a bug, that's still a thing that needs to be reported.

So if after the save conversion on the last big update, you got more dice than the universe has seconds of life, the best we can suggest is contacting us! We will do the best in our power to fix your old corrupted save. But be aware there may be some times that it's impossible (mainly if you didn't play for the last 7~10 years, the amount of uncounted problems can be beyond any repair), but even in this horrific situation, talk with us, say what you hold dear about your old save, and we might be able to find a path that will make you happy.