Noticias:

Debes de estar registrado para poder ver el contenido indicado. Registrate o Conectate

Menú Principal

Advanced Champion Mod

Iniciado por Swarlog, Ago 31, 2022, 08:41 PM

Tema anterior - Siguiente tema

Swarlog

Index: dist/game/config/L2JMods.properties
===================================================================
--- dist/game/config/L2JMods.properties (revision 6306)
+++ dist/game/config/L2JMods.properties (working copy)
@@ -14,47 +14,13 @@
 # To set all champion mobs to Passive, set True.
 ChampionPassive = False
 
-# % chance for a mob to became champion (0 to disable).
-ChampionFrequency = 5
-
-# Title of all Champion Mobs.
-ChampionTitle = Champion
-
-# Min and max levels allowed for a mob to be a Champion mob.
-ChampionMinLevel = 20
-ChampionMaxLevel = 70
-
-# Hp multiplier for Champion mobs.
-ChampionHp = 8
-
-# Hp Regen Multiplier for Champion mobs.
-ChampionHpRegen = 1.0
-
-# Standard rewards multiplier for Champion mobs.
-ChampionRewards = 8
-
-# Adena & Seal Stone rewards multiplier for Champion mobs.
-ChampionAdenasRewards = 1.0
-
-# P. Attack and M. Attack bonus for Champion mobs.
-ChampionAtk = 1.0
-
-# Physical/Magical Attack Speed bonus for Champion mobs.
-ChampionSpdAtk = 1.0
-
-# Specified reward item ID
-ChampionRewardItemID = 6393
-
-# The amount of the specified reward a player will receive if they are awarded the item.
-ChampionRewardItemQty = 1
-
 # % Chance to obtain a specified reward item from a higher level Champion mob.
 # Default: 0
 ChampionRewardLowerLvlItemChance = 0
 
-# % Chance to obtain a specified reward item from a lower level Champion mob.
+# Allowed level difference between player and mob, when ChampionRewardLowerLvlItemChance is not applied.
 # Default: 0
-ChampionRewardHigherLvlItemChance = 0
+ChampionLvlDiffAllowed = 0
 
 # Do you want to enable the vitality calculation when killing champion mobs?
 # Be aware that it can lead to huge unbalance on your server, your rate for that mob would
Index: java/com/l2jserver/Config.java
===================================================================
--- java/com/l2jserver/Config.java (revision 6306)
+++ java/com/l2jserver/Config.java (working copy)
@@ -686,20 +686,8 @@
  // --------------------------------------------------
  public static boolean L2JMOD_CHAMPION_ENABLE;
  public static boolean L2JMOD_CHAMPION_PASSIVE;
- public static int L2JMOD_CHAMPION_FREQUENCY;
- public static String L2JMOD_CHAMP_TITLE;
- public static int L2JMOD_CHAMP_MIN_LVL;
- public static int L2JMOD_CHAMP_MAX_LVL;
- public static int L2JMOD_CHAMPION_HP;
- public static int L2JMOD_CHAMPION_REWARDS;
- public static float L2JMOD_CHAMPION_ADENAS_REWARDS;
- public static float L2JMOD_CHAMPION_HP_REGEN;
- public static float L2JMOD_CHAMPION_ATK;
- public static float L2JMOD_CHAMPION_SPD_ATK;
  public static int L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE;
- public static int L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE;
- public static int L2JMOD_CHAMPION_REWARD_ID;
- public static int L2JMOD_CHAMPION_REWARD_QTY;
+ public static int L2JMOD_CHAMPION_LVL_DIFF;
  public static boolean L2JMOD_CHAMPION_ENABLE_VITALITY;
  public static boolean L2JMOD_CHAMPION_ENABLE_IN_INSTANCES;
  public static boolean TVT_EVENT_ENABLED;
@@ -2245,20 +2233,8 @@
 
  L2JMOD_CHAMPION_ENABLE = L2JModSettings.getBoolean("ChampionEnable", false);
  L2JMOD_CHAMPION_PASSIVE = L2JModSettings.getBoolean("ChampionPassive", false);
- L2JMOD_CHAMPION_FREQUENCY = L2JModSettings.getInt("ChampionFrequency", 0);
- L2JMOD_CHAMP_TITLE = L2JModSettings.getString("ChampionTitle", "Champion");
- L2JMOD_CHAMP_MIN_LVL = L2JModSettings.getInt("ChampionMinLevel", 20);
- L2JMOD_CHAMP_MAX_LVL = L2JModSettings.getInt("ChampionMaxLevel", 60);
- L2JMOD_CHAMPION_HP = L2JModSettings.getInt("ChampionHp", 7);
- L2JMOD_CHAMPION_HP_REGEN = L2JModSettings.getFloat("ChampionHpRegen", 1);
- L2JMOD_CHAMPION_REWARDS = L2JModSettings.getInt("ChampionRewards", 8);
- L2JMOD_CHAMPION_ADENAS_REWARDS = L2JModSettings.getFloat("ChampionAdenasRewards", 1);
- L2JMOD_CHAMPION_ATK = L2JModSettings.getFloat("ChampionAtk", 1);
- L2JMOD_CHAMPION_SPD_ATK = L2JModSettings.getFloat("ChampionSpdAtk", 1);
  L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE = L2JModSettings.getInt("ChampionRewardLowerLvlItemChance", 0);
