For units I believe I'll add it in
BOOL Player::CanBuildUnit(const sint32 type) const

ShowOnMap is my next endeavor but if this code is simlar to my Good and CanSettle On code I may knock this out.
The concept is to add a flag CivOnly and a separate flag CultureOnly for use by modders to make units, advances, buildings, tileimps, and wonders only availble to certain civs. this would reduce the burden of making unique civ advance trees or grantadvance slic. Slic is great but time should be devoted to bigger things I think and this could make it easy for some sceanrios like WW2.
If your wonder CultureOnly will be like CivOnly except it will check for CityStyle instead of civ name.
I think the Civ only might use this code:
cultureroupCode:sint32 name; sint32 n; if (g_theCivilisationDB->GetCivilisation(name)){ for(n = 0; n < rec->GetCivOnly(); i++) { if(rec->GetGetCivOnly(n) == name) { return true; } } }
Code:sint32 style; sint32 s; if (g_theCivilisationDB->GetCityStyle(style)){ for(n = 0; n < rec->GetCultureOnly(); i++) { if(rec->GetCultureOnly(c) == name) { return true; } } }
Last edited by Ekmek; March 2, 2005 at 23:35.

For units I believe I'll add it in
BOOL Player::CanBuildUnit(const sint32 type) const
Last edited by Ekmek; March 11, 2005 at 18:29.

The CivOnly code might be a little bit more difficuilt since the civilisation database a CTP1 database and not a CTP2 database generated by dbgen.
-Martin
Civ2 military advisor: "No complaints, Sir!"

Martin,
I see that the code doesn't have Civs in the dbgen, but I'm not looking to modify the database files for civs but to ad it in units, advances, imps etc as flags and then functions that check to see the civ type (or city style). How else is it different? Should I do something like Mr Baggins did on modifiedgovernments?

I see thatcivilizationDb doesnt have a GetCivilization but all of the 'Get' functions have the constand (const CIV_INDEX civ). I think this is what you mean about it working a la ctp1.
continuing research...

I went into the civilisationDB (H and cpp) files and I'd say they are a mess probably because they are ctp1 and not as familiar as the ctp2 stuff I've been looking at...but in the h I found this code that I think I could use for my flag....
andCode:StringId GetPluralCivName(const CIV_INDEX civ) const { Assert(civ>=0) ; Assert(civ<=(CIV_INDEX)(m_nRec)) ; return (m_rec[civ].GetPluralCivName()) ; } StringId GetCountryName(const CIV_INDEX civ) const { Assert(civ>=0) ; Assert(civ<=(CIV_INDEX)(m_nRec)) ; return (m_rec[civ].GetCountryName()) ; } StringId GetSingularCivName(const CIV_INDEX civ) const { Assert(civ>=0) ; Assert(civ<=(CIV_INDEX)(m_nRec)) ; return (m_rec[civ].GetSingularCivName()) ; }
Code:sint32 GetCityStyle( const CIV_INDEX civ ) const { Assert( civ >= 0 ); Assert( civ <= (CIV_INDEX)(m_nRec) ); return ( m_rec[civ].GetCityStyle() ); }

CityStyle works fine, the data is stored in a CTP2 database, and the CityData object should have the piece of information stored, no need to use this function from the civilisation database.
However the civilisation stuff is an headache.
-Martin
Civ2 military advisor: "No complaints, Sir!"

hmmmm....I'd love to do CivOnly because it makes more sense, but I guess I can live with CityStyleOnly (or CultureOnly) and it could be a workaround if people wanted to make it Civspecific they can make a citystyle per civ (and probably just repeat city graphics) and I maybe up to redoing the CityStyle.txt etc per civ instead of pergroup....

Don't drop this civ only idea we have just to invest more time for it (or better just you), and therefore I think we should just start with the culture idea.
-Martin
Civ2 military advisor: "No complaints, Sir!"

agreed and I'll take a stab at it this weekend hopefully (although I really want to get somewhere on ShowOnMap too).
I'm thinking that the code should be identical for tileimps, units, advances, and builings. Just have to add the optional flag to all the cdb files.
but yes I'd like to unravel the civilization db problem (eventually)

As I trudge through the other stuff I'll hopefully post something on this soon (mainly since it may have a greater impact)
but I looked it ctydata.cpp and found this:
How come I cant use the GetCivilisation() here and get CIV_COUNTRY from the Civilization.txt? I know you said its not thesame but from looking in the code my (UNTRAINED) eye can tell the difference.Code:#if defined(ACTIVISION_ORIGINAL) m_cityStyle = g_player[m_owner]->m_civilisation->GetCityStyle(); #else // Set the style of the founder of the city - if any. if (g_player[o] && g_player[o]->GetCivilisation()) { m_cityStyle = g_player[o]->GetCivilisation()->GetCityStyle(); } #endif

