Skip to content

Commit

Permalink
Fix difficulty system being broken.
Browse files Browse the repository at this point in the history
and: f50ecba
Fix potential crash with VampireBaron #1428
Improve Difficulty system documentation
  • Loading branch information
maxanier committed Oct 5, 2024
1 parent 304518c commit 6a16135
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,48 @@
package de.teamlapen.vampirism.api.difficulty;

import org.jetbrains.annotations.NotNull;

import static net.minecraft.util.Mth.clamp;

/**
* Represents a calculated difficulty level.
* The used difficulty levels are in percentage of the max reachable level.
* So a level 5 in a faction which has a max level of 10 would be represented by 5/10*100=50
*/
public record Difficulty(int minPercLevel, int maxPercLevel, int avgPercLevel) {
public class Difficulty {

/**
* Percentage between 0 and 100
*/
public final int minPercLevel, maxPercLevel, avgPercLevel;

public Difficulty(int mil, int mal, int al) {
mal = clamp(mal, 0, 100);
mil = clamp(mil, 0, mal);
al = clamp(al, mil, mal);
this.minPercLevel = mil;
this.maxPercLevel = mal;
this.avgPercLevel = al;
}

public int minPercLevel() {
return minPercLevel;
}

public int maxPercLevel() {
return maxPercLevel;
}

public int avgPercLevel() {
return avgPercLevel;
}

public boolean isZero() {
return (this.minPercLevel == 0 && this.maxPercLevel == 0);
}

@Override
public @NotNull String toString() {
return "Difficulty: min_" + minPercLevel + " max_" + maxPercLevel + " avg_" + avgPercLevel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public boolean doHurtTarget(@NotNull Entity entity) {
public SpawnGroupData finalizeSpawn(@NotNull ServerLevelAccessor worldIn, @NotNull DifficultyInstance difficultyIn, @NotNull MobSpawnType reason, @Nullable SpawnGroupData spawnDataIn) {
this.getEntityData().set(LADY, this.getRandom().nextBoolean());
if (reason == MobSpawnType.COMMAND || reason == MobSpawnType.SPAWN_EGG) {
this.setEntityLevel(getRandom().nextInt(getMaxEntityLevel() + 1));
// this.setEntityLevel(getRandom().nextInt(getMaxEntityLevel() + 1));
}
return super.finalizeSpawn(worldIn, difficultyIn, reason, spawnDataIn);
}
Expand Down Expand Up @@ -299,17 +299,21 @@ public boolean shouldShowName() {

@Override
public int suggestEntityLevel(@NotNull Difficulty d) {
int avg = Math.round(((d.avgPercLevel()) / 100F - 5 / 14F) / (1F - 5 / 14F) * MAX_LEVEL);
int max = Math.round(((d.maxPercLevel()) / 100F - 5 / 14F) / (1F - 5 / 14F) * MAX_LEVEL);
int min = Math.round(((d.minPercLevel()) / 100F - 5 / 14F) / (1F - 5 / 14F) * (MAX_LEVEL));

//Currently, this is not called when the entity is spawned by a command or spawn egg to guarantee a spawn-> See finalizeSpawn

//We want to distribute the baron levels between player levels 5 (from here on you need pure blood for leveling and 14 {@link de.teamlapen.vampirism.REFERENCE.HIGHEST_VAMPIRE_LEVEL}
int avg = Math.round(((d.avgPercLevel() / 100f - 5 / 14f) / (1F - 5 / 14F)) * MAX_LEVEL);
int max = Math.round(((d.maxPercLevel() / 100f - 5 / 14f) / (1F - 5 / 14F)) * MAX_LEVEL);
int min = Math.round(((d.minPercLevel() / 100f - 5 / 14f) / (1F - 5 / 14F)) * MAX_LEVEL);
//Values may be <0 leading to entity spawn being canceled
LogManager.getLogger().warn("Level " + avg + " / " + max + " / " + min + " / " + d.maxPercLevel());
return switch (random.nextInt(7)) {
case 0 -> min;
case 1 -> max + 1;
case 2 -> avg;
case 3 -> avg + 1;
case 4, 5 -> random.nextInt(MAX_LEVEL + 1);
default -> random.nextInt(max + 2 - min) + min;
default -> random.nextInt(max - min + 2) + min; //Even if values are negative max> min -> argument is >=2)
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import java.util.List;

/**
* Calculates a (local) difficulity based on the player faction levels
* Calculates a (local) difficulty based on the player faction levels
*/
public class DifficultyCalculator {

/**
* Can be null if no players are found
* Can be null if no alive players are found
*
* @return a difficulty level based on the given player's faction levels
*/
Expand All @@ -31,15 +31,17 @@ Difficulty calculateDifficulty(@Nullable List<? extends Player> playerList) {
int min = Integer.MAX_VALUE;
int max = 0;
int sum = 0;
int playerCount = 0;
for (Player p : playerList) {
if (!p.isAlive()) continue;
playerCount++;
FactionPlayerHandler handler = FactionPlayerHandler.get(p);
int pLevel = handler.getCurrentLevel();
if (pLevel == 0) {
min = 0;
continue;
}
int level = (int) (pLevel / (float) handler.getCurrentFaction().getHighestReachableLevel());
int level = Math.round(pLevel / (float) handler.getCurrentFaction().getHighestReachableLevel() * 100F);
if (level < min) {
min = level;
}
Expand All @@ -48,7 +50,11 @@ Difficulty calculateDifficulty(@Nullable List<? extends Player> playerList) {
}
sum += max;
}
return new Difficulty(min, max, Math.round(sum / (float) playerList.size()));
//Careful, if no player is alive `min` may still be Integer.MAX_VALUE and playerCount is 0
if (playerCount == 0) {
return null;
}
return new Difficulty(min, max, Math.round(sum / (float) playerCount));
}

/**
Expand Down

0 comments on commit 6a16135

Please sign in to comment.