Script:Info

From Gothic 2 Online: Wiki
Jump to navigation Jump to search

Gothic Online implements a high level imperative, object-oriented programming language Squirrel. Unfortunately, hardly any editors support Squirrel syntax, so before you start scripting make your editor ready, and read article about squirrel and editors.

Example code written in Squirrel:

local table = { a = 10, b = { a = "Text" }, c = [1, 2, 3], [100] = "expression index" };
local array = [ 1, 2, 3, { a = 10, b = 20 } ];

foreach (key, value in array)
{
	::print (key + ": " + value);
}

/////////////////////////////////////////////
/// Classes
/////////////////////////////////////////////

class Vector
{
	x = 0;
	y = 0;
	z = 0;
}
 
class Entity
{	
	constructor(entityname, pos)
	{
		name = entityname;
		position = pos;
	}
									
	position = null;
	name = null;
}
 
function Entity::MoveTo(pos)
{
	position = pos;
}
 
class Player extends Entity
{
	constructor(entityname, pos)
	{
		base.constructor(entityname, pos);
	}

	function DoSomething()
	{
		::print("I'm doing something");
	}
	
}
 
local position = Vector();
position.x = 0; position.y = 0; position.z = 0;

local player = Player("The Player", position);
player.MoveTo(100,200,300);

Config

Config file using xml format and combines everything into one working server. You can split your config file into pieces using import tag. This will make it more clear. For more information about available tags look here

Example

Here is an example of simple config file, that loads another config file.


Main config file:

<server>
	<config public=true host_name="Gothic 2 Online" max_slots=32 port=28970 rcon_pass="SomePassword" />
	<master host="185.5.97.181" port=7777 />
	<version build=0 />
	<world name="NEWWORLD\\NEWWORLD.ZEN" />
	<description>
	<![CDATA[
    		<b>
        		<font color=blue>Gothic</font> 2 <font color=red>Online</font>
    		</b>
	]]>
	</description>

	<import src="mygamemode/scripts.xml" />
</server>

Imported config file (scripts.xml):

<server>
	<script src="server-scripts/main.nut" type="server" />
</server>

Special config tags

We provide some special tags that import items and mds definitions. If you are new in Gothic world you probably don't know what term mds mean, but let's just say that is something with animations overlays. Why items and mds are loaded from xml file? Because we generating ids for them, and we can better control player, so this help us to protect server from cheaters. That's why every item and new mds have to be listed in the xml file.

NOTE! Generated ids aren't unique.

Example

Here is an example of config file that loads items and mds.

<server>
	<items src="items.xml" />
	<mds src="mds.xml" />
</server>

In scripts you can get item or mds id like this.

print("ITFO_BEER id: " + Items.id("ITFO_BEER"));
print("HUMANS_SPRINT.MDS id: " + Mds.id("HUMANS_SPRINT.MDS"));

Architecture

Script architecture is divided into two sides client and server.

  • Client side - scripts which are downloaded directly into client PC and loaded while game is stared. Future advice, this isn't place for important logic. Client side scripts are dedicated for GUI systems etc.
  • Server side - scripts loaded directly onto the server. Server side contains all the information about players, so gamemode logic should be placed here.

Most of the server logic will be server side, but if there is something that can't be solved on the server side you probably need to make it client side.
Client script has some global constants that, are changes whatever you join to the server. Here is the list:

heroId Contains current local player id.

Events

Events are mechanism that tells scripts, that something happened. For example if player join to the server is called event onPlayerJoin on the server side and onInit on the client side. To use events you have to add handler in scripts.

local function joinHandler(playerid)
{
	sendMessageToAll(playerid, 0, 255, 0, getPlayerName(playerid) + " joined to the server");
}

addEventHandler("onPlayerJoin", joinHandler);

You can even register your own event. Using custom events are recommended especially for libraries or frameworks. Thanks to it, we have one events mechanism for everything.

// Register custom event
addEvent("onPlayerLogin"); 

local function commandHandler(playerid, cmd, params)
{
	if (cmd == "login")
	{
		local args = sscanf(params, "s");
		if (args)
		{
			if (args[0] == "secretpassword")
				callEvent("onPlayerLogin", playerid);
		}
		else
			sendPlayerMessage(playerid, 255, 0, 0, "Wrong syntax. Type /login password");
	}
}

addEventHandler("onPlayerCommand", joinHandler);

local function loginHandler(playerid)
{
	sendPlayerMessage(playerid, 255, 255, 0, getPlayerName(playerid) + " has logged in");
}

addEventHandler("onPlayerLogin", loginHandler);

Debugging

As we said in previous chapter, architecture is divided into client and server, the same goes for debugging mechanizm.

Client side

Client has build in console, which is available under tilde (~). Default view of the console is info. In info view you will see messages from the print function and multiplayer. To change to debug view, use command view error, and then you can go back using view info. View are scrollable, with arrows (up/down).

Server side

Every error message from scripts, will be displayed in console output.