First shot at this code...
Its based on my previous success CanSettleOn. My only two questions is that the code I got for g_player had actually g_player[o] but I didn't think that was necessary in this instanceCode:sint32 s; for(s = 0; s < rec->GetCultureOnly(); s++) { if(rec->GetCultureOnlyIndex(s) == g_player->GetCivilisation()->GetCityStyle()) { return TRUE; } }
My other concern is the CultureOnly flag. Can I use CultureOnly in other cdb stuff (advances, buildings, imps, etc). My instinct says yes because I determine what rec its checking but just want to make sure that I don't have to come up with different names each time.

The code seems to be ok except that g_player is an arrary a set of players and not just one player. And except that the condition in the for loop is not rec->GetCultureOnly() but the number of CulturOnly and you retrieve this with rec->GetNumCultureOnly(). And that the context is missing, however it belongs right above the final return. However as it stands now it is pretty useless as it always returns TRUE, so as in your good restriction thread you have to add an return FALSE; behind the for-loop. And of course you code should only be executed if the number of CultureOnly's is bigger then 0. And of course to figure out the number you use rec->GetNumCultureOnly().Originally posted by E
Its based on my previous success CanSettleOn. My only two questions is that the code I got for g_player had actually g_player[o] but I didn't think that was necessary in this instance
Of course you can define it in all the databases the obsolete flag is also defined multiple times.Originally posted by E
My other concern is the CultureOnly flag. Can I use CultureOnly in other cdb stuff (advances, buildings, imps, etc). My instinct says yes because I determine what rec its checking but just want to make sure that I don't have to come up with different names each time.
-Martin
Civ2 military advisor: "No complaints, Sir!"

Still got to figure out what you mean by context and thats great about the cdb. Once I get a decent piece of code going I'll work on putting it everywhere a modder may want it (this may cut down on slic for modders).Code:sint32 s; for(s = 0; s > rec->GetCultureOnly(); s++) { if(rec->GetNumCultureOnly(s) == g_player->GetCivilisation()->GetCityStyle()) { return TRUE; } }return FALSE;
Another question though. The "//" boxes I've been doing for new code. If I add thisnew code into some other code that already has the box do I just add it in the box or make another box?

You mean the #if-#else block? If you put new code in a block that is compiled if ACTIVISION_ORIGINAL is not defined then you don't need your own. However you have instances in the code where it is done. That's a problem if you start to modify something in a big chunk of new code, so that you don't realize it that you are modifying non ACTIVISION_ORIGINAL code.Originally posted by E
Another question though. The "//" boxes I've been doing for new code. If I add thisnew code into some other code that already has the box do I just add it in the box or make another box?
However for your code fragment you have still to put it into an if-block.
And of course the contex is still missing, you have to insert it somewhere. So it does make sense and not non-sense.
-Martin
Civ2 military advisor: "No complaints, Sir!"

Actually, I was asking abou this kind of block:
I haven't see innstances where multiple changes have occured in the ame code and it may happen as I add CultureOnly to Terain improvements and others.Code://---------------------------------------------------------------------------- // // Name : terrainutil_CanPlayerBuildAt // // Description: Checks terrain improvement properties to see if it can build on a tile only if it has a good // // Parameters : sint32 pl : Variable for player // // //----------------------------------------------------------------------------
As for "context" I'm not sure I'm getting the definition right but do you mean put it in some original code to see where it is positioned? or something else?

In most cases the discriptions are the same function name doesn't change, parameter list doesn't change and if it does change then it is just updated. And if you want to talk about what you have done then edit the Remarks.Originally posted by E
I haven't see innstances where multiple changes have occured in the ame code and it may happen as I add CultureOnly to Terain improvements and others.
At Merriam Webster you find this definition:Originally posted by E
As for "context" I'm not sure I'm getting the definition right but do you mean put it in some original code to see where it is positioned? or something else?
1 : the parts of a discourse that surround a word or passage and can throw light on its meaning
And that is what I mean here the text around your code or better the surrounding code, that clarifies the meaning whether it is right or wrong.
-Martin
Civ2 military advisor: "No complaints, Sir!"

