Quick Modding Questions Thread

Is it possible to have different set of music for eras, like in Civ5? Some track would be played only if you are at war with someone, others only if you are at peace with everyone and the rest can be played in either cases.

Yes. You can do it by creating a number of dummy eras. Create 1 dummy era for the war music playlist and 1 for the peace music playlist in the XML. You can specify the playlist of each dummy era with the <EraInfoSoundtracks> tag in the XML. (You could create a 3rd dummy era for the "combined" playlist, but you could also use the proper era music lists as the default "combined" music playlist)

In CvPlayer.cpp, you will find the EraTypes CvPlayer::getSoundtrackEra() function. This function is used by the game to determine which era should be used to get the playlist from. You can modify this function to return one of the dummy eras to obtained the war music playlist or peace music playlist. See the example below for some pseudocode.

Code:
EraTypes CvPlayer::getSoundtrackEra()
{
    ReligionTypes eStateReligion = getStateReligion();
    EraTypes eCurrentEra = getCurrentEra();
    if atWar:
    {
        return DUMMY_ERA_WAR;
    }
    else if atPeace:
    {
        return DUMMY_ERA_PEACE;
    }
   else: # This else statement is only required if you created a 3rd dummy era. If you modified the music lit
   {
      return DUMMY_ERA_COMBINED;
   }
    return eCurrentEra;
}
}

If you want a unique war, peace and combined playlist for each era, you'll need a 2 dummy eras for each era too.
 
Thanks but is it possible to do it without dummy eras? To my understanding if the game switches to a new era than it cannot switch back to a previous. So if it switches from PEACE to WAR than it cannot switch back to PEACE once the war is over.

And with this approach you don't need a COMBINED era since it always either WAR or PEACE. So some tracks would simply need to be present in both lists.
 
This approach doesn't make you switch era at all. You're actual era remains the classical, medieval or whatever era your are in. Only when trying to determine what playlist it should play, the game gets tricked into thinking you are in a different (dummy) era and it plays the playlist of that dummy era. All other game mechanics still use the proper era.

In DoC this method is used to have unique soundtrack for east asian, south east asian and middle eastern soundtrack.

Spoiler :
Code:
EraTypes CvPlayer::getSoundtrackEra()
{
    ReligionTypes eStateReligion = getStateReligion();
    EraTypes eCurrentEra = getCurrentEra();

    if (eStateReligion == CONFUCIANISM || eStateReligion == TAOISM)
    {
        if (eCurrentEra == ERA_CLASSICAL || eCurrentEra == ERA_MEDIEVAL || eCurrentEra == ERA_RENAISSANCE)
        {
            return (EraTypes)ERA_EAST_ASIA;
        }
    }
    else if (eStateReligion == BUDDHISM || eStateReligion == HINDUISM)
    {
        if (eCurrentEra == ERA_CLASSICAL || eCurrentEra == ERA_MEDIEVAL || eCurrentEra == ERA_RENAISSANCE)
        {
            switch (getCivilizationType())
            {
            case CHINA:
            case MONGOLS:
            case JAPAN:
            case KOREA:
                return (EraTypes)ERA_EAST_ASIA;
            default:
                return (EraTypes)ERA_SOUTH_ASIA;
            }
        }
    }
    else if (eStateReligion == ISLAM || eStateReligion == ZOROASTRIANISM)
    {
        if (eCurrentEra == ERA_MEDIEVAL || eCurrentEra == ERA_RENAISSANCE)
        {
            return (EraTypes)ERA_MIDDLE_EAST;
        }
    }
    else if (eStateReligion == NO_RELIGION)
    {
        if (eCurrentEra == ERA_MEDIEVAL)
        {
            return (EraTypes)ERA_CLASSICAL;
        }
    }

    return eCurrentEra;
}
 
The API does have some functions regarding playing soundtrack. Giving a quick glance what functions are available I think it is possible. But I'm not 100% sure.
 
