Nightinggale
Deity
- Joined
- Feb 2, 2009
- Messages
- 5,281
This is mainly a reminder for myself telling me what I should do. Sometimes I think of ideas I have to postpone implementing and then later I forget about them
Obviously people can reply here and ideas can be debated and evolve.
Activation status: 83/88
I rewrote the XML reading code and the cache. Activating the cache mean to inject the cache into the relevant places in the code in a way that the code acts as we would expect it to work.
Done. However a number of tags were skipped as they have never been implemented in the DLL.
1-4 is important before next release. The rest is DLL internals, which will improve performance and can wait.
I have come this far. I might as well finish it all before next release.
Possibly add bools to a trait saying it's free for all players who aren't native and one for non-natives. That will allow a quick setup for difference between native/non-native without having to edit every single leader. Also it removes the risk of forgetting to add it to a specific leader. This would be good to have in next release.
List of files:
Move support files for those files into the new dir as well, such as CivicOptionInfos and TechCategoryInfos.
Figure out if DllExport can be removed from CvCivicInfo. If not, then renaming could be an issue. Solution:
Rename CivicInfo to PlayerEffects or CivEffects and assign CivicInfo to those civics, which are actually civics.
All XML files provide data to info classes. I think it would be best with CivEffectInfo.
Make CvGlobal functions to access each type of CivEffectInfo.
GC will then take care of the offset issue and deliver the correct one from the shared vector.
effect civic
On save:
disable civic, save, enable civic. This can be done by just changing the bool array, which would skip cache updating.
Reason: BoolArray (like JIT array) only saves from index 0 to the highest non-default. By clearing the rear, less data is saved and filesize is reduced.
On game start/load:
postLoadGameFixes() should call a cache set function for each player. It should do for alive players:
This function should be written in a way, which allows it to be called at any time without breaking anything. It will most likely only need to be called from postLoadGameFixes(), but writing it to just work in other cases is good, should the need show up.
Python
It will be a whole lot of work to add all the CivEffect get functions to all the affected classes, especially if the number of classes keep increasing. It will also make it harder to use shared code.
Solution 1: figure out python class inheritance. This might be tricky as the class is returned from the DLL and as such is not pure python.
Solution 2: generate a CivEffect class, where IDs represent a fake single vector and expose this class to python.
This is like Tech ID 4 is CivEffect numCivics + 4. The get function in CvGlobals will be slower than the get functions for each type. However it is only used for python, high performance isn't an issue.
This needs further investigation, but I think solution 2 will be the one with the cleanest implementation in python. It will be like making individual pedia pages and then to fill out the effect, it simply calls a function to do that and this function takes getCivEffectIndex() as argument.
The DLL will not really be affected either way as class inheritance is pure C++ and works well. Looping all CivEffects is not really needed due to the cache, though it might be useful during init. In fact init will need to ask "is any CivEffect allowing this" (for everything in allows group), which really is the only time where looping all would make sense.
Solution 3: Don't expose CivEffects to python
This one is the most simple one to code. If we need to print some text, we can make a getText function, which python use to print everything. If help popup use the same getText function, then we will only have to write the text stuff once.
It isn't unlikely that we will have to make multiple functions to get text and each screen then merge the replies as needed or print them in different boxes or whatever we come up with.
Sea trade route discovery
This is disabled for now. The trigger mechanism is in CvUnit::setXY(), but it is hardcoded and performance isn't great for a function called this often.
Possible solution: Add a CivEffect to EuropeInfo in XML. In setXY(), if the new plot has access to a trade screen, which the owner doesn't know about, then the owner is given the CivEffect from XML. The movie name can be set in Europe XML and be triggered by enabling the trade screen with any CivEffect. That way the DLL supports movies for any trade screen, regardless of how it is invented.
Maybe add an InfoArray to CvPlot and store which trade screens it can access. This saves some looping in setXY. If it is added in addition to the current access code (instead of replacing), it can be a bool array of screens, which can be discovered by moving into them. That way setXY only has to check the (often empty) InfoArray and owner's CvPlayer::canUseTradeRoute().
AI
We might have to make a CivEffect in XML, which tells special rules for the AI. If trade routes are enabled and disabled here, which could be used to set vanilla Europe for the AI. The DLL code will not take AI into account and the vanilla Europe will then not have a special meaning in the code.
Obviously people can reply here and ideas can be debated and evolve.
I rewrote the XML reading code and the cache. Activating the cache mean to inject the cache into the relevant places in the code in a way that the code acts as we would expect it to work.
Done. However a number of tags were skipped as they have never been implemented in the DLL.
Add all trait tags to CivicInfoCache all new (trait) tags in CvPlayerThe only tags, which aren't cached will likely have to be redesignedApply cache to actually workMove CivicInfo to new directorySplit CivicInfo into multiple filesGenerate an effect civic, which sets +1 to all allows, which aren't enabled in XML
(this can simplify CvPlayer cache generation)Make reduced JIT, which stores only none-zero values ticket linkMake all getBool functions return an int of value 0 or 1.
This will allow adding all "bools" of owned CivEffectInfos and storing the count. This mean if the player loses one of those, the count would go from 2 to 1 and nothing happens. No looping to figure out if any other CivEffectInfo has the bool set.Change CvPlayer cache to store allow score rather than bool.
Allows cache updating based on the changed civic instead of looping all like now- Reduce/remove non-CivicInfo from the cache
Stuff like making a native trait, which enables the yields, which are now enabled by being native Cache every single effect in CvPlayer (gifts excluded). There should be no reason to loop CivEffectInfos except for cache generation or display.
That will allow a setup where adding a massive amount of CivEffectInfos will have little or no performance penalty on the game.- Rename tags to follow naming convention and write wiki text regarding the naming convention.
Make a vector of CivEffects, which are applied to players when setting up the cache
This vector should read an XML file with one CivEffect and then it should add a CivEffect where bIsInit is set in the constructor
This will allow XML setup of default player behaviour as well as copying the current setup where everything is allowed if nothing enables itFix discover sea trade route by entering access plot- Add an InfoArray in CvPlayer telling which trait he has. If it is empty, the get function will return the InfoArray from leader XML (which will have to be converted to InfoArray)
The only place to actually set traits in CvPlayer would be in scenarios. This mean scenarios can set custom traits, but if no traits are set, it will rely on XML - Clear researched techs when start reading a scenario. This will remove the normal starting techs and only provide those, which are in the scenario file
- Implement research cost modifiers in handicap and gamespeed
- Implement yield bonus for connected missions and trading posts
Add the ability to completely clear promotion effect cache in units and recalculate (useful when new promotions are allowed)- Add techs for nation states in CvPlayer::init() and generally clean up assigning techs in that function
I have come this far. I might as well finish it all before next release.
Possibly add bools to a trait saying it's free for all players who aren't native and one for non-natives. That will allow a quick setup for difference between native/non-native without having to edit every single leader. Also it removes the risk of forgetting to add it to a specific leader. This would be good to have in next release.
List of files:
- Civics
- Inventions
- TradePerks
- Censures
- Traits
- Effects
Move support files for those files into the new dir as well, such as CivicOptionInfos and TechCategoryInfos.
Spoiler :
Looks like the exe is aware of CvCivicInfo and can get the vector from the DLL. However it never calls any function beginning with CvCivicInfo::
The next question is if the call in the exe can be reached. It makes little sense to get the vector if it can't access any of the functions related to it. I would say it's likely leftover code from something, which didn't make it into the final exe, such as possibly debug code.
Rename CvCivicInfo to CivEffectInfo (or whatever)
Last in the header file, add
That way we can store CvCivicInfos in the vector and give those to the exe and it will be happy. In the DLL, we can use CivEffectInfo. This will work because we can always "revert" a class to the parent class and only use parent functions and variables. In this extreme case the child class will add nothing other than the name the exe expects.
Maybe we should have a class for each type and add type specific functions to each, meaning we will have CvTechInfo::getInventionCategory().
The next question is if the call in the exe can be reached. It makes little sense to get the vector if it can't access any of the functions related to it. I would say it's likely leftover code from something, which didn't make it into the final exe, such as possibly debug code.
Rename CvCivicInfo to CivEffectInfo (or whatever)
Last in the header file, add
Code:
class CvCivicInfo : public CivEffectInfo
{};
Maybe we should have a class for each type and add type specific functions to each, meaning we will have CvTechInfo::getInventionCategory().
All XML files provide data to info classes. I think it would be best with CivEffectInfo.
Make CvGlobal functions to access each type of CivEffectInfo.
Code:
for (int i = 0; i < GC.getNumTechInfos(); i++)
{
CivEffectInfo kTech = GC.getTechInfo(i);
effect civic
On save:
disable civic, save, enable civic. This can be done by just changing the bool array, which would skip cache updating.
Reason: BoolArray (like JIT array) only saves from index 0 to the highest non-default. By clearing the rear, less data is saved and filesize is reduced.
On game start/load:
postLoadGameFixes() should call a cache set function for each player. It should do for alive players:
- Enable civic effect (skip cache update for performance reasons)
- Clear CivEffectInfo cache
- Loop all CivEffectInfos and assign cache
- Era restrictions (post 100)
This function should be written in a way, which allows it to be called at any time without breaking anything. It will most likely only need to be called from postLoadGameFixes(), but writing it to just work in other cases is good, should the need show up.
Python
It will be a whole lot of work to add all the CivEffect get functions to all the affected classes, especially if the number of classes keep increasing. It will also make it harder to use shared code.
Solution 1: figure out python class inheritance. This might be tricky as the class is returned from the DLL and as such is not pure python.
Solution 2: generate a CivEffect class, where IDs represent a fake single vector and expose this class to python.
This is like Tech ID 4 is CivEffect numCivics + 4. The get function in CvGlobals will be slower than the get functions for each type. However it is only used for python, high performance isn't an issue.
This needs further investigation, but I think solution 2 will be the one with the cleanest implementation in python. It will be like making individual pedia pages and then to fill out the effect, it simply calls a function to do that and this function takes getCivEffectIndex() as argument.
The DLL will not really be affected either way as class inheritance is pure C++ and works well. Looping all CivEffects is not really needed due to the cache, though it might be useful during init. In fact init will need to ask "is any CivEffect allowing this" (for everything in allows group), which really is the only time where looping all would make sense.
Solution 3: Don't expose CivEffects to python
This one is the most simple one to code. If we need to print some text, we can make a getText function, which python use to print everything. If help popup use the same getText function, then we will only have to write the text stuff once.
It isn't unlikely that we will have to make multiple functions to get text and each screen then merge the replies as needed or print them in different boxes or whatever we come up with.
Sea trade route discovery
This is disabled for now. The trigger mechanism is in CvUnit::setXY(), but it is hardcoded and performance isn't great for a function called this often.
Possible solution: Add a CivEffect to EuropeInfo in XML. In setXY(), if the new plot has access to a trade screen, which the owner doesn't know about, then the owner is given the CivEffect from XML. The movie name can be set in Europe XML and be triggered by enabling the trade screen with any CivEffect. That way the DLL supports movies for any trade screen, regardless of how it is invented.
Maybe add an InfoArray to CvPlot and store which trade screens it can access. This saves some looping in setXY. If it is added in addition to the current access code (instead of replacing), it can be a bool array of screens, which can be discovered by moving into them. That way setXY only has to check the (often empty) InfoArray and owner's CvPlayer::canUseTradeRoute().
AI
We might have to make a CivEffect in XML, which tells special rules for the AI. If trade routes are enabled and disabled here, which could be used to set vanilla Europe for the AI. The DLL code will not take AI into account and the vanilla Europe will then not have a special meaning in the code.