DLL - More modular diplo relations

whoward69

DLL Minion
Joined
May 30, 2011
Messages
8,728
Location
Near Portsmouth, UK
Is there any way that making diplomatic relations more modular...? The global limitation of three custom diplomatic values is really inhibiting. I believe that Putmalk's CivIV Diplomacy mod adds additional ones through his DLL. Perhaps it would be non-trivial to allow the addition of new diplomatic modifiers through Lua.
An answer to whether this is possible would set my mind at rest :)

All of Putmalk's code is already in the CP DLL, so something we/I can easily take a look at.
 
Putmalk's code is all vassalage, map trading, etc related and not generic.

I'm assuming the problem is not so much reusing the three Lua scenario events (as these are accumulators) but getting the associated bullet point in the diplomacy screen
 
As you say, the actual modifier itself is accumulative; so yes, the issue is just that displaying information about diplomatic relations is limited to three entries (which require updating scenario specific text as it stands) across all mods.
 
There is no way for the C++ code to get a string from Lua, so the only way I can think of doing this is to add a database table, and insert a row for each diplo modifier.

The C++ code can then loop the (cached) db table and call a common GetDiploModifier event with the id of the modifier from the table. If the returned modifier is non-zero it will then build the tool-tip from the text key in the db table, eg

Code:
<GameData>
  <Table name="DiploModifiers">
    <Column name="ID" type="integer" primarykey="true" autoincrement="true"/>
    <Column name="Type" type="text" unique="true" notnull="true"/>
    <Column name="Description" type="text" reference="Language_en_US(Tag)"/>
  </Table>
  
  <DiploModifiers>
    <Row>
      <ID>0</ID>
      <Type>DIPLOMODIFIER_SCENARIO1</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_STRING_1</Description>
    </Row>
    <Row>
      <Type>DIPLOMODIFIER_SCENARIO2</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_STRING_2</Description>
    </Row>
    <Row>
      <Type>DIPLOMODIFIER_SCENARIO3</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_STRING_3</Description>
    </Row>
  </DiploModifiers>
</GameData>

A modder can then add as many rows as they want to the table, and would just need to add a check in the common event that it was for their entry

Code:
<GameData>
  <DiploModifiers>
    <Row>
      <Type>DIPLOMODIFIER_MY_STUFF</Type>
      <Description>TXT_KEY_MY_MOD_DIPLO_MODIFIER</Description>
    </Row>
  </DiploModifiers>
</GameData>

Code:
OnDiploModifier(iModifier)
  local iValue = 0

  if (iModifier == GameInfoTypes.DIPLOMODIFIER_MY_STUFF) then
    -- Set iValue to whatever
  end

  return iValue
end
GameEvents.DiploModifier.Add(OnDiploModifier)

(Don't get hung up on the event name or it's parameters, they can be decided later)
 
Coming to a build near you soon ...

Enable the GetDiploModifier event

Code:
  <CustomModOptions>
    <Update>
      <Where Name="EVENTS_DIPLO_MODIFIERS" />
      <Set Value="1"/>
    </Update>
  </CustomModOptions>

Add to the DiploModifiers table three new entries, two only for US<->USSR relations

Code:
  <DiploModifiers>
    <Row>
      <Type>DIPLOMODIFIER_IRON_CURTAIN</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_IRON_CURTAIN</Description>
    </Row>
    <Row>
      <Type>DIPLOMODIFIER_COLD_WAR_US</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_COLD_WAR_US</Description>
      <FromCivilizationType>CIVILIZATION_AMERICA</FromCivilizationType>
      <ToCivilizationType>CIVILIZATION_RUSSIA</ToCivilizationType>
    </Row>
    <Row>
      <Type>DIPLOMODIFIER_COLD_WAR_USSR</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_COLD_WAR_USSR</Description>
      <FromCivilizationType>CIVILIZATION_RUSSIA</FromCivilizationType>
      <ToCivilizationType>CIVILIZATION_AMERICA</ToCivilizationType>
    </Row>
  </DiploModifiers>

  <Language_en_US>
    <Row Tag="TXT_KEY_SPECIFIC_DIPLO_IRON_CURTAIN">
      <Text>Iron Curtain: {1_modifier} {2_fromPlayer} {3_fromCiv} {4_toPlayer} {5_toCiv}</Text>
    </Row>
    <Row Tag="TXT_KEY_SPECIFIC_DIPLO_COLD_WAR_US">
      <Text>Cold War: {1_num} because {3} hates {5}</Text>
    </Row>
    <Row Tag="TXT_KEY_SPECIFIC_DIPLO_COLD_WAR_USSR">
      <Text>Cold War: Because {5} distrusts {3} ... {1_num}</Text>
    </Row>
  </Language_en_US>

