Mod-Modders Guide to Fall Further

I'm stuck working on unt graphics because I cannot find how to keep a nif file the same when importing (either in blender or 3dsmax) and exporting without modifying anything, I always loose information about ATTACHABLES.

Do the art guys have a suggestion as to how to do so (Warkirby? help ...) :) ?

I'm pretty sure it's not possible to maintain that info, but there is an easy workaround.

Get yourself one model, fully premade. With all the attachables and stuff. Then, anything new you make, just copy the new parts and paste them into that template. In essence, have a backup with all the attachables that never changes.

Not sure how relevant this is to your situation, but "nifswapping" is a pretty common practice in general. After changing something, rather than actually using the nif you export, just copy your changed parts back into the original nif, overwriting what you changed, and saving it as a new file.
 
You can do anything to Civics in the DLL. Without that... it'd be tricky/annoying I imagine.

Heh. Figured a way around that - had the civic pass out a promotion to the units once the requirements are met (civic running + technology). Using *only* XML to have effects happen is an exercise in critical thinking for sure, though.
 
I need help for setting some tags in CvTraitInfo::copyNonDefaults().

In Orbis, we have some hugely frightening trait things, like this:
Code:
	pXML->Init2DIntList(&m_ppaiSpecialistCommerceChange, GC.getNumSpecialistInfos(), NUM_COMMERCE_TYPES);
	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"SpecialistCommerceChanges"))
	{
		iNumChildren = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());

		if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"SpecialistCommerceChange"))
		{
			for(j=0;j<iNumChildren;j++)
			{
				pXML->GetChildXmlValByName(szTextVal, "SpecialistType");
				k = pXML->FindInInfoClass(szTextVal);
				if (k > -1)
				{
					// delete the array since it will be reallocated
					SAFE_DELETE_ARRAY(m_ppaiSpecialistCommerceChange[k]);
					if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"CommerceChanges"))
					{
						// call the function that sets the yield change variable
						pXML->SetCommerce(&m_ppaiSpecialistCommerceChange[k]);
						gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
					}
					else
					{
						pXML->InitList(&m_ppaiSpecialistCommerceChange[k], NUM_COMMERCE_TYPES);
					}
				}

				if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
				{
					break;
				}
			}

			// set the current xml node to it's parent node
			gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
		}

		// set the current xml node to it's parent node
		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
And this:
Code:
	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(), "GlobalSeaPlotYieldChanges"))
	{
		pXML->SetYields(&m_paiGlobalSeaPlotYieldChange);
		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
	else
	{
		pXML->InitList(&m_paiGlobalSeaPlotYieldChange, NUM_YIELD_TYPES);
	}
And I don't know at all how I'm supposed to write them in ::copyNonDefaults(). I'm nearly sure I can find some template to copy somewhere but, well, some help would be welcomed anyway :)
 
I'm pretty sure it's not possible to maintain that info, but there is an easy workaround.

Get yourself one model, fully premade. With all the attachables and stuff. Then, anything new you make, just copy the new parts and paste them into that template. In essence, have a backup with all the attachables that never changes.

Not sure how relevant this is to your situation, but "nifswapping" is a pretty common practice in general. After changing something, rather than actually using the nif you export, just copy your changed parts back into the original nif, overwriting what you changed, and saving it as a new file.

Actually I never edited the nif with text editor :) only nifscope.
But I'll give it a try, it seems quite reasonable.

Tears blobby to crystaline on the way !
 
Not sure how relevant this is to your situation, but "nifswapping" is a pretty common practice in general. After changing something, rather than actually using the nif you export, just copy your changed parts back into the original nif, overwriting what you changed, and saving it as a new file.

OK, the nif files do not seem so easy to manipulate. How do you select the "changed parts" to copy back into the original ? Which software are you using (hex editor ?) ?
 
I need help for setting some tags in CvTraitInfo::copyNonDefaults().

In Orbis, we have some hugely frightening trait things, like this:
Code:
    pXML->Init2DIntList(&m_ppaiSpecialistCommerceChange, GC.getNumSpecialistInfos(), NUM_COMMERCE_TYPES);
    if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"SpecialistCommerceChanges"))
    {
        iNumChildren = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());

        if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"SpecialistCommerceChange"))
        {
            for(j=0;j<iNumChildren;j++)
            {
                pXML->GetChildXmlValByName(szTextVal, "SpecialistType");
                k = pXML->FindInInfoClass(szTextVal);
                if (k > -1)
                {
                    // delete the array since it will be reallocated
                    SAFE_DELETE_ARRAY(m_ppaiSpecialistCommerceChange[k]);
                    if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"CommerceChanges"))
                    {
                        // call the function that sets the yield change variable
                        pXML->SetCommerce(&m_ppaiSpecialistCommerceChange[k]);
                        gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
                    }
                    else
                    {
                        pXML->InitList(&m_ppaiSpecialistCommerceChange[k], NUM_COMMERCE_TYPES);
                    }
                }

                if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
                {
                    break;
                }
            }

            // set the current xml node to it's parent node
            gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
        }

        // set the current xml node to it's parent node
        gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
    }
