private void DoTournament(Caravan caravan, Pawn participant) { var competitorPool = MedievalTournamentUtility.GenerateCompetitors(competitorCount, category, Faction, PossibleCompetitors); var fullAudience = competitorPool.Concat(caravan.PawnsListForReading).Where(p => p != participant).ToList(); float participantEff = MedievalTournamentUtility.TournamentEffectivenessFor(participant, category); var entries = new List <BattleLogEntry_Event>(); bool cancelled = false; // Simulate a progression through the rounds int curPlace = competitorCount + 1; for (int i = 0; i < competitorCount; i++) { var competitor = competitorPool.RandomElement(); competitorPool.Remove(competitor); // This is where battle simulation happens float competitorEff = MedievalTournamentUtility.TournamentEffectivenessFor(competitor, category); float winChance = MedievalTournamentUtility.EffectivenessAdvantageToWinChanceCurve.Evaluate(participantEff - competitorEff); var victor = Rand.Chance(winChance) ? participant : competitor; var loser = (participant == victor) ? competitor : participant; if (!ResolveDisaster(victor, loser, fullAudience.Where(p => p != competitor).ToList(), out var victim, out var disEntry)) { if (category.rulePack != null) { entries.Add(new BattleLogEntry_Event(loser, category.rulePack, victor)); } if (participant == victor) { curPlace--; } else { break; } }
public void Notify_CaravanArrived(Caravan caravan) { var participants = new List <Pawn>(); var nonParticipants = new List <Pawn>(); MedievalTournamentUtility.GroupParticipants(caravan.PlayerPawnsForStoryteller.Where(p => p.RaceProps.Humanlike).ToList(), category, participants, nonParticipants); // Create dialogue tree var leader = Faction.leader; var tourneyNode = new DiaNode("VanillaFactionsExpanded.MedievalTournamentInitial".Translate(leader.LabelShort, Faction.Name, category.label, competitorCount, GenLabel.ThingsLabel(rewards), leader.Named("PAWN"))); // Option 1: Participate var participateNode = new DiaNode("VanillaFactionsExpanded.ParticipateInitial".Translate()); var participateOption = new DiaOption("VanillaFactionsExpanded.Participate".Translate()) { link = participateNode }; tourneyNode.options.Add(participateOption); for (int i = 0; i < participants.Count; i++) { var pawn = participants[i]; var pawnOption = new DiaOption(MedievalTournamentUtility.ParticipantOptionText(pawn, category)) { action = () => DoTournament(caravan, pawn), resolveTree = true }; participateNode.options.Add(pawnOption); } for (int i = 0; i < nonParticipants.Count; i++) { var pawn = nonParticipants[i]; var pawnOption = new DiaOption(MedievalTournamentUtility.ParticipantOptionText(pawn, category)) { disabled = true }; participateNode.options.Add(pawnOption); } var participateGoBack = new DiaOption("GoBack".Translate()) { link = tourneyNode }; participateNode.options.Add(participateGoBack); // Option 2: Attack (angers faction) var attackOption = new DiaOption($"{"CommandAttackSettlement".Translate()} ({"AngersFaction".Translate()})") { action = () => { LongEventHandler.QueueLongEvent(() => { Faction.TrySetRelationKind(Faction.OfPlayer, FactionRelationKind.Hostile, false); var competitorPool = PossibleCompetitors.ToList(); var extraPawnParams = StorytellerUtility.DefaultParmsNow(IncidentCategoryDefOf.ThreatBig, caravan); extraPawnParams.faction = Faction; var pawnGroupMakerParams = IncidentParmsUtility.GetDefaultPawnGroupMakerParms(PawnGroupKindDefOf.Combat, extraPawnParams, true); pawnGroupMakerParams.generateFightersOnly = true; var hostilePawns = MedievalTournamentUtility.GenerateCompetitors(competitorCount, category, Faction, PossibleCompetitors).Concat(PawnGroupMakerUtility.GeneratePawns(pawnGroupMakerParams)).ToList(); var map = CaravanIncidentUtility.SetupCaravanAttackMap(caravan, hostilePawns, true); if (hostilePawns.Any()) { LordMaker.MakeNewLord(Faction, new LordJob_AssaultColony(Faction), map, hostilePawns); } Find.TickManager.Notify_GeneratedPotentiallyHostileMap(); for (int i = 0; i < rewards.Count; i++) { GenPlace.TryPlaceThing(rewards[i], map.Center, map, ThingPlaceMode.Near); } }, "GeneratingMapForNewEncounter", false, null); Find.WorldObjects.Remove(this); }, resolveTree = true }; tourneyNode.options.Add(attackOption); // Option 3: Leave var leaveOption = new DiaOption("VanillaFactionsExpanded.Leave".Translate()) { resolveTree = true }; tourneyNode.options.Add(leaveOption); // Add dialogue menu Find.WindowStack.Add(new Dialog_NodeTree(tourneyNode, title: LabelCap)); }