Debug waypoints

Added Luck and did changes on roolChestTier for LootChest
Added possibility to have conditions on dynamic waypoints
Added intermediary waypoints even when using dynamic waypoints.
This commit is contained in:
Guillaume 2022-05-04 11:22:00 +02:00
parent c8096765b4
commit e41749135e
11 changed files with 209 additions and 77 deletions

View File

@ -1,16 +1,12 @@
package net.Indyuce.mmocore.api.load;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.loot.droptable.condition.*;
import org.bukkit.configuration.ConfigurationSection;
import net.Indyuce.mmocore.api.block.BlockType;
import net.Indyuce.mmocore.api.block.SkullBlockType;
import net.Indyuce.mmocore.api.block.VanillaBlockType;
import net.Indyuce.mmocore.loot.droptable.condition.BiomeCondition;
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
import net.Indyuce.mmocore.loot.droptable.condition.LevelCondition;
import net.Indyuce.mmocore.loot.droptable.condition.PermissionCondition;
import net.Indyuce.mmocore.loot.droptable.condition.WorldCondition;
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
import net.Indyuce.mmocore.loot.droptable.dropitem.DropTableDropItem;
import net.Indyuce.mmocore.loot.droptable.dropitem.GoldDropItem;
@ -109,6 +105,9 @@ public class DefaultMMOLoader extends MMOLoader {
@Override
public Condition loadCondition(MMOLineConfig config) {
if(config.getKey().equals("distance"))
return new DistanceCondition(config);
if (config.getKey().equals("world"))
return new WorldCondition(config);

View File

@ -459,7 +459,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
*
* @param target Target waypoint
*/
public void warp(Waypoint source, Waypoint target, CostType costType) {
public void warp(Waypoint target, double cost) {
/*
* This cooldown is only used internally to make sure the player is not
@ -467,10 +467,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
* player waypoints data
*/
setLastActivity(PlayerActivity.USE_WAYPOINT);
Validate.isTrue(source!=null||costType!=CostType.NORMAL_USE,"You must precise a source to use normal waypoint" );
final double cost = costType == CostType.DYNAMIC_USE ? target.getDynamicCost() : source.getCost(target);
giveStellium(-cost, PlayerResourceUpdateEvent.UpdateReason.USE_WAYPOINT);
new BukkitRunnable() {

View File

@ -61,6 +61,7 @@ public enum StatType {
// Utility
ADDITIONAL_EXPERIENCE,
COOLDOWN_REDUCTION,
CHANCE,
// Damage-type based stats
MAGIC_DAMAGE,

View File

@ -12,6 +12,7 @@ import net.Indyuce.mmocore.waypoint.CostType;
import net.Indyuce.mmocore.waypoint.Waypoint;
import net.Indyuce.mmocore.waypoint.WaypointOption;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
@ -21,10 +22,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
public class WaypointViewer extends EditableInventory {
public WaypointViewer() {
@ -67,8 +65,9 @@ public class WaypointViewer extends EditableInventory {
}
public class WaypointItem extends SimplePlaceholderItem<WaypointViewerInventory> {
private final SimplePlaceholderItem noWaypoint, locked,notLinked,notDynamic;
private final WaypointItemHandler availWaypoint,noStellium;
private final SimplePlaceholderItem noWaypoint, locked;
private final WaypointItemHandler availWaypoint, noStellium, notLinked, notDynamic, currentWayPoint;
public WaypointItem(ConfigurationSection config) {
super(Material.BARRIER, config);
@ -77,15 +76,18 @@ public class WaypointViewer extends EditableInventory {
Validate.notNull(config.getConfigurationSection("locked"), "Could not load 'locked' config");
Validate.notNull(config.getConfigurationSection("not-a-destination"), "Could not load 'not-a-destination' config");
Validate.notNull(config.getConfigurationSection("not-dynamic"), "Could not load 'not-dynamic' config");
Validate.notNull(config.getConfigurationSection("current-waypoint"), "Could not load 'current-waypoint' config");
Validate.notNull(config.getConfigurationSection("not-enough-stellium"), "Could not load 'not-enough-stellium' config");
Validate.notNull(config.getConfigurationSection("display"), "Could not load 'display' config");
noWaypoint = new SimplePlaceholderItem(config.getConfigurationSection("no-waypoint"));
locked = new SimplePlaceholderItem(config.getConfigurationSection("locked"));
notLinked = new SimplePlaceholderItem(config.getConfigurationSection("not-a-destination"));
notDynamic = new SimplePlaceholderItem(config.getConfigurationSection("not-dynamic"));
noStellium = new WaypointItemHandler(config.getConfigurationSection("not-enough-stellium"));
availWaypoint = new WaypointItemHandler(config.getConfigurationSection("display"));
notLinked = new WaypointItemHandler(config.getConfigurationSection("not-a-destination"), true);
notDynamic = new WaypointItemHandler(config.getConfigurationSection("not-dynamic"), true);
currentWayPoint = new WaypointItemHandler(config.getConfigurationSection("current-waypoint"), true);
noStellium = new WaypointItemHandler(config.getConfigurationSection("not-enough-stellium"), false);
availWaypoint = new WaypointItemHandler(config.getConfigurationSection("display"), false);
}
@Override
@ -102,6 +104,10 @@ public class WaypointViewer extends EditableInventory {
// Locked waypoint?
Waypoint waypoint = inv.waypoints.get(index);
if (inv.current != null && inv.current.equals(waypoint))
return currentWayPoint.display(inv, n);
if (!inv.getPlayerData().hasWaypoint(waypoint))
return locked.display(inv, n);
@ -109,17 +115,13 @@ public class WaypointViewer extends EditableInventory {
if (inv.current != null && !inv.paths.containsKey(waypoint))
return notLinked.display(inv, n);
// Not dynamic waypoint
if (inv.current == null && !waypoint.hasOption(WaypointOption.DYNAMIC))
if (inv.current == null && !inv.paths.containsKey(waypoint))
return notDynamic.display(inv, n);
//Dynamic waypoint
if (waypoint.hasOption(WaypointOption.DYNAMIC) && inv.current == null && waypoint.getDynamicCost() > inv.getPlayerData().getStellium())
return noStellium.display(inv, n);
//Normal cost
if (inv.current != null && inv.paths.get(waypoint).getCost() > inv.getPlayerData().getStellium())
if (inv.paths.get(waypoint).getCost() > inv.getPlayerData().getStellium())
return noStellium.display(inv, n);
@ -128,8 +130,11 @@ public class WaypointViewer extends EditableInventory {
}
public class WaypointItemHandler extends InventoryItem<WaypointViewerInventory> {
public WaypointItemHandler(ConfigurationSection config) {
private final boolean onlyName;
public WaypointItemHandler(ConfigurationSection config, boolean onlyName) {
super(config);
this.onlyName = onlyName;
}
@Override
@ -151,10 +156,12 @@ public class WaypointViewer extends EditableInventory {
Waypoint waypoint = inv.waypoints.get(inv.page * inv.getByFunction("waypoint").getSlots().size() + n);
holders.register("name", waypoint.getName());
holders.register("current_cost", decimal.format(inv.waypointCostType.equals(CostType.DYNAMIC_USE) ? waypoint.getDynamicCost() : inv.paths.get(waypoint).getCost()));
holders.register("normal_cost", decimal.format(inv.paths.get(waypoint).getCost()));
holders.register("dynamic_cost", decimal.format(waypoint.getDynamicCost()));
holders.register("intermediary_waypoints", inv.paths.get(waypoint).displayIntermediaryWayPoints());
if (!onlyName) {
holders.register("current_cost",inv.paths.get(waypoint).getCost());
holders.register("normal_cost", decimal.format(inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).getCost() : Double.POSITIVE_INFINITY));
holders.register("dynamic_cost", decimal.format(waypoint.getDynamicCost()));
holders.register("intermediary_waypoints", inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).displayIntermediaryWayPoints(inv.waypointCostType.equals(CostType.DYNAMIC_USE)) : "none");
}
return holders;
}
@ -176,6 +183,23 @@ public class WaypointViewer extends EditableInventory {
for (Waypoint.PathInfo pathInfo : current.getAllPath())
paths.put(pathInfo.getFinalWaypoint(), pathInfo);
}
if (current == null) {
//We first check all the dynamic waypoints
for (Waypoint waypoint : waypoints) {
if (waypoint.canHaveDynamicUse(playerData.getPlayer()))
paths.put(waypoint,new Waypoint.PathInfo(waypoint, waypoint.getDynamicCost()));
}
//Iterate through all the dynamic points and find all the points it is linked to and the path
HashSet<Waypoint> waypointSet = new HashSet<>(paths.keySet());
for (Waypoint source : waypointSet) {
for (Waypoint.PathInfo target : source.getAllPath()) {
if (!paths.containsKey(target.getFinalWaypoint()) || paths.get(target.getFinalWaypoint()).getCost() > target.getCost()) {
paths.put(target.getFinalWaypoint(), target);
}
}
}
}
this.waypointCostType = current == null ? CostType.DYNAMIC_USE : CostType.NORMAL_USE;
}
@ -201,7 +225,8 @@ public class WaypointViewer extends EditableInventory {
if (item.getFunction().equals("waypoint")) {
PersistentDataContainer container = event.getCurrentItem().getItemMeta().getPersistentDataContainer();
String tag = container.get(new NamespacedKey(MMOCore.plugin, "wayPointId"), PersistentDataType.STRING);
String tag = container.has(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) ?
container.get(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) : "";
if (tag.equals(""))
return;
@ -220,20 +245,20 @@ public class WaypointViewer extends EditableInventory {
}
// Waypoint does not have target as destination
if (current != null && current.getPath(waypoint)==null) {
if (current != null && current.getPath(waypoint) == null) {
MMOCore.plugin.configManager.getSimpleMessage("cannot-teleport-to").send(player);
return;
}
// Not dynamic waypoint
if (current == null && !waypoint.hasOption(WaypointOption.DYNAMIC)) {
if (current == null && !paths.containsKey(waypoint)) {
MMOCore.plugin.configManager.getSimpleMessage("not-dynamic-waypoint").send(player);
return;
}
// Stellium cost
CostType costType = current == null ? CostType.DYNAMIC_USE : CostType.NORMAL_USE;
double withdraw = current == null ? waypoint.getDynamicCost() : paths.get(waypoint).getCost();
double withdraw = paths.get(waypoint).getCost();
double left = withdraw - playerData.getStellium();
if (left > 0) {
MMOCore.plugin.configManager.getSimpleMessage("not-enough-stellium", "more", decimal.format(left)).send(player);
@ -244,10 +269,7 @@ public class WaypointViewer extends EditableInventory {
return;
player.closeInventory();
if (current == null)
playerData.warp(null, waypoint, costType);
else
playerData.warp(current, waypoint, costType);
playerData.warp(waypoint, withdraw);
}
}

View File

@ -4,6 +4,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.LootChestSpawnEvent;
import net.Indyuce.mmocore.api.player.PlayerActivity;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.loot.LootBuilder;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
@ -85,7 +86,7 @@ public class LootChestRegion {
player.setLastActivity(PlayerActivity.LOOT_CHEST_SPAWN);
// First randomly determine the chest tier
ChestTier tier = rollTier();
ChestTier tier = rollTier(player);
// Find a random location, 20 trials max
Location location = getRandomLocation(player.getPlayer().getLocation());
@ -116,14 +117,22 @@ public class LootChestRegion {
MMOCore.plugin.lootChests.register(lootChest);
}
// TODO stat to increase chance to get higher tiers?
public ChestTier rollTier() {
public ChestTier rollTier(PlayerData player) {
double chance = player.getStats().getStat(StatType.CHANCE);
double s = 0;
//chance=0 ->the tier.chance remains the same
//chance ->+inf -> the tier.chance becomes the same for everyone, uniform law
//chance=8-> tierChance=sqrt(tierChance)
double sum = 0;
for (ChestTier tier : tiers) {
if (random.nextDouble() < tier.chance / (1 - s))
sum += Math.pow(tier.chance, 1 / Math.pow((1 + chance),1/3));
}
double s=0;
for (ChestTier tier : tiers) {
s+=Math.pow(tier.chance, 1 / Math.pow((1 + chance),1/3))/sum;
if (random.nextDouble() < s)
return tier;
s += tier.chance;
}
return tiers.stream().findAny().orElse(null);

View File

@ -0,0 +1,39 @@
package net.Indyuce.mmocore.loot.droptable.condition;
import io.lumine.mythic.lib.api.MMOLineConfig;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.generator.WorldInfo;
import java.util.stream.Collectors;
public class DistanceCondition extends Condition{
private final Location location;
private final double distance;
public DistanceCondition(MMOLineConfig config) {
super(config);
Validate.isTrue(config.contains("world"));
Validate.isTrue(config.contains("x"));
Validate.isTrue(config.contains("y"));
Validate.isTrue(config.contains("z"));
Validate.isTrue(config.contains("distance"));
Validate.isTrue(Bukkit.getWorld(config.getString("world"))!=null,"This world doesn't exist");
location=new Location(Bukkit.getWorld(config.getString("world")),config.getDouble("x"),
config.getDouble("y"),config.getDouble("z"));
distance=config.getDouble("distance");
}
@Override
public boolean isMet(ConditionInstance entity) {
Entity entity1=entity.getEntity();
return entity1.getWorld().equals(location.getWorld())&&location.distance(entity1.getLocation())<distance;
}
}

View File

@ -1,8 +1,12 @@
package net.Indyuce.mmocore.waypoint;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
import net.Indyuce.mmocore.player.Unlockable;
import org.apache.commons.lang.Validate;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@ -11,6 +15,7 @@ import org.bukkit.craftbukkit.libs.jline.internal.Nullable;
import org.bukkit.entity.Player;
import java.util.*;
import java.util.logging.Level;
public class Waypoint implements Unlockable {
private final String id, name;
@ -33,7 +38,9 @@ public class Waypoint implements Unlockable {
/**
* Stellium cost for each action (0 being the default cost)
*/
private final double dynamicCost,setSpawnCost;
private final double dynamicCost, setSpawnCost;
private final ArrayList<Condition> dynamicUseConditions = new ArrayList<>();
private final Map<CostType, Double> costs = new HashMap<>();
public double getDynamicCost() {
@ -55,21 +62,39 @@ public class Waypoint implements Unlockable {
loc = readLocation(Objects.requireNonNull(config.getString("location"), "Could not read location"));
radiusSquared = Math.pow(config.getDouble("radius"), 2);
dynamicCost=config.getDouble("cost.dynamic-use");
setSpawnCost=config.getDouble("cost.set-spawnpoint");
dynamicCost = config.getDouble("cost.dynamic-use");
setSpawnCost = config.getDouble("cost.set-spawnpoint");
for (WaypointOption option : WaypointOption.values())
options.put(option, config.getBoolean("option." + option.getPath(), option.getDefaultValue()));
//We load all the linked WayPoints
ConfigurationSection section=config.getConfigurationSection("linked");
for(String key: section.getKeys(false)) {
destinations.put(key,config.getInt(key));
if (config.contains("linked")) {
ConfigurationSection section = config.getConfigurationSection("linked");
for (String key : section.getKeys(false)) {
destinations.put(key, section.getInt(key));
}
}
if (config.contains("conditions")) {
List<String> conditions = config.getStringList("conditions");
for (String condition : conditions) {
dynamicUseConditions.add(MMOCore.plugin.loadManager.loadCondition(new MMOLineConfig(condition)));
}
//destinations.addAll(config.getStringList("linked"));
}
}
public boolean canHaveDynamicUse(Player player) {
if (!options.get(WaypointOption.DYNAMIC))
return false;
for (Condition condition : dynamicUseConditions) {
if (!condition.isMet(new ConditionInstance(player)))
return false;
}
return true;
}
public String getId() {
@ -149,7 +174,7 @@ public class Waypoint implements Unlockable {
paths.add(checked);
checkedPoints.add(checked.getFinalWaypoint());
if(checked.getFinalWaypoint().equals(targetWaypoint))
if (checked.getFinalWaypoint().equals(targetWaypoint))
return checked;
for (String wayPointId : checked.getFinalWaypoint().destinations.keySet()) {
@ -213,7 +238,7 @@ public class Waypoint implements Unlockable {
return new Location(world, x, y, z, yaw, pitch);
}
public class PathInfo {
public static class PathInfo {
private final ArrayList<Waypoint> waypoints;
private final double cost;
@ -226,10 +251,15 @@ public class Waypoint implements Unlockable {
}
public PathInfo(Waypoint waypoint) {
this.waypoints = (ArrayList<Waypoint>) Arrays.asList(waypoint);
this.waypoints = new ArrayList<>();
this.waypoints.add(waypoint);
cost = 0;
}
public PathInfo(Waypoint waypoint,double cost) {
this.waypoints = new ArrayList<>();
this.waypoints.add(waypoint);
this.cost = cost;
}
public ArrayList<PathInfo> addInOrder(ArrayList<PathInfo> pathInfos) {
int index = 0;
@ -238,6 +268,7 @@ public class Waypoint implements Unlockable {
pathInfos.set(index, this);
return pathInfos;
}
index++;
}
//If index==pathInfos.size() we add the waypoint at the end
pathInfos.add(this);
@ -245,29 +276,43 @@ public class Waypoint implements Unlockable {
}
public PathInfo(ArrayList<Waypoint> waypoints, double cost) {
this.waypoints = waypoints;
public PathInfo(List<Waypoint> waypoints, double cost) {
this.waypoints = new ArrayList<>(waypoints);
this.cost = cost;
}
public String displayIntermediaryWayPoints() {
if(waypoints.size()<=2)
return "";
String result="";
for(int i=1;i<waypoints.size()-1;i++) {
result+=waypoints.get(i).name+(i!=waypoints.size()-2?",":"");
/**
*
* @param dynamic We display the first waypoint if it is dynamic as it is an intermediary point
* @return
*/
public String displayIntermediaryWayPoints(boolean dynamic) {
String result = "";
if(!dynamic) {
if (waypoints.size() <= 2)
return "none";
for (int i = 1; i < waypoints.size() - 1; i++) {
result += waypoints.get(i).name + (i != waypoints.size() - 2 ? "," : "");
}
}
if(dynamic) {
if (waypoints.size() <= 1)
return "none";
for (int i = 0; i < waypoints.size() - 1; i++) {
result += waypoints.get(i).name + (i != waypoints.size() - 2 ? "," : "");
}
}
return result;
}
}
public PathInfo addWayPoint(Waypoint waypoint) {
Validate.isTrue(!waypoints.contains(waypoint), "You can't create cyclic path");
ArrayList<Waypoint> newWaypoints = new ArrayList<>();
newWaypoints.addAll(waypoints);
newWaypoints.add(waypoint);
double cost=this.cost+getFinalWaypoint().getSimpleCostDestination(waypoint);
return new PathInfo(newWaypoints,cost);
double cost = this.cost + getFinalWaypoint().getSimpleCostDestination(waypoint);
return new PathInfo(newWaypoints, cost);
}

View File

@ -45,6 +45,13 @@ items:
- '&7You cannot teleport as you are not standing on a waypoint.'
current-waypoint:
name: '&a{name}'
item: ENDER_PEARL
lore:
- '&7The waypoint you are standing at.'
# When you don't have enough stellium
not-enough-stellium:
name: '&a{name}'
@ -61,7 +68,7 @@ items:
lore:
- '&7You can teleport to this waypoint.'
- '&7 Intermediary waypoints : {intermediary_waypoints}'
- '&7Intermediary waypoints : {intermediary_waypoints}'
- '&7Click to teleport for &b{current_cost} &7Stellium.'
next:

View File

@ -22,7 +22,7 @@ exp-sources: {}
on-fish:
overriding-drop-table:
conditions:
- 'region{name=swamp}'
- 'biome{name=swamp}'
# When drop table is read, one of these
# items will be selected randomly.

View File

@ -58,6 +58,11 @@ default:
COOLDOWN_REDUCTION:
base: 0
per-level: 0
#Increases chance to have rare loot chests
CHANCE:
base: 0
per-level: 0
# Dealt by skills
SKILL_DAMAGE:

View File

@ -17,8 +17,6 @@ spawn:
# Stellium cost in order to use the waypoint.
# Stellium is like stamina however it's not used
# by skills and regens much slower than mana.
normal-use: 3
# Cost when not standing on any waypoint.
dynamic-use: 5
@ -42,12 +40,12 @@ spawn:
default: true
# All the waypoints you can teleport to when standing
# on that waypoint. If that list is empty you are able
# on that waypoint. And the cost needed to travel to his pointIf that list is empty you are able
# to teleport to any waypoint
linked:
- spawn1
- spawn2
- forest
spawn1: 4
spawn2: 5
spawn1:
name: Spawn1
@ -62,6 +60,15 @@ spawn1:
# on any waypoint (waypoint must be unlocked).
dynamic: true
##Not necessary if the waypoint doesn't allow dynamic use
##The conditions for the dynamic-use of the waypoint
conditions:
- 'distance{world=world;x=69;y=71;z=163;distance=500}'
linked:
spawn: 4
spawn2:
name: Spawn2
location: 'world 69 71 136 136 0'
@ -70,3 +77,5 @@ spawn2:
normal-use: 3
option:
enable-menu: false
linked:
spawn: 3