You are right. I tracked down where it is used, and I found this function. (I double checked and this one is in the vanilla game) You could modify this to create custom playlist depending on being at war or at peace.

Spoiler :
Code:
int CvGame::getNextSoundtrack(EraTypes eLastEra, int iLastSoundtrack) const
{
    // EraTypes eCurEra = GET_PLAYER(getActivePlayer()).getCurrentEra();
    EraTypes eCurEra = GET_PLAYER(getActivePlayer()).getSoundtrackEra();
    CvEraInfo& kCurrentEra = GC.getEraInfo(eCurEra);
    if (kCurrentEra.getNumSoundtracks() == 0)
    {
        return -1;
    }
    else if (kCurrentEra.getNumSoundtracks() == 1 || (eLastEra != eCurEra && kCurrentEra.isFirstSoundtrackFirst()))
    {
        return kCurrentEra.getSoundtracks(0);
    }
    else
    {
        return kCurrentEra.getSoundtracks(GC.getASyncRand().get(kCurrentEra.getNumSoundtracks(), "Pick Song ASYNC"));
    }
}
 
I think the best you can do with Python is play a specific track based on a particular event, but when it completes the game will continue by picking another track based on your current era instead.

Maybe there is an event that fires when a track is about to finish so you can trigger another one with Python, I don't know about that. Even if there is it might turn out kind of patchy because the DLL might start a song and you override it abruptly from Python.
 
Hi, I've been trying to create a new wonder graphic building. Its not quite finished and looks okay as a blender file or object but won't export as a nif file. I got a 136408 value out of bounds message when trying to export. Does anyone know how I can fix this?
The object file is attached.
 

Attachments

  • NifskopeIssue.zip
    711 KB · Views: 31
Hi, I've been trying to create a new wonder graphic building. Its not quite finished and looks okay as a blender file or object but won't export as a nif file. I got a 136408 value out of bounds message when trying to export. Does anyone know how I can fix this?
The object file is attached.
Your model had 15 different materials in blender. Each material in blender with be a separate "trishape" mesh in the nif. So, I deleted them and replaced with a single material.
But, the main thing that was really slowing things down was there was a ton of duplicate vertices. In blender I selected the mesh and did the "removed duplicate vertices" option and there were like 36k. :eek:
So, previously the nif I exported was 2mb in size. Now it is like 12k. :lol:
Altissia? what is that?
 

Attachments

  • NifskopeIssue_MT.rar
    427.8 KB · Views: 30
  • Altissia.jpg
    Altissia.jpg
    16 KB · Views: 234
Thanks @MightyToad. Where in blender would I find the remove duplicate vertices option and how do you delete meshes? (Odds are I’ll have the same issues when I try to create any other models or when I add the remaining details to this one)

Altissia? what is that?
It’s a location in FFXV.

---
Follow up question. I've put in the remaining water and the outer cliffs. Only physical component to add now are the statues.
However, the wrong image is being applied for rendering, seems to be an overlaying of different skins that I had worked on. The image I want used is that in the bottom left, in the preview but the image that is used is that in the top right. How do I correct blender so that it uses just the image from the bottom left for the skinning?
 

Attachments

  • Wrongskin.PNG
    Wrongskin.PNG
    719.7 KB · Views: 36
Last edited:
To remove duplicate vertices:
In Edit Mode Select all Vertices by pressing "A"
I usually press "Spacebar", but you can manually navigate through the "Mesh" tab on the lower taskbar.
Go to "Vertices". Then Select "Remove Doubles".
You could also go to "Faces", and "Convert to triangles". But this is done automatically when you export a nif anyway.
In order to not have 15 different Trishapes in the exported nif you need to assign a single material to the mesh in Blender. So, to start fresh I just deleted all the materials and started over with a new one.
I made a mini tutorial of Screenshots every step of the way. Too many to post. I will attach a ZIP.
As for Question #2:
I don't know why this happens, but visible crap is not removed from "Alpha" areas when you erase them. It is still visible in Blender, and if you don't have an alpha property in your nif. What I do is just create a new blank file in Gimp (create alpha channel and erase everything). Then, in the old file Select "Copy Visible". Then paste that in the new file. Now all the alpha areas will be clean white.
 

