An Idiots Guide to Editing the DLL

Alright, I finished up the PillageCommerce stuff and when I went to compile, it complained about an illegal else without an if, but there is an if. This is the code (watch out its a lot, I've bolded the if and the matching else):

Spoiler :
Code:
[B]if[/B] (isDead())
			{
				int iExperience = defenseXPValue();
				iExperience = ((iExperience * iAttackerStrength) / iDefenderStrength);
				iExperience = range(iExperience, GC.getDefineINT("MIN_EXPERIENCE_PER_COMBAT"), GC.getDefineINT("MAX_EXPERIENCE_PER_COMBAT"));
				pDefender->changeExperience(iExperience, maxXPValue(), true, pPlot->getOwnerINLINE() == pDefender->getOwnerINLINE(), !isBarbarian());
				
/******************************************************************************************/
/*  Author: TheLadiesOgre (Original Concept By: Tsentom1)                                 */
/*  Date: 03.09.2009                                                                      */
/*  ModComp: Promotions DLL                                                               */
/*  Intended to: Add functionality for iVictory________Heals                              */
/******************************************************************************************/
				int iUnitsHealed = 0;
				if ((pDefender->getVictoryAdjacentTileHeal()) >= GC.getGameINLINE().getSorenRandNum(100, "Field Hospital Die Roll")) 
				{
					int iI;
					for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
					{
						CvPlot* pLoopPlot = plotDirection(pPlot->getX_INLINE(), pPlot->getY_INLINE(), ((DirectionTypes)iI));

						if (pLoopPlot != NULL)
						{
							if (pLoopPlot->area() == pPlot->area())
							{
								CLLNode<IDInfo>* pUnitNode = pLoopPlot->headUnitNode();

								while (pUnitNode != NULL)
								{
									CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
									pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);

									if (pLoopUnit->getTeam() == getTeam())
									{
										iUnitsHealed++;
										pLoopUnit->doHeal();
									}
								}
							}
						}
					}
				}
				
				bool bDefenderHealed = false;
				if ((pDefender->getVictorySameTileHeal()) >= GC.getGameINLINE().getSorenRandNum(100, "Field Surgeon Die Roll"))
				{
					bDefenderHealed = true;
					CLLNode<IDInfo>* pUnitNode = pPlot->headUnitNode();

					while (pUnitNode != NULL)
					{
						CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
						pUnitNode = pPlot->nextUnitNode(pUnitNode);

						if (pLoopUnit->getTeam() == getTeam())
						{
							iUnitsHealed++;
							pLoopUnit->doHeal();
						}
					}
				}

				if (!bDefenderHealed && (pDefender->getVictoryHeal()) >= GC.getGameINLINE().getSorenRandNum(100, "Field Medic Die Roll"))
				{
					pDefender->doHeal();
				}

				if (iUnitsHealed > 0)
				{
					CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_ENEMY_FIELD_MEDIC_DEFENDERS", GET_PLAYER(pDefender->getOwnerINLINE()).getCivilizationAdjective());
					gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COMBAT", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pDefender->getX_INLINE(), pDefender->getY_INLINE());

					szBuffer = gDLL->getText("TXT_KEY_MISC_FIELD_MEDIC_DEFENDERS", getNameKey(), iUnitsHealed);
					gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_POSITIVE_DINK", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pDefender->getX_INLINE(), pDefender->getY_INLINE());
				}

				if (pDefender->isPillageOnVictory())
				{
					// Use python to determine pillage amounts...
					lPillageGold = 0;
			
					CyPlot* pyPlot = new CyPlot(pPlot);
					CyUnit* pyUnit = new CyUnit(this);

					CyArgsList argsList;
					argsList.add(gDLL->getPythonIFace()->makePythonObject(pyPlot));	// pass in plot class
					argsList.add(gDLL->getPythonIFace()->makePythonObject(pyUnit));	// pass in unit class

					gDLL->getPythonIFace()->callFunction(PYGameModule, "doPillageGold", argsList.makeFunctionArgs(),&lPillageGold);

					delete pyPlot;	// python fxn must not hold on to this pointer 
					delete pyUnit;	// python fxn must not hold on to this pointer 

					iPillageGold = (int)lPillageGold;
					iPillageGold += (iPillageGold * getPillageChange()) / 100;
					int iI = 0;

					if ((iPillageGold > 0) && (!pDefender->isPillageCommerceChange((CommerceTypes)iI)))
					{
						GET_PLAYER(pDefender->getOwnerINLINE()).changeGold(iPillageGold);

						szBuffer = gDLL->getText("TXT_KEY_MISC_PLUNDERED_GOLD_ON_VICTORY", iPillageGold, pDefender->getNameKey(), getVisualCivAdjective(getTeam()));
						gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGE", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

						szBuffer = gDLL->getText("TXT_KEY_MISC_DEAD_LOOTED", getNameKey(), getVisualCivAdjective(pDefender->getTeam()));
						gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
						}
					}

					if ((iPillageGold > 0) && (pDefender->isPillageCommerceChange(COMMERCE_CULTURE) == true))
					{
						float fInfluenceRatio = 0.0f;
						fInfluenceRatio = doVictoryInfluence(this, false, false);
						GET_PLAYER(pDefender->getOwnerINLINE()).changeGold(iPillageGold);

						szBuffer = gDLL->getText("TXT_KEY_MISC_PLUNDERED_CULTURE_GOLD_ON_VICTORY", iPillageGold, pDefender->getNameKey(), getVisualCivAdjective(getTeam()));

						if (fInfluenceRatio > 0.0f)
						{
							CvWString szInfluence;
							szInfluence.Format(L" Tile influence: +%.1f%%", fInfluenceRatio);
							szBuffer += szInfluence;
						}

						gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGE", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
						szBuffer = gDLL->getText("TXT_KEY_MISC_LOOTED_DEAD_SLANDERED", getNameKey(), getVisualCivAdjective(pDefender->getTeam()));
					
						CvWString szInfluence;
						szInfluence.Format(L" Tile influence: -%.1f%%", fInfluenceRatio);
						szBuffer += szInfluence;

						gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
						}
					}

					if ((iPillageGold > 0) && (pDefender->isPillageCommerceChange(COMMERCE_ESPIONAGE) == true))
					{
						GET_PLAYER(pDefender->getOwnerINLINE()).changeGold(iPillageGold);
						GET_TEAM(getTeam()).changeEspionagePointsAgainstTeam(GET_PLAYER(pDefender->getOwnerINLINE()).getTeam(), iPillageGold);

						szBuffer = gDLL->getText("TXT_KEY_MISC_PLUNDERED_ESPIONAGE_GOLD_ON_VICTORY", iPillageGold, getVisualCivAdjective(getTeam()));
						gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGE", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

						szBuffer = gDLL->getText("TXT_KEY_MISC_INTERROGATED_BEFORE_EXECUTION", getNameKey(), getVisualCivAdjective(pDefender->getTeam()));
						gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
					}

					if ((iPillageGold > 0) && (pDefender->isPillageCommerceChange(COMMERCE_GOLD) == true))
					{
						GET_PLAYER(pDefender->getOwnerINLINE()).changeGold(iPillageGold * 2);
					
						szBuffer = gDLL->getText("TXT_KEY_MISC_PLUNDERED_GOLD_ON_VICTORY", iPillageGold);
						gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGE", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

						szBuffer = gDLL->getText("TXT_KEY_MISC_BEGGED_FOR_MERCY", getNameKey(), getVisualCivAdjective(pPlot->getTeam()));
						gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
					}

					if ((iPillageGold > 0) && (pDefender->isPillageCommerceChange(COMMERCE_RESEARCH) == true))
					{
						GET_PLAYER(pDefender->getOwnerINLINE()).changeGold(iPillageGold);
						TechTypes eCurrentTech = GET_PLAYER(pDefender->getOwnerINLINE()).getCurrentResearch();
						GET_TEAM(getTeam()).changeResearchProgress(eCurrentTech, iPillageGold, pDefender->getOwnerINLINE());

						szBuffer = gDLL->getText("TXT_KEY_MISC_PLUNDERED_RESEARCH_GOLD_ON_VICTORY", iPillageGold);
						gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGE", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

						szBuffer = gDLL->getText("TXT_KEY_MISC_TECH_COMPROMISED", getNameKey(), getVisualCivAdjective(pPlot->getTeam()));
						gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
					}
				}
