package server.life;
import constants.GameConstants;
import java.awt.Point;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataDirectoryEntry;
import provider.MapleDataFileEntry;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import provider.wz.MapleDataType;
import server.Randomizer;
import server.maps.MapleMapFactory;
import tools.FileoutputUtil;
import tools.Pair;
import tools.StringUtil;
public class MapleLifeFactory {
private static final MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/Mob.wz"));
private static final MapleDataProvider npcData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/Npc.wz"));
private static final MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/String.wz"));
private static final MapleDataProvider etcDataWZ = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/Etc.wz"));
private static final MapleData mobStringData = stringDataWZ.getData("Mob.img");
private static final MapleData npcStringData = stringDataWZ.getData("Npc.img");
private static final MapleData npclocData = etcDataWZ.getData("NpcLocation.img");
private static final Map<Integer, String> npcNames = new HashMap();
private static final Map<Integer, MapleMonsterStats> monsterStats = new HashMap();
private static final Map<Integer, Integer> NPCLoc = new HashMap();
private static final Map<Integer, List<Integer>> questCount = new HashMap();
public static AbstractLoadedMapleLife getLife(int id, String type) {
if (type.equalsIgnoreCase("n")) {
return getNPC(id);
}
if (type.equalsIgnoreCase("m")) {
return getMonster(id);
}
System.err.println("Unknown Life type: " + type + "");
return null;
}
public static int getNPCLocation(int npcid) {
if (NPCLoc.containsKey(npcid)) {
return NPCLoc.get(npcid);
}
int map = MapleDataTool.getIntConvert(Integer.toString(npcid) + "/0", npclocData, -1);
NPCLoc.put(npcid, map);
return map;
}
public static void loadQuestCounts(boolean reload) {
if (reload) {
questCount.clear();
}
if (!questCount.isEmpty()) {
return;
}
for (MapleDataDirectoryEntry mapz : data.getRoot().getSubdirectories()) {
if (mapz.getName().equals("QuestCountGroup")) {
for (MapleDataFileEntry entry : mapz.getFiles()) {
int id = Integer.parseInt(entry.getName().substring(0, entry.getName().length() - 4));
MapleData dat = data.getData("QuestCountGroup/" + entry.getName());
if ((dat != null) && (dat.getChildByPath("info") != null)) {
List z = new ArrayList();
for (MapleData da : dat.getChildByPath("info")) {
z.add(MapleDataTool.getInt(da, 0));
}
questCount.put(id, z);
} else {
FileoutputUtil.log("null questcountgroup");
}
}
}
}
for (MapleData c : npcStringData) {
if (c.getName().contains("pack_ignore")) {
continue;
}
int nid = Integer.parseInt(c.getName());
String n = StringUtil.getLeftPaddedStr(nid + ".img", '0', 11);
try {
if (npcData.getData(n) != null) {
String name = MapleDataTool.getString("name", c, "MISSINGNO");
if ((!name.contains("MapleTV")) && (name.contains("婴儿月妙"))) {
continue;
}
npcNames.put(nid, name);
}
} catch (NullPointerException e) {
} catch (RuntimeException e) {
}
}
}
public static List<Integer> getQuestCount(int id) {
return (List) questCount.get(id);
}
public static MapleMonster getMonster(int mobId) {
MapleMonsterStats stats = getMonsterStats(mobId);
if (stats == null) {
return null;
}
return new MapleMonster(mobId, stats);
}
public static MapleMonsterStats getMonsterStats(int mobId) {
MapleMonsterStats stats = (MapleMonsterStats) monsterStats.get(Integer.valueOf(mobId));
if (stats == null) {
MapleData monsterData;
try {
monsterData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(mobId) + ".img", '0', 11));
} catch (RuntimeException e) {
return null;
}
if (monsterData == null) {
return null;
}
MapleData monsterInfoData = monsterData.getChildByPath("info");
stats = new MapleMonsterStats(mobId);
if (monsterInfoData.getChildByPath("maxHP").getData().equals("??????")) {
stats.setHp(2147483646L);
} else {
stats.setHp(MapleDataTool.getIntConvert("maxHP", monsterInfoData));
}
stats.setMp(MapleDataTool.getIntConvert("maxMP", monsterInfoData, 0));
stats.setExp(GameConstants.getPartyPlayEXP(mobId) > 0 ? GameConstants.getPartyPlayEXP(mobId) : mobId == 9300027 ? 0 : MapleDataTool.getIntConvert("exp", monsterInfoData, 0));
stats.setLevel((short) MapleDataTool.getIntConvert("level", monsterInfoData, 1));
stats.setCharismaEXP((short) MapleDataTool.getIntConvert("charismaEXP", monsterInfoData, 0));
stats.setRemoveAfter(MapleDataTool.getIntConvert("removeAfter", monsterInfoData, 0));
stats.setrareItemDropLevel((byte) MapleDataTool.getIntConvert("rareItemDropLevel", monsterInfoData, 0));
stats.setFixedDamage(MapleDataTool.getIntConvert("fixedDamage", monsterInfoData, -1));
stats.setOnlyNormalAttack(MapleDataTool.getIntConvert("onlyNormalAttack", monsterInfoData, 0) > 0);
stats.setBoss((GameConstants.getPartyPlayHP(mobId) > 0) || (MapleDataTool.getIntConvert("boss", monsterInfoData, 0) > 0) || (mobId == 8810018) || (mobId == 9410066) || ((mobId >= 8810118) && (mobId <= 8810122)));
stats.setExplosiveReward(MapleDataTool.getIntConvert("explosiveReward", monsterInfoData, 0) > 0);
stats.setUndead(MapleDataTool.getIntConvert("undead", monsterInfoData, 0) > 0);
stats.setEscort(MapleDataTool.getIntConvert("escort", monsterInfoData, 0) > 0);
stats.setPartyBonus((GameConstants.getPartyPlayHP(mobId) > 0) || (MapleDataTool.getIntConvert("partyBonusMob", monsterInfoData, 0) > 0));
stats.setPartyBonusRate(MapleDataTool.getIntConvert("partyBonusR", monsterInfoData, 0));
if (mobStringData.getChildByPath(String.valueOf(mobId)) != null) {
stats.setName(MapleDataTool.getString("name", mobStringData.getChildByPath(String.valueOf(mobId)), "MISSINGNO"));
}
stats.setBuffToGive(MapleDataTool.getIntConvert("buff", monsterInfoData, -1));
stats.setChange(MapleDataTool.getIntConvert("changeableMob", monsterInfoData, 0) > 0);
stats.setFriendly(MapleDataTool.getIntConvert("damagedByMob", monsterInfoData, 0) > 0);
stats.setNoDoom(MapleDataTool.getIntConvert("noDoom", monsterInfoData, 0) > 0);
stats.setFfaLoot(MapleDataTool.getIntConvert("publicReward", monsterInfoData, 0) > 0);
stats.setCP((byte) MapleDataTool.getIntConvert("getCP", monsterInfoData, 0));
stats.setPoint(MapleDataTool.getIntConvert("point", monsterInfoData, 0));
stats.setDropItemPeriod(MapleDataTool.getIntConvert("dropItemPeriod", monsterInfoData, 0));
stats.setPhysicalAttack(MapleDataTool.getIntConvert("PADamage", monsterInfoData, 0));
stats.setMagicAttack(MapleDataTool.getIntConvert("MADamage", monsterInfoData, 0));
stats.setPDRate((byte) MapleDataTool.getIntConvert("PDRate", monsterInfoData, 0));
stats.setMDRate((byte) MapleDataTool.getIntConvert("MDRate", monsterInfoData, 0));
stats.setAcc(MapleDataTool.getIntConvert("acc", monsterInfoData, 0));
stats.setEva(MapleDataTool.getIntConvert("eva", monsterInfoData, 0));
stats.setSummonType((byte) MapleDataTool.getIntConvert("summonType", monsterInfoData, 0));
stats.setCategory((byte) MapleDataTool.getIntConvert("category", monsterInfoData, 0));
stats.setSpeed(MapleDataTool.getIntConvert("speed", monsterInfoData, 0));
stats.setPushed(MapleDataTool.getIntConvert("pushed", monsterInfoData, 0));
MapleData selfd = monsterInfoData.getChildByPath("selfDestruction");
if (selfd != null) {
stats.setSelfDHP(MapleDataTool.getIntConvert("hp", selfd, 0));
stats.setRemoveAfter(MapleDataTool.getIntConvert("removeAfter", selfd, stats.getRemoveAfter()));
stats.setSelfD((byte) MapleDataTool.getIntConvert("action", selfd, -1));
} else {
stats.setSelfD((byte) -1);
}
MapleData firstAttackData = monsterInfoData.getChildByPath("firstAttack");
int firstAttack = 0;
if (firstAttackData != null) {
if (firstAttackData.getType() == MapleDataType.FLOAT) {
firstAttack = Math.round(MapleDataTool.getFloat(firstAttackData));
} else {
firstAttack = MapleDataTool.getInt(firstAttackData);
}
}
stats.setFirstAttack(firstAttack > 0);
if ((stats.isBoss()) || (isDmgSponge(mobId))) {
if ((monsterInfoData.getChildByPath("hpTagColor") == null) || (monsterInfoData.getChildByPath("hpTagBgcolor") == null)) {
stats.setTagColor(0);
stats.setTagBgColor(0);
} else {
stats.setTagColor(MapleDataTool.getIntConvert("hpTagColor", monsterInfoData));
stats.setTagBgColor(MapleDataTool.getIntConvert("hpTagBgcolor", monsterInfoData));
}
}
MapleData banishData = monsterInfoData.getChildByPath("ban");
if (banishData != null) {
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
}
MapleData reviveInfo = monsterInfoData.getChildByPath("revive");
if (reviveInfo != null) {
List revives = new LinkedList();
for (MapleData bdata : reviveInfo) {
revives.add(MapleDataTool.getInt(bdata));
}
stats.setRevives(revives);
}
MapleData monsterSkillData = monsterInfoData.getChildByPath("skill");
if (monsterSkillData != null) {
int i = 0;
List skills = new ArrayList();
while (monsterSkillData.getChildByPath(Integer.toString(i)) != null) {
skills.add(new Pair(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0), MapleDataTool.getInt(i + "/level", monsterSkillData, 0)));
i++;
}
stats.setSkills(skills);
}
decodeElementalString(stats, MapleDataTool.getString("elemAttr", monsterInfoData, ""));
int link = MapleDataTool.getIntConvert("link", monsterInfoData, 0);
if (link != 0) {
monsterData = data.getData(StringUtil.getLeftPaddedStr(link + ".img", '0', 11));
}
for (MapleData idata : monsterData) {
if (idata.getName().equals("fly")) {
stats.setFly(true);
stats.setMobile(true);
break;
}
if (idata.getName().equals("move")) {
stats.setMobile(true);
}
}
for (int i = 1;; i++) {
MapleData attackData = monsterData.getChildByPath("attack" + i + "/info");
if (attackData == null) {
break;
}
MobAttackInfo ret = new MobAttackInfo();
ret.setDeadlyAttack(attackData.getChildByPath("deadlyAttack") != null);
ret.setMpBurn(MapleDataTool.getInt("mpBurn", attackData, 0));
ret.setDiseaseSkill(MapleDataTool.getInt("disease", attackData, 0));
ret.setDiseaseLevel(MapleDataTool.getInt("level", attackData, 0));
ret.setMpCon(MapleDataTool.getInt("conMP", attackData, 0));
ret.attackAfter = MapleDataTool.getInt("attackAfter", attackData, 0);
ret.PADamage = MapleDataTool.getInt("PADamage", attackData, 0);
ret.MADamage = MapleDataTool.getInt("PADamage", attackData, 0);
ret.magic = (MapleDataTool.getInt("magic", attackData, 0) > 0);
if (attackData.getChildByPath("range") != null) {
ret.range = MapleDataTool.getInt("range/r", attackData, 0);
if ((attackData.getChildByPath("range/lt") != null) && (attackData.getChildByPath("range/rb") != null)) {
ret.lt = ((Point) attackData.getChildByPath("range/lt").getData());
ret.rb = ((Point) attackData.getChildByPath("range/rb").getData());
}
}
stats.addMobAttack(ret);
}
byte hpdisplaytype = -1;
if (stats.getTagColor() > 0) {
hpdisplaytype = 0;
} else if (stats.isFriendly()) {
hpdisplaytype = 1;
} else if ((mobId >= 9300184) && (mobId <= 9300215)) {
hpdisplaytype = 2;
} else if ((!stats.isBoss()) || (mobId == 9410066) || (stats.isPartyBonus())) {
hpdisplaytype = 3;
}
stats.setHPDisplayType(hpdisplaytype);
monsterStats.put(mobId, stats);
}
return stats;
}
public static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {
for (int i = 0; i < elemAttr.length(); i += 2) {
stats.setEffectiveness(Element.getFromChar(elemAttr.charAt(i)), ElementalEffectiveness.getByNumber(Integer.valueOf(String.valueOf(elemAttr.charAt(i + 1)))));
}
}
private static boolean isDmgSponge(int mid) {
switch (mid) {
case 8810018:
case 8810118:
case 8810119:
case 8810120:
case 8810121:
case 8810122:
case 8820009:
case 8820010:
case 8820011:
case 8820012:
case 8820013:
case 8820014:
case 8820108:
case 8820109:
case 8820110:
case 8820111:
case 8820112:
case 8820113:
case 8820114:
case 8820300:
case 8820301:
case 8820302:
case 8820303:
case 8820304:
return true;
}
return false;
}
/**
* 新建一个NPC的实例
* @param nid
* @return
*/
public static MapleNPC getNPC(int nid) {
String name = npcNames.get(Integer.valueOf(nid));
if (name == null) {
return null;
}
// 增加一个NPC的脚本属性属性值
MapleNPC npc = new MapleNPC(nid, name);
final MapleDataProvider wzNpc = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/Npc.wz"));
MapleData data = wzNpc.getData(StringUtil.getLeftPaddedStr(Integer.toString(nid) + ".img", '0', 11));
MapleData link = data.getChildByPath("info/quest");
if (link != null) {
String scriptName = MapleDataTool.getString("info/quest", data);
npc.setScriptName(scriptName);
FileoutputUtil.log("NPC("+nid+")存在脚本任务:"+scriptName);
}
return npc;
}
public static int getRandomNPC() {
List vals = new ArrayList(npcNames.keySet());
int ret = 0;
while (ret <= 0) {
ret = ((Integer) vals.get(Randomizer.nextInt(vals.size())));
if ((npcNames.get(ret)).contains("MISSINGNO")) {
ret = 0;
}
}
return ret;
}
public static Map<Integer, String> getNPCNames() {
return npcNames;
}
}