yairm210/Unciv

"Hidden from users" not hiding triggerable effect on event notification

SpacedOutChicken opened this issue · 4 comments

Is there an existing issue for this?

  • I have searched the existing issues

Game Version

4.11.4

Describe the bug

When creating an event, if you specify one triggered outcome to be hidden from users, it doesn't actually get hidden. It shows up anyway, with the "hidden from users" text clearly visible.

Steps to Reproduce

In the mod I've attached, a certain event happens every 20 turns with 90% chance. Whenever it happens, one of the options always displays the effect that should be hidden.

Screenshots

Screenshot (194)

Link to save file

RiversOfLava.zip
Here is the mod with the event in question. The event trigger is given in the Global Uniques JSON.

Operating System

Windows

Additional Information

I also noticed that it's possible to save-scum in order to avoid this event, since the event is randomized. If not for that, I would have included a saved game just before the event occurring, but the randomized nature of the event means that it won't necessarily happen, making it possible to restart the turn in order to potentially avoid the undesirable event.

I just discovered "events" yesterday... Of course it has a new renderer and of course that needs to respect hidden flags separately...

But - still pondering. I had started planning to migrate Tutorials - all three or four kinds - to full ruleset objects, having a "automatically render as floating text" or "automatically pop up as tutorial" unique with conditionals controlling when to show and how - and when to hide the floating ones. Events might have been just an extension...

it's possible to save-scum

Yes... val stateBasedRandom by lazy { Random(state.hashCode()) } is meant to treat that, but - doesn't (puzzle for y'all - why)...

Spoilers


Any.hashCode() is more or less Java-internal and can be assumed to be something like a memory address - differs each process launch. YourClass.hashCode() is only deterministic if YourClass properly implements the equality contract. StateForConditionals tries to - data class does it for you - but fails as one ore more (most actually) of its component field classes don't. Civilization - nope - could use civName instead. City - nope, could use id instead. Tile - nope, could use position instead, Vector2 does. And so on...

    override fun hashCode(): Int {
        fun Civilization?.hash() = this?.civName?.hashCode() ?: 0
        fun City?.hash() = this?.id?.hashCode() ?: 0
        fun Tile?.hash() = this?.position?.hashCode() ?: 0
        fun MapUnit?.hash() = (this?.name?.hashCode() ?: 0) + 17 * this?.currentTile.hash()
        fun ICombatant?.hash() = (this?.getName()?.hashCode() ?: 0) + 17 * this?.getTile().hash()
        fun CombatAction?.hash() = this?.name?.hashCode() ?: 0
        fun Region?.hash() = this?.rect?.hashCode() ?: 0

        var result = civInfo.hash()
        result = 31 * result + city.hash()
        result = 31 * result + unit.hash()
        result = 31 * result + tile.hash()
        result = 31 * result + ourCombatant.hash()
        result = 31 * result + theirCombatant.hash()
        result = 31 * result + attackedTile.hash()
        result = 31 * result + combatAction.hash()
        result = 31 * result + region.hash()
        result = 31 * result + ignoreConditionals.hashCode()
        return result
    }

... in StateForConditionals would likely work.

Untestable - java.lang.Exception: Terrain Coast does not exist in ruleset! How do you even generate a land-only map??? (A: editor)

Fixed:
image