Repository navigation
fix: end a lure once every absent player's logout grace has run out - #18
Merged
Merged
Conversation
A committed player whose logout grace expired was marked to die on next login, and that pending death kept the lure alive. If the player never came back on that character, the lure never ended: the province got no ambient spawns, nobody could place a new lure, and visitors kept taking deserter damage. Only presence or a running grace now holds a lure. When the grace runs out the player has left the fight, so the lure fails as usual once nobody else is present. Because they abandoned a running fight, the death they owe moves to the infestation when the lure fails and still kills that character on its next login, or is dropped once that character has died. Unidentified (held) debts still end with the lure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Returning as the owing character removed the saved debt before the kill, so damage that was cancelled, reduced or survived (totem, invulnerability) forgave the penalty for good. The kill now leaves the debt in place; only a settled death clears it, so a kill that does not land is owed again on the next return. One return kills at most once, whatever number of debts it owes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Returning as the character that owed a running lure's death removed deathOnLogin before the kill, so damage that was cancelled, reduced or survived forgave the death. The kill now leaves the debt, commitment and character in place; settleDeath clears them when the death happens, so a kill that does not land is owed again on the next return. A return kills at most once across running and failed lures, and leaving the lure after surviving moves the debt to the infestation instead of erasing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A lure stayed active while any committed player still owed a death on login. A committed player whose 300 s logout grace ran out was marked to die on next login, and
hasLivingOrGracetreated that pending death as a reason to keep the lure. If the only committed player logged out and never came back on that character, the lure never ended:Fix
Only presence or a running grace holds a lure now. In
hasLivingOrGrace, a committed player still counts only if they are online, alive and on the committed character, or still inside their logout grace. Once the grace runs out, that player has left the fight. If nobody committed is present and nobody is still in grace,checkWipefails the lure through the normalfailLurepath: hologram and lure furniture removed,clearLure, ambient reconcile, save, wither sound andlure-failmessages. That is the same path as any other failure. Neither path calls the map export, which only publishes province, severity and group, so there is nothing about the lure to update.The death they owe outlives the failed lure.
Infestation.clearLure()wipesdeathOnLoginandlogoutCharacter, so failing the lure on its own would have erased the penalty. I kept the debt because the player abandoned a running fight. BeforeclearLure,failLurenow moves every identified debt (committed, with a known character, or the account on servers without characters) into a newInfestation.owedDeathsmap (account → characters). That map:placeLure/clearLure, so a new lure in the same province does not erase it and does not block the account's other characters from joiningowedDeathsininfestations.json. Older files without the field load as empty.characterReturned: returning as the owing character kills it (samemax(40, health + 10)damage as today). The kill does not remove the debt. Only a settled death does (settleDeath, reached from the death event the kill causes). If the damage is cancelled, reduced, or survived through a totem or invulnerability, the debt stays saved and is owed again on the next return. One return kills at most once, however many debts it owes. A player who is already dead on return is not killed again. If another character of the account has since died, that character's debt is dropped. Another living character's debt waits.settleDeath: a saved character death (onCharacterDeath) or the player's death as that character, or on servers without characters the account's deathlogoutCharacterdoes, so a provider outage cannot turn a character debt into an account debtUnidentified (held) debts still end with the lure, as before: no character can be reached to settle them. Victory and admin
clear/setremove the whole infestation, and owed deaths with it. Victory behaves as it did in v0.3.2, where a win also wiped pending debts.Running-lure deaths follow the same rule. Before this PR, a return as the owing character removed
deathOnLoginandlogoutCharacterbefore callingdamage, so a kill that did not land forgave the death. That was true in v0.3.2 too. Now the kill leaves the debt, commitment and character in place, andsettleDeathclears them when the death actually happens. A kill that does not land is owed again on the next return. Across running and failed lures, one return kills at most once. If a death lands, it settles every debt for that character. Two cases still drop the debt without a kill, as before: another character of the account has died, or the account is no longer committed. A player who survives the kill and then runs/lure leaveno longer escapes: leaving moves their running-lure debt intoowedDeathsinstead of erasing it.Restart path is unchanged. A shutdown is still not a departure, so nobody gets a grace or a debt from it. A lure with nobody back fails on the first tick after startup with no penalty. I extended
restartIsNotADepartureSoTheEmptyLureFailsWithoutPenaltyto check that nothing is owed and that logging back in deals no damage.Tests
New in
InfestationManagerTest, driven through the real tick:soleCommittedPlayerPastGraceFailsTheLureButStillDiesOnReturningAsThatCharacter: the lure holds during grace. After the grace expires, the next tick fails it: furniture and hologram removed, ambient reconciled, visitor toldlure-fail, and no more deserter damage. The debt is owed to ALICE. Returning as BOB does nothing, returning as ALICE deals the kill, the debt stays until the death event settles it, and a later login does nothing.aKillThatDoesNotLandKeepsTheOwedDeathAcrossSaveAndLoadUntilADeathSettlesIt: two infestations owe ALICE's death and the damage leaves her alive. One return deals one kill, not two. Both debts survive saving and reloading from disk. The next return kills again, the death settles both debts, and a later login does nothing.oneCommittedPlayerPastGraceLeavesTheFightWhileAnotherKeepsItAlive: the lure continues while the second player fights, even with the departed player back online on another character. When the fighter dies, the lure fails and the departed player's debt is kept. It is dropped once that character is recorded dead.returningWithinGraceKeepsTheLureWithoutPenalty: no failure, no damage, nothing owed.aRunningLureKillThatDoesNotLandIsOwedAgainUntilADeathSettlesIt: two running lures owe ALICE's death while another player keeps both alive. The damage leaves her alive, and one return deals one kill. Debt, commitment and character are all kept, and the next return kills again. Once a kill lands, the death settles both lures, which stay active for the fighter, and a later login does nothing.leavingTheLureAfterSurvivingTheKillStillOwesTheDeath: surviving the kill and then using/lure leavemoves the debt toowedDeaths, and the next return kills again.owedDeathsSettleByAccountWithoutCharactersAndByTheSavedDeathWithThem: standalone account debts, a player already dead on return (no kill, debt kept), account death, sticky tracking from loaded owed deaths, and per-character saved deaths.Updated:
graceExpiresIntoDeathOnLoginAndWipeNeedsNoSurvivorsOrGrace: an expired grace no longer holds the lure.unidentifiedDebtsDoNotKeepTheLureAliveAcrossSaveAndLoad, renameddebtsDoNotKeepTheLureAliveAndOnlyTaggedOnesOutliveItAcrossSaveAndLoad: the tagged debt now moves toowedDeathsand survives save and load.deathOnLoginWaitsForTheCharacterWhoLoggedOffAndIsDroppedOnceThatCharacterDied,returningDebtStopsWhenDamageReentersAnotherSessionEvenForTheSameCharacter,standalonePenaltyLoopStopsWhenAProviderAppearsDuringDamageandInfestationsServicesTest.sharedStartAppliesOnlyTheCurrentCharactersGraceAndDeath: a kill that did not land now keeps the debt, and these tests used to assert it was gone. They still check that one return deals only one kill.InfestationDataTest: round trip, malformed or legacy rows, andplaceLure/clearLurekeepingowedDeaths.mvn -B clean verifypasses locally on JDK 21 with 181 tests and 100% line coverage.Notes
main-SNAPSHOTand releases are tagged separately.🤖 Generated with Claude Code