2024-08-23 14:12:59 -04:00
|
|
|
package noppes.npcs.controllers;
|
|
|
|
|
|
2025-02-03 16:59:06 -05:00
|
|
|
import net.minecraft.item.ItemStack;
|
2024-08-23 14:12:59 -04:00
|
|
|
import net.minecraft.nbt.CompressedStreamTools;
|
|
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
|
|
|
import net.minecraft.nbt.NBTTagList;
|
|
|
|
|
import noppes.npcs.CustomNpcs;
|
|
|
|
|
import noppes.npcs.LogWriter;
|
|
|
|
|
import noppes.npcs.api.handler.data.IMagic;
|
|
|
|
|
import noppes.npcs.controllers.data.Magic;
|
|
|
|
|
|
|
|
|
|
import java.io.*;
|
2025-02-03 16:59:06 -05:00
|
|
|
import java.util.*;
|
2024-08-23 14:12:59 -04:00
|
|
|
import java.util.zip.GZIPInputStream;
|
|
|
|
|
|
|
|
|
|
public class MagicController {
|
2025-02-03 16:59:06 -05:00
|
|
|
public HashMap<Integer, Magic> magicSync = new HashMap<Integer, Magic>();
|
|
|
|
|
public HashMap<Integer, Magic> magics;
|
2024-08-23 14:12:59 -04:00
|
|
|
|
2025-02-03 16:59:06 -05:00
|
|
|
private static MagicController instance;
|
2024-08-23 14:12:59 -04:00
|
|
|
|
2025-02-03 16:59:06 -05:00
|
|
|
private int lastUsedID = 0;
|
2024-08-23 14:12:59 -04:00
|
|
|
|
2025-02-03 16:59:06 -05:00
|
|
|
public MagicController() {
|
|
|
|
|
instance = this;
|
|
|
|
|
magics = new HashMap<Integer, Magic>();
|
|
|
|
|
}
|
2024-08-23 14:12:59 -04:00
|
|
|
|
2025-02-03 16:59:06 -05:00
|
|
|
public static MagicController getInstance() {
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
2024-08-23 14:12:59 -04:00
|
|
|
|
2025-02-03 16:59:06 -05:00
|
|
|
public Magic getMagic(int magic) {
|
|
|
|
|
return magics.get(magic);
|
|
|
|
|
}
|
2024-08-23 14:12:59 -04:00
|
|
|
|
2025-02-03 16:59:06 -05:00
|
|
|
public void load() {
|
2024-08-23 14:12:59 -04:00
|
|
|
magics = new HashMap<Integer, Magic>();
|
|
|
|
|
lastUsedID = 0;
|
2025-02-03 16:59:06 -05:00
|
|
|
File saveDir = CustomNpcs.getWorldSaveDirectory();
|
|
|
|
|
if (saveDir == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
File file = new File(saveDir, "magic.dat");
|
|
|
|
|
if (file.exists()) {
|
|
|
|
|
loadMagicFile(file);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
try {
|
|
|
|
|
File file = new File(saveDir, "magic.dat_old");
|
|
|
|
|
if (file.exists()) {
|
|
|
|
|
loadMagicFile(file);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception ee) { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (magics.isEmpty()) {
|
|
|
|
|
// Create default magics
|
|
|
|
|
Magic nature = new Magic(0, "Nature", 0x00DD00);
|
|
|
|
|
Magic arcane = new Magic(1, "Arcane", 0xF2DD00);
|
|
|
|
|
Magic ice = new Magic(2, "Ice", 0xDD0000);
|
|
|
|
|
Magic fire = new Magic(3, "Fire", 0xDD0000);
|
|
|
|
|
Magic dark = new Magic(4, "Dark", 0xDD0000);
|
|
|
|
|
Magic holy = new Magic(5, "Holy", 0xDD0000);
|
|
|
|
|
|
|
|
|
|
// Define weaknesses (extra damage percentages as fractions)
|
|
|
|
|
// Cycle: Nature -> Arcane -> Fire -> Ice -> Nature
|
|
|
|
|
nature.weaknesses.put(1, 0.20f); // Nature is weak to Arcane (20% extra damage)
|
|
|
|
|
arcane.weaknesses.put(3, 0.25f); // Arcane is weak to Fire (25%)
|
|
|
|
|
fire.weaknesses.put(2, 0.30f); // Fire is weak to Ice (30%)
|
|
|
|
|
ice.weaknesses.put(0, 0.20f); // Ice is weak to Nature (20%)
|
|
|
|
|
|
|
|
|
|
// Dark and Holy are opposites
|
|
|
|
|
dark.weaknesses.put(5, 0.40f); // Dark is weak to Holy (40%)
|
|
|
|
|
holy.weaknesses.put(4, 0.40f); // Holy is weak to Dark (40%)
|
|
|
|
|
|
|
|
|
|
// Add them to the registry
|
|
|
|
|
magics.put(nature.id, nature);
|
|
|
|
|
magics.put(arcane.id, arcane);
|
|
|
|
|
magics.put(ice.id, ice);
|
|
|
|
|
magics.put(fire.id, fire);
|
|
|
|
|
magics.put(dark.id, dark);
|
|
|
|
|
magics.put(holy.id, holy);
|
|
|
|
|
}
|
|
|
|
|
printAllMagicInteractions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void loadMagicFile(File file) throws IOException {
|
|
|
|
|
DataInputStream stream = new DataInputStream(
|
|
|
|
|
new BufferedInputStream(new GZIPInputStream(new FileInputStream(file)))
|
|
|
|
|
);
|
|
|
|
|
loadMagic(stream);
|
|
|
|
|
stream.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void loadMagic(DataInputStream stream) throws IOException {
|
|
|
|
|
HashMap<Integer, Magic> magic = new HashMap<Integer, Magic>();
|
|
|
|
|
NBTTagCompound nbttagcompound1 = CompressedStreamTools.read(stream);
|
|
|
|
|
lastUsedID = nbttagcompound1.getInteger("lastID");
|
|
|
|
|
NBTTagList list = nbttagcompound1.getTagList("NPCMagic", 10); // using "NPCMagic" as tag
|
|
|
|
|
|
|
|
|
|
if (list != null) {
|
|
|
|
|
for (int i = 0; i < list.tagCount(); i++) {
|
|
|
|
|
NBTTagCompound nbttagcompound = list.getCompoundTagAt(i);
|
|
|
|
|
Magic loadMagic = new Magic();
|
|
|
|
|
loadMagic.readNBT(nbttagcompound);
|
|
|
|
|
magic.put(loadMagic.id, loadMagic);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.magics = magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public NBTTagCompound getNBT() {
|
|
|
|
|
NBTTagList list = new NBTTagList();
|
|
|
|
|
for (int slot : magics.keySet()) {
|
|
|
|
|
Magic mag = magics.get(slot);
|
|
|
|
|
NBTTagCompound nbtMagic = new NBTTagCompound();
|
|
|
|
|
mag.writeNBT(nbtMagic);
|
|
|
|
|
list.appendTag(nbtMagic);
|
|
|
|
|
}
|
|
|
|
|
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
|
|
|
|
nbttagcompound.setInteger("lastID", lastUsedID);
|
|
|
|
|
nbttagcompound.setTag("NPCMagic", list); // use same tag as loadMagic
|
|
|
|
|
return nbttagcompound;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void saveFactions() {
|
|
|
|
|
try {
|
|
|
|
|
File saveDir = CustomNpcs.getWorldSaveDirectory();
|
|
|
|
|
File file = new File(saveDir, "magic.dat_new");
|
|
|
|
|
File file1 = new File(saveDir, "magic.dat_old");
|
|
|
|
|
File file2 = new File(saveDir, "magic.dat");
|
|
|
|
|
CompressedStreamTools.writeCompressed(getNBT(), new FileOutputStream(file));
|
|
|
|
|
if (file1.exists()) {
|
|
|
|
|
file1.delete();
|
|
|
|
|
}
|
|
|
|
|
file2.renameTo(file1);
|
|
|
|
|
if (file2.exists()) {
|
|
|
|
|
file2.delete();
|
|
|
|
|
}
|
|
|
|
|
file.renameTo(file2);
|
|
|
|
|
if (file.exists()) {
|
|
|
|
|
file.delete();
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogWriter.except(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Magic get(int magicID) {
|
|
|
|
|
return magics.get(magicID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<IMagic> list() {
|
|
|
|
|
return new ArrayList<IMagic>(this.magics.values());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void saveMagic(Magic mag) {
|
|
|
|
|
if (mag.id < 0) {
|
|
|
|
|
mag.id = getUnusedId();
|
|
|
|
|
while (hasName(mag.name))
|
|
|
|
|
mag.name += "_";
|
|
|
|
|
} else {
|
|
|
|
|
Magic existing = magics.get(mag.id);
|
|
|
|
|
if (existing != null && !existing.name.equals(mag.name))
|
|
|
|
|
while (hasName(mag.name))
|
|
|
|
|
mag.name += "_";
|
|
|
|
|
}
|
|
|
|
|
magics.remove(mag.id);
|
|
|
|
|
magics.put(mag.id, mag);
|
2024-08-23 14:12:59 -04:00
|
|
|
|
|
|
|
|
NBTTagCompound facCompound = new NBTTagCompound();
|
|
|
|
|
mag.writeNBT(facCompound);
|
2025-01-29 18:25:34 -05:00
|
|
|
// Server.sendToAll(EnumPacketClient.SYNC_UPDATE, SyncType.MAGIC, facCompound);
|
2025-02-03 16:59:06 -05:00
|
|
|
saveFactions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getUnusedId() {
|
|
|
|
|
if (lastUsedID == 0) {
|
|
|
|
|
for (int catid : magics.keySet())
|
|
|
|
|
if (catid > lastUsedID)
|
|
|
|
|
lastUsedID = catid;
|
|
|
|
|
}
|
|
|
|
|
lastUsedID++;
|
|
|
|
|
return lastUsedID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean hasName(String newName) {
|
|
|
|
|
if (newName.trim().isEmpty())
|
|
|
|
|
return true;
|
|
|
|
|
for (Magic mag : magics.values())
|
|
|
|
|
if (mag.name.equals(newName))
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Magic getMagicFromName(String magicName) {
|
|
|
|
|
for (Map.Entry<Integer, Magic> entryMag : MagicController.getInstance().magics.entrySet()) {
|
|
|
|
|
if (entryMag.getValue().name.equalsIgnoreCase(magicName)) {
|
|
|
|
|
return entryMag.getValue();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String[] getNames() {
|
|
|
|
|
String[] names = new String[magics.size()];
|
|
|
|
|
int i = 0;
|
|
|
|
|
for (Magic mag : magics.values()) {
|
|
|
|
|
names[i] = mag.name.toLowerCase();
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
return names;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- New functions for applying magic NBT stats and calculating damage ---
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Applies magic-type damage to an item. A weapon/item can have multiple magic damage values.
|
|
|
|
|
* The damage is stored under a compound tag "MagicDamage" where each key is the magic ID.
|
|
|
|
|
*/
|
|
|
|
|
public static void addMagicDamageToItem(ItemStack item, int magicId, float damage) {
|
|
|
|
|
if (item == null) return;
|
|
|
|
|
if (item.stackTagCompound == null)
|
|
|
|
|
item.stackTagCompound = new NBTTagCompound();
|
|
|
|
|
NBTTagCompound compound = item.stackTagCompound;
|
|
|
|
|
NBTTagCompound magicDamage;
|
|
|
|
|
if (compound.hasKey("MagicDamage")) {
|
|
|
|
|
magicDamage = compound.getCompoundTag("MagicDamage");
|
|
|
|
|
} else {
|
|
|
|
|
magicDamage = new NBTTagCompound();
|
|
|
|
|
}
|
|
|
|
|
magicDamage.setFloat(String.valueOf(magicId), damage);
|
|
|
|
|
compound.setTag("MagicDamage", magicDamage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Applies magic resistance to an armor piece.
|
|
|
|
|
* The resistance is stored under a compound tag "MagicResistances" with the magic ID as key.
|
|
|
|
|
*/
|
|
|
|
|
public static void addMagicResistanceToArmor(ItemStack armor, int magicId, float resistance) {
|
|
|
|
|
if (armor == null) return;
|
|
|
|
|
if (armor.stackTagCompound == null)
|
|
|
|
|
armor.stackTagCompound = new NBTTagCompound();
|
|
|
|
|
NBTTagCompound compound = armor.stackTagCompound;
|
|
|
|
|
NBTTagCompound magicResist;
|
|
|
|
|
if (compound.hasKey("MagicResistances")) {
|
|
|
|
|
magicResist = compound.getCompoundTag("MagicResistances");
|
|
|
|
|
} else {
|
|
|
|
|
magicResist = new NBTTagCompound();
|
|
|
|
|
}
|
|
|
|
|
magicResist.setFloat(String.valueOf(magicId), resistance);
|
|
|
|
|
compound.setTag("MagicResistances", magicResist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Given a collection of armor pieces, sums the resistance value for the specified magic ID.
|
|
|
|
|
*/
|
|
|
|
|
public static float calculateTotalMagicResistance(int magicId, Iterable<ItemStack> armors) {
|
|
|
|
|
float totalResistance = 0.0F;
|
|
|
|
|
for (ItemStack armor : armors) {
|
|
|
|
|
if (armor != null && armor.hasTagCompound() && armor.stackTagCompound.hasKey("MagicResistances")) {
|
|
|
|
|
NBTTagCompound magicResist = armor.stackTagCompound.getCompoundTag("MagicResistances");
|
|
|
|
|
if (magicResist.hasKey(String.valueOf(magicId))) {
|
|
|
|
|
totalResistance += magicResist.getFloat(String.valueOf(magicId));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return totalResistance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Calculates the final magic damage after applying armor resistances.
|
|
|
|
|
* For a given magic type, the resistance is applied.
|
|
|
|
|
*
|
|
|
|
|
* @param magicId the magic type
|
|
|
|
|
* @param baseDamage the base damage value
|
|
|
|
|
* @param armors an Iterable collection of armor ItemStacks
|
|
|
|
|
* @return the final damage after reduction
|
|
|
|
|
*/
|
|
|
|
|
public static float calculateFinalMagicDamage(int magicId, float baseDamage, Iterable<ItemStack> armors) {
|
|
|
|
|
if (getInstance().getMagic(magicId) == null) {
|
|
|
|
|
// If the magic type is not defined, treat it as non-magical.
|
|
|
|
|
return baseDamage;
|
|
|
|
|
}
|
|
|
|
|
float resistance = calculateTotalMagicResistance(magicId, armors);
|
|
|
|
|
// Resistance is assumed to be a fractional reduction (e.g., 0.2 = 20% reduction).
|
|
|
|
|
return baseDamage * (1.0F - resistance);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Extracts magic damage values from a weapon ItemStack.
|
|
|
|
|
* It looks for a compound tag "CNPCMagic" first; if not found, it falls back to "MagicDamage".
|
|
|
|
|
* Returns a mapping of magic ID to its damage value.
|
|
|
|
|
*/
|
|
|
|
|
public static Map<Integer, Float> getMagicDamageFromItem(ItemStack item) {
|
|
|
|
|
Map<Integer, Float> damageMap = new HashMap<Integer, Float>();
|
|
|
|
|
if (item == null || item.stackTagCompound == null) return damageMap;
|
|
|
|
|
NBTTagCompound compound = item.stackTagCompound;
|
|
|
|
|
NBTTagCompound damageCompound = null;
|
|
|
|
|
if (compound.hasKey("CNPCMagic")) {
|
|
|
|
|
NBTTagCompound magicCompound = compound.getCompoundTag("CNPCMagic");
|
|
|
|
|
if (magicCompound.hasKey("MagicDamage")) {
|
|
|
|
|
damageCompound = magicCompound.getCompoundTag("MagicDamage");
|
|
|
|
|
}
|
|
|
|
|
} else if (compound.hasKey("MagicDamage")) {
|
|
|
|
|
damageCompound = compound.getCompoundTag("MagicDamage");
|
|
|
|
|
}
|
|
|
|
|
if (damageCompound != null) {
|
|
|
|
|
Set<String> keys = damageCompound.func_150296_c();
|
|
|
|
|
for (String key : keys) {
|
|
|
|
|
try {
|
|
|
|
|
int magicId = Integer.parseInt(key);
|
|
|
|
|
float dmg = damageCompound.getFloat(key);
|
|
|
|
|
damageMap.put(magicId, dmg);
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
// Ignore non-integer keys.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return damageMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Extracts magic resistances from an armor ItemStack.
|
|
|
|
|
* It checks for a "CNPCMagic" container first; if not present, it falls back to "MagicResistances".
|
|
|
|
|
* Returns a mapping of magic ID to its resistance value.
|
|
|
|
|
*/
|
|
|
|
|
public static Map<Integer, Float> getMagicResistancesFromItem(ItemStack item) {
|
|
|
|
|
Map<Integer, Float> resistMap = new HashMap<Integer, Float>();
|
|
|
|
|
if (item == null || item.stackTagCompound == null) return resistMap;
|
|
|
|
|
NBTTagCompound compound = item.stackTagCompound;
|
|
|
|
|
NBTTagCompound resistCompound = null;
|
|
|
|
|
if (compound.hasKey("CNPCMagic")) {
|
|
|
|
|
NBTTagCompound magicCompound = compound.getCompoundTag("CNPCMagic");
|
|
|
|
|
if (magicCompound.hasKey("MagicResistances")) {
|
|
|
|
|
resistCompound = magicCompound.getCompoundTag("MagicResistances");
|
|
|
|
|
}
|
|
|
|
|
} else if (compound.hasKey("MagicResistances")) {
|
|
|
|
|
resistCompound = compound.getCompoundTag("MagicResistances");
|
|
|
|
|
}
|
|
|
|
|
if (resistCompound != null) {
|
|
|
|
|
Set<String> keys = resistCompound.func_150296_c();
|
|
|
|
|
for (String key : keys) {
|
|
|
|
|
try {
|
|
|
|
|
int magicId = Integer.parseInt(key);
|
|
|
|
|
float res = resistCompound.getFloat(key);
|
|
|
|
|
resistMap.put(magicId, res);
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
// Ignore non-integer keys.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return resistMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Validates whether an item (weapon or armor) contains any magic-related NBT.
|
|
|
|
|
*/
|
|
|
|
|
public static boolean hasMagicStats(ItemStack item) {
|
|
|
|
|
if (item == null || item.stackTagCompound == null) return false;
|
|
|
|
|
NBTTagCompound compound = item.stackTagCompound;
|
|
|
|
|
return compound.hasKey("CNPCMagic") || compound.hasKey("MagicDamage") || compound.hasKey("MagicResistances");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Calculates a damage breakdown for each magic type from a weapon when applied against a set of armors.
|
|
|
|
|
* This function will ignore any magic with ID 0 (neutral), so only magic damage is returned.
|
|
|
|
|
* Returns a map where keys are magic IDs (non-zero) and values are the final damage for that type.
|
|
|
|
|
*/
|
|
|
|
|
public static Map<Integer, Float> calculateDamageBreakdown(ItemStack weapon, Iterable<ItemStack> armors) {
|
|
|
|
|
Map<Integer, Float> breakdown = new HashMap<Integer, Float>();
|
|
|
|
|
Map<Integer, Float> weaponDamage = getMagicDamageFromItem(weapon);
|
|
|
|
|
for (Map.Entry<Integer, Float> entry : weaponDamage.entrySet()) {
|
|
|
|
|
int magicId = entry.getKey();
|
|
|
|
|
// Skip magic ID 0 (neutral)
|
|
|
|
|
if (magicId == 0) continue;
|
|
|
|
|
float dmg = entry.getValue();
|
|
|
|
|
float finalDmg = calculateFinalMagicDamage(magicId, dmg, armors);
|
|
|
|
|
breakdown.put(magicId, finalDmg);
|
|
|
|
|
}
|
|
|
|
|
return breakdown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Calculates the total final magic damage of a weapon after applying the resistances of a set of armor pieces.
|
|
|
|
|
* This sums only the magic interactions (magic IDs other than 0).
|
|
|
|
|
*/
|
|
|
|
|
public static float calculateTotalDamage(ItemStack weapon, Iterable<ItemStack> armors) {
|
|
|
|
|
float totalDamage = 0.0F;
|
|
|
|
|
Map<Integer, Float> breakdown = calculateDamageBreakdown(weapon, armors);
|
|
|
|
|
for (Float dmg : breakdown.values()) {
|
|
|
|
|
totalDamage += dmg;
|
|
|
|
|
}
|
|
|
|
|
return totalDamage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Prints all magic interactions (weaknesses) in the registry.
|
|
|
|
|
* For each magic (defender) that has weaknesses, prints the corresponding attacker and the extra damage percentage.
|
|
|
|
|
* Format: "Magic ID: [attacker id], Name: "[attacker name]" does [percentage*100]% extra damage to Magic ID: [defender id], Name: "[defender name]".
|
|
|
|
|
*/
|
|
|
|
|
public static void printAllMagicInteractions() {
|
|
|
|
|
MagicController mc = getInstance();
|
|
|
|
|
for (Magic defender : mc.magics.values()) {
|
|
|
|
|
for (Map.Entry<Integer, Float> entry : defender.weaknesses.entrySet()) {
|
|
|
|
|
int attackerId = entry.getKey();
|
|
|
|
|
float percentage = entry.getValue();
|
|
|
|
|
Magic attacker = mc.getMagic(attackerId);
|
|
|
|
|
if (attacker != null) {
|
|
|
|
|
System.out.println("Magic ID: " + attacker.id + ", Name: \"" + attacker.name + "\" does "
|
|
|
|
|
+ (percentage * 100) + "% extra damage to Magic ID: " + defender.id + ", Name: \"" + defender.name + "\"");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-23 14:12:59 -04:00
|
|
|
}
|