- L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE = L2JModSettings.getInt("ChampionRewardHigherLvlItemChance", 0);
- L2JMOD_CHAMPION_REWARD_ID = L2JModSettings.getInt("ChampionRewardItemID", 6393);
- L2JMOD_CHAMPION_REWARD_QTY = L2JModSettings.getInt("ChampionRewardItemQty", 1);
+ L2JMOD_CHAMPION_LVL_DIFF = L2JModSettings.getInt("ChampionLvlDiffAllowed", 0);
  L2JMOD_CHAMPION_ENABLE_VITALITY = L2JModSettings.getBoolean("ChampionEnableVitality", false);
  L2JMOD_CHAMPION_ENABLE_IN_INSTANCES = L2JModSettings.getBoolean("ChampionEnableInInstances", false);
 
@@ -3516,45 +3492,9 @@
  case "championenable":
  L2JMOD_CHAMPION_ENABLE = Boolean.parseBoolean(pValue);
  break;
- case "championfrequency":
- L2JMOD_CHAMPION_FREQUENCY = Integer.parseInt(pValue);
- break;
- case "championminlevel":
- L2JMOD_CHAMP_MIN_LVL = Integer.parseInt(pValue);
- break;
- case "championmaxlevel":
- L2JMOD_CHAMP_MAX_LVL = Integer.parseInt(pValue);
- break;
- case "championhp":
- L2JMOD_CHAMPION_HP = Integer.parseInt(pValue);
- break;
- case "championhpregen":
- L2JMOD_CHAMPION_HP_REGEN = Float.parseFloat(pValue);
- break;
- case "championrewards":
- L2JMOD_CHAMPION_REWARDS = Integer.parseInt(pValue);
- break;
- case "championadenasrewards":
- L2JMOD_CHAMPION_ADENAS_REWARDS = Float.parseFloat(pValue);
- break;
- case "championatk":
- L2JMOD_CHAMPION_ATK = Float.parseFloat(pValue);
- break;
- case "championspdatk":
- L2JMOD_CHAMPION_SPD_ATK = Float.parseFloat(pValue);
- break;
  case "championrewardlowerlvlitemchance":
  L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE = Integer.parseInt(pValue);
  break;
- case "championrewardhigherlvlitemchance":
- L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE = Integer.parseInt(pValue);
- break;
- case "championrewarditemid":
- L2JMOD_CHAMPION_REWARD_ID = Integer.parseInt(pValue);
- break;
- case "championrewarditemqty":
- L2JMOD_CHAMPION_REWARD_QTY = Integer.parseInt(pValue);
- break;
  case "championenableininstances":
  L2JMOD_CHAMPION_ENABLE_IN_INSTANCES = Boolean.parseBoolean(pValue);
  break;
