1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Glory and Greatness, Development Thread

Discussion in 'Civ4 - Creation & Customization' started by seasnake, Dec 10, 2010.

  1. seasnake

    seasnake Conquistador

    Joined:
    Apr 21, 2006
    Messages:
    1,880
    Location:
    California, United States
    This is Glory and Greatness, the development thread for the mod. Seasnake and Baldyr are the authors, I'm handling XML and Artwork and Baldyr is handling Python.

    Glory and Greatness has one simple goal, to be a really awesome version of the Civ IV BTS. This has gone through a few concepts, but thanks to awesome support from Baldyr, it currently looks like this: 40 civs with one leader only, each civ will have 1-2 UBs and 2-3 UUs, with a variety of civ-specific unique abilities. The 40 civs include the base 34 and the Iroquois (Native America is changed to Sioux), Gran Colombia, Israel, Songhai, Siam, and Polynesia.

    This mod uses Blue Marble and Chuggi's Improved Leaders, and a modified version of GeoModder's Ethnic Citystyles and Varietas Delectat. There are also several small changes for balance sake/fun (E.G. spies now move two and Bureaucracy allows for unlimited Spy Specialists).

    First thing's first, we're working on the Unique Civ Abilities. The following list is the first vision for how each civ could be different. What Baldyr and I are asking for, dear readers, is for people who are in the know to weigh in on this list. We need to talk about how we can accomplish these ideas, if they are good ideas to begin with, suggestions for better abilities, discussions on balance, etc. Forum feedback will be, we hope, a huge reason Glory and Greatness will truly be an excellent mod for an excellent game.

    UPDATED 12/13/2010

    To clarify: Each civ has a unique Palace and a Unique Tech it starts the game with. So abilities can be based on their unique palace like a great wonder, or on tech (like the Mayans having the world centered).

    NOTES: Arsenal and Manufactuary are new buildings necessary to train certain units, Manufactuary for Artillery and Tanks, Arsenal for Cannons and Ships of the line, etc. Hit and Fade is Tsentom's skirmisher promotion, renamed to "Hit and Fade" because I hate that in the civpedia you click on the promotion and get the Malinese UU. I've done my best to choose evocative names for abilities, but I'm aware that it doesn't always correlate too well with ability. Suggestions appreciated.
     
  2. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    A very good and concise index! :goodjob: But maybe put the list of abilities into spoiler tags?

    I'll get to analyzing this stuff once I get the chance. Right now my hands are pretty full.

    Just to clarify: I don't think we need to use the unique Palaces or Techs for triggering/enabling any Python code. Because I already wrote a helper function for identifying the Civs. But I guess those are still needed for some XML based effects, so I won't complain any further about this. :p

    And yes, I do think this will be a bang-up mod! :king: All design credit belongs to you however - I'm just the code monkey. :lol:
     
  3. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Ok, these are my preliminary verdicts on the abilities not doable in with XML settings:
    If we use the custom DLL released by Asaf, then this is possible to do with CyPlayer.setExtraTerrainYield().
    This would be possible to do with the unitKilled event callback.
    You mean like bonuses on the map, somewhere in the vicinity of the starting location? :confused: It should be possible to do on the GameStart event callback.
    Spoiler :
    We need to define what plots types are priority though, so that we get reasonable results. Also how far away from the starting location those tiles can be located. (It would probably be fun to create a code that firstly looks for suitable tiles within the BFC of the capital to be. But if none are found, then increase the search area in layers until such plots are found.)

    These should be possible to do with the getUnitCostMod callback (CvGameUtils) but enabling the callback will in itself cause some lag, because the code will be evaluated every single time the game checks for units costs...
    Meaning, for example? :confused:
    I've done this before with the canDoCivic callback (CvGameUtils) - adds lag (but then again does all Python).
    This can be done with CyTeam.changeExtraMoves()
    This one I'm not sure how to implement. It wouldn't be reasonable to check all units every turn to see whether or not they are on unfriendly ground and give them a temporary combat boost. Perhaps something can be added to the SDK to enable this as a XML tag (somewhere) - or to expose some SDK function to Python. Any ideas, anyone?
    This one I already did.
    Spoiler :
    Code:
    def colombia(pCity, ePlayer, bConquest):
            """
            No Revolting in Captured cities.
            """
            if bConquest and isCivPlayer("Gran Colombia", ePlayer):
                    pCity.setOccupationTimer(0)

    While it seems possible to affect the unhappiness from drafting with CyCity.changeConscriptAngerTimer() it would be rather cumbersome to constantly check all cities with CyCity.getConscriptAngerTimer(). The problem being the lack of a game event that creates a call to Python on conscription.

    Any ideas? (Making a new XML tag would probably be an option.)
    Did it already.
    Spoiler :
    Code:
    def germany(pWinningUnit, pLosingUnit):
            """
            50 percent chance to capture barbarian units and get gold reward.
            """
            ePlayer = pWinningUnit.getOwner()
            if ( isCivPlayer("Germany", ePlayer)
                 and pLosingUnit.getDomainType() == eLand
                 and pLosingUnit.getOwner() == eBarbarian
                 and isProbabilityPercent(iGermanProbability, "germany") ):
                    captureUnit(ePlayer, pWinningUnit, pLosingUnit)
                    grantGold(ePlayer, iGermanGold)

    Also done.
    Spoiler :
    Code:
    def inca(eTech, ePlayer):
            """
            Free Tech on reaching Classical, Renaissance and Modern Eras.
            """
            if not isCivPlayer("Inca", ePlayer): return
            player = tPlayer[ePlayer]
            player.getData()
            lIncanEras = player.data
            if not lIncanEras:
                    lIncanEras = list(tIncanEras)
            eTechEra = gc.getTechInfo(eTech).getEra()
            ePlayerEra = player.CyPlayer.getCurrentEra()
            if lIncanEras[eTechEra] == True:
                    lIncanEras[eTechEra] = None
            elif lIncanEras[ePlayerEra] == None:
                    player.CyTeam.setHasTech(eTech, True, ePlayer, False, True)
                    lIncanEras[ePlayerEra] = False
            player.storeData(lIncanEras)

    Very doable on the cityBuilt event callback.
    It should be possible to intersect the game on the cityGrowth event and add the food with CyCity.changeFood().
    Code:
    +1 Food from Forest
    I have no real idea on this. It seems straight forward enough, but there doesn't seem to be anything in the SDK either. So it would probably require something new being added to the SDK.
    Done.
    Spoiler :
    Code:
    def japan(pUnit):
            """
            20 percent chance for a unit to heal fully after combat victory.
            """
            if isCivPlayer("Japan", pUnit.getOwner()) and isProbabilityPercent(iJapaneseProbability, "japan"):
                    pUnit.setDamage(0, False)

    Adding culture point to map plots would be more straight forward than to figure out what city should get it. Its Japanese units dying within own borders, then? :confused:
    As described in another thread, this is very doable with CyPlayer.chooseTech(). But it really only works for the human player, so a Mali AI would need something else to get the job done. Adding CyPlayer.AI_chooseFreeTech() to the Python API would do the trick, but is not entirely necessary.
    Yep.
    Spoiler :
    Code:
    def maya(pWinningUnit, pLosingUnit, ePlayer):
            """
            Enslave - 25 percent chance to get a Worker unit any time a land unit is defeated in combat.
            """
            if ( isCivPlayer("Maya", ePlayer)
                 and pLosingUnit.getDomainType() == eLand
                 and isProbabilityPercent(iMayanProbability, "maya")
                 and pLosingUnit.getUnitType() >= eWarrior ):
                    spawnUnit(ePlayer, pWinningUnit.getX(), pWinningUnit.getY())

    Indeed.
    Spoiler :
    Code:
    def netherlands():
            """
            Receive 3 percent interest on gold reserves each game turn (rounded down).
            """
            for pPlayer in list(player.CyPlayer for player in getCivPlayers("Netherlands")):
                    if not pPlayer.isAlive(): return
                    pPlayer.setGold(int(pPlayer.getGold() * ((iNetherlandsInterest + 100) / 100.0)))

    Spoiler :
    Code:
    def ottomanCapture(pWinningUnit, ePlayer, pLosingUnit):
            """
            5O percent chance to capture enemy ships and earn gold.
            """
            if pLosingUnit.getDomainType() == eSea and isProbabilityPercent(iOttomanProbability, "ottoman"):
                    captureUnit(ePlayer, pWinningUnit, pLosingUnit)
                    grantGold(ePlayer, iOttomanGold)

    Spoiler :
    Code:
    def ottomanCulture(pCity, ePlayer, bConquest):
            """
            Spread culture in conquered cities.
            """
            if bConquest:
                    pCity.changeCulture(ePlayer, iOttomanCulture, True)

    Should be possible to do with the goldenAge event callback.
    Spoiler :
    Code:
    def persia(ePlayer):
            """
            All land and sea units gain one extra movement point during Golden Ages.
            """
            if not isCivPlayer("Persia", ePlayer): return
            iExtraMoves = iPersianMoves
            if not tPlayer[ePlayer].CyPlayer.isGoldenAge():
                    iExtraMoves = - iExtraMoves
            for eDomain in range(DomainTypes.NUM_DOMAIN_TYPES):
                    if tPersianDomains[eDomain]:
                            tPlayer[ePlayer].CyTeam.changeExtraMoves(eDomain, iExtraMoves)

    Should be possible to do on the unitCreated event callback.
    Should be possible with the getBuildingCostMod callback (CvGameUtils) but would cause lag.
    I'm guessing getUpgradePriceOverride (CvGameUtils).
    Spoiler :
    Code:
    def russia(pUnit, pPlot):
            """
            Enemy units in Russian territory take damage when either moving or fighting.
            """
            eUnitOwner, ePlotOwner = pUnit.getOwner(), pPlot.getOwner()
            if ( isCivPlayerAlive("Russia")
                 and not eUnitOwner == ePlotOwner
                 and isCivPlayer("Russia", ePlotOwner)
                 and isAtWar(ePlotOwner, eUnitOwner) ):
                    if pUnit.movesLeft() == 0:
                            pUnit.changeDamage(5, eBarbarian)

    Might be possible but I'm not seeing any clear-cut Python implementations at the moment. Could get rather messy in any case.
    The goodyReceived event callback.
    While I already did this the latter part needs to be implemented.
    canUpgradeAnywhere callback in CvGameUtils?

    All of the above could of course be done with some SDK hack or another. If someone wants to do all these in C++ then that would cause less lag. :p
     
  4. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    I thought I might as well reveal what code is already done for this mod. This is the GGUtils module:
    Spoiler :
    PHP:
    ### Helper functions and assorted classes for the Glory and Greatness mod, by Baldyr

    from CvPythonExtensions import *
    import cPickle as pickle
    import PyHelpers

    gc 
    CyGlobalContext()
    Game CyGame()
    Map CyMap()
    Interface = 
    CyInterface()

    ### helper functions

    def getAdjacentTiles(iXiY):
            
    """
            Used for looping - yields a pair of x and y coordinates (integers) at a time
            corresponding to all adjacent map tiles.
            """
            
    for x in range(iX 1iX 2):
                    for 
    y in range(iY 1iY 2):
                            if 
    != iX and != iY:
                                    yield 
    xy
                                    
    def getBFC
    (iXiY):
            
    """
            Used for looping - yields one valid city radius plot index value (integer) at a
            time.
            """
            
    for x in range(iX 2iX 3):
                    for 
    y in range(iY 2iY 3):
                            if 
    Map.plot(xy).isCityRadius() or not Map.plot(iXiY).isCity():
                                    yield 
    Map.plotNum(xy)

    def getCivPlayers(name):
            
    """
            Used for looping - yields one CivPlayer class instance at a time.
            """
            
    for player in players.get(name, []):
                    yield 
    player

    def getCombatType
    (pUnit):
            
    """
            Returns the UnitCombatTypes enumerated value (integer) for pUnit.
            """
            
    return gc.getUnitInfo(pUnit.getUnitType()).getUnitCombatType()

    def getIndex(categoryentry):
            
    """
            Returns the enumerated index value (integer) of the specified entry belonging to
            the specified category, as specified by the XML.
            """
            
    key category "_" entry.replace(" ""_")
            return 
    gc.getInfoTypeForString(key.upper())

    def isAtWar(ePlayereRival):
            
    """
            Returns True if ePlayer's team is at war with eRival's team.
            """
            
    return tPlayer[ePlayer].CyTeam.isAtWar(tPlayer[eRival].team)

    def isCivPlayer(nameePlayer):
            
    """
            Returns True if the player corresponding to the ePlayer argument is present in
            the list of CivPlayer class instances.
            """
            
    for eCurrent in list(player.ID for player in getCivPlayers(name)):
                    if 
    ePlayer == eCurrent:
                            return 
    True
            
    return False

    def isCivPlayerAlive
    (name):
            
    """
            Returns True if any of the players supplied with the list of CivPlayer class
            instances is alive.
            """
            
    for pPlayer in list(player.CyPlayer for player in getCivPlayers(name)):
                    if 
    pPlayer.isAlive():
                            return 
    True
            
    return False

    def isCivPlayerCulture
    (namepPlot):
            
    """
            Returns True if pPlot has culture by any player with the name civilization
            attribute.
            """
            
    for ePlayer in list(player.ID for player in getCivPlayers(name)):
                    if 
    pPlot.isWithinCultureRange(ePlayer):
                            return 
    True
            
    return False

    def isCivPlayerOwned
    (namepPlot):
            
    """
            Returns True if pPlot is owned by any player with the name civilization attribute.
            """
            
    for ePlayer in list(player.ID for player in getCivPlayers(name)):
                    if 
    pPlot.getOwner() == ePlayer:
                            return 
    True
            
    return False

    def isHasMet
    (namepTeam):
            
    """
            Returns True if pTeam has met any member of a team with the name civilization
            attribute.
            """
            
    for eTeam in list(player.team for player in getCivPlayers(name)):
                    if 
    pTeam.isHasMet(eTeam):
                            return 
    True
            
    return False

    def isProbabilityPercent
    (iPercentdebug=""):
            
    """
            Returns True in iPercent cases out of 100. The debug message argument is optional.
            """
            
    return Game.getSorenRandNum(100debug) < iPercent

    class CivPlayer:

            
    """
            Each instance contains references to IDs and various class instances associated
            with the player corresponding to the ePlayer argument.
            """
            
            
    def __init__(selfePlayer):
                    
    self.ID ePlayer
                    self
    .CyPlayer gc.getPlayer(ePlayer)
                    
    self.civilization self.CyPlayer.getCivilizationType()
                    
    self.team self.CyPlayer.getTeam()
                    
    self.CyTeam gc.getTeam(self.team)
                    
    self.PyPlayer PyHelpers.PyPlayer(ePlayer)
                    
    self.data self.getData()

            
    def getScriptData(self):
                    return 
    self.CyPlayer.getScriptData()

            
    def getData(self):
                    
    scriptData self.getScriptData()
                    if 
    scriptData:
                            
    self.data pickle.loads(scriptData)
                    else:
                            
    self.data None

            def setScriptData
    (self):
                    
    self.CyPlayer.setScriptData(pickle.dumps(self.data))

            
    def setData(selfdata):
                    
    self.data data

            def storeData
    (selfdata):
                    
    self.setData(data)
                    
    self.setScriptData()

    # sets up player arrays

    lPlayers range(Game.countCivPlayersEverAlive())
    tCivilizations = ("Holy Rome""Byzantium""Portugal""Celt""Arabia""Gran Colombia""Germany""Inca""Japan""Maya""Netherlands""Ottoman""Persia""Russia""Scandinavia")
    playerslSorted dict(), list()
    tPlayer tuple(CivPlayer(ePlayer) for ePlayer in lPlayers)
    for 
    name in tCivilizations:
            for 
    player in list(tPlayer[ePlayer] for ePlayer in lPlayers):
                    if 
    player.civilization == getIndex("Civilization"name) and not player in lSorted:
                            
    lSorted.append(player)
                            if 
    name in players:
                                    
    players[name].append(player)
                            else:
                                    
    players[name] = [player]
     
  5. seasnake

    seasnake Conquistador

    Joined:
    Apr 21, 2006
    Messages:
    1,880
    Location:
    California, United States
    i have a mod that does this, it's the Salvager Trait. The Mod changes the CvEventManager thus:

    Spoiler :

    def onCombatResult(self, argsList):
    'Combat Result'
    pWinner,pLoser = argsList
    playerX = PyPlayer(pWinner.getOwner())
    unitX = PyInfo.UnitInfo(pWinner.getUnitType())
    playerY = PyPlayer(pLoser.getOwner())
    unitY = PyInfo.UnitInfo(pLoser.getUnitType())

    ###Salvager Trait START###

    iTrait = gc.getInfoTypeForString("TRAIT_SALVAGER")
    iWinner = gc.getPlayer(pWinner.getOwner())
    if (iWinner.hasTrait(iTrait)):
    cost = unitY.getProductionCost()
    gold = cost/15
    playerX.changeGold(gold)

    ###Salvager Trait END###



    no, I just mean in the XML for the Babylon palace I'll type give it BONUS_SILK under the free bonus line and give 2 types. Sort of like how Hollywood does hit movies.

    Tsentom (may his name be praised in song) scripted that out in Python, again in the event manager. It's from his Influential Trait:

    Spoiler :

    def onBeginPlayerTurn(self, argsList):
    'Called at the beginning of a players turn'
    iGameTurn, iPlayer = argsList

    ## Inf Trait Start ##

    pPlayer = gc.getPlayer(iPlayer)
    iTeam = pPlayer.getTeam()
    pTeam = gc.getTeam(iTeam)
    iTrait = CvUtil.findInfoTypeNum(gc.getTraitInfo,gc.getNumTraitInfos(),'TRAIT_CARTHAGE')

    if (pPlayer.hasTrait(iTrait)):

    for iPlayer in range(gc.getMAX_PLAYERS()):
    ppPlayer = gc.getPlayer(iPlayer)
    if ( (ppPlayer.isAlive()==true) and (ppPlayer.isBarbarian()==false) ):
    if ( gc.getTeam(ppPlayer.getTeam()).isVassal(iTeam) == true ):
    iGold = ppPlayer.getGold( )
    if ppPlayer.getGold( ) >= 5000:
    ppPlayer.changeGold( 50 )
    if ppPlayer.getGold( ) < 5000:
    if ppPlayer.getGold( ) >= 50:
    ppPlayer.changeGold( iGold//50 )
    else:
    ppPlayer.changeGold( 1 )

    ppPlayer.changeCombatExperience( +1 )

    ## Inf Trait End ##

    def onEndPlayerTurn(self, argsList):
    'Called at the end of a players turn'
    iGameTurn, iPlayer = argsList



    Here is from the Nationalist trait, again (i merged a lot of Mods into my last mod, Rise of Empires). It works pretty well, but maybe you know something more elegant.

    Spoiler :

    def onModNetMessage(self, argsList):
    'Called whenever CyMessageControl().sendModNetMessage() is called - this is all for you modders!'

    iData1, iData2, iData3, iData4, iData5 = argsList

    ## Nationalist code start

    if(iData1 == 1): ## Change Conscript Angry Time
    pPlayer = gc.getPlayer(iData2)
    pCity = pPlayer.getCity(iData3)
    pCity.changeConscriptAngerTimer(iData4)

    ## Nationalist code end

    print("Modder's net message!")

    CvUtil.pyPrint( 'onModNetMessage' )

    ...

    ## Nationalist code start

    player = gc.getPlayer(iPlayer)
    iTimeLeft = pCity.getConscriptAngerTimer()

    if player.hasTrait(gc.getInfoTypeForString('TRAIT_GERMAN')) and iTimeLeft > 0:
    CyMessageControl().sendModNetMessage(1, iPlayer, pCity.getID(), -iTimeLeft, 0)
    ##pCity.changeConscriptAngerTimer(iTimeLeft * -1)

    ## Nationalist code end



    YUP. It's a take on Tsentom's wonder, Terracotta Army.

    Spoiler :

    ## Terracotta Start ##

    iPlayer = unit.getOwner()
    pPlayer = gc.getPlayer(iPlayer)
    pPID = pPlayer.getID()

    b_Terra = gc.getInfoTypeForString("BUILDING_PALACE_JAPAN")
    obsoleteTech = gc.getBuildingInfo(b_Terra).getObsoleteTech()

    if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
    for iCity in range(pPlayer.getNumCities()):
    ppCity = pPlayer.getCity(iCity)
    if ppCity.getNumActiveBuilding(b_Terra) == true:
    iX = unit.getX()
    iY = unit.getY()
    for iiX in range(iX-1, iX+2, 1):
    for iiY in range(iY-1, iY+2, 1):
    pPlot2 = CyMap().plot(iiX,iiY)
    if pPlot2.isCity():
    pCity = pPlot2.getPlotCity()

    pPID = pPlayer.getID()
    pCC = pCity.getCulture(pPID)
    pCC = int( (unit.getExperience()))
    pCity.changeCulture(pPID, pCC, true)

    estiEnd = CyGame().getEstimateEndTurn()
    if ( estiEnd >= 1000 ):
    pCC2 = int(8)
    pCity.changeCulture(pPID, pCC2, true)
    elif ( estiEnd >= 700 ):
    pCC2 = int(4)
    pCity.changeCulture(pPID, pCC2, true)
    elif ( estiEnd >= 400 ):
    pCC2 = int(2)
    pCity.changeCulture(pPID, pCC2, true)
    elif ( estiEnd >= 300 ):
    pCC2 = int(1)
    pCity.changeCulture(pPID, pCC2, true)
    elif ( estiEnd < 300 ):
    pCC2 = int(1)
    pCity.changeCulture(pPID, pCC2, true)

    ## Terracotta End ##

    if (not self.__LOG_UNITKILLED):
    return
    CvUtil.pyPrint('Player %d Civilization %s Unit %s was killed by Player %d'
    %(player.getID(), player.getCivilizationName(), PyInfo.UnitInfo(unit.getUnitType()).getDescription(), attacker.getID()))



    But quite possibly there's a much easier way to do this, maybe though this will help with some of that.

    Tsentom's Strategic Trait has this feature, but it has one minor detail, it overrides attached great generals so that Great General units will have to pay, albeit half cost, for unit upgrades. So maybe this helps:

    Spoiler :

    def getUpgradePriceOverride(self, argsList):
    iPlayer, iUnitID, iUnitTypeUpgrade = argsList

    ## Str Trait Start ##

    pPlayer = gc.getPlayer(iPlayer)
    pUnit = pPlayer.getUnit(iUnitID)

    iPrice = gc.getDefineINT("BASE_UNIT_UPGRADE_COST")
    iPrice += (max(0, (pPlayer.getUnitProductionNeeded(iUnitTypeUpgrade) - pPlayer.getUnitProductionNeeded(pUnit.getUnitType()))) * gc.getDefineINT("UNIT_UPGRADE_COST_PER_PRODUCTION"))

    if ((not pPlayer.isHuman()) and (not pPlayer.isBarbarian())):
    pHandicapInfo = gc.getHandicapInfo(gc.getGame().getHandicapType())
    iPrice = iPrice * pHandicapInfo.getAIUnitUpgradePercent() / 100
    iPrice = iPrice * max(0, ((pHandicapInfo.getAIPerEraModifier() * pPlayer.getCurrentEra()) + 100)) / 100

    iPrice = iPrice - ((iPrice * pUnit.getUpgradeDiscount()) / 100)

    iTrait = CvUtil.findInfoTypeNum(gc.getTraitInfo,gc.getNumTraitInfos(),'TRAIT_ROME')

    if (pPlayer.hasTrait(iTrait)):
    iPrice = ((gc.getDefineINT("BASE_UNIT_UPGRADE_COST"))/2)
    iPrice += (((max(0, (pPlayer.getUnitProductionNeeded(iUnitTypeUpgrade) - pPlayer.getUnitProductionNeeded(pUnit.getUnitType()))) * gc.getDefineINT("UNIT_UPGRADE_COST_PER_PRODUCTION")))/2)

    if ((not pPlayer.isHuman()) and (not pPlayer.isBarbarian())):
    pHandicapInfo = gc.getHandicapInfo(gc.getGame().getHandicapType())
    iPrice = ((iPrice * pHandicapInfo.getAIUnitUpgradePercent() / 100)/2)
    iPrice = ((iPrice * max(0, ((pHandicapInfo.getAIPerEraModifier() * pPlayer.getCurrentEra()) + 100)) / 100)/2)

    iPrice = ((iPrice - ((iPrice * pUnit.getUpgradeDiscount()) / 100))/2)

    return iPrice

    ## Str Trait End ##




    Might be for the best then if I just made it so that units got a promotion like Medic I. No need to complicate things too much.

    I've downloaded several of the Tsentom Traits and Wonders, as well as work done by other people, which is one the bases upon which I'm trying select this Unique Powers. I'm happy to e-mail you more, but it often seems you have a solution that is much cleaner.

    The big one will be the forest improvement for the Iroquois, if we can't do that we'll need to come up with something else fast, that one is sort of the Iroquois bread and butter ability.

    As always awesome work so far.
     
  6. seasnake

    seasnake Conquistador

    Joined:
    Apr 21, 2006
    Messages:
    1,880
    Location:
    California, United States
    The first civ is done: America.

    America now has the B-17, which replaces the bomber and combines longer range with a heavier payload. The new American Building is the Town Hall, a Courthouse replacement that gives 3 beakers to the city.

    Look at the screenshots, you'll see the civpedia page, the new building and unit, the american palace (looking like the Capitol Building in DC), and the abilities in action (the free specialist and the town producing two hammers).
     

    Attached Files:

  7. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    seasnake, could you please put all the code you posted into
    Code:
     tags, because Python becomes nigh unreadable without the indentation. (Its not just for formatting the code - it actually determines what line of code belongs to the body of what statement.)
    
    The Nationalist code seemed weird to me - I've never looked into CyMessageControl... :p What is a Mod Net Message? :confused:
    
    edit: I think I figured out the conscription anger timer thing. The key is using the CityDoTurn event callback. So Germany is in the bag, then. :D
    
    edit2: If I understand this correctly, the Carthaginian vassal boost should basically be +1 combat experience counted towards the next GG and some additional gold (1-50 depending on the current state of the treasury) on every turn. This is it?
    
    edit3: The Terracotta Army wonder code only seems to be effective when the unit is adjacent to any city. So the extra culture goes to that city. Would you like to increase the range? Should this only work inside Japanese territory?
     
  8. j_mie6

    j_mie6 Deity

    Joined:
    Dec 20, 2009
    Messages:
    2,963
    Location:
    Bristol (uni)/Swindon (home)
    I have to agree with baldyr, you need to put your indentations in. I call it defining parent tags (authough I'm sure there is a much better name for it)

    thought I would check this out as it came up in my own discussion thread!
     
  9. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    edit: Added another method to the wish-list. The follow-up post is also updated.

    We need to compile a list of SDK changes requests for Asaf's consideration. Looking at the index of all the abilities I would like these methods to be available in the Python API:
    Spoiler :
    CyPlayer.AI_chooseFreeTech()
    CyPlayer.setExtraFeatureYield( eYieldType, iExtraYield )
    CyTeam.setExtraForeignCombat( iCombatBonus )
    CyTeam.setExtraDomesticCombat( iCombatBonus )
    CyTeam.setUnitsCanHealInForeignTerritory( bEnable )

    All but the first one might as well be made available as new XML tags - there is no benefit from running these methods on the GameStart event callback instead of loading the settings with Civ4CivilizationInfos.xml.

    seasnake, you could take a look at the change log of Asaf's custom DLL for ideas for new/replacement abilities. Included are new Python methods:
    Spoiler :
    CyPlayer.changeCityDefenseModifier(int iChange)
    CyPlayer.changeWarWearinessModifier(int iChange)
    CyPlayer.changeDistanceMaintenanceModifier(int iChange)
    CyPlayer.changeNumCitiesMaintenanceModifier(int iChange)
    CyPlayer.setCitiesCultureStrengthModifier(int iValue)
    CyPlayer.setExCitiesCultureStrengthModifier(int iValue)
    CyCity.changeExtraDefense(int iChange)
     
  10. seasnake

    seasnake Conquistador

    Joined:
    Apr 21, 2006
    Messages:
    1,880
    Location:
    California, United States
     
  11. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Make sure to copy-paste the code again - not to try and indent the code manually, line by line.

    Also, its a good thing that you post the code you already found/used. Looking at sample code for these things makes it obvious what should - and shouldn't - be done. I'll write everything up from scratch anyway (copy-paste is not programming :p) and most of the time the code can be made to be more efficient in the process. But more than often there really is no point in re-inventing the wheel, is there? (I do however insist on fixing things, even if they aren't technically broken. :rolleyes:)
     
  12. seasnake

    seasnake Conquistador

    Joined:
    Apr 21, 2006
    Messages:
    1,880
    Location:
    California, United States
    Dang it, it looks good but then I post it and it flubs.

    I'm going to prepare a word document or something and attach it to post, with the indents intact that way.
     
  13. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    You realize that you need to use the
    Code:
     tags, right? Because otherwise the BB will just delete all that indentation once you post the code.
    
    edit: And you don't need to fix that post if it is causing you issues. But you should make a habit of using the code tag in the future whenever you're posting code (Python, XML or other). I think I already have what I need.
     
  14. Asaf

    Asaf Sleep Deprived

    Joined:
    Mar 22, 2010
    Messages:
    1,326
    I'll take a look at it some time later this week (hopefully).
    I have a few things I need to do first, but I don't mind adding these to the DLL.

    Can you just give a short description for each, just to make sure we're on the same page?
     
  15. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    edit: Post has been rewritten.

    :goodjob:

    This is supposedly already in the SDK (CvPlayerIA) and needs to be exposed to Python.

    This should work like setExtraTerrainYield() and seExtraPlotTypeYield().

    Should give a combat bonus to all units on unfriendly territory.

    Should give a combat bonus to all units in friendly territory.

    Adds to the healing rate of units in hostile territory.

    All methods might as well belong to the CyPlayer class. I just figured that some of them would be more convenient to put in CyTeam, but I really wouldn't know.
     
  16. God-Emperor

    God-Emperor Deity

    Joined:
    Jul 18, 2009
    Messages:
    3,551
    Location:
    Texas
    And food from desert for Arabia. I noticed that they also get "gold" from desert. No plot normally yields gold, since gold is not a yield type. They yield commerce, which becomes gold (or research, culture, or espionage) based on the slider settigns. If gold is what is really wanted, that could be difficult since there is no way to display it in the normal plot yield displays...
     
  17. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Nope, Desert is a TerrainType not a FeatureType, so the Arabian ability is handled with another one of Asaf's methods.

    I'm guessing it should read "commerce" (as in "little gold coin icon").
     
  18. God-Emperor

    God-Emperor Deity

    Joined:
    Jul 18, 2009
    Messages:
    3,551
    Location:
    Texas
    Oops. I don't know why, but I was thinking flood plains.
     
  19. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Aha, double-misunderstanding, then. :p (Its Flood Plains and not Desert that gives the extra yields, right?)

    Then we urgently need Asaf's new DLL!
     
  20. seasnake

    seasnake Conquistador

    Joined:
    Apr 21, 2006
    Messages:
    1,880
    Location:
    California, United States
    Domestic for the Iroquois, but in Enemy territory for France. Sort of duplicating the effect of the V Foreign Legion but for all troops of France.

    Right, commerce. Sorry for the misunderstanding.
     

Share This Page