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

I didnt really read the details on that post properly.

But it seems obvious to me if you want to make anychanges now is the time to make them. Theres only been a couple of scenarios made.

You know if you stay your'll be wanting to make the change later you say it yourself

"This is still in beta-testing, after all"
 
Oh, there will be changes. I was just wondering what the users actually would prefer. As they have probably worked more with the application than I've managed to do myself.

And as long as I don't touch the current methods there will no backwards comparability issues what-so-ever.
 
I'm guessing that everyone is away on holiday or at least not doing any scenario making at the moment. :rolleyes:

Well, I'm hacking away on the next PyScenario beta release as I just managed to, against some pretty stiff hurdles, make the methods I needed for my own scenario work. Right now I'm busy compiling the source code for the update, incorporating most of the stuff recently discussed on this board.

Two things previously released in Custom modules haven't made the cut at the moment, however. The first one is the addition to the flip() method requested by LuKo (I believe). Has anyone tested this any? (It involved a bRaze setting that would potentially make AI Civs not disband flipping cities. I only know that the actual flipping part works, but haven't been able to do the testing required to see if there will be any razing.)

The second is also one of LuKo's requests. Or, rather something we tried out before I succumbed and made the change to the check() method that he originally requested. Namely the alive() method featured in another Custom module. Is it sufficient to have this functionality in the check() method or would the alive() method actually be useful? (The idea is not to jump on every opportunity to expand the API. Not at the moment, at least.)

Other than that, I'll begin testing things out shortly and then I can start working on the documentation involved. So expect an update within a week, at least. And a small mod-scenario named Spartacus! The Story of the Roman Servile Wars is due shortly thereafter. :D It incorporates a custom Action than can be used for creating "self-fueling" rebellions. :king: (This method will not become a part of the PyScenario standard library, as it is too specific, but can of course be imported as a Custom module to any PyScenario script. There are some options for customization in the Custom module itself though.)
 
So the new update is live!

Besides final versions of most of the requested methods posted here lately - and quite a few fixes and changes - the main feature this time around is probably that you can now enter the unit AI type as an integer value! :goodjob:

Also, you can enable Python exception during reload of the Scenario module (these were axed in a previous update, as an invalid scenario script doesn't equal a bug report) by changing the line #27 in the PyScenario.py file to:
Code:
bDisplayDebugMessages = True
Note however that this will also enable tons of debug messages printed in the Python Debug Log, which will add lag to your scenario. So make sure to change it back once you've managed to get your scenario working:
Code:
bDisplayDebugMessages = [B]False[/B]
See the change log for all the goodness. :king:
 
This looks interesting. I probably wouldn't find a use for it- since I don't really mod RFC- but it's still very interesting. It could probably be adapted for vanilla BTS or other mods too.

Anyway, I don't know if you'd be interested in this, but I recently took a look at your Python code and it would be very easy to make scenarios as plugins rather than all part of the same file- allowing users to have multiple PyScenario scripts installed without manually merging the Scenario.py files.

So easy, in fact, that I just did it. I haven't tested it, but the same method worked for a piece of independent Python software.

I can post it after I verify that it works.
 
This looks interesting. I probably wouldn't find a use for it- since I don't really mod RFC- but it's still very interesting. It could probably be adapted for vanilla BTS or other mods too.
This is the beta-version and is made especially for RFC. The Alpha build will probably be mod-independent but rather built around the BUG infrastructure. Then the final version can be adapted to specific mods, like RFC.

Anyway, I don't know if you'd be interested in this, but I recently took a look at your Python code and it would be very easy to make scenarios as plugins rather than all part of the same file- allowing users to have multiple PyScenario scripts installed without manually merging the Scenario.py files.
Yeah, its very easy to do. But I haven't bothered confusing my beta-testers with it.

In fact, it should be as easy as to import the other PyScenario script into the first one. In fact, you could import as many scripts as you like. But I haven't actually tested it myself either... (Its not any kind of priority at the moment, but I don't foresee any problems with it either.)
 
Yeah, its very easy to do. But I haven't bothered confusing my beta-testers with it.

