love the button idea, can it go dark if it cannot be used? like how some attacks go dark when inside a city
and if we have a button, do we want that they need to be in a city?

I'm hoping that Upgrading units becomes part of the code (I'm sure many do)
I figure it will involve a lot of code, and I'm hoping others may be interested. I've done some initial digging and see that we'll have to add a button (like I've done under the expel boot):
Then I think we'll have to add the upgrade flag of course (I already added it to the cdb)
A CanUpgrade function that will entail if the unit is at a city, if an advance is available and (possibly) if a building is available.
Next the cost. The slic is pre-set but I think if we calculate the shield cost of the unit minus the cost of the upgrading unit times a number of Gold (is there somewhere that gives a gold to shield ratio? I didn't see it in DiffDB and thought infrastructure or capitalization would have it)
Then the upgrade paths. this may be hardest for me since I'm not sure how to get it to check if you've missed a few upgrades (say a warrior to infrantry but you didn't upgrade to pikemen)
Finally, AI. Should we make it free for the AI like the SLIC or try to teach it. I notice Civ3 isn't good at this and I tend toward giving the AI free, automatic upgrades (for the challenge factor if anything).
Please post comments and I hope some are willing to contribute (because I have to finish show on map first).

love the button idea, can it go dark if it cannot be used? like how some attacks go dark when inside a city
and if we have a button, do we want that they need to be in a city?

Units can only be upgraded within a city, a fortification or perhaps when grouped with a "supply" unit?
As for the AI, it should at least be tried to use it properly without giving it a cheat of free upgrades first. /Martin G.![]()
Call to Power 2: Apolyton Edition - download the latest version (12th June 2011)
CtP2 AE Wiki & Modding Reference
One way to compile the CtP2 Source Code.

fortification and supply unit hmmm I guess it would just require addind an additional flag for imps and units and then a check at the position of the unit...
Yeah I'd like the AI to "think" about it to, but as my code attempts show I think AI is out of my league for now.
Last edited by Ekmek; March 27, 2005 at 22:34.

Just a little research as I fix (again) my code. I think the CDB may have to have something like:
Code:Struct UpgradeTo { Record Unit Unit Int Cost }

The easiest solution to this is, to check on the BeginTurnUnit event whether the unit can be upgraded and if it can upgrade it. Of course this has nothing to do with strategic planing but is better than nothing.Originally posted by E
fortification and supply unit hmmm I guess it would just require addind an additional flag for imps and units and then a check at the position of the unit...
Yeah I'd like the AI to "think" about it to, but as my code attempts show I think AI is out of my league for now.
Why so restrictive? It should be up to the modder how it works, whether the unit needs to be in a city or can be upgraded on high sea.Originally posted by Maquiladora
Units can only be upgraded within a city, a fortification or perhaps when grouped with a "supply" unit?
-Martin
Last edited by Martin Gühmann; March 28, 2005 at 13:08.
Civ2 military advisor: "No complaints, Sir!"

Well that was my point Martin, that it should be possible with a unit (called "supply unit" as an example) with a flag present on the same tile as the unit wanting to be upgraded, a certain city improvement present in the city, a flag for tile improvements capable of it, whatever, so its all possible.
Call to Power 2: Apolyton Edition - download the latest version (12th June 2011)
CtP2 AE Wiki & Modding Reference
One way to compile the CtP2 Source Code.
In the case of naval units, assuming they're being considered, I don't think that upgrading should be possible. Ships cannot be modified to the extent of the Tech leaps in CtP2. You can't really convert a Ship-of-the-Line into an Ironclad! The only item to carry over would be the crews.
Also, once Tech reaches a certain level, some upgrades won't be possible in the field, ie, Cavalry to Tank, as they are equipment specific.

actually you CAN "convert a Ship-of-the-Line into an Ironclad", but not into anything after ironclads...
but what if upgrade had different cost depending on situation? fort cost more than city (forts dont make extra stuff for soldiers) and then quite a jump for when grouped w/ some supply or hero unit? possible?

I should say that the struct describing the upgrade should add any other requirement. e.g. the struct could also have RequiredBuilding if a building is required, etc...
On the other hand, it would really be nice to have arbitrary logical combinations of requirements, and the only way to do this is to hand off to SLIC - perhaps some simple text-file based method like requiring a building, and then hand off to SLIC (via a new mod_ function or an appropriate event) to allow modders to do anything more complicated that they want (like supply units, etc.).

J,
are you recommending something like a SLICflag that in the SLIC code you could have the SLIC see if a unit has that flag and then have an operation with it. OR create a SLIC flag that you specify the slic file and if you have the unit at the start of the turn it runs the slic file?

Nothing to get excited about just a draft of my code (still need to finish ShowOnMap)
This is just based on my success with gifting units. It came to me that the disbanding and creating a unit would be similar to upgrading units but with a few different checks.
However, this should be a separate order than disband so I have to figure out how to add new orders. and the a check for city building, tileimp, and a unit with a upgrading property. then what to do with the AI. Civ3 is no guide because I didn't see the AI do much upgrading. My inclination is to have some units upgrade every age or number of turns and NOT cost the AI gold because the AI spends his gold too fast to store enough for upgrading.
This is all down the road, just getting it documented.
Anyways my Upgrade code is in there but I'm sure I'll have to do some tweaking tonight so I'll see if the basic mechanics work.
Code://Disband an army. Recover 1/2 it's ShieldCost if it's in a city. void ArmyData:: Disband() { Cell *cell = g_theWorld->GetCell(m_pos); sint32 CellOwner = cell->GetOwner(); Diplomat & cell_diplomat = Diplomat::GetDiplomat(CellOwner); if(g_player[m_owner]->m_all_armies->Num() < 2 && g_player[m_owner]->m_all_cities->Num() < 1) return; sint32 i; Unit city = g_theWorld->GetCity(m_pos); for(i = m_nElements - 1; i >= 0; i--) { if(city.m_id != (0)) { //Initial Upgrade code (before I know how to create new orders) by E 4-17-2006 if(m_array[i].GetDBRec()->GetUpgradeTo()){ sint32 newunit = m_array[i].GetDBRec()->GetNumUpgradeTo(); sint32 newshields = g_theUnitDB->Get(m_array[i].GetDBRec()->GetNumUpgradeTo(), g_player[m_owner]->GetGovernmentType())->GetShieldCost(); sint32 oldschield = m_array[i].GetDBRec()->GetShieldCost(); sint32 rushmod = g_theGovernmentDB->Get(g_player[m_owner]->m_government_type)->GetUnitRushModifier(); sint32 goldcost = (newshields - oldshields) * rushmod; if((g_player[m_owner]->GetPlayerType() != PLAYER_TYPE_ROBOT) && (g_player[m_owner]->m_gold->GetLevel() > goldcost) && (city.AccessData()->GetCityData()->CanBuildUnit(newunit))) { m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); g_player[m_owner]->CreateUnit(newunit, m_pos, Unit(), FALSE, CAUSE_NEW_ARMY_INITIAL); g_player[m_owner]->m_gold->SubGold(goldcost); } else { city.AccessData()->GetCityData()->AddShields(m_array[i].GetDBRec()->GetShieldCost() / 2); } } else { city.AccessData()->GetCityData()->AddShields(m_array[i].GetDBRec()->GetShieldCost() / 2); } } // m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); // } //EMOD Gift Units for Human Player 4-12-2006 if (!AgreementMatrix::s_agreements.HasAgreement(CellOwner, m_owner, PROPOSAL_TREATY_DECLARE_WAR)){ if(m_array[i].GetDBRec()->GetCanBeGifted()){ sint32 newunit = m_array[i].GetType(); sint32 regardcost = (m_array[i].GetDBRec()->GetAttack()) / 5; if((g_player[m_owner]->GetPlayerType() != PLAYER_TYPE_ROBOT) && (CellOwner > 0)) { StringId strId; g_theStringDB->GetStringID("REGARD_EVENT_UNITS_GIFTED", strId); m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); g_player[CellOwner]->CreateUnit(newunit, m_pos, Unit(), FALSE, CAUSE_NEW_ARMY_INITIAL); cell_diplomat.LogRegardEvent(m_owner, regardcost, REGARD_EVENT_GOLD, strId); } else { m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); } } else { m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); } } else { m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); } } /// if ( g_selected_item->GetSelectedCity(city) ) { } }

You put the stuff into ArmyData::Disband(), are mad? You should use for it an own method.
-Martin
Civ2 military advisor: "No complaints, Sir!"

I know and it will be its own method (eventually) but for now I just wanted to check if the disband and creating works as well as the gold and shield cost checks. then I'll move it to an upgrade function and map it to an order

Must it really be disband and create? Why not just change the unit owner?Originally posted by E
disband and creating
-Martin
Civ2 military advisor: "No complaints, Sir!"

Oh, for Gifting. I'll check it out, so far it works thoughOriginally posted by Martin Gühmann
Must it really be disband and create? Why not just change the unit owner?
-Martin![]()

Well it depends where it is, whether it is in a city or in open field espeacilly whether it is in the land of the receiver.Originally posted by E
Oh, for Gifting. I'll check it out, so far it works though![]()
-Martin
Civ2 military advisor: "No complaints, Sir!"

thats what i was going for, it just disbands everywhere else. once i make Gifting an order than I'll have a bool if the cell is valid for gifting.Originally posted by Martin Gühmann
Well it depends where it is, whether it is in a city or in open field espeacilly whether it is in the land of the receiver.
-Martin

So you want to do it like in Civ4, and not like in Civ2 where you send the units via diplomacy.Originally posted by E
thats what i was going for, it just disbands everywhere else. once i make Gifting an order than I'll have a bool if the cell is valid for gifting.
-Martin
Civ2 military advisor: "No complaints, Sir!"

yes, it seems more tedius but i'm not up for the task of doing it through diplomacy

I decided to test Upgrading in Sleep (like the slic) instead of disband. Sleep does it work better because why would you sleep in a city instead of entrench and naval units probably wont be upgradeable (you got to build a new ship)
anyways I tired a lot of times and eventually just outcommented it all. Here it is for history sake
Code:// Put this army on sentinal duty. void ArmyData::Sleep() { //ORIGINAL // sint32 i; // for(i = 0; i < m_nElements; i++) { // //EMOD upgrade code 4-25-2006 outcommented sint32 i; sint32 s = 0; Unit city = g_theWorld->GetCity(m_pos); for(i = m_nElements - 1; i >= 0; i--) { // if((city.m_id != (0)) && (m_array[i].GetDBRec()->GetUpgradeToIndex(s))) { // add terrainutil_HasAirfield(m_pos) || terrainutil_HasFort(m_pos) || terrainutil_HasUpgrader(m_pos) // for(s = 0; s < m_array[i].GetDBRec()->GetNumUpgradeTo(); s++) { // sint32 s = m_array[i].GetDBRec()->GetNumUpgradeTo(); // s++) { //m_array[i].GetDBRec()->GetUpgradeToIndex(s) // if(city.AccessData()->GetCityData()->CanBuildUnit(m_array[i].GetDBRec()->GetUpgradeToIndex(s))){ // sint32 newunit = m_array[i].GetDBRec()->GetUpgradeToIndex(s); // sint32 newshields = m_array[i].GetDBRec()->GetShieldCost() * 2; // sint32 oldshields = m_array[i].GetDBRec()->GetShieldCost(); // sint32 rushmod = g_theGovernmentDB->Get(g_player[m_owner]->m_government_type)->GetUnitRushModifier(); // sint32 goldcost = (newshields - oldshields);// * rushmod; // // if((city.AccessData()->GetCityData()->CanBuildUnit(m_array[i].GetDBRec()->GetUpgradeToIndex(s))) ){//&& (g_player[m_owner]->m_gold->GetLevel() > goldcost)) { //&& (g_player[m_owner]->GetPlayerType() != PLAYER_TYPE_ROBOT) // m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); // g_player[m_owner]->CreateUnit(s, m_pos, Unit(), FALSE, CAUSE_NEW_ARMY_INITIAL); // g_player[m_owner]->m_gold->SubGold(goldcost); // } else { // g_gevManager->AddEvent(GEV_INSERT_AfterCurrent, GEV_SleepUnit, // GEA_Unit, m_array[i], // GEA_End); // } // // } // } else { //end EMOD g_gevManager->AddEvent(GEV_INSERT_AfterCurrent, GEV_SleepUnit, GEA_Unit, m_array[i], GEA_End); // } } }
I should note that it was generating a crash when it tried to get the unit. GetDBRec and GetOwner were mentioned there too (I dont have the crash.txt with me right now). Cant figure out how to fix. I tried a debugslic but that getcontinent assert is still there. I'll try again with another playtest version I have.

E, why do you kill the unit and add a new one instead of simply replacing its type?
-Martin
Civ2 military advisor: "No complaints, Sir!"

I don't think there is a ChangeType function. And I haven't seen an example of a unit changing its type. But also when you create a unit it adds it to the array and killing it removes it so this is the best way that i can keep those things in line. Atleast with my limited knowledge.

And what? Can't you make a SetType method?Originally posted by E
I don't think there is a ChangeType function.(SetType that is the standart name for such methods by the way)
And that keeps you from doing, instead of the plain simple way you chose a complicate way of killing the old unit causing a lot computed stuff and adding a new unit and again this means adding a lot of CPU load and memory usage and so on.Originally posted by E
And I haven't seen an example of a unit changing its type. But also when you create a unit it adds it to the array and killing it removes it so this is the best way that i can keep those things in line. Atleast with my limited knowledge.
Making it more complicated than necessary asks for trouble, basicly it is just an asignement of a new value and maybe an additional graphic update and you are done.
-Martin
Civ2 military advisor: "No complaints, Sir!"

Well I got it working with this bit of code
But upgrading from a warrior to a legion (in my civ3 mod) came to 2000 gold. So I'm thinking about reducing the rushmodCode:// Put this army on sentinal duty or upgrade it. void ArmyData::Sleep() { Cell *cell = g_theWorld->GetCell(m_pos); sint32 CellOwner = cell->GetOwner(); sint32 i; sint32 s; //rec = g_theUnitDB->Get(m_array[i].GetType(), g_player[GetOwner()]->GetGovernmentType()); Unit city = g_theWorld->GetCity(m_pos); for(i = m_nElements - 1; i >= 0; i--) { const UnitRecord *rec = m_array[i].GetDBRec(); if((city.m_id != (0)) && (rec->GetNumUpgradeTo() > 0)) { for(s = 0; s < rec->GetNumUpgradeTo(); s++) { sint32 oldshield = rec->GetShieldCost(); sint32 newshield = g_theUnitDB->Get(rec->GetUpgradeToIndex(s))->GetShieldCost(); sint32 rushmod = g_theGovernmentDB->Get(g_player[m_owner]->m_government_type)->GetUnitRushModifier(); sint32 goldcost = (newshield - oldshield) * rushmod; sint32 newunit = rec->GetUpgradeToIndex(s); if(city.AccessData()->GetCityData()->CanBuildUnit(rec->GetUpgradeToIndex(s)) && (g_player[m_owner]->m_gold->GetLevel() > goldcost)){ m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); g_player[m_owner]->CreateUnit(newunit, m_pos, Unit(), FALSE, CAUSE_NEW_ARMY_INITIAL); g_player[m_owner]->m_gold->SubGold(goldcost); } else { g_gevManager->AddEvent(GEV_INSERT_AfterCurrent, GEV_SleepUnit, GEA_Unit, m_array[i], GEA_End); } } } else { g_gevManager->AddEvent(GEV_INSERT_AfterCurrent, GEV_SleepUnit, GEA_Unit, m_array[i], GEA_End); } } }

And why do you still break a fly on the wheel by killing the old unit and creating a new unit instead of just changing the type of the unit?
-Martin
Civ2 military advisor: "No complaints, Sir!"

that would entail creating a function that identifies the type of the unit (GetType()) and finding some way to change that sint32. Where I can understand what needs to be done, I still don't know how to do it. My best guess was that the SetType would be something like type = upgradetoIndex(s) kind of like how the gold = 0 stuff works. But still not sure how to call it.Originally posted by Martin Gühmann
And why do you still break a fly on the wheel by killing the old unit and creating a new unit instead of just changing the type of the unit?
-Martin
So yes I'm lazy but I'm also not a programmer and so far this works. I'm open to change with more instructionbut I think that should be explored once I learn more about how new orders are created so we don't use the sleep command.
But I am happy this worksthis was actually a lot less lines than i thought it would take and its easy for modders to implement with out doing a lot of changing to the slic files

No it doesn't, because there is already a method called UnitData::GetType. All you need is to create a UnitData::SetType method. There are myrads of examples of Get and Set methods in the entire source code. So it shouldn't be a problem to copy and paste and modify one of them. If you don't at an input valid check then it is just one single little tiny additional line to UnitData.h.Originally posted by E
that would entail creating a function that identifies the type of the unit (GetType()) and finding some way to change that sint32.
It is something like this, the upgrade to index is the argument of the SetType method and you don't need to figure out its type, because the type is just an index into the unit database, and since you have the record you don't need this.Originally posted by E
Where I can understand what needs to be done, I still don't know how to do it. My best guess was that the SetType would be something like type = upgradetoIndex(s) kind of like how the gold = 0 stuff works. But still not sure how to call it.
Maybe I should be lazzy too and just outcomment those pieces of inefficent, buggy or not working at all code.Originally posted by E
So yes I'm lazy but I'm also not a programmer and so far this works.
Well for the start I would be happy with a replacement of the unit killing and creation overhead by a simple type change. Maybe I should really outcomment those two lines in question in my next revision so that you can find them more easily.Originally posted by E
I'm open to change with more instructionbut I think that should be explored once I learn more about how new orders are created so we don't use the sleep command.
The next step is to put the stuff into its own Unit::Upgrade method and than call this method by a UnitUpgrade event.
A change type slic function would be nice, but before we get this one we need such a method in the Unit class.Originally posted by E
But I am happy this worksthis was actually a lot less lines than i thought it would take and its easy for modders to implement with out doing a lot of changing to the slic files
-Martin
Civ2 military advisor: "No complaints, Sir!"

Looking here...
and based on this in unit.cppCode:void UnitData::SetOwner(PLAYER_INDEX newo) { m_owner = newo; ENQUEUE(); }
I realize I have to make a void function for set type and it will call a sint32 for the new type. But I'm guess m_type in unitdata.cpp I jus set to the type value?Code:PLAYER_INDEX Unit::GetOwner() const { return g_theUnitPool->GetUnit(m_id)->GetOwner(); } sint32 Unit::GetType() const { return g_theUnitPool->GetUnit(m_id)->GetType(); }
I'll give it a shot

well I tried this and all it did was sleep the unit and take my gold
Code:for(i = m_nElements - 1; i >= 0; i--) { const UnitRecord *rec = m_array[i].GetDBRec(); if((city.m_id != (0)) && (rec->GetNumUpgradeTo() > 0)) { for(s = 0; s < rec->GetNumUpgradeTo(); s++) { sint32 oldshield = rec->GetShieldCost(); sint32 newshield = g_theUnitDB->Get(rec->GetUpgradeToIndex(s))->GetShieldCost(); sint32 rushmod = g_theGovernmentDB->Get(g_player[m_owner]->m_government_type)->GetUnitRushModifier(); sint32 goldcost = (newshield - oldshield) * rushmod; sint32 newunit = rec->GetUpgradeToIndex(s); if(city.AccessData()->GetCityData()->CanBuildUnit(rec->GetUpgradeToIndex(s)) && (g_player[m_owner]->m_gold->GetLevel() > goldcost)){ m_array[i].SetType(newunit); //m_array[i].Kill(CAUSE_REMOVE_ARMY_DISBANDED, -1); //g_player[m_owner]->CreateUnit(newunit, m_pos, Unit(), FALSE, CAUSE_NEW_ARMY_INITIAL); g_player[m_owner]->m_gold->SubGold(goldcost); } else { g_gevManager->AddEvent(GEV_INSERT_AfterCurrent, GEV_SleepUnit, GEA_Unit, m_array[i], GEA_End); } } } else {Code:void Unit::SetType(const sint32 type) { AccessData()->SetType(type); } void UnitData::SetType(sint32 type) { m_type = type; //ENQUEUE(); }
not seeing how type is accesed
Bookmarks