Skip to content

Instantly share code, notes, and snippets.

@VlLight
Created December 5, 2013 15:50
Show Gist options
  • Save VlLight/7807848 to your computer and use it in GitHub Desktop.
Save VlLight/7807848 to your computer and use it in GitHub Desktop.
Advanced champion mod
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())
{
Index: dist/game/data/scripts/handlers/admincommandhandlers/AdminKill.java
===================================================================
--- dist/game/data/scripts/handlers/admincommandhandlers/AdminKill.java (revision 10058)
+++ dist/game/data/scripts/handlers/admincommandhandlers/AdminKill.java (working copy)
@@ -22,6 +22,7 @@
import java.util.logging.Logger;
import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ChampionData;
import com.l2jserver.gameserver.handler.IAdminCommandHandler;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2World;
@@ -28,6 +29,7 @@
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2ControllableMobInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.stats.Stats;
import com.l2jserver.gameserver.network.SystemMessageId;
/**
@@ -135,9 +137,9 @@
}
target.reduceCurrentHp(target.getMaxHp() + target.getMaxCp() + 1, activeChar, null);
}
- else if (Config.L2JMOD_CHAMPION_ENABLE && target.isChampion())
+ else if (target.isChampion())
{
- target.reduceCurrentHp((target.getMaxHp() * Config.L2JMOD_CHAMPION_HP) + 1, activeChar, null);
+ target.reduceCurrentHp((target.getMaxHp() * ChampionData.getInstance().getMultiplier(target.getChampionType(), Stats.MAX_HP)) + 1, activeChar, null);
}
else
{
Index: dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java
===================================================================
--- dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java (revision 10058)
+++ dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java (working copy)
@@ -22,8 +22,8 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.AdminTable;
+import com.l2jserver.gameserver.datatables.ChampionData;
import com.l2jserver.gameserver.handler.AdminCommandHandler;
import com.l2jserver.gameserver.handler.IAdminCommandHandler;
import com.l2jserver.gameserver.model.L2Clan;
@@ -32,6 +32,7 @@
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.stats.Stats;
import com.l2jserver.gameserver.network.SystemMessageId;
/**
@@ -253,9 +254,9 @@
target.reduceCurrentHp(target.getMaxHp() + target.getMaxCp() + 1, activeChar, null);
filename = "charmanage.htm";
}
- else if (Config.L2JMOD_CHAMPION_ENABLE && target.isChampion())
+ else if (target.isChampion())
{
- target.reduceCurrentHp((target.getMaxHp() * Config.L2JMOD_CHAMPION_HP) + 1, activeChar, null);
+ target.reduceCurrentHp((target.getMaxHp() * ChampionData.getInstance().getMultiplier(target.getChampionType(), Stats.MAX_HP)) + 1, activeChar, null);
}
else
{
Index: dist/game/data/stats/champions.xml
===================================================================
--- dist/game/data/stats/champions.xml (revision 0)
+++ dist/game/data/stats/champions.xml (working copy)
@@ -0,0 +1,31 @@
+<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../xsd/champions.xsd">
+ <champion>
+ <!-- Spawn chance in percents. Sum of chances for all champions shouldn't greater, than 100% -->
+ <chance>1</chance>
+ <!-- level bounds -->
+ <minLvl>1</minLvl>
+ <maxLvl>85</maxLvl>
+ <!-- identification -->
+ <title>Champion</title>
+ <glow>1</glow> <!-- 1 - red or 2 - blue -->
+ <!-- rewards multiplier section -->
+ <bonusExp>1</bonusExp>
+ <bonusSp>1</bonusSp>
+ <bonusDrop>1</bonusDrop>
+ <bonusDropAdena>1</bonusDropAdena>
+ <!-- specific reward('s) -->
+ <reward id="57" min="1" max="2" />
+ <!-- stats multiplier section -->
+ <maxHp>1</maxHp>
+ <regHp>1</regHp>
+ <maxMp>1</maxMp>
+ <regMp>1</regMp>
+ <pAtk>1</pAtk>
+ <pAtkSpd>1</pAtkSpd>
+ <mAtk>1</mAtk>
+ <mAtkSpd>1</mAtkSpd>
+ <pDef>1</pDef>
+ <mDef>1</mDef>
+ <moveSpd>1</moveSpd>
+ </champion>
+</list>
Index: dist/game/data/xsd/champions.xsd
===================================================================
--- dist/game/data/xsd/champions.xsd (revision 0)
+++ dist/game/data/xsd/champions.xsd (working copy)
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="list">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="champion" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="chance" minOccurs="1" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ <xs:maxInclusive value="100" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="minLvl" type="xs:positiveInteger" minOccurs="0" maxOccurs="1" />
+ <xs:element name="maxLvl" type="xs:positiveInteger" minOccurs="0" maxOccurs="1" />
+ <xs:element name="title" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="glow" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:positiveInteger">
+ <xs:maxInclusive value="2" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="bonusExp" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="bonusSp" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="bonusDrop" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="bonusDropAdena" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="reward" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:positiveInteger" use="required" />
+ <xs:attribute name="min" type="xs:positiveInteger" use="required" />
+ <xs:attribute name="max" type="xs:positiveInteger" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="maxHp" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="regHp" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="maxMp" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="regMp" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="pAtk" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="pAtkSpd" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="mAtk" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="mAtkSpd" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="pDef" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="mDef" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="moveSpd" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:float">
+ <xs:minExclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment