diff --git a/docs/0.9.5/.buildinfo b/docs/0.9.5/.buildinfo index 8711dbf77a..9c997fc88e 100644 --- a/docs/0.9.5/.buildinfo +++ b/docs/0.9.5/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 5c30377db0aba959976f60592b4f359e +config: 17b3a0eee77a9e8fa590d1b9c4113963 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/0.9.5/Default-Commands.html b/docs/0.9.5/Default-Commands.html index 10ad68b385..31acacb72c 100644 --- a/docs/0.9.5/Default-Commands.html +++ b/docs/0.9.5/Default-Commands.html @@ -53,45 +53,45 @@ with Batch-Processor’s interactive mode.

+
+

A side note on html messages vrs text2html messages

+

So…lets say you have a desire to make your webclient output more like standard webpages… +For telnet clients, you could collect a bunch of text lines together, with ASCII formatted borders, etc. +Then send the results to be rendered client-side via the text2html plugin.

+

But for webclients, you could format a message directly with the html plugin to render the whole thing as an +HTML table, like so:

+
    # Server Side Python Code:
+
+    if target.is_webclient():
+        # This can be styled however you like using CSS, just add the CSS file to web/static/webclient/css/...
+        table = [
+                 "<table>",
+                  "<tr><td>1</td><td>2</td><td>3</td></tr>",
+                  "<tr><td>4</td><td>5</td><td>6</td></tr>",
+                 "</table>"
+               ]
+        target.msg( html=( "".join(table), {"type": "mytag"}) )
+    else:
+        # This will use the client to render this as "plain, simple" ASCII text, the same
+        #   as if it was rendered server-side via the Portal's text2html() functions
+        table = [ 
+                "#############",
+                "# 1 # 2 # 3 #",
+                "#############",
+                "# 4 # 5 # 6 #",
+                "#############"
+               ]
+        target.msg( html2html=( "\n".join(table), {"type": "mytag"}) )
+
+
+

Writing your own Plugins

So, you love the functionality of the webclient, but your game has specific @@ -184,7 +227,7 @@ window and the first input window are unique in that they can’t be “closed output and the one starting input window. This is done by modifying your server’s goldenlayout_default_config.js.

Start by creating a new -mygame/web/static_overrides/webclient/js/plugins/goldenlayout_default_config.js file, and adding +mygame/web/static/webclient/js/plugins/goldenlayout_default_config.js file, and adding the following JSON variable:

