CivEffects

I'm done cleaning up the XML load code. We are now one step closer to be able to read XML files in any order. It turned out that even with reading the types before reading the rest, it didn't entirely leave order behind. I noticed that by the fact that I suddenly had no units at all.

The issue was that when reading Civilization info, it relies on unitclass info containing the default unit. However since unit comes last in the alphabet, unitclass haven't been read yet.

I fixed this by using readSub(). It's a function I added for sub professions. However when reading the types, it actually reads readSub. I simply added a readSub() function for unitclassinfo and made it read default class. The same goes for buildings as they had the same issue (but B is fairly early in the alphabet and I don't think it caused issues). This mean default unit type is available from unit class info even before unitclasses are read for real.

From now on, if a read(pXML) function relies on GC.get*Info(), the tag it reads should be read by readSub() and then we are free of read order issues. However if readSub has to read a type, it should assert if getNum*Infos() for that type is 0.

I made one exception to this new rule. UnitArtStyleTypeInfo is read last because it relies heavily on unitinfo data and too much for me to bother trying to fix that.
 
I'm currently implementing a new concept for storing if a player has an active Censure.

It's a JIT array, which defaults to 0 and if the stored value is different from 0, the player has the Censure.

In CvPlayer::doTurn(), if a value is higher than 0, it decreases by 1. This mean the int value tells how many turns the Censure will last. This may or may not be exposed in the GUI later.

If the Censure is permanent, it can be assigned -1. It's different from 0, which mean it's active and it's not higher than 0, meaning doTurn() will not modify it.

I haven't committed it yet because I want to code this in a more generic approach. It would be ideal if this concept can be used for multiple CivEffect classes without duplicating more code than absolutely needed.

Some classes will be stored as bools though. Techs and Civics should not really expire.
 
It looks good for starters. As a side note; I am thinking that Censures could be good or bad. They are all bad now, but I want to add new ones where the Pope blesses you and you gain a bonus for a time, or perhaps permanent while you remain in his good graces.
 
Updated the wiki with:
Timed CivEffects

hasCivEffect is a short, meaning it can be set to a number. doCivEffects(), called from CvPlayer::doTurn(), will decrease the number if it is more than 0. This mean a CivEffect can be set to 3 and it will automatically disable itself after 3 turns.
Applying a CivEffect permanently can be done by setting it to -1 or any other number below 0.
I wrote the code a few days ago, but reading Kailric's post made me realize that I forgot to add this feature to the wiki. Censures is one of those, which can be timed and the code will not care if a CivEffect is positive, negative or both at the same time. This mean the code is already ready for timed positive censures.
 
After being stuck for almost a week, I finally came up with a solution to what I got stuck on. I renamed TRADE_IDEAS to TRADE_TECHS and then the compiler would point out any TRADE_IDEAS left in the code and I could change all of them in one go. Now I finally ended up with a decent progress again :)

I have decided to make perks and techs behave in a very similar way. Perks have become techs, which are bought with father points instead of YIELD_IDEAS, but otherwise they aim to behave the same way. This mean it will be possible to make a tech tree for perks as well as I just implemented full support for that in the DLL. I haven't added any diplomacy for perks and I don't plan to do so, at least not anytime soon.

I have been thinking of providing the ability to make civics block other civics, techs block techs and so on. CivicInfo has it in Develop, but I skipped that part in CivEffects because I lack a good design. The problem with the current design is that it will not allow say a trait to block a civic. I want the flexibility to ban Muslim trait from using a pope worship civic.

I'm thinking of handling all banning directly from CivEffects, but that is not without problems. What if a player has Civic A, then invents tech B, which bans A? What if perk C bans tech D, which is already invented? It is possible to reach a number of undefined conditions this way and it is kind of tricky to solve those.

One solution I'm considering is to allow CivEffects to ban any CivEffect, which can get banned. The solution to not reaching undefined combinations would then be to add asserts to the XML reading code. If the CivEffect can be turned on/off during the game, it can only ban CivEffects of the same type as it is itself. If it is set from game start (like traits), then it can ban any type. This way the code elsewhere will not have to consider legal combinations as by default they are all legal. The question is: have I overlooked something?

About banning of the same category. I plan to use readPass2 to set mutual banning. If civic A bans Civic B, then Civic B will automatically ban Civic A even if no bans have been set in B. This will ensure that it isn't possible to enable B and than A and have both at the same time just because B is missed in XML setup.
 
