Well, I was right about the entity system being a rabbit hole. I've spent more of my free programming time in the past two weeks reading and re-reading whitepapers and design documents than I have thinking about the goals of the game. On the plus side, though, I've got a much better understanding of what I want to happen in the underlying framework of the game, and I think I've got a basic system that will be usable in a couple of other projects that I want to explore after this one.
We're sticking with a couple of the original design concepts for the Infinity System. It is still entity based, with the core "thing" in the game being nothing more than an ID reference into an entity repository. This ID will have components attached to it, which are defined as nothing more than containers of variables with no actual logic. Game logic still lives mainly in black-box objects referred to as "game systems". Each game system handles a specific task, such as AI pathfinding, or movement, or combat.
At that point, though, the similarities end. To drive game logic, each system registers a set of events that it responds to. An event is basically an entity template that defines one or more components that contain the data for that particular type of event. Once the source of the event creates and populates the event entity, that event is passed through the event handlers on the entities involved in the event. Those handlers are allowed to modify data on the event's components, fire new events of their own, or respond that they have handled the event. Once the handlers are done, if the event is still unresolved, then the system that registered as the generic handler for that event is notified and resolves the event. This allows entity specifications to modify the way game systems apply their logic to a given entity.
For example, suppose a medium freighter is firing its laser turret on an attacking pirate fighter. A LaserAttack event is raised, with the freighter as the actor, and the pirate ship as the target. The event's component also specifies that the source of the attack is the laser turret entity installed on the freighter. The combat system is given the event, and then checks for a defined handler on each entity in a specified order. The freighter first, then the turret, then the pirate. The freighter might adjust the to-hit chance based on the fact that it's not built for combat, the turret simply ignores the event, and the pirate might adjust the to-hit chance again due to the maneuverability of the target ship. Since none of those handlers responded that they handled the event, the combat system is now free to finish resolving the attack by making a check on the attack's to-hit value. If it succeeds, it would then fire a WeaponHit event with the turret as the actor and the pirate as the target. The turret sets the damage value of the hit, and the pirate sets its shield value. The combat system is then free to either directly apply damage to the pirate (potentially firing a ShipDestroyed event), or to break the resolution of damage down further by firing one or more Damage events.
The power of this system lies in the realization that another type of target ship may have a handler for WeaponHit that checks the power of the source laser, and simply aborts the hit if the laser isn't powerful enough to damage it. Similarly, a special laser turret that contains an auto-targeting computer may register a handler for LaserAttack that automatically fires WeaponHit without a skill check and informs the game system that the attack event has already been resolved, thus bypassing hit avoidance of the target ship entirely. All of this happens without actually modifying the code that handles the generic case of a laser weapon fired at another ship.
Enough for now. I'm going to go work on the design document a bit before I have to mow the lawn. :)
While poking about defining the data required to properly model the game, I've also been thinking about the way the actual game logic will operate on these disparate objects. I'm currently considering a Non-Deterministic Finite Automata approach, where game entities are just collections of game state and potential/executing behavior, but I'm worried that it will lead me down a rabbit hole of attempting to implement an overly-generic framework for building the game, rather than actually working on the game. Oh, rabbit-holes. Thanks to you, I should have my level 10 spelunker's merit badge by now...
It's an exceptionally dangerous proposition for me due to two things. First, the abstract concept is like a neon sign in my head. I can see the core implementation like it was drawn up on my favorite 12'x8' whiteboard at work. Secondly, the challenges in implementing a solid, generic framework for developing future games are, honestly, more interesting to me than the challenges of designing a rule set for a specific game.
I might have to do a little more thinking on this and see if I can break it down into a set of quickly-attainable stories to put in Pivotal. If so, maybe I can keep myself from haring off course too far and kill two birds with one stone. Namely, get the game firmly started while implementing a system that will make feature addition and future game design a lot simpler.
Almost immediately after having the idea for ST and setting up the project and site hosting, I got absolutely slammed at work and lost all my free time and motivation. That is mostly over now. I've got three awesome co-workers who actually know what they're doing (a pleasant change) and it's lowered my stress levels to the point where I have some extra creative juices flowing.
So, keep an eye on this space! I'm working on some of the basic market functionality, and trying to get a grip on the overall layout of the system by putting together some high-level system documentation. The first several iterations of code aren't going to be much fun to play with on their own, but they're a necessary starting point, and I'm very happy to have the drive to work on this again!
1-3 of 3