DistributionBuilder - yeelp/Distinct-Damage-Descriptions GitHub Wiki

DDD's DistributionBuilder lets you define custom damage distributions and the contexts they apply to in ZenScript? Want exposed electrical wires to do lightning damage? Or maybe the config won't let you set the distribution for a particular modded feature in exactly the way you want. Enter the DistributionBuilder! If you can define the context where you want to apply a distribution, you can build it with this!

Importing the class

It might be required for you to import the class if you encounter any issues, like casting an array, so better be safe than sorry and add the import.

import mods.ddd.distributions.DistributionBuilder;

Creating a Distribution

First off, you need to create an instance of the DistributionBuilder. You can do this with the create(string) static ZenMethod.

val exampleDistribution = mods.ddd.distributions.DistributionBuilder.create("example");

Much like with the DamageTypeBuilder, The string you give to the create ZenMethod must be unique! No other distribution can have that name. However, you can define a distribution and a damage type with the same name; distributions must only have names unique amongst each other.

Building a Distribution

After you've set what you want (See the section on ZenProperties), you should build the distribution with the build() ZenMethod.

exampleDistribution.build();

Making changes to the DistributionBuilder past this point won't change the distribution that was created. Note that the distribution doesn't exist yet. All the register ZenMethod does is queue this distribution to be registered.

Setting the distribution's context

The DistributionBuilder has a ZenProperty called isContextApplicable. This is of a type called IsContextApplicable. We call this the context function. The context function is a function that takes 3 arguments:

  • An ICustomDistribution that represents this distribution.
  • An IDamageSource that represents the damage source being used.
  • An IEntityLivingBase that represents the attacked entity. To get the attacking entity, you can use the IDamageSource's trueSource and immediateSource ZenGetters, depending on what you need.

The function returns either true or false. It returns true when this distribution should be used, and it returns false otherwise. If you don't set the context function, your script will throw an exception.

Setting the distribution

To define the distribution, you need to set its weights. This can be done with one of two ZenMethods:

  • setWeight(IDDDDamageType, float)
  • setWeight(string, float) This is an overloaded ZenMethod. They have the same name, but you can provide either an IDDDDamageType or a string. The string version requires you to specify the internal name of the damage type, which should be all lowercase. The IDDDDamageType version can let you use the damage type bracket handler to define the damage type you're setting the weight for, however ContentTweaker scripts run before DDD registers damage types and distributions (remember what was mentioned in the building section). So the setWeight ZenMethod that takes an IDDDDamageType only works for built in types.

This can not be stressed enough. If you are creating a custom distribution that uses a custom damage type, you MUST use setWeight(string, float)! In general, it is probably better to always use the string version of setWeight to avoid this problem altogether.

Note that like with the config, the weights of the distribution must add up to 1! Your script will throw an exception otherwise.

ZenProperties

ZenProperty Name Type Notes
name string This is the internal name of the distribution. This field gets set to whatever you pass in to the create static ZenMethod, but you can change it like a normal ZenProperty. Note that your script will throw an exception if you set this to null and then try to register the distribution!
isContextApplicable IsContextApplicable This is the context function. See Setting the distribution's context.
priority int This is the priority of the distribution. Higher priority distributions will have their context functions checked first. This is useful to have generic "catch all" custom distributions with low priority and then specific distribution that are applied in specific contexts with high priority. If their context functions return false, then the lower priority, more generic custom distribution will have its more broad context function checked.

ZenMethods

void setWeight(IDDDDamageType, float);

  • Sets the weight of this damage type in this distribution to the specified amount. See Setting the distribution. Remember this version only works for built in damage types!

void setWeight(string, float);

  • Sets the weight for the type specified by the internal name that the string represents to the specified amount. See Setting the distribution.

void build();

  • Queues this distribution to be built and registered. This DistributionBuilder can not be used to build multiple distributions so after this is called, this ZenMethod will do nothing if called again. Your script will throw an exception if the name ZenProperty is null, if the name is already in use, some weights are negative, the weights do not add to 1, or no context function is set.

Static ZenMethods

Static ZenMethods have to be called on the ZenClass

DistributionBuilder create(string);

  • Creates a new DistributionBuilder where the name ZenProperty will be set to the specified string.

Example

#loader contenttweaker
#modloaded distinctdamagedescriptions

val dist = mods.ddd.distributions.DistributionBuilder.create("example");
dist.priority = 3;
dist.setWeight(<dddtype:force>, 0.25); //25% Force damage, using the bracket handler version of setWeight since force is a built in type.
dist.setWeight("example", 0.5); //50% Example damage, note we need to have created a damage type called example, like we did in the DamageTypeBuilder article! We have to use the string version of setWeight here since example is a custom damage type.
dist.setWeight("psychic", 0.25); //25% Psychic damage. We use the string version of setWeight, though we could've used the bracket handler version since psychic is a built in type.

//This is our context function! For this example, we want this distribution to apply when getting pricked by a cactus in the nether only!
dist.isContextApplicable = function(thisDist, src, target) {
   //we add guard statements; basically filter out all other contexts except the context we want!
   //first, if the dimension this damage took place in is not the nether, our distribution should not apply. (nether is dimension -1)
   if(target.world.dimension != -1) {
      return false;
   }
   //If we reached this point in execution, then we didn't enter the above block so we must be in the nether. Now check if the damage source is caused by a cactus. Cacti have their own damage source in Minecraft. If it is not cause by a cactus, our distribution should not apply.
   if(src.damageType != "cactus") {
      return false;
   }
   //If we reached this point in execution, then we didn't enter the above two blocks, so we must be in the nether, and the damage source must be caused by a cactus. That's our context!
   return true;
};
dist.build();