Merge branch 'review/slice-9-ab-recheck'
This commit is contained in:
@@ -369,6 +369,31 @@ public static class TalkCircles
|
||||
BehaviorDef? rules) =>
|
||||
Math.Clamp(current + (rules?.TalkLanguageSkillPerHour ?? 0.005f) * hours, skill.Range.Min, skill.Range.Max);
|
||||
|
||||
/// <summary>
|
||||
/// Enemies do not sit in the same circle. RankInvitees only looks at the initiator when
|
||||
/// forming; a later join is a self-invite, so either side already treating the other as an
|
||||
/// enemy is enough to refuse.
|
||||
/// </summary>
|
||||
public static bool JoinerFits(Person joiner, IReadOnlyList<Person> members, BehaviorDef? rules)
|
||||
{
|
||||
foreach (var member in members)
|
||||
{
|
||||
if (member.Id.Equals(joiner.Id, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
joiner.Opinions.TryGetValue(member.Id, out var fromJoiner);
|
||||
member.Opinions.TryGetValue(joiner.Id, out var fromMember);
|
||||
if (IsEnemy(fromJoiner, rules) || IsEnemy(fromMember, rules))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Invite priority: friends, classmates, others. Enemies never invited.</summary>
|
||||
public static IReadOnlyList<string> RankInvitees(
|
||||
Person initiator,
|
||||
|
||||
@@ -147,10 +147,10 @@ internal static class TalkCircleSystem
|
||||
return TryStartPhone(school, person, nodeId, action);
|
||||
}
|
||||
|
||||
var existing = FindOpenCircle(school, nodeId, actionId);
|
||||
if (existing is not null)
|
||||
var existing = FindOpenCircle(school, nodeId, actionId, person);
|
||||
if (existing is not null && JoinCircle(school, existing, personId, action))
|
||||
{
|
||||
return JoinCircle(school, existing, personId, action);
|
||||
return true;
|
||||
}
|
||||
|
||||
return TryStartGroup(school, person, nodeId, action);
|
||||
@@ -319,6 +319,14 @@ internal static class TalkCircleSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
var sitting = circle.Members
|
||||
.Select(id => school.Roster!.People.First(row => row.Id.Equals(id, StringComparison.Ordinal)))
|
||||
.ToArray();
|
||||
if (!TalkCircles.JoinerFits(person, sitting, rules))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
circle.Members.Add(personId);
|
||||
circle.Members.Sort(StringComparer.Ordinal);
|
||||
school.TalkCircleByPerson[personId] = circle.Id;
|
||||
@@ -326,20 +334,26 @@ internal static class TalkCircleSystem
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ActiveTalkCircle? FindOpenCircle(School school, string nodeId, string actionId)
|
||||
private static ActiveTalkCircle? FindOpenCircle(School school, string nodeId, string actionId, Person joiner)
|
||||
{
|
||||
var rules = school.Catalog!.BehaviorRules;
|
||||
var max = TalkCircles.MaxSize(actionId, rules, [], school.Catalog);
|
||||
foreach (var circle in school.TalkCirclesById.Values)
|
||||
{
|
||||
if (circle.NodeId.Equals(nodeId, StringComparison.Ordinal)
|
||||
&& circle.ActionId.Equals(actionId, StringComparison.Ordinal)
|
||||
&& circle.RemainingMinutes > 0)
|
||||
if (!circle.NodeId.Equals(nodeId, StringComparison.Ordinal)
|
||||
|| !circle.ActionId.Equals(actionId, StringComparison.Ordinal)
|
||||
|| circle.RemainingMinutes <= 0
|
||||
|| circle.Members.Count >= max)
|
||||
{
|
||||
var rules = school.Catalog!.BehaviorRules;
|
||||
var max = TalkCircles.MaxSize(actionId, rules, [], school.Catalog);
|
||||
if (circle.Members.Count < max)
|
||||
{
|
||||
return circle;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var sitting = circle.Members
|
||||
.Select(id => school.Roster!.People.First(row => row.Id.Equals(id, StringComparison.Ordinal)))
|
||||
.ToArray();
|
||||
if (TalkCircles.JoinerFits(joiner, sitting, rules))
|
||||
{
|
||||
return circle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user