Add an event handler (as this is an accumulator event, I could have written multiple event handlers)

Code:
function OnGetDiploModifier(iDiploModifier, iFromPlayer, iToPlayer)
  local iModifier = 0
  
  if (iDiploModifier == GameInfoTypes.DIPLOMODIFIER_IRON_CURTAIN) then
    iModifier = 10
  elseif (iDiploModifier == GameInfoTypes.DIPLOMODIFIER_COLD_WAR_US) then
    iModifier = 20
  elseif (iDiploModifier == GameInfoTypes.DIPLOMODIFIER_COLD_WAR_USSR) then
    iModifier = 30
  end
  
  print(string.format("OnGetDiploModifier(%s, %i, %s, %s)", GameInfo.DiploModifiers[iDiploModifier].Type, iModifier, Players[iFromPlayer]:GetCivilizationDescription(), Players[iToPlayer]:GetCivilizationDescription()))
  return iModifier
end
GameEvents.GetDiploModifier.Add(OnGetDiploModifier)

Start a game and test it

Code:
[ Lua State = MyLuaChanges ]
> pUsPlayer = Players[Game.GetCivilizationPlayer(GameInfoTypes.CIVILIZATION_AMERICA)]
> pUssrPlayer = Players[Game.GetCivilizationPlayer(GameInfoTypes.CIVILIZATION_RUSSIA)]
> pUkPlayer = Players[Game.GetCivilizationPlayer(GameInfoTypes.CIVILIZATION_ENGLAND)]

> for _, sOpinion in ipairs([B]pUsPlayer:GetOpinionTable(pUssrPlayer[/B]:GetID())) do print(sOpinion) end
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO1, 0, American Empire, Russian Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO2, 0, American Empire, Russian Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO3, 0, American Empire, Russian Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_IRON_CURTAIN, 10, American Empire, Russian Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_COLD_WAR_US, 20, American Empire, Russian Empire)
 MyLuaChanges: [COLOR_FADING_NEGATIVE_TEXT]Iron Curtain: 10 Washington American Empire Catherine Russian Empire[ENDCOLOR]
 MyLuaChanges: [COLOR_NEGATIVE_TEXT]Cold War: 20 because American Empire hates Russian Empire[ENDCOLOR]

> for _, sOpinion in ipairs([B]pUssrPlayer:GetOpinionTable(pUsPlayer[/B]:GetID())) do print(sOpinion) end
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO1, 0, Russian Empire, American Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO2, 0, Russian Empire, American Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO3, 0, Russian Empire, American Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_IRON_CURTAIN, 10, Russian Empire, American Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_COLD_WAR_USSR, 30, Russian Empire, American Empire)
 MyLuaChanges: [COLOR_FADING_NEGATIVE_TEXT]Iron Curtain: 10 Catherine Russian Empire Washington American Empire[ENDCOLOR]
 MyLuaChanges: [COLOR_NEGATIVE_TEXT]Cold War: Because American Empire distrusts Russian Empire ... 30[ENDCOLOR]

> for _, sOpinion in ipairs([B]pUkPlayer:GetOpinionTable(pUssrPlayer[/B]:GetID())) do print(sOpinion) end
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO1, 0, English Empire, Russian Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO2, 0, English Empire, Russian Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_SCENARIO3, 0, English Empire, Russian Empire)
 MyLuaChanges: OnGetDiploModifier(DIPLOMODIFIER_IRON_CURTAIN, 10, English Empire, Russian Empire)
 MyLuaChanges: [COLOR_FADING_NEGATIVE_TEXT]Iron Curtain: 10 Elizabeth English Empire Catherine Russian Empire[ENDCOLOR]
 
