• New Horizons on Maelstrom
    Maelstrom New Horizons


    Visit our website www.piratehorizons.com to quickly find download links for the newest versions of our New Horizons mods Beyond New Horizons and Maelstrom New Horizons!

High Priority Updating the Character Model Groups

One problem is that the lines in "initModels.c" which restrict female walkers are mostly "AssignModelTypeNatMask(isstart, model, "Rich_Citizens", 1.0, GetNationStringNorthEuroFr());". There aren't any for women in "SouthEuro". This was presumably supposed to be the code which puts different models in different nations, but it only seems to distinguish between North and South Europe, and South doesn't have any of its own. Which means Spanish and Portuguese colonies still seem to have the limited set as seen before the fix.
 
Indeed even if the code works, the actual assignments should be correct as well.
That would require someone to go through the models and figure out which ones look North European, which ones look South European and which ones can be used for all.
Would be nice if that is done properly though, because that would distinguish the various nations' towns further.
It is pretty cool if the characters in a Spanish town actually LOOK Spanish.

Would you be able to have a look into this? If so, be certain you do this AFTER installing my latest ZIP update from yesterday.
I made a lot of unrelated changes to initModels.c and it would be a pain to say the least to merge that later with other changes to that file. :wp
 
The obvious thing would be to check that any character whose "model.nation" is either "SPAIN" or "PORTUGAL" and has an "AssignModelTypeNatMask" line should have it set to "GetNationStringSouthEuro())". ;)
 
To be sure!
Of course the model.nation assignments may sometimes be a bit arbitrary as well.

Anyway, would you be willing to have a look at that? After the amount of work I did yesterday, I'd much prefer not editing initModels.c again for a while.... :wp
 
Here it is. Any references to "GetNationStringNorthEuro" or "GetNationStringNorthEuroFr" which apply to a character whose nation is "SPAIN" or "PORTUGAL" are now replaced by "GetNationStringSouthEuro". Additionally, "liz2", who has darker skin and hair than "liz1", is also now "SouthEuro" (despite being nation "PIRATE", which makes me wonder what Arthur Wellesley's sister in "Hornblower" has been doing xD). I tested it by starting a new free play game as a Spanish sailor, which puts me in San Juan, a good place for spotting random Spanish civilians as the trade centre is adjacent to the port. In due time one of the models which I'd changed to be "GetNationStringSouthEuro" showed up.
 

Attachments

  • initModels.zip
    40.3 KB · Views: 182
Last edited:
So it sounds like this is actually working for real now? Exciting indeed!! :dance

The model.nation assignments were only used for the nation tailors where you can buy them.
The AssignModelType lines are used for the actual random characters in the game.
The model.nation is now also used by the Select Storyline Interface, but that is neither here nor there. :wp
 
The ones I changed were "AnnaDeLeiva", "Downgir52", "Downgirl2" and "liz2". "Huber_por" and "Huber_spa" were already set to "SouthEuro". Some others are set to "Not(PIRATE)" or "BitNot(GetNationStringSouthEuro())", which I left alone.

Besides, if a certain outfit is only available from tailors of a certain nationality then it's likely that only people of that nationality will buy it. Unless, that is, they're allowed to travel overseas on clothes-shopping trips, which would make the whole idea of nation-restricted costumes pointless. So the tailor nationality is as good a guide as any. :)
 
The game code would accept model.nation = ENGLAND but AssignModelType for GetNationStringSouthEuro() only.
The model should then show up only in Spanish and Portuguese towns, but be sold only be English tailors.

I absolutely agree that does not make sense and the model.nation and the nation used for AssignModelType should match properly.

Can you actually notice a difference now in the models encountered between Spanish and Portuguese towns?
Maybe, just for the sake of it, it would be fun to distinguish the models a bit further by avoiding Not(PIRATE) and having most model linked to only a few of the nations.
In other words, limit the number of "fully generic" models.

What happens for America, by the way? I wonder if that is counted as NorthEuro or SouthEuro. Logically, they should probably match with England.
But I think that because it is an additional nation that was never factored into this, it might be that they would match with Portugal/Spain instead.
Or perhaps, now that this feature actually seems to work (finally!), they'll be severely limited in models altogether and ONLY use the generic ones. :shock
 