Index: java/com/l2jserver/gameserver/datatables/ChampionData.java
===================================================================
--- java/com/l2jserver/gameserver/datatables/ChampionData.java (revision 0)
+++ java/com/l2jserver/gameserver/datatables/ChampionData.java (working copy)
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2004-2013 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.datatables;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import com.l2jserver.Config;
+import com.l2jserver.gameserver.engines.DocumentParser;
+import com.l2jserver.gameserver.model.L2DropData;
+import com.l2jserver.gameserver.model.StatsSet;
+import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jserver.gameserver.model.stats.Stats;
+import com.l2jserver.util.Rnd;
+
+/**
+ * This class holds the data about Champion monster parameters.
+ * @author GKR
+ */
+public final class ChampionData extends DocumentParser
+{
+ private List<StatsSet> _championData;
+ private List<Integer> _championChances;
+ private List<List<L2DropData>> _championRewards;
+
+ protected ChampionData()
+ {
+ if (Config.L2JMOD_CHAMPION_ENABLE)
+ {
+ _championData = new ArrayList<>();
+ _championChances = new ArrayList<>();
+ _championRewards = new ArrayList<>();
+ load();
+ }
+ }
+
+ /**
+ * Loads configuration data.
+ */
+ @Override
+ public void load()
+ {
+ _championData.clear();
+ _championChances.clear();
+ _championRewards.clear();
+ parseDatapackFile("data/stats/champions.xml");
+ _log.info(getClass().getSimpleName() + ": Loaded " + _championData.size() + " champion templates.");
+ }
+
+ /**
+ * Parses configuration files.
+ */
+ @Override
+ protected void parseDocument()
+ {
+ final Node list = getCurrentDocument().getFirstChild();
+
+ NamedNodeMap attrs;
+ int sumChance = 0;
+ for (Node n = list.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ StatsSet dataHolder = new StatsSet();
+ List<L2DropData> rewards = new ArrayList<>();
+ if (n.getNodeName().equals("champion"))
+ {
+ if (sumChance <= 1000000)
+ {
+ for (Node championData = n.getFirstChild(); championData != null; championData = championData.getNextSibling())
+ {
+ if (championData.getNodeName().equals("chance"))
+ {
+ int chance = (int) (Float.parseFloat(championData.getTextContent()) * 10000);
+ sumChance += chance;
+ if (sumChance <= 1000000)
+ {
+ _championChances.add(chance);
+ }
+ else
+ {
+ _log.warning(getClass().getSimpleName() + ": sum of chances is greater, than 100% - champion definition ignored");
+ break;
+ }
+ }
+ else if (championData.getNodeName().equals("reward"))
+ {
+ attrs = championData.getAttributes();
+ final int itemId = parseInteger(attrs, "id");
+ final int min = parseInteger(attrs, "min");
+ final int max = parseInteger(attrs, "max");
+ if (ItemTable.getInstance().getTemplate(itemId) != null)
+ {
+ rewards.add(new L2DropData(itemId, min, max, 0));
+ }
+ else
+ {
+ _log.warning(getClass().getSimpleName() + ": invalid item id: " + itemId);
+ }
+ }
+ else
+ {
+ dataHolder.set(championData.getNodeName(), championData.getTextContent());
+ }
+ }
+ _championData.add(dataHolder);
+ _championRewards.add(rewards);
+ }
+ else
+ {
+ _log.warning(getClass().getSimpleName() + ": sum of chances is greater, than 100% - champion definition ignored");
+ }
+ }
+ }
+ }
+
+ /**
+ * @param championType type of champion.
+ * @param name String name of multiplier.
+ * @return value of multiplier for given champion type.
+ */
+ public float getMultiplier(int championType, String name)
+ {
+ float mul;
+ if ((championType >= 0) && (championType < _championData.size()))
+ {
+ mul = _championData.get(championType).getFloat(name, 1);
+ }
+ else
+ {
+ mul = 1;
+ }
+
+ return mul;
+ }
+
+ /**
+ * @param championType type of champion.
+ * @param stat stat to calculate multiplier.
+ * @return value of multiplier for given champion type.
+ */
+ public float getMultiplier(int championType, Stats stat)
+ {
+ return getMultiplier(championType, stat.getValue());
+ }
+
+ /**
+ * @param championType type of champion
+ * @param monster monster to check
+ * @return {@code true} if given monster meeets level requirements for given type of champion
+ */
+ private boolean checkLevel(int championType, L2MonsterInstance monster)
+ {
+ boolean result;
+ if ((championType >= 0) && (championType < _championData.size()))
+ {
+ int minLvl = _championData.get(championType).getInt("minLvl", 1);
+ int maxLvl = _championData.get(championType).getInt("maxLvl", 1000);
+
+ result = (monster.getLevel() >= minLvl) && (monster.getLevel() <= maxLvl);
+ }
+ else
+ {
+ result = false;
+ }
+
+ return result;
+ }
+
+ /**
+ * @param monster monster to check
+ * @return random type of champion for given monster, based on config rules
+ */
+ public int calculateChampionType(L2MonsterInstance monster)
+ {
+ int championType = -1;
+
+ // Check, if monster meets all conditions
+ if (!monster.getTemplate().isQuestMonster() && !monster.isRaid() && !monster.isRaidMinion() && (Config.L2JMOD_CHAMPION_ENABLE_IN_INSTANCES || (monster.getInstanceId() == 0)))
+ {
+ int totalProb = 0;
+ for (int i = 0; i < _championChances.size(); i++)
+ {
+ if (!checkLevel(i, monster))
+ {
+ continue;
+ }
+
+ final int fortune = Rnd.get(1000000);
+ if ((fortune >= totalProb) && (fortune < (totalProb + _championChances.get(i))))
+ {
+ championType = i;
+ break;
+ }
+ totalProb += _championChances.get(i);
+ }
+ }
+ return championType;
+ }
+
+ /**
+ * @param championType type of champion.
+ * @return glow type for given champion type.
+ */
+ public int getGlow(int championType)
+ {
+ int teamId;
+ if ((championType >= 0) && (championType < _championData.size()))
+ {
+ teamId = _championData.get(championType).getInt("glow", 0);
+ }
+ else
+ {
+ teamId = 0;
+ }
+
+ return teamId;
+ }
+
+ /**
+ * @param championType type of champion.
+ * @return title for given champion type.
+ */
+ public String getTitle(int championType)
+ {
+ String title;
+ if ((championType >= 0) && (championType < _championData.size()))
+ {
+ title = _championData.get(championType).getString("title", "");
+ }
+ else
+ {
+ title = "";
+ }
+
+ return title;
+ }
+
+ /**
+ * @param championType type of champion.
+ * @return glow List of specific rewards for given champion type.
+ */
+ public List<L2DropData> getReward(int championType)
+ {
+ if ((championType >= 0) && (championType < _championData.size()))
+ {
+ return _championRewards.get(championType);
+ }
+
+ return null;
+ }
+
+ /**
+ * @param championType type of champion
+ * @return {@code true} if given type of champion has personal reward.
+ */
+ public boolean hasPersonalReward(int championType)
+ {
+ return ((getReward(championType) != null) && !getReward(championType).isEmpty());
+ }
+
+ public static ChampionData getInstance()
+ {
+ return SingletonHolder._instance;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final ChampionData _instance = new ChampionData();
+ }
+}
\ No newline at end of file
Index: java/com/l2jserver/gameserver/GameServer.java
===================================================================
--- java/com/l2jserver/gameserver/GameServer.java (revision 6306)
+++ java/com/l2jserver/gameserver/GameServer.java (working copy)
@@ -40,6 +40,7 @@
 import com.l2jserver.gameserver.datatables.AdminTable;
 import com.l2jserver.gameserver.datatables.ArmorSetsData;
 import com.l2jserver.gameserver.datatables.AugmentationData;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.datatables.BotReportTable;
 import com.l2jserver.gameserver.datatables.BuyListData;
 import com.l2jserver.gameserver.datatables.CategoryData;
