Script Player

Introduction

From CR 4.9.7.8 it is possible to create non-humans players by script. These players have all the properties of normal players. They have a crew, wealth, build knowledge, home base material, hostility, teams, etc. However, script players do not have a game view port and they can not be controlled by human users.
Script players can be used to create AI controlled opponent teams in special scenarios.

Runtime join

For creating an AI player at run time - e.g. a new deathmatch opponent - you can use CreateScriptPlayer. This call will be followed (possibly with a little delay) by a InitializePlayer callback for the new player.
Example:
/* Script einer aktivierten Spielregel namens "KI Erzeugen" */

#strict

public func Activate(int iPlr)
  {
  // Der Spieler iPlr hat die Spielregel ausgewählt. Erzeuge einen KI-Gegner!
  return(CreateScriptPlayer("Computer", 0x7f7f7f));
  }
  
protected func InitializePlayer(int iPlr)
  {
  // Ein Spieler ist beigetreten. Dieser Aufruf erfolgt an das Szenarienscript, sowie an alle Spielregeln,
  // Spielziele und Umweltobjekte
  // Ist es ein Scriptspieler?
  if (GetPlayerType(iPlr) == C4PT_Script)
    {
    // Dann übernimm die Steuerung für alle Clonks!
    var iCrew, pCrew;
    while (pCrew = GetCrew(iPlr, iCrew++))
      AddEffect("Int_EAI", pCrew, 1, 100, this());
    }
  }
  
protected func FxInt_EAITimer(object pCrew, int iEffNum, int iEffTime)
  {
  // Nächsten Gegner angreifen
  var pEnemy = FindObject2(Find_Hostile(GetOwner(pCrew)), Find_OCF(OCF_Alive), Sort_Distance());
  if (pEnemy) SetCommand(pCrew, "Attack", pEnemy);
  return FX_OK;
  }
This script for a sample rule object allows the user to create AI opponents at runtime. Also, it will order all clonks of the AI players to attack. Notice: this sample script only handles those clonks automatically created through the scenario settings. Additional clonks placed by specialized scripting are not handled.
For internet games you can set MaxScriptPlayers in Teams.txt to a value greater than 0. This will enable the option to have script players join in the game lobby.

Default join

If scripted players should be present in the scenario right from the beginning (comparable to objects created via Objects.txt) then you should create them via the SavePlayerInfos.txt component:
[PlayerInfoList]
LastPlayerID=1

  [Client]
  ID=0
  Flags=Initial

    [Player]
    Name="Aliens"
    Flags=Joined
    ID=1
    Type=Script
    Team=2
    Color=65535
    GameNumber=1
    GameJoinFrame=0
This method effectively performs a player restore, similar to a regular player restore in a savegame resume. Consequently, no InitializePlayer is called for this player and no startup material or crew is created. A crew for this player should be created in the scenario script. Alternatively, a crew may be present in the Objects.txt. Otherwise, the script player will be eliminated shortly after game start.
Contrary to regular players, script players are saved if you perform "Save as scenario" in developer mode. This way, you can automatically generate the correct SavePlayerInfos.txt and an according crew in the Objects.txt of the scenario. In order to do this, simply execute CreateScriptPlayer from the console and create some Clonks for the newly created script player. Then save the game as scenario. The script player Clonks will automatically be restored with the correct owner and in the crew of the script player.

Specialized Players

Sometimes it can be desirable to create a script player at runtime, but still execute a specialized initialization instead of the default crew and base material creation. For example, a Hazard deathmatch scenario may provide a specialized alien enemy.
By passing a parameter to CreateScriptPlayer, scenario initialization can be prevented, i.e. no creation of start materials, no setting of player parameters such as homebase material by the according presets and no InitializePlayer-calls are done. Instead, a single CreateScriptPlayer-callback is done to the definition passed as idExtraData. Example:
/* Script einer aktivierten Spielregel namens "Aliens erzeugen" */

#strict

public func Activate(int iPlr)
  {
  // Der Spieler iPlr hat die Spielregel ausgewählt. Erzeuge einen Alien-Gegner!
  return(CreateScriptPlayer("Aliens", 0x00ff00, 0, CSPF_FixedAttributes | CSPF_NoScenarioInit, GetID()));
  }
  
protected func InitializeScriptPlayer(int iPlr, int idTeam)
  {
  // Ein Alienspieler ist beigetreten
  // Da keine Szenarieninitialisierung durchgeführt wurde, muss in diesem Callback eine Crew für den Spieler erstellt werden
  // Erstelle einen grünen Clonk - ein richtiges Szenario sollte natürlich echte Aliens mitbringen :)
  var pAlien = CreateObject(CLNK, LandscapeWidth()/2, -1, iPlr);
  MakeCrewMember(pAlien, iPlr);
  SetClrModulation(0x7fff7f, pAlien);
  // Und angreifen lassen
  AddEffect("Int_EAI", pAlien, 1, 100, 0, GetID());
  }
  
protected func FxInt_EAITimer(object pCrew, int iEffNum, int iEffTime)
  {
  // Nächsten Gegner angreifen
  var pEnemy = FindObject2(Find_Hostile(GetOwner(pCrew)), Find_OCF(OCF_Alive), Sort_Distance());
  if (pEnemy) SetCommand(pCrew, "Attack", pEnemy);
  return FX_OK;
  }
Sven2, Dezember 2007