Hi,whoward69.I am learning your code to adjust diplomacy relations.But my GameEvents.GetDiploModifier seems never happen.
I have enabled your VMC, given my XML file an OnModActivated -->Updatabase entry and given my lua file an InGameUIAddin.But my second function in lua never give any printing while the first function gives correct outcom.So I suppose the GameEvents.GetDiploModifier did not happen.How can I trigger it?
Or is there something I haven't done?
This is code in lua.
Code:
--[[To do:Every time a Major Civilization Conquested a city of Greece(take it for experiment here),
  the Civilization will get a diplomacy penality(determined by the population remain in the city) between all other major civilizations.]]
  -----Reference resources:   GameEvents.CityCaptureComplete(iOldOwner--playerID, bIsCapital, iX, iY--City, iNewOwner, iPop, bConquest)
  local t_DipPenalityValue = {}
  function DecideDiploPenality(iOldOwner, bIsCapital, iX, iY, iNewOwner, iPop, bConquest)
  local PoorPlayer = Players[iOldOwner]
  local EvilPlayer = Players[iNewOwner]
  local iVictim = iPop
  print("PoorPlayer is Greece")
  if bConquest == true  and PoorPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GREECE then
    print("EvilPlayer is you")
    t_DipPenalityValue[iNewOwner] = t_DipPenalityValue[iNewOwner] or 0
    if bIsCapital == true then
        t_DipPenalityValue[iNewOwner] = t_DipPenalityValue[iNewOwner] + iVictim * 5
    elseif bIsCapital == false then
        t_DipPenalityValue[iNewOwner] = t_DipPenalityValue[iNewOwner] + iVictim * 1
    end
  end
  print("iDiploPenality is",t_DipPenalityValue[iNewOwner])
end

GameEvents.CityCaptureComplete.Add(DecideDiploPenality)




function OnGetDiploPenality(iDiploModifier,iFromPlayer,iToPlayer)
print("im working")
if iDiploModifier == GameInfoTypes.DIPLOMODIFIER_EVIL_CONQUEST and t_DipPenalityValue[iToPlayer] then
    print("Penaity is",t_DipPenalityValue[iToPlayer])
    return t_DipPenalityValue[iToPlayer]
    end
end

GameEvents.GetDiploModifier.Add(OnGetDiploModifier)
And this is my XML.
Code:
<GameData>

<CustomModOptions>
    <Update>
      <Where Name="EVENTS_DIPLO_MODIFIERS" />
      <Set Value="1"/>
    </Update>
  </CustomModOptions>

    <Table name="DiploModifiers">
        <Column name="ID" type="integer" primarykey="true" autoincrement="true"/>
        <Column name="Type" type="text" unique="true" notnull="true"/>
        <Column name="Description" type="text" reference="Language_en_US(Tag)"/>
    </Table>
 
  <DiploModifiers>
    <Row>
      <Type>DIPLOMODIFIER_EVIL_CONQUEST</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_EVIL_CONQUEST</Description>
    </Row>
  </DiploModifiers>
 
  <Language_en_US>
    <Row Tag="TXT_KEY_SPECIFIC_DIPLO_EVIL_CONQUEST">
        <Text>The city alliance nailed you to the black list</Text>
    </Row>
  </Language_en_US>

  </GameData>
I'm not sure if it's polite here to post question to a post three years ago. If offended, please forgive me.


EDIT:It seems I have a Typo about the name of my function when call it by the Event.
And the table is not needed for I have the VMC.
 
Last edited:
Hi,whoward69.I am learning your code to adjust diplomacy relations.But my GameEvents.GetDiploModifier seems never happen.
I have enabled your VMC, given my XML file an OnModActivated -->Updatabase entry and given my lua file an InGameUIAddin.But my second function in lua never give any printing while the first function gives correct outcom.So I suppose the GameEvents.GetDiploModifier did not happen.How can I trigger it?
Or is there something I haven't done?
This is code in lua.
Code:
--[[To do:Every time a Major Civilization Conquested a city of Greece(take it for experiment here),
  the Civilization will get a diplomacy penality(determined by the population remain in the city) between all other major civilizations.]]
  -----Reference resources:   GameEvents.CityCaptureComplete(iOldOwner--playerID, bIsCapital, iX, iY--City, iNewOwner, iPop, bConquest)
  local t_DipPenalityValue = {}
  function DecideDiploPenality(iOldOwner, bIsCapital, iX, iY, iNewOwner, iPop, bConquest)
  local PoorPlayer = Players[iOldOwner]
  local EvilPlayer = Players[iNewOwner]
  local iVictim = iPop
  print("PoorPlayer is Greece")
  if bConquest == true  and PoorPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GREECE then
    print("EvilPlayer is you")
    t_DipPenalityValue[iNewOwner] = t_DipPenalityValue[iNewOwner] or 0
    if bIsCapital == true then
        t_DipPenalityValue[iNewOwner] = t_DipPenalityValue[iNewOwner] + iVictim * 5
    elseif bIsCapital == false then
        t_DipPenalityValue[iNewOwner] = t_DipPenalityValue[iNewOwner] + iVictim * 1
    end
  end
  print("iDiploPenality is",t_DipPenalityValue[iNewOwner])
