emipa606 / RealFactionGuest

Repository for the Rimworld mod named Real Faction Guest (Continued)
https://steamcommunity.com/sharedfiles/filedetails/?id=2886929245
MIT License
0 stars 1 forks source link

[Bug]Another circumstance to trigger caravan issue. #4

Open rtxyd opened 1 month ago

rtxyd commented 1 month ago

So I got the same bug as last time, when I called one of Rimsenal Factions‘ caravan. And one of the solution is https://github.com/emipa606/RealFactionGuest/blob/7fcb49c3e904054c95f241efc2cc6e484fbeef19/Source/raceQuestPawn/patch_PawnGenerator_GeneratePawn.cs#L85-L86

change the ">" to ">=", it seems if the combat power of the request equals to exact the pawn's combatpower of what we collected in the list, it skips the pawnkind. In this case the trader is skipped, so it triggers the same bug. This is a simple solution, definitely not the best (just for solving current gameplay). Like patch every pawngroup generator of rimworld rather putting every pawnkind in one list and generating by given combatpower. So there might be another potential bug: if there is a pawnkind and its sequence in the list is upper than traderkind, and it's combat power is lower than traderkind, the trader will be still skipped. And this is vanilla generation order of a caravan and its methods: )LJ@X23UZ1IUL~{}T 8)ISD

So I figure out two better solutions, **This is an attempt, so may not help.

  1. make every pawngroup their own collection, and when choosing pawn by combatpower, we just follow the vanilla order: first traders, second carriers, third guards,

    For solution 1

    // this is a fake code
    list traders, list carriers, list guards, 
    foreach (list traders) {calculution combatpower, choose pawn} 
    foreach (list carriers) {calculution combatpower, choose pawn}  
    foreach (list guards) {calculution combatpower, choose pawn}
  2. still use whole in one list, but sequence the list by vanilla order, add gurds fist, then carriers. then traders, so the traders will be accessed first, then carriers, then guards.

    For solution 2

    https://github.com/emipa606/RealFactionGuest/blob/7fcb49c3e904054c95f241efc2cc6e484fbeef19/Source/raceQuestPawn/patch_PawnGenerator_GeneratePawn.cs#L63-L80

    // this is a fake code
    list all
    list traders, list carriers, list guards
    foreach ( item in pawngroupmaker )
     traders.add( item.traders )
     carriers.add( item.carriers )
     guards.add( item.guards )
    all.addrange(guards)
    all.addrange(carriers)
    all.addrange(traders) //so the order is same of vanilla
    foreach (list all) (combatpower, choose pawn)
rtxyd commented 1 month ago

The attempts above may omit something. Like simplely make ">=" may cause something bad? I don't know why it's ">" instead of ">=" in the original code.

emipa606 commented 1 month ago

Please do a PR with the proposed solution and Ill take a look at it.

rtxyd commented 1 month ago

I got a better solution 3, the solutions above will be integrated in this solution. The point is which incidents should use the method, and which not. So if the caravan use vanilla method to generate, we can safely skip it in this mod. I make a filter of that And the PR may not be so fast. I havent tested it enough.

                //check stack if it's vanilla caravan trader generation request and skip it to vanilla generation.
                //in 1.5 frame 1 is this method, 2 is harmony patched generatePawn, and 3 is generate traders/carriers/guards
                var stack = new StackTrace(0, true);
                StackFrame frame = stack.GetFrame(3);
                MethodBase method = frame.GetMethod();
                Type declaringType = method.DeclaringType;

                if (declaringType.ToString() == "RimWorld.PawnGroupKindWorker_Trader")
                {
                    return; //exactly the incident, skip
                }
                else
                {
                    StringBuilder stringBuilder = new StringBuilder(255);
                    for (int i = 4; i < stack.FrameCount; i++)
                    {
                        frame = stack.GetFrame(i);
                        method = frame.GetMethod();
                        declaringType = method.DeclaringType;
                        stringBuilder.Append(declaringType.ToString());
                        stringBuilder.Append("\n");
                    }
                    var fulltrace = stringBuilder.ToString();
                    if (fulltrace.Contains("RimWorld.PawnGroupKindWorker_Trader"))
                    {
                        return;
                    }
                }