package server.quest;
import client.MapleCharacter;
import client.MapleQuestStatus;
import constants.GameConstants;
import database.DatabaseConnection;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import scripting.quest.QuestScriptManager;
import tools.FileoutputUtil;
import tools.MaplePacketCreator;
import tools.Pair;
public class MapleQuest implements Serializable {
private static final long serialVersionUID = 9179541993413738569L;
// 所有任务集合
private static final Map<Integer, MapleQuest> quests = new LinkedHashMap();
// 按照NPC来查任务
private static final Map<Integer,List<Integer>> npcQuest = new LinkedHashMap();
protected int id;
// 任务开始条件
protected List<MapleQuestRequirement> startReqs = new LinkedList();
// 任务完成条件
protected Map<String,List<MapleQuestComplete>> completeReqs = new LinkedHashMap();
// 任务状态流
protected Map<String,String> questStatusList = new LinkedHashMap();
// 任务奖励数据
protected Map<String,List<MapleQuestReward>> rewards = new LinkedHashMap();
// protected List<MapleQuestAction> startActs = new LinkedList();
// protected List<MapleQuestAction> completeActs = new LinkedList();
// protected Map<Integer, Integer> relevantMobs = new LinkedHashMap();
// protected Map<Integer, Integer> questItems = new LinkedHashMap();
// 脚本任务
private static final Map<Integer, MapleQuest> questScript = new LinkedHashMap();
protected Map<String, List<Pair<String, Pair<String, Integer>>>> partyQuestInfo = new LinkedHashMap();
private int npcId = 0;
private String startStatus = "";
private String endStatus = "";
private boolean autoStart = false;
private boolean autoPreComplete = false;
private boolean repeatable = false;
private boolean customend = false;
private boolean blocked = false;
private boolean autoAccept = false;
private boolean autoComplete = false;
private boolean scriptedStart = false;
private int viewMedalItem = 0;
private int selectedSkillID = 0;
protected String name = "";
public MapleQuest(int id) {
this.id = id;
}
protected MapleQuest() {}
/**
* 任务数据解析
* @param questData
* @return
* @throws SQLException
*/
private static MapleQuest loadQuest(ResultSet questData) throws SQLException {
MapleQuest ret = new MapleQuest(questData.getInt("questid"));
ret.name = questData.getString("name");
ret.npcId = questData.getInt("npcId");
ret.startStatus = questData.getString("start_status");
ret.endStatus = questData.getString("end_status");
Connection con = DatabaseConnection.getConnection();
// 开始这个任务需要的条件
PreparedStatement psr = con.prepareStatement("SELECT * FROM wz_questreqdata WHERE questid = ?");
psr.setInt(1, ret.id);
ResultSet rse = psr.executeQuery();
while (rse.next()) {
MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(rse.getString("name"));
MapleQuestRequirement req = new MapleQuestRequirement(ret, type, rse);
// if (type.equals(MapleQuestRequirementType.interval)) {
// ret.repeatable = true;
// } else if (type.equals(MapleQuestRequirementType.normalAutoStart)) {
// ret.repeatable = true;
// ret.autoStart = true;
// } else if (type.equals(MapleQuestRequirementType.startscript)) {
// ret.scriptedStart = true;
// } else if (type.equals(MapleQuestRequirementType.endscript)) {
// ret.customend = true;
// } else if (type.equals(MapleQuestRequirementType.mob)) {
// for (Pair<Integer, Integer> mob : req.getDataStore()) {
// ret.relevantMobs.put(mob.left, mob.right);
// }
// } else if (type.equals(MapleQuestRequirementType.item)) {
// for (Pair<Integer, Integer> it : req.getDataStore()) {
// ret.questItems.put(it.left, it.right);
// }
// }
ret.startReqs.add(req);
}
rse.close();
// 任务完成需要的数据
PreparedStatement psComplete = con.prepareStatement("SELECT * FROM wz_questcompletedata WHERE questid = ?");
psComplete.setInt(1,ret.id);
rse = psComplete.executeQuery();
while (rse.next()) {
MapleQuestCompleteType ty = MapleQuestCompleteType.getByWZName(rse.getString("name"));
MapleQuestComplete reward = new MapleQuestComplete(ty,rse.getInt("itemId"),rse.getInt("num"));
String questStatus = rse.getString("quest_status");
List<MapleQuestComplete> tmpReward = ret.completeReqs.get(questStatus);
if (tmpReward == null) {
tmpReward = new LinkedList();
}
tmpReward.add(reward);
ret.completeReqs.put(questStatus,tmpReward);
}
FileoutputUtil.log(ret.completeReqs.toString());
// 任务奖励数据
PreparedStatement psReward = con.prepareStatement("SELECT * FROM wz_questrewarddata WHERE questId = ?");
psReward.setInt(1,ret.id);
rse = psReward.executeQuery();
while (rse.next()) {
MapleQuestRewardType ty = MapleQuestRewardType.getByWZName(rse.getString("name"));
MapleQuestReward reward = new MapleQuestReward(ty,rse);
String questStatus = rse.getString("quest_status");
List<MapleQuestReward> tmpReward = ret.rewards.get(questStatus);
if (tmpReward == null) {
tmpReward = new LinkedList();
}
tmpReward.add(reward);
ret.rewards.put(questStatus,tmpReward);
}
// 任务流
PreparedStatement psStatus = con.prepareStatement("SELECT * FROM wz_queststatus WHERE questid = ?");
psStatus.setInt(1,ret.id);
rse = psStatus.executeQuery();
while (rse.next()) {
ret.questStatusList.put(rse.getString("cur_status"),rse.getString("next_status"));
}
// 组队任务
PreparedStatement psp = con.prepareStatement("SELECT * FROM wz_questpartydata WHERE questid = ?");
psp.setInt(1, ret.id);
rse = psp.executeQuery();
while (rse.next()) {
if (!ret.partyQuestInfo.containsKey(rse.getString("rank"))) {
ret.partyQuestInfo.put(rse.getString("rank"), new ArrayList());
}
((List) ret.partyQuestInfo.get(rse.getString("rank"))).add(new Pair(rse.getString("mode"), new Pair(rse.getString("property"), rse.getInt("value"))));
}
rse.close();
return ret;
}
public List<Pair<String, Pair<String, Integer>>> getInfoByRank(String rank) {
return (List) this.partyQuestInfo.get(rank);
}
public boolean isPartyQuest() {
return this.partyQuestInfo.size() > 0;
}
public int getSkillID() {
return this.selectedSkillID;
}
public String getName() {
return this.name;
}
public int getNpcId() {return this.npcId;}
public String getStartStatus() {return this.startStatus;}
/**
* 初始化任务数据
* @param reload
*/
public static void initQuests(boolean reload) {
if (reload) {
quests.clear();
}
if (!quests.isEmpty() ) {
return;
}
Connection con = DatabaseConnection.getConnection();
try (
PreparedStatement questData = con.prepareStatement("SELECT * FROM wz_questdata");
ResultSet rs = questData.executeQuery();
) {
while (rs.next()) {
List<Integer> tmp = npcQuest.get(rs.getInt("npcId"));
if (tmp == null) {
tmp = new LinkedList<>();
}
quests.put(rs.getInt("questid"), loadQuest(rs));
tmp.add(rs.getInt("questid"));
npcQuest.put(rs.getInt("npcId"), tmp);
}
questData.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static MapleQuest getInstance(int id) {
MapleQuest ret = quests.get(Integer.valueOf(id));
if (ret == null) {
// 这是一个脚本任务
FileoutputUtil.log("找不到任务:"+id+"有可能是脚本任务!");
MapleQuest vet = new MapleQuest(id);
quests.put(id,vet);
return vet;
}
return ret;
}
public static MapleQuest getInstatce(){
MapleQuest ret = new MapleQuest();
return ret;
}
public static Collection<MapleQuest> getAllInstances() {
Map<Integer, MapleQuest> mapVK = new LinkedHashMap();
Set col = quests.keySet();
Iterator iter = col.iterator();
while (iter.hasNext()) {
Integer key = (Integer) iter.next();
MapleQuest value = quests.get(key);
mapVK.put(key, value);
}
return mapVK.values();
}
public boolean canStartScriptQuest(String name){
Connection con = DatabaseConnection.getConnection();
try (
PreparedStatement questData = con.prepareStatement("SELECT * FROM wz_questdata");
ResultSet rs = questData.executeQuery();) {
// while (rs.next()) {
// quests.put(rs.getInt("questid"), loadQuest(rs, psr, psa, pss, psq, psi, psp));
// }
questData.close();
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
/**
* 判断这个NPC下是否有任务可以做
* @param chr
* @param npcid
* @return
*/
public boolean canStart(MapleCharacter chr, Integer npcid) {
// if ((chr.getQuest(this).getStatus() != MapleQuestStatus.QUEST_UNSTART)
// && ((chr.getQuest(this).getStatus() != MapleQuestStatus.QUEST_COMPLETED)
// )) {
// if (chr.isShowPacket()) {
// chr.dropMessage(6, new StringBuilder().append("开始任务 canStart: ").append(chr.getQuest(this).getStatus() != 0).append(" - ").append((chr.getQuest(this).getStatus() != 2) || (!this.repeatable)).append(" repeatable: ").append(this.repeatable).toString());
// }
// return false;
// }
if ((this.blocked) && (!chr.isGM())) {
if (chr.isShowPacket()) {
chr.dropMessage(6, new StringBuilder().append("开始任务 canStart - blocked ").append(this.blocked).toString());
}
return false;
}
Map<Integer,MapleQuestStatus> questComplete = chr.getCompletedQuests();
boolean isCanStart = false;
for (Integer r : getQuestIdByNpcId(npcid)) {
if (questComplete.containsKey(r)) {
break;
}
// 检查其它要求
if (this.startReqs.size() == 0) { // 没有条件要求
isCanStart = true;
break;
} else {
boolean isOk = true;
for(MapleQuestRequirement re : this.startReqs) {
if (re.check(chr,npcid) == false) {
isOk = false;
break;
}
}
isCanStart = isOk;
}
break;
}
// 检查已经开始的任务
MapleQuest tmp = chr.getQuestInfoById(getId());
if (tmp != null) {
return false;
}
return isCanStart;
}
/**
* 根据NPC来获取任务列表
* @param npcId
* @return
*/
public List <Integer> getQuestIdByNpcId(int npcId) {
List <Integer> questList = this.npcQuest.get(npcId);
if (questList == null) {
return new ArrayList<Integer>();
} else {
return questList;
}
}
/**
* 判断任务是否能够完成
* @param chr
* @return
*/
public boolean canComplete(MapleCharacter chr) {
if (chr.getQuest(this).getStatus() != 1) {
return false;
}
if ((this.blocked) && (!chr.isGM())) {
return false;
}
// if ((this.autoComplete) && (npcid != null) && (this.viewMedalItem <= 0)) {
// forceComplete(chr, npcid);
// return false;
// }
String queststatus = chr.getQuest(this).getCustomData();
List <MapleQuestComplete> com = this.completeReqs.get(queststatus);
if (com == null) {
return false;
}
for (MapleQuestComplete r : com) {
if (!r.check(chr)) {
return false;
}
}
return true;
}
public void RestoreLostItem(MapleCharacter chr, int itemid) {
if ((this.blocked) && (!chr.isGM())) {
return;
}
// for (MapleQuestAction a : this.startActs) {
// if (a.RestoreLostItem(chr, itemid)) {
// break;
// }
// }
}
/**
* 开始WZ中的任务
* @param chr
* @param npc
*/
public boolean start(MapleCharacter chr, int npc) {
boolean isComplete = false;
if ((checkNPCOnMap(chr, npc))) {
// 检查是否达到任务完成条件
for (Integer questId : getQuestIdByNpcId(npc)) {
MapleQuest chrQuest = chr.getQuestInfoById(questId);
if (chrQuest == null) {
isComplete = false;
break;
}
if (chrQuest.canComplete(chr)) {
chrQuest.complete(chr,npc);
isComplete = true;
}
}
return isComplete;
} else {
FileoutputUtil.log("NPC不在该地图上:"+npc);
return isComplete;
}
}
public void complete(MapleCharacter chr, int npc) {
complete(chr, npc, null);
}
/**
* 完成玩家的任务
* @param chr
* @param npc
* @param selection
*/
public void complete(MapleCharacter chr, int npc, Integer selection) {
if ((chr.getMap() != null) && ((this.autoPreComplete) || (checkNPCOnMap(chr, npc))) && (canComplete(chr))) {
// 扣除任务道具
List <MapleQuestComplete> com = this.completeReqs.get(chr.getQuest(this).getCustomData());
boolean removeItem = true;
for (MapleQuestComplete r : com) {
if (r.removeQuestItem(chr) == false) {
removeItem = false;
return ;
}
}
if (removeItem == true) {
// 更新玩家任务状态
forceComplete(chr, npc);
// 发送奖励
String curStatus = chr.getQuest(this).getCustomData();
List <MapleQuestReward> rewardData = this.rewards.get(curStatus);
// 通用奖励,金币和经验
if (rewardData == null) {
return ;
}
for (MapleQuestReward reward : rewardData) {
reward.getRewardToChr(chr);
}
}
}
}
public void forfeit(MapleCharacter chr) {
if (chr.getQuest(this).getStatus() != 1) {
return;
}
MapleQuestStatus oldStatus = chr.getQuest(this);
MapleQuestStatus newStatus = new MapleQuestStatus(this, 0);
newStatus.setForfeited(oldStatus.getForfeited() + 1);
newStatus.setCompletionTime(oldStatus.getCompletionTime());
chr.updateQuest(newStatus);
}
public void forceStart(MapleCharacter chr, int npc, String customData) {
MapleQuestStatus newStatus = new MapleQuestStatus(this, (byte) 1, npc);
newStatus.setForfeited(chr.getQuest(this).getForfeited());
newStatus.setCompletionTime(chr.getQuest(this).getCompletionTime());
newStatus.setCustomData(customData);
chr.updateQuest(newStatus);
}
/**
* 完成任务
* @param chr
* @param npc
*/
public void forceComplete(MapleCharacter chr, int npc) {
MapleQuestStatus newStatus = new MapleQuestStatus(this, (byte) MapleQuestStatus.QUEST_COMPLETED, npc);
newStatus.setForfeited(chr.getQuest(this).getForfeited());
String nextData = this.questStatusList.get(chr.getQuest(this).getCustomData());
if (nextData == null) {
nextData = this.endStatus;
}
newStatus.setCustomData(nextData);
chr.updateQuest(newStatus);
chr.dropMessage(0,"恭喜完成任务:"+this.getName());
}
public int getId() {
return this.id;
}
private boolean checkNPCOnMap(MapleCharacter player, int npcId) {
return ((npcId == 1013000)) || (npcId == 2151009) || (npcId == 3000018) || (npcId == 9010000) || ((npcId >= 2161000) && (npcId <= 2161011)) || (npcId == 9000040) || (npcId == 9000066) || (npcId == 2010010) || (npcId == 1032204) || (npcId == 0) || ((player.getMap() != null) && (player.getMap().containsNPC(npcId)));
}
public int getMedalItem() {
return this.viewMedalItem;
}
public boolean isBlocked() {
return this.blocked;
}
public boolean hasStartScript() {
return this.scriptedStart;
}
public boolean hasEndScript() {
return this.customend;
}
}