first shot...
Code:BOOL Player::CanBuildUnit(const sint32 type) const { const UnitRecord *rec = g_theUnitDB->Get(type); if (!HasAdvance(rec->GetEnableAdvanceIndex())) return FALSE; sint32 o; for(o = rec->GetNumObsoleteAdvance() - 1; o >= 0; o--) { if(HasAdvance(rec->GetObsoleteAdvanceIndex(o))) return FALSE; } if(g_exclusions->IsUnitExcluded(type)) return FALSE; if(rec->GetCantBuild()) { return FALSE; } if(rec->GetNumGovernmentType() > 0) { sint32 i; bool found = false; for(i = 0; i < rec->GetNumGovernmentType(); i++) { if(rec->GetGovernmentTypeIndex(i) == m_government_type) { found = true; break; } } if(!found) return FALSE; } if(rec->GetNumCultureOnly() > 0) sint32 s; for(s = 0; s < rec->GetCultureOnly(); s++) { if(rec->GetNumCultureOnly(s) == g_player->GetCivilisation()->GetCityStyle()) { return TRUE; } }return FALSE; } if(rec->GetNuclearAttack() && wonderutil_GetNukesEliminated(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids() || rec->GetSlaveUprising()) { if(wonderutil_GetFreeSlaves(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids()) { sint32 i, n = m_all_units->Num(); for(i = 0; i < n; i++) { if(m_all_units->Access(i).GetDBRec()->GetNoSlaves()) return FALSE; } } if(rec->GetNoSlaves()) { sint32 i, n = m_all_cities->Num(); for(i = 0; i < n; i++) { if(m_all_cities->Access(i).CountSlaves() > 0) return FALSE; } n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(m_all_units->Access(i).GetDBRec()->GetSlaveRaids()) return FALSE; } } if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } return TRUE; }
Last edited by Ekmek; March 11, 2005 at 18:05.

Wow if you give this CultureOnly flag to the Abolitionist unit you can build it even if you have slaves. You can build nukes even if the Nanite Defuser has defused every single nuke on earth and would defuse every new nuke as well. You can build Slavers even if you have Abolitionist. And you can build Eco Rangers even if this type of attack is excluded. And all I have to do is to add this flag.
Appart from that and a missing open brace, and awfull usage of white space (get the indention right) the code looks good. To fix the first problem you should move your code to the end of the function (as stated earlier in this thread) right above the final return statement.
To get the civ only attribute working you have to consider that these civs have names for instance:
The first is the civ name, you have to figure out how to retrive this StringID. And of course you have to add a StringID entry to the according *.cdb files.Code:EGYPTIAN "Ägypter" EGYPTIAN_LEADERM_NAME "Ramses" EGYPTIAN_LEADERF_NAME "Hatshepsut" EGYPTIAN_COUNTRY_NAME "Ägypten" EGYPTIAN_SINGULAR "Ägypter" EGYPTIAN_PLURAL "Ägypter"
-Martin
Civ2 military advisor: "No complaints, Sir!"

