Announcement

Collapse
No announcement yet.

PROJECT: Good Specific Terrain Improvements

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PROJECT: Good Specific Terrain Improvements

    Martin has been helping me (in the other forum) on how to code Cities that can only settle on specific types of terrain. I might be almost done with that, so my next attempt is along the same lines. Its to add a flag that makes it so that the player can only build terrain improvements on tiles with certain goods. I feel this will give the modder the ability to add some unique improvements and add different bonuses to a game.


    I know I have to add a spot in the terrutil.cdb, but terrainutil.cpp will be my coding challenging

    Code:
    bool terrainutil_CanPlayerBuildAt(const TerrainImprovementRecord *rec, sint32 pl, const MapPoint &pos)
    {
    	sint32 i;
                 [b] I think I need to define a variable here [/b]
    	Assert(rec != NULL);
    	if(rec == NULL)
    		return false;
    
    	Assert(pl >= 0);
    	Assert(pl < k_MAX_PLAYERS);
    	if(pl < 0 || pl >= k_MAX_PLAYERS)
    		return false;
    
    	Assert(g_player[pl]);
    	if(!g_player[pl])
    		return false;
    
    	Cell *cell = g_theWorld->GetCell(pos);
    	Assert(cell);
    	if(!cell)
    		return false;
    
    	if(cell->GetOwner() == -1) {
    		if(rec->GetIntBorderRadius()) {
    			if(!g_player[pl]->IsVisible(pos)) {
    				
    				return false;
    			}
    		} else {
    			return false;
    		}
    	}
    
    	if(cell->GetOwner() >= 0 && cell->GetOwner() != pl)
    	{
    		
    		bool haveAlliance = AgreementMatrix.s_agreements.HasAgreement(pl, cell->GetOwner(), PROPOSAL_TREATY_ALLIANCE);
    
    		if(cell->GetOwner() > 0 && haveAlliance) {
    			if(rec->GetClassRoad() ||
    				(g_player[pl]->GetGaiaController() && g_player[pl]->GetGaiaController()->GaiaControllerTileImp(rec->GetIndex()))) {
    				
    				
    			} else {
    				return false;
    			}
    		} else {
    			return false;
    		}
    	}
    
    	
    	if(g_theWorld->GetCity(pos).IsValid())
    		return false;
    		
    	if(rec->GetClassTerraform()) {
    		sint32 terr;
    		if(!rec->GetTerraformTerrainIndex(terr))
    			return false;
    
    		if(cell->GetTerrain() == terr)
    			return false;
    
    		const TerrainRecord *tfrom = g_theTerrainDB->Get(cell->GetTerrain());
    		const TerrainRecord *tto = g_theTerrainDB->Get(terr);
    		if(tfrom->GetRemoveAdvanceIndex() < 0 || tto->GetAddAdvanceIndex() < 0)
    			return false;
    
    		if(!g_player[pl]->HasAdvance(tfrom->GetRemoveAdvanceIndex()) ||
    			!g_player[pl]->HasAdvance(tto->GetAddAdvanceIndex())) {
    			return false;
    		}
    	} else {
    		
    		const TerrainImprovementRecord::Effect *eff;
    		eff = terrainutil_GetTerrainEffect(rec, cell->GetTerrain());
    		if(!eff)
    			return false;
    		
    		if(!g_player[pl]->HasAdvance(eff->GetEnableAdvanceIndex()))
    			return false;
    		
    		sint32 a;
    		for(a = 0; a < eff->GetNumObsoleteAdvance(); a++) {
    			if(g_player[pl]->HasAdvance(eff->GetObsoleteAdvanceIndex(a))) {
    				return false;
    			}
    		}
    		
    	[i][b] I think this is the code I should base it on: [/b][/i]
    	
    		[b]for(i = 0; i < rec->GetNumCantBuildOn(); i++) {
    			if(rec->GetCantBuildOnIndex(i) == cell->GetTerrain()) {
    				return FALSE;
    			}
    		} [/b]
    	}
    
    [i][b] but something like this: [/b][/i]	
    
    [b]for(r = 0; r < g_theResourceDB->Get(resource); r++) {
    			if(rec->GetBuildGoodOnIndex(r) == cell->GetTerrain()) {
    				return FALSE;  //changed, thanks J
    			}
    		}  [/b]
    
    
    	return true;
    }


    this is just my working start, but comment if interested....
    Last edited by Ekmek; January 21, 2005, 12:52.
    Formerly known as "E" on Apolyton

    See me at Civfanatics.com

  • #2
    If you do things that way around you must remember to return false if the program gets through the whole for loop without returning true.

    Comment


    • #3
      Thanks J. I need to check on how goods are linked. I don't think I can use the SLIC HasGood function here can I?
      Formerly known as "E" on Apolyton

      See me at Civfanatics.com

      Comment


      • #4
        NO but you can rip off the code
        "Every time I learn something new it pushes some old stuff out of my brain" Homer Jay Simpson
        The BIG MC making ctp2 a much unsafer place.
        Visit the big mc’s website

        Comment


        • #5
          BigMC you know where the code is? just checking before I run a HasGood search in XP....

          PS I've looked throught the mapgenfiles once or twice. My C++ is very weak but it made some sense. I think we might have to look into it (with help) if we are ever going to get the new terrains (and ctp2 to accept them better) added in there...
          Formerly known as "E" on Apolyton

          See me at Civfanatics.com

          Comment


          • #6
            Originally posted by J Bytheway
            If you do things that way around you must remember to return false if the program gets through the whole for loop without returning true.
            E, John means the return after the for loop not within the for loop. And by the way the function should return a bool and not a BOOL, these are two different things, even if they can be converted into each other easiliy. Nevertheless that is at least a bad style of programming. At least Activision is to blame in this case.

            Originally posted by E
            I know I have to add a spot in the terrutil.cdb, but terrainutil.cpp will be my coding challenging
            Actual the file is called terrimprove.cdb, there is no terrutil.cdb.

            Another thing I wonder about, is why the function does not contain Fromafar's changes.

            Now let's come to the for loop you have added. The counting variable is called r. Why do you use an additional counting variable if the the counting variable i is already there and is not needed to store its value. And I see again Activision did it like that in the code as well. However it wastes a little bit of memory, for bytes to be precise.

            What really wrong with your for loop is, is that it tries to go through the whole good database. But now you access the BuildGoodOn array, not a good idea if the good database has less entries then your BuildGoodOn array.

            So you have to figure out the size of the BuildGoodOn array.

            Another question is how to assure backwards compatibility. What happens if your new flag is not present. Actual I would name it IsRestrictedToGood, your name sounds to me like the good is built on an improvement. This is more clear, as it means that you can only build it on the given good.

            However there is still a problem in the logic.

            Originally posted by E
            BigMC you know where the code is? just checking before I run a HasGood search in XP....
            You would already know it, if you have done it. But of course you can guess where you find it, but of course I don't tell you this.

            But still we have to think about the logic, it should return true; if all the original critera are met, and your new flag is not present in the database record, if it is present, it should only return true if the previous critera are met and the good at the location is the right one. However the function does not do this right now.

            -Martin
            Civ2 military advisor: "No complaints, Sir!"

            Comment


            • #7
              the 6 lines of code you are after are in the fill *"$^&*(^%$£" martin also mentioned the locations of these files in the new slicfunc thread oh and so everybody knows about it you
              .
              Could
              Please
              post it on the forums .

              however martin will not let me tell you were to find it but follow the clues I gave you.
              "Every time I learn something new it pushes some old stuff out of my brain" Homer Jay Simpson
              The BIG MC making ctp2 a much unsafer place.
              Visit the big mc’s website

              Comment


              • #8
                No problem BigMc, I'm good at the search but just wondering if you ran across it recently....

                I'm looking at these codes to steal...


                #1
                Code:
                C3TerrDB.cpp
                return g_theResourceDB->Get(type_good)->GetGold();
                
                if (g_theTerrainDB->Get(tt)->HasGood(tg))
                or this one...

                #2
                Code:
                SlicFunc.cpp
                SFN_ERROR Slic_HasGood::Call(SlicArgList *args)
                {	if(args->m_numArgs != 1)
                		return SFN_ERROR_NUM_ARGS;
                	MapPoint pos;
                	if(!args->GetPos(0, pos))
                		return SFN_ERROR_TYPE_ARGS;
                	sint32 good;
                	if(!g_theWorld->GetGood(pos, good)) {
                		m_result.m_int = -1;
                	} else {
                		m_result.m_int = good;}
                	
                	return SFN_ERROR_OK; }
                and this one...

                #3
                Code:
                 wldgen.cpp
                BOOL hasGood = GetGood(pos, good);
                #4
                Code:
                 cell.cpp
                sint32 Cell::GetGoodsIndex(sint32 &val) const
                {
                    val = (m_env & k_MASK_ENV_GOOD);
                    if (val == 0) {
                        return FALSE;
                	} else {
                		val >>= k_SHIFT_ENV_GOOD;
                		val--;
                		while(val >= 0 && 
                			  (g_theTerrainDB->Get(m_terrain_type)->GetNumResources() <= val)) {
                			val--;
                		}
                		if(val < 0)
                			return FALSE;
                		return TRUE;
                    }
                }

                I'm thinking #1 might be the one I'll have to tweak...
                Last edited by Ekmek; January 21, 2005, 23:58.
                Formerly known as "E" on Apolyton

                See me at Civfanatics.com

                Comment


                • #9
                  Code:
                  bool terrainutil_CanPlayerBuildAt(const TerrainImprovementRecord *rec, sint32 pl, const MapPoint &pos)
                  {
                  	sint32 i;
                  
                  	Assert(rec != NULL);
                  	if(rec == NULL)
                  		return false;
                  
                  	Assert(pl >= 0);
                  	Assert(pl < k_MAX_PLAYERS);
                  	if(pl < 0 || pl >= k_MAX_PLAYERS)
                  		return false;
                  
                  	Assert(g_player[pl]);
                  	if(!g_player[pl])
                  		return false;
                  
                  	Cell *cell = g_theWorld->GetCell(pos);
                  	Assert(cell);
                  	if(!cell)
                  		return false;
                  
                  	if(cell->GetOwner() == -1) {
                  		if(rec->GetIntBorderRadius()) {
                  			if(!g_player[pl]->IsVisible(pos)) {
                  				
                  				return false;
                  			}
                  		} else {
                  			return false;
                  		}
                  	}
                  
                  	if(cell->GetOwner() >= 0 && cell->GetOwner() != pl)
                  	{
                  #if defined(ACTIVISION_ORIGINAL)	// Non-standard syntax		
                  		bool haveAlliance = AgreementMatrix.s_agreements.HasAgreement(pl, cell->GetOwner(), PROPOSAL_TREATY_ALLIANCE);
                  #else
                  		bool const haveAlliance	= 
                  			AgreementMatrix::s_agreements.HasAgreement(pl, cell->GetOwner(), PROPOSAL_TREATY_ALLIANCE);
                  #endif
                  		if(cell->GetOwner() > 0 && haveAlliance) {
                  			if(rec->GetClassRoad() ||
                  				(g_player[pl]->GetGaiaController() && g_player[pl]->GetGaiaController()->GaiaControllerTileImp(rec->GetIndex()))) {
                  	
                  			} else {
                  				return false;}
                  		} else {
                  			return false;}
                  	}
                  	if(g_theWorld->GetCity(pos).IsValid())
                  		return false;
                  	if(rec->GetClassTerraform()) {
                  		sint32 terr;
                  		if(!rec->GetTerraformTerrainIndex(terr))
                  			return false;
                  		if(cell->GetTerrain() == terr)
                  			return false;
                  		const TerrainRecord *tfrom = g_theTerrainDB->Get(cell->GetTerrain());
                  		const TerrainRecord *tto = g_theTerrainDB->Get(terr);
                  		if(tfrom->GetRemoveAdvanceIndex() < 0 || tto->GetAddAdvanceIndex() < 0)
                  			return false;
                  		if(!g_player[pl]->HasAdvance(tfrom->GetRemoveAdvanceIndex()) ||
                  			!g_player[pl]->HasAdvance(tto->GetAddAdvanceIndex())) {
                  			return false; }
                  	} else {
                  		const TerrainImprovementRecord::Effect *eff;
                  		eff = terrainutil_GetTerrainEffect(rec, cell->GetTerrain());
                  		if(!eff)
                  			return false;
                  		if(!g_player[pl]->HasAdvance(eff->GetEnableAdvanceIndex()))
                  			return false;
                  		sint32 a;
                  		for(a = 0; a < eff->GetNumObsoleteAdvance(); a++) {
                  			if(g_player[pl]->HasAdvance(eff->GetObsoleteAdvanceIndex(a))) {
                  				return false; }}
                  		for(i = 0; i < rec->GetNumCantBuildOn(); i++) {
                  			if(rec->GetCantBuildOnIndex(i) == cell->GetTerrain()) {
                  				return false; }}
                  		[b]for(i = 0; i < rec->GetNumIsRestrictedToGood(); i++) {
                  			if(rec->GetIsRestrictedToGoodIndex(i) == cell->GetGood()) {
                  				return true; }}[/b]
                  	}
                                  return true;
                  }
                  I found the code with FROMAFAR's changes and its really big! Iposted it all so you can get the flow. The code I added is in bold of course. I ripped off the Cantbuildon as you can see and used the cell.cpp GetGood function. I think it works similar to HasGood (as seen in the previous post)

                  My logic may have to be double checked though...
                  Formerly known as "E" on Apolyton

                  See me at Civfanatics.com

                  Comment


                  • #10
                    you got the one from slicfunc.cpp then.
                    "Every time I learn something new it pushes some old stuff out of my brain" Homer Jay Simpson
                    The BIG MC making ctp2 a much unsafer place.
                    Visit the big mc’s website

                    Comment


                    • #11
                      Originally posted by The Big Mc
                      you got the one from slicfunc.cpp then.
                      Actual it is not the one you can find in slicfunc.cpp. Actual it even doesn't exist. But I would go for the one in HasGood slic function as well.

                      However this function returns TRUE or FALSE whether there is a good on the given position. To retrieve the good's index you have use the variable that you passed as second argument to the function, in the example called "good". This good variable is passed to the function by reverence instead by value. You see this in the function definition, that includes the ampersand "&" in front of the parameter name.

                      So you have to call the GetGood function first and then check whether the index stored in the good variable is the same as the current GetIsRestrictedToGoodIndex.

                      And of course you only have to access the good's db index once, that means that you call the GetGood function before the for loop once.

                      Now to the logic, the function still returns true whether the tile improvement is restricted to a certain good or not. So you have to put it into a contitioned if block, that is only entered if the size of the RestrictedToGood array is greater than zero. And of course if the for loop is finished without returning true and given it has been entered before, the function should return false, so another return false; belongs into the conditioned if block after the for loop.

                      And another remark about the layout, actual I only talked about open braces, not about closing braces. The closing braces should have the same indetion like the coresponding if or for or while, so that you don't have to search for them, for the open ones that is clear that they are close to the accoring if, for etc.

                      -Martin
                      Civ2 military advisor: "No complaints, Sir!"

                      Comment


                      • #12
                        Code:
                        sint32 good;
                        		if(!g_theWorld->GetGood(pos, good)) {
                        			m_result.m_int = -1;
                        		} else {
                        			m_result.m_int = good;}
                        		for(i = 0; i < rec->GetNumIsRestrictedToGood(); i++) {
                        			if(rec->GetIsRestrictedToGoodIndex(i) == good ) {
                        				return true; }}
                        I've added some of your comments but I still have to look at how to incorporate the logic
                        Formerly known as "E" on Apolyton

                        See me at Civfanatics.com

                        Comment


                        • #13
                          You just need to call the GetGood function, ifs and else ifs, you can use then the good variable.

                          And think again about the logic and correct the layout and post the whole function again. Well at least the lower else block.

                          -Martin
                          Civ2 military advisor: "No complaints, Sir!"

                          Comment


                          • #14
                            dp

                            -Martin
                            Civ2 military advisor: "No complaints, Sir!"

                            Comment


                            • #15
                              Code:
                                                  const TerrainImprovementRecord::Effect *eff;
                              		eff = terrainutil_GetTerrainEffect(rec, cell->GetTerrain());
                              		if(!eff)
                              			return false;
                              		
                              		if(!g_player[pl]->HasAdvance(eff->GetEnableAdvanceIndex()))
                              			return false;
                              		
                              		sint32 a;
                              		for(a = 0; a < eff->GetNumObsoleteAdvance(); a++) {
                              			if(g_player[pl]->HasAdvance(eff->GetObsoleteAdvanceIndex(a))) {
                              				return false;
                              			}
                              		} [b]
                              		sint32 good;
                              		if(cell->GetGood(good)>0 {
                              			(g_theWorld->GetGood(good)&& g_theWorld->GetGood(rec->GetIndex(good))
                              		} else {
                              			return false; }
                              
                              		if (i >0; i < rec->GetNumIsRestrictedToGood(); i++) {
                              			if(rec->GetIsRestrictedToGoodIndex(i) != GetGood(good)) {
                              				return false; 
                              			}
                              		}[/b]
                              		for(i = 0; i < rec->GetNumCantBuildOn(); i++) {
                              			if(rec->GetCantBuildOnIndex(i) == cell->GetTerrain()) {
                              				return false;
                              			}
                              		}
                              	}
                              	return true;
                              }

                              The [b]bold[/b[ stuff is the only thing I changed. My thinking here is:
                              I defined the variable good, then checked to see if the tile has a good. And then get the index for that good. Then I used the variable 'i' to get the index to see if the improvement is restricted to that type of good. If they are NOT equal then it retuns false and then checks the CantBuildOn...


                              Is this right? Do goods have an index number, how do I define names (I remember the txt uses Desert_Good_One or something like that)
                              Last edited by Ekmek; January 25, 2005, 01:25.
                              Formerly known as "E" on Apolyton

                              See me at Civfanatics.com

                              Comment

                              Working...
                              X