Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines
(4 edits)

On version 0.2.1, there is an unintuitive and rather unexpected behavior on all the skills that take some inflation from one bodypart and then transfers it to other bodyparts or transforms it into other things. These skills that deflates from a part, and then inflates to another part or convert it into other things, doesnt take into account how much change is actually applied after clamping (mainly due to Rank base minimum, spirit-induced minimum or "Lactation Lock" status).

For example, the "Redirect Presure" Skill says that it "Takes half of the most inflated part and redirects it to the least inflated part".

  • Expected behavior 1: takes half of the current inflation level from the most inflated part, from the minimum level to the current level, and redirects it to the least inflated part.
  • Expected behavior 2: takes half of the current inflation level from the most inflated part, from 0 to the current level, takes that amount from the inflation level between minimum level and current level, and redirects it to the least inflated part.
  • Actual behavior: tries to take half of the current inflation level from the most inflated part, from 0 to the current level, clamps the most inflated part to the minimum level, and adds the mistaken amount to the least inflated part, creating more unbalanced inflation than before.

This makes the skill unviable at any other Rank than "B Rank", while inhabited by Helium Spirits or under the "Lactation Lock" status (that is, with all minimums at 0 and no deflation-locking status). Other skills that deflate and inflate specific amounts of inflation also could lead to creating more inflation than before.

 

The Solution I came out with was to add a returning feature to the modify_inflation funtion, to make it return the total effective amount of inflation/deflation dealt (absolute value). And then, update the code in all these inflation-transfer/transform skills to take into account the effective inflated/deflated amount.

The following list show all the places affected by the minor bug, and the quick fixes I applied (all code line numbers based on original v0.2.1 unaltered files):

 

1.1) Take into account the modified amount in the "Air Control" Skill.

# 5 inflation from most-part to least-part.

[code]

  File "game/init.rpy", lines 3537-3551, inside skill_use_air_control:

    def skill_use_air_control():

        amount_to_shift = 5

        part_from = get_most_likely_to_pop_part()

        if not part_from:

            notify("Air Control: No parts have inflation to shift from.")

            return False # <--

        part_to = get_least_likely_to_pop_part(exclude_part=part_from)  # <-- Get the part to inflate excluding the part to deflate.

        if not part_to:

            notify("Air Control: No parts have room to shift inflation to.")

            return False # <--

        initial_context = renpy.game.context().current

        modified_amount = modify_inflation(part_from, -amount_to_shift) # <-- Get the effectively deflated amount.

        if modified_amount == 0: # <-- When the most likely to pop cannot be deflated.

            notify("Air Control: Cannot deflate part to shift from.") # <--

            return False # <-- 

        if renpy.game.context().current is initial_context:

            modify_inflation(part_to, modified_amount) # <-- Inflates the effectively deflated amount.

            notify(f"Air Control: Shifted {modified_amount} inflation from {part_from} to {part_to}.")# <--

        return True # <--

[/code]

 

1.2) Take into account the modified amount in the "Pressure Shift" Skill.

 # 10 inflation from most-part to least-part.

[code]

  File "game/init.rpy", lines 3602-279, inside skill_use_pressure_shift:

    def skill_use_pressure_shift():

        amount_to_shift = 10 

        part_from = get_most_likely_to_pop_part()

        part_to = get_least_likely_to_pop_part(exclude_part=part_from)  # <-- Get the part to inflate excluding the part to deflate.

        if not part_from or not part_to: # <--

            notify("Cannot effectively shift pressure.")

            return False # <--

        initial_context = renpy.game.context().current

        modified_amount = modify_inflation(part_from, -amount_to_shift) # <-- Get the effectively deflated amount.

        if modified_amount == 0: # <-- When the most likely to pop cannot be deflated.

            notify("Cannot effectively shift pressure.") # <--

            return False # <-- 

        if renpy.game.context().current is initial_context:

            modify_inflation(part_to, modified_amount) # <-- Inflates the effectively deflated amount.

            notify(f"Shifted {modified_amount} inflation from {part_from} to {part_to}.")# <--

        return True # <--

[/code]

 

1.3) Update legacy code for most/least parts and take into account the modified amount in the "Redirect Pressure" Skill.

# halft inflation from most-part to least-part.

#For the Expected behavior 1, use "net_level" to calc the dynamic half (minimum to current level).

#For the Expected behavior 2, use "gross_level" to calc the total half (zero to current level).