/******************************************************************************************/
/*  Promotions DLL End; TheLadiesOgre; 03.09.2009                                         */
/******************************************************************************************/
			}
			[B]else[/B]

It looks perfectly fine to me, but it refuses to work, what is it that I am missing? I know that it has to be something idiotically simple

Edit: The bold if and the bold else line up in VC++
 
Isn't there one } too many here?
Code:
					if ((iPillageGold > 0) && (!pDefender->isPillageCommerceChange((CommerceTypes)iI)))
					{
						GET_PLAYER(pDefender->getOwnerINLINE()).changeGold(iPillageGold);

						szBuffer = gDLL->getText("TXT_KEY_MISC_PLUNDERED_GOLD_ON_VICTORY", iPillageGold, pDefender->getNameKey(), getVisualCivAdjective(getTeam()));
						gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGE", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

						szBuffer = gDLL->getText("TXT_KEY_MISC_DEAD_LOOTED", getNameKey(), getVisualCivAdjective(pDefender->getTeam()));
						gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
						}
					}
 
I feel stupid, I was right though, it was something simple I was overlooking due to my lack of experience. thank you again
 
Bah, it happens sometime ;)
Like when you forgot to type CvWhateverClassYouModIn:: when creating a new function :p
 
I've compiled one, now how exactly do I get the best use out of it? The pillage promotions are causing CTD's (at least I think it is them), I was able to use one twice before a CTD and every other time as soon as I clicked the button, straight back out to the desktop. Really, really sucks but at least I'm pretty sure it has something to do with the level one promotions (I was trying to play through getting them instead of WBing them in).
 
