View difference between Paste ID: emSrp56A and KDSijJLX
SHOW: | | - or go back to the newest paste.
1
diff --git a/config/CustomMods/SpecialMods.ini b/config/CustomMods/SpecialMods.ini
2
index 28c8e27..661452f 100644
3
--- a/config/CustomMods/SpecialMods.ini
4
+++ b/config/CustomMods/SpecialMods.ini
5
@@ -1,4 +1,12 @@
6
 #=====================================================
7
+#              View Drop Mob Shift
8
+#=====================================================
9
+#Enable? Retail: False
10
+AltGameViewNpc = True
11
12
#=====================================================
13
 #       Admin Login On Skill Super Haste Active
14
 #=====================================================
15
 #Start with the super rod skill activated?
16
diff --git a/java/net/sf/l2j/Config.java b/java/net/sf/l2j/Config.java
17
index e0d8b1a..d159519 100644
18
--- a/java/net/sf/l2j/Config.java
19
+++ b/java/net/sf/l2j/Config.java
20
@@ -52,6 +52,8 @@
21
 	// Clans settings
22
 	// --------------------------------------------------
23
 	/** Clans */
24
+	public static boolean ALT_GAME_VIEWNPC;
25
 	public static boolean ANNOUNCE_BOSS_ALIVE;
26
 	public static boolean ANNOUNCE_RAIDBOS_KILL;
27
 	public static boolean ANNOUNCE_GRANDBOS_KILL;
28
@@ -1410,6 +1412,7 @@
29
 	private static final void loadSpecial()