end

GameEvents.CityCaptureComplete.Add(DecideDiploPenality)




function OnGetDiploPenality(iDiploModifier,iFromPlayer,iToPlayer)
print("im working")
if iDiploModifier == GameInfoTypes.DIPLOMODIFIER_EVIL_CONQUEST and t_DipPenalityValue[iToPlayer] then
    print("Penaity is",t_DipPenalityValue[iToPlayer])
    return t_DipPenalityValue[iToPlayer]
    end
end

GameEvents.GetDiploModifier.Add(OnGetDiploModifier)
And this is my XML.
Code:
<GameData>

<CustomModOptions>
    <Update>
      <Where Name="EVENTS_DIPLO_MODIFIERS" />
      <Set Value="1"/>
    </Update>
  </CustomModOptions>

    <Table name="DiploModifiers">
        <Column name="ID" type="integer" primarykey="true" autoincrement="true"/>
        <Column name="Type" type="text" unique="true" notnull="true"/>
        <Column name="Description" type="text" reference="Language_en_US(Tag)"/>
    </Table>
 
  <DiploModifiers>
    <Row>
      <Type>DIPLOMODIFIER_EVIL_CONQUEST</Type>
      <Description>TXT_KEY_SPECIFIC_DIPLO_EVIL_CONQUEST</Description>
    </Row>
  </DiploModifiers>
 
  <Language_en_US>
    <Row Tag="TXT_KEY_SPECIFIC_DIPLO_EVIL_CONQUEST">
        <Text>The city alliance nailed you to the black list</Text>
    </Row>
  </Language_en_US>

  </GameData>
I'm not sure if it's polite here to post question to a post three years ago. If offended, please forgive me.
You broke one coding XML error already, so that invalidates all of the XML code. You also don't have a save function on that variable.. so I'm unsure.

Code:
UPDATE CustomModOptions
SET Value = 1
WHERE Name = 'EVENTS_DIPLO_MODIFIERS' AND Value = 0;

INSERT INTO DiploModifiers (Type, Description)
SELECT 'DIPLOMODIFIER_CIVIC_SAME', 'TXT_KEY_SPECIFIC_DIPLO_CIVIC_SAME' UNION ALL
SELECT 'DIPLOMODIFIER_CIVIC_DIFFERENCE', 'TXT_KEY_SPECIFIC_DIPLO_CIVIC_DIFFERENCE';

INSERT INTO LocalizedText
    (Language, Tag, Text)
VALUES
    ('en_US', 'TXT_KEY_SPECIFIC_DIPLO_CIVIC_SAME', 'Similar values in life bring us closer.'),
    ('en_US', 'TXT_KEY_SPECIFIC_DIPLO_CIVIC_DIFFERENCE', 'Different values in life set us apart.');

Code:
function OverSnowOneWinterMorn(iDiploModifier, iFromPlayer, iToPlayer)
    local iFromPlayerID = Players[iFromPlayer]
    local iToPlayerID = Players[iToPlayer]
    local iModifier = 0
    if (iDiploModifier == GameInfoTypes.DIPLOMODIFIER_CIVIC_SAME) then
        if iToPlayerID:HasPolicy(iDepotism) and iFromPlayerID:HasPolicy(iDepotism) then
            iModifier = iModifier - 1
        elseif iToPlayerID:HasPolicy(iHereditaryRule) and iFromPlayerID:HasPolicy(iHereditaryRule) then
            iModifier = iModifier - 5
        elseif iToPlayerID:HasPolicy(iPatronage) and iFromPlayerID:HasPolicy(iPatronage) then
            iModifier = iModifier - 3
        elseif iToPlayerID:HasPolicy(iRepresentation) and iFromPlayerID:HasPolicy(iRepresentation) then
            iModifier = iModifier - 3
        elseif iToPlayerID:HasPolicy(iPoliceState) and iFromPlayerID:HasPolicy(iPoliceState) then
            iModifier = iModifier - 3
        elseif iToPlayerID:HasPolicy(iUniversalSuffrage) and iFromPlayerID:HasPolicy(iUniversalSuffrage) then
            iModifier = iModifier - 7
        elseif iToPlayerID:HasPolicy(iConfederation) and iFromPlayerID:HasPolicy(iConfederation) then
            iModifier = iModifier - 3
        end
    end
    return iModifier
end
GameEvents.GetDiploModifier.Add(OverSnowOneWinterMorn)

Compare the difference and see what you did wrong.
 
Back
Top Bottom