Closed aed3 closed 1 year ago
After reading through the design work in pkmn/engine - which I'll probably be referencing a lot because of how thorough it is - I have another idea which gets rid of looking up events altogether.
battle.runEvent
calls as the exist now and replace them with deliberate functions for each event type (battle.runEvent(UseItem, ...)
becomes battle.onUseItem(...)
)onModifyDamage
is called, that function will check run a switch statement against the move user's item, and if the user has a Life Orb, LifeOrb::onModifyDamage
will get calledThis allows for all the event handlers from the same effect type to continue to be written in the same place and resused, keeping the code organized. Also, separating the code out like this allows for swapping out runEvent functions depending on the game being simulated.
Not sure yet how well this will work with the "Analyze Effect" portion of the code or of its performance benefits over other options. This also breaks if the order of events for a specific type ever changes (like factoring in a Choice Band's boost on a move changes from before to after factoring in any weather-based boosts), but right now I'm not aware of that ever happening.
Hard-coding Events
After reading through the design work in pkmn/engine - which I'll probably be referencing a lot because of how thorough it is - I have another idea which gets rid of looking up events altogether.
- Maintain the
battle.runEvent
calls as the exist now and replace them with deliberate functions for each event type (battle.runEvent(UseItem, ...)
becomesbattle.onUseItem(...)
)- Within those specific runEvent functions, all the possible event handler functions for it will be listed and the one to run will be chosen based on various switch and if statements
- For example, if
onModifyDamage
is called, that function will check run a switch statement against the move user's item, and if the user has a Life Orb,LifeOrb::onModifyDamage
will get called- The order in which event handlers are listed in these functions will act as a replacement for the "priority" parameter some events use
This allows for all the event handlers from the same effect type to continue to be written in the same place and resused, keeping the code organized. Also, separating the code out like this allows for swapping out runEvent functions depending on the game being simulated.
Not sure yet how well this will work with the "Analyze Effect" portion of the code or of its performance benefits over other options. This also breaks if the order of events for a specific type ever changes (like factoring in a Choice Band's boost on a move changes from before to after factoring in any weather-based boosts), but right now I'm not aware of that ever happening.
Maybe using an inheritance/virtual method design instead of switch and if statements here is better. It is for sure from a maintainability standpoint, but performance is TBD: I'm looking into it.
Settled with 945900d6ff8f9637909ea6161f8b155ba7c34ea1 in designs/Features/EventHandling.md
When taking a CPU profile of Showdown when running my AI, this set of functions uses the most time overall and the most time per call. However, changing these functions to be performant might require changing the entire structure of the code, so finding the best way to handle events that various parts of a battle can activate is step 1.