I just figured out that you put it into the wrong function. In this function the Player::CanBuildUnit method belongs the part about the civilisation.
And into the following function the culture part goes:
If it is CityStyle dependent then I expect that cities with different styles behave different, irrespecteive of the current owner, otherwise you would just need the civ only flag.Code://---------------------------------------------------------------------------- // // Name : CityData::CanBuildUnit // // Description: Checks whether the city can build the unit specified by type. // // Parameters : type: The unit type for that is checked whether the city can // build it. // // Globals : g_player: The list of players // g_theUnitDB: The unit database // g_slicEngine: The slic engine // g_theWorld: The world prperties // // Returns : Whether the city can build the unit specified by type. // // Remark(s) : - // //---------------------------------------------------------------------------- BOOL CityData::CanBuildUnit(sint32 type) const { #if defined(ACTCIVSION_ORIGINAL) // Removed by Martin Gühmann same code in Player::CanBuildUnit const UnitRecord *rec = g_theUnitDB->Get(type); if(!rec) return FALSE; MapPoint pos; m_home_city.GetPos(pos); if (!g_player[m_owner]->HasAdvance(rec->GetEnableAdvanceIndex())) return FALSE; sint32 o; for(o = rec->GetNumObsoleteAdvance() - 1; o >= 0; o--) { if(g_player[m_owner]->HasAdvance(rec->GetObsoleteAdvanceIndex(o))) return FALSE; } if(g_exclusions->IsUnitExcluded(type)) return FALSE; if(rec->GetCantBuild()) { return FALSE; } if(rec->GetNumGovernmentType() > 0) { sint32 i; bool found = false; for(i = 0; i < rec->GetNumGovernmentType(); i++) { if(rec->GetGovernmentTypeIndex(i) == g_player[m_owner]->m_government_type) { found = true; break; } } if(!found) return FALSE; } if(rec->GetNuclearAttack() && wonderutil_GetNukesEliminated(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids() || rec->GetSlaveUprising()) { if(wonderutil_GetFreeSlaves(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids()) { sint32 i, n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_units->Access(i).GetDBRec()->GetNoSlaves()) return FALSE; } } if(rec->GetNoSlaves()) { sint32 i, n = g_player[m_owner]->m_all_cities->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_cities->Access(i).CD()->SlaveCount() > 0) return FALSE; } n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_units->Access(i).GetDBRec()->GetSlaveRaids()) return FALSE; } } if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } #else // Added by Martin Gühmann if(!g_player[m_owner]->CanBuildUnit(type)) return FALSE; const UnitRecord *rec = g_theUnitDB->Get(type); if(!rec) return FALSE; MapPoint pos; m_home_city.GetPos(pos); #endif if(!g_slicEngine->CallMod(mod_CanCityBuildUnit, TRUE, m_home_city.m_id, rec->GetIndex())) return FALSE; if(!rec->GetMovementTypeLand() && !rec->GetMovementTypeTrade() && !rec->GetIsTrader()) { if(g_theWorld->IsWater(pos.x, pos.y) && rec->GetSeaCityCanBuild()) { return TRUE; } if((g_theWorld->IsLand(pos.x, pos.y) || g_theWorld->IsMountain(pos.x, pos.y)) && rec->GetLandCityCanBuild()) { return TRUE; } if(rec->GetMovementTypeSea() || rec->GetMovementTypeShallowWater()) { if(g_theWorld->IsNextToWater(pos.x, pos.y)) { return TRUE; } return FALSE; } else if(rec->GetMovementTypeAir()) { return TRUE; } return FALSE; } return TRUE; }
However the culture stuff should be checked first so at the end of my added-block. It should return FALSE if there was no culture match and it should execute the rest of the code if there was a culture match. And of course you check it against the sytle of the city and not against the style of the owner.
-Martin
Civ2 military advisor: "No complaints, Sir!"

woah, cool.
First, I'm shocked I made it this far this fast.
Second, I wasn't really thinking about matching the unit CultureOnly to the City's style itself. But thats a great idea, so in mods if a european captures and Indian city than can build Indian style units from that city only (like War Elephants in Alexander). Excellent idea, take that civ3!
Will do the corrections and look into the civonly stuff.