Attachments

  • Remove_Doubles_Material.rar
    245.1 KB · Views: 31
  • Gimp_Alphathing.jpg
    Gimp_Alphathing.jpg
    74.9 KB · Views: 217
Has anyone ever tried to active the hotkey/keyboard shortcut for Unit & Building creation ? Maybe a MOD has it activated ?

Seems like firaxis did plan to do that since we have this at the end of the XML UnitInfo and Building Info :
<HotKey/>
<bAltDown>0</bAltDown>
<bShiftDown>0</bShiftDown>
<bCtrlDown>0</bCtrlDown>
<iHotKeyPriority>0</iHotKeyPriority>

But everytime I tried to simply fill it in (for example below, for Worker) :
<HotKey>KB_J</HotKey>
<bAltDown>0</bAltDown>
<bShiftDown>1</bShiftDown>
<bCtrlDown>1</bCtrlDown>

I had no results.
Would love to get a heads up without re-inventing the wheel if it has ever been looked at
 
Hi,

Two completely unrelated queries;

1) In this post,
Spoiler :
There is no way of knowing exactly what you should use without looking at the specific unit's characteristics and running them through the algorithm to build a specific unit AI type, and then doing the same for some other units and comparing the values. Different unit AI types produce values in different ranges and consider different factors.

(To just see a general recommendation for a starting point, the next to last paragraph gives one.)

Example: for the basic Attack unit AI type...
let CV be the land unit's "combat value" - this is based on the unit's strength and the number of first strikes and first strike chances it gets all ultimately divided by the
strength of the strongest land unit that any player has ever built in this game. It is, for a land unit,
CV = 100 * S * (((F * 2) + C) * 5 + 100) / 100 / H
where S is this unit type's combat strength, F is number of first strikes inherent to the unit type (not from promotions), C is number of inherent first strike chances, and H is strength of highest strength land unit ever built by anybody so far in the game. (So it increases the value by 10% per first strike and 5% per first strike chance.) Therefore if this is a unit that has a strength equal to the highest strength unit anyone has ever built so far and no built-in first strikes or chances, then it will get a value of 100. Weaker units will be proportional to that (50 for one half that strong, excluding possible first strike related increases). If the unit being evaluated is stronger than any land unit anyone has ever built so far then it will have a CV over 100. A unit with built-in first strikes and/or chances can also end up over 100 (especially if it has a strength that is equal to, or greater than, any that has been built so far).

the basic UNITAI_ATTACK evaluation gives a value via:
let F be 1 if the AI is not using the "fast movers" strategy type, 2 if it is
let M be number of moves the unit gets
let W be the unit's withdrawal chance
let L be the unit's combat limit

start with Value = 1 + iAIWeight

then via integer math (so all fractions are dropped from each step before applying them), to Value:

add CV
add CV * M * F / 2
add CV * W / 100

then if the unit has a combat limit under 100 (so it can't kill its target, like a catapult),
subtract CV * (125 - L) / 100

For the attack and city attack unit AI types, if the AI is evaluating the unit for an overseas attack and the unit starts with a free promotion that has the amphibious property then its Value is increased by 33% (dropping fractions).

Now you finally have the Value assigned to the unit for the attack type unit AI.

Note that this is the basic preliminary value. The evaluation actually runs through everything it can build twice. The first time to get the highest value, then it reevaluates every unit that is at least 67% of this value and considers additional factors that are the same regardless of the unit AI type being evaluated. All of these additional adjustments but one are multipliers to the base value. These factors include how much XP the unit starts with (+10% per free XP, rounded down), a bonus if the unit type gets one or more free promotions from buildings, another if it gets one or more from its inherent properties, and likewise from civics (working out to +15% per category in which it gets one or more free promotions). Each also gets multiplied by a random factor from 1 to 1.49 (in steps of .01), and also gets a bonus if it can currently be rushed without happy cost or if it can't be rushed with the bonus equal to the production cost already invested in that unit type, a penalty related to how many of that unit type it is already building in its cities, and a penalty if it dies when it attacks (suicide flag set), and finally another factor which depends on whether or not rushing causes unhappiness (or if it can't rush) to determine which of two adjustments to make. As you can see, it is somewhat complex and includes a significant random factor...