@@ -274,6 +275,10 @@
  HerbDropTable.getInstance();
  SkillLearnData.getInstance();
  NpcTable.getInstance();
+ if (Config.L2JMOD_CHAMPION_ENABLE)
+ {
+ ChampionData.getInstance();
+ }
  WalkingManager.getInstance();
  StaticObjects.getInstance();
  ZoneManager.getInstance();
Index: java/com/l2jserver/gameserver/model/actor/L2Attackable.java
===================================================================
--- java/com/l2jserver/gameserver/model/actor/L2Attackable.java (revision 6306)
+++ java/com/l2jserver/gameserver/model/actor/L2Attackable.java (working copy)
@@ -34,6 +34,7 @@
 import com.l2jserver.gameserver.ai.L2CharacterAI;
 import com.l2jserver.gameserver.ai.L2FortSiegeGuardAI;
 import com.l2jserver.gameserver.ai.L2SiegeGuardAI;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.datatables.EventDroplist;
 import com.l2jserver.gameserver.datatables.EventDroplist.DateDrop;
 import com.l2jserver.gameserver.datatables.HerbDropTable;
@@ -80,7 +81,7 @@
 {
  private boolean _isRaid = false;
  private boolean _isRaidMinion = false;
- private boolean _champion = false;
+ private int _championType = -1;
  private final Map<L2Character, AggroInfo> _aggroList = new ConcurrentHashMap<>();
  private boolean _isReturningToSpawnPoint = false;
  private boolean _canReturnToSpawnPoint = true;
@@ -521,10 +522,10 @@
  long exp = expSp[0];
  int sp = expSp[1];
 
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion())
+ if (isChampion())
  {
- exp *= Config.L2JMOD_CHAMPION_REWARDS;
- sp *= Config.L2JMOD_CHAMPION_REWARDS;
+ exp *= ChampionData.getInstance().getMultiplier(getChampionType(), Stats.BONUS_EXP);
+ sp *= ChampionData.getInstance().getMultiplier(getChampionType(), Stats.BONUS_SP);
  }
 
  exp *= 1 - penalty;
@@ -630,10 +631,10 @@
  long exp = expSp[0];
  int sp = expSp[1];
 
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion())
+ if (isChampion())
  {
- exp *= Config.L2JMOD_CHAMPION_REWARDS;
- sp *= Config.L2JMOD_CHAMPION_REWARDS;
+ exp *= ChampionData.getInstance().getMultiplier(getChampionType(), Stats.BONUS_EXP);
+ sp *= ChampionData.getInstance().getMultiplier(getChampionType(), Stats.BONUS_SP);
  }
 
  exp *= partyMul;
@@ -1045,9 +1046,9 @@
  dropChance *= isRaid() && !isRaidMinion() ? Config.RATE_DROP_ITEMS_BY_RAID : Config.RATE_DROP_ITEMS;
  }
 
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion())
+ if (isChampion())
  {
- dropChance *= Config.L2JMOD_CHAMPION_REWARDS;
+ dropChance *= ChampionData.getInstance().getMultiplier(getChampionType(), "bonusDrop");
  }
 
  // Set our limits for chance of drop
@@ -1103,9 +1104,9 @@
  dropChance -= L2DropData.MAX_CHANCE;
  }
 
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion() && ((drop.getItemId() == PcInventory.ADENA_ID) || Util.contains(SevenSigns.SEAL_STONE_IDS, drop.getItemId())))
+ if (isChampion() && ((drop.getItemId() == PcInventory.ADENA_ID) || Util.contains(SevenSigns.SEAL_STONE_IDS, drop.getItemId())))
  {
- itemCount *= Config.L2JMOD_CHAMPION_ADENAS_REWARDS;
+ itemCount *= ChampionData.getInstance().getMultiplier(getChampionType(), "bonusDropAdena");
  }
 
  if (itemCount > 0)
