Game Development Community

dev|Pro Game Development Curriculum

Warscale 25 - Single Player and Disconnection

by Guimo · 10/28/2008 (3:28 pm) · 4 comments

Hi everybody still reading this series!

This was a busy week (as usual) with lots of challenges. Originally I had planned to devote the week to the end game procedure, but, as I told you the last week, trying to run two clients at the same time in the small Dell Latitude is painfully slow so I was forced to code a single player mode also.

What was planned
a. Enhanced game state management
The when a game is created, its status is sent to the client but in time the game status may change as new players join the game or when the game starts. Some game may become unavailable and shouldnt be joined to. Now, any game status change in the server is sent to the clients so they can see which games are available to join.

b. Enhanced disconnection handling
The disconnection process has been debugged and its working fine. The game is able to detect disconnections in many situations like while in the game room, during loading, during the game or at the end of the game, and act appropiately. The game can detect if the player has abandoned the game willingly or he has just disconnected. Rewards are computed and pleuers abandoning a battle when started will be penalized.

c. Improved end game handling
A small screen has been created to show the game results. The window will dissapear after some seconds and will return to the game room. A bug using the GuiObjectView in the GameRoom has been fixed.

I like the new game stability. Its harder to crash the game and can handle way more situations.

What wasnt planned
a. Single player mode
I was forced to implement a single player mode. If you remember, the single-player architecture was already in place while I was coding the game prototype but it had to be adapted to the client/server mode so that the server may control the game. I know a single player game which requires to connect to Internet sounds strange but its required because in this case you may get rewards if you succeed in the game so the server must control the game result.

I decided to go for the "Kill the boss" game type (soon to be named Slayer). In this mode the server will pick a suitable opponent for you, i.e. it may pick a Dragon or a Basilisk and you will be sent against that creature. If you defeat it you will win some gold, if you lose you will also get gold but just a minimal ammount. I'm still not sure if I should allow the player to request a different opponent at will as the player may want to pick say... a Dragon Slayer sword in his equipment and request opponents until the server returns a Dragon. Or maybe I can just make the monster inmune to slaying effects for this type of games.

I only have the AI basics right now but I hope its easier to code the AI for a single monster. The point is that the game required some changes for this mode to work but now everything is on the right track.

b. Torque Script problems
Its not the first time I find this problem. Looks like Torque has a problem with the namespaces and sometimes it gets confused. The result was that my ScriptObjects were unable to call some basic functions from SimObject like schedule or dump. I lost a lot of time trying to solve this. I managed to get a simple but effective solution but its working now.
For those curious, the problem was this. Say I define a function as:
function WSAIPlayer::create(%name, %modelid) {
   %ai = new ScriptObject(WSAIPlayer);
   %ai.name = %name;
   %ai.avatarid = %modelid;         //This model will represent this player
   %ai.isAIPlayer = true;           //Marks this player as an AI player
   return %ai;
}
function WSAIPlayer::MyMethod(%this) {
  echo("MyMethod");
}

Then I called:
%ai = WAIPlayer::create("Guimo", 1001);

The object was created fine and I can invoke %ai.MyMethod() and will get the appropiate answer. But if I tried a Torque native method, something like %ai.dump() or %ai.schedule(128, "MyMethod") or even %ai.delete() the console answered with something like:
WSAIPlayer -> ScriptObject -> SimObject - Unknown command schedule.

So it recognized the hierarchy but couldnt find the function. The funny thing is that if you try this in a small project you get no errors and will run fine, but I have a lot of classes and namespaces. That may be affecting Torque.

Fortunately, this problem has a simple solution. Instead of calling the create function as:
function WSAIPlayer::create(%name, %modelid)...

Name it as:
function WSAIPlayer_create(%name, %modelid)...

Obviously you will need to change your calls to the function, but now everything works fine.

Screenshots
Lots of internal work so there is no much to show you.
The first screen is the GameRoom but now a Grey Bear is being used as an opponent.
www.spritekin.com/warscale/wsascreen25a.jpg
The second screen is the end screen which appears when the battle ends. Its a simple screen for now. It was supposed to say - You received 0 gold. - (0 is the standar reward for now) but for a bug which has already been fixed.
www.spritekin.com/warscale/wsascreen25b.jpg
The plan for this week
Update the Options dialog adding some buttons and features. This is a feared item. I need to convert all the Torque options editor to something more on the Warscale style.
Add more keyboard handlers. That is, make the keyboard respond to logical situations like if you have a dialog with Ok ad Cancel buttons, you may expect Enter to handle the Ok on click event and the ESC key to handle the cancel button.


Following in the list:
Start with the Map Editor, required to create new maps and blockmaps.
Crate at least 3 maps, probably using resources from an environment pack or two.
Add the map selection features to the Game Lobby.
Adjust the battle so it can handle the new map formats.
Update the battle UI. Add more messages.
Improve the chat. Start reading about Green Ear integration.
Add sounds and background music.
Improve and clean up current game features.
Code Monster AI.
Add Permanent Area sorceries, like storms, walls of fire and similar tricks.

As only 11 weeks remain for my January 15 target for the alpha version. As you see the time is limited.


Snippet
This week (and I hope the following weeks also), I will leave you with a small snippet which may be useful to you (or not). For me its been extremely helpful. You can put this function inside the engine code and recompile:
//Replace spaces with 0x1
char* encodeString(char* s) {
	char* res = s;
	while(*res) {
		if(*res == ' ')
			*res = 1;			//white to 1
		res++;
	}
	return s;
}

ConsoleFunction(encodeString, const char*, 2, 2, "encodeString(text)")
{
   argc;
   return encodeString((char*)argv[1]);
}

//Replace 0x1 with spaces
char* decodeString(char* s) {
	char* res = s;
	while(*res) {
		if(*res == 1)
			*res = ' ';			//1 to white
		res++;
	}
	return s;
}

ConsoleFunction(decodeString, const char*, 2, 2, "decodeString(text)")
{
   argc;
   return decodeString((char*)argv[1]);
}

What it does. encodeString replaces white spaces in a string with the character 0x1 so the new string is considered a single string with no spaces. decodeString recovers it back.
This is useful to handle long names or long text, avoiding some problems while parsing information in a string. You may use it in different situations. For me its really useful as it lets me handle player and creature names or passwords as a single word.
Example:
%name = "Black Bear";
echo(getWordCount(%name) SPC "words"); //unencoded, prints 2 words
%name = encodeString(%name);
echo(getWordCount(%name) SPC "words"); //encoded, prints 1 word
%name = decodeString(%name);
echo(getWordCount(%name) SPC "words"); //unencoded, prints 2 words


Thats all for now, good luck with our own projects!
Guimo

#1
10/29/2008 (10:15 am)
Great stuff, keep them coming.
#2
10/29/2008 (12:06 pm)
There is something with Guimo more relevant than his actual work: determination; is dificult to find!
#3
10/29/2008 (9:25 pm)
@Novack
Your words are flattering coming from the guy which managed to update all the RTS Kit code! Thats determination!
#4
10/30/2008 (12:36 pm)
Heh :) Thank you Guimo, although I must say that I were more like a catalizer than the man doing all the work.

Keep up that spirit!