A trigger-event system is pretty fool-proof (as illustrated hereas illustrated here). Trigger an event, and all objects listening to that event will react. It can get quite cumbersome though, managing event types, especially when you have similar events, but different targets. The alternative I'm proposing is a messaging solution similar to your example, with a few key differences:
Event {
List ids;
Action action;
List args;
}
The ids represent all the entities that should receive the event (eg. player1, goblin3, world, HUD). The action would be an action from a preset list of possibilities (eg. damage_player, heal_goblin, reset_level). The args would be any list of arguments relating to the action (so for a heal action, it might be a number representing the amount).
Next, you have your EventManager:
EventManager {
Queue events;
Dictionary listeners;
addEvent(Event event);
delegateEvents();
addListener(String id, Listener listener);
}
The event manager holds two types of items: events, and listeners. Whenever an event occurs, it gets passed to the event manager (addEvent()). The event gets added to the queue of events. Then, at some point, (such as during the next update loop), you call delegateEvents(), which sends the list of events to the approproate listeners. Let's define a listener before moving on:
Listener {
Queue events;
}
Every game object/entity, that is capable of receiving events, will have a listener attached to it. The EventManager will store a reference to this listener (added via the addListener() function), and will delegate events to these listeners, as illustrated above.
Once the events have been passed on to the listeners, the game objects/entities themselves will go through the events passed through to their listeners. The way in which they interpret the events will be specified for the game object itself. So if a heal (action) event is passed to the player (id), with an argument of 418 (arg), the player will update its own health with 418 additional hp. The player would then send an event to the renderer, and sound engine, that a heal of type foo was initialized at location bar, and they would then initialize the appropriate animation and sound.
Just to illustrate the difference between using triggers vs. messages, again using the healing example:
The first iteration of your game doesn't have a healing animation. You heal, it only updates a stat. Then, you want to polish it up, add some visual flare; with a trigger-event system, you need to register the renderer as a listener to the player heal event. In comparison, with the messaging solution, you need to tell the player to send a heal event to the renderer.
Two ways to achieve the same thing. I'd advocate the messaging solution, but that's mostly just personal preference.