Empty messages, minLevel, maxLevel and monsterIds LongTimeEvent parameters.

This commit is contained in:
MobiusDevelopment
2019-11-19 00:10:54 +00:00
parent e847e61cd5
commit ead417a1bf
102 changed files with 2254 additions and 2693 deletions

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -67,6 +66,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1097,12 +1097,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -66,6 +65,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1093,12 +1093,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -66,6 +65,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1093,12 +1093,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -66,6 +65,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1093,12 +1093,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -65,6 +64,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1082,12 +1082,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -65,6 +64,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1082,12 +1082,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -65,6 +64,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1082,12 +1082,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -65,6 +64,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1090,12 +1090,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -35,7 +35,6 @@ import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.ai.FortSiegeGuardAI; import org.l2jmobius.gameserver.ai.FortSiegeGuardAI;
import org.l2jmobius.gameserver.ai.SiegeGuardAI; import org.l2jmobius.gameserver.ai.SiegeGuardAI;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -61,6 +60,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1044,18 +1044,28 @@ public class Attackable extends Npc
final PlayerInstance player = lastAttacker.getActingPlayer(); final PlayerInstance player = lastAttacker.getActingPlayer();
// Don't drop anything if the last attacker or owner isn't PlayerInstance // Don't drop anything if the last attacker or owner isn't PlayerInstance
if ((player == null) || ((player.getLevel() - getLevel()) > 9)) if (player == null)
{
return;
}
if ((player.getLevel() - getLevel()) > 9)
{ {
return; return;
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -43,7 +43,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -57,8 +57,9 @@ public class LongTimeEvent extends Quest
private String _eventName; private String _eventName;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -67,7 +68,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -169,7 +170,20 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
final int finalChance = !chance.isEmpty() && chance.endsWith("%") ? Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000 : 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{
for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
}
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
{ {
@@ -183,13 +197,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -293,18 +307,17 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
final long currentTime = System.currentTimeMillis(); // Add drop.
// Add drop if (_dropList != null)
if ((_dropList != null) && (currentTime < _dropPeriod.getEndDate().getTime()))
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - currentTime; final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
for (NpcSpawn spawn : _spawnList) for (NpcSpawn spawn : _spawnList)
@@ -313,13 +326,19 @@ public class LongTimeEvent extends Quest
} }
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -363,9 +382,19 @@ public class LongTimeEvent extends Quest
{ {
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -382,7 +411,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -35,7 +35,6 @@ import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.ai.FortSiegeGuardAI; import org.l2jmobius.gameserver.ai.FortSiegeGuardAI;
import org.l2jmobius.gameserver.ai.SiegeGuardAI; import org.l2jmobius.gameserver.ai.SiegeGuardAI;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -61,6 +60,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.attackable.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1044,18 +1044,28 @@ public class Attackable extends Npc
final PlayerInstance player = lastAttacker.getActingPlayer(); final PlayerInstance player = lastAttacker.getActingPlayer();
// Don't drop anything if the last attacker or owner isn't PlayerInstance // Don't drop anything if the last attacker or owner isn't PlayerInstance
if ((player == null) || ((player.getLevel() - getLevel()) > 9)) if (player == null)
{
return;
}
if ((player.getLevel() - getLevel()) > 9)
{ {
return; return;
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -43,7 +43,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -57,8 +57,9 @@ public class LongTimeEvent extends Quest
private String _eventName; private String _eventName;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -67,7 +68,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -169,7 +170,20 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
final int finalChance = !chance.isEmpty() && chance.endsWith("%") ? Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000 : 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{
for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
}
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
{ {
@@ -183,13 +197,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -293,18 +307,17 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
final long currentTime = System.currentTimeMillis(); // Add drop.
// Add drop if (_dropList != null)
if ((_dropList != null) && (currentTime < _dropPeriod.getEndDate().getTime()))
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - currentTime; final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
for (NpcSpawn spawn : _spawnList) for (NpcSpawn spawn : _spawnList)
@@ -313,13 +326,19 @@ public class LongTimeEvent extends Quest
} }
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -363,9 +382,19 @@ public class LongTimeEvent extends Quest
{ {
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -382,7 +411,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -66,6 +65,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1093,12 +1093,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -66,6 +65,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1093,12 +1093,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -66,6 +65,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1093,12 +1093,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -68,6 +67,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1115,12 +1115,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -68,6 +67,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1115,12 +1115,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -68,6 +67,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1115,12 +1115,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.announce.EventAnnouncement; import org.l2jmobius.gameserver.model.announce.EventAnnouncement;
import org.l2jmobius.gameserver.model.holders.DropHolder; import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.util.Broadcast; import org.l2jmobius.gameserver.util.Broadcast;
@@ -58,8 +58,9 @@ public class LongTimeEvent extends Quest
boolean _enableShrines = false; boolean _enableShrines = false;
// Messages // Messages
protected String _onEnterMsg = "Event is in process"; protected String _onEnterMsg = "";
protected String _endMsg = "Event ends!"; protected String _endMsg = "";
private int _enterAnnounceId = -1;
protected DateRange _eventPeriod = null; protected DateRange _eventPeriod = null;
protected DateRange _dropPeriod; protected DateRange _dropPeriod;
@@ -68,7 +69,7 @@ public class LongTimeEvent extends Quest
protected final List<NpcSpawn> _spawnList = new ArrayList<>(); protected final List<NpcSpawn> _spawnList = new ArrayList<>();
// Drop data for event // Drop data for event
protected final List<DropHolder> _dropList = new ArrayList<>(); protected final List<EventDropHolder> _dropList = new ArrayList<>();
// Items to destroy when event ends. // Items to destroy when event ends.
protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>(); protected final List<Integer> _destoyItemsOnEnd = new ArrayList<>();
@@ -165,8 +166,7 @@ public class LongTimeEvent extends Quest
if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
{ {
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
// Loading droplist // Loading droplist
if (n.getNodeName().equalsIgnoreCase("droplist")) if (n.getNodeName().equalsIgnoreCase("droplist"))
@@ -181,11 +181,19 @@ public class LongTimeEvent extends Quest
final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); final int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); final int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
final String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); final String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
int finalChance = 0; final double finalChance = !chance.isEmpty() && chance.endsWith("%") ? Double.parseDouble(chance.substring(0, chance.length() - 1)) : 0;
final Node minLevelNode = d.getAttributes().getNamedItem("minLevel");
if (!chance.isEmpty() && chance.endsWith("%")) final int minLevel = minLevelNode == null ? 1 : Integer.parseInt(minLevelNode.getNodeValue());
final Node maxLevelNode = d.getAttributes().getNamedItem("maxLevel");
final int maxLevel = maxLevelNode == null ? Integer.MAX_VALUE : Integer.parseInt(maxLevelNode.getNodeValue());
final Node monsterIdsNode = d.getAttributes().getNamedItem("monsterIds");
final List<Integer> monsterIds = new ArrayList<>();
if (monsterIdsNode != null)
{ {
finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; for (String id : monsterIdsNode.getNodeValue().split(","))
{
monsterIds.add(Integer.parseInt(id));
}
} }
if (ItemTable.getInstance().getTemplate(itemId) == null) if (ItemTable.getInstance().getTemplate(itemId) == null)
@@ -200,13 +208,13 @@ public class LongTimeEvent extends Quest
continue; continue;
} }
if ((finalChance < 10000) || (finalChance > 1000000)) if ((finalChance < 0) || (finalChance > 100))
{ {
LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); LOGGER.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
continue; continue;
} }
_dropList.add(new DropHolder(null, itemId, minCount, maxCount, finalChance)); _dropList.add(new EventDropHolder(itemId, minCount, maxCount, finalChance, minLevel, maxLevel, monsterIds));
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
@@ -272,8 +280,7 @@ public class LongTimeEvent extends Quest
} }
// Load destroy item list at all times. // Load destroy item list at all times.
final Node first = doc.getDocumentElement().getFirstChild(); for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
for (Node n = first; n != null; n = n.getNextSibling())
{ {
if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd")) if (n.getNodeName().equalsIgnoreCase("destoyItemsOnEnd"))
{ {
@@ -309,16 +316,16 @@ public class LongTimeEvent extends Quest
*/ */
protected void startEvent() protected void startEvent()
{ {
// Add drop // Add drop.
if (_dropList != null) if (_dropList != null)
{ {
for (DropHolder drop : _dropList) for (EventDropHolder drop : _dropList)
{ {
EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); EventDroplist.getInstance().addGlobalDrop(_dropPeriod, drop);
} }
} }
// Add spawns // Add spawns.
final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); final Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
if (_spawnList != null) if (_spawnList != null)
{ {
@@ -328,19 +335,25 @@ public class LongTimeEvent extends Quest
} }
} }
// Enable town shrines // Enable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(true); EventShrineManager.getInstance().setEnabled(true);
} }
// Send message on begin // Event enter announcement.
if (!_onEnterMsg.isEmpty())
{
// Send message on begin.
Broadcast.toAllOnlinePlayers(_onEnterMsg); Broadcast.toAllOnlinePlayers(_onEnterMsg);
// Add announce for entering players // Add announce for entering players.
AnnouncementsTable.getInstance().addAnnouncement(new EventAnnouncement(_eventPeriod, _onEnterMsg)); final EventAnnouncement announce = new EventAnnouncement(_eventPeriod, _onEnterMsg);
AnnouncementsTable.getInstance().addAnnouncement(announce);
_enterAnnounceId = announce.getId();
}
// Schedule event end (now only for message sending) // Schedule event end.
ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd); ThreadPool.schedule(new ScheduleEnd(), millisToEventEnd);
} }
@@ -382,16 +395,27 @@ public class LongTimeEvent extends Quest
@Override @Override
public void run() public void run()
{ {
// Disable town shrines // Disable town shrines.
if (_enableShrines) if (_enableShrines)
{ {
EventShrineManager.getInstance().setEnabled(false); EventShrineManager.getInstance().setEnabled(false);
} }
// Destroy items that must exist only on event period. // Destroy items that must exist only on event period.
destoyItemsOnEnd(); destoyItemsOnEnd();
// Send message on end
// Send message on end.
if (!_endMsg.isEmpty())
{
Broadcast.toAllOnlinePlayers(_endMsg); Broadcast.toAllOnlinePlayers(_endMsg);
} }
// Remove announce for entering players.
if (_enterAnnounceId != -1)
{
AnnouncementsTable.getInstance().deleteAnnouncement(_enterAnnounceId);
}
}
} }
void destoyItemsOnEnd() void destoyItemsOnEnd()
@@ -408,7 +432,7 @@ public class LongTimeEvent extends Quest
player.destroyItemByItemId(_eventName, itemId, -1, player, true); player.destroyItemByItemId(_eventName, itemId, -1, player, true);
} }
} }
// Update database // Update database.
try (Connection con = DatabaseFactory.getConnection(); try (Connection con = DatabaseFactory.getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?")) PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE item_id=?"))
{ {

View File

@@ -1,79 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.script;
/**
* @author Zoey76
*/
public class EventDrop
{
private final int[] _itemIdList;
private final long _minCount;
private final long _maxCount;
private final int _dropChance;
public EventDrop(int[] itemIdList, long min, long max, int dropChance)
{
_itemIdList = itemIdList;
_minCount = min;
_maxCount = max;
_dropChance = dropChance;
}
public EventDrop(int itemId, long minCount, long maxCount, int dropChance)
{
_itemIdList = new int[]
{
itemId
};
_minCount = minCount;
_maxCount = maxCount;
_dropChance = dropChance;
}
/**
* @return the _itemId
*/
public int[] getItemIdList()
{
return _itemIdList;
}
/**
* @return the _minCount
*/
public long getMinCount()
{
return _minCount;
}
/**
* @return the _maxCount
*/
public long getMaxCount()
{
return _maxCount;
}
/**
* @return the _dropChance
*/
public int getDropChance()
{
return _dropChance;
}
}

View File

@@ -12,6 +12,9 @@
<xs:attribute name="min" type="xs:positiveInteger" use="required" /> <xs:attribute name="min" type="xs:positiveInteger" use="required" />
<xs:attribute name="max" type="xs:positiveInteger" use="required" /> <xs:attribute name="max" type="xs:positiveInteger" use="required" />
<xs:attribute name="chance" type="xs:token" use="required" /> <xs:attribute name="chance" type="xs:token" use="required" />
<xs:attribute name="minLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="maxLevel" type="xs:positiveInteger" use="optional" />
<xs:attribute name="monsterIds" type="xs:string" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>

View File

@@ -16,14 +16,13 @@
*/ */
package org.l2jmobius.gameserver.datatables; package org.l2jmobius.gameserver.datatables;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.script.DateRange; import org.l2jmobius.gameserver.script.DateRange;
import org.l2jmobius.gameserver.script.EventDrop;
/** /**
* This class manage drop of Special Events created by GM for a defined period.<br> * This class manage drop of Special Events created by GM for a defined period.<br>
@@ -38,28 +37,22 @@ public class EventDroplist
*/ */
private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet(); private static final Collection<DateDrop> ALL_NPC_DATE_DROPS = ConcurrentHashMap.newKeySet();
public static class DateDrop private static final class DateDrop
{ {
protected final DateRange _dateRange; private final DateRange _dateRange;
private final EventDrop _eventDrop; private final EventDropHolder _eventDrop;
public DateDrop(DateRange dateRange, EventDrop eventDrop) public DateDrop(DateRange dateRange, EventDropHolder eventDrop)
{ {
_dateRange = dateRange; _dateRange = dateRange;
_eventDrop = eventDrop; _eventDrop = eventDrop;
} }
/** public EventDropHolder getEventDrop()
* @return the _eventDrop
*/
public EventDrop getEventDrop()
{ {
return _eventDrop; return _eventDrop;
} }
/**
* @return the _dateRange
*/
public DateRange getDateRange() public DateRange getDateRange()
{ {
return _dateRange; return _dateRange;
@@ -67,51 +60,26 @@ public class EventDroplist
} }
/** /**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .
* @param itemIdList The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param dateRange The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] itemIdList, int[] count, int chance, DateRange dateRange)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemIdList, count[0], count[1], chance)));
}
/**
* @param itemId the item Id for the drop
* @param min the minimum drop count
* @param max the maximum drop count
* @param chance the drop chance
* @param dateRange the event drop rate range * @param dateRange the event drop rate range
* @param drop the event drop
*/ */
public void addGlobalDrop(int itemId, long min, long max, int chance, DateRange dateRange) public void addGlobalDrop(DateRange dateRange, EventDropHolder drop)
{ {
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, new EventDrop(itemId, min, max, chance))); ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, drop));
}
/**
* Adds an event drop for a given date range.
* @param dateRange the date range.
* @param eventDrop the event drop.
*/
public void addGlobalDrop(DateRange dateRange, EventDrop eventDrop)
{
ALL_NPC_DATE_DROPS.add(new DateDrop(dateRange, eventDrop));
} }
/** /**
* @return all DateDrop of EventDroplist allNpcDateDrops within the date range. * @return all DateDrop of EventDroplist allNpcDateDrops within the date range.
*/ */
public List<DateDrop> getAllDrops() public Collection<EventDropHolder> getAllDrops()
{ {
final List<DateDrop> list = new LinkedList<>(); final Collection<EventDropHolder> list = new ArrayList<>();
final Date currentDate = new Date(); final Date currentDate = new Date();
for (DateDrop drop : ALL_NPC_DATE_DROPS) for (DateDrop drop : ALL_NPC_DATE_DROPS)
{ {
if (drop._dateRange.isWithinRange(currentDate)) if (drop.getDateRange().isWithinRange(currentDate))
{ {
list.add(drop); list.add(drop.getEventDrop());
} }
} }
return list; return list;

View File

@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData; import org.l2jmobius.gameserver.data.xml.impl.ExtendDropData;
import org.l2jmobius.gameserver.datatables.EventDroplist; import org.l2jmobius.gameserver.datatables.EventDroplist;
import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable; import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType; import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType; import org.l2jmobius.gameserver.enums.DropType;
@@ -66,6 +65,7 @@ import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill; import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableKill;
import org.l2jmobius.gameserver.model.holders.EventDropHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.SkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Item;
@@ -1093,12 +1093,17 @@ public class Attackable extends Npc
} }
// Go through DateDrop of EventDroplist allNpcDateDrops within the date range // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) for (EventDropHolder drop : EventDroplist.getInstance().getAllDrops())
{ {
if (Rnd.get(1000000) < drop.getEventDrop().getDropChance()) if (!drop.getMonsterIds().isEmpty() && !drop.getMonsterIds().contains(getId()))
{ {
final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)]; continue;
final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()); }
final int monsterLevel = getLevel();
if ((monsterLevel >= drop.getMinLevel()) && (monsterLevel <= drop.getMaxLevel()) && (Rnd.get(100d) < drop.getChance()))
{
final int itemId = drop.getItemId();
final long itemCount = Rnd.get(drop.getMin(), drop.getMax());
if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying()) if (Config.AUTO_LOOT_ITEM_IDS.contains(itemId) || Config.AUTO_LOOT || isFlying())
{ {
player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the PlayerInstance that has killed the Attackable

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program 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.
*
* 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
* 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 org.l2jmobius.gameserver.model.holders;
import java.util.Collection;
/**
* @author Mobius
*/
public class EventDropHolder extends DropHolder
{
private final int _minLevel;
private final int _maxLevel;
private final Collection<Integer> _monsterIds;
public EventDropHolder(int itemId, long min, long max, double chance, int minLevel, int maxLevel, Collection<Integer> monsterIds)
{
super(null, itemId, min, max, chance);
_minLevel = minLevel;
_maxLevel = maxLevel;
_monsterIds = monsterIds;
}
public int getMinLevel()
{
return _minLevel;
}
public int getMaxLevel()
{
return _maxLevel;
}
public Collection<Integer> getMonsterIds()
{
return _monsterIds;
}
}

Some files were not shown because too many files have changed in this diff Show More