Modders Guide to FfH2

Ok, this one is probably going out to Cephalo mostly, might need Mapscript knowledge.


The Tectonic's Mapscript creates your maps by seeding a couple of continents, then moving them around and causing Mountain Ranges where they collide, and occasionally breaking islands off of a main continent.

How possible do you all think that it would be to bring these pre-game, raw number functions into the game?


What I am picturing, is re-write the Kilmorph Constelation to break an island off of the largest landmass in the game (no terrain destroyed, just chooses a chunk to move out into the water a distance. Then you also re-write the Danalin Constellation to grab the smallest island in the game and smack it up against the nearest continent. Again, no land tiles destroyed, but some ocean tiles will be turned into Peaks to show the tectonic activity of intersecting landmasses.

I think that there is some VERY serious enjoyment from something like this. Obviously there would be a minimum requirement for percent of the map which is water tiles (ie - won't trigger on a Lakes map, but could trigger on Pangea type maps with high water level).
 
Edit: ok, I had the worldbuilder problem again. Then I closed the program and restarted it, and the problem was gone again.

Awhile ago I was having a problem that sounds similar to yours. It was solved by reinstalling Civ4. I'm pretty sure it wasn't caused by any mods, too. I just had the odd WB behavior, not CTDs, but maybe there's just something wonky with your Civ install.
 
So, making Hidden Nationality non-aggressive in cities did indeed cause a WoC issue (thank you AutoPlay!). I am looking over how to fix the WoC, but keep the non-aggressiveness, since it MUST work somehow, being as the native isAlwaysHostile tag works... This would imply that somewhere it is checking UnitInfo, instead of Unit, for the Always Hostile Tag, and that somewhere is what fixes the issue.


Some questions which pops up:

in CvPlayerAI.cpp:
Code:
		case UNITAI_PIRATE_SEA:
			[COLOR="Red"]if (GC.getUnitInfo(eUnit).isAlwaysHostile() && GC.getUnitInfo(eUnit).isHiddenNationality())[/COLOR]
			{
				bValid = true;
			}
			break;

Shouldn't this be an OR statement, instead of AND?

Code:
	case UNITAI_EXPLORE_SEA:
		{
			int iExploreValue = 100;
			if (pArea != NULL)
			{
			if (pArea->isWater())
			{
				if (pArea->getUnitsPerPlayer(BARBARIAN_PLAYER) > 0)
				{
					iExploreValue += (2 * iCombatValue);
				}
			}
			}
			iValue += (GC.getUnitInfo(eUnit).getMoves() * iExploreValue);
			[COLOR="#ff0000"]if (GC.getUnitInfo(eUnit).isAlwaysHostile())[/COLOR]
			{
				iValue /= 2;
			}
		iValue /= (1 + AI_unitImpassableCount(eUnit));
		}
		break;

Ought to include Hidden Nationality in here as well.


Unfortunately those are the only two blips which come up for me looking at the Always Hostile code. Everything else is called to the Unit, and adjusting how HN was handled in there did no good.

If something was added to the AI when it selected targets though to account for not having HN units attempt to attack anything in a city, it might do the trick. But that is a big might.
 
032e with no changes to the dll claims that:

Code:
AttributeError: 'CyGame' object has no attribute 'getTrueGlobalCounter'

But the front page of this thread indicates it should be available, and Vehem has it working in Fall Further...
 
032e with no changes to the dll claims that:

Code:
AttributeError: 'CyGame' object has no attribute 'getTrueGlobalCounter'

But the front page of this thread indicates it should be available, and Vehem has it working in Fall Further...

The functions in the first thread are CvGame functions (as listed), not CyGame functions. I dont carry anything into Python unless its needed.
 
Was it there in earlier version?

I was just merging (while I was writting this it finished compiling, but I haven't tested it yet) the DLLs of Fall Further (well, the parts I want in my modmod, which is mostly Broader Alignments), xienwolf's xml modcomp, and UnitStats and I ran in to the error where it could find getTrueGlobalCounter. I had overlooked adding it because it was in the middle of a section of code you added, with no comments saying that it was Vehem's work.
 
Python question:

I added this to onCityAcquired in EventsManager

Code:
if gc.getPlayer(pCity.getOwner()).getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SCIONS'):
	iBCPop = pCity.getPopulation()
	iBCMod = iBCPop / 2
	pCity.changePopulation(-iBCMod)

It does what I want it to do - if a Civilization_Scions unit captures a city the population is halved (that's after the usual -1.)

However, it only seems to work with "/ 2" for iBCPop.
For example "iBCPop * 0.67" (or "* 2 / 3") doesn't work. Any idea why?
 
How large of a population did you try? It might be a simple rounding issue.


setPopulation might work better, since then you are dealing with the larger portion of the fraction. Not sure if that is exposed to Python though.


Create a city with a population of 61 and test each of them under that capture. Should be notably different.


If you mean just plain doesn't work at all, make sure that you use (parenthetical statements) excessively to ensure that the operations are done in the order that you want them done in.
 
How large of a population did you try? It might be a simple rounding issue.

40.
I just tried it again and checked something:
"* 0.5" and "* .5" don't work either - the city loses the normal 1 point of pop... but "/ 2" still works.

/ 3 works.
/ 1.5 doesn't.
/ (3/2) results in 0 population - as does (iBCPop / (3/2))

Maybe the 0.5 in 3/2 is dropped... but iBCPop / 1.5 seems to result in a 0, if it's being used at all.

There is no smilie that conveys my degree of bafflement.

setPopulation might work better, since then you are dealing with the larger portion of the fraction. Not sure if that is exposed to Python though.

setPopulation can be used, though I might run into similar math errors. IIRC, though, it worked OK and the problem was my function to keep the population > 0. But maybe that's the only way to make it work.


If you mean just plain doesn't work at all, make sure that you use (parenthetical statements) excessively

That's good to hear, too. I was using () excessively elsewhere and wondered if that was messing things up.


Thanks!
 
Multiply the population by 100, do your calculations, then divide the end result by 100.

Yay! That worked - I multiplied getPopulation by 10 and divided by 15 rather than 1.5.

"Yay!" again.

That explains some problems elsewhere I'd attributed to my general ignorance of python. And
I'll see about applying the "cheat" to the Scions' Awakened spawning - it's currently over 70 lines long and I'm far from sure about what it's _really_ doing.

Thanks!
 
Well, I'm using Codeblocks, I normally just do a Final Release, but this time I targetted a Debug. My options are All, Debug, Release, Release FxsMemory, Debug FxsMemory, and Final Release.

Without the msvcprtd.lib, I go through every file in the debug dll, then it states that it is missing that file. If I place the Lib in the same folder as all my cpp & h files, I get a funky hige error about a bunch of strings involving python being missing. Same if I place it in the 2003 files, or the SDK Toolkit files, or the Python or Boost folders included with the DLL source.
 
Does anyone have an idea why miscastchances > 0 ALLWAYS miscast? The code looks like a normal sorenrand with a range of 100 but even miscastchances of 5 allways miscast so something seems to be bugged here.:confused:

Hmm.. it looks like its because I didnt put the break inside the check. Right now its:

Code:
    int iMiscastChance = GC.getSpellInfo((SpellTypes)spell).getMiscastChance() + m_pUnitInfo->getMiscastChance();
    if (iMiscastChance > 0)
    {
        if (GC.getGameINLINE().getSorenRandNum(100, "Miscast") < iMiscastChance)
        {
            if (!isEmpty(GC.getSpellInfo((SpellTypes)spell).getPyMiscast()))
            {
                CyUnit* pyUnit = new CyUnit(this);
                CyArgsList argsList;
                argsList.add(gDLL->getPythonIFace()->makePythonObject(pyUnit));	// pass in unit class
                argsList.add(spell);//the spell #
                gDLL->getPythonIFace()->callFunction(PYSpellModule, "miscast", argsList.makeFunctionArgs()); //, &lResult
                delete pyUnit; // python fxn must not hold on to this pointer
            }
        }
        gDLL->getInterfaceIFace()->addMessage((PlayerTypes)getOwner(), true, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_MESSAGE_SPELL_MISCAST"), "AS2D_WONDER_UNIT_BUILD", MESSAGE_TYPE_MAJOR_EVENT, "art/interface/buttons/spells/miscast.dds", (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT"), getX_INLINE(), getY_INLINE(), true, true);
        gDLL->getInterfaceIFace()->setDirty(SelectionButtons_DIRTY_BIT, true);
        return;
    }

It should be:

Code:
    int iMiscastChance = GC.getSpellInfo((SpellTypes)spell).getMiscastChance() + m_pUnitInfo->getMiscastChance();
    if (iMiscastChance > 0)
    {
        if (GC.getGameINLINE().getSorenRandNum(100, "Miscast") < iMiscastChance)
        {
            if (!isEmpty(GC.getSpellInfo((SpellTypes)spell).getPyMiscast()))
            {
                CyUnit* pyUnit = new CyUnit(this);
                CyArgsList argsList;
                argsList.add(gDLL->getPythonIFace()->makePythonObject(pyUnit));	// pass in unit class
                argsList.add(spell);//the spell #
                gDLL->getPythonIFace()->callFunction(PYSpellModule, "miscast", argsList.makeFunctionArgs()); //, &lResult
                delete pyUnit; // python fxn must not hold on to this pointer
            }
            gDLL->getInterfaceIFace()->addMessage((PlayerTypes)getOwner(), true, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_MESSAGE_SPELL_MISCAST"), "AS2D_WONDER_UNIT_BUILD", MESSAGE_TYPE_MAJOR_EVENT, "art/interface/buttons/spells/miscast.dds", (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT"), getX_INLINE(), getY_INLINE(), true, true);
            gDLL->getInterfaceIFace()->setDirty(SelectionButtons_DIRTY_BIT, true);
            return;
        }
    }

I'll fix it in the next version (and of course the above code should fix it in yours).
 
Back
Top Bottom