Skip to content

Commit

Permalink
Technologies can now provide a civ wide commerce modifier.
Browse files Browse the repository at this point in the history
CIV4TechInfos.xml now has a new (optional) field for granting a
percentage commerce modifier. The save file format has been updated to
save this new information. The AI for choosing techs has been updated to
understand the changes. The tech chooser and tech information text has
been updated to report the new information. (This includes added a new
widget, and new text xml.)

The city screen now shows unaccounted for modifiers as being "from
Civilization". This is how the new modifier will be reported in the city
screen mouse-over text.

(This new feature will most likely be used to provide a percentage
science bonus to Scientific Method; but that change has not been made
yet. )
  • Loading branch information
karadoc committed Oct 5, 2016
1 parent a603058 commit f33cf7e
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 15 deletions.
10 changes: 10 additions & 0 deletions Assets/Python/Screens/CvTechChooser.py
Expand Up @@ -702,6 +702,16 @@ def addIconsToTechPanel(self, screen, i, fX, iX, iY, szTechRecord):
j = 0
k = 0

# K-Mod. Commerce modifiers
for j in range(CommerceTypes.NUM_COMMERCE_TYPES):
if (gc.getTechInfo(i).getCommerceModifier(j) > 0):
szCommerceModifierButton = self.getNextWidgetName("CommerceModifierButton")
screen.addDDSGFCAt( szCommerceModifierButton, szTechRecord, gc.getCommerceInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_GLOBAL_COMMERCE_MODIFIER, i, j, False )
fX += X_INCREMENT

j = 0
k = 0

# K-Mod. Extra specialist commerce
for j in range(CommerceTypes.NUM_COMMERCE_TYPES):
if (gc.getTechInfo(i).getSpecialistExtraCommerce(j) > 0):
Expand Down
4 changes: 4 additions & 0 deletions Assets/xml/Technologies/CIV4TechnologiesSchema.xml
Expand Up @@ -55,6 +55,9 @@
<element type="DomainExtraMove" minOccurs="0" maxOccurs="*"/>
</ElementType>
<ElementType name="iCommerce" content="textOnly" dt:type="int"/>
<ElementType name="CommerceModifiers" content="eltOnly">
<element type="iCommerce" minOccurs="0" maxOccurs="*"/>
</ElementType>
<ElementType name="SpecialistExtraCommerces" content="eltOnly">
<element type="iCommerce" minOccurs="0" maxOccurs="*"/>
</ElementType>
Expand Down Expand Up @@ -141,6 +144,7 @@
<element type="iGridX"/>
<element type="iGridY"/>
<element type="DomainExtraMoves"/>
<element type="CommerceModifiers" minOccurs="0"/>
<element type="SpecialistExtraCommerces" minOccurs="0"/>
<element type="CommerceFlexible"/>
<element type="TerrainTrades"/>
Expand Down
10 changes: 10 additions & 0 deletions Assets/xml/Text/Civ4GameText_K-Mod.xml
Expand Up @@ -25,6 +25,16 @@
<Spanish>[SPACE]en la casilla</Spanish>
</TEXT>

<!-- Percentage modifiers from "Civilization" (eg. from tech) -->
<TEXT>
<Tag>TXT_KEY_MISC_HELP_MODIFIER_FROM_CIV</Tag>
<English>[ICON_BULLET]%D1%%%F2 from Civilization</English>
<French>[ICON_BULLET]%D1%%%F2 (civilisation)</French>
<German>[ICON_BULLET]%D1%%%F2 durch Zivilisation</German>
<Italian>[ICON_BULLET]%D1%%%F2 per la civilt&#224;</Italian>
<Spanish>[ICON_BULLET]%D1%%%F2 por civilizaci&#243;n</Spanish>
</TEXT>