The game code would accept model.nation = ENGLAND but AssignModelType for GetNationStringSouthEuro() only.
The model should then show up only in Spanish and Portuguese towns, but be sold only be English tailors.
You could do that, yes. I didn't. :D

Can you actually notice a difference now in the models encountered between Spanish and Portuguese towns?
Maybe, just for the sake of it, it would be fun to distinguish the models a bit further by avoiding Not(PIRATE) and having most model linked to only a few of the nations.
In other words, limit the number of "fully generic" models.
These models are rare and it takes quite a lot of repeated moving back and forth between adjacent locations to see them. It took me lots of moves between San Juan town and port to even spot one. I haven't tried Portugal because Sao Jorge is much less convenient for this, and after I'd confirmed that at least one or two of the models I'd assigned to be "SouthEuro" now showed up in a Spanish port, I rather wanted to get on with playing "Bartolomeu"!

My guess is that there's no more distinction between Spain and Portugal than there is between England, Holland and France - there's just the division between north and south. But since these models appear so rarely when they are just split between north and south, refining it to distinguish between individual nations would make them all but extinct, rendering all this work pointless!

What happens for America, by the way? I wonder if that is counted as NorthEuro or SouthEuro. Logically, they should probably match with England.
But I think that because it is an additional nation that was never factored into this, it might be that they would match with Portugal/Spain instead.
Or perhaps, now that this feature actually seems to work (finally!), they'll be severely limited in models altogether and ONLY use the generic ones. :shock
Take a look at "globals.c", where "NorthEuro", "NorthEuroFr" and "SouthEuro" are defined as "1000100", "1100100" and "0010010" respectively, and also observe how "GetNationString" generates a string for a specific nation. America appears to be represented by the final digit, so at the moment it won't get any of these nation-restricted models. That can easily be changed by replacing the final "0" with a "1" in the relevant definition. Pirates also don't seem to get them, so I'm seriously inclined to lose the "AssignModelTypeNatMask" line from at least some of the "Downgirl" models - loose women like that ought to appear in pirate settlements as well. :D (Or maybe define new settings "NorthEuroPirate" and "SouthEuroPirate" for such characters as can appear in a specific European group and in a pirate town.)

And then there's the problem of any town which you capture for yourself and hoist the Personal flag, which will promptly be deserted by all these models...
 
My guess is that there's no more distinction between Spain and Portugal than there is between England, Holland and France - there's just the division between north and south. But since these models appear so rarely when they are just split between north and south, refining it to distinguish between individual nations would make them all but extinct, rendering all this work pointless!
I wasn't suggesting limiting models to ONLY one nation. I was only suggesting to avoid assigning models to ALL nations at once.
So wandering around a Spanish/Portuguese port, you would definitely notice seeing different models compared to walking around an English one.

Doing this would also make any imperfections with the system more readily apparent, such as America and Personal Nation not being considered just yet.
And if we can see what is wrong, then we can try to do something about it.

Pirates also don't seem to get them, so I'm seriously inclined to lose the "AssignModelTypeNatMask" line from at least some of the "Downgirl" models - loose women like that ought to appear in pirate settlements as well. :D (Or maybe define new settings "NorthEuroPirate" and "SouthEuroPirate" for such characters as can appear in a specific European group and in a pirate town.)
You might not even need a new function.
I think it would work to just have two AssignModelType lines, one for NorthEuro and one for PIRATE only to add pirates as extra.
 
I moved a lot of recent posts to this thread instead to reflect that this is no longer a bug.
It also seems to fix in relatively well with a "High Priority" Feature Request I posted a few months ago but that I still didn't get started on.

Hopefully we can get somewhere with the character model assignments as this could definitely add to the atmosphere in the game.
Seeing a large variety of models in the game and having different models used in different situations should be pretty cool. :woot
 
