Author Topic: Code To Create A New Player Slot For The Ai (mp)?  (Read 1321 times)

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1223
Code To Create A New Player Slot For The Ai (mp)?
« on: February 23, 2006, 03:50:16 PM »
(Originally sent as a PM to Hacker, he requested that I post it in the programming forum for all to see)
In La Corrida and Peacekeeper, the AI was never gaia and never ended up with the same color as a player, because it fills in the next available player slot. How does it do this?

(Meep, the forum automatically changed the capitalization and stuff of my topic title to appear more slightly more n00bish D:)
« Last Edit: February 23, 2006, 04:09:52 PM by Arklon »

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1194
    • http://www.eddy-b.com
Code To Create A New Player Slot For The Ai (mp)?
« Reply #1 on: February 23, 2006, 04:17:55 PM »
How does it do this ?!
It just asks TethysGame how many players there are, and just creates a new player (AI) in (humanPlayers+1), that ain't so hard.
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1223
Code To Create A New Player Slot For The Ai (mp)?
« Reply #2 on: February 23, 2006, 04:27:26 PM »
Quote
How does it do this ?!
It just asks TethysGame how many players there are, and just creates a new player (AI) in (humanPlayers+1), that ain't so hard.
But how do you make a new player without it being gaia (due to max players thing)?

Offline Mcshay

  • Administrator
  • Sr. Member
  • *****
  • Posts: 404
Code To Create A New Player Slot For The Ai (mp)?
« Reply #3 on: February 23, 2006, 04:37:42 PM »
When I tried that Eddy, the AI was a white player with broken buildings and vehicles. Nothing worked.

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3101
Code To Create A New Player Slot For The Ai (mp)?
« Reply #4 on: February 23, 2006, 06:28:56 PM »
Well, I reverse engineered the code in La Corrida, and came up with this:

Code: [Select]
// Determine the number of humans in the game
for (int numHumans = 2; numHumans < 7; numHumans++)
{
    if (!Player[numHumans].IsHuman())
        break;
}

// Set up the AI base in the next available slot
// (The last human player would be numHumans-1, so the first empty slot is numHumans)
Player[numHumans].SetOre(10000);
Player[numHumans].GoEden();
Player[numHumans].SetTechLevel(6);
// and so on... La Corrida does not use Player.GoAI() at all.

The number of players inside the DescBlock is still 4 (4 max humans).
The only other thing that La Corrida has, that other missions do not (except Peacekeeper), is an export called "DescBlockEx". It can be defined as:
Code: [Select]
struct SDescBlockEx {
    int unk0;
    int unk1;
    int unk2;
    int unk3;
    int unk4;
    int unk5;
    int unk6;
    int unk7;
};

SCRIPT_API SDescBlockEx DescBlockEx = { 1, 0, 0, 0, 0, 0, 0, 0 };
in Main.cpp.

It seems to exist in Peacekeeper's DLL too, It seems that the first field controls the number of extra player slots. OP2 makes one obscure reference to a "DescBlockEx" string in the EXE but I haven't really traced the code at that point much yet.

You could try putting it into your DLL if you wanted to. Not sure if it would make a difference or not.