@@ -1163,9 +1164,9 @@
  // Applies Drop rates
  categoryDropChance *= isRaid() && !isRaidMinion() ? Config.RATE_DROP_ITEMS_BY_RAID : Config.RATE_DROP_ITEMS;
 
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion())
+ if (isChampion())
  {
- categoryDropChance *= Config.L2JMOD_CHAMPION_REWARDS;
+ categoryDropChance *= ChampionData.getInstance().getMultiplier(getChampionType(), "bonusDrop");
  }
 
  // Set our limits for chance of drop
@@ -1207,9 +1208,9 @@
  dropChance *= isRaid() && !isRaidMinion() ? Config.RATE_DROP_ITEMS_BY_RAID : Config.RATE_DROP_ITEMS;
  }
 
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion())
+ if (isChampion())
  {
- dropChance *= Config.L2JMOD_CHAMPION_REWARDS;
+ dropChance *= ChampionData.getInstance().getMultiplier(getChampionType(), "bonusDrop");
  }
 
  dropChance = Math.round(dropChance);
@@ -1269,9 +1270,9 @@
  dropChance -= L2DropData.MAX_CHANCE;
  }
 
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion() && ((drop.getItemId() == PcInventory.ADENA_ID) || Util.contains(SevenSigns.SEAL_STONE_IDS, drop.getItemId())))
+ if (isChampion() && ((drop.getItemId() == PcInventory.ADENA_ID) || Util.contains(SevenSigns.SEAL_STONE_IDS, drop.getItemId())))
  {
- itemCount *= Config.L2JMOD_CHAMPION_ADENAS_REWARDS;
+ itemCount *= ChampionData.getInstance().getMultiplier(getChampionType(), "bonusDropAdena");
  }
 
  if (!Config.MULTIPLE_ITEM_DROP && !ItemTable.getInstance().getTemplate(drop.getItemId()).isStackable() && (itemCount > 1))
@@ -1580,33 +1581,27 @@
  }
  }
  // Apply Special Item drop with random(rnd) quantity(qty) for champions.
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion() && ((Config.L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE > 0) || (Config.L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE > 0)))
+ if (isChampion() && ChampionData.getInstance().hasPersonalReward(getChampionType()) && (((getLevel() + Config.L2JMOD_CHAMPION_LVL_DIFF) >= player.getLevel()) || (Config.L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE > 0)))
  {
- int champqty = Rnd.get(Config.L2JMOD_CHAMPION_REWARD_QTY);
- ItemHolder item = new ItemHolder(Config.L2JMOD_CHAMPION_REWARD_ID, ++champqty);
-
- if ((player.getLevel() <= getLevel()) && (Rnd.get(100) < Config.L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE))
+ for (L2DropData reward : ChampionData.getInstance().getReward(getChampionType()))
  {
- if (Config.AUTO_LOOT || isFlying())
+ int champqty = Rnd.get(reward.getMinDrop(), reward.getMaxDrop());
+
+ if (champqty > 0)
  {
- player.addItem("ChampionLoot", item.getId(), item.getCount(), this, true); // Give the item(s) to the L2PcInstance that has killed the L2Attackable
+ if (((getLevel() + Config.L2JMOD_CHAMPION_LVL_DIFF) >= player.getLevel()) || ((Rnd.get(100) < Config.L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE)))
+ {
+ if (Config.AUTO_LOOT || isFlying())
+ {
+ player.addItem("ChampionLoot", reward.getItemId(), champqty, this, true); // Give the item(s) to the L2PcInstance that has killed the L2Attackable
+ }
+ else
+ {
+ dropItem(player, reward.getItemId(), champqty);
+ }
+ }
  }
- else
- {
- dropItem(player, item);
- }
  }
- else if ((player.getLevel() > getLevel()) && (Rnd.get(100) < Config.L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE))
- {
- if (Config.AUTO_LOOT || isFlying())
- {
- player.addItem("ChampionLoot", item.getId(), item.getCount(), this, true); // Give the item(s) to the L2PcInstance that has killed the L2Attackable
- }
- else
- {
- dropItem(player, item);
- }
- }
  }
 
  // Instant Item Drop :>
@@ -2312,15 +2307,29 @@
  return null;
  }
 
- public void setChampion(boolean champ)
+ /**
+ * Set this champion type of this Npc.
+ * @param champType
+ */
+ public void setChampionType(int champType)
  {
- _champion = champ;
+ _championType = champType;
+ setTeam(ChampionData.getInstance().getGlow(champType));
  }
 
+ /**
+ * @return champion type of this L2Attackable.
+ */
  @Override
+ public int getChampionType()
+ {
+ return _championType;
+ }
+
+ @Override
  public boolean isChampion()
  {
- return _champion;
+ return (Config.L2JMOD_CHAMPION_ENABLE && (_championType >= 0));
  }
 
  @Override
