private static void assignRoleTargets(RoleAssignmentData data) { // Set Lawyer Target if (Lawyer.lawyer != null) { var possibleTargets = new List <PlayerControl>(); foreach (PlayerControl p in PlayerControl.AllPlayerControls) { if (!p.Data.IsDead && !p.Data.Disconnected && !p.isLovers() && (p.Data.Role.IsImpostor || p == Jackal.jackal)) { possibleTargets.Add(p); } } if (possibleTargets.Count == 0) { MessageWriter w = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.LawyerPromotesToPursuer, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(w); RPCProcedure.lawyerPromotesToPursuer(); } else { var target = possibleTargets[TheOtherRoles.rnd.Next(0, possibleTargets.Count)]; MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.LawyerSetTarget, Hazel.SendOption.Reliable, -1); writer.Write(target.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.lawyerSetTarget(target.PlayerId); } } }
private static void assignSpecialRoles(RoleAssignmentData data) { // Assign Mafia if (data.impostors.Count >= 3 && data.maxImpostorRoles >= 3 && (rnd.Next(1, 101) <= CustomOptionHolder.mafiaSpawnRate.getSelection() * 10)) { setRoleToRandomPlayer((byte)RoleId.Godfather, data.impostors); setRoleToRandomPlayer((byte)RoleId.Janitor, data.impostors); setRoleToRandomPlayer((byte)RoleId.Mafioso, data.impostors); data.maxImpostorRoles -= 3; } // Assign Lovers if (rnd.Next(1, 101) <= CustomOptionHolder.loversSpawnRate.getSelection() * 10) { if (data.impostors.Count > 0 && data.crewmates.Count > 0 && data.maxCrewmateRoles > 0 && data.maxImpostorRoles > 0 && rnd.Next(1, 101) <= CustomOptionHolder.loversImpLoverRate.getSelection() * 10) { setRoleToRandomPlayer((byte)RoleId.Lover1, data.impostors); setRoleToRandomPlayer((byte)RoleId.Lover2, data.crewmates); data.maxCrewmateRoles--; data.maxImpostorRoles--; } else if (data.crewmates.Count >= 2 && data.maxCrewmateRoles >= 2) { setRoleToRandomPlayer((byte)RoleId.Lover1, data.crewmates); setRoleToRandomPlayer((byte)RoleId.Lover2, data.crewmates); data.maxCrewmateRoles -= 2; } } // Assign Child if (rnd.Next(1, 101) <= CustomOptionHolder.childSpawnRate.getSelection() * 10) { if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && rnd.Next(1, 101) <= 33) { setRoleToRandomPlayer((byte)RoleId.Child, data.impostors); data.maxImpostorRoles--; } else if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0) { setRoleToRandomPlayer((byte)RoleId.Child, data.crewmates); data.maxCrewmateRoles--; } } }
private static void assignRoleModifiers(RoleAssignmentData data) { // Madmate for (int i = 0; i < CustomOptionHolder.madmateSpawnRate.count; i++) { if (rnd.Next(1, 100) <= CustomOptionHolder.madmateSpawnRate.rate * 10) { var candidates = Madmate.candidates; if (candidates.Count <= 0) { break; } if (Madmate.madmateType == Madmate.MadmateType.Simple) { if (data.maxCrewmateRoles <= 0) { break; } setModifierToRandomPlayer((byte)ModifierType.Madmate, Madmate.candidates); data.maxCrewmateRoles--; } else { setModifierToRandomPlayer((byte)ModifierType.Madmate, Madmate.candidates); } } } // Munou for (int i = 0; i < CustomOptionHolder.munouSpawnRate.count; i++) { if (rnd.Next(1, 100) <= CustomOptionHolder.munouSpawnRate.rate * 10) { var candidates = Munou.candidates; if (candidates.Count <= 0) { break; } if (Munou.munouType == Munou.MunouType.Simple) { if (data.maxCrewmateRoles <= 0) { break; } setModifierToRandomPlayer((byte)ModifierType.Munou, Munou.candidates); data.maxCrewmateRoles--; } else { setModifierToRandomPlayer((byte)ModifierType.Munou, Munou.candidates); } } } // AntiTeleport for (int i = 0; i < CustomOptionHolder.antiTeleportSpawnRate.count; i++) { if (rnd.Next(1, 100) <= CustomOptionHolder.antiTeleportSpawnRate.rate * 10) { var candidates = AntiTeleport.candidates; if (candidates.Count <= 0) { break; } setModifierToRandomPlayer((byte)ModifierType.AntiTeleport, AntiTeleport.candidates); } } // Mini for (int i = 0; i < CustomOptionHolder.miniSpawnRate.count; i++) { if (rnd.Next(1, 100) <= CustomOptionHolder.miniSpawnRate.rate * 10) { var candidates = Mini.candidates; if (candidates.Count <= 0) { break; } setModifierToRandomPlayer((byte)ModifierType.Mini, Mini.candidates); } } }
private static void assignChanceRoles(RoleAssignmentData data) { blockedAssignments = 0; // Get all roles where the chance to occur is set grater than 0% but not 100% and build a ticket pool based on their weight List <byte> crewmateTickets = data.crewSettings.Where(x => x.Value.rate > 0 && x.Value.rate < 10).Select(x => Enumerable.Repeat(x.Key, x.Value.rate * x.Value.count)).SelectMany(x => x).ToList(); List <byte> neutralTickets = data.neutralSettings.Where(x => x.Value.rate > 0 && x.Value.rate < 10).Select(x => Enumerable.Repeat(x.Key, x.Value.rate * x.Value.count)).SelectMany(x => x).ToList(); List <byte> impostorTickets = data.impSettings.Where(x => x.Value.rate > 0 && x.Value.rate < 10).Select(x => Enumerable.Repeat(x.Key, x.Value.rate * x.Value.count)).SelectMany(x => x).ToList(); // Assign roles until we run out of either players we can assign roles to or run out of roles we can assign to players while ( (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && impostorTickets.Count > 0) || (data.crewmates.Count > 0 && ( (data.maxCrewmateRoles > 0 && crewmateTickets.Count > 0) || (data.maxNeutralRoles > 0 && neutralTickets.Count > 0) ))) { Dictionary <TeamType, List <byte> > rolesToAssign = new Dictionary <TeamType, List <byte> >(); if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0 && crewmateTickets.Count > 0) { rolesToAssign.Add(TeamType.Crewmate, crewmateTickets); } if (data.crewmates.Count > 0 && data.maxNeutralRoles > 0 && neutralTickets.Count > 0) { rolesToAssign.Add(TeamType.Neutral, neutralTickets); } if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && impostorTickets.Count > 0) { rolesToAssign.Add(TeamType.Impostor, impostorTickets); } // Randomly select a pool of role tickets to assign a role from next (Crewmate role, Neutral role or Impostor role) // then select one of the roles from the selected pool to a player // and remove all tickets of this role (and any potentially blocked role pairings) from the pool(s) var roleType = rolesToAssign.Keys.ElementAt(rnd.Next(0, rolesToAssign.Keys.Count())); var players = roleType == TeamType.Crewmate || roleType == TeamType.Neutral ? data.crewmates : data.impostors; var index = rnd.Next(0, rolesToAssign[roleType].Count); var roleId = rolesToAssign[roleType][index]; var player = setRoleToRandomPlayer(rolesToAssign[roleType][index], players); if (player == byte.MaxValue && blockedAssignments < maxBlocks) { blockedAssignments++; continue; } blockedAssignments = 0; rolesToAssign[roleType].RemoveAll(x => x == roleId); if (CustomOptionHolder.blockedRolePairings.ContainsKey(roleId)) { foreach (var blockedRoleId in CustomOptionHolder.blockedRolePairings[roleId]) { // Remove tickets of blocked roles from all pools crewmateTickets.RemoveAll(x => x == blockedRoleId); neutralTickets.RemoveAll(x => x == blockedRoleId); impostorTickets.RemoveAll(x => x == blockedRoleId); } } // Adjust the role limit switch (roleType) { case TeamType.Crewmate: data.maxCrewmateRoles--; break; case TeamType.Neutral: data.maxNeutralRoles--; break; case TeamType.Impostor: data.maxImpostorRoles--; break; } } }
private static void assignEnsuredRoles(RoleAssignmentData data) { blockedAssignments = 0; // Get all roles where the chance to occur is set to 100% List <byte> ensuredCrewmateRoles = data.crewSettings.Where(x => x.Value.rate == 10).Select(x => Enumerable.Repeat(x.Key, x.Value.count)).SelectMany(x => x).ToList(); List <byte> ensuredNeutralRoles = data.neutralSettings.Where(x => x.Value.rate == 10).Select(x => Enumerable.Repeat(x.Key, x.Value.count)).SelectMany(x => x).ToList(); List <byte> ensuredImpostorRoles = data.impSettings.Where(x => x.Value.rate == 10).Select(x => Enumerable.Repeat(x.Key, x.Value.count)).SelectMany(x => x).ToList(); // Assign roles until we run out of either players we can assign roles to or run out of roles we can assign to players while ( (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && ensuredImpostorRoles.Count > 0) || (data.crewmates.Count > 0 && ( (data.maxCrewmateRoles > 0 && ensuredCrewmateRoles.Count > 0) || (data.maxNeutralRoles > 0 && ensuredNeutralRoles.Count > 0) ))) { Dictionary <TeamType, List <byte> > rolesToAssign = new Dictionary <TeamType, List <byte> >(); if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0 && ensuredCrewmateRoles.Count > 0) { rolesToAssign.Add(TeamType.Crewmate, ensuredCrewmateRoles); } if (data.crewmates.Count > 0 && data.maxNeutralRoles > 0 && ensuredNeutralRoles.Count > 0) { rolesToAssign.Add(TeamType.Neutral, ensuredNeutralRoles); } if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && ensuredImpostorRoles.Count > 0) { rolesToAssign.Add(TeamType.Impostor, ensuredImpostorRoles); } // Randomly select a pool of roles to assign a role from next (Crewmate role, Neutral role or Impostor role) // then select one of the roles from the selected pool to a player // and remove the role (and any potentially blocked role pairings) from the pool(s) var roleType = rolesToAssign.Keys.ElementAt(rnd.Next(0, rolesToAssign.Keys.Count())); var players = roleType == TeamType.Crewmate || roleType == TeamType.Neutral ? data.crewmates : data.impostors; var index = rnd.Next(0, rolesToAssign[roleType].Count); var roleId = rolesToAssign[roleType][index]; var player = setRoleToRandomPlayer(rolesToAssign[roleType][index], players); if (player == byte.MaxValue && blockedAssignments < maxBlocks) { blockedAssignments++; continue; } blockedAssignments = 0; rolesToAssign[roleType].RemoveAt(index); if (CustomOptionHolder.blockedRolePairings.ContainsKey(roleId)) { foreach (var blockedRoleId in CustomOptionHolder.blockedRolePairings[roleId]) { // Set chance for the blocked roles to 0 for chances less than 100% if (data.impSettings.ContainsKey(blockedRoleId)) { data.impSettings[blockedRoleId] = (0, 0); } if (data.neutralSettings.ContainsKey(blockedRoleId)) { data.neutralSettings[blockedRoleId] = (0, 0); } if (data.crewSettings.ContainsKey(blockedRoleId)) { data.crewSettings[blockedRoleId] = (0, 0); } // Remove blocked roles even if the chance was 100% foreach (var ensuredRolesList in rolesToAssign.Values) { ensuredRolesList.RemoveAll(x => x == blockedRoleId); } } } // Adjust the role limit switch (roleType) { case TeamType.Crewmate: data.maxCrewmateRoles--; break; case TeamType.Neutral: data.maxNeutralRoles--; break; case TeamType.Impostor: data.maxImpostorRoles--; break; } } }
private static void selectFactionForFactionIndependentRoles(RoleAssignmentData data) { // Assign Guesser (chance to be impostor based on setting) bool isEvilGuesser = (rnd.Next(1, 101) <= CustomOptionHolder.guesserIsImpGuesserRate.getSelection() * 10); if (CustomOptionHolder.guesserSpawnBothRate.getSelection() > 0) { if (rnd.Next(1, 101) <= CustomOptionHolder.guesserSpawnRate.getSelection() * 10) { if (isEvilGuesser) { if (data.impostors.Count > 0 && data.maxImpostorRoles > 0) { byte evilGuesser = setRoleToRandomPlayer((byte)RoleType.EvilGuesser, data.impostors); data.impostors.ToList().RemoveAll(x => x.PlayerId == evilGuesser); data.maxImpostorRoles--; data.crewSettings.Add((byte)RoleType.NiceGuesser, (CustomOptionHolder.guesserSpawnBothRate.getSelection(), 1)); } } else if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0) { byte niceGuesser = setRoleToRandomPlayer((byte)RoleType.NiceGuesser, data.crewmates); data.crewmates.ToList().RemoveAll(x => x.PlayerId == niceGuesser); data.maxCrewmateRoles--; data.impSettings.Add((byte)RoleType.EvilGuesser, (CustomOptionHolder.guesserSpawnBothRate.getSelection(), 1)); } } } else { if (isEvilGuesser) { data.impSettings.Add((byte)RoleType.EvilGuesser, (CustomOptionHolder.guesserSpawnRate.getSelection(), 1)); } else { data.crewSettings.Add((byte)RoleType.NiceGuesser, (CustomOptionHolder.guesserSpawnRate.getSelection(), 1)); } } // Assign Swapper (chance to be impostor based on setting) if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && rnd.Next(1, 101) <= CustomOptionHolder.swapperIsImpRate.getSelection() * 10) { data.impSettings.Add((byte)RoleType.Swapper, (CustomOptionHolder.swapperSpawnRate.getSelection(), 1)); } else if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0) { data.crewSettings.Add((byte)RoleType.Swapper, (CustomOptionHolder.swapperSpawnRate.getSelection(), 1)); } // Assign Shifter (chance to be neutral based on setting) bool shifterIsNeutral = false; if (data.crewmates.Count > 0 && data.maxNeutralRoles > 0 && rnd.Next(1, 101) <= CustomOptionHolder.shifterIsNeutralRate.getSelection() * 10) { data.neutralSettings.Add((byte)RoleType.Shifter, (CustomOptionHolder.shifterSpawnRate.getSelection(), 1)); shifterIsNeutral = true; } else if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0) { data.crewSettings.Add((byte)RoleType.Shifter, (CustomOptionHolder.shifterSpawnRate.getSelection(), 1)); shifterIsNeutral = false; } // Assign any dual role types foreach (var option in CustomDualRoleOption.dualRoles) { if (option.count <= 0 || !option.roleEnabled) { continue; } int niceCount = 0; int evilCount = 0; while (niceCount + evilCount < option.count) { if (option.assignEqually) { niceCount++; evilCount++; } else { bool isEvil = rnd.Next(1, 101) <= option.impChance * 10; if (isEvil) { evilCount++; } else { niceCount++; } } } if (niceCount > 0) { data.crewSettings.Add((byte)option.roleType, (option.rate, niceCount)); } if (evilCount > 0) { data.impSettings.Add((byte)option.roleType, (option.rate, evilCount)); } } MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetShifterType, Hazel.SendOption.Reliable, -1); writer.Write(shifterIsNeutral); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.setShifterType(shifterIsNeutral); }
private static void assignSpecialRoles(RoleAssignmentData data) { // Assign GM if (CustomOptionHolder.gmEnabled.getBool() == true) { byte gmID = 0; if (CustomOptionHolder.gmIsHost.getBool() == true) { PlayerControl host = AmongUsClient.Instance?.GetHost().Character; gmID = setRoleToHost((byte)RoleType.GM, host); // First, remove the GM from role selection. data.crewmates.RemoveAll(x => x.PlayerId == host.PlayerId); data.impostors.RemoveAll(x => x.PlayerId == host.PlayerId); } else { gmID = setRoleToRandomPlayer((byte)RoleType.GM, data.crewmates); } PlayerControl p = PlayerControl.AllPlayerControls.ToArray().ToList().Find(x => x.PlayerId == gmID); if (p != null && CustomOptionHolder.gmDiesAtStart.getBool()) { p.Exiled(); } } // Assign Lovers for (int i = 0; i < CustomOptionHolder.loversNumCouples.getFloat(); i++) { var singleCrew = data.crewmates.FindAll(x => !x.isLovers()); var singleImps = data.impostors.FindAll(x => !x.isLovers()); bool isOnlyRole = !CustomOptionHolder.loversCanHaveAnotherRole.getBool(); if (rnd.Next(1, 101) <= CustomOptionHolder.loversSpawnRate.getSelection() * 10) { int lover1 = -1; int lover2 = -1; int lover1Index = -1; int lover2Index = -1; if (singleImps.Count > 0 && singleCrew.Count > 0 && (!isOnlyRole || (data.maxCrewmateRoles > 0 && data.maxImpostorRoles > 0)) && rnd.Next(1, 101) <= CustomOptionHolder.loversImpLoverRate.getSelection() * 10) { lover1Index = rnd.Next(0, singleImps.Count); lover1 = singleImps[lover1Index].PlayerId; lover2Index = rnd.Next(0, singleCrew.Count); lover2 = singleCrew[lover2Index].PlayerId; if (isOnlyRole) { data.maxImpostorRoles--; data.maxCrewmateRoles--; data.impostors.RemoveAll(x => x.PlayerId == lover1); data.crewmates.RemoveAll(x => x.PlayerId == lover2); } } else if (singleCrew.Count >= 2 && (isOnlyRole || data.maxCrewmateRoles >= 2)) { lover1Index = rnd.Next(0, singleCrew.Count); while (lover2Index == lover1Index || lover2Index < 0) { lover2Index = rnd.Next(0, singleCrew.Count); } lover1 = singleCrew[lover1Index].PlayerId; lover2 = singleCrew[lover2Index].PlayerId; if (isOnlyRole) { data.maxCrewmateRoles -= 2; data.crewmates.RemoveAll(x => x.PlayerId == lover1); data.crewmates.RemoveAll(x => x.PlayerId == lover2); } } if (lover1 >= 0 && lover2 >= 0) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetLovers, Hazel.SendOption.Reliable, -1); writer.Write((byte)lover1); writer.Write((byte)lover2); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.setLovers((byte)lover1, (byte)lover2); } } } // Assign Mafia if (data.impostors.Count >= 3 && data.maxImpostorRoles >= 3 && (rnd.Next(1, 101) <= CustomOptionHolder.mafiaSpawnRate.getSelection() * 10)) { setRoleToRandomPlayer((byte)RoleType.Godfather, data.impostors); setRoleToRandomPlayer((byte)RoleType.Janitor, data.impostors); setRoleToRandomPlayer((byte)RoleType.Mafioso, data.impostors); data.maxImpostorRoles -= 3; } // Assign Bomber if (data.impostors.Count >= 2 && data.maxImpostorRoles >= 2 && (rnd.Next(1, 101) <= CustomOptionHolder.bomberSpawnRate.getSelection() * 10)) { setRoleToRandomPlayer((byte)RoleType.BomberA, data.impostors); setRoleToRandomPlayer((byte)RoleType.BomberB, data.impostors); data.maxImpostorRoles -= 2; } // Assign Mimic if (data.impostors.Count >= 2 && data.maxImpostorRoles >= 2 && (rnd.Next(1, 101) <= CustomOptionHolder.mimicSpawnRate.getSelection() * 10)) { setRoleToRandomPlayer((byte)RoleType.MimicK, data.impostors); setRoleToRandomPlayer((byte)RoleType.MimicA, data.impostors); data.maxImpostorRoles -= 2; } }