var goldenlayout_config = {
     content: [{
@@ -269,7 +312,7 @@ base.html.

Remember, plugins are load-order dependent, so make sure the new <script> tag comes before the goldenlayout.js

-

Next, create a new plugin file mygame/web/static_overrides/webclient/js/plugins/myplugin.js and +

Next, create a new plugin file mygame/web/static/webclient/js/plugins/myplugin.js and edit it.

let myplugin = (function () {
     //
@@ -331,6 +374,7 @@ window.plugin_handler.add("myplugin", myplugin);
 
  • Plugin Manager API (from webclient_gui.js)
  • Plugin callbacks API
  • Example/Default Plugins (plugins/*.js)
  • +
  • A side note on html messages vrs text2html messages
  • Writing your own Plugins diff --git a/docs/1.0-dev/Contribs/Contrib-Buffs.html b/docs/1.0-dev/Contribs/Contrib-Buffs.html index 57c0f7fc05..a465168198 100644 --- a/docs/1.0-dev/Contribs/Contrib-Buffs.html +++ b/docs/1.0-dev/Contribs/Contrib-Buffs.html @@ -126,6 +126,9 @@ values on the cache.

    buffs after application, they are very useful. The handler’s check/trigger methods utilize some of these getters, while others are just for developer convenience.

    get(key) is the most basic getter. It returns a single buff instance, or None if the buff doesn’t exist on the handler. It is also the only getter that returns a single buff instance, rather than a dictionary.

    +
    +

    Note: The handler method has(buff) allows you to check if a matching key (if a string) or buff class (if a class) is present on the handler cache, without actually instantiating the buff. You should use this method for basic “is this buff present?” checks.

    +

    Group getters, listed below, return a dictionary of values in the format {buffkey: instance}. If you want to iterate over all of these buffs, you should do so via the dict.values() method.

      @@ -183,6 +186,38 @@ buffs that are reactive to being checked; for example, removing themselves, alte

      Note: You can also trigger relevant buffs at the same time as you check them by ensuring the optional argument trigger is True in the check method.

      +

      Modifiers are calculated additively - that is, all modifiers of the same type are added together before being applied. They are then +applied through the following formula.

      +
      (base + total_add) / max(1, 1.0 + total_div) * max(0, 1.0 + total_mult)
      +
      +
      +
      +

      Multiplicative Buffs (Advanced)

      +

      Multiply/divide modifiers in this buff system are additive by default. This means that two +50% modifiers will equal a +100% modifier. But what if you want to apply mods multiplicatively?

      +

      First, you should carefully consider if you truly want multiplicative modifiers. Here’s some things to consider.

      +
        +
      • They are unintuitive to the average user, as two +50% damage buffs equal +125% instead of +100%.

      • +
      • They lead to “power explosion”, where stacking buffs in the right way can turn characters into unstoppable forces

      • +
      +

      Doing purely-additive multipliers allows you to better control the balance of your game. Conversely, doing multiplicative multipliers enables very fun build-crafting where smart usage of buffs and skills can turn you into a one-shot powerhouse. Each has its place.

      +

      The best design practice for multiplicative buffs is to divide your multipliers into “tiers”, where each tier is applied separately. You can easily do this with multiple check calls.

      +
      damage = damage
      +damage = handler.check(damage, 'damage')
      +damage = handler.check(damage, 'empower')
      +damage = handler.check(damage, 'radiant')
      +damage = handler.check(damage, 'overpower')
      +
      +
      +
      +
      +

      Buff Strength Priority (Advanced)

      +

      Sometimes you only want to apply the strongest modifier to a stat. This is supported by the optional strongest bool arg in the handler’s check method

      +
      def take_damage(self, source, damage):
      +    _damage = self.buffs.check(damage, 'taken_damage', strongest=True)
      +    self.db.health -= _damage
      +
      +
      +
  • Trigger Buffs

    @@ -255,6 +290,15 @@ and add a context to the mix.

    Apply the buff, take damage, and watch the thorns buff do its work!

    +
    +

    Viewing

    +

    There are two helper methods on the handler that allow you to get useful buff information back.

    + +

    You can also create your own custom viewing methods through the various handler getters, which will always return the entire buff object.

    +

    Creating New Buffs

    @@ -266,24 +310,46 @@ However, there are a lot of individual moving parts to a buff. Here’s a step-t -

    They also always store some useful mutable information about themselves in the cache:

    +

    Buffs also have a few useful properties:

    + +
    +

    Buff Cache (Advanced)

    +

    Buffs always store some useful mutable information about themselves in the cache (what is stored on the owning object’s database attribute). A buff’s cache corresponds to {buffkey: buffcache}, where buffcache is a dictionary containing at least the information below:

    -

    You can always access the raw cache dictionary through the cache attribute on an instanced buff. This is grabbed when you get the buff through -a handler method, so it may not always reflect recent changes you’ve made, depending on how you structure your buff calls. All of the above -mutable information can be found in this cache, as well as any arbitrary information you pass through the handler add method (via to_cache).

    +

    Sometimes you will want to dynamically update a buff’s cache at runtime, such as changing a tickrate in a hook method, or altering a buff’s duration. +You can do so by using the interface buff.cachekey. As long as the attribute name matches a key in the cache dictionary, it will update the stored +cache with the new value.

    +

    If there is no matching key, it will do nothing. If you wish to add a new key to the cache, you must use the buff.update_cache(dict) method, +which will properly update the cache (including adding new keys) using the dictionary provided.

    +
    +

    Example: You want to increase a buff’s duration by 30 seconds. You use buff.duration += 30. This new duration is now reflected on both the instance and the cache.

    +
    +

    The buff cache can also store arbitrary information. To do so, pass a dictionary through the handler add method (handler.add(BuffClass, to_cache=dict)), +set the cache dictionary attribute on your buff class, or use the aforementioned buff.update_cache(dict) method.

    +
    +

    Example: You store damage as a value in the buff cache and use it for your poison buff. You want to increase it over time, so you use buff.damage += 1 in the tick method.

    +
    +

    Modifiers

    @@ -292,9 +358,9 @@ mods of a specific stat string and apply their modifications to the value; howev

    Mod objects consist of only four values, assigned by the constructor in this order:

    The most basic way to add a Mod to a buff is to do so in the buff class definition, like this:

    class DamageBuff(BaseBuff):
    @@ -312,8 +378,7 @@ never permanently change a stat modified by a buff. To remove the modification,
     

    An advanced way to do mods is to generate them when the buff is initialized. This lets you create mods on the fly that are reactive to the game state.

    class GeneratedStatBuff(BaseBuff):
         ...
    -    def __init__(self, handler, buffkey, cache={}) -> None:
    -        super().__init__(handler, buffkey, cache)
    +    def at_init(self, *args, **kwargs) -> None:
             # Finds our "modgen" cache value, and generates a mod from it
             modgen = list(self.cache.get("modgen"))
             if modgen:
    @@ -367,7 +432,7 @@ example, if you want a buff that makes the player take more damage when they are
     
    class FireSick(BaseBuff):
         ...
         def conditional(self, *args, **kwargs):
    -        if self.owner.buffs.get_by_type(FireBuff): 
    +        if self.owner.buffs.has(FireBuff): 
                 return True
             return False
     
    @@ -382,6 +447,7 @@ conditionals are checked each tick.

  • remove/dispel: Allows you to remove or dispel the buff. Calls at_remove/at_dispel, depending on optional arguments.

  • pause/unpause: Pauses and unpauses the buff. Calls at_pause/at_unpause.

  • reset: Resets the buff’s start to the current time; same as “refreshing” it.

  • +
  • alter_cache: Updates the buff’s cache with the {key:value} pairs in the provided dictionary. Can overwrite default values, so be careful!

  • @@ -432,14 +498,22 @@ file will be overwritten, so edit that file rather than this one.

  • Apply a Buff
  • Get Buffs
  • Remove Buffs
  • -
  • Check Modifiers
  • +
  • Check Modifiers +
  • Trigger Buffs
  • Ticking
  • Context
  • +
  • Viewing
  • Creating New Buffs