Index: java/com/l2jserver/gameserver/model/actor/L2Character.java
===================================================================
--- java/com/l2jserver/gameserver/model/actor/L2Character.java (revision 6306)
+++ java/com/l2jserver/gameserver/model/actor/L2Character.java (working copy)
@@ -44,6 +44,7 @@
 import com.l2jserver.gameserver.ai.CtrlIntention;
 import com.l2jserver.gameserver.ai.L2AttackableAI;
 import com.l2jserver.gameserver.ai.L2CharacterAI;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.datatables.DoorTable;
 import com.l2jserver.gameserver.datatables.ItemTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
@@ -6538,9 +6539,9 @@
 
  public void reduceCurrentHp(double i, L2Character attacker, boolean awake, boolean isDOT, L2Skill skill)
  {
- if (Config.L2JMOD_CHAMPION_ENABLE && isChampion() && (Config.L2JMOD_CHAMPION_HP != 0))
+ if (isChampion())
  {
- getStatus().reduceHp(i / Config.L2JMOD_CHAMPION_HP, attacker, awake, isDOT, false);
+ getStatus().reduceHp(i / ChampionData.getInstance().getMultiplier(getChampionType(), Stats.MAX_HP), attacker, awake, isDOT, false);
  }
  else
  {
@@ -6651,6 +6652,14 @@
  }
 
  /**
+ * @return champion type of this L2Attackable.
+ */
+ public int getChampionType()
+ {
+ return -1;
+ }
+
+ /**
  * Check player max buff count
  * @return max buff count
  */
Index: java/com/l2jserver/gameserver/model/actor/stat/CharStat.java
===================================================================
--- java/com/l2jserver/gameserver/model/actor/stat/CharStat.java (revision 6306)
+++ java/com/l2jserver/gameserver/model/actor/stat/CharStat.java (working copy)
@@ -21,6 +21,7 @@
 import java.util.Arrays;
 
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.model.Elementals;
 import com.l2jserver.gameserver.model.PcCondOverride;
 import com.l2jserver.gameserver.model.actor.L2Character;
@@ -297,9 +298,9 @@
  public int getMAtk(L2Character target, L2Skill skill)
  {
  float bonusAtk = 1;
- if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
+ if (_activeChar.isChampion())
  {
- bonusAtk = Config.L2JMOD_CHAMPION_ATK;
+ bonusAtk = ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), Stats.MAGIC_ATTACK);
  }
  if (_activeChar.isRaid())
  {
@@ -316,9 +317,9 @@
  public int getMAtkSpd()
  {
  float bonusSpdAtk = 1;
- if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
+ if (_activeChar.isChampion())
  {
- bonusSpdAtk = Config.L2JMOD_CHAMPION_SPD_ATK;
+ bonusSpdAtk = ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), Stats.MAGIC_ATTACK_SPEED);
  }
 
  double val = calcStat(Stats.MAGIC_ATTACK_SPEED, _activeChar.getTemplate().getBaseMAtkSpd() * bonusSpdAtk);
@@ -359,6 +360,11 @@
  // Get the base MDef of the L2Character
  double defence = _activeChar.getTemplate().getBaseMDef();
 
+ if (_activeChar.isChampion())
+ {
+ defence *= ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), Stats.MAGIC_DEFENCE);
+ }
+
  // Calculate modifier for Raid Bosses
  if (_activeChar.isRaid())
  {
@@ -415,9 +421,9 @@
  public int getPAtk(L2Character target)
  {
  float bonusAtk = 1;
- if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
+ if (_activeChar.isChampion())
  {
- bonusAtk = Config.L2JMOD_CHAMPION_ATK;
+ bonusAtk = ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), Stats.POWER_ATTACK);
  }
  if (_activeChar.isRaid())
  {
@@ -432,9 +438,9 @@
  public int getPAtkSpd()
  {
  float bonusAtk = 1;
- if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
+ if (_activeChar.isChampion())
  {
- bonusAtk = Config.L2JMOD_CHAMPION_SPD_ATK;
+ bonusAtk = ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), Stats.POWER_ATTACK_SPEED);
  }
  int val = (int) Math.round(calcStat(Stats.POWER_ATTACK_SPEED, _activeChar.getTemplate().getBasePAtkSpd() * bonusAtk, null, null));
  return val;
@@ -446,7 +452,19 @@
  */
  public int getPDef(L2Character target)
  {
- return (int) calcStat(Stats.POWER_DEFENCE, (_activeChar.isRaid()) ? _activeChar.getTemplate().getBasePDef() * Config.RAID_PDEFENCE_MULTIPLIER : _activeChar.getTemplate().getBasePDef(), target, null);
+ float bonus = 1;
+
+ if (_activeChar.isChampion())
+ {
+ bonus = ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), Stats.POWER_DEFENCE);
+ }
+
+ if (_activeChar.isRaid())
+ {
+ bonus *= Config.RAID_PDEFENCE_MULTIPLIER;
+ }
+
+ return (int) calcStat(Stats.POWER_DEFENCE, _activeChar.getTemplate().getBasePDef() * bonus, target, null);
  }
 
  /**
@@ -471,12 +489,17 @@
  */
  public int getRunSpeed()
  {
- final float baseRunSpd = _activeChar.isInsideZone(ZoneId.WATER) ? getSwimRunSpeed() : getBaseMoveSpeed(MoveType.RUN);
+ float baseRunSpd = _activeChar.isInsideZone(ZoneId.WATER) ? getSwimRunSpeed() : getBaseMoveSpeed(MoveType.RUN);
  if (baseRunSpd == 0)
  {
  return 0;
  }
 
+ if (_activeChar.isChampion())
+ {
+ baseRunSpd *= ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), "moveSpd");
+ }
+
  return (int) Math.round(calcStat(Stats.MOVE_SPEED, baseRunSpd, null, null));
  }
 
