
Currently:
- Projectile is an Entity. This allows an Actor to move into the same tile as it.
- Projectile has an on_move function, so when an Actor does move into its tile the Projectile hits it. (specifically ActorProject:projectDoStop, see below).
- Projectile:projectile has a damtype argument that can be either a function (as it is in archeryShoot) or a simple damage type (think PHYSICAL, or ACID, etc). This can be confusing at first, but makes it very easy to generalize what a Projectile does without modifying the Projectile class itself.
- Projectile has a project.def table that holds the definitions(?) for the projectile, things like range, starting position, target position, damtype, etc). Very nested namespace, but is that really a problem?
- Projectile has an act function. This allows the Projectile to be updated by the game's tick. The actual functions are found in the ActorProject interface, namely projectDoMove, projectDoAct and projectDoStop.
- ActorProject:projectDoMove draws a line from the starting position to the target position, then finds the projectile's current position along that line. The next position along the line is determined and we check if there is something there to hit. The actual movement is done in Projectile:act before the ActorProject:projectDoAct or ActorProject:projectDoStop function calls.
- ActorProject:projectDoAct deals the damage without killing the projectile. The damtype argument is checked and either executed (if it is a function) or uses the DamageType:get(damtype).projector chain. The damage only appears to be applied to the current tile, although a custom damage projector could change this.
- ActorProject:projectDoStop deals damage and kills the projectile. This function explicitly checks for what type of damage (ball, cone or single tile) and then calls ActorProject:projectDoAct on each affected tile.
Also, is there a reason that ActorProject:projectDoAct doesn't have the explicit check for ball/cone types of damage? One case that would favor that sort of check would be a massive fireball that doesn't explode on impact, simply moves through and possibly knocking back (ouch!). We could generalize the in-flight action and on-stop action to be completely independent so you can have a piercing arrow (single tile PHYSICAL damage when in-flight) ending with an explosion (cone ACID damage from the vial of acid within the arrow shaft).
Specific to ToME is the 7th point, where ToME calls the huge function defined in Combat:archeryShoot. One odd thing I noticed is that the actual removal of ammo from the shooting actor is saved until this point, which seems counter-intuitive. I understand the reason (variable ammo in the case of Dual Arrows, Volley of Arrows, etc) but think this deserves some more thought. Maybe remove the maximum number of ammo for the talent at the time of shooting? If you can potentially hit 5 things shouldn't you have to shoot 5 arrows?
I wanted to get these initial thoughts out there so DG and others can look over them, and if I get the green light from DG will come up with a more detailed refactor proposal. Cheers!