Skip to content

01 Game and Store Commands Refactor

Marc Johnston edited this page Jul 20, 2022 · 8 revisions

GAME COMMANDS

The first round of refactoring was to convert the SWITCH statement in the CommandHandler to use objects for commands. During the conversion process, it became evident that the ActivationHandler and the CastingHandler were similar objects performing the same objective; so the ActivationHandler and CastingHandler classes were converted into the ICommand interface and all command actions were converted into class objects that implements the ICommand interface. The parameters into the handler class constructors (player and level) are passed as objects to the command execution.

COMMAND OBJECTS

A "Commands" folder was created and all of the command objects have been placed into this folder. Also, note that the ICommand and IStoreCommand interfaces were placed into the same folder.

STORE COMMANDS

During the conversion, it was noticed that the store also referenced a handful of the same commands. To accommodate this, an IStoreCommand interface was also added. The IStoreCommand interface defines the same Execute method, but does not pass the Level object because stores should not be able to interact with items outside of the store. All game command objects that also serve as store commands were updated to also implement the IStoreCommand interface. During this process, a flaw was exposed where the store needed to pass the current Level object to the command. This flaw is apparent when the command needs the player to select an object using the GetItem method. The GetItem method requires a Level object to allow the player to select an object from the floor.

There are two avenues to absolve this deficiency.

  1. Refactor the IStoreCommand.Execute(Player) into IStoreCommand.Execute(Player, SaveGame.Instance.Level) but that would allow the store access to items in the Town.
  2. Refactor the GetItem method. This is the avenue we will take. Once the GetItem framework objects are created, a base class should be able to implement the GetItem that is limited to the player inventory.

REPEAT PROPERTY

Several commands support the ability to be performed multiple times. The code that identified this functionality was: if (Gui.CommandArgument != 0) { CommandRepeat = Gui.CommandArgument - 1; Player.RedrawNeeded.Set(RedrawFlag.PrState); Gui.CommandArgument = 0; }

This functionality is supported by these commands.

  • Alter
  • Bash
  • Close
  • Disarm
  • Open
  • Tunnel
  • Walk
  • Search
  • Stay

In addition, a logic statement (shown below) was found that appeared to provide an automatic repeat count for several commands.

        if (CommandArgument <= 0 && !shopping)
        {
            if ("TBDocs+".Contains(CurrentCommand.ToString()))
            {
                CommandArgument = 99;
            }
        }

This logic statement appears to modify these commands:

  • Tunnel
  • Bash
  • Disarm
  • Open
  • Close
  • Alter

To support this functionality, a nullable integer Repeat property was added. For commands that do not support repeat, a value of zero should be returned. For command that have an auto repeat of 99, a value of 99 should be returned. Otherwise, for commands that support repeat, the value should return as null.

DYNAMIC LOADING AND COMMAND MANAGER

To ensure all command objects are loaded, a dynamic loading process was created. Upon startup, using reflection, all objects are scanned to determine if they implement in the ICommand and/or IStoreCommand interfaces. If so, they are added to an appropriate list and made available in the CommandManager static class.

TECH DEBT

  1. A couple areas of tech debt were created and exposed during this process. There were a few commands where the execute method is being called by other parts of the application (e.g. Save game). To accommodate the additional references, the execute method for several of the commands was converted into a static method.

These commands were affected:

  • Feeling command
  • Stay command
  • Store command ... used by SaveGame to start in store
  • CastCommand.GetSpell
  • Walk command ... two pickup variations
  • Throw command ... used by MutationLauncher
  1. A couple of the commands made use of a "pickup" parameter. To resolve this, the command objects were inherited and the properties were made virtual with an override.
Clone this wiki locally