package scripting;
import client.MapleClient;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.GameConstants;
import handling.channel.ChannelServer;
import java.awt.Point;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import server.MapleCarnivalFactory;
import server.MapleCarnivalFactory.MCSkill;
import server.MapleItemInformationProvider;
import server.Randomizer;
import server.life.MapleLifeFactory;
import server.life.MapleMonster;
import server.maps.MapleReactor;
import server.maps.ReactorDropEntry;
import tools.FileoutputUtil;
import tools.packet.CField;
public class ReactorActionManager extends AbstractPlayerInteraction {
private final MapleReactor reactor;
public ReactorActionManager(MapleClient c, MapleReactor reactor) {
super(c, reactor.getReactorId(), c.getPlayer().getMapId(), null);
this.reactor = reactor;
}
// only used for meso = false, really. No minItems because meso is used to fill the gap
public void dropItems() {
dropItems(false, 0, 0, 0, 0);
}
public void dropItems(boolean meso, int mesoChance, int minMeso, int maxMeso) {
dropItems(meso, mesoChance, minMeso, maxMeso, 0);
}
public void dropItems(boolean meso, int mesoChance, int minMeso, int maxMeso, int minItems) {
final List<ReactorDropEntry> chances = ReactorScriptManager.getInstance().getDrops(reactor.getReactorId());
final List<ReactorDropEntry> items = new LinkedList<>();
if (meso) {
if (Math.random() < (1 / (double) mesoChance)) {
items.add(new ReactorDropEntry(0, mesoChance, -1));
}
}
int numItems = 0;
// narrow list down by chances
final Iterator<ReactorDropEntry> iter = chances.iterator();
// for (DropEntry d : chances){
while (iter.hasNext()) {
ReactorDropEntry d = iter.next();
if (Math.random() < (1 / (double) d.chance) && (d.questid <= 0 || getPlayer().getQuestStatus(d.questid) == 1)) {
numItems++;
items.add(d);
}
}
// if a minimum number of drops is required, add meso
while (items.size() < minItems) {
items.add(new ReactorDropEntry(0, mesoChance, -1));
numItems++;
}
final Point dropPos = reactor.getPosition();
dropPos.x -= (12 * numItems);
int range, mesoDrop;
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (final ReactorDropEntry d : items) {
if (d.itemId == 0) {
range = maxMeso - minMeso;
mesoDrop = Randomizer.nextInt(range) + minMeso * ChannelServer.getInstance(getClient().getChannel()).getMesoRate(getClient().getPlayer() != null ? getClient().getPlayer().getWorld() : 0);
reactor.getMap().spawnMesoDrop(mesoDrop, dropPos, reactor, getPlayer(), false, (byte) 0);
} else {
Item drop;
if (GameConstants.getInventoryType(d.itemId) != MapleInventoryType.EQUIP) {
drop = new Item(d.itemId, (byte) 0, (short) 1, (byte) 0);
} else {
drop = ii.randomizeStats((Equip) ii.getEquipById(d.itemId));
}
drop.setGMLog("從反應堆" + reactor.getReactorId() + "中掉寶,地圖" + getPlayer().getMap() + "時間 " + FileoutputUtil.CurrentReadable_Time());
reactor.getMap().spawnItemDrop(reactor, getPlayer(), drop, dropPos, false, false);
}
dropPos.x += 25;
}
}
public void dropSingleItem(int itemId) {
Item drop;
if (GameConstants.getInventoryType(itemId) != MapleInventoryType.EQUIP) {
drop = new Item(itemId, (byte) 0, (short) 1, (byte) 0);
} else {
drop = MapleItemInformationProvider.getInstance().randomizeStats((Equip) MapleItemInformationProvider.getInstance().getEquipById(itemId));
}
drop.setGMLog("從反應堆" + reactor.getReactorId() + "中掉寶,地圖" + getPlayer().getMap() + "時間 " + FileoutputUtil.CurrentReadable_Time());
reactor.getMap().spawnItemDrop(reactor, getPlayer(), drop, reactor.getPosition(), false, false);
}
@Override
public void spawnNpc(int npcId) {
spawnNpc(npcId, getPosition());
}
// returns slightly above the reactor's position for monster spawns
public Point getPosition() {
Point pos = reactor.getPosition();
pos.y -= 10;
return pos;
}
public MapleReactor getReactor() {
return reactor;
}
public int hitBigby() {
MapleReactor bigby = null;
for (MapleReactor r : getMap().getAllReactor()) {
if (r.getReactorId() == 1301000) {
bigby = r;
}
}
if (bigby != null) {
bigby.forceHitReactor((byte) (bigby.getState() + 1));
if (bigby.getState() == 10) {
return 2;
}
return 1;
}
return 0;
}
public void spawnZakum() {
reactor.getMap().spawnZakum(getPosition().x, getPosition().y);
}
public void spawnFakeMonster(int id) {
spawnFakeMonster(id, 1, getPosition());
}
// summon one monster, remote location
public void spawnFakeMonster(int id, int x, int y) {
spawnFakeMonster(id, 1, new Point(x, y));
}
// multiple monsters, reactor location
public void spawnFakeMonster(int id, int qty) {
spawnFakeMonster(id, qty, getPosition());
}
// multiple monsters, remote location
public void spawnFakeMonster(int id, int qty, int x, int y) {
spawnFakeMonster(id, qty, new Point(x, y));
}
// handler for all spawnFakeMonster
private void spawnFakeMonster(int id, int qty, Point pos) {
for (int i = 0; i < qty; i++) {
reactor.getMap().spawnFakeMonsterOnGroundBelow(MapleLifeFactory.getMonster(id), pos);
}
}
public void killAll() {
reactor.getMap().killAllMonsters(true);
}
public void killMonster(int monsId) {
reactor.getMap().killMonster(monsId);
}
public void killReactor(int reactId) {
reactor.getMap().getReactorById(reactId).delayedDestroyReactor(1);
}
// summon one monster on reactor location
@Override
public void spawnMonster(int id) {
spawnMonster(id, 1, getPosition());
}
// summon monsters on reactor location
@Override
public void spawnMonster(int id, int qty) {
spawnMonster(id, qty, getPosition());
}
public void dispelAllMonsters(final int num) { //dispels all mobs, cpq
final MCSkill skil = MapleCarnivalFactory.getInstance().getGuardian(num);
if (skil != null) {
for (MapleMonster mons : getMap().getAllMonstersThreadsafe()) {
mons.dispelSkill(skil.getSkill());
}
}
}
public void cancelHarvest(boolean succ) {
getPlayer().setFatigue((byte) (getPlayer().getFatigue() + 1));
getPlayer().getMap().broadcastMessage(getPlayer(), CField.showHarvesting(getPlayer().getId(), 0), false);
getPlayer().getMap().broadcastMessage(CField.harvestResultEffect(getPlayer().getId(), succ));
getPlayer().getMap().broadcastMessage(CField.harvestResult(getPlayer().getId(), succ));
}
public void doHarvest() { //TODO LEGEND
if (getPlayer().getFatigue() >= 200 || getPlayer().getStat().harvestingTool <= 0 || getReactor().getTruePosition().distanceSq(getPlayer().getTruePosition()) > 10000) {
return;
}
final int pID = getReactor().getReactorId() < 200000 ? 92000000 : 92010000;
final String pName = (getReactor().getReactorId() < 200000 ? "藥草採集" : "採礦");
final int he = getPlayer().getProfessionLevel(pID);
if (he <= 0) {
return;
}
final Item item = getInventory(1).getItem((short) getPlayer().getStat().harvestingTool);
if (item == null || ((item.getItemId() / 10000)) != (getReactor().getReactorId() < 200000 ? 150 : 151)) {
return;
}
int hm = getReactor().getReactorId() % 100;
int successChance = 90 + ((he - hm) * 10);
if (getReactor().getReactorId() % 100 == 10) {
hm = 1;
successChance = 100;
} else if (getReactor().getReactorId() % 100 == 11) {
hm = 10;
successChance -= 40;
}
getPlayer().getStat().checkEquipDurabilitys(getPlayer(), -1, true);
int masteryIncrease = (hm - he) * 2 + 20;
final boolean succ = randInt(100) < successChance;
if (!succ) {
masteryIncrease /= 10;
dropSingleItem(getReactor().getReactorId() < 200000 ? 4022023 : 4010010);
} else {
dropItems();
if (getReactor().getReactorId() < 200000) {
addTrait("sense", 5);
if (Randomizer.nextInt(10) == 0) {
dropSingleItem(2440000);
}
if (Randomizer.nextInt(100) == 0) {
dropSingleItem(4032933);
}
} else {
addTrait("insight", 5);
if (Randomizer.nextInt(10) == 0) {
dropSingleItem(2440001); //IMP
}
}
}
cancelHarvest(succ);
playerMessage(-5, pName + "的熟練度增加。 (+" + masteryIncrease + ")");
if (getPlayer().addProfessionExp(pID, masteryIncrease)) {
playerMessage(-5, pName + "已升級。");
}
}
}