30
 	{
31
 		final ExProperties Special = initProperties(SPECIAL_MODS);
32
+		ALT_GAME_VIEWNPC = Boolean.parseBoolean(Special.getProperty("AltGameViewNpc", "False"));
33
 		AUTO_LOOT_EXCLUDE_ITEMS = Special.getProperty("AutoLootExcludeItems", "1341,1342,1343,1344,1345");
34
 		String[] array = AUTO_LOOT_EXCLUDE_ITEMS.split(",");
35
 		AUTO_LOOT_LIST_EXCLUDE_ITEMS = new int[array.length];
36
diff --git a/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java b/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java
37
index 1eeeed6..1c2a717 100644
38
--- a/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java
39
+++ b/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java
40
@@ -27,6 +27,7 @@
41
 import net.sf.l2j.Config;
42
 import net.sf.l2j.gameserver.GameServer;
43
 import net.sf.l2j.gameserver.handler.voicedcommandhandlers.GainXpSp;
44
+import net.sf.l2j.gameserver.handler.voicedcommandhandlers.Shiff_Mod;
45
 import net.sf.l2j.gameserver.handler.voicedcommandhandlers.VoicedBanking;
46
 import net.sf.l2j.gameserver.handler.voicedcommandhandlers.VoicedBossSpawn;
47
 import net.sf.l2j.gameserver.handler.voicedcommandhandlers.VoicedCastles;
48
@@ -58,6 +59,7 @@
49
 	private VoicedCommandHandler()
50
 	{
51
 		_datatable = new HashMap<>();
52
+		registerVoicedCommandHandler(new Shiff_Mod());
53
 		if(Config.ENABLE_COMMAND_RAID)
54
 		{
55
 		registerVoicedCommandHandler(new VoicedBossSpawn());
56
diff --git a/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminEditChar.java b/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminEditChar.java
57
index 09a06a9..48cdbd5 100644
58
--- a/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminEditChar.java
59
+++ b/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminEditChar.java
60
@@ -579,7 +579,7 @@
61
 	 * @param player : The {@link Player} who requested that action.
62
 	 * @param targetPlayer : The {@link Player} target to gather informations from.
63
 	 */
64
-	private static void gatherPlayerInfo(Player player, Player targetPlayer)
65
+	public static void gatherPlayerInfo(Player player, Player targetPlayer)
66
 	{
67
 		final NpcHtmlMessage html = new NpcHtmlMessage(0);
68
 		gatherPlayerInfo(player, targetPlayer, html);
69
diff --git a/java/net/sf/l2j/gameserver/handler/voicedcommandhandlers/Shiff_Mod.java b/java/net/sf/l2j/gameserver/handler/voicedcommandhandlers/Shiff_Mod.java
70
new file mode 100644
71
index 0000000..6c8586e
72
--- /dev/null
73
+++ b/java/net/sf/l2j/gameserver/handler/voicedcommandhandlers/Shiff_Mod.java
74
@@ -0,0 +1,193 @@
75
+/* This program is free software: you can redistribute it and/or modify it under
76
+ * the terms of the GNU General Public License as published by the Free Software
77
+ * Foundation, either version 3 of the License, or (at your option) any later
78
+ * version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful, but WITHOUT
81
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
82
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
83
+ * details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License along with
86
+ * this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+package net.sf.l2j.gameserver.handler.voicedcommandhandlers;
89
+
90
+import java.text.DecimalFormat;
91
+import java.util.StringTokenizer;
92
+
93
+import net.sf.l2j.commons.lang.StringUtil;
94
+
95
+import net.sf.l2j.Config;
96
+import net.sf.l2j.gameserver.data.xml.IconTable;
97
+import net.sf.l2j.gameserver.data.xml.ItemData;
98
+import net.sf.l2j.gameserver.data.xml.NpcData;
99
+import net.sf.l2j.gameserver.handler.IVoicedCommandHandler;
100
+import net.sf.l2j.gameserver.model.actor.Player;
101
+import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
102
+import net.sf.l2j.gameserver.model.item.DropCategory;
103
+import net.sf.l2j.gameserver.model.item.DropData;
104
+import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
105
+import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
106
+
107
+public class Shiff_Mod implements IVoicedCommandHandler
108
+{
109
+	private final static int PAGE_LIMIT = 15;
110
+	private static final String[] _voicedCommands = 
111
+	{
112
+		"shifffmodddrop",
113
+	};
114
+	
115
+	@Override
116
+	public boolean useVoicedCommand(String command, Player activeChar, String target)
117
+	{
118
+		
119
+		if (activeChar.isDead() || activeChar.isFakeDeath() || activeChar.getKarma() > 0 || activeChar.getPvpFlag() > 0 || activeChar.isAlikeDead() || activeChar.isFestivalParticipant() || activeChar.isInJail() 
120
+			|| activeChar.isInOlympiadMode() || activeChar.isInObserverMode() ||  activeChar.isFlying() || activeChar.isTeleporting() || activeChar.isParalyzed() 
121
+			|| activeChar.isSleeping() || activeChar.isInDuel () || activeChar.isBetrayed() || activeChar.isMounted() || activeChar.isRooted())
122
+		{
123
+			activeChar.sendMessage("You Cannot Use This Command Right Now");
124
+			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
125
+			return false;
126
+		}
127
+		if (command.startsWith("shifffmodddrop"))
128
+		{
129
+			final StringTokenizer st = new StringTokenizer(command, " ");
130
+			st.nextToken();
131
+			int npcId = Integer.parseInt(st.nextToken());
132
+			int page = (st.hasMoreTokens()) ? Integer.parseInt(st.nextToken()) : 1;
133
+			
134
+			ShiffNpcDropList(activeChar, npcId, page);
135
+		}
136
+		return true;
137
+	}
138
+	
139
+	@Override
140
+	public String[] getVoicedCommandList()
141
+	{
142
+		return _voicedCommands;
143
+	}
144
+	
145
+	private static void ShiffNpcDropList(Player activeChar, int npcId, int page)
146
+	{
147
+		final NpcTemplate npcData = NpcData.getInstance().getTemplate(npcId);
148
+		if (npcData == null)
149
+		{
150
+			activeChar.sendMessage("Npc template is unknown for id: " + npcId + ".");
151
+			return;
152
+		}
153
+		
154
+		final StringBuilder sb = new StringBuilder(2000);
155
+		
156
+		if (!npcData.getDropData().isEmpty())
157
+		{
158
+			StringUtil.append(sb, "<html><title> ", npcData.getName(), " Drop List  ", page, "</title><body>");
159
+			StringUtil.append(sb, "<center><img src=\"l2ui_ch3.herotower_deco\" width=256 height=32><br>");
160
+			StringUtil.append(sb, "<img src=\"L2UI.SquareGray\" width=280 height=1>");
161
+			StringUtil.append(sb, "<table border=0 bgcolor=000000 width=\"290\"><tr>");
162
+			StringUtil.append(sb, "<td align=center><font color=\"LEVEL\">Name Item</font></td>");
163
+			StringUtil.append(sb, "<td align=center><font color=\"FF6600\">Quantity Drop</font></td>");
164
+			StringUtil.append(sb, "<td align=center>Chance Drop</td>");
165
+			StringUtil.append(sb, "</tr></table>");
166
+			StringUtil.append(sb, "<img src=\"L2UI.SquareGray\" width=280 height=1>");
167
+			StringUtil.append(sb, "<br><img src=\"L2UI.SquareGray\" width=280 height=1>");
168
+			
169
+			int myPage = 1;
170
+			int i = 0;
171
+			int shown = 0;
172
+			boolean hasMore = false;
173
+			
174
+			for (DropCategory cat : npcData.getDropData())
175
+			{
176
+				if (shown == PAGE_LIMIT)
177
+				{
178
+					hasMore = true;
179
+					break;
180
+				}
181
+				
182
+				for (DropData drop : cat.getAllDrops())
183
+				{
184
+					if (myPage != page)
185
+					{
186
+						i++;
187
+						if (i == PAGE_LIMIT)
188
+						{
189
+							myPage++;
190
+							i = 0;
191
+						}
192
+						continue;
193
+					}
194
+					
195
+					if (shown == PAGE_LIMIT)
196
+					{
197
+						hasMore = true;
198
+						break;
199
+					}
200
+					
201
+					
202
+					
203
+					DecimalFormat df2 = new DecimalFormat("##.##");
204
+					
205
+					double ChanceInt = ((double)drop.getChance()/10000 * Config.RATE_DROP_ITEMS);
206
+					String Chance = df2.format(ChanceInt);
207
+					
208
+					int caluleAdena = ((int)Config.RATE_DROP_ADENA + (int)Config.RATE_DROP_ITEMS);
209
+					
210
+					
211
+					StringUtil.append(sb, "<table bgcolor=000000><tr>");
212
+					StringUtil.append(sb, "<td><img src=\"" + IconTable.getIcon(drop.getItemId()) + "\" width=32 height=32></td><td>");
213
+					StringUtil.append(sb, "<table><tr><td><font color=\"LEVEL\">", ItemData.getInstance().getTemplate(drop.getItemId()).getName(), "</font>");
214
+					
215
+					//calculando porcentagem Adenas Drop
216
+					if(drop.getItemId() == 57) {
217
+						StringUtil.append(sb, "<font color=\"FF6600\"> (", drop.getMinDrop() * caluleAdena, "/", drop.getMaxDrop() * caluleAdena , ")</font>");
218
+					}
219
+					else
220
+					{
221
+						//calculando porcentagem Items Drop
222
+						StringUtil.append(sb, "<font color=\"FF6600\"> (", drop.getMinDrop() , "/", drop.getMaxDrop() , ")</font>");
223
+					}
224
+					StringUtil.append(sb, "</td></tr>"); 
225
+					StringUtil.append(sb, "<tr><td>Rate: " + String.valueOf(Chance) + "%" + (drop.isQuestDrop() ? "Quest" : (cat.isSweep() ? "<font color=\"00FF00\"> Sweep</font><img src=\"L2UI.SquareGray\" width=233 height=1>" : "<font color=\"3BB9FF\"> Drop</font><img src=\"L2UI.SquareGray\" width=233 height=1>")) + "</td></tr></table></td></tr>");
226
+					shown++;
227
+				}
228
+			}
229
+			
230
+			
231
+			StringUtil.append(sb, "</table>");
232
+			StringUtil.append(sb, "<img src=\"L2UI.SquareGray\" width=280 height=1><br>");
233
+			StringUtil.append(sb, "<img src=\"L2UI.SquareGray\" width=280 height=1>");
234
+			StringUtil.append(sb, "<table width=\"100%\" bgcolor=000000><tr>");
235
+			
236
+			if (page > 1)
237
+			{
238
+				StringUtil.append(sb, "<td width=120><a action=\"bypass -h voiced_shifffmodddrop ", npcId, " ", page - 1, "\">Prev Page</a></td>");
239
+				if (!hasMore)
240
+					StringUtil.append(sb, "<td width=100>Page ", page, "</td><td width=70></td></tr>");
241
+			}
242
+			
243
+			if (hasMore)
244
+			{
245
+				if (page <= 1)
246
+					StringUtil.append(sb, "<td width=120></td>");
247
+				
248
+				StringUtil.append(sb, "<td width=100>Page ", page, "</td><td width=70><a action=\"bypass -h voiced_shifffmodddrop ", npcId, " ", page + 1, "\">Next Page</a></td></tr>");
249
+			}
250
+			StringUtil.append(sb, "</table>");
251
+		}
252
+		else
253
+			StringUtil.append(sb, "This NPC has no drops.");
254
+		
255
+		StringUtil.append(sb, "</body></html>");
256
+		
257
+		final NpcHtmlMessage html = new NpcHtmlMessage(0);
258
+		html.setHtml(sb.toString());
259
+		activeChar.sendPacket(html);
260
+	}
261
+	
262
+	public void addRadar(Player activeChar, int x, int y, int z)
263
+	{
264
+		activeChar.getRadarList().addMarker(x, y, z);
265
+	}
266
+	
267
+}
268
\ No newline at end of file
269
diff --git a/java/net/sf/l2j/gameserver/model/WorldObject.java b/java/net/sf/l2j/gameserver/model/WorldObject.java
270
index 491d925..aec4dc6 100644
271
--- a/java/net/sf/l2j/gameserver/model/WorldObject.java
272
+++ b/java/net/sf/l2j/gameserver/model/WorldObject.java
273
@@ -175,7 +175,10 @@
274
 	{
275
 		_name = value;
276
 	}
277
-	
278
+	public void onActionShift(Player player)
279
+	{
280
+		player.sendPacket(ActionFailed.STATIC_PACKET);
281
+	}
282
 	public final int getObjectId()
283
 	{
284
 		return _objectId;
285
diff --git a/java/net/sf/l2j/gameserver/model/actor/Creature.java b/java/net/sf/l2j/gameserver/model/actor/Creature.java
286
index 95d63d2..c669703 100644
287
--- a/java/net/sf/l2j/gameserver/model/actor/Creature.java
288
+++ b/java/net/sf/l2j/gameserver/model/actor/Creature.java
289
@@ -48,6 +48,7 @@
290
 import net.sf.l2j.gameserver.model.location.Location;
291
 import net.sf.l2j.gameserver.model.zone.type.WaterZone;
292
 import net.sf.l2j.gameserver.network.serverpackets.AbstractNpcInfo.NpcInfo;
293
+import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
294
 import net.sf.l2j.gameserver.network.serverpackets.ChangeMoveType;
295
 import net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket;
296
 import net.sf.l2j.gameserver.network.serverpackets.Revive;
297
@@ -1436,7 +1437,16 @@
298
 				player.getAI().tryToInteract(this, isCtrlPressed, isShiftPressed);
299
 		}
300
 	}
301
+	@Override
302
+	public void onActionShift(Player player)
303
+	{
304
+		if (player.getTarget() != this)
305
+			player.setTarget(this);
306
+ 	
307
+		else
308
+			player.sendPacket(ActionFailed.STATIC_PACKET);
309
+			super.onActionShift(player);
310
+	}
311
 	/**
312
 	 * @return true if this {@link Creature} is inside an active {@link WorldRegion}.
313
 	 */
314
@@ -1884,7 +1894,6 @@
315
 	{
316
 		return false;
317
 	}
318
-	
319
 	/**
320
 	 * Test and cast curses if :
321
 	 * <ul>
322
diff --git a/java/net/sf/l2j/gameserver/model/actor/Npc.java b/java/net/sf/l2j/gameserver/model/actor/Npc.java
323
index 17a0088..95069bd 100644
324
--- a/java/net/sf/l2j/gameserver/model/actor/Npc.java
325
+++ b/java/net/sf/l2j/gameserver/model/actor/Npc.java
326
@@ -2,6 +2,7 @@
327
 
328
 import java.text.DateFormat;
329
 import java.util.ArrayList;
330
+import java.util.Arrays;
331
 import java.util.List;
332
 import java.util.Map;
333
 import java.util.StringTokenizer;
334
@@ -33,6 +34,8 @@
335
 import net.sf.l2j.gameserver.enums.items.ShotType;
336
 import net.sf.l2j.gameserver.idfactory.IdFactory;
337
 import net.sf.l2j.gameserver.model.WorldObject;
338
+import net.sf.l2j.gameserver.model.actor.instance.Merchant;
339
+import net.sf.l2j.gameserver.model.actor.instance.Monster;
340
 import net.sf.l2j.gameserver.model.actor.status.NpcStatus;
341
 import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
342
 import net.sf.l2j.gameserver.model.clanhall.ClanHall;
343
@@ -224,7 +227,69 @@
344
 	{
345
 		return (_shotsMask & type.getMask()) == type.getMask();
346
 	}
347
-	
348
+	@Override
349
+	public void onActionShift(Player player)
350
+	{
351
+		// Check if the L2PcInstance is a GM
352
+		if (player.isGM())
353
+		{
354
+			final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
355
+			html.setFile("data/html/admin/npcinfo.htm");
356
+			html.replace("%class%", getClass().getSimpleName());
357
+			html.replace("%id%", getTemplate().getNpcId());
358
+			html.replace("%lvl%", getTemplate().getLevel());
359
+			html.replace("%name%", getTemplate().getName());
360
+			html.replace("%race%", getTemplate().getRace().toString());
361
+			html.replace("%tmplid%", getTemplate().getIdTemplate());
362
+			html.replace("%aggro%", getTemplate().getAggroRange());
363
+			html.replace("%corpse%", StringUtil.getTimeStamp(getTemplate().getCorpseTime()));
364
+			html.replace("%enchant%", getTemplate().getEnchantEffect());
365
+			html.replace("%loc%", getX() + " " + getY() + " " + getZ());
366
+			
367
+			if (getSpawn() != null)
368
+			{
369
+				html.replace("%spawn%", getSpawn().getLoc().toString());
370
+				html.replace("%resp%", StringUtil.getTimeStamp(getSpawn().getRespawnDelay()));
371
+				html.replace("%rand_resp%", StringUtil.getTimeStamp(getSpawn().getRespawnRandom()));
372
+			}
373
+			else
374
+			{
375
+				html.replace("%spawn%", "<font color=FF0000>null</font>");
376
+				html.replace("%loc2d%", "<font color=FF0000>--</font>");
377
+				html.replace("%loc3d%", "<font color=FF0000>--</font>");
378
+				html.replace("%resp%", "<font color=FF0000>--</font>");
379
+				html.replace("%rand_resp%", "<font color=FF0000>--</font>");
380
+			}
381
+			
382
+			html.replace("%ai_type%", getTemplate().getAiType().name());
383
+			html.replace("%ai_clan%", (getTemplate().getClans() != null) ? "<tr><td width=100><font color=\"LEVEL\">Clan:</font></td><td align=right width=170>" + Arrays.toString(getTemplate().getClans()) + " " + getTemplate().getClanRange() + "</td></tr>" + ((getTemplate().getIgnoredIds() != null) ? "<tr><td width=100><font color=\"LEVEL\">Ignored ids:</font></td><td align=right width=170>" + Arrays.toString(getTemplate().getIgnoredIds()) + "</td></tr>" : "") : "");
384
+			html.replace("%ai_move%", String.valueOf(getTemplate().canMove()));
385
+			html.replace("%ai_seed%", String.valueOf(getTemplate().isSeedable()));
386
+			html.replace("%ai_ssinfo%", _currentSsCount + "[" + getTemplate().getSsCount() + "] - " + getTemplate().getSsRate() + "%");
387
+			html.replace("%ai_spsinfo%", _currentSpsCount + "[" + getTemplate().getSpsCount() + "] - " + getTemplate().getSpsRate() + "%");
388
+			html.replace("%butt%", ((this instanceof Merchant) ? "<button value=\"Shop\" action=\"bypass -h admin_show_shop " + getNpcId() + "\" width=65 height=19 back=\"L2UI_ch3.smallbutton2_over\" fore=\"L2UI_ch3.smallbutton2\">" : ""));
389
+			player.sendPacket(html);
390
+		}
391
+		else if (Config.ALT_GAME_VIEWNPC)
392
+		{
393
+			if (!(this instanceof Monster))
394
+			{
395
+				player.sendPacket(ActionFailed.STATIC_PACKET);
396
+				return;
397
+			}
398
+			final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
399
+			html.setFile("data/html/custom/dropNpc/npcinfo.htm");
400
+			html.replace("%id%", getTemplate().getNpcId());
401
+			html.replace("%lvl%", getTemplate().getLevel());
402
+			html.replace("%name%", getTemplate().getName());
403
+			html.replace("%loc%", getX() + " " + getY() + " " + getZ());
404
+			player.sendPacket(html);
405
+		}
406
+		if (player.getTarget() != this)
407
+			player.setTarget(this);
408
+		else
409
+			player.sendPacket(ActionFailed.STATIC_PACKET);
410
+	}
411
 	@Override
412
 	public void setChargedShot(ShotType type, boolean charged)
413
 	{
414
diff --git a/java/net/sf/l2j/gameserver/model/actor/Player.java b/java/net/sf/l2j/gameserver/model/actor/Player.java
415
index 44ffc27..6b4802b 100644
416
--- a/java/net/sf/l2j/gameserver/model/actor/Player.java
417
+++ b/java/net/sf/l2j/gameserver/model/actor/Player.java
418
@@ -84,6 +84,7 @@
419
 import net.sf.l2j.gameserver.geoengine.GeoEngine;
420
 import net.sf.l2j.gameserver.handler.IItemHandler;
421
 import net.sf.l2j.gameserver.handler.ItemHandler;
422
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminEditChar;
423
 import net.sf.l2j.gameserver.handler.skillhandlers.SummonFriend;
424
 import net.sf.l2j.gameserver.model.AccessLevel;
425
 import net.sf.l2j.gameserver.model.PetDataEntry;
426
@@ -665,7 +666,14 @@
427
 	{
428
 		return super.denyAiAction() || isInStoreMode() || _operateType == OperateType.OBSERVE;
429
 	}
430
-	
431
+	@Override
432
+	public void onActionShift(Player player)
433
+	{
434
+		if (player.isGM())
435
+			AdminEditChar.gatherPlayerInfo(player, this);
436
+		
437
+		super.onActionShift(player);
438
+	}
439
 	@Override
440
 	public PlayerMove getMove()
441
 	{
442
diff --git a/java/net/sf/l2j/gameserver/model/item/DropData.java b/java/net/sf/l2j/gameserver/model/item/DropData.java
443
index c36b9ee..d8fde92 100644
444
--- a/java/net/sf/l2j/gameserver/model/item/DropData.java
445
+++ b/java/net/sf/l2j/gameserver/model/item/DropData.java
446
@@ -1,5 +1,7 @@
447
 package net.sf.l2j.gameserver.model.item;
448
 
449
+import java.util.Arrays;
450
+
451
 /**
452
  * A container used by monster drops.<br>
453
  * <br>
454
@@ -10,6 +12,8 @@
455
 	public static final int MAX_CHANCE = 1000000;
456
 	
457
 	private final int _itemId;
458
+	private String _questID = null;
459
+	private String[] _stateID = null;
460
 	private final int _minDrop;
461
 	private final int _maxDrop;
462
 	private final int _chance;
463
@@ -25,9 +29,28 @@
464
 	@Override
465
 	public String toString()
466
 	{
467
-		return "DropData =[ItemID: " + _itemId + " Min: " + _minDrop + " Max: " + _maxDrop + " Chance: " + (_chance / 10000.0) + "%]";
468
+		String out = "ItemID: " + _itemId + " Min: " + _minDrop + " Max: " + _maxDrop + " Chance: " + (_chance / 10000.0) + "%";
469
+		if (isQuestDrop())
470
+		{
471
+			out = out + " QuestID: " + getQuestID() + " StateID's: " + Arrays.toString(getStateIDs());
472
+		}
473
+		return out;
474
+		//return "DropData =[ItemID: " + _itemId + " Min: " + _minDrop + " Max: " + _maxDrop + " Chance: " + (_chance / 10000.0) + "%]";
475
+	}
476
+	public String getQuestID()
477
+	{
478
+		return this._questID;
479
 	}
480
 	
481
+	public String[] getStateIDs()
482
+	{
483
+		return this._stateID;
484
+	}
485
+	
486
+	public boolean isQuestDrop()
487
+	{
488
+		return (this._questID != null) && (this._stateID != null);
489
+	}
490
 	/**
491
 	 * @return the id of the dropped item.
492
 	 */
493
diff --git a/java/net/sf/l2j/gameserver/network/clientpackets/Action.java b/java/net/sf/l2j/gameserver/network/clientpackets/Action.java
494
index e963ca2..52bfaed 100644
495
--- a/java/net/sf/l2j/gameserver/network/clientpackets/Action.java
496
+++ b/java/net/sf/l2j/gameserver/network/clientpackets/Action.java
497
@@ -1,63 +1,85 @@
498
 package net.sf.l2j.gameserver.network.clientpackets;
499
 
500
 import net.sf.l2j.gameserver.model.World;
501
 import net.sf.l2j.gameserver.model.WorldObject;
502
 import net.sf.l2j.gameserver.model.actor.Player;
503
-import net.sf.l2j.gameserver.model.entity.Duel.DuelState;
504
 import net.sf.l2j.gameserver.network.SystemMessageId;
505
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
506
 
507
 public final class Action extends L2GameClientPacket
508
 {
509
 	private int _objectId;
510
-	private boolean _isShiftAction;
511
+	@SuppressWarnings("unused")
512
+	private int _originX, _originY, _originZ;
513
+	private int _actionId;
514
 	
515
 	@Override
516
 	protected void readImpl()
517
 	{
518
 		_objectId = readD();
519
-		readD(); // originX
520
-		readD(); // originY
521
-		readD(); // originZ
522
-		_isShiftAction = readC() != 0;
523
+		_originX = readD();
524
+		_originY = readD();
525
+		_originZ = readD();
526
+		_actionId = readC();
527
 	}
528
 	
529
 	@Override
530
 	protected void runImpl()
531
 	{
532
-		final Player player = getClient().getPlayer();
533
-		if (player == null)
534
+		final Player activeChar = getClient().getPlayer();
535
+		if (activeChar == null)
536
 			return;
537
 		
538
-		if (player.isInObserverMode())
539
+		if (activeChar.isInObserverMode())
540
 		{
541
-			player.sendPacket(SystemMessageId.OBSERVERS_CANNOT_PARTICIPATE);
542
-			player.sendPacket(ActionFailed.STATIC_PACKET);
543
+			activeChar.sendPacket(SystemMessageId.OBSERVERS_CANNOT_PARTICIPATE);
544
+			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
545
 			return;
546
 		}
547
 		
548
-		if (player.getActiveRequester() != null)
549
+		if (activeChar.getActiveRequester() != null || activeChar.isOutOfControl())
550
 		{
551
-			player.sendPacket(ActionFailed.STATIC_PACKET);
552
+			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
553
 			return;
554
 		}
555
 		
556
-		final WorldObject target = (player.getTargetId() == _objectId) ? player.getTarget() : World.getInstance().getObject(_objectId);
557
-		if (target == null)
558
+		final WorldObject obj = (activeChar.getTargetId() == _objectId) ? activeChar.getTarget() : World.getInstance().getObject(_objectId);
559
+		if (obj == null)
560
 		{
561
-			player.sendPacket(ActionFailed.STATIC_PACKET);
562
+			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
563
 			return;
564
 		}
565
 		
566
-		final Player targetPlayer = target.getActingPlayer();
567
-		if (targetPlayer != null && targetPlayer.getDuelState() == DuelState.DEAD)
568
+		switch (_actionId)
569
 		{
570
-			player.sendPacket(SystemMessageId.OTHER_PARTY_IS_FROZEN);
571
-			player.sendPacket(ActionFailed.STATIC_PACKET);
572
-			return;
573
+			case 0:
574
+				obj.onAction(activeChar, false, false);
575
+				break;
576
+			
577
+			case 1:
578
+				obj.onActionShift(activeChar);
579
+				break;
580
+			
581
+			default:
582
+				// Invalid action detected (probably client cheating), log this
583
+				LOGGER.warn(activeChar.getName() + " requested invalid action: " + _actionId);
584
+				activeChar.sendPacket(ActionFailed.STATIC_PACKET);
585
+				break;
586
 		}
587
-		
588
-		target.onAction(player, false, _isShiftAction);
589
 	}
590
 	
591
 	@Override
592