In fact, it should be as easy as to import the other PyScenario script into the first one. In fact, you could import as many scripts as you like. But I haven't actually tested it myself either... (Its not any kind of priority at the moment, but I don't foresee any problems with it either.)

It's actually much simpler than that (at least, for end users)- you can set it up so PyScenario imports all Python files in a specific folder automatically. It relies on four things:

1. Python understanding any folders with a __init__.py file as their own class (also called a package)
2. The __import__('modulename') function, which imports the string modulename (or tries to)
3. os.walk(pathname), which lets you walk around all files and folders in a directory
4. The ability to modify the list of paths where Python looks for modules to import

What actually happens is the folder with its __init__.py file is treated as a package (collection of modules), and by saying "import foldername" you're actually importing foldername\__init__.py. Then in __init__.py, there would be code that loops around all files in the folder and imports them all.
 
It's actually much simpler than that (at least, for end users)- you can set it up so PyScenario imports all Python files in a specific folder automatically.
That is very interesting, actually. :goodjob: I'll be sure to revisit the packages topic once I get going on the Alpha/BUG version.

In the meanwhile, the importing thing should work. But the idea has been all-along that users should be able copy-paste content from each-others scenarios, maybe modify it or just use it in another context. Merging whole scenarios would be as easy, unlike merging regular Python modules. (With all the issues that indentation, classes and scriptData can cause.)

Also, I don't view PyScenario a modding tool as such. Its targeted at scenario makers who don't know any programming. If someone wants to mod RFC they should learn Python, at the very least...
 
What about my requests? :)
Argh! :p

I've been working on those for the past week, but never got around to testing everything properly. I was thinking you won't be back for at least a day or two... :lol:

I'll get back to you on this shortly. :D

edit: In the meanwhile - did you ever manage to verify whether the custom flip() method worked as you wished? Because once we can rule that fix out there is another thing we could try...
 
Ok, here they are:

migrate( iChange, eNationality=None, bSettlers=False, bWorkers=False, bRefugees=False )
The boolean arguments are for negative iChange only. One population point equals one settler or two workers. The last argument determines whether or not the spawned units belong to the city owner or to eNationality.

yields( iFood=None, iProduction=None, iCommerce=None, iHappiness=None, iHealth=None )
This takes both positive and negative values and the bonus/penalty is accumulative.

output( eBuilding, iFood=None, iProduction=None, iCommerce=None, iHappiness=None, iHealth=None, iGold=None, iResearch=None, iCulture=None, iEspionage=None )
This only takes positive numbers and the values don't stack.

Maybe there should also be a tCoords argument for these methods?

Code:
from Custom import *
Trigger.migrate = migrate
Trigger.yields = yields
Trigger.output = output
 

Attachments

How does it work? I define civ in trigger(), use output() and get for example +1 happiness for every barrack? And if I define area/city I get the effect just in the city?

[EDIT]: Another request (yeah, I'm annoying, I know)- stability check stabpoints( iNum = 0, bHave = True )

And another question:
Spoiler :
Trigger.war = war
Trigger.check = check
Trigger.owned = owned
Trigger.heads = heads
Trigger.flip = flip

above triggers are all included in new version and I can get rid of them?
 
How does it work? I define civ in trigger(), use output() and get for example +1 happiness for every barrack? And if I define area/city I get the effect just in the city?
Yeah, you figured it out. :goodjob:

I don't know how useful these methods will be however. Because if you give all Roman cities a food bonus with yields() - or give all Roman Granaries a similar bonus with output() - for conquering some Egyptian city or whatever - what if the Romans lose that city? The bonuses would remain in effect...

You could of course define a Trigger that makes all Roman cities/Granaries lose that bonus - but what about cities that weren't Roman at the time of the original conquest? (Like newly founded cities?)

But it was your idea so come up with a solution! :D
 
I just wonder if the trigger is about Egyptian city is it possible to fit in the same trigger additional food for Rome (of course I can do 2 triggers, but the less triggers the better. About conquered Roman cities solution is very simple- I add bonuses to the palace only :) )

