/*
OrpheusMS: MapleStory Private Server based on OdinMS
Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net>
Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server.quest;
import java.util.HashMap;
import java.util.Map;
import client.ISkill;
import client.MapleCharacter;
import client.MapleInventoryType;
import client.MapleJob;
import client.MapleQuestStatus;
import client.MapleStat;
import client.SkillFactory;
import constants.ItemConstants;
import constants.ServerConstants;
import provider.MapleData;
import provider.MapleDataTool;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import tools.MaplePacketCreator;
import tools.Randomizer;
/**
*
* @author Matze
*/
public class MapleQuestAction {
private MapleQuestActionType type;
private MapleData data;
private MapleQuest quest;
public MapleQuestAction(MapleQuestActionType type, MapleData data, MapleQuest quest) {
this.type = type;
this.data = data;
this.quest = quest;
}
public boolean check(MapleCharacter c) { // LOL WTF IS THIS CRAP
switch (type) {
case MESO:
int mesos = MapleDataTool.getInt(data);
if (c.getMeso() < mesos) {
return false;
}
break;
}
return true;
}
private boolean canGetItem(MapleData item, MapleCharacter c) {
if (item.getChildByPath("gender") != null) {
int gender = MapleDataTool.getInt(item.getChildByPath("gender"));
if (gender != 2 && gender != c.getGender()) {
return false;
}
}
if (item.getChildByPath("job") != null) {
int job = MapleDataTool.getInt(item.getChildByPath("job"));
if (job < 100) {
if (MapleJob.getBy5ByteEncoding(job).getId() / 100 != c.getJob().getId() / 100) {
return false;
}
} else if (job != c.getJob().getId()) {
return false;
}
}
return true;
}
public void run(MapleCharacter c, Integer extSelection) {
MapleQuestStatus status;
switch (type) {
case EXP:
status = c.getQuest(quest);
if (status.getStatus() == MapleQuestStatus.Status.NOT_STARTED && status.getForfeited() > 0) {
break;
}
if (c.isBeginnerJob()) {
c.gainExp(MapleDataTool.getInt(data), true, true);
} else {
c.gainExp(MapleDataTool.getInt(data) * ServerConstants.QUEST_EXP_RATE, true, true);
}
break;
case ITEM:
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Map<Integer, Integer> props = new HashMap<Integer, Integer>();
for (MapleData iEntry : data.getChildren()) {
if (iEntry.getChildByPath("prop") != null && MapleDataTool.getInt(iEntry.getChildByPath("prop")) != -1 && canGetItem(iEntry, c)) {
for (int i = 0; i < MapleDataTool.getInt(iEntry.getChildByPath("prop")); i++) {
props.put(props.size(), MapleDataTool.getInt(iEntry.getChildByPath("id")));
}
}
}
int selection = 0;
int extNum = 0;
if (props.size() > 0) {
selection = props.get(Randomizer.nextInt(props.size()));
}
for (MapleData iEntry : data.getChildren()) {
if (!canGetItem(iEntry, c)) {
continue;
}
if (iEntry.getChildByPath("prop") != null) {
if (MapleDataTool.getInt(iEntry.getChildByPath("prop")) == -1) {
if (extSelection != extNum++) {
continue;
}
} else if (MapleDataTool.getInt(iEntry.getChildByPath("id")) != selection) {
continue;
}
}
if (MapleDataTool.getInt(iEntry.getChildByPath("count"), 0) < 0) { // remove
// items
int itemId = MapleDataTool.getInt(iEntry.getChildByPath("id"));
MapleInventoryType iType = ii.getInventoryType(itemId);
short quantity = (short) (MapleDataTool.getInt(iEntry.getChildByPath("count"), 0) * -1);
MapleInventoryManipulator.removeById(c.getClient(), iType, itemId, quantity, true, false);
c.getClient().getSession().write(MaplePacketCreator.getShowItemGain(itemId, (short) MapleDataTool.getInt(iEntry.getChildByPath("count"), 0), true));
} else { // add items
int itemId = MapleDataTool.getInt(iEntry.getChildByPath("id"));
short quantity = (short) MapleDataTool.getInt(iEntry.getChildByPath("count"), 0);
if (c.getInventory(MapleItemInformationProvider.getInstance().getInventoryType(itemId)).getNextFreeSlot() > -1) {
MapleInventoryManipulator.addById(c.getClient(), itemId, quantity);
c.getClient().getSession().write(MaplePacketCreator.getShowItemGain(itemId, quantity, true));
} else {
c.dropMessage(1, "Inventory Full");
}
}
}
break;
case NEXTQUEST:
status = c.getQuest(quest);
int nextQuest = MapleDataTool.getInt(data);
if (status.getStatus() == MapleQuestStatus.Status.NOT_STARTED && status.getForfeited() > 0) {
break;
}
c.getClient().getSession().write(MaplePacketCreator.updateQuestFinish((short) quest.getId(), status.getNpc(), (short) nextQuest));
break;
case MESO:
status = c.getQuest(quest);
if (status.getStatus() == MapleQuestStatus.Status.NOT_STARTED && status.getForfeited() > 0) {
break;
}
c.gainMeso(MapleDataTool.getInt(data) * ServerConstants.QUEST_MESO_RATE, true, false, true);
break;
case QUEST:
for (MapleData qEntry : data) {
int questid = MapleDataTool.getInt(qEntry.getChildByPath("id"));
int stat = MapleDataTool.getInt(qEntry.getChildByPath("state"));
c.updateQuest(new MapleQuestStatus(MapleQuest.getInstance(questid), MapleQuestStatus.Status.getById(stat)));
}
break;
case SKILL:
for (MapleData sEntry : data) {
int skillid = MapleDataTool.getInt(sEntry.getChildByPath("id"));
byte skillLevel = (byte) MapleDataTool.getInt(sEntry.getChildByPath("skillLevel"));
int masterLevel = MapleDataTool.getInt(sEntry.getChildByPath("masterLevel"));
ISkill skillObject = SkillFactory.getSkill(skillid);
boolean shouldLearn = false;
MapleData applicableJobs = sEntry.getChildByPath("job");
for (MapleData applicableJob : applicableJobs) {
MapleJob job = MapleJob.getById(MapleDataTool.getInt(applicableJob));
if (c.getJob() == job) {
shouldLearn = true;
break;
}
}
if (skillObject.isBeginnerSkill()) {
shouldLearn = true;
}
skillLevel = (byte) Math.max(skillLevel, c.getSkillLevel(skillObject));
masterLevel = Math.max(masterLevel, c.getMasterLevel(skillObject));
if (shouldLearn) {
c.changeSkillLevel(skillObject, skillLevel, masterLevel, -1);
}
}
break;
case FAME:
status = c.getQuest(quest);
if (status.getStatus() == MapleQuestStatus.Status.NOT_STARTED && status.getForfeited() > 0) {
break;
}
c.addFame(MapleDataTool.getInt(data));
c.updateSingleStat(MapleStat.FAME, c.getFame());
int fameGain = MapleDataTool.getInt(data);
c.getClient().getSession().write(MaplePacketCreator.getShowFameGain(fameGain));
break;
case BUFF:
status = c.getQuest(quest);
if (status.getStatus() == MapleQuestStatus.Status.NOT_STARTED && status.getForfeited() > 0) {
break;
}
MapleItemInformationProvider.getInstance().getItemEffect(MapleDataTool.getInt(data)).applyTo(c);
break;
case PETSKILL:
status = c.getQuest(quest);
if (status.getStatus() == MapleQuestStatus.Status.NOT_STARTED && status.getForfeited() > 0) {
break;
}
int flag = MapleDataTool.getInt("petskill", data);
c.getPet(0).setFlag((byte) ItemConstants.getFlagByInt(flag));
break;
default:
}
}
}