That seems like a fairly comprehensive solution, especially where there are so many 'mechanic types' in play, where civ effects encompass so many things.

chances are the best thing is to make this, then see if we can break this, then refine to deal with any of the myriad possibilities that we could not at first conceive of.

These refinement solutions might be coding changes, or for some it may simply be the stated 'rule' in the wiki that says

"if you try and do A and B together, the game will explode. You have been warned."

If making a solution for it would be too hard or over arching or whatever, i.e. you lose a function that is fine simply to block another that is not.

"It's Health and Safety gone mad I tell ya!!" :hammer2:
 
These refinement solutions might be coding changes, or for some it may simply be the stated 'rule' in the wiki that says

"if you try and do A and B together, the game will explode. You have been warned."
As much as I like adding rules like that to the wiki, that approach is seriously flawed and I vote against it. The problem is that people read it once, add something 3 months later where they have forgotten that it is a violation. The only real way around this is to add proper asserts.

Having said that, adding wiki info on why it asserts, which allows people to look it up isn't a bad idea.
 
exactly, that is what I mean.

I can't, at the moment, think of a coding situation, where one thing would be fine and another would break, and the only solution would be to break both.

If this situation did exist though, I would vote that you keep the work and the break, and make a note of the 'way to break it' with a nice and helpful assert when it does break that says 'you broke it see wiki page X to know why!'
 
All sounds good to me Night, but yeah, with everything in CivicEffects banding stuff would be complicated. We still have to assume the Modders have some intelligence (yes, that means you Lib:wavey:). Trying to make the XML where it will not break a game is unfathomable. And attempting to predict where Modders would go wrong and compensate would be a bunch of work. We just need a Modders guide written for M:C that makes note of all the do's and don'ts. First we need to keep up with all the that ourselves then put it all in once place, the wiki would be great for that.

I've been swamped with school lately, but there is light ahead, we are heading into the last full month, then schools out for summer!!
 
We still have to assume the Modders have some intelligence
Isn't that like assuming earth is a triangle :confused:

The point in asserts is more or less to catch issues you overlooked yourself. If we really want to protect the DLL against poor XML code, rather than looking up the index in FindInInfoClass(), we should write our own function, which loops the XML in question and compare getType() vs the string you search for. That way it will assert if you write a civic if it expects a tech and so on. If such a function is written correctly, the XML read code would be a single line rather than the current two lines, which in turn will make the code more readable.

I think I will add such a function. The more I think about it, the more I like it. However for now I need to focus on CivEffects.
 
Just added a minor update in the code, which will be a major one for XML modders :)
Git log said:
Added DefaultCivEffectInfos.xml to set default values

This will simplify the setup for both DLL and XML
-the DLL will assign default values to the cache (not implemented yet)
-XML can assign what each value should start at in a single easy to read file

Currently some default values are set in globalDefineALT under a number of creative names
while other defaults are hardcoded in the DLL. In fact most values are hardcoded.
Using this new file, all default values are automatically accessible in XML with no extra DLL code.
By fully exploiting the new system in the DLL, this feature could be added using just a single line of code in the DLL. To be more precise it's the line telling what file to read. I have to admit that I planned ahead, which is why all the functions it calls were already in place as well as the vector to store the data.

Next up is deleting data from GlobalDefineALT and write it to this new file instead as well as cleanup in cache reset in the DLL. Data, which would be natural to set in this file is stuff like default number of units on the docks, unit heal rate in different plots (friendly, enemy etc) and the percentage the king takes for transporting a treasure (this is still possible, right? At least it should be possible to enable in XML).
 
I'm currently working on changing GC.getCivicInfo to return a const pointer rather than a reference. This is to prevent the missing & bug I encountered earlier and will eventually be used on all info classes. I'm doing it to civics now as it makes the compiler locate every single location where civic info is used. A lot of them should be changed to techs, which is why they all need reviewing.

A lot of the code needs cleanup. I try to improve all over the place when I touch the code, but that is hard when my main focus has to stay at implementing CivEffects. I really want those to be in a playable game soon.

