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

Fixing General Winter

Discussion in 'Rhye's and Fall Modmods' started by Baldyr, Sep 25, 2010.

  1. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    This is the current Russian UP from UniquePowers.py:
    Code:
    #------------------RUSSIAN U.P.-------------------
    
            def russianUP(self):
                    pRussia = gc.getPlayer(iRussia)
                    teamRussia = gc.getTeam(pRussia.getTeam()) 
                    for x in range(tRussianTopLeft[0], tRussianBottomRight[0]):
                            for y in range(tRussianTopLeft[1], tRussianBottomRight[1]):
                                    pCurrent = gc.getMap().plot( x, y )
                                    if (pCurrent.getOwner() == iRussia):
                                            iNumUnitsInAPlot = pCurrent.getNumUnits()
                                            if (iNumUnitsInAPlot):
                                                    for i in range(iNumUnitsInAPlot):
                                                            unit = pCurrent.getUnit(i)
                                                            if (teamRussia.isAtWar(unit.getOwner())):
    ##                                                                print("hp", unit.currHitPoints() )
    ##                                                                print("damage", unit.getDamage() )
                                                                    unit.setDamage(unit.getDamage()+8, iRussia)
    ##                                                                print("hp now", unit.currHitPoints() 
    ##                                                                print("damage", unit.getDamage() )
    Firstly, the tiles within the defined map coordinates are checked every single turn (after the Russian spawn). This is wasteful since most of the time there will be no foreign unit in this area - and unless they are an invading force the rule won't apply anyway.

    Secondly, the AI loses its capacity to carry out offensive operations because every single unit gets automatic damage on every turn - even while stationary and healing previous damage. So it would help if only moving units were affected by this - healing is already hampered outside of friendly territory.

    This is why I'm proposing a mod-mod (or rather a mod-mod-component) that relies on the onUnitMove callup from the SDK. This event needs to be included in CvRFCEventHandler.py and the call to russianUP() needs to be located here instead of being connected to the onBeginGameTurn via UniquePowers.UniquePowers.checkTurn().

    This is what the improved russianUP() method could look like:
    Code:
            def russianUP(self, pUnit, pPlot, pOldPlot):
                    iOwner = pUnit.getOwner()
                    iOwnerTeam = gc.getPlayer(iOwner).getTeam()
                    if pRussia.isAlive() and teamRussia.isAtWar(iOwnerTeam):
                            if iOwner != [COLOR="Red"]pOldPlot.getOwner() == [/COLOR]pPlot.getOwner() == iRussia:
                                    pUnit.setDamage(pUnit.getDamage() + [COLOR="Red"]8[/COLOR], iRussia)
    Also, these assignment statements should go into the top of the module - there is no need to define these every single time:
    Code:
    pRussia = gc.getPlayer(iRussia)
    teamRussia = gc.getTeam(pRussia.getTeam())
    This would also mean that the invading unit must move from one Russian tile into another Russian tile, which is somewhat less severe as the current rule. But this can easily be edited out by deleting the red marked code above. Or the amount of damage could be increased to compensate.

    Thoughts? Ideas?
     
  2. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
    In your version "General Winter" would fight even in the Mexico? Doesn't seem right.
    Winter was deadly for static armies, not so much for moving ones.
    Generally ( :) ) I like the idea. But dmg should be applied when army attacked (and didn't move) as well. Or even harder. And I like version without red code :p
     
  3. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    The problem with damaging stationary units is that they will stay stationary since the AI won't move then until they are (more or less) fully healed. So a healing enemy shouldn't take (any more) damage, or the units will be stationary most of the time until the war is over. (The proper way would be to change the AI behavior in the SDK however.)

    But you're of course right about the latitude issue - the rule of General Winter should only apply in temperate and above regions. The easiest way would be to implement a check for the Y coordinate:
    Code:
    if pPlot.getY() > iLimit:
    (Where iLimit would be the Y coordinate of the latitude. Any suggestions?)

    Personally I'm going to extend this into all enemy territory - not only within Russian borders. Call it a "attrition mod" then. :p And General Winter can make a comeback as a battlefield event - affecting both sides of the conflict within some Arctic or Subarctic region. (Not every single turn, obviously.) But nothing connected to the Russian player as such. (So there would be another Russian UP, then.)
     
  4. Leoreth

    Leoreth 心の怪盗団 Moderator

    Joined:
    Aug 23, 2009
    Messages:
    33,364
    Gender:
    Male
    Location:
    Leblanc
    Looks good, the current UP is really quite abusable against the AI.

    But I agree with LuKo that it should only affect Russia proper.
     
  5. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    A Russia that is expanding beyond its historical bounds is likely to collapse anyway, right? So a Russian Mexico isn't really such a huge issue.

    But of course its possible to restrict the area of effect in the X axis also.
    Code:
    if pPlot.getX() > 64 and pPlot.getY() > 48:
    Since you're both actively working on your own mod-mods - why not try something like this out? I'd be interested in hearing about any actual testing. :D
     
  6. Leoreth

    Leoreth 心の怪盗団 Moderator

    Joined:
    Aug 23, 2009
    Messages:
    33,364
    Gender:
    Male
    Location:
    Leblanc
    I've already made a mental note on the inside of my forehead ;) It's just that I'm already working on multiple features simultaneously and don't want to start testing another. I only hope I don't forget this. Maybe an additional note on the other side of my forehead won't hurt :D
     
  7. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    So this could be the whole thing, then (without all the annoying indentation or ridiculously elongated lines):
    Code:
            def russianUP(self, pUnit, pPlot, pOldPlot):
                    iOwner = pUnit.getOwner()
                    if ( pPlot.getX() > 64 and pPlot.getY() > 48 \
                         and pRussia.isAlive()\
                         and teamRussia.isAtWar(gc.getPlayer(iOwner).getTeam())\
                         and iOwner != pOldPlot.getOwner() == pPlot.getOwner() == iRussia ):
                            pUnit.setDamage(pUnit.getDamage() + 8, iRussia)
     
  8. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
    I would include it if units who fought this turn (but didn't actually move, because they have withdrawn or there is more units on the attacked plot) would take the damage as well.
     
  9. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    I'm not sure how to implement something like this, at least without adding additional code in several places. All I could find in the API was CyUnit.isCombat() - I'm assuming that CyUnit.isDefending() and CyUnit.isFighting() expire once the actual action is over? :confused:

    What do you mean by "or there is more units on the attacked plot"? One single unit takes no attrition but two units will? :confused:
     
  10. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Or, if non-moving units take damage then it breaks my basic idea. Because the code would be executed on the onUnitMove call up. So we're back at the onBeginGameTurn call up looping coordinates, then? This is already in the mod and working, so no need to "fix" that, right?
     
  11. Jarlaxe Baenre

    Jarlaxe Baenre Emperor

    Joined:
    Feb 17, 2010
    Messages:
    1,959
    Location:
    Calgary, Alberta, Canada
    How about you add a promotion called ''Russian Winter" that is unobtainable, and then give it to enemy units inside Russian borders and remove it when they leave. It could reduce their strength X percent, or other things like that.
     
  12. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    I actually can't do anything with XML modding myself at this point. But you're welcome to try such an approach... Anything that gets the job done, I guess.
     
  13. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
    So maybe dmg at the end of fight?
     
  14. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Hmm... That would be onCombatResult, then? But what units that are stationary/moving that aren't involved in combat?
     
  15. Ajidica

    Ajidica High Quality Person

    Joined:
    Nov 29, 2006
    Messages:
    19,285
    Could this not apply to the Mongols? They weren't really fazed by the winter and actualy used it against the Russians by traveling over frozen rivers.
     
  16. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
    onCombatResult AND onUnitMove ]:-> Let them suffer!
     
  17. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    My own mod-mod idea ("Attrition mod-mod") would apply the General Winter rule to all enemy territories. But, some unit types - like primitive melee units or nomadic units like Horse Archers - would not be affected by attrition. Because they aren't dependent on supply lines but can rather "live off the land". This also applies to some modern unit types, like the Paratrooper or really any unit with the Commando promotion.

    I actually already did this - it was my first programming exercise some six months ago. But I never got it to work exactly how I wanted, so I never published any of it. Such things should really be done in C++ because of the lag involved, but if I can figure out a way to do these things with Python only - who knows? I know a lot more today than I did back then, after all.
     
  18. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    So that would be double the damage if you move and fight then? And stationary units (who are healing anyway) would be spared any further damage?
     
  19. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
  20. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    So what exactly is supposed to happen onCombatResult then? Will only the foreign unit that survives the combat get the (additional) damage - or all units on that tile. (Because there was a battle and the entire stack should get punished, right?)
    Code:
            def russianUP(self, argsList):
                    bCombatResult = len(argsList) == 1
                    if bCombatResult:
                            pUnit = argsList[0]
                            pPlot = pOldPlot = pUnit.plot()
                    else:
                            pPlot, pUnit, pOldPlot = argsList
                    iOwner = pUnit.getOwner()
                    if ( pPlot.getX() > 64 and pPlot.getY() > 48 \
                         and pRussia.isAlive()\
                         and teamRussia.isAtWar(gc.getPlayer(iOwner).getTeam())\
                         and iOwner != pOldPlot.getOwner() == pPlot.getOwner() == iRussia ):
                            if bCombatResult:
                                    for i in range(pPlot.getNumUnits()):
                                            pUnit = pPlot.getUnit(i)
                                            if pUnit.getOwner() == iOwner:
                                                    pUnit.setDamage(pUnit.getDamage() + 5, iRussia)
                            else:
                                    pUnit.setDamage(pUnit.getDamage() + 5, iRussia)
    The additions actually make this a dual purpose method. The by passing it the argsList from each SDK call-up the method will know how to extract/fetch all the values it needs. So the method invocation will be the same for both onUnitMove and onCombatResult:
    Code:
    self.up.russianUP(argsList)
    The only thing missing is to add the onUnitMove() method to CvRFCEventHandler module. Under def __init__:
    Code:
                    eventManager.addEventHandler("unitMove",self.onUnitMove)
    And add the onUnitMove() method itself:
    Code:
            def onUnitMove(self, argsList):
                    self.up.russianUP(argsList)
    edit: Note that I lowered the actual amount of damage from 8 to 5 (for a combined total of 10 for both moving and fighting). The two types of attrition could however be different values, like 4 and 6 respectively.
     

Share This Page