And this:
Code:
    if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(), "GlobalSeaPlotYieldChanges"))
    {
        pXML->SetYields(&m_paiGlobalSeaPlotYieldChange);
        gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
    }
    else
    {
        pXML->InitList(&m_paiGlobalSeaPlotYieldChange, NUM_YIELD_TYPES);
    }
And I don't know at all how I'm supposed to write them in ::copyNonDefaults(). I'm nearly sure I can find some template to copy somewhere but, well, some help would be welcomed anyway :)

I think your example will be in ProjectInfos, I should have set up a double array in that one. Basically though, you just need a nested loop. Loop over SpecialistInfos on iI, and Commerce Types on iJ, and check for non-default values on each item individually.
 
Did the idea of 'aspects' of terrain tiles ever come to fruition? It seems that such a feature would make some of the new spells being thought up much more stable/feasible/genius/modifiable.
 
Looking at the scorpion clan whelp code, as odalrick suggested.


Spoiler :
Code:
if unit.getUnitType() == gc.getInfoTypeForString('UNIT_SCORPION_CLAN_WHELP'):
			pPlot = unit.plot()
			if pPlot.getNumUnits() < 3:
				newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ARCHER_SCORPION_CLAN'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
			else:
				iRiderWeight = 15
				iChariotWeight = 5
				if pPlayer.isHasTech(gc.getInfoTypeForString('TECH_CONSTRUCTION')):
					iChariotWeight += 25
				elif pPlayer.isHasTech(gc.getInfoTypeForString('TECH_HORSEBACK_RIDING')):
					iRiderWeight += 25
				iRnd = CyGame().getSorenRandNum(100, "Goblin Whelp Upgrade")
				if iRnd < iChariotWeight:
					newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_CHARIOT_SCORPION_CLAN'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
				elif iRnd < (iChariotWeight+iRiderWeight):
					newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_WOLF_RIDER_SCORPION_CLAN'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
				else:
					newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_GOBLIN_SCORPION_CLAN'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
			newUnit.convert(unit)
			unit = newUnit

A quick summary of my understanding as to what this should do:
When a whelp is created, it's turned into another unit, archer if there are few units on the tile, otherwise random between some other things.

I don't quite understand how this works, though. Two things are confusing me:

1. The Initunit function.
Code:
newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ARCHER_SCORPION_CLAN'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)

I would make an educated guess, from the parameters that are fed into it, that initunit creates a new unit. But then where does the whelp go? I thought the whelp becomes the new unit.

2. Convertunit
Spoiler :
Code:
newUnit.convert(unit)

We see that unit is defined at the top as the whelp, and newunit is defined through the code as another type of goblin. So it would seem that this converts whatever newunit is, into a whelp

So as far as I can read, what this code does is:

When a whelp is created. Another unit is created on the tile. And then that unit is turned into a whelp. We end up with two whelps.

I know that isn't what it does, so my understanding of it is screwed up somewhere. Can anyone explain ?
 
Also, is there a python method to check whether or not a unit is currently enraged. ie, out of the player's control.

I'm not actually wanting to check for the Enraged promotion, because there are multiple different promotions that have that effect. Rather, I want to check if the unit is under the effect that Enraged, Frenzy, Freelancer, etc, cause.
 
When a whelp is created. Another unit is created on the tile. And then that unit is turned into a whelp. We end up with two whelps.

I know that isn't what it does, so my understanding of it is screwed up somewhere. Can anyone explain ?

A new unit is created that is the kind of unit that you want to convert to, for instance a Goblin Archer.

Then you call newUnit.convert(oldUnit) and the newUnit automatically automatically sucks all relevant information; experience, level, promotions et cetera; from oldUnit and finally kills it.

End result: a new unit that looks like the old unit transformed.
 
Then you call newUnit.convert(oldUnit) and the newUnit automatically automatically sucks all relevant information; experience, level, promotions et cetera; from oldUnit and finally kills it.

Does this information sucking not also include unit type/artgroup ? Are there specific exceptions in there that allow the unit to not become a whelp in the process of doing so?

Is the unit killing a part of the convert function too? I don't see a kill command anywhere there.


Also, does it include the name? or if not, do you know the required python functions to get/set unit names?
People tend to like naming pet units in general, and a druid is quite likely to become that kind of unit...
 
Does this information sucking not also include unit type/artgroup ?

Apparently not, since they don't.;)

Is the unit killing a part of the convert function too? I don't see a kill command anywhere there.

Apparently, since Rubber Duckys are only appear when I've broken something.

Also, does it include the name? or if not, do you know the required python functions to get/set unit names?
People tend to like naming pet units in general, and a druid is quite likely to become that kind of unit...

I guess it includes the name. If it doesn't setName is the method to set the name of a unit. I'll let you guess the method to get name.
 
Whenever a unit changes type, like upgrading warrior to Axeman, this is exactly what happens in the DLL. Make a new unit, convert old unit. Last command in convert kills old unit in a special way that doesn't count as being killed for most purposes.
 
I've been replacing the event manager with my own version and I noticed that several events are dispatched by Fall Further, but not handled by the existing CvEventManager.

The events I noticed are:
combatHit
unitConverted
combatWithdrawal
spellCast
combatBegin
unitUpgraded

There could be more that just didn't trigger in my short test game.

I'm just wondering if there is any more information to be had.
 
Back
Top Bottom