When being evaluated for a different unit AI type, the same unit will end up with a different value assigned to it except via coincidence.

So...

If you want a general place to start when picking a value for an iAIWeight, I'd suggest that values under 20 will probably have only a very small effect, if any. Values of iAIWeight around 50 would should have a noticeable effect but not hugely shift the preference, and values up around 100 should have a stronger effect but still allow other units to be built for that unit AI type, at least sometimes, unless perhaps all the unit types in question (those that can be built for the specific unit AI type being evaluated) are a lot weaker than the strongest unit type built so far. Values up over 200 should have a large effect and possibly (for some unit AI types) overwhelm the chances of building anything else for that unit AI type unless some other unit gets more moves or some other bonus (like built-in first strikes) or the unit with iAIWeight bonus gets some penalty the others don't (like not being able to kill its target in the case of the attack unit AI type). But, again, each unit AI type uses a different calculation, some with several more factors than the attack AI uses, and therefore the same iAIWeight may give a large shift when the unit is being considered for one unit AI type and a not so large shift when being considered for some other unit AI type. If you assign a unit an iAIWeight that makes it picked a more often for the city attack unit AI, it might also have the side effect of making it always be picked for the attack unit AI type too.

Perhaps giving an iAIWeight of 50 or so and seeing what effect it has would be a good place to start.

If you want to examine the source code where all this is done, the picking of a unit type for a specific unit AI type is done in CvCityAI::AI_bestUnitAI. The basic value generation of a unit type for a unit AI is done in CvPlayerAI::AI_unitValue.
it refers to an AI using a “fast movers” strategy. Where are these strategies defined? What are the other strategy options? How do I assign such strategies to specific AI players?

2) I’m using several route type (trails, roads, rail, canal). They work fine on most tiles. However, within the cities, the canal is being shown as the default route, even for civs which can not build that route type. Where is it defined which route type is to be used within city graphics? Is it linked to tech or era?
 
2) I’m using several route type (trails, roads, rail, canal). They work fine on most tiles. However, within the cities, the canal is being shown as the default route, even for civs which can not build that route type. Where is it defined which route type is to be used within city graphics? Is it linked to tech or era?

By default, cities use the route type with the highest value that is available to you. The values are defined in RouteInfos.xml (<iValue), so you can change that easily. Availability for routes in cities is determined if you have the required tech or not.

In your case you can lower the value of the canal, which prioritizes the other route types. But that also means that cases where you want canals and a higher valued route type is available it will also use the higher prioritized route.

Each time you discover a new tech that enables a new route type the game triggers the CvPlot::updateCityRoute() function (see 1st spoiler). This function uses the Player.getBestRoute() function (see 2nd spoiler) to determine which route it should use. You can replace this with custom code if you want to force a certain route type instead of the one with the highest value. I recommend not changing the Player.getBestRoute() function itself, because that is also used for other game mechanics you probably do not want to affect.

Spoiler Plot.updateCityRoute() :

