OrionFive / Hospitality

Orion's "Hospitality" and more
https://www.patreon.com/orionmods
GNU General Public License v3.0
91 stars 54 forks source link

Guests share beds #803

Closed Nosohvost closed 2 months ago

Nosohvost commented 2 months ago

Guests sleep with strangers even if there are free beds with the same attractiveness.

To Reproduce

  1. Wait for a group of N guests to arrive
  2. Place N identical double beds in the same room
  3. Guests will share beds and be unnappy about it, even though there are free beds avaliable

This seems to be a bit random, so might take 2 tries to reproduce.

I looked at the source code, and I think what happens is 2 guests reserve the same bed and start walking to it. At that time the bed still has no owners, so both guests assume it is unoccupied and then sleep together.

I think the solution is to check for bed owners and bed reservations when calculating bed attractiveness. ReservationManager has a ReserversOf method which can probably be used for this. I have zero experience in modding or c#, so unfourtunately I don't know how to implement this myself.

image

OrionFive commented 2 months ago

Ah yeah. I see how this could cause it. When they choose to walk to it, they've already checked attractiveness, but there is no other reservation yet. By the time they reach it and make the reservation, there is another reservation, but it's not a blocking issue. I don't like that they have to evaluate all beds again at that point. Hm. Not sure how this should be fixed.

Nosohvost commented 2 months ago

Can pawns reserve beds before going to them? That would make it possible to check for opinion of the other guest who reserved the same bed. Don't pawns reserve workbenches before going to them? If so, it would make sense to implement the same logic with guest beds.

OrionFive commented 2 months ago

The reservation systems for beds and other objects work quite differently. They go to the bed to claim it, and it's not claimed until they reach it. Technically, they are also reserving it for usage, but since it's a double bed, it allows two pawns to reserve it, and this reservation is canceled if they're interrupted somehow. It's a completely different system.

Nosohvost commented 2 months ago

My suggestion was to use the reservation system to get info on reservers. This way guests know if they'll be sleeping with strangers in advance and choose their beds accordingly. This seems to be an elegant solution without guests reevaluating all beds. I've coded this and created a pull request.

OrionFive commented 2 months ago

It's live. I've adjusted it to make it work for beds with more than 2 owners. I wasn't able to find guests who would share a bed, so I couldn't verify sharing still works at all anymore now.

Nosohvost commented 2 months ago

return -250 + opinion; got replaced with return _tmpOwners.Sum(owner => (guest.relations.OpinionOf(owner) - 15) * 4); I think you removed the -250 penalty by accident? It causes pawns with more than 15 opinion to prefer sleeping with each other, which seems way too low.

On a side note, would it cause too much trouble to update the 1.4 assembly? My current playthrough is centered around Hospitality, and this bug annoyed me so much I decided to fix myself. Can't update the save file to 1.5 though. If it's too much of a hassle - no worries, you're already doing absolutely amazing work maintaining this mod for 8 years. Thank you!

OrionFive commented 2 months ago

The -250 is overkill, since there's already the check that they must have a romantic relationship.

Updating the 1.4 assembly is a fair bit of trouble. But if you make a PR of it updated correctly with the fix, I'll merge it. Make sure to compile it against the correct DLLs and with the correct assembly version, though.

Normally I never touch old versions after a new one is out because the risk of breaking the old version somehow is way too high.

Nosohvost commented 2 months ago

The romantic relationship is checked only in OtherOwnerScore method and contributes towards the ideological fulfillment score which always equals 0 without the DLC enabled. The OtherPawnOpinion method uses the formula I quoted above and gives a positive bed attractiveness for 15+ opinion. So without Ideology enabled, everyone wants to sleep with pretty/beautiful pawns and both get a mood debuff.

Try testing it without Ideology.

OrionFive commented 2 months ago

Ah, I must have missed that part. I suppose the relationship check should also be added to the other method then?

Nosohvost commented 2 months ago

I'd just remove OtherOwnerScore() - it seems redundant and easy to confuse with OtherPawnOpinion. The latter can include

var score = _tmpOwners.Sum(owner => (guest.relations.OpinionOf(owner) - 15) * 4 + (guest.relations.GetDirectRelation(PawnRelationDefOf.Spouse, owner) == null ? -250 : 0));

Note that WillingToShareBed() method always returns True without Ideology, so cannot be used here. This seems to solve the issue for Vanilla.

I don't own Ideology, so I don't know how it works. My best bet is to include WillingToShareBed() in GetIdeologicalFulfillment() and add +250 attractiveness if a pawn is willing to share bed. This should negate the -250 from sleeping with a stranger.

OrionFive commented 2 months ago

I've uploaded a fix. I've tested it without Ideology a few times and I think this should do the trick.

Nosohvost commented 2 months ago

Looks good!