Having the Debug DLL instead of a normal one automatically gains you Assert statements, which do some limited good. As long as you have written Assert checks in the right locations. The main use though is that once you launch your mod, you go to DEBUG->ATTACH TO PROCESS in VS (with your project open and preferably unaltered since the compile you are using). From the window that pops up, choose the process which is identified as Civ 4 Beyond the Sword.

You can also automatically connect the debugger to watch the XML loading happen as well. Slows you down, but sometimes reveals more bugs.
 
I looked to your files but I didn't find anything glaringly wrong. I'll look more into them and will keep you updated.
 
Easily, the best tutorial I have ever read, on any subject, period.


Very nice work.So easy to read, so understandable, superb editing and formatting.

*APPLAUSE*

hdk
 
Finally decided to add in the civic functionality for Units, so RevDCM could remove the Python Callback. But I can't even get past the schema file, I haven't even started working on the actual code yet. I took a look at fall further's schema code, and cloned what I thought was needed, but the game wol't even start up, due to the XML being broke. Here is what I've done:

From Fall Further UnitSchema
Code:
	<ElementType name="PrereqCivics" content="eltOnly">
		<element type="PrereqCivic" minOccurs="0"/>
	</ElementType>
...
<element type="PrereqCivics" minOccurs="0"/>

Added it to LoR's UnitSchema file:
Code:
	<ElementType name="PrereqBonuses" content="eltOnly">
		<element type="BonusType" minOccurs="0" maxOccurs="*"/>
	</ElementType>
[B]	<ElementType name="PrereqCivics" content="eltOnly">
		<element type="PrereqCivic" minOccurs="0"/>
	</ElementType>[/B]
	<ElementType name="ProductionTraitType" content="textOnly"/>
	<ElementType name="iProductionTrait" content="textOnly" dt:type="int"/>
	<ElementType name="ProductionTrait" content="eltOnly">
		<element type="ProductionTraitType"/>
		<element type="iProductionTrait"/>
	</ElementType>
	<ElementType name="ProductionTraits" content="eltOnly">
		<element type="ProductionTrait" minOccurs="0" maxOccurs="*"/>
	</ElementType>