[code]

  File "game/init.rpy", lines 3511-3535, inside skill_use_redirect_pressure:

    def skill_use_redirect_pressure():

        part_from = get_most_likely_to_pop_part() # <--

        if not part_from: # <--

            notify("Cannot redirect pressure: No valid parts to shift from.") # <--

            return False # <--

        part_to = get_least_likely_to_pop_part(exclude_part=part_from)  # <-- Get the part to inflate excluding the part to deflate.

        if not part_to: # <--

            no_part_to_message = "Cannot redirect pressure effectively: Target and source are the same." if get_least_likely_to_pop_part() is not None else "Cannot redirect pressure: No valid parts to shift to." # <-- If there is a part_to target when not using exclusion, then it is the excluded one

            notify(no_part_to_message) # <--

            return False # <--

        gross_level = getattr(store, f"yuki_{part_from}_level") # <-- Total current level (including the Rank base minimum and/or the spirit-induced minimum)

        net_level = gross_level - _clamp_level_minimum(0, part_from) # <-- Dynamic current level (excluding the Rank base minimum and/or the spirit-induced minimum)

        amount_to_redirect = int(round(net_level / 2.0)) # <-- Choose espected behavior (total level or dynamic level)

        if amount_to_redirect <= 0:

            notify("Not enough inflation in the largest part to redirect.")

            return False

        initial_context = renpy.game.context().current

        modified_amount = modify_inflation(part_from, -amount_to_redirect) # <-- Get the effectively deflated amount.

        if modified_amount == 0: # <-- When the most likely to pop cannot be deflated.

            notify("Cannot deflate the largest part to redirect.") # <--

            return False # <-- 

        if renpy.game.context().current is initial_context:

            modify_inflation(part_to, modified_amount) # <-- Inflates the effectively deflated amount.

            notify(f"Shifted {modified_amount} inflation from {part_from} to {part_to}.")# <--

        return True

[/code]

 

1.4) Take into account the modified amount in the "Udderly Balanced" Skill.

# 15 deflation from chest, 7 inflation to belly and 8 inflation to butt.

[code]

  File "game/init.rpy", lines 3472-3478, inside skill_use_udderly_balanced:

    def skill_use_udderly_balanced():

        initial_context = renpy.game.context().current

        modified_amount = modify_inflation("chest", -15) # <-- Effective amount deflated from "chest"

        if modified_amount == 0: return False # <-- Cannot deflate chest (maybe lactation lock is active)

        if renpy.game.context().current is initial_context: # Check if pop occurred

            modify_inflation("belly", (modified_amount // 2)) # <-- The floor half

            if renpy.game.context().current is initial_context: # Check if pop occurred again

                modify_inflation("butt", (modified_amount // 2) + (modified_amount % 2)) # <-- The tie breaking half (odd case)

        return True # <--

[/code]

 

1.5) Take into account the modified amount in "Milk Conversion" Skill.

# 10 deflation from chest and +2 lactation stacks.

[code]

  File "game/init.rpy", lines 3499-3509, inside skill_use_milk_conversion:

    def skill_use_milk_conversion():

        if store.yuki_chest_level >= 10:

            initial_context = renpy.game.context().current

            modified_amount = modify_inflation("chest", -10) # <-- Effective amount deflated from "chest"

            if modified_amount != 10: # <-- Cannot deflate enough of chest

                notify("Cannot convert 10 chest inflation to milk!") # <-- (maybe lactation lock is active)

                return False # <--

            if renpy.game.context().current is initial_context:

                store.lactation_stacks += 2

                notify(f"Converted 10 chest inflation into 2 Lactation Stacks! (Total: {store.lactation_stacks})")

                return True

        else:

            notify("Not enough chest inflation to convert to milk!")

        return False

[/code]

 

2) Refactor the return behavior of the modify_inflation Funtion, to return the absolute value of the total inflation levels modified.

[code]

  File "game/init.rpy", lines 306-380, inside modify_inflation:

    def modify_inflation(part, amount, _is_recursive_call=False):

        if part not in ["chest", "belly", "butt"]:

            renpy.log(f"Error: Invalid part '{part}' passed to modify_inflation.")

            return 0 # <-- No inflation level was modified.

        ...

        current_level = getattr(store, current_level_attr, 0)

        new_level_unclamped = current_level + amount

        

        current_total_modified_amount = 0 # <-- Modified amount on this call.

        ...

        if part == "belly" and amount > 0 and yuki_has_item("equip_tight_rubber_belt"):

            ...

            if new_level_unclamped > effective_belly_cap_with_belt:

                excess_belly_inflation_to_redirect = new_level_unclamped - effective_belly_cap_with_belt

                new_level_unclamped = effective_belly_cap_with_belt

                current_total_modified_amount += abs(effective_belly_cap_with_belt - current_level) # <-- Modified on belly from current_level to effective_belly_cap_with_belt (clamped).

                ...

        if amount > 0: # Inflation

            shake_duration_scale = max(min_shake_scale, min(float(abs(amount)) / base_inflation_for_shake, max_shake_scale))

            actual_change_this_part = new_level_unclamped - current_level

            current_total_modified_amount += abs(actual_change_this_part) # <-- Modified on part from current_level to new_level_unclamped (unclamped).

            ...

        elif amount < 0: # Deflation

            if part == "chest" and has_status_effect("status_lactation_lock"):

                if store.in_dungeon: notify("Lactation Lock prevents chest deflation!")

            else:

                new_level_clamped_deflate = _clamp_level_minimum(new_level_unclamped, part)

                actual_decrease_this_part = current_level - new_level_clamped_deflate

                current_total_modified_amount += abs(actual_decrease_this_part) # <-- Modified on part from current_level to new_level_clamped_deflate (clamped)

                ...

        if excess_belly_inflation_to_redirect > 0 and redirection_target_part:

            current_total_modified_amount += modify_inflation(redirection_target_part, excess_belly_inflation_to_redirect, _is_recursive_call=True) # <-- Modified on redirection_target_part recursively.

    

        if not _is_recursive_call:

            check_game_state_after_inflation()

        return current_total_modified_amount # <-- Total absolute-value modified amount (including recursion)

[/code]

;)