<TEXT>
<Tag>TXT_KEY_PER</Tag>
<English>[SPACE]per[SPACE]</English>
Expand Down
3 changes: 3 additions & 0 deletions CvGameCoreDLL/CvDLLWidgetData.cpp
Expand Up @@ -595,6 +595,9 @@ void CvDLLWidgetData::parseHelp(CvWStringBuffer &szBuffer, CvWidgetDataStruct &w
szBuffer.assign(gDLL->getText("TXT_KEY_GW_UNHAPPY_HELP"));
break;
// K-Mod. Extra specialist commerce
case WIDGET_HELP_GLOBAL_COMMERCE_MODIFIER:
GAMETEXT.setCommerceChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_CIVIC_IN_ALL_CITIES").GetCString(), GC.getTechInfo((TechTypes)(widgetDataStruct.m_iData1)).getCommerceModifierArray(), true, false);
break;
case WIDGET_HELP_EXTRA_SPECIALIST_COMMERCE:
GAMETEXT.setCommerceChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_CIVIC_PER_SPECIALIST").GetCString(), GC.getTechInfo((TechTypes)(widgetDataStruct.m_iData1)).getSpecialistExtraCommerceArray(), false, false);
break;
Expand Down
1 change: 1 addition & 0 deletions CvGameCoreDLL/CvEnums.h
Expand Up @@ -549,6 +549,7 @@ enum WidgetTypes // Exposed to Python
WIDGET_HELP_GW_INDEX,
WIDGET_HELP_GW_UNHAPPY,

WIDGET_HELP_GLOBAL_COMMERCE_MODIFIER,
WIDGET_HELP_EXTRA_SPECIALIST_COMMERCE,
// K-Mod end

Expand Down
28 changes: 28 additions & 0 deletions CvGameCoreDLL/CvGameTextMgr.cpp
Expand Up @@ -7763,6 +7763,9 @@ void CvGameTextMgr::setTechHelp(CvWStringBuffer &szBuffer, TechTypes eTech, bool
// K-Mod. Extra specialist commerce
setCommerceChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_CIVIC_PER_SPECIALIST").GetCString(), GC.getTechInfo(eTech).getSpecialistExtraCommerceArray());

// K-Mod. Global commerce modifers
setCommerceChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_CIVIC_IN_ALL_CITIES").GetCString(), GC.getTechInfo(eTech).getCommerceModifierArray(), true);

// Adjusting culture, science, etc
for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
{
Expand Down Expand Up @@ -15540,6 +15543,31 @@ void CvGameTextMgr::setCommerceHelp(CvWStringBuffer &szBuffer, CvCity& city, Com
iModifier += iCivicMod;
}

// Techs (K-Mod)
/* Rather than counting just tech modifiers. We might as well just have an generic case which supports other sources too.
int iTechMod = 0;
for (TechTypes i = (TechTypes)0; i < GC.getNumTechInfos(); i=(TechTypes)(i+1))
{
if (GET_TEAM(owner.getTeam()).isHasTech(i))
iTechMod += GC.getTechInfo(i).getCommerceModifier(eCommerceType);
}
if (iTechMod != 0)
{
szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_MODIFIER_FROM_CIV", iTechMod, info.getChar()));
szBuffer.append(NEWLINE);
iModifier += iCivicMod;
} */

// Left over modifiers!
int iUnaccountedModifiers = city.getTotalCommerceRateModifier(eCommerceType)-iModifier;
if (iUnaccountedModifiers != 0)
{
szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_MODIFIER_FROM_CIV", iUnaccountedModifiers, info.getChar()));
szBuffer.append(NEWLINE);
iModifier += iUnaccountedModifiers;
}
// K-Mod end

int iModYield = (iModifier * iBaseCommerceRate) / 100;

int iProductionToCommerce = city.getProductionToCommerceModifier(eCommerceType) * city.getYieldRate(YIELD_PRODUCTION);
Expand Down
34 changes: 33 additions & 1 deletion CvGameCoreDLL/CvInfos.cpp
Expand Up @@ -1011,6 +1011,7 @@ m_piDomainExtraMoves(NULL),
m_piFlavorValue(NULL),
m_piPrereqOrTechs(NULL),
m_piPrereqAndTechs(NULL),
m_piCommerceModifier(NULL), // K-Mod
m_piSpecialistExtraCommerce(NULL), // K-Mod
m_pbCommerceFlexible(NULL),
m_pbTerrainTrade(NULL)
Expand All @@ -1030,6 +1031,7 @@ CvTechInfo::~CvTechInfo()
SAFE_DELETE_ARRAY(m_piFlavorValue);
SAFE_DELETE_ARRAY(m_piPrereqOrTechs);
SAFE_DELETE_ARRAY(m_piPrereqAndTechs);
SAFE_DELETE_ARRAY(m_piCommerceModifier); // K-Mod
SAFE_DELETE_ARRAY(m_piSpecialistExtraCommerce); // K-Mod
SAFE_DELETE_ARRAY(m_pbCommerceFlexible);
SAFE_DELETE_ARRAY(m_pbTerrainTrade);
Expand Down Expand Up @@ -1275,6 +1277,19 @@ int CvTechInfo::getPrereqAndTechs(int i) const
}

// K-Mod
int CvTechInfo::getCommerceModifier(int i) const
{
FAssertMsg(m_piCommerceModifier, "Tech info not initialised");
FASSERT_BOUNDS(0, NUM_COMMERCE_TYPES, i, "CvTechInfo::getCommerceModifier");

return m_piCommerceModifier ? m_piCommerceModifier[i] : 0;
}

int* CvTechInfo::getCommerceModifierArray() const
{
return m_piCommerceModifier;
}

int CvTechInfo::getSpecialistExtraCommerce(int i) const
{
FAssertMsg(m_piSpecialistExtraCommerce, "Tech info not initialised");
Expand Down Expand Up @@ -1362,6 +1377,12 @@ void CvTechInfo::read(FDataStreamBase* stream)
stream->Read(GC.getNUM_AND_TECH_PREREQS(), m_piPrereqAndTechs);

// K-Mod
if (uiFlag >= 2)
{
SAFE_DELETE_ARRAY(m_piCommerceModifier)
m_piCommerceModifier = new int[NUM_COMMERCE_TYPES];
stream->Read(NUM_COMMERCE_TYPES, m_piCommerceModifier);
}
if (uiFlag >= 1)
{
SAFE_DELETE_ARRAY(m_piSpecialistExtraCommerce)
Expand All @@ -1387,7 +1408,7 @@ void CvTechInfo::write(FDataStreamBase* stream)
{
CvInfoBase::write(stream);

uint uiFlag=1;
uint uiFlag=2;
stream->Write(uiFlag); // flag for expansion

stream->Write(m_iAdvisorType);
Expand Down Expand Up @@ -1432,6 +1453,7 @@ void CvTechInfo::write(FDataStreamBase* stream)
stream->Write(GC.getNumFlavorTypes(), m_piFlavorValue);
stream->Write(GC.getNUM_OR_TECH_PREREQS(), m_piPrereqOrTechs);
stream->Write(GC.getNUM_AND_TECH_PREREQS(), m_piPrereqAndTechs);
stream->Write(NUM_COMMERCE_TYPES, m_piCommerceModifier); // K-Mod. uiFlag >= 2
stream->Write(NUM_COMMERCE_TYPES, m_piSpecialistExtraCommerce); // K-Mod. uiFlag >= 1
stream->Write(NUM_COMMERCE_TYPES, m_pbCommerceFlexible);
stream->Write(GC.getNumTerrainInfos(), m_pbTerrainTrade);
Expand Down Expand Up @@ -1495,6 +1517,16 @@ bool CvTechInfo::read(CvXMLLoadUtility* pXML)
pXML->GetChildXmlValByName(&m_iGridY, "iGridY");

// K-Mod
if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"CommerceModifiers"))
{
pXML->SetCommerce(&m_piCommerceModifier);
gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
}
else
{
pXML->InitList(&m_piCommerceModifier, NUM_COMMERCE_TYPES);
}

if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"SpecialistExtraCommerces"))
{
pXML->SetCommerce(&m_piSpecialistExtraCommerce);
Expand Down
3 changes: 3 additions & 0 deletions CvGameCoreDLL/CvInfos.h
Expand Up @@ -356,6 +356,8 @@ friend class CvXMLLoadUtility;
int getPrereqOrTechs(int i) const; // Exposed to Python
int getPrereqAndTechs(int i) const; // Exposed to Python

int getCommerceModifier(int i) const; // K-Mod, Exposed to Python
int* getCommerceModifierArray() const; // K-Mod
int getSpecialistExtraCommerce(int i) const; // K-Mod, Exposed to Python
int* getSpecialistExtraCommerceArray() const; // K-Mod
bool isCommerceFlexible(int i) const; // Exposed to Python
Expand Down Expand Up @@ -423,6 +425,7 @@ friend class CvXMLLoadUtility;
int* m_piPrereqOrTechs;
int* m_piPrereqAndTechs;

int* m_piCommerceModifier; // K-Mod
int* m_piSpecialistExtraCommerce; // K-Mod
bool* m_pbCommerceFlexible;
bool* m_pbTerrainTrade;
Expand Down
44 changes: 32 additions & 12 deletions CvGameCoreDLL/CvPlayerAI.cpp
Expand Up @@ -5013,7 +5013,7 @@ TechTypes CvPlayerAI::AI_bestTech(int iMaxPathLength, bool bIgnoreCost, bool bAs
}

// This function has been mostly rewritten for K-Mod.
// Note: many of the values used in this function are arbitrary; but adjusted them all to get closer to having a common scale.
// Note: many of the values used in this function are arbitrary; but I've adjusted them to get closer to having a common scale.
// The scale is roughly 4 = 1 commerce per turn.
// (Compared to the original numbers, this is * 1/100 * 7 * 4. 28/100)
int CvPlayerAI::AI_techValue( TechTypes eTech, int iPathLength, bool bIgnoreCost, bool bAsync, int* paiBonusClassRevealed, int* paiBonusClassUnrevealed, int* paiBonusClassHave ) const
Expand Down Expand Up @@ -5290,15 +5290,18 @@ int CvPlayerAI::AI_techValue( TechTypes eTech, int iPathLength, bool bIgnoreCost

// K-Mod. Extra specialist commerce. (Based on my civic evaluation code)
bool bSpecialistCommerce = false;
int iTotalBonusSpecialists = -1;
int iTotalCurrentSpecialists = -1;
for (CommerceTypes i = (CommerceTypes)0; i < NUM_COMMERCE_TYPES; i=(CommerceTypes)(i+1))
{
bSpecialistCommerce = kTechInfo.getSpecialistExtraCommerce(i) != 0;
}

if (bSpecialistCommerce)
{
int iTotalBonusSpecialists = 0;
int iTotalCurrentSpecialists = 0;
// If there are any bonuses, we need to count our specialists.
// (The value from the bonuses will be applied later.)
iTotalBonusSpecialists = iTotalCurrentSpecialists = 0;

int iLoop;
CvCity* pLoopCity;
Expand All @@ -5310,23 +5313,40 @@ int CvPlayerAI::AI_techValue( TechTypes eTech, int iPathLength, bool bIgnoreCost
iTotalCurrentSpecialists += pLoopCity->getNumGreatPeople();
iTotalCurrentSpecialists += pLoopCity->getSpecialistPopulation();
}
}

for (CommerceTypes i = (CommerceTypes)0; i < NUM_COMMERCE_TYPES; i=(CommerceTypes)(i+1))
for (CommerceTypes i = (CommerceTypes)0; i < NUM_COMMERCE_TYPES; i=(CommerceTypes)(i+1))
{
int iCommerceValue = 0;

// Commerce for specialists
if (bSpecialistCommerce)
{
iValue += 4*AI_averageCommerceMultiplier(i)*(kTechInfo.getSpecialistExtraCommerce(i) * std::max((getTotalPopulation()+12*iTotalBonusSpecialists) / 12, iTotalCurrentSpecialists));
iCommerceValue += 4*AI_averageCommerceMultiplier(i)*(kTechInfo.getSpecialistExtraCommerce(i) * std::max((getTotalPopulation()+12*iTotalBonusSpecialists) / 12, iTotalCurrentSpecialists));
}
}
// K-Mod end

for (int iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
{
if (kTechInfo.isCommerceFlexible(iJ))
// Commerce multipliers. (using iCommerceValue from the specialists bonuses to calculate compound effect).
iCommerceValue += kTechInfo.getCommerceModifier(i) * (4*getCommerceRate(i)+iCommerceValue) / AI_averageCommerceMultiplier(i);

// Flexible commerce. (This is difficult to evaluate accurately without checking a lot of things - which I'm not going to do right now.)
if (kTechInfo.isCommerceFlexible(i))
{

iCommerceValue += 80 + 4 * iCityCount;
/* original
iValue += 4 * iCityCount * (3*AI_averageCulturePressure()-200) / 100;
if ((iJ == COMMERCE_CULTURE) && (AI_isDoVictoryStrategy(AI_VICTORY_CULTURE2)))
if (i == COMMERCE_CULTURE && AI_isDoVictoryStrategy(AI_VICTORY_CULTURE2))
{
iValue += 280;
}
} */
}

if (iCommerceValue)
{
iCommerceValue *= AI_commerceWeight(i);
iCommerceValue /= 100;

iValue += iCommerceValue;
}
}

Expand Down
3 changes: 2 additions & 1 deletion CvGameCoreDLL/CvTeam.cpp
Expand Up @@ -6472,9 +6472,10 @@ void CvTeam::processTech(TechTypes eTech, int iChange)
kLoopPlayer.changeAssets(GC.getTechInfo(eTech).getAssetValue() * iChange);
kLoopPlayer.changePower(GC.getTechInfo(eTech).getPowerValue() * iChange);
kLoopPlayer.changeTechScore(getTechScore(eTech) * iChange);
// K-Mod. Extra commerce for specialist (new xml field)
// K-Mod. Processing for new xml fields
for (CommerceTypes eCommerce = (CommerceTypes)0; eCommerce < NUM_COMMERCE_TYPES; eCommerce=(CommerceTypes)(eCommerce+1))
{
kLoopPlayer.changeCommerceRateModifier(eCommerce, GC.getTechInfo(eTech).getCommerceModifier(eCommerce) * iChange);
kLoopPlayer.changeSpecialistExtraCommerce(eCommerce, GC.getTechInfo(eTech).getSpecialistExtraCommerce(eCommerce) * iChange);
}
// K-Mod end
Expand Down
3 changes: 2 additions & 1 deletion CvGameCoreDLL/CyEnumsInterface.cpp
Expand Up @@ -397,7 +397,8 @@ void CyEnumsPythonInterface()
.value("WIDGET_HELP_GW_INDEX", WIDGET_HELP_GW_INDEX)
.value("WIDGET_HELP_GW_UNHAPPY", WIDGET_HELP_GW_UNHAPPY)

// Extra specialist commerce (from tech)
// Extra specialist commerce, and commerce modifers (from tech)
.value("WIDGET_HELP_GLOBAL_COMMERCE_MODIFIER", WIDGET_HELP_GLOBAL_COMMERCE_MODIFIER)
.value("WIDGET_HELP_EXTRA_SPECIALIST_COMMERCE", WIDGET_HELP_EXTRA_SPECIALIST_COMMERCE)
// K-Mod end
.value("NUM_WIDGET_TYPES", NUM_WIDGET_TYPES)
Expand Down
1 change: 1 addition & 0 deletions CvGameCoreDLL/CyInfoInterface1.cpp
Expand Up @@ -96,6 +96,7 @@ void CyInfoPythonInterface1()
.def("getPrereqOrTechs", &CvTechInfo::getPrereqOrTechs, "int (int i)")
.def("getPrereqAndTechs", &CvTechInfo::getPrereqAndTechs, "int (int i)")

.def("getCommerceModifier", &CvTechInfo::getCommerceModifier, "int (int i)") // K-Mod
.def("getSpecialistExtraCommerce", &CvTechInfo::getSpecialistExtraCommerce, "int (int i)") // K-Mod
.def("isCommerceFlexible", &CvTechInfo::isCommerceFlexible, "bool (int i)")
.def("isTerrainTrade", &CvTechInfo::isTerrainTrade, "bool (int i)")
Expand Down

0 comments on commit f33cf7e

Please sign in to comment.