...
		<element type="BonusType" minOccurs="0"/>
		<element type="PrereqBonuses" minOccurs="0"/>
		[B]<element type="PrereqCivics" minOccurs="0"/>[/B]
		<element type="ProductionTraits" minOccurs="0"/>

I haven't even tried adding the tag into any file, just testing to see if the schema worked, and it fails...

I have not had a problem adding stuff to the schema for integers and booleans, so what am I doing wrong here?
 
Is there a:
Code:
<ElementType name="PrereqCivic" content="textOnly"/>

Anywhere in your code? You also need that line, along with the:

Code:
	<ElementType name="PrereqCivics" content="eltOnly">
		<element type="PrereqCivic" minOccurs="0"/>
	</ElementType>
 
Hello, I'm still having trouble with CivicPrereqs, they are just refusing to work, I've added everything I needed to add (at least I think I did), hell, I even added a new function in CvGameCoreUtils called isCivicRequiredForPromotion() (I modeled it after isTechRequiredForProject()). I am nearing my wits end, I really want to get started on the Slaver Promotion, but not without working CivicPrereq. Everything we've already discussed about them is in, but I know I have to be missing something, I just don't know what. I really want to try to get this without doing a direct import, but I'm starting to doubt that I can.
 
Ok, so things needed for a civic prereq field: Assuming you want to authorize multiple Civics on a single promotion, and assuming that it will be an OR type of mix:

You need to add either an boolean array of size CivicInfos or an INT list of arbitrary size to CvInfos. You need to load the civics from the XML into the array or list to indicate which civics will authorize the promotion.

Next you need to modify gametext to loop over civics (for the array array option, the size of the list for the list option) during parsePromotionHelp function and state the need of the civics. Then you'll check out the pedia in game to ensure that things are loading proper.

If the civics you want listed are being listed, the next step would be to go into UnitInfos and add a loop over civics (or list length) in ::isPromotionValid. Start with a boolean bValid set as false, and if a civic listed for the promotion is found to be active for the owner, flip bValid to true and break the loop, authorizing the promotion for this aspect of the prereqs.
 
Since you don't have a Creating a completely new Array XML tag tutorial written yet, and a civics check in the UnitsSchema seems to be in high demand, any chance you could write up such a tutorial? I've tried to get a civic check working using the FF code for promotions, and can't figure it out. A properly done array that can be used in UnitInfos would get alot of use, as it would instantly get implemented in RevolutionDCM, and by extension all mods that use a RevDCM core (RoM, LoR, Quote Capita, and Dune Wars to name a few).
 
So you want a prereqCivic for Units? Could put that up on the blocks to code easily enough
Yeah, a RequiredCivics array (or setup) to train units in UnitInfos would be perfect. A required RequiredCivics array to select a promotion and have it work would also be benificial, but I'd have to convert this for my uses. You already have this in FF, but I can't make it work when cloning it to UnitInfos.
 
Cool, an Array Tutorial would be exceedingly helpful, given the troubles I've been having. Like I've said before there are several things I'd like to add, but IMHO they all hinge on having a CivicPrereq. Thank you again, I'll be looking forward to it.
 
Hi there,

I have a few problems and I'm not sure how to go about them.

- I wanna know how to hook up a SDK function to a button in python (like an action button). I asked on the thread by TC01 but he says that he doesn't know how to do it.

- I'd like to understand how the game manages the resources of the same civilization on the different land mass IF it can't trade over water. Sounds contradictory I know so here is the situation. I'm working on a ww2 mod and I want to force the players who have key resources to send them overseas by "tanker" ships to their other cities who are requiring them to build units, buildings, etc. So far I have managed (with alot of help) too shut down cross ocean trading, I made a tanker ship unit and an action button exists for it. The action would be to increment the number of turns of production requiring the carried resource to the city where it is presently located.

Here is where things get difficult.

I'd like for every territory zone (for the same civ) to have an integer counting the amount of turns of production left with the resource in question. I'm not sure if CvArea.cpp controls the territory or the whole civ.

Thanks for your time
 
Top Bottom