Quick Modding Questions Thread

Hi,

I've recently had to reinstall Civ and its working for the main game but I'm getting errors when I try to start my own mod.

The error message is,
"Assert Failed

File: .\.\CvGlobals.cpp
Line: 3681
Expression: strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
Message: info type hÓ~H†SIîþîþîþîþîþîþîþîþîþîþîþîþÞˆ;£Ý` not found, Current XML file is: xml\Units/CIV4SpellInfos.xml"

Spoiler :
which traces back to
Code:
int CvGlobals::getInfoTypeForString(const char* szType, bool hideAssert) const
   {
   FAssertMsg(szType, "null info type string");
   InfosMap::const_iterator it = m_infosMap.find(szType);
   if (it!=m_infosMap.end())
   {
       return it->second;
   }

   if(!hideAssert)
   {
       CvString szError;
       szError.Format("info type %s not found, Current XML file is: %s", szType, GC.getCurrentXMLFile().GetCString());
       FAssertMsg(strcmp(szType, "NONE")==0 || strcmp(szType, "")==0, szError.c_str());
       gDLL->logMsg("xml.log", szError);
   }

   return -1;
}

How do I find what's triggering this error and fix it?


Edit: Fixed this. Two steps back in the Call Stack, there was a reference to a new GlobalDefinesAlt entry, which had not made it back into the mod folder. There's a subsequent issue but I'll try to solve that one myself before asking for help again.
 
Last edited:
Message: info type hÓ~H†SIîþîþîþîþîþîþîþîþîþîþîþîþÞˆ;£Ý` not found, Current XML file is: xml\Units/CIV4SpellInfos.xml"

I just have to say...that is the best error message I've ever seen. And it's in SpellInfos...LOL :lol:

How does one pronounce hÓ~H†SIîþîþîþîþîþîþîþîþîþîþîþîþÞˆ;£Ý` anyway?
 
I just have to say...that is the best error message I've ever seen. And it's in SpellInfos...LOL :lol:
Spoiler :
mnVws6z.jpg
 
I have added some terrain features for water (Islets and Kelp).
upload_2021-8-30_0-22-25.png


My goal is, that seafood can appear on these tiles too but they don't. Any ideas why?

Here's the code for Fish:
Code:
        <BonusInfo>
            <Type>BONUS_FISH</Type>
            <Description>TXT_KEY_BONUS_FISH</Description>
            <Civilopedia>TXT_KEY_BONUS_FISH_PEDIA</Civilopedia>
            <BonusClassType>BONUSCLASS_GENERAL</BonusClassType>
            <ArtDefineTag>ART_DEF_BONUS_FISH</ArtDefineTag>
            <TechReveal>TECH_FISHING</TechReveal>
            <TechCityTrade>TECH_PRESERVATION</TechCityTrade>
            <TechObsolete>NONE</TechObsolete>
            <YieldChanges>
                <iYieldChange>1</iYieldChange>
                <iYieldChange>0</iYieldChange>
                <iYieldChange>0</iYieldChange>
            </YieldChanges>
            <iAITradeModifier>0</iAITradeModifier>
            <iAIObjective>0</iAIObjective>
            <iHealth>1</iHealth>
            <iHappiness>0</iHappiness>
            <iPlacementOrder>6</iPlacementOrder>
            <iConstAppearance>50</iConstAppearance>
            <iMinAreaSize>10</iMinAreaSize>
            <iMinLatitude>0</iMinLatitude>
            <iMaxLatitude>80</iMaxLatitude>
            <Rands>
                <iRandApp1>25</iRandApp1>
                <iRandApp2>25</iRandApp2>
                <iRandApp3>0</iRandApp3>
                <iRandApp4>0</iRandApp4>
            </Rands>
            <iPlayer>0</iPlayer>
            <iTilesPer>64</iTilesPer>
            <iMinLandPercent>0</iMinLandPercent>
            <iUnique>1</iUnique>
            <iGroupRange>0</iGroupRange>
            <iGroupRand>0</iGroupRand>
            <bArea>0</bArea>
            <bHills>0</bHills>
            <bFlatlands>0</bFlatlands>
            <bNoRiverSide>0</bNoRiverSide>
            <bNormalize>0</bNormalize>
            <TerrainBooleans>
                <TerrainBoolean>
                    <TerrainType>TERRAIN_COAST</TerrainType>
                    <bTerrain>1</bTerrain>
                </TerrainBoolean>
                <TerrainBoolean>
                    <TerrainType>TERRAIN_OCEAN</TerrainType>
                    <bTerrain>1</bTerrain>
                </TerrainBoolean>
            </TerrainBooleans>
            <FeatureBooleans>
                <FeatureBoolean>
                    <FeatureType>FEATURE_STORM</FeatureType>
                    <bFeature>1</bFeature>
                </FeatureBoolean>
                <FeatureBoolean>
                    <FeatureType>FEATURE_KELP</FeatureType>
                    <bFeature>1</bFeature>
                </FeatureBoolean>
                <FeatureBoolean>
                    <FeatureType>FEATURE_ISLAND</FeatureType>
                    <bFeature>1</bFeature>
                </FeatureBoolean>
                <FeatureBoolean>
                    <FeatureType>FEATURE_ISLAND_NORTH</FeatureType>
                    <bFeature>1</bFeature>
                </FeatureBoolean>
            </FeatureBooleans>
            <FeatureTerrainBooleans>
                <FeatureTerrainBoolean>
                    <TerrainType>TERRAIN_COAST</TerrainType>
                    <bFeatureTerrain>1</bFeatureTerrain>
                </FeatureTerrainBoolean>
                <FeatureTerrainBoolean>
                    <TerrainType>TERRAIN_OCEAN</TerrainType>
                    <bFeatureTerrain>1</bFeatureTerrain>
                </FeatureTerrainBoolean>
            </FeatureTerrainBooleans>
                </BonusInfo>
 
Anyone knows where the flags are called? I mean I found ART_UNITGROUP_FLAG_ANCIENT in CIV4ArtDefines_Misc.
And there is a Space_Flag in Final Frontier. How could I add that for the Future era?
 
Hi,

@hrochland has created the Crannog graphic. I've now discovered that LSYSTEM_WATER and LSYSTEM_LIGHTHOUSE don't seem to work for displaying a graphic in a lake.
The art ref is
Spoiler :
Code:
       <ArtRef Name="building:LSYSTEM_LIGHTHOUSE">
           <Attribute Class="Era">ERA_ANCIENT,ERA_CLASSICAL,ERA_MEDIEVAL,ERA_COUN,ERA_ORDE,ERA_RUNE,ERA_EMPY,ERA_VEIL,ERA_LEAF,ERA_OCTO</Attribute>
           <Attribute Class="Scalar">bNoWaterTest:1</Attribute>
           <!-- this bypasses water testing -->
           <Attribute Class="Scalar">szSpecialLayout:Water</Attribute>
           <Scale>1.5</Scale>
       </ArtRef>
       <ArtRef Name="building:LSYSTEM_WATER">
           <Attribute Class="Scalar">bNoWaterTest:1</Attribute>
           <!-- this bypasses water testing -->
           <Attribute Class="Scalar">szSpecialLayout:Water</Attribute>
           <Scale>1.0</Scale>
       </ArtRef>
How would I go about making these LSYSTEMs work in lakes also and/or create a new LSYSTEM specifically for lake buildings?

Edit: One workaround fix to give the graphic would be to use python to create an IMPROVEMENT_CRANNOG on an adjacent lake tile when the crannog building is built. Is there a neater way to do it using LSYSTEM?
 
Last edited:
Hey guys, am hoping an easy one for you...

On the top left of my main interface screen, I've put a couple of 'StackedBarGFC' (one is a rework of "Faith" of Platyping, and the other is the relatively common GP Bar),
I would like to be able to click the GP Bar and being sent directly to (inside) the city that will produce the next GP

I would have though it's easy, since I know how to use 'def handleinput' for my custom button,
But it's not working and am not quite sure why...

- is it simply not possible with a 'StackedBarGFC' or am making a mistake ? It has to be handled somewhere else than in def handleInput (self, inputClass) of CvMainInterface ?
- While we're at it... what would be the command to open the city directly ?


My top-left, gets in yellow when you hoover on it as you would think

Screenshot 2021-10-07 21.26.05.png



Code:
def handleInput (self, inputClass):

This work, with my button "CivSelectedButton" opens the right menu
Code:
  elif(inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED and inputClass.getFunctionName() == "CivSelectedButton"):
            CivSelected.CivSelectedDisplay().interfaceScreen()
            return 11

This doesn't work, I tried combination of name for my bar ("MainGPBar","MainGPBar13" etc.)
Code:
        #2.237 - Not working
        if(inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED and inputClass.getFunctionName() == "MainGPBar"):
            CivSelected.CivSelectedDisplay().interfaceScreen()
            return 13

I can send more details/code but I don't want to overwhelm the topic with it!

Thanks a ton !



EDIT - Mea Culpa it "somehow" works --> it works if I click SLIGHTY RIGHT of the text... am not quite sure how to handle this... if any ideas
 
Last edited:
Ok I found that !

I change the question to what I hinted as second question :

- How to I ask to zoom in a (given) city ?
- How do I open one of the BTS/normal adviser ?

I though this would do, but it throws error, as if not entering by 'the front door'

Code:
        if(inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED and inputClass.getFunctionName() == "FaithBar"):
            CvReligionScreen.CvReligionScreen().interfaceScreen()
            return 15
It does open the CvReligionScreen but it also gives pythons error because not all the __init__ part is ran.
 
Is there a way to randomly place terrain features on the map? I have added Fog and Sandstorm and I'd like if they are randomly placed on tundra and desert tiles.
I was thinking about events but that will always pick a player, right?
 
Is there a way to randomly place terrain features on the map? I have added Fog and Sandstorm and I'd like if they are randomly placed on tundra and desert tiles.
I was thinking about events but that will always pick a player, right?

Easiest way is to do in the mapscript(s) itself/themselves ?

if you know the order of functions triggered by mapscripts (https://forums.civfanatics.com/threads/the-map-building-process.353005/#post-8884459)
you can very easily call a dedicated logic for that kind of things in the last step (def startHumansOnSameTile()) and launch it from there, at the end of the generation.

If you find it cumbersome to change all the mapscript, and are sure you want to force this on each map;
Then you can create a new function in the C++ as part of the mapscript process, which starts at the end of the process, doing this for you.
For cleanliness I would do a callback to the maps themselves to check if you have a flag NOT to do this process in a new dedicated function but you may find it superfluous for your mod.
 
Easiest way is to do in the mapscript(s) itself/themselves ?

if you know the order of functions triggered by mapscripts (https://forums.civfanatics.com/threads/the-map-building-process.353005/#post-8884459)
you can very easily call a dedicated logic for that kind of things in the last step (def startHumansOnSameTile()) and launch it from there, at the end of the generation.

If you find it cumbersome to change all the mapscript, and are sure you want to force this on each map;
Then you can create a new function in the C++ as part of the mapscript process, which starts at the end of the process, doing this for you.
For cleanliness I would do a callback to the maps themselves to check if you have a flag NOT to do this process in a new dedicated function but you may find it superfluous for your mod.
Okay... First, thanks for the answer :)
Sorry, I wasn't clear enough.

The game can place these feature at the START of the game but that's not what I want.
I want them to appear DURING the game and little later disappear - for that there is an XML tag: <iDisappearance>
I tried using <iGrowth> tag but 1) it spreads only to neighboring tiles and 2) it's impossible to find a right balance between <iGrowth> and <iDisappearance> ; the map either gets spammed with the feature or they all disappear.
 
Okay... First, thanks for the answer :)
Sorry, I wasn't clear enough.

The game can place these feature at the START of the game but that's not what I want.
I want them to appear DURING the game and little later disappear - for that there is an XML tag: <iDisappearance>
I tried using <iGrowth> tag but 1) it spreads only to neighboring tiles and 2) it's impossible to find a right balance between <iGrowth> and <iDisappearance> ; the map either gets spammed with the feature or they all disappear.

Ah gotcha!

As much as I usually prefer to do in SDK when I can, this one screams python to me :
in CvEventManager add code in 'onBeginGameTurn' ?

Throw two dice, if first one is <10 (10%) new Storm, is second <50 (50%) stop current storm
Then you loop all map plots shuffle them etc to add it (or remove it).
Might be a bit taxing perf-wise to run each time but you only run the loops if you're in the odds of event happening.
 
Ah gotcha!

As much as I usually prefer to do in SDK when I can, this one screams python to me :
in CvEventManager add code in 'onBeginGameTurn' ?

Throw two dice, if first one is <10 (10%) new Storm, is second <50 (50%) stop current storm
Then you loop all map plots shuffle them etc to add it (or remove it).
Might be a bit taxing perf-wise to run each time but you only run the loops if you're in the odds of event happening.
I can merge some things in python but I'm not a programer. So do you know of any particular code or modcomp that is similar?
And placing it is enough. To remove the feature there is an XML tag as I mentioned above.
 
I can merge some things in python but I'm not a programer. So do you know of any particular code or modcomp that is similar?
And placing it is enough. To remove the feature there is an XML tag as I mentioned above.

I have/had a python erorr when I prepared this for you but it works.
It's very basic and I don't like the idea of looping all plots of the map every begin turn but is definitely the quickest to code :

Code:
    def onBeginGameTurn(self, argsList):
        'Called at the beginning of the end of each turn'
        iGameTurn = argsList[0]
        CvTopCivs.CvTopCivs().turnChecker(iGameTurn)
      
        iDesert = gc.getInfoTypeForString("TERRAIN_DESERT")
        iPalm = gc.getInfoTypeForString("FEATURE_PALM_FOREST")
        for x in range(CyMap().getGridWidth()):
            for y in range(CyMap().getGridHeight()):
                p = CyMap().plot(x,y)   
                if p.getTerrainType() == iDesert:
                    iProba = CyGlobalContext().getGame().getMapRandNum(100,"iProba")
                    if p.getFeatureType() == -1 and iProba <= 20:
                        p.setFeatureType(iPalm, 0)
                    if p.getFeatureType() == iPalm and iProba <= 50:
                        p.setFeatureType(-1, -1)
The example is with my Feature the "Palm Forest", obviously you need to put your feature instead there
 
I have/had a python erorr when I prepared this for you but it works.
It's very basic and I don't like the idea of looping all plots of the map every begin turn but is definitely the quickest to code :

Code:
    def onBeginGameTurn(self, argsList):
        'Called at the beginning of the end of each turn'
        iGameTurn = argsList[0]
        CvTopCivs.CvTopCivs().turnChecker(iGameTurn)
   
        iDesert = gc.getInfoTypeForString("TERRAIN_DESERT")
        iPalm = gc.getInfoTypeForString("FEATURE_PALM_FOREST")
        for x in range(CyMap().getGridWidth()):
            for y in range(CyMap().getGridHeight()):
                p = CyMap().plot(x,y)
                if p.getTerrainType() == iDesert:
                    iProba = CyGlobalContext().getGame().getMapRandNum(100,"iProba")
                    if p.getFeatureType() == -1 and iProba <= 20:
                        p.setFeatureType(iPalm, 0)
                    if p.getFeatureType() == iPalm and iProba <= 50:
                        p.setFeatureType(-1, -1)
The example is with my Feature the "Palm Forest", obviously you need to put your feature instead there
Thank you!
I haven't tried it yet but I think I have found the part in the sourcecode that is responsible for dynamic storms:
Code:
#ifdef MULTI_FEATURE_MOD
    for (int i=(int)m_aFeatures.size()-1; i>=0; i--)
    {
        iProbability = GC.getFeatureInfo(m_aFeatures[i].eFeature).getDisappearanceProbability();

        if (iProbability > 0)
        {
            int iOdds = (10000*GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getVictoryDelayPercent())/100;
            if (GC.getGameINLINE().getSorenRandNum(iOdds, "Feature Disappearance") < iProbability)
            {
                setHasFeature(m_aFeatures[i].eFeature, false);
            }
        }
    }
    int iStorm = GC.getInfoTypeForString("FEATURE_STORM", true);
    bool bNoStorms = GC.getGameINLINE().isModderGameOption(MODDERGAMEOPTION_NO_STORMS);
      
    for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
    {
        CvFeatureInfo& kFeature = GC.getFeatureInfo((FeatureTypes)iI);
        if ((kFeature.getGrowthProbability() > 0 && !isUnit()) || kFeature.getSpreadProbability() > 0)
        {
            if (getImprovementType() == NO_IMPROVEMENT || (kFeature.isCanGrowAnywhere() && !isBeingWorked() && !isWater()))
            {
                if (!((iStorm == iI) && bNoStorms))
                {
                    if (canHaveFeature((FeatureTypes)iI, kFeature.getSpreadProbability() > 0))
                    {
                        if ((getBonusType() == NO_BONUS) || (GC.getBonusInfo(getBonusType()).isFeature(iI)) || kFeature.getSpreadProbability() > 0)
                        {
                            iProbability = kFeature.isCanGrowAnywhere() ? kFeature.getGrowthProbability() : 0;

                            for (iJ = 0; iJ < NUM_CARDINALDIRECTION_TYPES; iJ++)
                            {
                                pLoopPlot = plotCardinalDirection(getX_INLINE(), getY_INLINE(), ((CardinalDirectionTypes)iJ));

                                if (pLoopPlot != NULL)
                                {
                                    if (pLoopPlot->getHasFeature((FeatureTypes)iI))
                                    {
                                        if (pLoopPlot->getImprovementType() == NO_IMPROVEMENT)
                                        {
                                            iProbability += kFeature.getGrowthProbability();
                                        }
                                        else
                                        {
                                            iProbability += GC.getImprovementInfo(pLoopPlot->getImprovementType()).getFeatureGrowthProbability();
                                        }
                                        iProbability += kFeature.getSpreadProbability();
                                    }
                                }
                            }

                            iProbability *= std::max(0, (GC.getFEATURE_GROWTH_MODIFIER() + 100));
                            iProbability /= 100;

                            if (isRoute())
                            {
                                iProbability *= std::max(0, (GC.getROUTE_FEATURE_GROWTH_MODIFIER() + 100));
                                iProbability /= 100;
                            }

                            if (iProbability > 0)
                            {
                                int iOdds = (10000*GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getVictoryDelayPercent())/100;
                                if (GC.getGameINLINE().getSorenRandNum(iOdds, "Feature Growth 1") < iProbability)
                                {
                                    // Grow river and tile art only as main feature
                                    if (!kFeature.canBeSecondary())
                                    {
                                        setFeatureType((FeatureTypes)iI);
                                    }
                                    else
                                    {
                                        setHasFeature((FeatureTypes)iI, true);
                                    }
                                    strcpy(szSound, kFeature.getGrowthSound());
                                    pCity = GC.getMapINLINE().findCity(getX_INLINE(), getY_INLINE(), getOwnerINLINE(), NO_TEAM, false);

                                    if (pCity != NULL && isInViewport())
                                    {
                                        MEMORY_TRACK_EXEMPT();

                                        // Tell the owner of this city.
                                        if (iI == iStorm)
                                        {
                                            szBuffer = gDLL->getText("TXT_KEY_MISC_STORM_GROWN_NEAR_CITY", pCity->getNameKey());
                                        }
                                        else
                                        {
                                            szBuffer = gDLL->getText("TXT_KEY_MISC_FEATURE_GROWN_NEAR_CITY", kFeature.getTextKeyWide(), pCity->getNameKey());
                                        }
                                      
                                        AddDLLMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, szSound, MESSAGE_TYPE_INFO, kFeature.getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), getX_INLINE(), getY_INLINE(), true, true);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
#else
    if (getFeatureType() != NO_FEATURE)
    {
        iProbability = GC.getFeatureInfo(getFeatureType()).getDisappearanceProbability();

        if (iProbability > 0)
        {

Code:
        int iStorm = GC.getInfoTypeForString("FEATURE_STORM", true);
        bool bNoStorms = GC.getGameINLINE().isModderGameOption(MODDERGAMEOPTION_NO_STORMS);
      
        for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
        {
            CvFeatureInfo& kFeature = GC.getFeatureInfo((FeatureTypes)iI);
            if ((kFeature.getGrowthProbability() > 0 && !isUnit()) || kFeature.getSpreadProbability() > 0)
            {
                if (getImprovementType() == NO_IMPROVEMENT || (kFeature.isCanGrowAnywhere() && !isBeingWorked() && !isWater()))
                {
                    if (!((iStorm == iI) && bNoStorms))
                    {
                        if (canHaveFeature((FeatureTypes)iI, kFeature.getSpreadProbability() > 0))
                        {
                            if ((getBonusType() == NO_BONUS) || (GC.getBonusInfo(getBonusType()).isFeature(iI)) || kFeature.getSpreadProbability() > 0)
                            {
                                iProbability = kFeature.isCanGrowAnywhere() ? kFeature.getGrowthProbability() : 0;

                                for (iJ = 0; iJ < NUM_CARDINALDIRECTION_TYPES; iJ++)
                                {
                                    pLoopPlot = plotCardinalDirection(getX_INLINE(), getY_INLINE(), ((CardinalDirectionTypes)iJ));

                                    if (pLoopPlot != NULL)
                                    {
                                        if (pLoopPlot->getFeatureType() == ((FeatureTypes)iI))
                                        {
                                            if (pLoopPlot->getImprovementType() == NO_IMPROVEMENT)
                                            {
                                                iProbability += kFeature.getGrowthProbability();
                                            }
                                            else
                                            {
                                                iProbability += GC.getImprovementInfo(pLoopPlot->getImprovementType()).getFeatureGrowthProbability();
                                            }
                                            iProbability += kFeature.getSpreadProbability();
                                        }
                                    }
                                }

                                iProbability *= std::max(0, (GC.getFEATURE_GROWTH_MODIFIER() + 100));
                                iProbability /= 100;

                                if (isRoute())
                                {
                                    iProbability *= std::max(0, (GC.getROUTE_FEATURE_GROWTH_MODIFIER() + 100));
                                    iProbability /= 100;
                                }

                                if (iProbability > 0)
                                {
                                    int iOdds = (10000*GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getVictoryDelayPercent())/100;
                                    if (GC.getGameINLINE().getSorenRandNum(iOdds, "Feature Growth 2") < iProbability)
                                    {
                                        setFeatureType((FeatureTypes)iI);
                                        strcpy(szSound, kFeature.getGrowthSound());
                                        pCity = GC.getMapINLINE().findCity(getX_INLINE(), getY_INLINE(), getOwnerINLINE(), NO_TEAM, false);
                                        //if (GC.getGameINLINE().getElapsedGameTurns() > 1)
                                        //{
                                            /*if (kFeature.isCanGrowAnywhere() && getImprovementType() != NO_IMPROVEMENT && !isWater())
                                            {
                                                setOvergrown(true);
                                                if (pCity != NULL)
                                                {
                                                    szBuffer = gDLL->getText("TXT_KEY_MISC_FEATURE_OVERGROWN_NEAR_CITY", kFeature.getTextKeyWide(), GC.getImprovementInfo(getImprovementType()).getTextKeyWide(), pCity->getNameKey());
                                                    AddDLLMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, szSound, MESSAGE_TYPE_INFO, kFeature.getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), getX_INLINE(), getY_INLINE(), true, true);
                                                }
                                            }*/
                                        //}

                                        if (pCity != NULL && isInViewport())
                                        {
                                            MEMORY_TRACK_EXEMPT();

                                            // Tell the owner of this city.
                                            if (iI == iStorm)
                                            {
                                                szBuffer = gDLL->getText("TXT_KEY_MISC_STORM_GROWN_NEAR_CITY", pCity->getNameKey());
                                            }
                                            else
                                            {
                                                szBuffer = gDLL->getText("TXT_KEY_MISC_FEATURE_GROWN_NEAR_CITY", kFeature.getTextKeyWide(), pCity->getNameKey());
                                            }
                                          
                                            AddDLLMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, szSound, MESSAGE_TYPE_INFO, kFeature.getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), getViewportX(),getViewportY(), true, true);
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
#endif
}
Do you think you could rewrite it and add the 2 features I need?
FEATURE_SANDSTORM should appear on TERRAIN_DESERT
and FEATURE_FOG on TERRAIN_TUNDRA and TERRAIN_SNOW.
 

Attachments

Last edited:
Hey,

So I am/was a bit confused what that was and what you actually want(ed).

This is obviously not BTS code since it already refers to the feature storm (hardcoded), I presume its a dedicated mod which has this feature and is building on the code of forest growth and spreading.

You can't edit the python nor the SDK yourself but you're in a position to copy chunks of C++ and compile the dll yourself ? (Asking because it's no use looking at the SDK if you cannot).

The code is very thorough and takes into account all possibilities and everything you can think off (if my assumption above is correct it's firaxis'), still, if what you dislike is the fact that it's SPREADING in cardinal direction rather than popping up randomly, I think it make sense to start code for that from scratch.
You could EXCLUDE storms from spreading (exclude them from the loops above, or remove the specific code, or changing the xml back to 0 for everything). Then you write something specific just for storm, either just below that code in C++, either in python like I did.

Is there a shortcoming to what I wrote for you ? What does it NOT do that you want it to do ?
Presumably if you use 20% and 50% like I did, you'll have 30% of tiles with storm at all times. I'd chose 2% and 50% for good balance
 
Last edited:
So I am/was a bit confused what that was and what you actually want(ed).
Sorry about that :blush:
This is obviously not BTS code since it already refers to the feature storm (hardcoded), I presume its a dedicated mod which has this feature and is building on the code of forest growth and spreading.
Yes, I'm modding AND2.
You can't edit the python nor the SDK yourself but you're in a position to copy chunks of C++ and compile the dll yourself ? (Asking because it's no use looking at the SDK if you cannot).
Well, I can do some python merging but only basic. I cannot do any dll work - other than trying to find out what certain things may mean - but I know who to ask to merge it. At least I can ask him. Boy, I know it sounds complicated :sad:
The code is very thorough and takes into account all possibilities and everything you can think off (if my assumption above is correct it's firaxis'), still, if what you dislike is the fact that it's SPREADING in cardinal direction rather than popping up randomly, I think it make sense to start code for that from scratch.
You could EXCLUDE storms from spreading (exclude them from the loops above, or remove the specific code, or changing the xml back to 0 for everything). Then you write something specific just for storm, either just below that code in C++, either in python like I did.

Is there a shortcoming to what I wrote for you ? What does it NOT do that you want it to do ?
Presumably if you use 20% and 50% like I did, you'll have 30% of tiles with storm at all times. I'd chose 2% and 50% for good balance
Sorry, I didn't want to look thankless. I really appreciate your work, you just said that you prefer to do things in the dll, so I thought of making a search for
FEATURE_STORM. I found this and though it could help.
But I will try your python code. I am really grateful for your help. Thank you! :hatsoff:
 
Hi,

I'm considering trying to create a Chand Baori type tile improvement. As this is a step well, the graphic should be going deeper than the level of the terrain. Has anyone used a (partially) transparent terrain type in any mod to allow for visibility of an improvement which goes below the ground?
Is it feasible to have a transparent terrain type or will this just look messed up where the tile graphic has to blend with adjacent tiles?
Otherwise, could a partially transparent terrain work, i.e. like a desert terrain but transparent in the centre, where the improvement would be placed? Would this allow for an improvement, which goes below the usual surface of the tile to be visible, while keeping a working edge with the bordering tiles?
If creating such a new terrain type, are these the three new dds that would need to be created or would only one need to be changed to create the transparent area?
<Path>Art/Terrain/Textures/DesertHollowBlend.dds</Path>
<Grid>Art/Terrain/Textures/DesertHollowGrids.dds</Grid>
<Detail>Art/Terrain/Textures/DesertHollowDetail.dds</Detail>

Has someone created such deep improvements before and come up with an effective way to represent them, without messing with the terrain art?
 

Attachments

  • 1.jpg
    1.jpg
    47.8 KB · Views: 27
terrain_alpha.jpg


I erased a hole in the grassblend texture to see if you could see the improvement below. Yes, looks like that will work.

Ignoring how difficult it would be to get the hole right; What if the improvement isn't present? You would have to have some code somewhere that will use the normal texture, then switch to the one with the hole when the improvement is built. Or, just have this well a feature like the oasis. :think:

Has someone created such deep improvements before and come up with an effective way to represent them, without messing with the terrain art?
I think messing with terrain art probably isn't necessary. You only need to achieve the illusion of depth. You could have 50% of the model above the ground level, and only 2D art texture to represent the rest.
 
Back
Top Bottom