For now I simply killed off assigning techs to nation states. Develop branch gives it the first 41 civics and that design is so bad that I won't/can't convert it into something, which supports CivEffects. We should come up with something, which can be set in XML without too much hassle. One thing, which comes to my mind is recursive addition. If we add tech A in XML, the player will get A and both requirements for A and the requirements for the requirements and so on. That way in order to assign everything, all you have to do is to assign all "dead ends". Well at least in theory.
 
For now I simply killed off assigning techs to nation states. Develop branch gives it the first 41 civics and that design is so bad that I won't/can't convert it into something, which supports CivEffects
Yeah, I think it's best to keep things straightforward/flexible and simply assign the starting Techs/Civics you want directly in CivilizationInfos.xml . It isn't hard to simply cut and paste a block of starting Techs if you want to provide them to several civs, and this gives you the maximum flexibility if you want to add some slight variations.

Another neat feature for Techs with multiple "Or" prereqs comes from the Rise of Mankind mod of Civ4. In that mod, you can get a slight discount to research for each one of the "Or" Prereq Techs you have completed. For example if Philosophy requires Writing or Religion or Code of Laws as prereqs, you still only need a minimum of one of the prereqs, but if you have more you can get -5%, -10%, or -15% discount to researching Philosophy depending on how many of its prereqs you have completed. :king::science:
 
Another neat feature for Techs with multiple "Or" prereqs comes from the Rise of Mankind mod of Civ4. In that mod, you can get a slight discount to research for each one of the "Or" Prereq Techs you have completed. For example if Philosophy requires Writing or Religion or Code of Laws as prereqs, you still only need a minimum of one of the prereqs, but if you have more you can get -5%, -10%, or -15% discount to researching Philosophy depending on how many of its prereqs you have completed. :king::science:
I have been meaning to take a closer look at RoM. To be honest I know very little about it other than it recently added "unicode" support (not true unicode, but close enough) and that addition is based on what I wrote in M:C to support Russian.

I have completely redesigned how tech requirements are calculated. Rather than a complex if else structure, it calculates a score. For each requirements, which isn't present, it adds -1. For each Or requirements (that's just one) that you have, it adds +1. If the score ends up being at least 0, you can research the tech in question.

This could be modified to start with 100, add 5 for each unfulfilled requirements and subtract 5 for each fulfilled Or requirements. If the number ends up being 100 or lower, it can be researched and at the same time the number will be a research cost modifier, which gives -5% for each extra tech you have in addition to the minimum requirements.

To make this even more interesting, requirements and requirementsOr could be changed into lists and it could handle an unlimited number of requirements. The tech tree might have an issue with that (it needs updating anyway), but it should be fairly easy to add to the game mechanics.

The question is, how do we want it to be and how much should be possible to configure in XML?
 
That OR -cost feature sounds cool.

What if you added a globaldefine that set the modify per tech.

So it could be 1% or 50% or whatever.

That or an extra tag in the OR section that lets you specify how much benefit you get from each OR.

So
<TechPrereqOR>TECH_X
<imodifier>10

etc.

If you could also add a negative value to the imodifier, I think that would cover every conceivable use for the system, including technologies that work against each other.

So as a poor example, if you researched oil production research, it would make renewable energy research more 'expensive' and therefore take longer.

Or in a 2071 setting you could have bio-hybrid and cybernetic techs that work against each other.
 
I think I solved the issue of providing techs without too much XML work while at the same time control everything from XML. I noticed that natives get all native techs for free. This should be changed into a list of tech categories in Traits. On game init, a player will get all the techs of all categories in the list. We add a native trait, which provides native techs and a pope trait, which provides all tech categories. Copy pasting the categories is easier than the individual techs and it allows human and alien techs in col2071 and possibly other stuff as well.

Also rather than assigning all the techs, it should loop the techs and assign what can be researched. The loop itself is looped until it doesn't add more techs. That should avoid accidentally adding two techs, which bans each other and other illegal combinations. I think I should write some sort of init tech function rather than writing all this in CvPlayer::init(). It would quickly get messy.

That OR -cost feature sounds cool.

What if you added a globaldefine that set the modify per tech.
I was thinking something like that as well. Setting it for each tech sounds like a lot of work and it would be inconsistent, hence harder to use when playing.

If you could also add a negative value to the imodifier, I think that would cover every conceivable use for the system, including technologies that work against each other.

So as a poor example, if you researched oil production research, it would make renewable energy research more 'expensive' and therefore take longer.