Edit -- looked into it. Only La Co and Peacekeeper have the DescBlockEx (well, the pre release demo missions may as well, but those aren't as important)

Edit again -- adding the DescBlockEx to a test mission causes the AI player to show up on the map as normal. I believe it is counted by TethysGame::NoPlayers, as it placed Plymouth buildings, and then placed Eden buildings on top of it (It must have been created by the for loop, because I put extra CreateBase instructions outside of the for loop after calling Player.GoEden and it placed Eden buildings as well).
« Last Edit: February 23, 2006, 06:57:52 PM by op2hacker »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4751
Re: Code To Create A New Player Slot For The Ai (mp)?
« Reply #5 on: March 15, 2019, 02:04:34 AM »
Slight update for anyone finding this. The newer version of the SDK uses "Export" rathre than "SCRIPT_API".

I took another look at the code that processes the "DescBlockEx" export today.


Details:

The DescBlockEx related code does not exist in the CD version of Outpost 2 (1.2.0.5). Outpost2.exe does not reference it. No levels from the CD install contain a "DescBlockEx" export. It was added in the official Sierra release update pack 1 (1.2.0.7). In the update, the executable file, and two levels (ml2_21.dll and ml4_21.dll) use "DescBlockEx".

From the most recent executable, the DescBlockEx export is referenced in exactly 1 place, in the method:
Code: [Select]
00402780  Function: GetNumAiPlayers([ECX] char* scriptName):int* numAiPlayers

In this method, the code retrieves a pointer to the "DescBlockEx" export, then allocates 4 bytes of memory, and copies the first 4 bytes from DescBlockEx export into the allocated buffer, and returns a pointer to this buffer. As this is the only reference to "DescBlockEx" in the executable file, it seems only the first 4 bytes are ever used.

Looking at the two DLL files, the struct is a maximum of 32 bytes. In both DLLs there is another unrelated global variable 32 bytes beyond the DescBlockEx export. In both DLLs, there is a lack of references to the addresses between the start of the DescBlock export, and the next referenced variable 32 bytes later. This suggests there are no other global variables in that region, and strongly implies all 32 bytes belong to the same DescBlockEx variable, or are padding/alignment bytes after/between variables. As neither the DescBlockEx export, nor the following global variable are 32-byte aligned, and the following variable has no need of anything more than 4-byte alignment, it is unlikely all this empty data is purely for padding/alignment. The size is likely 29-32 bytes, most likely being the full 32 bytes. A size of 32 bytes can hold 8 ints.

In both DLLs, the first 4 bytes contain the value 1 (numAiPlayers), and the remainder are filled with 0. The DescBlockEx export appeared immediately after the DescBlock export (though that is not a requirement, just an obvious place to put it).



Summary:
You could get away with only exporting 4 bytes (a bit messy):
Code: [Select]
Export int DescBlockEx = 1; // numAiPlayers

Though I would recommend exporting the full struct (the struct name is arbitrary):
Code: [Select]
struct WhateverStructNameYouWant {
    int numAiPlayers;
    int unused1;
    int unused2;
    int unused3;
    int unused4;
    int unused5;
    int unused6;
    int unused7;
};

Export WhateverStructNameYouWant DescBlockEx = { 1, 0, 0, 0, 0, 0, 0, 0 };

A more compact looking, yet full sized struct and initialization is:
Code: [Select]
struct SDescBlockEx {
    int numAiPlayers;
    int unused[7];
};

Export SDescBlockEx DescBlockEx = { 1 };

In the last example, the unused fields are collapsed into a single array in the struct, and the export definition uses automatic 0 filling of fields that are not explicitly set. It's also updated to use the "Export" macro, rather than "SCRIPT_API".

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 856
Re: Code To Create A New Player Slot For The Ai (mp)?
« Reply #6 on: March 16, 2019, 06:20:41 PM »
Thanks for posting this. I was feeling fairly dumb not understanding what was going on to get multiplayer AI working. I'll try to update my 2 multiplayer scenarios so there are examples of the new format floating around.

Would it make sense to define SDescBlockEx in Outpost2DLL? That way we don't have to keep on defining it in each scenario that wants multiplayer AI.

Thanks,
Brett

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4751
Re: Code To Create A New Player Slot For The Ai (mp)?
« Reply #7 on: March 17, 2019, 11:35:01 AM »
Yes, we should look at moving that struct into Outpost2DLL. We might want to consider renaming it from SDescBlockEx though. The original DescBlock export is actually an AIModDesc struct. Maybe the new struct should be named AIModDescEx? We can discuss on GitHub.
« Last Edit: March 18, 2019, 07:58:47 AM by Hooman »

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 2171
    • LairWorks Entertainment
Re: Code To Create A New Player Slot For The Ai (mp)?
« Reply #8 on: March 17, 2019, 06:56:08 PM »
Seeing as there's relevant discussion in this thread, I'm unlocking it for now for non-admin/non-mod users to be able to post in this topic.