Code:
void CvPlot::updateCityRoute(bool bUpdatePlotGroup)
{
    RouteTypes eCityRoute;

    if (isCity())
    {
        FAssertMsg(isOwned(), "isOwned is expected to be true");

        eCityRoute = GET_PLAYER(getOwnerINLINE()).getBestRoute();

        if (eCityRoute == NO_ROUTE)
        {
            eCityRoute = ((RouteTypes)(GC.getDefineINT("INITIAL_CITY_ROUTE_TYPE")));
        }

        setRouteType(eCityRoute, bUpdatePlotGroup);
    }
}


Spoiler Player.getBestRoute() :
Code:
RouteTypes CvPlayer::getBestRoute(CvPlot* pPlot) const
{
    PROFILE_FUNC();

    RouteTypes eRoute;
    RouteTypes eBestRoute;
    int iValue;
    int iBestValue;
    int iI;

    iBestValue = 0;
    eBestRoute = NO_ROUTE;

    for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
    {
        eRoute = ((RouteTypes)(GC.getBuildInfo((BuildTypes)iI).getRoute()));

        if (eRoute != NO_ROUTE)
        {
            if ((pPlot != NULL) ? ((pPlot->getRouteType() == eRoute) || canBuild(pPlot, ((BuildTypes)iI))) : GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getBuildInfo((BuildTypes)iI).getTechPrereq())))
            {
                iValue = GC.getRouteInfo(eRoute).getValue();

                if (iValue > iBestValue)
                {
                    iBestValue = iValue;
                    eBestRoute = eRoute;
                }
            }
        }
    }

    return eBestRoute;
}

This does affect which route type is actually placed on the map, which is normally what determines which route is display. It is possible to have a different route displayed than the actual route, but than you need to edit some other functions. However I think this would be confusing to people. (But it could be nice for cities like Venice)
 
Last edited:
1) In this post, [...] it refers to an AI using a “fast movers” strategy. Where are these strategies defined? What are the other strategy options?
There are bitmasks defined in AI_Defines.h. They date back to the BAI mod for Warlords (SVN revision | explanations by Blake, not covering fast-movers and not necessarily up to date). The CITY_ROLE flags are unused; I guess Blake didn't get around to implementing those. All strategies get updated (at most) once per turn in CvPlayerAI::AI_getStrategyHash. To see how the strategies affect AI behavior, one can only search the AI classes for "AI_STRATEGY_".
How do I assign such strategies to specific AI players?
By changing the conditions/ calculations in AI_getStrategyHash. It would be easy enough to change CvPlayerAI::m_iStrategyHash from other functions, but such changes would get overwritten by the next update in AI_getStrategyHash.
I would like to add the "Field of view" thing for my MOD. [...] It's part of BUG of course, but there are so many mods using it, is there a MODCOMP for it ? I'm not finding it... It would be much easier than reverse engineer in BUG where it was done
I think it's all in CvMainInterface.py, surrounded by comments that say "field of view". (And there's the integration of the option into the BUG menu ...)
 
Hello, I want to add a new "build research" type thing to build in cities. However I couldn't find it anywhere in the XML files.
A nudge in the right direction would be appreciated.
 
@Nanophage, look at CIV4ProcessInfos.xml in XML/GameInfo.

@merijn_v1. Thanks. That sorted it. I made the mistake of defining the build for the route with NONE as the PrereqTech, as the only unit which could use the build had a tech prereq.

@f1rpo. Thanks also. This info will go in my long term things to do list. Reworking the AI is still a bit too intimidating.
 
I think it's all in CvMainInterface.py, surrounded by comments that say "field of view". (And there's the integration of the option into the BUG menu ...)
Finally had time to look again at this and it wasn't as scary as I though.
It is, indeed, all in CvMainInterface.py (perhaps I got confused by BUG's call to it's 'Core' python file) and ended up redoing from scratch double checking how they'd done it at the time.
It's only a clean use of "addSlider"

Thanks for the answer !
 
1) Is there a limit on the number of CityArtStyles that the game will (accurately) use?

Edit: 2) Is there a way to tell which way a river is flowing, i.e. which way to the sea/ocean?
 
Last edited:
Top Bottom