Or in a 2071 setting you could have bio-hybrid and cybernetic techs that work against each other.
We have a research cost modifier in CivEffect. It can be set to to say -5 to provide a 5% discount (that's the idea in this feature), but I intentionally designed it to allow positive numbers too, meaning if it contains 5, it will add 5% to the research cost. This is set for each tech category individually.

That would be a hassle to set up through as it needs to be set in each tech, but it gave me an idea. Tech categories is nothing at the moment other than placeholder for types used as ints in techs (and strings for the GUI). We could change them to become CivEffects. Whenever a tech is added/removed, the tech category is also added/removed. This would allow us to add research modifiers, which stacks for each tech you have of a certain category. At the same time if you research say mass destruction weapons, you could get a diplomatic penalty for each tech you get. CivEffects would unlock all sorts of interesting combinations, most of them we haven't thought about yet.
 
I think I solved the issue of providing techs without too much XML work while at the same time control everything from XML. I noticed that natives get all native techs for free. This should be changed into a list of tech categories in Traits. On game init, a player will get all the techs of all categories in the list. We add a native trait, which provides native techs and a pope trait, which provides all tech categories. Copy pasting the categories is easier than the individual techs and it allows human and alien techs in col2071 and possibly other stuff as well.

Also rather than assigning all the techs, it should loop the techs and assign what can be researched. The loop itself is looped until it doesn't add more techs. That should avoid accidentally adding two techs, which bans each other and other illegal combinations. I think I should write some sort of init tech function rather than writing all this in CvPlayer::init(). It would quickly get messy.


I was thinking something like that as well. Setting it for each tech sounds like a lot of work and it would be inconsistent, hence harder to use when playing.


We have a research cost modifier in CivEffect. It can be set to to say -5 to provide a 5% discount (that's the idea in this feature), but I intentionally designed it to allow positive numbers too, meaning if it contains 5, it will add 5% to the research cost. This is set for each tech category individually.

That would be a hassle to set up through as it needs to be set in each tech, but it gave me an idea. Tech categories is nothing at the moment other than placeholder for types used as ints in techs (and strings for the GUI). We could change them to become CivEffects. Whenever a tech is added/removed, the tech category is also added/removed. This would allow us to add research modifiers, which stacks for each tech you have of a certain category. At the same time if you research say mass destruction weapons, you could get a diplomatic penalty for each tech you get. CivEffects would unlock all sorts of interesting combinations, most of them we haven't thought about yet.

That tech category / CivEffects idea sounds awesome :king:

About the OrPrereq cost feature, I like Lib's first idea to have a single globaldefine that can set the percent cost change per tech, then you could use your already existing prereq score counter to multiply by the globaldefine multiplier. Depending on the mod you could let the percent cost change to be negative, zero, or even a positive cost increase (if you wanted to design a mod with a "deep" techtree that encourages specialization rather than a "wide" one where everyone ends up with the same early techs).:science:
 
So, in defense of my &#8220;41 techs to NationStates&#8221; hardcode it was&#8217;t a &#8220;design&#8221;. At that moment I needed to give Nation States an advancement of techs and I didn&#8217;t feel like adding 41 free techs to the XML so I just added that bit of code. The &#8220;design&#8221; I had in mind was to add AI code so that the AI could spend points to purchase techs that it considered good for its empire. We talked about this before. We should have an option so that you don&#8217;t have to add techs at all to &#8220;advance start civs&#8221; (which is what a NationState is atm) because they will choose their own techs based on points they have to spend. We could probably use similar code that Civ4 does as I am sure they have some system set up for the AI to purchase techs. The AI would then choose techs based on Traits they have and other factors.

Also, the option to purchase techs shouldn&#8217;t be limited to nation states, but rather any Civ with Tech points to spend can spend those at the start including the player. This way if you wanted to set up Advanced or more Difficult scenarios you can set the starting civ players to be able to purchase techs and all you have to worry about is setting their starting traits and the AI will choose their techs. This would be cool if there where tons of Or techs that has been talked about as the AI could choose which Or tech it wanted based on its Traits (Militaristic Civs would choose Military Category techs more often).

Anyway, the CivEffects as Category and the Or bonus/penalty costs sounds like a great idea and also the ideas on assigning all Native Techs and such based on Traits.
 
Top Bottom