@@ -522,12 +545,17 @@
  */
  public int getWalkSpeed()
  {
- final float baseWalkSpd = _activeChar.isInsideZone(ZoneId.WATER) ? getSwimWalkSpeed() : getBaseMoveSpeed(MoveType.WALK);
+ float baseWalkSpd = _activeChar.isInsideZone(ZoneId.WATER) ? getSwimWalkSpeed() : getBaseMoveSpeed(MoveType.WALK);
  if (baseWalkSpd == 0)
  {
  return 0;
  }
 
+ if (_activeChar.isChampion())
+ {
+ baseWalkSpd *= ChampionData.getInstance().getMultiplier(_activeChar.getChampionType(), "moveSpd");
+ }
+
  return (int) Math.round(calcStat(Stats.MOVE_SPEED, baseWalkSpd));
  }
 
Index: java/com/l2jserver/gameserver/model/actor/status/CharStatus.java
===================================================================
--- java/com/l2jserver/gameserver/model/actor/status/CharStatus.java (revision 6306)
+++ java/com/l2jserver/gameserver/model/actor/status/CharStatus.java (working copy)
@@ -27,10 +27,12 @@
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.ThreadPoolManager;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.stat.CharStat;
 import com.l2jserver.gameserver.model.stats.Formulas;
+import com.l2jserver.gameserver.model.stats.Stats;
 import com.l2jserver.util.Rnd;
 
 public class CharStatus
