Author Topic: Outpost 2 Coding 101: Week 5  (Read 8697 times)

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Outpost 2 Coding 101: Week 5
« on: February 14, 2010, 08:41:58 PM »
Week 5
Your First Last One Standing - Because "Last One Standing" Sounds Better Than "Last Person Of Non-Specific Race, Gender, Religion, Ethnicity, or Sexual Preference Standing"

Alright, it's time to put all of the knowledge you've learned so far into this first test!  It's time to make your first fully-functional multiplayer game!

I want you to start fresh from the template this time, okay?

Here's what I want you to start with:
-Code to handle morale steady on/off
-Code to handle day/night on/off
-Code to handle disasters on/off (don't actually add the disasters yet)
-Setup initial resources for all players
-Standard LoS victory condition

Now go create some bases.  Before I forget:
Code: [Select]
Player[#].CenterViewOn(X, Y);	// Focus a player's view on a location.

Want some bonus points?  If not, skip down to (END EXTRA EFFORT).

(BEGIN EXTRA EFFORT)[/b][/size]
Randomized Starting Locations:
Scroll up to the top of your file.  You should see a bunch of lines that say #include <etc.h>.  Add a blank line underneath those lines and add this:
Code: [Select]
// Used below to randomize bases
#define numof(array) (sizeof(array)/sizeof(array[0]))
#define autosize(array) numof(array), array

We're not done yet though.  In InitProc:
Code: [Select]
// Randomized Base code.  Thanks for the suggestions, Arklon!
    int i[6] = { 0, 1, 2, 3, 4, 5 };
    RandomizeList(autosize(i) );

    // Create bases - check to make sure owner is active first!
    if (Player[i[0]].IsHuman() )
    {
        SetupBase1(i[0]);
    }

    if (Player[i[1]].IsHuman() )
    {
        SetupBase2(i[1]);
    }

        if (Player[i[2]].IsHuman() )
    {
        SetupBase3(i[2]);
    }

    if (Player[i[3]].IsHuman() )
    {
        SetupBase4(i[3]);
    }

    if (Player[i[4]].IsHuman() )
    {
        SetupBase5(i[4]);
    }

    if (Player[i[5]].IsHuman() )
    {
        SetupBase6(i[5]);
    }

This code assumes you have six players and one base per player.  If you have less, remove if statements as needed, and change int i[6] = { 0, 1, 2, 3, 4, 5 } to int i[number of Players] = { 0, 1, ... (number of players - 1) }.  Since after reading that and confusing myself, here's an example for only 4P:

Code: [Select]
// Randomized Base code, 4P example.
    int i[4] = { 0, 1, 2, 3 };
    RandomizeList(autosize(i) );

    // Create bases - check to make sure owner is active first!
    if (Player[i[0]].IsHuman() )
    {
        SetupBase1(i[0]);
    }

    if (Player[i[1]].IsHuman() )
    {
        SetupBase2(i[1]);
    }

        if (Player[i[2]].IsHuman() )
    {
        SetupBase3(i[2]);
    }

    if (Player[i[3]].IsHuman() )
    {
        SetupBase4(i[3]);
    }

Are we done yet?  Sorry, not quite.  You'll notice these are all functions, right?  That means we'll have to create functions for base creation above InitProc.

Code: [Select]
// Base Creation Functions
void SetupBase1(int i);
{
Player[i].CenterViewOn(X, Y); // Focus a player's view on a location.
Unit x;

TethysGame::CreateUnit(x, mapCommandCenter, LOCATION(X, Y), i, mapNone, 0);
// More units here...
}

Notice that we're now using i for the player number.  That's because we, the programmer, no longer know which player is getting this base.  Rest assured, though, that OP2 does.  Anyways, repeat this for all player bases.  You probably want to give the bases slightly different layouts, but make sure everybody has the same stuff!
(END EXTRA EFFORT)[/b][/size]

Done yet?  Good.  Say, want to make it so the Structure Factories start with structure kits in them?  Of course you do!  So go find where you create each player's Structure Factory.

Code: [Select]
TethysGame::CreateUnit(x, mapStructureFactory, ...);
Now, immediately under that line:
Code: [Select]
x.SetFactoryCargo(0, mapNursery, mapNone);

Doesn't that remind you of something?  Yup, it's just like setting the lights on for units.  We tell OP2 to look at unit x (in this case, a Structure Factory) and add cargo to its cargo bays.  Let's look at it in detail.
Code: [Select]
SetFactoryCargo(Cargo Bay, Unit Type, Cargo Type);
You understand that, right?  Just remember that cargo bay numbers are like player numbers, so Bay 1 = 0 in code, Bay 2 = 1 in code, ...
Anyways, what if we want different kits in the factory based on resource settings?  Easy!  Same thing we did for initial resources:
Code: [Select]
// Structure Factory Cargo Set By Resource Settings
switch (Player[i].Difficulty() )
    {
        case 0:
            Unit1.SetFactoryCargo(0, mapTokamak, mapNone);
            Unit1.SetFactoryCargo(1, mapNursery, mapNone);
            Unit1.SetFactoryCargo(2, mapUniversity, mapNone);
            Unit1.SetFactoryCargo(3, mapVehicleFactory, mapNone);
            Unit1.SetFactoryCargo(4, mapRobotCommandCenter, mapNone);
            Unit1.SetFactoryCargo(5, mapResidence, mapNone);
            break;
        case 1:
            Unit1.SetFactoryCargo(0, mapTokamak, mapNone);
            Unit1.SetFactoryCargo(1, mapNursery, mapNone);
            Unit1.SetFactoryCargo(2, mapUniversity, mapNone);
            break;
        case 2:
            // None.
            break;
    }

Okay, so that's game setup, base design, and victory conditions set up.  Add ore in good locations all around the map.  Include a healthy mix of bar yield and type.  Don't forget to add Fumaroles and Magma Vents (if the terrain allows it)!

So, what's left?  Disasters, right?  Well, go add some!  Don't make them too powerful or frequent; this is an LoS and people tend to complain if an uberquake owns them just before they were about to win.  Also, no Blight!  Volcanoes are not recommended, but if you feel like it, go for it.

Congratulations!  You've got a working Last One Standing!  There's just one thing you still need...

Initial Vehicles
I told you we'd get to 'em, didn't I?  Stick this in each player's base creation:

Code: [Select]
short numSoFar = 0;	// Number of units created so far
while (numSoFar <= TethysGame::InitialUnits() );
{
if (Player[#].IsEden() )
{
  TethysGame::CreateUnit(x, mapLynx, LOCATION( (xPos + numSoFar), yPos), Player#, mapLaser, 0);
   x.DoSetLights(1);
}
else
{
  TethysGame::CreateUnit(x, mapLynx, LOCATION( (xPos + numSoFar), yPos), Player#, mapMicrowave, 0);
   x.DoSetLights(1);
}
numSoFar++;  // Increment the counter by 1
}
numSoFar = 0; // Reset for next attempt

That should work...  Anyways, that may require some tweaking based on how you're creating the bases.
If you're using functions to create the bases, as demonstrated in the random bases code above:
-Delete the numSoFar++ line.

If you're creating all of the bases in the same function (in InitProc):
-Only include the short numSoFar = 0 line the first time you use that code.

A note of caution:  This code will create a line of units up to 12 tiles long.  Make sure you have enough space on the map for that!  Pick your location carefully.

That should do it then!  Your first LoS, in all its glory!  Compile it, test it, and play it on IRC!  Post it here for everyone to see!

Questions, comments, results?  Post 'em!

Special Bonus:  I've attached a (near-perfect) recreation of the original Pie Chart.  Feel free to look it over if you need help.
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline Spikerocks101

  • Hero Member
  • *****
  • Posts: 711
Outpost 2 Coding 101: Week 5
« Reply #1 on: February 14, 2010, 11:24:13 PM »
looks cool. though i haven't tried, it give me ideas.
I AM YOUR PET ROCK!!!!!!

Offline Flashy

  • Sr. Member
  • ****
  • Posts: 391
Outpost 2 Coding 101: Week 5
« Reply #2 on: March 25, 2010, 08:02:10 AM »
How can you create more than 6 randomized bases? I don`t want to use the land rush code of week 8, it confuses me.
Does this work:
Code: [Select]
   // Code for 8 bases
   int i[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
        

//Or int i[5] = { 0, 1, 2, 3, 4, 5, 6, 7 };??



   RandomizeList(autosize(i) );

   if (Player[i[0]].IsHuman() )
   {
       SetupBase1(i[0]);
   }

   if (Player[i[1]].IsHuman() )
   {
       SetupBase2(i[1]);
   }

       if (Player[i[2]].IsHuman() )
   {
       SetupBase3(i[2]);
   }

       if (Player[i[3]].IsHuman() )
   {
       SetupBase4(i[3]);
   }

       if (Player[i[4]].IsHuman() )
   {
       SetupBase5(i[4]);
   }

       if (Player[i[5]].IsHuman() )
   {
       SetupBase6(i[5]);
   }

       if (Player[i[6]].IsHuman() )
   {
       SetupBase7(i[6]);
   }

       if (Player[i[7]].IsHuman() )
   {
       SetupBase8(i[7]);
   }


It should be possible, because I played 6 player maps with 2 players.
« Last Edit: March 25, 2010, 08:11:36 AM by Flashy »
Praise the mighty light towers!!!

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Outpost 2 Coding 101: Week 5
« Reply #3 on: March 25, 2010, 08:12:48 AM »
Why don't you just try it?  That code should work, though you run the risk of accidentally creating a base for Player 7 (neutral units) or, if you're extremely unlucky, Player 8 (doesn't exist) if something goes wrong.
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Outpost 2 Coding 101: Week 5
« Reply #4 on: March 25, 2010, 08:27:10 AM »
Would it not be easier if you just made a for (j=0; j<Tethysgame::NoPlayers(); j++) SetupBase (i[j]), assigning the first sites found in the now randomized array of starting positions? It would be a simple way to avoid creating too many bases.
« Last Edit: March 25, 2010, 08:27:31 AM by Hidiot »
"Nothing from nowhere, I'm no one at all"

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Outpost 2 Coding 101: Week 5
« Reply #5 on: March 25, 2010, 08:38:06 AM »
Umm... Yes.  :blush:  
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Outpost 2 Coding 101: Week 5
« Reply #6 on: March 26, 2010, 01:51:48 AM »
I agree with Hidiots suggestion. Although, the SetupBaseX functions have a
"parameter" appended as part of their name, which would need to be moved to a real parameter for that to work.


Also, if you're initializing an array while declaring it, you can omit the dimension and have it auto determined by the compiler.

Code: [Select]
int i[] = {0,1,2,3,4,5,6};

That would imply a declaration of "int i[7]". This has the advantage that you can edit the length of the array quite easily without also having to adjust the size. It just works. Of course, if you need a certain size, and just want zero filling if the intialization list is shorter than the declared size, then by all means, include both the size and an initializer list.

Note that there is only room allocated for 7 player objects. If you try to initialize any more than that, you may end up overwriting some other important data, quite possibly causing the game to crash. Also, if the 7th player is played by a real person, or perhaps even a computer AI, you may experience some odd bahavior. Things like weapons fire is owned by the last player.

 

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Outpost 2 Coding 101: Week 5
« Reply #7 on: March 26, 2010, 07:21:35 AM »
Things like having Player 7's tubes connected to a Command Center causes it to crash, Hooman.  Nobody's playing as P7 anytime soon.  ;)
« Last Edit: March 26, 2010, 07:21:46 AM by Sirbomber »
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline jcj94

  • Sr. Member
  • ****
  • Posts: 407
    • http://techfusion-279.com
Outpost 2 Coding 101: Week 5
« Reply #8 on: March 18, 2011, 04:58:56 PM »
Instead of setupbase(1) I used

if (Player[i[1]].IsHuman() )
   {  
      TethysGame::CreateUnit(x, mapTokamak, LOCATION( 120+31, 120-1), randList[1], mapNone, 0);
      TethysGame::CreateUnit(x, (map_id)39, LOCATION(115+31, 110-1), randList[1], (map_id)0, 0);
... more units and stuff later

Would that be okay instead so long as I don't use the default function of

if (TethysGame::NoPlayers() > 0

Which is "better" is really my question.



EDIT: I found that when using the ThethysGame, you tend to create other bases that the AI seams to take over, but doesn't use (obviously becasue they have no special headers and whatnot.)

 

Offline Knake

  • Newbie
  • *
  • Posts: 12
Outpost 2 Coding 101: Week 5
« Reply #9 on: December 15, 2011, 05:46:35 PM »
I've made my First LoS!

It's not much but still :)

minimap.rar
Newbie mapper...