I keep seeing the code this stuff to ID the civilization, I'm unclear why these won't work...
(g_theCivilisationDB->GetCivilisation())
(g_theStringDB->GetNameStr(str_id),
Also I really like the CityData CityStyle Idea, but I think I'll make that into CityStyleOnly and keep CultureOnly for units that match the player's citystyle to allow for culture group units (native American, european, etc) its easier than listing all the civs out, and we haven't figured out CivOnly yet...
I'll finish the other stuff this weekend...
Last edited by Ekmek; March 12, 2005 at 20:06.

for CultureOnly....
Code://---------------------------------------------------------------------------- // // Name : CanBuildUnit // // Description: Checks the unit properties to see if a player can build that type of unit // // // Parameters : sint32 s : Variable for citystyle // // // Globals : g_theUnitDB : Unit properties // g_player : Player properties // // Returns : BOOL: TRUE if the Unit record has the same CultureOnly value as the Player's CityStyle // FALSE if the Unit doesn't have this restriction // // Remark(s) : The CultureOnly lets only players with the same CityStyle as CultureOnly's style to build that unit // //---------------------------------------------------------------------------- BOOL Player::CanBuildUnit(const sint32 type) const { const UnitRecord *rec = g_theUnitDB->Get(type); if (!HasAdvance(rec->GetEnableAdvanceIndex())) return FALSE; sint32 o; for(o = rec->GetNumObsoleteAdvance() - 1; o >= 0; o--) { if(HasAdvance(rec->GetObsoleteAdvanceIndex(o))) return FALSE; } if(g_exclusions->IsUnitExcluded(type)) return FALSE; if(rec->GetCantBuild()) { return FALSE; } if(rec->GetNumGovernmentType() > 0) { sint32 i; bool found = false; for(i = 0; i < rec->GetNumGovernmentType(); i++) { if(rec->GetGovernmentTypeIndex(i) == m_government_type) { found = true; break; } } if(!found) return FALSE; } if(rec->GetNuclearAttack() && wonderutil_GetNukesEliminated(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids() || rec->GetSlaveUprising()) { if(wonderutil_GetFreeSlaves(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids()) { sint32 i, n = m_all_units->Num(); for(i = 0; i < n; i++) { if(m_all_units->Access(i).GetDBRec()->GetNoSlaves()) return FALSE; } } if(rec->GetNoSlaves()) { sint32 i, n = m_all_cities->Num(); for(i = 0; i < n; i++) { if(m_all_cities->Access(i).CountSlaves() > 0) return FALSE; } n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(m_all_units->Access(i).GetDBRec()->GetSlaveRaids()) return FALSE; } } if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } #if defined(ACTIVISION_ORIGINAL) if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } #else if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } if(rec->GetNumCultureOnly() > 0) { sint32 s; for(s = 0; s < rec->GetCultureOnly(); s++) { if(rec->GetNumCultureOnly(s) == g_player->GetCivilisation()->GetCityStyle()) { return TRUE; } }return FALSE; } #endif return TRUE; }
Also the CityData.cpp I have is dated 12/6/2004, the last time I saw it was in the all pack you released in december, is there a later one (this one doesn't have your changes).

for CityStyleOnly (even though I have an outdata CityData.cpp)
I put the else because i "think" thats whats need to continue with the code. I also added the != because that sounds like what you said I should do to make it return falseCode:if(rec->GetNumCityStyleOnly() > 0) { sint32 s; for(s = 0; s < rec->GetCityStyleOnly(); s++) { if(rec->GetNumCityStyleOnly(s) != m_cityStyle ->GetCivilisation()->GetCityStyle()) { return FALSE; } } } else #endif
the italics stuff is stuff after the array. My gut tells me to take it out since the m_citystyle I think is an array for a city's citystyle and it will just check that...

Else is not needed unless you want to make something happen if the condition in the if is false. So something like this:Originally posted by E
I put the else because i "think" thats whats need to continue with the code. I also added the != because that sounds like what you said I should do to make it return false
So the else there is not needed.Code:if(a == 1) { a = a +1; } else { a = a + 2 }
The != part I *think* is right, I don't really know though.
Caution! Under no circumstances confuse the mesh with the interleave operator, except under confusing circumstances!
-Intercal reference manual
People often remark of me, "You say sorry far to much!". To which my common-sense reply is "I apologise".

Yes, on my hard driveOriginally posted by E
Also the CityData.cpp I have is dated 12/6/2004, the last time I saw it was in the all pack you released in december, is there a later one (this one doesn't have your changes)., or why should I provide you with a modified version of CityData::CanBuildUnit method?
For the discription: The best is you look at the discription I made for CityData::CanBuildUnit and copy the relevant parts and modify it so that it fits. Then you see that the name of the function is Player::CanBuildUnit and not just CanBuildUnit. This name is ambigious, we see here at least two functions with this name. Then the parameter of this function isn't called s, and it is not for city styles. The return discription is wrong. And the remark doesn't tell me that you added this specific feature we are discussing here.
Well for brevity and to avoid duplicated work, here is the discription of the function Player::CanBuildUnit:
All you have to do now is to write something that makes sense into the Remark(s).Code://---------------------------------------------------------------------------- // // Name : Player::CanBuildUnit // // Description: Checks whether the city can build the unit specified by type. // // Parameters : type: The unit type for that is checked whether the player can // build it. // // Globals : g_player: The list of players // g_theUnitDB: The unit database // g_theWonderTracker: The wonder tracker // g_exclusions: The exclusions data // // Returns : Whether the city can build the unit specified by type. // // Remark(s) : - // //----------------------------------------------------------------------------
Now let's come to the code:
Why do you copy the code about the EcoRangers? First you have it in the #if defined(ACTIVISION_ORIGINAL) block and then you have it in the #else without any changes. That's superflous. defined(ACTIVISION_ORIGINAL) is a boolean expression and if you want to negate it then you use in c++ the exclamation mark operator, that holds for preprocessor derectives as well. And please give the return FALSE; inside your code its own line.Code:#if defined(ACTIVISION_ORIGINAL) if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTrack er->GetBuiltWonders())) { return FALSE; } #else if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTrack er->GetBuiltWonders())) { return FALSE; } if(rec->GetNumCultureOnly() > 0) { sint32 s; for(s = 0; s < rec->GetCultureOnly(); s++) { if(rec->GetNumCultureOnly(s) == g_player->GetCivilisation()->GetCityStyle()) { return TRUE; } }return FALSE; } #endif
Then you exchanged GetCultureOnly and GetNumCultureOnly and actual it should be GetCultureOnlyIndex instead of GetCultureOnly. That is is also true for the CityStyleOnly code and was also the case in the code fragment you posted last time.
Otherwise it looks ok.
Tombom is right about this, it doesn't belong to that place.Originally posted by E
I put the else because i "think" thats whats need to continue with the code.
And that's wrong either. This returns FALSE in most cases, even if it shouldn't.Originally posted by E
I also added the != because that sounds like what you said I should do to make it return false
m_citystyle is a member of CityData and that is not an array that is a long, so a simple number. The best is you take a close look on the GovernmentType code and do some copy and paste actions.Originally posted by E
the italics stuff is stuff after the array. My gut tells me to take it out since the m_citystyle I think is an array for a city's citystyle and it will just check that...
-Martin
Civ2 military advisor: "No complaints, Sir!"

For Culture Only...
As a warning I'm looking to add my code to the advances, buildings, tileimprovements, and wonders as well (and I don't think it will require a change in my coding).
Code://---------------------------------------------------------------------------- // // Name : Player::CanBuildUnit // // Description: Checks whether the city can build the unit specified by type. // // Parameters : type: The unit type for that is checked whether the player can // build it. // // Globals : g_player: The list of players // g_theUnitDB: The unit database // g_theWonderTracker: The wonder tracker // g_exclusions: The exclusions data // // Returns : Whether the city can build the unit specified by type. // // Remark(s) : CultureOnly flag added by E. It allows only civilizations with // the same CityStyle as CultureOnly's style to build that unit // //---------------------------------------------------------------------------- BOOL Player::CanBuildUnit(const sint32 type) const { #if defined(ACTIVISION_ORIGINAL) const UnitRecord *rec = g_theUnitDB->Get(type); if (!HasAdvance(rec->GetEnableAdvanceIndex())) return FALSE; sint32 o; for(o = rec->GetNumObsoleteAdvance() - 1; o >= 0; o--) { if(HasAdvance(rec->GetObsoleteAdvanceIndex(o))) return FALSE; } if(g_exclusions->IsUnitExcluded(type)) return FALSE; if(rec->GetCantBuild()) { return FALSE; } if(rec->GetNumGovernmentType() > 0) { sint32 i; bool found = false; for(i = 0; i < rec->GetNumGovernmentType(); i++) { if(rec->GetGovernmentTypeIndex(i) == m_government_type) { found = true; break; } } if(!found) return FALSE; } if(rec->GetNuclearAttack() && wonderutil_GetNukesEliminated(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids() || rec->GetSlaveUprising()) { if(wonderutil_GetFreeSlaves(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids()) { sint32 i, n = m_all_units->Num(); for(i = 0; i < n; i++) { if(m_all_units->Access(i).GetDBRec()->GetNoSlaves()) return FALSE; } } if(rec->GetNoSlaves()) { sint32 i, n = m_all_cities->Num(); for(i = 0; i < n; i++) { if(m_all_cities->Access(i).CountSlaves() > 0) return FALSE; } n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(m_all_units->Access(i).GetDBRec()->GetSlaveRaids()) return FALSE; } } if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } #else if(rec->GetNumCultureOnly() > 0) { sint32 s; for(s = 0; s < rec->GetNumCultureOnly(); s++) { if(rec->GetCultureOnlyIndex(s) == GetCivilisation()->GetCityStyle()) { return TRUE; } } return FALSE; } #endif return TRUE; }
Last edited by Ekmek; March 14, 2005 at 11:57.

For CityStyleOnly...
I added it to the code you posted and since its only on your hard I figured I'd add it into the standard too (to prevent you from adding back your changes)...
Also I used m_founder instead of m_owner that I found in your code to remember a city's citystyle (a nice add on by the way). I hoping this is the right way to check the city's style as opposed to the current owner's style.
Code://---------------------------------------------------------------------------- // // Name : CityData::CanBuildUnit // // Description: Checks whether the city can build the unit specified by type. // // Parameters : type: The unit type for that is checked whether the city can // build it. // // Globals : g_player: The list of players // g_theUnitDB: The unit database // g_slicEngine: The slic engine // g_theWorld: The world prperties // // Returns : Whether the city can build the unit specified by type. // // Remark(s) : CityStyleOnly added by E. Limits certain units to be built only // at certain cities of certain styles. // //---------------------------------------------------------------------------- BOOL CityData::CanBuildUnit(sint32 type) const { #if defined(ACTCIVSION_ORIGINAL) // Removed by Martin Gühmann same code in Player::CanBuildUnit const UnitRecord *rec = g_theUnitDB->Get(type); if(!rec) return FALSE; MapPoint pos; m_home_city.GetPos(pos); if (!g_player[m_owner]->HasAdvance(rec->GetEnableAdvanceIndex())) return FALSE; sint32 o; for(o = rec->GetNumObsoleteAdvance() - 1; o >= 0; o--) { if(g_player[m_owner]->HasAdvance(rec->GetObsoleteAdvanceIndex(o))) return FALSE; } if(g_exclusions->IsUnitExcluded(type)) return FALSE; if(rec->GetCantBuild()) { return FALSE; } if(rec->GetNumGovernmentType() > 0) { sint32 i; bool found = false; for(i = 0; i < rec->GetNumGovernmentType(); i++) { if(rec->GetGovernmentTypeIndex(i) == g_player[m_owner]->m_government_type) { found = true; break; } } if(!found) return FALSE; } if(rec->GetNuclearAttack() && wonderutil_GetNukesEliminated(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids() || rec->GetSlaveUprising()) { if(wonderutil_GetFreeSlaves(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids()) { sint32 i, n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_units->Access(i).GetDBRec()->GetNoSlaves()) return FALSE; } } if(rec->GetNoSlaves()) { sint32 i, n = g_player[m_owner]->m_all_cities->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_cities->Access(i).CD()->SlaveCount() > 0) return FALSE; } n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_units->Access(i).GetDBRec()->GetSlaveRaids()) return FALSE; } } if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTrack er->GetBuiltWonders())) { return FALSE; } #else // Added by Martin Gühmann if(!g_player[m_owner]->CanBuildUnit(type)) return FALSE; const UnitRecord *rec = g_theUnitDB->Get(type); if(!rec) return FALSE; MapPoint pos; m_home_city.GetPos(pos); // Added by E if(rec->GetNumCityStyleOnly() > 0) { sint32 s; for(s = 0; s < rec->GetNumCityStyleOnly(); s++) { if(rec->GetCityStyleOnlyIndex(s) == g_player[m_founder]->m_citystyle) { return TRUE; } } return FALSE } #endif if(!g_slicEngine->CallMod(mod_CanCityBuildUnit, TRUE, m_home_city.m_id, rec->GetIndex())) return FALSE; if(!rec->GetMovementTypeLand() && !rec->GetMovementTypeTrade() && !rec->GetIsTrader()) { if(g_theWorld->IsWater(pos.x, pos.y) && rec->GetSeaCityCanBuild()) { return TRUE; } if((g_theWorld->IsLand(pos.x, pos.y) || g_theWorld->IsMountain(pos.x, pos.y)) && rec->GetLandCityCanBuild()) { return TRUE; } if(rec->GetMovementTypeSea() || rec->GetMovementTypeShallowWater()) { if(g_theWorld->IsNextToWater(pos.x, pos.y)) { return TRUE; } return FALSE; } else if(rec->GetMovementTypeAir()) { return TRUE; } return FALSE; } return TRUE; }
Last edited by Ekmek; March 13, 2005 at 15:29.

Player::CanBuildUnit
What does do the #if defined(ACTIVISION_ORIGINAL) at the start of the function, you was was supposed to replace the #else by #if !defined(ACTIVISION_ORIGINAL). This mistake shows me that so far you haven't done the preprocessor exercise. Do it now. In the description block you used tabs instead of spaces. While spending the return FALSE; its own line you deleted a closing brace, that you have to reinsert.
The retriving the city style, first g_player is an array, so it should be g_player[m_owner], second g_player[m_owner] is here identical with the this pointer, so it doesn't need to be written here.
Otherwise it seems to be fine.
CityData::CanBuildUnit
If now CityStyleOnly is defined then the according unit can be build if the according city style match, even if it is a boat and the city is not a costoal city. Actual I told you look at the GovernmentType code, as it does excactly we want just for Govenments enistead of city styles: And this thread is now full of this piece of code.
What does this fragment of code it returns FALSE if there is at least one government defined and there wasn't a matching government, otherwise it let the function contine the execution.Code:if(rec->GetNumGovernmentType() > 0) { sint32 i; bool found = false; for(i = 0; i < rec->GetNumGovernmentType(); i++) { if(rec->GetGovernmentTypeIndex(i) == g_player[m_owner]->m_government_type) { found = true; break; } } if(!found) return FALSE; }
Then also retriving the city style doesn't work like this. There is no Player::m_citystyle, there is only a CityData::m_citystyle, so just write m_citystyle into the code.
-Martin
Civ2 military advisor: "No complaints, Sir!"

For CitystyleOnly...I just redid governmenttype...
Code://---------------------------------------------------------------------------- // // Name : CityData::CanBuildUnit // // Description: Checks whether the city can build the unit specified by type. // // Parameters : type: The unit type for that is checked whether the city can // build it. // // Globals : g_player: The list of players // g_theUnitDB: The unit database // g_slicEngine: The slic engine // g_theWorld: The world prperties // // Returns : Whether the city can build the unit specified by type. // // Remark(s) : CityStyleOnly added by E. Limits certain units to be built only // at certain cities of certain styles. // //---------------------------------------------------------------------------- BOOL CityData::CanBuildUnit(sint32 type) const { #if defined(ACTCIVSION_ORIGINAL) // Removed by Martin Gühmann same code in Player::CanBuildUnit const UnitRecord *rec = g_theUnitDB->Get(type); if(!rec) return FALSE; MapPoint pos; m_home_city.GetPos(pos); if (!g_player[m_owner]->HasAdvance(rec->GetEnableAdvanceIndex())) return FALSE; sint32 o; for(o = rec->GetNumObsoleteAdvance() - 1; o >= 0; o--) { if(g_player[m_owner]->HasAdvance(rec->GetObsoleteAdvanceIndex(o))) return FALSE; } if(g_exclusions->IsUnitExcluded(type)) return FALSE; if(rec->GetCantBuild()) { return FALSE; } if(rec->GetNumGovernmentType() > 0) { sint32 i; bool found = false; for(i = 0; i < rec->GetNumGovernmentType(); i++) { if(rec->GetGovernmentTypeIndex(i) == g_player[m_owner]->m_government_type) { found = true; break; } } if(!found) return FALSE; } if(rec->GetNuclearAttack() && wonderutil_GetNukesEliminated(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids() || rec->GetSlaveUprising()) { if(wonderutil_GetFreeSlaves(g_theWonderTracker->GetBuiltWonders())) { return FALSE; } } if(rec->GetSlaveRaids() || rec->GetSettlerSlaveRaids()) { sint32 i, n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_units->Access(i).GetDBRec()->GetNoSlaves()) return FALSE; } } if(rec->GetNoSlaves()) { sint32 i, n = g_player[m_owner]->m_all_cities->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_cities->Access(i).CD()->SlaveCount() > 0) return FALSE; } n = g_player[m_owner]->m_all_units->Num(); for(i = 0; i < n; i++) { if(g_player[m_owner]->m_all_units->Access(i).GetDBRec()->GetSlaveRaids()) return FALSE; } } if(rec->GetCreateParks() && !wonderutil_GetParkRangersEnabled(g_theWonderTrack er->GetBuiltWonders())) { return FALSE; } #else // Added by Martin Gühmann if(!g_player[m_owner]->CanBuildUnit(type)) return FALSE; const UnitRecord *rec = g_theUnitDB->Get(type); if(!rec) return FALSE; MapPoint pos; m_home_city.GetPos(pos); // Added by E if(rec->GetNumCityStyleOnly() > 0) { sint32 s; bool found = false; for(s = 0; s < rec->GetNumCityStyleOnly(); s++) { if(rec->GetCityStyleOnlyIndex(s) == m_citystyle) { found = true; break; } } if(!found) return FALSE; } #endif if(!g_slicEngine->CallMod(mod_CanCityBuildUnit, TRUE, m_home_city.m_id, rec->GetIndex())) return FALSE; if(!rec->GetMovementTypeLand() && !rec->GetMovementTypeTrade() && !rec->GetIsTrader()) { if(g_theWorld->IsWater(pos.x, pos.y) && rec->GetSeaCityCanBuild()) { return TRUE; } if((g_theWorld->IsLand(pos.x, pos.y) || g_theWorld->IsMountain(pos.x, pos.y)) && rec->GetLandCityCanBuild()) { return TRUE; } if(rec->GetMovementTypeSea() || rec->GetMovementTypeShallowWater()) { if(g_theWorld->IsNextToWater(pos.x, pos.y)) { return TRUE; } return FALSE; } else if(rec->GetMovementTypeAir()) { return TRUE; } return FALSE; } return TRUE; }
Bookmarks