I wasn't suggesting limiting models to ONLY one nation. I was only suggesting to avoid assigning models to ALL nations at once.
So wandering around a Spanish/Portuguese port, you would definitely notice seeing different models compared to walking around an English one.
Eventually. As I said, the nation-limited characters appear rarely. The most common types are still the unrestricted ones.
Doing this would also make any imperfections with the system more readily apparent, such as America and Personal Nation not being considered just yet.
And if we can see what is wrong, then we can try to do something about it.

You might not even need a new function.
I think it would work to just have two AssignModelType lines, one for NorthEuro and one for PIRATE only to add pirates as extra.
And something similar could probably be done for America - maybe add it to a mixture of some NorthEuro and SouthEuro types to make America multi-cultural. :)

I don't see how Personal nation can be incorporated. Look again at how "globals.c" defines these strings. A nation mask is "EFSpHPA", the bits being England, France, Spain, pirate, Holland, Portugal and America respectively. Adding America to "NorthEuro" or "SouthEuro", or adding another line such as "AssignModelTypeNatMask(isstart, model, "Rich_Citizens", 1.0, GetNationString(AMERICA);" is easy. Personal doesn't have a place in the nation mask so adding lines to allow Personal would be harder - as far as I can see, the only way to allow a model to appear in Personal towns is to remove the national restriction entirely.
 
Eventually. As I said, the nation-limited characters appear rarely. The most common types are still the unrestricted ones.
Perhaps if we restrict more models, then they would become more common (by necessity: there would be very little else ;) ).

And something similar could probably be done for America - maybe add it to a mixture of some NorthEuro and SouthEuro types to make America multi-cultural. :)
:woot

I don't see how Personal nation can be incorporated. Look again at how "globals.c" defines these strings. A nation mask is "EFSpHPA", the bits being England, France, Spain, pirate, Holland, Portugal and America respectively. Adding America to "NorthEuro" or "SouthEuro", or adding another line such as "AssignModelTypeNatMask(isstart, model, "Rich_Citizens", 1.0, GetNationString(AMERICA);" is easy. Personal doesn't have a place in the nation mask so adding lines to allow Personal would be harder - as far as I can see, the only way to allow a model to appear in Personal towns is to remove the national restriction entirely.
All nations are actually numbers defined in globals.c . England is 0 and I think America is 6 or 7.
Personal Nation does have a number like that, but I think it is 10 and therefore falls outside the normal range.
I would expect it is possible to add it to the masks somewhere though. After all, the other nations can be added, so why not that one?
 
All nations are actually numbers defined in globals.c . England is 0 and I think America is 6 or 7.
Personal Nation does have a number like that, but I think it is 10 and therefore falls outside the normal range.
I would expect it is possible to add it to the masks somewhere though. After all, the other nations can be added, so why not that one?
Because, as I said, the mask is "EFSpHPA", the bits being England, France, Spain, pirate, Holland, Portugal and America respectively. The function "GetNationString" cycles from 0 to "NATIONS_QUANTITY", which I'm guessing is set somewhere to 6, otherwise the function won't generate a mask compatible with the fixed masks defined by "GetNationStringNorthEuro" and "GetNationStringSouthEuro".

So adding America is easy, it just needs the last bit in one of the pre-defined masks changed from 0 to 1. Or, if you can indeed have multiple "AssignModelTypeNatMask" lines in a model definition, then add one for America. But Personal has no place in the mask. "PRIVATEER_NATION" is defined in "globals.c" as 8, and I'm guessing that's Personal. So you'd need to either find where "NATIONS_QUANTITY is defined (it's not defined in "globals.c") and change it to 8; or change "GetNationString" to cycle up to "MAX_NATIONS", which is defined in "globals.c" as 8. Then the fixed masks such as "GetNationStringNorthEuro" would need to be extended. And I've no idea what that will do to whatever code reads those masks.

Incidentally, I'm not so sure that having more than one "AssignModelTypeNatMask" in a model definition will work, otherwise why were "GetNationStringNorthEuro" (England + Holland) and "GetNationStringNorthEuroFr" (England + Holland + France) defined? Why not just have "AssignModelTypeNatMask" lines for England, Holland and France as appropriate all in the model definitions? I suspect that if you have more than one, the last one will overwrite all previous ones, so that if a model definition has, for example:
Code:
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(ENGLAND);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(HOLLAND);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(FRANCE);
then the model will only appear in French towns. But there's an easy way to check that - put exactly that code into one of the more commonly seen models, then see where it appears...
 