BTW: don't miss my edit :P
 
What does the bHave argument do in your suggestion?

You can simply delete the import statement ("from Custom import *") for custom modules you're not using any more. But then you also need to delete the assignment statements that follow - those were the ones you were asking about. Any such assignment you delete makes PyScenario use the official version of that method instead (of the custom one).

But note that I never incorporated the new argument for the flip() method so you'd still need to use that Custom module. In fact, you need to use both that one and the one I posted before. Do you know how to use two Custom modules or simply merge them into one?

Does it have to be an Egyptian city? Do you have to specify Rome as a Roman city? Why not simply look for the coordinates of the city in Egypt (it could be Babylonian or something) and then add the bonus to the city at the Rome coordinates. Or some combination whereof.

Looking at the API I see that the lost() method offers three ways of specifying the city: name, eReceiver and tCoords. A map area defined with target() is of course also valid.
 
stabpoints (0, 1) - civ has 0 or more stab
stabpoints (0, 0) - civ has less than 0 stab

I don't need to update pyScenario just now so I won't, but I would be grateful if new version consist of current version +flip + migrate, yield, output :) It would clean up mess a bit.

I'm afraid if I define check of having Egypt then I would be unable to define Rome as area of effect, if you know what I mean :)
 
stabpoints (0, 1) - civ has 0 or more stab
stabpoints (0, 0) - civ has less than 0 stab
I'm not sure that stability checks should be part of PyScenario - because its not intended to be used to mod stability as such - but I'll see what I can do.

I don't need to update pyScenario just now so I won't, but I would be grateful if new version consist of current version +flip + migrate, yield, output :) It would clean up mess a bit.
Once you've tested all these custom methods I will be able to update. :D

Other than that - you really should update. There are bugfixes in the latest release and the methods you are currently importing from a Custom module are also updated. Any bug report would be of little value also, since you're not using the current version... And then I won't be able verify that the custom methods mentioned in the previous paragraph really work on as intended on the current version. So this is a problem.

I think I'll just help you to import whatever custom methods you need to use with the new version. What do you need?

I'm afraid if I define check of having Egypt then I would be unable to define Rome as area of effect, if you know what I mean :)
You mean having two plot lists in one single Trigger? No, that wouldn't work and only the one you define lastly would be valid.

This is when you have to use two separate Triggers - one with Rome as the target player and with the Roman area as the plot list - and one with Egypt as the target player and with the Egyptian area as the plot list. Then you bind them together with label() and fired().
 
How to script fall of the Empire without stability checks? :D

The custom methods gives just more possibilities, so even if they are bugged it's still worth to include them even if just for bug reports :) Probably I use (or at least import) every custom module...

Yeah, I know how to do this, just wondered if it's possible to make it in one (defining target of yields/output would be a great addition. But it would be good if you could use tiles, tuples, etc. or None).
 
How to script fall of the Empire without stability checks? :D
Yeah... I'll have to get back to you on this. But my point is that there already is a system for collapses and secessions in RFC. You wanna double up - or would you rather mod the existing features?

The custom methods gives just more possibilities, so even if they are bugged it's still worth to include them even if just for bug reports :)
Er... I do these custom things for you to test. If you're not testing them with the latest version of PyScenario, your testing is of limited (or no) use to me.

Probably I use (or at least import) every custom module...
You really shouldn't do this, because you will be replacing the methods in the latest update with old custom methods. You need to manage what you import into your scenario. What if you run into a problem and need to report the issue? Then I'd have to go in and edit your stuff for you so that you can test it out again. I'm not gonna fix any bugs in outdated versions!

Yeah, I know how to do this, just wondered if it's possible to make it in one (defining target of yields/output would be a great addition. But it would be good if you could use tiles, tuples, etc. or None).
If you explain what exactly you need then I will try to make it for you. So that you can test it out.

What arguments are you missing from the latest batch of Actions? (You know that you can define a single tile with target(), an area also with target(), any plot list imaginable with tiles(), a city with find() or just use all cities of the target player by not defining any city/area?)
 
Back
Top Bottom