@@ -186,7 +188,14 @@
 
  public void reduceMp(double value)
  {
- setCurrentMp(Math.max(getCurrentMp() - value, 0));
+ if (getActiveChar().isChampion())
+ {
+ setCurrentMp(Math.max(getCurrentMp() - (value / ChampionData.getInstance().getMultiplier(getActiveChar().getChampionType(), Stats.MAX_MP)), 0));
+ }
+ else
+ {
+ setCurrentMp(Math.max(getCurrentMp() - value, 0));
+ }
  }
 
  /**
Index: java/com/l2jserver/gameserver/model/L2Spawn.java
===================================================================
--- java/com/l2jserver/gameserver/model/L2Spawn.java (revision 6306)
+++ java/com/l2jserver/gameserver/model/L2Spawn.java (working copy)
@@ -30,6 +30,7 @@
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.GeoData;
 import com.l2jserver.gameserver.ThreadPoolManager;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.datatables.NpcPersonalAIData;
 import com.l2jserver.gameserver.datatables.TerritoryTable;
 import com.l2jserver.gameserver.idfactory.IdFactory;
@@ -36,6 +37,7 @@
 import com.l2jserver.gameserver.model.actor.L2Attackable;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Npc;
+import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
 import com.l2jserver.gameserver.model.interfaces.IIdentifiable;
 import com.l2jserver.gameserver.model.interfaces.ILocational;
@@ -640,23 +642,11 @@
  mob.setHeading(getHeading());
  }
 
- if (mob instanceof L2Attackable)
+ if (Config.L2JMOD_CHAMPION_ENABLE && mob.isMonster())
  {
- ((L2Attackable) mob).setChampion(false);
+ ((L2MonsterInstance) mob).setChampionType(ChampionData.getInstance().calculateChampionType((L2MonsterInstance) mob));
  }
 
- if (Config.L2JMOD_CHAMPION_ENABLE)
- {
- // Set champion on next spawn
- if (mob.isMonster() && !getTemplate().isQuestMonster() && !mob.isRaid() && !mob.isRaidMinion() && (Config.L2JMOD_CHAMPION_FREQUENCY > 0) && (mob.getLevel() >= Config.L2JMOD_CHAMP_MIN_LVL) && (mob.getLevel() <= Config.L2JMOD_CHAMP_MAX_LVL) && (Config.L2JMOD_CHAMPION_ENABLE_IN_INSTANCES || (getInstanceId() == 0)))
- {
- if (Rnd.get(100) < Config.L2JMOD_CHAMPION_FREQUENCY)
- {
- ((L2Attackable) mob).setChampion(true);
- }
- }
- }
-
  // Link the L2NpcInstance to this L2Spawn
  mob.setSpawn(this);
 
Index: java/com/l2jserver/gameserver/model/quest/Quest.java
===================================================================
--- java/com/l2jserver/gameserver/model/quest/Quest.java (revision 6306)
+++ java/com/l2jserver/gameserver/model/quest/Quest.java (working copy)
@@ -39,6 +39,7 @@
 import com.l2jserver.gameserver.GameTimeController;
 import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.cache.HtmCache;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.datatables.DoorTable;
 import com.l2jserver.gameserver.datatables.ItemTable;
 import com.l2jserver.gameserver.datatables.NpcTable;
@@ -3370,18 +3371,18 @@
  minAmount *= Config.RATE_QUEST_DROP;
  maxAmount *= Config.RATE_QUEST_DROP;
  dropChance *= Config.RATE_QUEST_DROP; // TODO separate configs for rate and amount
- if ((npc != null) && Config.L2JMOD_CHAMPION_ENABLE && npc.isChampion())
+ if ((npc != null) && npc.isChampion())
  {
- dropChance *= Config.L2JMOD_CHAMPION_REWARDS;
+ dropChance *= ChampionData.getInstance().getMultiplier(npc.getChampionType(), "bonusDrop");
  if ((itemId == PcInventory.ADENA_ID) || (itemId == PcInventory.ANCIENT_ADENA_ID))
  {
- minAmount *= Config.L2JMOD_CHAMPION_ADENAS_REWARDS;
- maxAmount *= Config.L2JMOD_CHAMPION_ADENAS_REWARDS;
+ minAmount *= ChampionData.getInstance().getMultiplier(npc.getChampionType(), "bonusDropAdena");
+ maxAmount *= ChampionData.getInstance().getMultiplier(npc.getChampionType(), "bonusDropAdena");
  }
  else
  {
- minAmount *= Config.L2JMOD_CHAMPION_REWARDS;
- maxAmount *= Config.L2JMOD_CHAMPION_REWARDS;
+ minAmount *= ChampionData.getInstance().getMultiplier(npc.getChampionType(), "bonusDrop");
+ maxAmount *= ChampionData.getInstance().getMultiplier(npc.getChampionType(), "bonusDrop");
  }
  }
 
Index: java/com/l2jserver/gameserver/model/stats/Formulas.java
===================================================================
--- java/com/l2jserver/gameserver/model/stats/Formulas.java (revision 6306)
+++ java/com/l2jserver/gameserver/model/stats/Formulas.java (working copy)
@@ -25,6 +25,7 @@
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.SevenSigns;
 import com.l2jserver.gameserver.SevenSignsFestival;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.datatables.HitConditionBonus;
 import com.l2jserver.gameserver.datatables.KarmaData;
 import com.l2jserver.gameserver.instancemanager.CastleManager;
@@ -262,12 +263,12 @@
  double hpRegenMultiplier = cha.isRaid() ? Config.RAID_HP_REGEN_MULTIPLIER : Config.HP_REGEN_MULTIPLIER;
  double hpRegenBonus = 0;
 
- if (Config.L2JMOD_CHAMPION_ENABLE && cha.isChampion())
+ if (cha.isChampion())
  {
- hpRegenMultiplier *= Config.L2JMOD_CHAMPION_HP_REGEN;
+ hpRegenMultiplier *= ChampionData.getInstance().getMultiplier(cha.getChampionType(), Stats.REGENERATE_HP_RATE);
  }
 
- if (cha.isPlayer())
+ else if (cha.isPlayer())
  {
  L2PcInstance player = cha.getActingPlayer();
 
@@ -383,7 +384,11 @@
  double mpRegenMultiplier = cha.isRaid() ? Config.RAID_MP_REGEN_MULTIPLIER : Config.MP_REGEN_MULTIPLIER;
  double mpRegenBonus = 0;
 
- if (cha.isPlayer())
+ if (cha.isChampion())
+ {
+ mpRegenMultiplier *= ChampionData.getInstance().getMultiplier(cha.getChampionType(), Stats.REGENERATE_MP_RATE);
+ }
+ else if (cha.isPlayer())
  {
  L2PcInstance player = cha.getActingPlayer();
 
Index: java/com/l2jserver/gameserver/network/serverpackets/AbstractNpcInfo.java
===================================================================
--- java/com/l2jserver/gameserver/network/serverpackets/AbstractNpcInfo.java (revision 6306)
+++ java/com/l2jserver/gameserver/network/serverpackets/AbstractNpcInfo.java (working copy)
@@ -19,6 +19,7 @@
 package com.l2jserver.gameserver.network.serverpackets;
 
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ChampionData;
 import com.l2jserver.gameserver.datatables.ClanTable;
 import com.l2jserver.gameserver.instancemanager.TownManager;
 import com.l2jserver.gameserver.model.L2Clan;
@@ -99,9 +100,9 @@
  _name = cha.getName();// On every subclass
  }
 
- if (Config.L2JMOD_CHAMPION_ENABLE && cha.isChampion())
+ if (cha.isChampion() && !ChampionData.getInstance().getTitle(cha.getChampionType()).isEmpty())
  {
- _title = (Config.L2JMOD_CHAMP_TITLE); // On every subclass
+ _title = ChampionData.getInstance().getTitle(cha.getChampionType()); // On every subclass
  }
  else if (cha.getTemplate().isServerSideTitle())
  {

By GKR, up  VlLight.