PRIVATEER_NATION is unused. PERSONAL_NATION should be its own #define.

NATIONS_QUANTITY is a variable that is larger depending on whether America exists or not.
It is set in PROGRAM\NATIONS\nations_init.c .

Incidentally, I'm not so sure that having more than one "AssignModelTypeNatMask" in a model definition will work, otherwise why were "GetNationStringNorthEuro" (England + Holland) and "GetNationStringNorthEuroFr" (England + Holland + France) defined? Why not just have "AssignModelTypeNatMask" lines for England, Holland and France as appropriate all in the model definitions? I suspect that if you have more than one, the last one will overwrite all previous ones, so that if a model definition has, for example:
Code:
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(ENGLAND);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(HOLLAND);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(FRANCE);
then the model will only appear in French towns. But there's an easy way to check that - put exactly that code into one of the more commonly seen models, then see where it appears...
I'm not at all sure how that code works and whether it overwrites previous assignments or not.
I always assumed they coded it that way to reduce the amount of lines and manual labour required.
But we'd either need to dig into the code or test this conclusively to be sure.
 
PRIVATEER_NATION is unused. PERSONAL_NATION should be its own #define.
Ah, found it. PERSONAL_NATION is defined as -1. Which means there is no way that "GetNationString", which starts at 0 and counts up, will ever find it.
NATIONS_QUANTITY is a variable that is larger depending on whether America exists or not.
It is set in PROGRAM\NATIONS\nations_init.c .
So "GetNationString" will generate different length strings depending on whether America exists, but fixed strings such as "GetNationStringNorthEuroFr" are always 7 bits long. This might work depending on how the code which reads the strings works - do you know where it is? (And I wonder if that's why, before your more recent fix, models with such national masks only appeared in the later two periods?)

I'm not at all sure how that code works and whether it overwrites previous assignments or not.
I always assumed they coded it that way to reduce the amount of lines and manual labour required.
But we'd either need to dig into the code or test this conclusively to be sure.
Easy, though possibly time consuming. Change, for example, the definition of "towngirl7" to include:
Code:
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(ENGLAND);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(HOLLAND);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(FRANCE);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(PORTUGAL);
AssignModelTypeNatMask(isstart, model, "Lower_Citizens", 1.0, GetNationString(SPAIN);
Then see where she shows up. If all the masks are in effect then she'll be everywhere. If each one overwrites the previous one then she'll only show up in Spanish towns.
 
The work you two are doing seems to be having some effect. Lookee who I ran into outside of Port Royal. This is the first time I have seen her outside of the Tortuga tavern.
POTC new 2015-05-28 15-30-37-66.jpg
 
Personal Nation is -1? Then why do I seem to remember it was 10?
Anyway, that might possibly make it simpler. Can the bit loop be started at -1 instead of zero?
Or alternatively include an offset of plus our minus one?

The model code is all in program\models\models.c and I think that is where those nation group uses should be too.
 
If you start the bit loop at -1 then it will throw the fixed masks out of sync. Whichever nation is picked first, whether England at 0 or Personal at -1, will be the left-most bit. You'd need to change the definitions of "NorthEuro", "NorthEuroFr" and "SouthEuro", and also find whatever code reads the masks and change it to start at -1 as well. On the other hand, there is provision for two Guest Nations, one of which is used as America. I don't think the other is used. Otherwsise, if "PRIVATEER_NATION" is not used, change it to be -1 and change Personal to be 8. Again, though, it would depend on how the code which reads masks works.

And if you're going to modify both the code which generates masks and the code which reads them, how about changing it to use numbers rather than strings, which makes a whole lot more sense? In that case, instead of having to go through a loop to generate a single-nation mask, "GetNationString(int nat)" would merely need to return 2^nat. Composite masks such as NorthEuro would simply be 2^ENGLAND + 2^HOLLAND, for example. Reading the mask for a given nation would be something like "if (mask AND 2^nation == 0) return false;" again replacing a clumsy loop to scan through characters of a string.

Perhaps if we restrict more models, then they would become more common (by necessity: there would be very little else ;) ).
I don't like this idea for several reasons. One is that if restricted models are rare for any other reason then you'd just end up with fewer random civilians wandering around. Another is that you might have more distinction between towns of different nations but you'd have less variety within a town; with a more limited set of models from which to choose, each nation would be populated by numerous clones of a few types. Besides, fashion depends less on location and more on time - what was being worn in 18th century London, for example, probably bore more resemblance to what was being worn in 18th century Paris than to what was being worn in 17th century London. To model that, or for that matter to give a decent variety to specific nations, would require someone to create a lot of civilian models, as has already been done for military models which is why soldiers have period-correct uniforms. Then, of course, there's the matter of what happens when a town changes hands - is the entire population wiped out and replaced by people of the conquering nation, or do the people just continue to wear what they already have and pay their taxes to the new governor? The current system effectively has a few patriots move out and a few new people move in, with most of the population staying where they are, which is probably more realistic than major ethnic cleansing.

Which means the current set-up, where most models are available to all towns and a few are restricted to North Europe or South Europe, results in a decent mix of models in all towns with a few specific ones to give a bit of difference between nations.
 
I don't particularly want to do any substantial changes to the code for this.
Though I was thinking of rewriting the function call to get a model for random citizens to have a chance-based switch based on town wealth.
After all, there are groups of citizens that are Poor, Normal and Rich but I'm not at all sure if they're actually used like that.
As far as I could tell, the game just selects a random model out of all relevant groups based on the chances defined at the top of initModels.c .

These "groups" are used for random citizens and I think also for the smugglers in dungeons.
To simplify things, we could also just create a "Smugglers" group which we could use for the actual smugglers too.
Then we can do away with that "weird stuff" at the top of initModels.c altogether and start working with a system that is at least a bit simpler to understand.
Also, we might then be able to do away with most hard-coded use of models, including that for the smugglers and some of the soldier/sailor code.
At the moment we have at least several systems in place for both and it would be quite nice to have it ALL handled by the SAME system.

I don't like this idea for several reasons. One is that if restricted models are rare for any other reason then you'd just end up with fewer random civilians wandering around.
That wouldn't happen. The game decides how many civilians to put in town before searching for the models.
So you might get less variety of models within a certain city, but not actually less citizens.

The code might check if a certain model is already used in a certain location though. In that case, you might start seeing Nathaniel Hawks walking around if there aren't enough models assigned to the group.
But I think that doesn't happen. The game only checks the player and officer models to avoid having twins of the player and his officers walking around.

Another is that you might have more distinction between towns of different nations but you'd have less variety within a town; with a more limited set of models from which to choose, each nation would be populated by numerous clones of a few types.
That is true. Not sure how bad that problem would be. Depends of course on how many models are in each nation group.
If there are enough models, there will still be variety within the town, but it'll also be clearly different from the other nations.

Besides, fashion depends less on location and more on time - what was being worn in 18th century London, for example, probably bore more resemblance to what was being worn in 18th century Paris than to what was being worn in 17th century London. To model that, or for that matter to give a decent variety to specific nations, would require someone to create a lot of civilian models, as has already been done for military models which is why soldiers have period-correct uniforms.
Fair enough. It is actually possible to set any model to appear only within certain periods.
The model.period lines applied to the soldiers should work just as well for civilians. Do you think we have any non-soldier models in the game that don't look like they belong in certain time periods?

Then, of course, there's the matter of what happens when a town changes hands - is the entire population wiped out and replaced by people of the conquering nation, or do the people just continue to wear what they already have and pay their taxes to the new governor? The current system effectively has a few patriots move out and a few new people move in, with most of the population staying where they are, which is probably more realistic than major ethnic cleansing.
The fixed town folk will of course remain themselves and the "Enc_walkers" will switch their nationality to the new "location nation".
Those characters are newly generated upon each location reload.
 
Back
Top