Production Choices

Valkrionn

The Hamster King
Joined
May 23, 2008
Messages
14,450
Location
Crestview FL
Alright, potentially difficult problem here. But an interesting one. :lol:

Basically, I need to map out how production choices are made available, but I hit a wall after CvDLLWidgetData::doTrain().

What I am attempting to do, is allow for the addition of UUs on a city-by-city basis (making use of a new CityClass object which I've already implemented); To do this, I added a CityUnit array. I am attempting to do this in such a way that it would allow for multiple units (or buildings, but focusing on one at a time here) of the same unitclass to be constructed; I have no plans for this, but the flexibility it would allow would be nice (particularly with Barbarians, as we plan for each barb city to possess a cityclass representative of a race in the mod; Dwarves, Elves, Humans, Orcs, etc).

Has anyone ever mapped these functions out? Any ideas on how to proceed? I've been able to get the units to show up in the production popup, but they are not produced and cause a crash.
 
I'm not sure what you're asking, or what you're trying to do.

Are you attempting to produce two units at once? And they have to be UU's?
What are the CityClass and CityUnit?

Which functions are you looking for? What do you mean by production choices? Do you mean the AI selection of production?
 
I think that the OP means that city A would be able to train UU X while city B would be able to train UU Y.

I read about a Python fix for something similar recently, involving a interface hack that doesn't limit the available units to only the UUs belonging to the city's owner. The rest would be done with a canTrain callback, or something. But I guess it could be done in the SDK as well.
 
Oh! thanks Baldyr. I re-read Valk's post after reading your comment and it all makes sense now.
(He already uses C++, so I guess this is the preferred solution)

CityClass! same as UnitClass or BuildingClass! (Or CivicClass, in the mod comp I'm currently working on :p)

Nice idea!
So each civ actually settles cities of a specific city class, and these cities remain with the city class even after they are conquered?
I think I saw an Afforess mod comp for this (might be someone else's, though).
But it was for UU's (and maybe UB's).

So the CityUnit Array is the same as the array each civ info has for UU's?
And can a city class mix UU's and UB's from different civs? Does it have other specific qualities?

Anyway, regarding the code:
Everything you need for this is in CvCity.cpp.

You have the following methods:
Code:
CvCity::canTrain() // Units - You actually have two of these methods
CvCity::canConstruct() // Buildings
CvCity::canCreate() // Projects
CvCity::canMaintain() // Processes - build wealth, research, culture

These are called whenever the city options are examined (when you try adding something to the queue, every turn to check if the current order can be continue, to display the relevant UI, tests for the AI).
 
Oh! thanks Baldyr. I re-read Valk's post after reading your comment and it all makes sense now.
(He already uses C++, so I guess this is the preferred solution)

Right. ;)

CityClass! same as UnitClass or BuildingClass! (Or CivicClass, in the mod comp I'm currently working on :p)

We're also planning to add TechClasses (purely graphical, our tech tree will be on multiple pages), ImprovementClasses (we want true unique improvements), and so on. :lol: Added some other files as well but they're fairly specific to the mod (AffinityInfos, allowing for in-depth affinities on units, SpawnGroupInfos, allowing us to spawn specific stacks of barbarian units very easily, LeaderClassInfos, as we have three different types of leader, etc).

IIRC, Opera wanted CivicClasses as well, so we may look into your modcomp. :lol:

Nice idea!
So each civ actually settles cities of a specific city class, and these cities remain with the city class even after they are conquered?
I think I saw an Afforess mod comp for this (might be someone else's, though).
But it was for UU's (and maybe UB's).

Not quite; What you're referring to is Kael's Assimilation modcomp, and is also included.

What it will actually be for is to allow splits within a civ. For example, an upcoming civ will be divided into Houses, one for each UnitCombat; To construct units of that combat, the city must belong to that House (IE, must have a cityclass). Another use will be for the Sprawling civs such as the Kuriotates; Their main cities will gain a CityClass making them able to work the third radius, and grant trade bonuses; The "settlement" cities will be reduced to just the first radius, gain a trade nerf, and be prevented from building national/team/world units (simple bools already in place). Sounds harsh, but it's far better than settlements that couldn't do anything at all. ;)

CityClass will generally be removed when conquered.

So the CityUnit Array is the same as the array each civ info has for UU's?
And can a city class mix UU's and UB's from different civs? Does it have other specific qualities?

Not quite; It's an array of UnitInfos, rather than UnitClassInfos. It is loaded from the owner's CivUnits array (or the original owners, in the case of owners with the Assimiliation trait), and then modified by the CityClass. This way, multiple units of the same UnitClass can be constructed. Hypothetically. :lol:

Anyway, regarding the code:
Everything you need for this is in CvCity.cpp.

You have the following methods:
Code:
CvCity::canTrain() // Units - You actually have two of these methods
CvCity::canConstruct() // Buildings
CvCity::canCreate() // Projects
CvCity::canMaintain() // Processes - build wealth, research, culture

These are called whenever the city options are examined (when you try adding something to the queue, every turn to check if the current order can be continue, to display the relevant UI, tests for the AI).

Not quite true; Units I add pass through canTrain() just fine at this point (stepped through with a debug DLL), the issue is they flat out are not passed to canTrain(). Only units in the civUnits array are, and when I attempt to convert that to use the new cityUnits() array, I receive a crash.
 
Basically, I need to map out how production choices are made available, but I hit a wall after CvDLLWidgetData::doTrain().
Not quite true; Units I add pass through canTrain() just fine at this point (stepped through with a debug DLL), the issue is they flat out are not passed to canTrain(). Only units in the civUnits array are, and when I attempt to convert that to use the new cityUnits() array, I receive a crash.
So where are you crashing exactly? Did you manage to get the units to the city screen? But get a crash when you choose to train the unit?
 
The units show in the production popup on the right (CvDLLButtonPopup), but selecting them causes nothing to show in the city bar and then a crash on next turn. Similar changes in CvDLLWidgetData (which is where the other production choices are defined) either fails to have an effect, or causes an immediate crash.
 
I don't know what causes the crash (will try to think of it some more later), but this is what happens after CvDLLWidgetData::doTrain() is called:

CvMessageControl::sendPushOrder() is called (either directly or for the selected cities).
This causes a CvNetPushOrder message to be created and sent.

Later it is executed (see CvNetPushOrder ::Execute()), and calls CvCity:: pushOrder().
In it, canTrain() is called, so your filters should work there as well.

Where exactly is the crash in the code?
 
Not sure at this point; I'm essentially removing my old code and trying again.

The current issue with doTrain() is saying that eUnit is not defined (which is crap) but the best way I can see to fix that, involves transitioning from a simple int array of units, to a more complex array of unitclasses/units. And removes the ability for multiple units of the same class. But, it may well be necessary.
 
I always leave the widgets for the LAST step personally. First test out that you can build the units you should be able to and not any of the ones you shouldn't IMO. Do that through by checking the city screen (a nice savefile with a few cities planted who belong to appropriate test houses is ideal, you will likely have to test it very frequently.


I played with the unitclasses stuff a LOT while trying to improve how Assimilation worked to make it more in line with how FF translated the ability. Also I tried to enable building multiple units with the same unitclass (and buildings) in a single city. There are quite a few random places where the code jumps back to UnitClass that you have to watch out for, and many of them reference different variables to figure out how to translate the class (player, city, territory owner...). Typically, one of those checks is where you crash at.


Since you are adding an array of your own, make certain that it is the appropriate size, and has catch statements to prevent operating beyond valid ranges of course.



The biggest issue you will have to face with this change is deciding how unit upgrades work, both for the player and for his allies. I would say that if this mechanic is primarily attached to a single civ, make it impossible for their allies to upgrade in their territory, and force them to have any upgrading unit be in range of an appropriately affiliated city. That should remove most complications for you. Though the city you are in range of is detected based on which city "owns" the tile you are standing on, so if your player builds cities too close to one another it may be difficult to figure out why he cannot upgrade 2 different house affiliated units on the same tile between the two cities (only one of them would actually be allowed since only 1 city can own the tile at a time). A massively complicated solution to that dilemma would be to have the houses spread their own culture values so that a tile CAN have multiple house affiliations (and so that your favorite unit type can quite likely upgrade from anywhere within your borders, while special ones that you rarely build quite likely still have to get very near their hometown).


I thought that at one time I had figured this problem out. But maybe I am just remembering getting Assimilation to finally work the way I had wanted it to (excluding the continued ability to construct the basic unit of any class). You have my code as your base, so make sure to look at Kael's code as well. I may not have completely reverted everything and a minor mistake I made could still exist and cause frustration.
 
Back
Top Bottom