Cog provides several ways to do this, but no matter what method you use, using several cogs to do something makes debugging and just understanding your code much harder. If any of you have tried to make sense of Raynar's Rbots code, then you know how much more complicated your code can become when you have to break up one cog into several smaller ones. Always be sure to write in plenty of commenting beside verbs like SendMessage() and SendTrigger().
SendTrigger(dest, ID, param0, param1, param2, param3);
For what we're going over, the destination is the most important argument. This tells the verb who the trigger is going to be sent to. The integer is either going to be -1 for everybody, or the thing number of the player who's computer we want to talk to. We'll go more into this in the multiplayer tutorial.
If a trigger is sent out with a dest of -1, then every cog on all computers in the game will be able to receive that message. Triggers wouldn't be that useful if you couldn't tell them apart - that's what the second argument is for. This is the trigger's ID, which will be the sourceref of the trigger message.
The fact that all cogs that use triggers have to listen to every trigger makes them somewhat wasteful. In most cases, you'll have one cog that needs to tell something to another cog. If you use a trigger and a unique ID, every cog on the receiving computer will have to look at that message and compare it's ID to the IDs that it's looking for.
Also, because triggers have only a player as a destination and not a cog, it can be difficult for anyone reading your code (and for you later on) to tell which cog is listening for that trigger without any comments.
For example, let's say we're writing a new scoring system and we need to write something that will make the server-side cog send a trigger to the client-side cogs to tell them what the new score is. The server code might look like:
broadcast_score: // tell all clients that the new score is curScore. // receiving cog will be client_score.cog. SendTrigger(-1, 33, curScore, oldScore, 0, 0); return;And in the client's cog we would have:
trigger: if(GetSourceRef() == 33) { // received trigger from server_score.cog. // first param will be the new score, and the // second will be the old score. curScore = GetParam(0); } return;In cases like this, there are an unknown number of recipients, verbs like SendMessage() are designed to send a message to a specific cog - and they can't do messages to other computers. So for this example, SendTrigger() is the only choice even though only one cog needed to receive the trigger.
SendMessage(cog, message); retval=SendMessageEx(cog, message, param0, param1, param2, param3);SendMessage() is the simple version, it just needs the destination cog, and the message to send. SendMessageEx() is the extended version which allows you to send four parameters.
Since an ID is not used when sending messages, you have a range of user messages (user0-user7) to use. There's also a global0 message which you can use if you need to. You aren't restricted to using only these messages, you can use any of JK's predefined messages.
The downside of these message verbs is that it's hard to get a reference to a cog - it's not the cog file, it's the number of the cog in the JKL's cog section. A common way to add custom cogs to a patch is through the items.dat. This avoids using the static.jkl, and it allows you to use GetInvCog() to return a reference to that cog. So if you load all of your cogs through the inventory, then you won't have a problem sending messages between them.
For an example, let's say that you have two custom cogs. The first one needs to synchronize three variables with the second. If we used a trigger in this case, then every local cog would hear the trigger, and we don't need to do that. So the first cog might have code like:
comm_sync: SendMessageEx(GetInvCog(GetLocalPlayerThing(), 117), user0, syncVar1, syncVar2, syncVar3, 0); return;We're assuming that the first cog is loaded with bin 116, and the second is loaded with 117. The second cog would have this code:
user0: syncVar1 = GetParam(0); syncVar2 = GetParam(1); syncVar3 = GetParam(2); return;
As you saw in the syntax of SendMessageEx() you can send a value back to the calling thread with ReturnEx(). The return type is flexable just like the other message parameters. ReturnEx() is used the same as in damaged and autoselect.