Contents Back Forward |
8. Wonders Thread | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8.1 Wonders Thread overview In the last chapter we've seen how Civ Thread works. Here we'll analyze another thread in greater depth, the Wonders Thread. The wonders thread continuously scans the wonder list in memory and continuously executes the WonderCheck function. The CSPL designer protects his civ-related events by just changing the WonderCheck function, leaving untouched the main structure of Wonders Thread. There is a big difference between Wonders Thread and the other Threads we saw in previous chapters, as Wonders Thread doesn't use a ReadNextWonder function. The exact source-code of Wonders Thread is the following: void WonderCycle() { while(true)//Starts a continuous cycle     {     WonderCheck();//Call WonderCheck function continuously     Sleep(1);//Wait a bit (just to avoid freezing ToT)     } } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8.2 Wonders functions In CSPL I've defined several functions to manage wonders:
WORD GetCityWonder(int Wonder) It scans Wonders list for wonder passed as parameter and returns the ID number of city in which wonder is located (it returns 0xFFFF if wonder has not been built yet while it returns 0xEFFF if wonder has been destroyed, I've coded two constants to help CSPL designers: WOND_NOT_BUILT and WOND_DESTROYED which maps these values) bool SetCityWonder(WORD CityID,int Wonder) This function sets Wonder passed as parameter as built in city with ID equals to CityID passed as parameter. bool DestroyWonder(int Wonder) This function is used to destroy a wonder (the wonder passed as parameter) Destroying a wonder means that the wonder cannot be built again by other civs, and it appears as "lost" in the wonder screen. bool DeleteWonder(int Wonder) This function is used to delete a wonder (the wonder passed as parameter). Deleting a wonder means that the wonder is restored to a pre-built state. It can be built by civs with the correct pre-requisites and it doesn't show in the wonder screen. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8.3 Example 7 : MovingWonder (From an idea first presented by CyberChrist.) This example is the first to use different threads, so expect it to be a bit more complicated than the others. One of the annoyances about Wonders is that they're stuck in the cities in which they're built. In some scenarios it could be interesting to move wonders as units between cities of the owner civilization, almost as if they were units. Imagine a Special King unit which acts as a wonder when stationed in cities (maybe as Shakespeare theatre to calm down the citizenry or as King Richard's crusade to boost production in the city) or an Einstein unit which acts as a moving Copernicus observatory. This is exactly what we're trying to do in this example. PHASE 0: CREATING A NEW PROJECTAs we've learned in the previous chapters the first step towards CSPL compilation is the project creation (usually done with CSPLCompanion);Again, begin by creating a new project called MovingWonder. PHASE 1: UNDERSTANDING WHAT WE NEEDThe first thing a CSPL designer should think is : "which thread do I need?"In this situation, since we want to play with wonders AND units, our choice is very easy. We need BOTH the Wonders Thread and the Units Thread. PHASE 2: DESIGNING THE EVENTThe next thing we have to do is to design the "skeleton" of our event:From the first chapter we know that each event is made of HEAD (Trigger Statement) and BODY (Action Statement): In this case HEAD is "The King Unit is in a city" while BODY is "Set wonder as built in that city." PHASE 3: FIXING UP SECONDARY PROBLEMSThe event designed in phase 2 leaves a lot of problems unresolved:First of all, there is only one Wonder so we need to ensure that there will be only one Special King Unit in the whole game. This can be done creating the King Unit as a special unit, which means setting the prereq to "no" and giving a single unit to a particular civ (either give it to one civ from start or deliver it later via events). Another problem is the wonder itself, as we must ensure that no one will ever be able to build that wonder (again, this can be achieved with the "no" prereq). Another question is what should we do while the King is in transit between cities? In my opinion, the wonder should be destroyed and re-established when the King unit enters a new city. Thus if the King is killed while moving, the wonder effect is lost forever. Now that we've cleared up these issues, we can start developing the event. PHASE 4: CODING THE EVENTWe should continuously check the King unit's position and likewise check if there is a city at that position. If the answer is yes, we should place the wonder in that city, while if the answer is no we must destroy the wonder.First of all we need to identify the King unit. If the King unit is present from the start we can extract the ID number and call UnitID to obtain information about this special unit, or else we can use UnitType called with King type as parameter to obtain the same info (notice that obviously there must be only one unit of King type in the game). Let's say we don't need Mech. Inf. unit in our medieval scenario and so we'll use the mech inf type as our King type. It's time to write a bit of code:
Then we have to detect if unit is inside a city or not:
if (StillActive) If IsThereACity is true than a city is present at the King coordinates and its information is stored in the Temp variable. Now we've got to do two things. If there isn't a city we need to destroy the wonder (BTW I chose Shakespeare's theatre for this example), otherwise we need to set this wonder into Temp city. This is done with the following code:
if (IsThereACity)
As we said above the code we've written should be placed in WonderCheck:
PHASE 5: MERGING THE RESULTING SOURCE CODENow it's time to merge all the source code we've written:Editing CSPLClient.h: In CSPLClient.h we need to activate the wonders thread: BYTE ACTIVITY_FLAG=ACTIVATE_WONDER; And we're finished with CSPLClient.h . Editing CSPLClient.csp: The only thing we need to do here is edit the WonderCheck function as described in the previous phase:
PHASE 6: COMPILING AND LINKING THE SOURCE CODEAt this point save the CSPLClient.h and CSPLClient.csp files and use CSPLCompanion to compile and link MovingWonder. This will create a CSPLClient executable in MovingWonder directory.To test this example you should create a game with a couple of cities, and then add a Mech Inf unit (remember our hypothesis of using the Mech Inf type as the King unit). Start CSPLClient.exe and move the Mech. Inf. unit between your cities. Frequently open the Wonder screen, and if all goes well you should see Shakespeare's Theatre moving from city to city with the King (Mech. Inf.) unit. Notice that this example is far from an efficient CSPL program because the same info about city presence on the King tile can be obtained by looking directly to the map structure (using the city bit, read the Map Thread chapter for more details). We would still have to call CityAt to obtain the City information but ONLY if a city is present, thus saving a lot of precious CPU time. |