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

Introducing: PyScenario - easy-to-use scenario event scripting for RFC

Discussion in 'Rhye's and Fall Modmods' started by Baldyr, May 16, 2010.

  1. Leoreth

    Leoreth 心の怪盗団 Moderator

    Joined:
    Aug 23, 2009
    Messages:
    34,318
    Gender:
    Male
    Location:
    Leblanc
    It's usually only a few techs, isn't it? I can't imagine a purpose for knowing the first inventor of every tech.
     
  2. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    What I mean is, that PyScenario is not a mod-mod - its a scenario event scripting tool. How would I know what Techs the scenario maker needs to check? So I basically need this to work with any Tech, regardless. Building a master index of all Techs and setting a value each time one is acquired is one way to go. Not the preferred way, obviously...
     
  3. Leoreth

    Leoreth 心の怪盗団 Moderator

    Joined:
    Aug 23, 2009
    Messages:
    34,318
    Gender:
    Male
    Location:
    Leblanc
    I see. Maybe you could get around the giant index by setting up two small ones, where the first tracks which tech index i saves and the other if it has already been discovered?

    It's still clunky, but I guess for something with as many possibilities as this, the DLL might be the better address anyway, if you're going for elegance.
     
  4. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    No index if I can help it, but we'll just have to see about that. And the application is named PyScenario because its done in Python. (And that's because I don't know any C++. :lol:)
     
  5. Leoreth

    Leoreth 心の怪盗団 Moderator

    Joined:
    Aug 23, 2009
    Messages:
    34,318
    Gender:
    Male
    Location:
    Leblanc
    I'm already curious how you will solve it :)
     
  6. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Well, I'm gonna start with trying out CyGame.countKnownTechNumTeams() in the Python console...
     
  7. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    I'm getting confusing results in the Python console, but this function surely counts the number of teams that has a Tech?
    Code:
    int CvGame::countKnownTechNumTeams(TechTypes eTech)
    {
    	int iCount = 0;
    
    	for (int iI = 0; iI < MAX_TEAMS; iI++)
    	{
    		if (GET_TEAM((TeamTypes)iI).isEverAlive())
    		{
    			if (GET_TEAM((TeamTypes)iI).isHasTech(eTech))
    			{
    				iCount++;
    			}
    		}
    	}
    
    	return iCount;
    }
    So I'll just go with the Python representation of it then and see if it works. :p
     
  8. Leoreth

    Leoreth 心の怪盗団 Moderator

    Joined:
    Aug 23, 2009
    Messages:
    34,318
    Gender:
    Male
    Location:
    Leblanc
    From my understanding it does.
     
  9. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Attached is a custom version of the tech() Condition:

    tech( eTech=None, eEra=None, bFirst=None )

    The bFirst setting affects other both settings - if set to True then the Civ receiving the Tech must be the first to discover the specified Tech - or to be the first one to enter the specified Era. A False setting will only fire if its not the first time the Tech is discovered or the Era is reached.
     

    Attached Files:

  10. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    By the way, I believe I just figured out a way to add signs/landmarks to the map with Python - and to remove them. I actually didn't know that was doable.

    This probably means that there will be a sign() Action in the next PyScenario update. :D A Trigger without a Target Players then creates a "landmark" visible to all players. And the default name will be the Trigger label, but you can of course override this with a optional string setting. I'm not sure how the tile labels will be removed however, but what about an augmented erase() Action? Like a bSigns setting. Spawning a city will remove any sign on that plot, of course. But perhaps the city naming could be controlled by whatever the sign says?

    Or perhaps the signs can be part of the terrain() Action instead, I dunno yet. But I'm exited none-the-less. (In my own scenario Villages and Towns will spawn dynamically on the map, and now I can add signs to them. :king:)
     
  11. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
  12. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
    Code:
    from PyScenario import *
    from Custom import *
    Like that? (never remember :p )

    [EDIT]: OK, it worked. What happens if I build national wonder in a city if another city already has the wonder? Like palace? Two national wonders or it will disappear from other city?
     
  13. Alexius08

    Alexius08 Emperor

    Joined:
    May 28, 2010
    Messages:
    1,108
    Or I had [insert national wonder that is not a palace here] built in one of my cities, then I capture an enemy city that also had it?
     
  14. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    National Wonders are auto razed on acquisition, so normally one player can't get two of them.

    But if you use Python (or PyScenario, same difference) to give a city a NW that already exists - who knows? Try it?
     
  15. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    I'm doing the Golden Age thing next but I realized that the method could potentially be useful for more things. What other features could be covered by the same method? I'm thinking stuff like Anarchy, Plague and Great Depression. Anarchy is already covered by the civics() method however, and I'm not so sure I can hack into Plague.py or Stability.py without making changes in the actual modules. And I'd rather not.

    edit: Looking the RFC code I can't see why plagues and depressions couldn't be triggered from PyScenario.py without editing the affected modules themselves.

    Any ideas before I start testing the Golden Ages?

    edit: What about naming a golden age method renaissance()? Its one word and implies that the Civ will be experiencing a rebirth of sorts. What about rebirth()? It might be too similar to respawn() and reset() though... I have no idea what to call something that could be used to set golden age, plague and depression turns however! Perhaps another method then, like calamity()?
     
  16. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
    As for me you could name it jabberwack() and I'll be happy :p calamity() sounds OK :p
     
  17. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Attached is the custom Action rebirth():

    rebirth( iNum=None, bScaling=True, ePlayer=None )

    The method adds/subtracts iNum turns worth of Golden Age for the Target Player. (bScaling adapts this to the current game speed.) A None setting will auto-detect the default number of turns for that player (always scaled for speed). The optional ePlayer setting can be used to override any Target Player for this method only.
    Code:
    from Custom import *
    Trigger.rebirth = rebirth
     

    Attached Files:

  18. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Could you give me an example of use for this?
     
  19. LuKo

    LuKo The Royal Guard

    Joined:
    Aug 28, 2006
    Messages:
    1,501
    Location:
    Poland
    Trigger("A").fired("B",False).message("Prepare!")
    Trigger("B").fired("A").fired("B",False).units( a lot of barbarians)
    Trigger("C").stability(-20).fired("B").defire("A")

    If stability() CHECKS stability, not changes it.
     
  20. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    So, in other words, you want Triggers "A" and "B" to only fire once? But once Trigger "C" fires you need to basically reload Trigger "A" so that it doesn't register a fired any more?

    Other than that, due to the ad hoc nature of the fired() Condition you wouldn't be able to make a reference to the second Trigger in the first one. Because when the first Trigger is initialized it won't recognize the label of the second one.

    Also, the second Trigger is referencing itself - it might fail on the same principle as the first one.

    If something like what you propose was to work I might have to rewrite the whole code for Trigger binding, I'm afraid. I'm not sure if I have the time for all the testing and debugging involved. Stuff like move the initialized Trigger objects into a dictionary from the current list setup. That should fix the indexing once-and-for-all - as long as two Triggers don't have the same label.
     

Share This Page