views:

80

answers:

2

I have written a client<>server based multiplayer game and have finished the basics (it's a flash client written in actionscript 3). The next step will be implementing a system which will allow me to easily add abilities to the game.

The problem here is that an ability can do so many things. Eg. player A uses ability "repair" on player B, the following will have to happen:

  • Player A sends message to server informing about the action
  • Player A is now showing a "repair casted" animation on its own ship
  • The server has to inform all players near that ship A now has the "repair casted" animation
  • The server has to increase the "health" of player B because it has been repaired by player A
  • The server has to inform all nearby players that player B now has a different health value
  • The server has to inform all nearby players that player B should show the "being repaired" animation

That's just an example, a lot of things have to happen for 1 simple ability. I could go into every object and add lines of code just for this spell. However, that would become a mess when I need to add a lot (~50) abilities. Also notice that some abilities do whole other things than others, some will have to show animations, some won't. Some will have to damage, some will have to increase statistics, etc.

So, how is such "ability system" usually handled both client and server side?

+4  A: 

On client side never do a thing without the consent of the server. So client should only send the request of an ability and an optional target or some value. Also client should have to listen server for any commands. On the other hand, server should implement a function or classes (whatever you feel comfortable) to control ability actions. Whenever a client requests an ability to cast ability function should be called. As first task, function should check prerequisites. If they fail, client should be notified. Otherwise, a use repair ability ok signal should be passed to client. Then the function finds and send required commands to any nearby ships while updating their statuses. This method will guarantee that abilities cannot be abused by clients.

To understand it check the following, this is for illustration of the method, so dont tell me its not good to use so many ifs.

Client

function massRepair() {
    server.send("USE mass_repair;"); //no decisions in here
}

function recive(command, target) {
    if(command=="USE mass_repair OK")
        massRepairAnim.gotoAndPlay(0);

    if(command=="ANIM mass_repair") {
        massRepairAnim.setTarget(target);
        massRepairAnim.gotoAndPlay(0);
    }

    if(command==/SET ENERGY [0-9]/) {
         value=getValue(command);
         setEnergy(value);
    }

    if(command==/SET HEALTH [0-9]/) {
         value=getValue(command);
         setHealth(value);
    }

    if(command=="ANIM self_repair") {
        selfRepairAnim.gotoAndPlay(0);
    }

    if(command=="USE mass_repair FAIL NOENERGY") {
        display("Not enough energy to use the skill");
    }
}

somebutton.click=function() { massRepair(); }

Server

function userMassRepair(Ship owner) {
    if(owner.energy<30) {
        send(owner, "USE mass_repair FAIL NOENERGY");
        return false;
    }

    owner.energy-=30;
    send(owner, "SET ENERGY "+owner.energy); //every data sent is absolute
    send(owner, "USE mass_repair OK");

   foreach(ship in owner.shipsInRange(100)) {
        if(owner.ally(ship)) {
             ship.health+=10;
             ship.send("SET HEALTH " + ship.health);
             ship.send("ANIM mass_repair "+owner.position);
             ship.send("ANIM self_repair");
        }
   }
}
Cem Kalyoncu
+2  A: 

It looks like a lot of things, but it's really just a permutation of several standard components. Most actions will consist of changes to intrinsic properties and some cosmetics to be shown on the client, and there are only a handful of different ways to do those.

You need something like the following:

  • a standard way of sending actions to the server, which allows for convenient extraction of arbitrary parameters (as each action may have some very specific arguments)
  • a message type from server to clients to start playing a specified animation on a specified ship
  • a message type from server to clients increasing the health value on a ship

Then your server code for the action you mention looks like this pseudocode:

if (message.type == REPAIR)
{
    repairer = message.actor;
    repaired = message.target;

    // Insert verification code here to check that the 2 ships are close enough,
    // that the repairer is entitled to perform this action, etc

    // Verification has passed: do the work
    broadcastToAllClients(new Message(type=PLAY_ANIM, target=repairer, value=REPAIR_CASTED));
    broadcastToAllClients(new Message(type=CHANGE_PROPERTY, target=repaired, proerty=HEALTH, value=5)); // 5 is the amount 
    broadcastToAllClients(new Message(type=PLAY_ANIM, target=repaired, value=BEING_REPAIRED));
}

That is very easy to extend to any number of actions, and will just require a few extra message types to accommodate the different things that can change or can be displayed.

Kylotan