Skip to content

Commit

Permalink
Make meteor reagents completely configurable and add some new options…
Browse files Browse the repository at this point in the history
… to their functionality.

Config files are placed in /config/BloodMagic/meteors/reagents/.
Default configs will be generated if the folder is not present. Defaults will not be generated if the folder is present AND empty if you want to remove every reagent's effects.
Create a file named reagentName.json to configure that reagent (orbisTerrae.json, potentia.json, ...). Reagent names may most easily be found by looking at the tooltips of belljars in NEI.

Available reagent configuration options are:

For the following three configs, the single largest increase (largest positive config) and single largest decrease (largest negative config) values are used, just like how Orbis Terrae completely overshadows Terrae in the old system. Default values for these three configs are all 0:
radiusChange: int (change the radius of the meteor. Minimum radius is 1)
fillerChanceChange: int (change the filler chance similar to how it was done with the old weight system, except the max chance is now 100 instead of 1000. For example, terrae with a fillerChanceChange of 10 is equivalent to how it increased the total weight by 100 previously. Full formula is fillerChance = (fillerChance + fillerChanceChange) * 100 / (100 + fillerChanceChange). For example, a fillerChance of 50 with Orbis Terrae's default fillerChanceChange of 20 gives a new fillerChance of about 58%. This fixes meteors with very high fillerChance values (90+) from being entirely made of filler when supplied with (Orbis) Terrae like how they were in my last commit)
rawFillerChanceChange: int (directly change the filler chance by the supplied amount. fillerChance += rawFillerChanceChange. For example, a fillerChance of 50 with a rawFillerChanceChange of -20 gives a new fillerChance of 30)
The final value for fillerChance will always be between 0 and 100 inclusive. Reagents will not add filler to meteors with a fillerChance of 0. rawFillerChanceChange is applied before fillerChanceChange. A reagent with fillerChanceChange of -100 will always set the fillerChance of a meteor to 0.

For the following two configs, any reagent with these options set to true will apply this change to the whole meteor. Default value for both of these is false:
disableExplosions: boolean (if set to true, this reagent entirely disables explosions caused by the meteor)
invertExplosionBlockDamage: boolean (if set to true, this reagent inverts the setting B:doMeteorsDestroyBlocks in config/AWWayofTime.cfg for this meteor. May be used to make normally dangerous meteors safe, or can be used as a tradeoff to unlock a powerful effect when meteors are normally safe)

This config's format is the same as the meteor ore and filler configs:
filler: array of strings that define blocks (For example, incendium's default filler array is "minecraft:netherrack:0:60", minecraft:glowstone:0:60", minecraft:soul_sand:0:60")
For best results when combining reagents, try to ensure that all reagent filler arrays you define have the same total weight. Default configs use a total of 180 because it is highly composite, but that exact number is not required to be used.

The formats for blocks in the meteor and reagent configs has been slightly altered to allow certain blocks to be placed only when a specified reagent is present. The block formats are now:
modId:itemName:meta:weight(:reagent1, reagent2, ... optional)
OREDICT:oreDictName:weight(:reagent1, reagent2, ... optional)
Don't include the () in any configs, they just show what the optional section. Spaces after the commas used to separate reagents are optional. The colon is required if any reagents are specified, and commas are required to separate multiple reagents.
Any one reagent in the list must be present for that block to be present, for example: "minecraft:diamond_ore:0:100:terrae,orbisTerrae" will only allow diamond ore to be placed when either Terrae OR Orbis Terrae are present.
Block lists in reagent configs CAN depend on other reagents being present! Changing tenebrae's default filler entry to "minecraft:obsidian:0:180:magicales" will make it only change the filler out for obsidian if magicales is also present.
Reagents required for blocks in ore/filler lists do NOT require a config file to be present in /config/BloodMagic/meteors/reagents/, but creating an empty config file for it will not cause problems.
NEI will show the tooltip "Required reagent: x, y, ..." for any meteor ores or filler blocks that require a reagent.

The legacy config format [block, weight, block, weight ...] has been REMOVED. All of the meteor configs in GTNH have already been rewritten in one of the two newer formats.
  • Loading branch information
koolkrafter5 committed Jan 14, 2025
1 parent 2e95450 commit f9ee04c
Show file tree
Hide file tree
Showing 12 changed files with 445 additions and 345 deletions.
227 changes: 19 additions & 208 deletions src/main/java/WayofTime/alchemicalWizardry/AlchemicalWizardry.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package WayofTime.alchemicalWizardry.client.nei;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -16,6 +15,9 @@

import org.lwjgl.opengl.GL11;

import com.google.common.base.Joiner;

import WayofTime.alchemicalWizardry.api.alchemy.energy.Reagent;
import WayofTime.alchemicalWizardry.common.summoning.meteor.MeteorParadigm;
import WayofTime.alchemicalWizardry.common.summoning.meteor.MeteorParadigmComponent;
import WayofTime.alchemicalWizardry.common.summoning.meteor.MeteorRegistry;
Expand All @@ -31,7 +33,6 @@ public class CachedMeteorRecipe extends CachedRecipe {

private final List<PositionedStack> input = new ArrayList<>();
private final List<PositionedStack> outputs = new ArrayList<>();
private final List<PositionedStack> filler = new ArrayList<>();
private final int cost;
private final int radius;
private Point focus;
Expand All @@ -50,14 +51,17 @@ public CachedMeteorRecipe(MeteorParadigm meteor, ItemStack focusStack) {
float componentRatio = 1 - fillerRatio;

for (MeteorParadigmComponent component : sortedComponents) {
ItemStack stack = component.getValidBlockParadigm();
ItemStack stack = component.getBlock();
int xPos = 3 + 18 * col;
int yPos = 37 + 18 * row;

List<String> tooltips = new ArrayList<>();
float chance = component.getWeight() / totalComponentWeight * componentRatio;
tooltips.add(I18n.format("nei.recipe.meteor.chance", getFormattedChance(chance)));
tooltips.add(I18n.format("nei.recipe.meteor.amount", getEstimatedAmount(chance, meteor.radius)));
if (!component.getRequiredReagents().isEmpty()) {
tooltips.add(I18n.format("nei.recipe.meteor.reagent", getReagentStrings(component)));
}
this.outputs.add(new TooltipStack(stack, xPos, yPos, tooltips));

col++;
Expand All @@ -82,7 +86,7 @@ public CachedMeteorRecipe(MeteorParadigm meteor, ItemStack focusStack) {
float totalFillerWeight = meteor.getTotalListWeight(meteor.fillerList);

for (MeteorParadigmComponent filler : sortedFiller) {
ItemStack stack = filler.getValidBlockParadigm();
ItemStack stack = filler.getBlock();
int xPos = 3 + 18 * col;
int yPos = 37 + 18 * row;

Expand All @@ -91,6 +95,9 @@ public CachedMeteorRecipe(MeteorParadigm meteor, ItemStack focusStack) {
tooltips.add(I18n.format("nei.recipe.meteor.chance", getFormattedChance(chance)));
tooltips.add(I18n.format("nei.recipe.meteor.amount", getEstimatedAmount(chance, meteor.radius)));
tooltips.add(I18n.format("nei.recipe.meteor.filler"));
if (!filler.getRequiredReagents().isEmpty()) {
tooltips.add(I18n.format("nei.recipe.meteor.reagent", getReagentStrings(filler)));
}
this.outputs.add(new TooltipStack(stack, xPos, yPos, tooltips));

col++;
Expand All @@ -109,6 +116,15 @@ public CachedMeteorRecipe(MeteorParadigm meteor, ItemStack focusStack) {
this.cost = meteor.cost;
}

private String getReagentStrings(MeteorParadigmComponent component) {
ArrayList<Reagent> reagents = component.getRequiredReagents();
ArrayList<String> reagentNames = new ArrayList<>();
for (Reagent r : reagents) {
reagentNames.add(r.name);
}
return Joiner.on(", ").join(reagentNames);
}

@Override
public List<PositionedStack> getIngredients() {
return this.input;
Expand Down Expand Up @@ -152,10 +168,10 @@ public void loadCraftingRecipes(String outputId, Object... results) {
@Override
public void loadCraftingRecipes(ItemStack result) {
for (MeteorParadigm meteor : getSortedMeteors()) {
if (meteor.componentList.stream().anyMatch(m -> matchItem(result, m.getValidBlockParadigm()))) {
if (meteor.componentList.stream().anyMatch(m -> matchItem(result, m.getBlock()))) {
arecipes.add(new CachedMeteorRecipe(meteor, result));
}
if (meteor.fillerList.stream().anyMatch(m -> matchItem(result, m.getValidBlockParadigm()))) {
if (meteor.fillerList.stream().anyMatch(m -> matchItem(result, m.getBlock()))) {
arecipes.add(new CachedMeteorRecipe(meteor, result));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package WayofTime.alchemicalWizardry.common.entity.projectile;

import java.util.ArrayList;

import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;

import WayofTime.alchemicalWizardry.api.alchemy.energy.Reagent;
import WayofTime.alchemicalWizardry.api.alchemy.energy.ReagentRegistry;
import WayofTime.alchemicalWizardry.common.summoning.meteor.MeteorRegistry;

public class EntityMeteor extends EnergyBlastProjectile {

private int meteorID;

public boolean hasTerrae;
public boolean hasOrbisTerrae;
public boolean hasCrystallos;
public boolean hasIncendium;
public boolean hasTennebrae;
public ArrayList<Reagent> reagentList = new ArrayList<>();

public EntityMeteor(World par1World) {
super(par1World);
Expand All @@ -33,23 +33,23 @@ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
super.writeEntityToNBT(par1NBTTagCompound);

par1NBTTagCompound.setInteger("meteorID", meteorID);
par1NBTTagCompound.setBoolean("hasTerrae", hasTerrae);
par1NBTTagCompound.setBoolean("hasOrbisTerrae", hasOrbisTerrae);
par1NBTTagCompound.setBoolean("hasCrystallos", hasCrystallos);
par1NBTTagCompound.setBoolean("hasIncendium", hasIncendium);
par1NBTTagCompound.setBoolean("hasTennebrae", hasTennebrae);

for (Reagent r : reagentList) {
par1NBTTagCompound.setBoolean("reagent." + r.name, true);
}

}

@Override
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
super.readEntityFromNBT(par1NBTTagCompound);

meteorID = par1NBTTagCompound.getInteger("meteorID");
hasTerrae = par1NBTTagCompound.getBoolean("hasTerrae");
hasOrbisTerrae = par1NBTTagCompound.getBoolean("hasOrbisTerrae");
hasIncendium = par1NBTTagCompound.getBoolean("hasIncendium");
hasCrystallos = par1NBTTagCompound.getBoolean("hasCrystallos");
hasTennebrae = par1NBTTagCompound.getBoolean("hasTennebrae");
for (Reagent r : ReagentRegistry.reagentList.values()) {
if (par1NBTTagCompound.getBoolean("reagent." + r.name)) {
reagentList.add(r);
}
}
}

@Override
Expand All @@ -66,27 +66,16 @@ public void onImpact(MovingObjectPosition mop) {
if (mop.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY && mop.entityHit != null) {
this.onImpact(mop.entityHit);
} else if (mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
MeteorRegistry.createMeteorImpact(
worldObj,
mop.blockX,
mop.blockY,
mop.blockZ,
this.meteorID,
new boolean[] { hasTerrae, hasOrbisTerrae, hasCrystallos, hasIncendium, hasTennebrae });
MeteorRegistry.createMeteorImpact(worldObj, mop.blockX, mop.blockY, mop.blockZ, this.meteorID, reagentList);
}

this.setDead();
}

@Override
public void onImpact(Entity mop) {
MeteorRegistry.createMeteorImpact(
worldObj,
(int) this.posX,
(int) this.posY,
(int) this.posZ,
meteorID,
new boolean[] { hasTerrae, hasOrbisTerrae, hasCrystallos, hasIncendium, hasTennebrae });
MeteorRegistry
.createMeteorImpact(worldObj, (int) this.posX, (int) this.posY, (int) this.posZ, meteorID, reagentList);

this.setDead();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import net.minecraft.world.World;

import WayofTime.alchemicalWizardry.AlchemicalWizardry;
import WayofTime.alchemicalWizardry.api.alchemy.energy.Reagent;
import WayofTime.alchemicalWizardry.api.alchemy.energy.ReagentRegistry;
import WayofTime.alchemicalWizardry.api.rituals.IMasterRitualStone;
import WayofTime.alchemicalWizardry.api.rituals.RitualComponent;
Expand Down Expand Up @@ -56,20 +57,10 @@ public void performEffect(IMasterRitualStone ritualStone) {
EntityMeteor meteor = new EntityMeteor(world, x + 0.5f, 257, z + 0.5f, meteorID);
meteor.motionY = -1.0f;

if (this.canDrainReagent(ritualStone, ReagentRegistry.terraeReagent, 1000, true)) {
meteor.hasTerrae = true;
}
if (this.canDrainReagent(ritualStone, ReagentRegistry.orbisTerraeReagent, 1000, true)) {
meteor.hasOrbisTerrae = true;
}
if (this.canDrainReagent(ritualStone, ReagentRegistry.crystallosReagent, 1000, true)) {
meteor.hasCrystallos = true;
}
if (this.canDrainReagent(ritualStone, ReagentRegistry.incendiumReagent, 1000, true)) {
meteor.hasIncendium = true;
}
if (this.canDrainReagent(ritualStone, ReagentRegistry.tenebraeReagent, 1000, true)) {
meteor.hasTennebrae = true;
for (Reagent r : ReagentRegistry.reagentList.values()) {
if (this.canDrainReagent(ritualStone, r, 1000, true)) {
meteor.reagentList.add(r);
}
}

entityItem.setDead();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

public class Meteor {

private String[] ores;
private int radius;
private int cost;
private String focusModId;
private String focusName;
private int focusMeta;
public String[] ores;
public int radius;
public int cost;
public String focusModId;
public String focusName;
public int focusMeta;
private String[] filler;
private int fillerChance;

Expand All @@ -32,6 +32,9 @@ public static void loadConfig() {
if (files != null) {
try {
for (File f : files) {
if (f.isDirectory()) {
continue;
}
BufferedReader br = new BufferedReader(new FileReader(f));
Meteor m = gson.fromJson(br, Meteor.class);
MeteorRegistry.registerMeteorParadigm(
Expand Down
Loading

0 comments on commit f9ee04c

Please sign in to comment.