搜索结果: *

  1. Suggestion: Horses should be fed

    Are you sure this would be more realistic?

    The Mongol armies were successful in part because their horses could graze off the land. They managed 2-4 mounts per soldier without issue. The Mamluks started a policy of scorched earth (burning pastures) to prevent grazing.

    I'm not convinced by the arguments that the game doesn't show armies taking time to graze. I'm not aware of anyone measuring the distances in the game and figuring out how fast parties are actually moving. In fact, part of the reason why Mongol armies moved as quickly as they did (60 miles per day is given by multiple books) is because that was the only way they could keep the horses fed with enough grass. See e.g. https://history.stackexchange.com/a/10336
  2. Recruited lords leave player faction immediately & dying, outnumbered factions can instantly recruit new lords

    It seems that, due to this mod not being updated, it's no longer available for download. Dcvd2005 can you update it? This is still a problem, I just lost a vassal that asked me 300k to join my kingdom.

    I managed to download the compiled folder from GitHub and to install it. But it's not working anymore. Lords are still leaving me.

    Thanks.
    I took down the mod because I realized that it would likely not work in future builds and I didn't want to update it for each new build. The mod worked by adjusting a calculation that the AI uses to decide if it should swap sides. This calculation is performed both for AI lords in the player's faction and AI lords in AI factions, i.e. it would fix this other reported bug as well https://forums.taleworlds.com/index...why-sturgia-gets-wiped-out-too-easily.420425/.

    Ultimately, I think this issue won't be resolved until Taleworlds fixes it or someone with more free time than me can invest themselves into maintaining a fix.
  3. Modding in C# feels incredibly boring and tedious.

    Replacing models and other classes to make mods may be the "right" way to do things from a programming architecture perspective, but it's absolutely terrible for modding. I feel like people aren't thinking this through *at all*.

    So you replaced one of the default models with your own, all fine and good, right?

    Except now your mod is completely incompatible with any other mod that wants to alter anything in that model as well.

    If you instead patched the one or two fields or methods you're interested in, unless other mods directly interfered with those exact fields or methods, it'd be compatible.

    Doing everything the "right" way is going to rapidly result in mod compatibility going into the toilet, all in pursuit of "clean" code, which matters exactly ZEEEERRRRROOOOO to mod users.
    Mod support is a spectrum.

    On one end of the spectrum, you have limited, sandboxed access to the game. You can add new items, but you can't replace existing items. Or -- if you support replacing or adding items, you can only do so one mod at a time, in the case of games that can't resolve differences between mods, like Warband.

    Some games limit mods to pure resources & data with no support for scripting. Other games like Skyrim provide scripting through events that mods can register a callback on, e.g. every game tick, or when something interesting happens like a hit is detected, or a new room is entered.

    I'm going through this list of definitions because I want to express how much mod support Bannerlord has before talking about Harmony and other methods that take advantage of C#'s rich runtime support for reflection.

    What can we do in Bannerlord, that we know of, several days after early access release?
    • Modules can replace resources defined by any module loaded before us, including the native game.
    • Modules can add to the XML, or replace the XML, of any module loaded before us, including the native game.
    • The game tries to resolve differences between modules by load order.
    • The game provides events that mods can register a callback on so that they can be called by the game engine to run their own code, e.g. the various OnTick events.
    • The game provides attributes that mods can use to register their classes for the reflection that the game provides, e.g. the encyclopedia or save format definitions.
    • The game code is divided into hundreds of small, discrete models with a handful of methods. Each model can be overridden or replaced in its entirely, by any mod, without conflict.
    • Game entities are defined in the XML modifiable above.
    • The UI code is divided into hundreds of small, discrete view models. These use reflection and can be replaced or overridden.
    • The UI layout is defined in the XML modifiable above.
    • It would be possible for multiple mods to override the same model if the game exposed a method that would find the last model of a given type in the list of loaded models before our mod, when we're loading our mod.
    And then there's Harmony. Not all languages are as easy to monkey patch as C#. There's no equivalent, easy-to-use library for monkey-patching C++ that I'm aware of, even though C++ supports run-time type information too. Java's reflection is similarly crippled, although Slay the Spire modders seem to make it work. There's a reason why Unity uses C# as well and Godot is adding support for it too.

    I'm not saying mod support is perfect.

    There are events that would be helpful that I don't see in the DLLs anywhere.
    There are functions and members that are private that should be public.
    There are functions that aren't marked as virtual.
    There are XML files that we can't seem to make work except as part of the native module.
    Loading & saving custom definitions can cause a crash after a mod is removed.

    But it should be clear to anyone who understands system design that this game was designed with the intent of supporting the modding community. For y'all to argue that the engine / architecture is terrible for modding is completely unfounded (refer back to all of the design choices in the bulleted list above).
  4. WB Coding Modify Base GUI XML File

    its easy to modify xml file in ModuleData folder but how can i do it for GUI folder?
    Hey, I was wondering this earlier today and I think I figured it out for my mod here.

    If you define the XML at the same folder path relative to your module's base directory, it seems to override any previous definition of that XML file. At the mod I linked to above, I replaced the game's native definition of GUI/Prefabs/Encyclopedia/EncyclopediaSubPages/EncyclopediaClanSubPageElement.xml by simply creating that same folder path in my module.

    Result:
    438-1586657393-1801093095.jpeg

    (note that in the native game, destroyed clans are not visually any different, but in this above image they're grey!)
  5. Modding in C# feels incredibly boring and tedious.

    It is also source of the performance issues :smile: Maybe not exactly for that example but LINQ can hurt performance a lot compared to a loop alternative. This is usually the case only for games though.
    To add more detail here:

    LINQ is a performance issue because it tends to create a lot of short-lived objects that need to be garbage collected. In a tight loop where the loop needs to run as quickly as possible on the CPU, the work done collecting that garbage can create more work than the time spent on the loop itself. Unfortunately for games, the game loop itself is a tight loop!

    I use ReSharper's Heap Allocation Viewer plugin when I'm writing C# code to keep track of stuff like that and make sure I'm only using LINQ in code that doesn't run every frame, e.g. initialization or in response to loading a new resource at run-time for debugging.

    I do understand the replies stating that it is a far better programming langage overall, and I'm not against that.

    The problem that I see is that it seems very easy to add tweaks, but it would be extremely hard for example to modify the individual combat AI, the spawn of a party, the properties of the hero class, the formula to output damages when in warband it was extremely simple.

    I am worried for many reasons, but also because they designed some systems to be incredibly black box and difficult to tweak such as the melee damage output in the code. If you fiddle with it, you will see a bunch of goto functions, of variables defined one after the other and it doesn't seem that it can be modified easily without using harmony. Seriously??

    public static float CalculateStrikeMagnitudeForSwing(
    float swingSpeed,
    float impactPointAsPercent,
    float weaponWeight,
    float weaponLength,
    float weaponInertia,
    float weaponCoM,
    float extraLinearSpeed)
    {
    float num1 = weaponLength * impactPointAsPercent - weaponCoM;
    float num2 = swingSpeed * (0.5f + weaponCoM) + extraLinearSpeed;
    double num3 = 0.5 * (double) weaponWeight * (double) num2 * (double) num2;
    float num4 = swingSpeed;
    double num5 = (double) (0.5f * weaponInertia * num4 * num4);
    double num6 = num3 + num5;
    float num7 = (float) (((double) num2 + (double) num4 * (double) num1) / (1.0 / (double) weaponWeight + (double) num1 * (double) num1 / (double) weaponInertia));
    float num8 = num2 - num7 / weaponWeight;
    float num9 = num4 - num7 * num1 / weaponInertia;
    float num10 = 0.5f * weaponWeight * num8 * num8 + 0.5f * weaponInertia * num9 * num9;
    double num11 = (double) num10;
    double num12 = num6 - num11;
    float num13 = num10 * 0.5f;
    return 0.067f * (float) (num12 + 0.5);
    public static float CalculateStrikeMagnitudeForThrust(
    float thrustWeaponSpeed,
    float weaponWeight,
    float extraLinearSpeed,
    bool isThrown)
    {
    float num = thrustWeaponSpeed + extraLinearSpeed;
    if (!isThrown)
    weaponWeight += 2.5f;
    return 0.125f * (0.5f * weaponWeight * num * num);
    }
    public static float ComputeRawDamageNew(
    DamageTypes damageType,
    float magnitude,
    float armorEffectiveness,
    float absorbedDamageRatio)
    {
    float num1 = 0.0f;
    float factorByDamageType = CombatStatCalculator.GetBluntDamageFactorByDamageType(damageType);
    float num2 = magnitude * factorByDamageType;
    float num3 = (float) (100.0 / (100.0 + (double) armorEffectiveness));
    float num4 = num1 + num2 * num3;
    float num5;
    switch (damageType)
    {
    case DamageTypes.Cut:
    num5 = Math.Max(0.0f, (float) ((double) magnitude * (double) num3 - (double) armorEffectiveness * 0.5));
    break;
    case DamageTypes.Pierce:
    num5 = Math.Max(0.0f, (float) ((double) magnitude * (double) num3 - (double) armorEffectiveness * 0.330000013113022));
    break;
    case DamageTypes.Blunt:
    label_5:
    return num4 * absorbedDamageRatio;
    default:
    return 0.0f;
    }
    num4 += num5 * (1f - factorByDamageType);
    goto label_5;
    }
    private static float GetBluntDamageFactorByDamageType(DamageTypes damageType)
    {
    float num = 0.0f;
    switch (damageType)
    {
    case DamageTypes.Cut:
    num = 0.1f;
    break;
    case DamageTypes.Pierce:
    num = 0.25f;
    break;
    case DamageTypes.Blunt:
    num = 1f;
    break;
    }
    return num;
    }


    That code you're looking at is decompiled, meaning that an algorithm has turned something that isn't human readable into what you're seeing. It's not necessarily what the original code looked like.

    To use another example, consider

    C#:
    public override float GetScoreOfKingdomToGetClan(Kingdom kingdom, Clan clan)
    {
        float num1 = Math.Min(2f, Math.Max(0.33f, (float) (1.0 + 0.0199999995529652 * (double) FactionManager.GetRelationBetweenClans(kingdom.RulingClan, clan))));
        float num2 = (float) (1.0 + (kingdom.Culture == clan.Culture ? 1.0 : 0.0));
        int num3 = clan.CommanderHeroes != null ? clan.CommanderHeroes.Count<Hero>() : 0;
        float num4 = (float) (((double) clan.TotalStrength + 150.0 * (double) num3) * 10.0);
        float powerRatioToEnemies = FactionHelper.GetPowerRatioToEnemies(kingdom);
        float reliabilityConstant = HeroHelper.CalculateReliabilityConstant(clan.Leader, 1f);
        float num5 = 1f / Math.Max(0.4f, Math.Min(2.5f, (float) Math.Sqrt((double) powerRatioToEnemies)));
        float num6 = num4 * num5;
        return (clan.CalculateSettlementValue(kingdom) * 0.1f + num6) * num1 * num2 * reliabilityConstant;
    }

    It's possible that this code is fairly close to what was in the game's original code.

    It's also possible that it actually looked something more like:

    C#:
    public override float GetScoreOfKingdomToGetClan(Kingdom kingdom, Clan clan)
    {
        var numClanHeroes = clan.CommanderHeroes.Count;
        var existingHeroesInKingdom = GetNumberOfHeroesInKingdom(kingdom);
    
        if ((numClanHeroes == 0) ||
            (existingHeroesInKingdom == 0))
        {
            return -1E+08f;
        }
    
        // Start with a basis of 0.
        var valueProposition = 0.0f;
    
        // Add value for the settlements the clan will bring to the kingdom, and the adjusted clan strength.
        // Adjusted clan strength is the clan strength ~ how badly the kingdom needs allies.
        var clanStrength = GetClanStrength(clan, numClanHeroes);
        var powerRatioToEnemies = FactionHelper.GetPowerRatioToEnemies(kingdom);
        var howBadlyDoesThisKingdomNeedSupport = 1f / Clamp(powerRatioToEnemies > 1 ? (float)Math.Sqrt(powerRatioToEnemies) : powerRatioToEnemies, 0.1f, 2.5f);
        var adjustedClanStrength = clanStrength * howBadlyDoesThisKingdomNeedSupport;
        valueProposition += clan.CalculateSettlementValue(kingdom) * 0.1f + adjustedClanStrength;
    
        // Increase the value for happier relations.
        var relationMult = Clamp(1.0f + 0.02f * FactionManager.GetRelationBetweenClans(kingdom.RulingClan, clan), 0.33f, 2f);
        valueProposition *= relationMult;
    
        // Increase the value for the same culture.
        var sameCultureMult = (float)(1.0 + (kingdom.Culture == clan.Culture ? 1.0 : 0.0));
        valueProposition *= sameCultureMult;
    
        // Increase the value if the lord is known to be honorable.
        var reliabilityConstant = HeroHelper.CalculateReliabilityConstant(clan.Leader);
        valueProposition *= reliabilityConstant;
    
        return valueProposition;
    }
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static float Clamp(float value, float min, float max)
    {
        return Math.Min(max, Math.Max(min, value));
    }
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static int GetNumberOfHeroesInKingdom(Kingdom kingdom)
    {
        var numHeroes = 0;
        foreach (var clan in kingdom.Clans)
        {
            if (clan.IsMinorFaction && clan != Clan.PlayerClan)
            {
                continue;
            }
    
            numHeroes += clan.CommanderHeroes.Count;
        }
        return numHeroes;
    }
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static float GetClanStrength(Clan clan, int numClanHeroes)
    {
        return (clan.TotalStrength + 150.0f * numClanHeroes) * 10.0f;
    }

    The decompiled code could have lost variable names, or added new intermediate values. There may be function calls missing because they were inlined. There won't be any comments. The spacing and separation won't look like a human did it.

    Well this looks incredibly bad to me, on top of the fact that it is not easily modifiable. And it is just a small part of the code for damage output calculation in melee. And it is also not balanced, because cutting damage will deal natively less damages than piercing damages because of the wrong formulae they implemented, spears will be overpowered when swung from a horse and so on and so forth.

    This function CalculateStrikeMagnitudeForSwing that you're looking at is actually used by a class called DefaultStrikeMagnitudeModel. While the function isn't immediately modifiable, the class can be entirely replaced. Once you do so, everything else in the game will use your class instead. That is incredibly powerful. It's as easy as creating a new class that inherits from DefaultStrikeMagnitudeModel and overriding whatever methods you want. You could replace the swing calculation, or the thrust calculation, or anything.

    So they decided to "fix" the problem by implementing a multiplier of damages of every blade of the game that you can build in the forge (you can see that in the xml files). If you know how to code, this is INCREDIBLY bad design. I'm really afraid that most of the code is difficult to read, difficult to modify and not balanced at all.

    It is common in game development to write your code in one language (e.g. C++, Java, or C#) and then support reading from a data file at run-time (XML, JSON, other custom text formats) so that you can quickly tweak or iterate on specific numbers, including multipliers.

    It is really good to try to simulate the physical properties of the real world, the economy etc etc but please do that when you have some knowledge in that, not just when you like fiddling around with wrong numbers and terrible simulations... And C# doesn't help by being the most difficult language to read for many reasons, with a really convoluted syntax for many things.

    C# has a syntax much like all other typed languages. It's comparable to Java, C, C++, TypeScript, and others. If you've only used a dynamic language like Python or Lua I can understand why it might be surprising to you.

    This game is not horribly bad, but it looks like they ported the code of warband to a better architecture but they understood that their architecture was actually really bad to make further progress (for example, dialogs with characters are boring and rare, and it is because their system to implement them looks just so wrong...). I must admit that having all the dialogs in one file in warband was much more convenient.

    The architecture of the game engine seems fine to me. I've only made two mods so far but in both cases I was pleasantly surprised by the organization of the code and thought given to decoupling components from each other. It's been very easy to reach in and make changes by swapping out a model or an XML file and the game's care given to the mod-focused architecture is what makes that possible, e.g. the loop that finds game models by searching backwards through the list of all the models grabbed from modules during init, or the use of reflection for the data-binding between the UI schema in XML and the view models in the game.

    I think what's happening here is that for many people this is their first experience with a large, complex codebase. With a dedicated sandbox for game scripting, that complexity is hidden from you. Unfortunately, the only way to hide that complexity is by making assumptions about what modders will want or need for you. One way to avoid that is to "dog-food" your system, meaning to use the system you expose for making mods to make your game. That's what TaleWorlds has done here. The core game is a module loader. The native game is a module. You'll get truly incredible mods from this design.

    It'll get easier to learn as you see more mods demonstrate how to replace or modify different parts of the code.
  6. SP Native Dead Clans Deactivate

    Download https://www.nexusmods.com/mountandblade2bannerlord/mods/438 About This mod changes the clan banners shown in the faction view so that destroyed clans are grey like dead heroes. Compatibility This mod patches the Refresh method on EncyclopediaFactionPageVM to return a subclass of...
  7. Random kingdom war declaration(s) by my own kingdom

    This happens to me as well.
  8. [Bug] Comprehensive and EASY TO READ list of known bugs/issues. Not prioritized in any order.

    This happened to me with a slight variation. The vassal did not bring their fiefs but still left after a brief stint. They also created their own kingdom rather than join their previous kingdom.

    I've made a dedicated thread for this here: https://forums.taleworlds.com/index...tions-can-instantly-recruit-new-lords.410230/
  9. After recruiting a lord in my kingdom he left 5 min after, I don't know why

    This is definitely the reason lol xD
    It's not -- I made another thread about this bug just moments ago because I missed this thread, but I can confirm this will happen with lords of >25 relation as well.


    I also created a bug report specifically for the "lords fleeing to the losing empire" comment you made above.
  10. Recruited lords leave player faction immediately & dying, outnumbered factions can instantly recruit new lords

    I looked for this bug last night and didn't see anything except for a comment or two on some snowball-related reddit threads. I had already made up my mind that I was going to post a bug report about this, and then right before posting, I found this mentioned in Captain Akbar's new list of bugs...
后退
顶部 底部