Mod Creation/Essentials: Difference between revisions

Clarified that traditional function expressions are more suitable than arrow functions for method patching
(Clarified that traditional function expressions are more suitable than arrow functions for method patching)
Tag: visualeditor-switched
 
(6 intermediate revisions by the same user not shown)
Line 204: Line 204:


Use <syntaxhighlight lang="js" inline>ctx.loadData</syntaxhighlight> to read and automatically parse a JSON resource.
Use <syntaxhighlight lang="js" inline>ctx.loadData</syntaxhighlight> to read and automatically parse a JSON resource.
''Comments in JSON are purely illustrative and not valid markup''


  <syntaxhighlight lang="js" line>// my-data.json
  <syntaxhighlight lang="js" line>// my-data.json
Line 213: Line 211:
   ]
   ]
}</syntaxhighlight>
}</syntaxhighlight>
<small>''Comments in JSON are purely illustrative and not valid markup''</small>


  <syntaxhighlight lang="js" line>// setup.mjs
  <syntaxhighlight lang="js" line>// setup.mjs
Line 338: Line 338:
   "load": ["path-to-your-data.json"]
   "load": ["path-to-your-data.json"]
}</syntaxhighlight>
}</syntaxhighlight>
<small>''Comments in JSON are purely illustrative and not valid markup''</small>


''or''
''or''
Line 408: Line 410:


''View this topic's relevant API reference here [[Mod Creation/Mod Context API Reference#Mod Settings]].''
''View this topic's relevant API reference here [[Mod Creation/Mod Context API Reference#Mod Settings]].''
{{Disclaimer|When loading your mod as a Local Mod via the Creator Toolkit, the mod must be linked to mod.io and you must have subscribed to and installed the mod via mod.io in order for this data to persist.}}


Your mod can define settings for the player to interact with and visually configure your mod in-game. This feature is accessible through a <code>settings</code> property on the context object. If your mod has any settings defined, your mod will appear in the sidebar under Mod Settings. Clicking this will open up a window with all of your defined settings.
Your mod can define settings for the player to interact with and visually configure your mod in-game. This feature is accessible through a <code>settings</code> property on the context object. If your mod has any settings defined, your mod will appear in the sidebar under Mod Settings. Clicking this will open up a window with all of your defined settings.
Line 542: Line 546:
   "load": "templates.html"
   "load": "templates.html"
}</syntaxhighlight>
}</syntaxhighlight>
<small>''Comments in JSON are purely illustrative and not valid markup''</small>


''or''
''or''
Line 576: Line 582:


''View the account storage's relevant API reference here [[Mod Creation/Mod Context API Reference#Account Data Storage]].''
''View the account storage's relevant API reference here [[Mod Creation/Mod Context API Reference#Account Data Storage]].''
{{Disclaimer|When loading your mod as a Local Mod via the Creator Toolkit, the mod must be linked to mod.io and you must have subscribed to and installed the mod via mod.io in order for this data to persist.}}


There are two options for storing data for your mod that isn't already saved as part of the game or settings: data saved with a character or data saved to the player's account. For most cases, however, character storage should be the preferred location and account storage used sparingly. Both of these stores are available through your mod's context object, as <code>characterStorage</code> and <code>accountStorage</code>, respectively. Aside from where the data is ultimately saved, character and account storage have identical methods and behaviors. Character storage is not available until after a character has been loaded (<code>onCharacterLoaded</code> lifecycle hook).
There are two options for storing data for your mod that isn't already saved as part of the game or settings: data saved with a character or data saved to the player's account. For most cases, however, character storage should be the preferred location and account storage used sparingly. Both of these stores are available through your mod's context object, as <code>characterStorage</code> and <code>accountStorage</code>, respectively. Aside from where the data is ultimately saved, character and account storage have identical methods and behaviors. Character storage is not available until after a character has been loaded (<code>onCharacterLoaded</code> lifecycle hook).
Line 611: Line 619:


From there you can use that patch to perform any of the following actions.
From there you can use that patch to perform any of the following actions.
=== A Quick Note on Function Syntax ===
When patching methods, for most scenarios you'll want to use a traditional function expression, rather than the arrow expression syntax. This will ensure <code>this</code> is bound to the class instance that is calling the method, rather than the context where the patch was defined.
For example,
<syntaxhighlight lang="js" line="1">export function setup({ patch }) {
  const methodPatch = patch(Class, 'method');
  // Do this
  methodPatch.before(function () { });
 
  // Or this
  function beforePatch () { }
  methodPatch.before(beforePatch);
 
  // Not this, unless you understand the implications of doing so
  methodPatch.before(() => { });
}</syntaxhighlight>


=== Do Something Before ===
=== Do Something Before ===
Line 616: Line 642:
Use the <code>before</code> method on the patch object to execute code immediately before the patched method. In addition, the callback hook will receive the arguments that were used to call the patched method as parameters, and can optionally modify them by returning the new arguments as an array.
Use the <code>before</code> method on the patch object to execute code immediately before the patched method. In addition, the callback hook will receive the arguments that were used to call the patched method as parameters, and can optionally modify them by returning the new arguments as an array.


  <syntaxhighlight lang="js" line>// setup.mjs
  <syntaxhighlight lang="js" line="1">// setup.mjs
export function setup({ patch }) {
export function setup({ patch }) {
   patch(Skill, 'addXP').before((amount, masteryAction) => {
   patch(Skill, 'addXP').before(function (amount, masteryAction) {
     console.log(`Doubling XP from ${amount} to ${amount * 2}!`);
     console.log(`Doubling XP from ${amount} to ${amount * 2}!`);
     return [amount * 2, masteryAction]; // Double all XP gains
     return [amount * 2, masteryAction]; // Double all XP gains
Line 628: Line 654:
Use the <code>after</code> method on the patch object to execute code immediately after the patched method. In addition, the callback hook will receive the value returned from the patched method along with the arguments used to call it as parameters. Optionally, an after hook can choose to override the returned value by returning a value itself. '''''Only''' a return value of <code>undefined</code> will be ignored.''
Use the <code>after</code> method on the patch object to execute code immediately after the patched method. In addition, the callback hook will receive the value returned from the patched method along with the arguments used to call it as parameters. Optionally, an after hook can choose to override the returned value by returning a value itself. '''''Only''' a return value of <code>undefined</code> will be ignored.''


  <syntaxhighlight lang="js" line>// setup.mjs
  <syntaxhighlight lang="js" line="1">// setup.mjs
export function setup({ patch }) {
export function setup({ patch }) {
   patch(Player, 'rollToHit').after((willHit) => {
   patch(Player, 'rollToHit').after(function (willHit) {
     if (!willHit) console.log('A miss? I think not!');
     if (!willHit) console.log('A miss? I think not!');
     return true;
     return true;
Line 692: Line 718:
   "setup": "setup.mjs"
   "setup": "setup.mjs"
}</syntaxhighlight>
}</syntaxhighlight>
<small>''Comments in JSON are purely illustrative and not valid markup''</small>


  <syntaxhighlight lang="js" line>// setup.mjs
  <syntaxhighlight lang="js" line>// setup.mjs
91

edits