View difference between Paste ID: HbYbVksH and sR7EAFLs
SHOW: | | - or go back to the newest paste.
1
### Eclipse Workspace Patch 1.0
2
#P L2J_Mobius_C6_Interlude
3
diff --git dist/db_installer/sql/game/character_autofarm.sql dist/db_installer/sql/game/character_autofarm.sql
4
new file mode 100644
5
index 0000000..35128de
6
--- /dev/null
7
+++ dist/db_installer/sql/game/character_autofarm.sql
8
@@ -0,0 +1,37 @@
9
+/*
10
+Navicat MySQL Data Transfer
11
+
12
+Source Server         : localhost
13
+Source Server Version : 50740
14
+Source Host           : localhost:3306
15
+Source Database       : 1faris
16
+
17
+Target Server Type    : MYSQL
18
+Target Server Version : 50740
19
+File Encoding         : 65001
20
+
21
+Date: 2023-10-15 07:01:50
22
+*/
23
+
24
+SET FOREIGN_KEY_CHECKS=0;
25
+
26
+-- ----------------------------
27
+-- Table structure for character_autofarm
28
+-- ----------------------------
29
+DROP TABLE IF EXISTS `character_autofarm`;
30
+CREATE TABLE `character_autofarm` (
31
+  `char_id` int(10) unsigned NOT NULL,
32
+  `char_name` varchar(35) COLLATE utf8_unicode_ci NOT NULL,
33
+  `auto_farm` tinyint(1) unsigned NOT NULL DEFAULT '0',
34
+  `radius` int(10) unsigned NOT NULL DEFAULT '1200',
35
+  `short_cut` int(10) unsigned NOT NULL DEFAULT '9',
36
+  `heal_percent` int(10) unsigned NOT NULL DEFAULT '30',
37
+  `buff_protection` tinyint(1) unsigned NOT NULL DEFAULT '0',
38
+  `anti_ks_protection` tinyint(1) unsigned NOT NULL DEFAULT '0',
39
+  `summon_attack` tinyint(1) unsigned NOT NULL DEFAULT '0',
40
+  `summon_skill_percent` int(10) unsigned NOT NULL DEFAULT '0',
41
+  `hp_potion_percent` int(10) unsigned NOT NULL DEFAULT '60',
42
+  `mp_potion_percent` int(10) unsigned NOT NULL DEFAULT '60',
43
+  PRIMARY KEY (`char_id`),
44
+  KEY `char_name` (`char_name`)
45
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
46
diff --git dist/game/data/html/mods/menu/AutoFarm.htm dist/game/data/html/mods/menu/AutoFarm.htm
47
new file mode 100644
48
index 0000000..19711f7
49
--- /dev/null
50
+++ dist/game/data/html/mods/menu/AutoFarm.htm
51
@@ -0,0 +1,126 @@
52
+<html><title>Auto Hunting</title>
53
+
54
+<table width=280>
55
+<tr>
56
+<td width=5></td>
57
+<td width=20 align="center"><img src="L2UI_CH3.herotower_deco" width=256 height=32></td>
58
+</tr>
59
+</table>
60
+
61
+<table width=265>
62
+<tr>
63
+<td width=120 align="right"><font color="LEVEL">Auto Farm State:</font> %autofarm%</td>
64
+<td width=20 align="left"><button width=75 height=19 back="buttons_bs.bs_64x27_1" fore="buttons_bs.bs_64x27_2" action="bypass voiced_enableAutoFarm" value="%button%"></td>
65
+</tr>
66
+</table>
67
+
68
+<br1>
69
+
70
+<table width=265>
71
+<tr>
72
+<td width=5></td>
73
+<td width=100 valign="top" align="center"><font color="e6dcbe">Target Range:</font> </td>
74
+<td width=20 align=center><button action="bypass voiced_radiusAutoFarm dec_radius" width=16 height=16 back=L2UI_CH3.prev1_down fore=L2UI_CH3.prev1></td>
75
+<td width=40 align=center><font color=CC9933>%radius%</font></td>
76
+<td width=20 align=center><button action="bypass voiced_radiusAutoFarm inc_radius" width=16 height=16 back=L2UI_CH3.next1_down fore=L2UI_CH3.next1></td>
77
+</tr> 
78
+<tr>
79
+<td width=5></td>
80
+<td width=100 valign="top" align="center"><font color="e6dcbe">Heal Percent: </font></td>
81
+<td width=20 align=center><button action="bypass voiced_healAutoFarm dec_heal" width=16 height=16 back=L2UI_CH3.prev1_down fore=L2UI_CH3.prev1></td>
82
+<td width=40 align=center><font color=CC9933>%heal%</font></td>
83
+<td width=20 align=center><button action="bypass voiced_healAutoFarm inc_heal" width=16 height=16 back=L2UI_CH3.next1_down fore=L2UI_CH3.next1></td>
84
+</tr> 
85
+<tr>
86
+<td width=5></td>
87
+<td width=100 valign="top" align="center"><font color="e6dcbe">Shortcut Page: </font></td>
88
+<td width=20 align=center><button action="bypass voiced_pageAutoFarm dec_page" width=16 height=16 back=L2UI_CH3.prev1_down fore=L2UI_CH3.prev1></td>
89
+<td width=40 align=center><font color=CC9933>%page%</font></td>
90
+<td width=20 align=center><button action="bypass voiced_pageAutoFarm inc_page" width=16 height=16 back=L2UI_CH3.next1_down fore=L2UI_CH3.next1></td>
91
+</tr> 
92
+<tr>
93
+<td width=5></td>
94
+<td width=100 valign="top" align="center"><font color="e6dcbe">Mana Potion Percent: </font></td>
95
+<td width=20 align=center><button action="bypass voiced_mpAutoFarm dec_mp_pot" width=16 height=16 back=L2UI_CH3.prev1_down fore=L2UI_CH3.prev1></td>
96
+<td width=40 align=center><font color=CC9933>%mpPotion%</font></td>
97
+<td width=20 align=center><button action="bypass voiced_mpAutoFarm inc_mp_pot" width=16 height=16 back=L2UI_CH3.next1_down fore=L2UI_CH3.next1></td>
98
+</tr> 
99
+<tr>
100
+<td width=5></td>
101
+<td width=100 valign="top" align="center"><font color="e6dcbe">Healing Potion Percent: </font></td>
102
+<td width=20 align=center><button action="bypass voiced_hpAutoFarm dec_hp_pot" width=16 height=16 back=L2UI_CH3.prev1_down fore=L2UI_CH3.prev1></td>
103
+<td width=40 align=center><font color=CC9933>%hpPotion%</font></td>
104
+<td width=20 align=center><button action="bypass voiced_hpAutoFarm inc_hp_pot" width=16 height=16 back=L2UI_CH3.next1_down fore=L2UI_CH3.next1></td>
105
+</tr>   
106
+<tr>
107
+<td width=5></td>
108
+<td width=100 valign="top" align="center"><font color="e6dcbe">Summon Skill Chance: </font></td>
109
+<td width=20 align=center><button action="bypass voiced_summonSkillAutoFarm dec_summonSkill" width=16 height=16 back=L2UI_CH3.prev1_down fore=L2UI_CH3.prev1></td>
110
+<td width=40 align=center><font color=CC9933>%summonSkill%</font></td>
111
+<td width=20 align=center><button action="bypass voiced_summonSkillAutoFarm inc_summonSkill" width=16 height=16 back=L2UI_CH3.next1_down fore=L2UI_CH3.next1></td>
112
+</tr> 
113
+</table>
114
+
115
+<table width=300>
116
+<tr>
117
+<td width=20 align=left><font color="e6dcbe">Enable Summon attack support</font></td>
118
+<td width=30></td>
119
+<td width=5 align=left><button action="bypass voiced_enableSummonAttack" %summonAtk% width="16" height="16"></td>
120
+</tr>
121
+<tr>
122
+<td width=50 align=left><font color="e6dcbe">Manner Mode, Anti-KS protection</font></td>
123
+<td width=20></td>
124
+<td width=10 align=left><button action="bypass voiced_enableAntiKs" %antiKs% width="16" height="16"></td>
125
+</tr>
126
+<tr>
127
+<td width=50 align=left><font color="e6dcbe">Disable Auto Farm after losing all buffs</font></td>
128
+<td width=20></td>
129
+<td width=10 align=left><button action="bypass voiced_enableBuffProtect" %noBuff% width="16" height="16"></td>
130
+</tr>
131
+</table>
132
+  
133
+<br1>
134
+<center>
135
+<table>
136
+<tr>
137
+    <td width=250><font color="LEVEL">Avoid specific monsters adding them to the blacklist</font></td>
138
+</tr>
139
+</table>
140
+	
141
+<table>
142
+<tr>
143
+	<td><button value="Blacklist Target" action="bypass voiced_ignoreMonster" width=90 height=14 back="buttons_bs.bs_64x15_1" fore="buttons_bs.bs_64x15_2"></td>
144
+	<td><button value="Unblacklist Target" action="bypass voiced_activeMonster" width=90 height=14 back="buttons_bs.bs_64x15_1" fore="buttons_bs.bs_64x15_2"></td>
145
+</tr>
146
+</table>
147
+</center>
148
+
149
+<img src="L2UI.SquareGray" width=310 height=1>
150
+<table bgcolor="000000" width=330>
151
+<tr>
152
+<td></td>
153
+<td><font color="LEVEL">Rules:</font></td>
154
+<td height=20><font color="e6dcbe">-</font> <font color="F42B00">'Attack'</font> <font color="e6dcbe">Shortcuts: </font><font color="F42B00">F1, F2, F3 & F4</font></td>
155
+</tr>
156
+<tr>
157
+<td></td>
158
+<td></td>
159
+<td height=20><font color="e6dcbe">-</font> <font color="70F011">'Chance'</font> <font color="e6dcbe">Shortcuts: </font><font color="70F011">F5, F6, F7 & F8</font></td>
160
+</tr>
161
+<tr>
162
+<td></td>
163
+<td></td>
164
+<td height=20><font color="e6dcbe">-</font> <font color="09E1FA">'Low Life'</font> <font color="e6dcbe">Shortcuts: </font><font color="09E1FA">F9, F10, F11 & F12</font></td>
165
+</tr>
166
+</table>
167
+<img src="L2UI.SquareGray" width=310 height=1>
168
+<br1>
169
+
170
+<table width=350>
171
+<tr>
172
+<td width=5></td>
173
+<td width=20 align="center"><a action="bypass voiced_menu">Back</a></td>
174
+</tr>
175
+</table>
176
+
177
+</body></html>
178
\ No newline at end of file
179
diff --git java/Base/AutoFarm/AutofarmConstants.java java/Base/AutoFarm/AutofarmConstants.java
180
new file mode 100644
181
index 0000000..70e4aef
182
--- /dev/null
183
+++ java/Base/AutoFarm/AutofarmConstants.java
184
@@ -0,0 +1,11 @@
185
+package Base.AutoFarm;
186
+
187
+import java.util.Arrays;
188
+import java.util.List;
189
+
190
+public class AutofarmConstants 
191
+{
192
+    public final static List<Integer> attackSlots = Arrays.asList(0, 1, 2, 3);
193
+    public final static List<Integer> chanceSlots = Arrays.asList(4, 5, 6, 7);
194
+    public final static List<Integer> lowLifeSlots = Arrays.asList(8, 9, 10, 11);
195
+}
196
\ No newline at end of file
197
diff --git java/Base/AutoFarm/AutofarmPlayerRoutine.java java/Base/AutoFarm/AutofarmPlayerRoutine.java
198
new file mode 100644
199
index 0000000..6f19aa0
200
--- /dev/null
201
+++ java/Base/AutoFarm/AutofarmPlayerRoutine.java
202
@@ -0,0 +1,586 @@
203
+package Base.AutoFarm;
204
+
205
+import java.util.ArrayList;
206
+import java.util.Arrays;
207
+import java.util.Collections;
208
+import java.util.List;
209
+import java.util.concurrent.ScheduledFuture;
210
+import java.util.function.Function;
211
+import java.util.stream.Collectors;
212
+
213
+import org.l2jmobius.commons.threads.ThreadPool;
214
+import org.l2jmobius.commons.util.Rnd;
215
+import org.l2jmobius.gameserver.ai.CtrlIntention;
216
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
217
+import org.l2jmobius.gameserver.handler.IItemHandler;
218
+import org.l2jmobius.gameserver.handler.ItemHandler;
219
+import org.l2jmobius.gameserver.handler.voicedcommandhandlers.VoicedAutoFarm;
220
+import org.l2jmobius.gameserver.model.ShortCut;
221
+import org.l2jmobius.gameserver.model.Skill;
222
+import org.l2jmobius.gameserver.model.WorldObject;
223
+import org.l2jmobius.gameserver.model.WorldRegion;
224
+import org.l2jmobius.gameserver.model.actor.Creature;
225
+import org.l2jmobius.gameserver.model.actor.Player;
226
+import org.l2jmobius.gameserver.model.actor.Summon;
227
+import org.l2jmobius.gameserver.model.actor.instance.Chest;
228
+import org.l2jmobius.gameserver.model.actor.instance.Monster;
229
+import org.l2jmobius.gameserver.model.actor.instance.Pet;
230
+import org.l2jmobius.gameserver.model.item.instance.Item;
231
+import org.l2jmobius.gameserver.model.skill.SkillType;
232
+import org.l2jmobius.gameserver.network.SystemMessageId;
233
+import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
234
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
235
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
236
+import org.l2jmobius.gameserver.util.Util;
237
+
238
+public class AutofarmPlayerRoutine
239
+{
240
+	private final Player player;
241
+	private ScheduledFuture<?> _task;
242
+	private Creature committedTarget = null;
243
+	
244
+	public AutofarmPlayerRoutine(Player player)
245
+	{
246
+		this.player = player;
247
+	}
248
+	
249
+	public void start()
250
+	{
251
+		if (_task == null)
252
+		{
253
+			_task = ThreadPool.scheduleAtFixedRate(() -> executeRoutine(), 450, 450);
254
+			
255
+			player.sendPacket(new ExShowScreenMessage("Auto Farming Actived...", 5 * 1000));
256
+			player.sendPacket(new SystemMessage(SystemMessageId.AUTO_FARM_ACTIVATED));
257
+			
258
+		}
259
+	}
260
+	
261
+	public void stop()
262
+	{
263
+		if (_task != null)
264
+		{
265
+			_task.cancel(false);
266
+			_task = null;
267
+			
268
+			player.sendPacket(new ExShowScreenMessage("Auto Farming Deactivated...", 5 * 1000));
269
+			player.sendPacket(new SystemMessage(SystemMessageId.AUTO_FARM_DESACTIVATED));
270
+			
271
+		}
272
+	}
273
+	
274
+	public void executeRoutine()
275
+	{
276
+		if (player.isNoBuffProtected() && (player.getAllEffects().size() <= 8))
277
+		{
278
+			player.sendMessage("You don't have buffs to use autofarm.");
279
+			player.broadcastUserInfo();
280
+			stop();
281
+			player.setAutoFarm(false);
282
+			VoicedAutoFarm.showAutoFarm(player);
283
+			return;
284
+		}
285
+		
286
+		calculatePotions();
287
+		checkSpoil();
288
+		targetEligibleCreature();
289
+		if (player.isMageClass())
290
+		{
291
+			useAppropriateSpell();
292
+		}
293
+		else if (shotcutsContainAttack())
294
+		{
295
+			attack();
296
+		}
297
+		else
298
+		{
299
+			useAppropriateSpell();
300
+		}
301
+		checkSpoil();
302
+		useAppropriateSpell();
303
+	}
304
+	
305
+	private void attack()
306
+	{
307
+		
308
+		physicalAttack();
309
+	}
310
+	
311
+	private void useAppropriateSpell()
312
+	{
313
+		Skill chanceSkill = nextAvailableSkill(getChanceSpells(), AutofarmSpellType.Chance);
314
+		
315
+		if (chanceSkill != null)
316
+		{
317
+			useMagicSkill(chanceSkill, false);
318
+			return;
319
+		}
320
+		
321
+		Skill lowLifeSkill = nextAvailableSkill(getLowLifeSpells(), AutofarmSpellType.LowLife);
322
+		
323
+		if (lowLifeSkill != null)
324
+		{
325
+			useMagicSkill(lowLifeSkill, true);
326
+			return;
327
+		}
328
+		
329
+		Skill attackSkill = nextAvailableSkill(getAttackSpells(), AutofarmSpellType.Attack);
330
+		
331
+		if (attackSkill != null)
332
+		{
333
+			useMagicSkill(attackSkill, false);
334
+			return;
335
+		}
336
+	}
337
+	
338
+	public Skill nextAvailableSkill(List<Integer> skillIds, AutofarmSpellType spellType)
339
+	{
340
+		for (Integer skillId : skillIds)
341
+		{
342
+			Skill skill = player.getSkill(skillId);
343
+			
344
+			if (skill == null)
345
+			{
346
+				continue;
347
+			}
348
+			
349
+			if ((skill.getSkillType() == SkillType.SIGNET) || (skill.getSkillType() == SkillType.SIGNET_CASTTIME))
350
+			{
351
+				continue;
352
+			}
353
+			
354
+			if (isSpoil(skillId))
355
+			{
356
+				if (monsterIsAlreadySpoiled())
357
+				{
358
+					continue;
359
+				}
360
+				return skill;
361
+			}
362
+			
363
+			if ((spellType == AutofarmSpellType.Chance) && (getMonsterTarget() != null))
364
+			{
365
+				if (getMonsterTarget().getFirstEffect(skillId) == null)
366
+				{
367
+					return skill;
368
+				}
369
+				continue;
370
+			}
371
+			
372
+			if ((spellType == AutofarmSpellType.LowLife) && (getHpPercentage() > player.getHealPercent()))
373
+			{
374
+				break;
375
+			}
376
+			
377
+			return skill;
378
+		}
379
+		
380
+		return null;
381
+	}
382
+	
383
+	private void checkSpoil()
384
+	{
385
+		if (canBeSweepedByMe() && getMonsterTarget().isDead())
386
+		{
387
+			Skill sweeper = player.getSkill(42);
388
+			if (sweeper == null)
389
+			{
390
+				return;
391
+			}
392
+			
393
+			useMagicSkill(sweeper, false);
394
+		}
395
+	}
396
+	
397
+	private Double getHpPercentage()
398
+	{
399
+		return (player.getCurrentHp() * 100.0f) / player.getMaxHp();
400
+	}
401
+	
402
+	private Double percentageMpIsLessThan()
403
+	{
404
+		return (player.getCurrentMp() * 100.0f) / player.getMaxMp();
405
+	}
406
+	
407
+	private Double percentageHpIsLessThan()
408
+	{
409
+		return (player.getCurrentHp() * 100.0f) / player.getMaxHp();
410
+	}
411
+	
412
+	private List<Integer> getAttackSpells()
413
+	{
414
+		return getSpellsInSlots(AutofarmConstants.attackSlots);
415
+	}
416
+	
417
+	private List<Integer> getSpellsInSlots(List<Integer> attackSlots)
418
+	{
419
+		ShortCut[] shortCutsArray = player.getAllShortCuts().toArray(new ShortCut[0]);
420
+		
421
+		return Arrays.stream(shortCutsArray).filter(shortcut -> (shortcut.getPage() == player.getPage()) && (shortcut.getType() == ShortCut.TYPE_SKILL) && attackSlots.contains(shortcut.getSlot())).map(ShortCut::getId).collect(Collectors.toList());
422
+	}
423
+	
424
+	private List<Integer> getChanceSpells()
425
+	{
426
+		return getSpellsInSlots(AutofarmConstants.chanceSlots);
427
+	}
428
+	
429
+	private List<Integer> getLowLifeSpells()
430
+	{
431
+		return getSpellsInSlots(AutofarmConstants.lowLifeSlots);
432
+	}
433
+	
434
+	private boolean shotcutsContainAttack()
435
+	{
436
+		ShortCut[] shortCutsArray = player.getAllShortCuts().toArray(new ShortCut[0]);
437
+		
438
+		return Arrays.stream(shortCutsArray).anyMatch(shortcut -> (shortcut.getPage() == player.getPage()) && (shortcut.getType() == ShortCut.TYPE_ACTION) && ((shortcut.getId() == 2) || (player.isSummonAttack() && (shortcut.getId() == 22))));
439
+	}
440
+	
441
+	private boolean monsterIsAlreadySpoiled()
442
+	{
443
+		return (getMonsterTarget() != null) && (getMonsterTarget().getSpoiledBy() != 0);
444
+	}
445
+	
446
+	private static boolean isSpoil(Integer skillId)
447
+	{
448
+		return (skillId == 254) || (skillId == 302);
449
+	}
450
+	
451
+	private boolean canBeSweepedByMe()
452
+	{
453
+		return (getMonsterTarget() != null) && getMonsterTarget().isDead() && (getMonsterTarget().getSpoiledBy() == player.getObjectId());
454
+	}
455
+	
456
+	private void castSpellWithAppropriateTarget(Skill skill, Boolean forceOnSelf)
457
+	{
458
+		if (forceOnSelf)
459
+		{
460
+			WorldObject oldTarget = player.getTarget();
461
+			player.setTarget(player);
462
+			player.useMagic(skill, false, false);
463
+			player.setTarget(oldTarget);
464
+			return;
465
+		}
466
+		
467
+		player.useMagic(skill, false, false);
468
+	}
469
+	
470
+	private void physicalAttack()
471
+	{
472
+		if (!(player.getTarget() instanceof Monster))
473
+		{
474
+			return;
475
+		}
476
+		
477
+		Monster target = (Monster) player.getTarget();
478
+		
479
+		if (!player.isMageClass())
480
+		{
481
+			if (target.isAutoAttackable(player) && GeoEngine.getInstance().canSeeTarget(player, target))
482
+			{
483
+				if (GeoEngine.getInstance().canSeeTarget(player, target))
484
+				{
485
+					player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
486
+					player.onActionRequest();
487
+					
488
+					if (player.isSummonAttack() && (player.getPet() != null))
489
+					{
490
+						// Siege Golem's
491
+						if (((player.getPet().getNpcId() >= 14702) && (player.getPet().getNpcId() <= 14798)) || ((player.getPet().getNpcId() >= 14839) && (player.getPet().getNpcId() <= 14869)))
492
+						{
493
+							return;
494
+						}
495
+						
496
+						Summon activeSummon = player.getPet();
497
+						activeSummon.setTarget(target);
498
+						activeSummon.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
499
+						
500
+						int[] summonAttackSkills =
501
+						{
502
+							4261,
503
+							4068,
504
+							4137,
505
+							4260,
506
+							4708,
507
+							4709,
508
+							4710,
509
+							4712,
510
+							5135,
511
+							5138,
512
+							5141,
513
+							5442,
514
+							5444,
515
+							6095,
516
+							6096,
517
+							6041,
518
+							6044
519
+						};
520
+						if (Rnd.get(100) < player.getSummonSkillPercent())
521
+						{
522
+							for (int skillId : summonAttackSkills)
523
+							{
524
+								useMagicSkillBySummon(skillId, target);
525
+							}
526
+						}
527
+					}
528
+				}
529
+			}
530
+			else
531
+			{
532
+				if (target.isAutoAttackable(player) && GeoEngine.getInstance().canSeeTarget(player, target))
533
+				{
534
+					if (GeoEngine.getInstance().canSeeTarget(player, target))
535
+					{
536
+						player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, target);
537
+					}
538
+				}
539
+			}
540
+		}
541
+		else
542
+		{
543
+			if (player.isSummonAttack() && (player.getPet() != null))
544
+			{
545
+				// Siege Golem's
546
+				if (((player.getPet().getNpcId() >= 14702) && (player.getPet().getNpcId() <= 14798)) || ((player.getPet().getNpcId() >= 14839) && (player.getPet().getNpcId() <= 14869)))
547
+				{
548
+					return;
549
+				}
550
+				
551
+				Summon activeSummon = player.getPet();
552
+				activeSummon.setTarget(target);
553
+				activeSummon.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
554
+				
555
+				int[] summonAttackSkills =
556
+				{
557
+					4261,
558
+					4068,
559
+					4137,
560
+					4260,
561
+					4708,
562
+					4709,
563
+					4710,
564
+					4712,
565
+					5135,
566
+					5138,
567
+					5141,
568
+					5442,
569
+					5444,
570
+					6095,
571
+					6096,
572
+					6041,
573
+					6044
574
+				};
575
+				if (Rnd.get(100) < player.getSummonSkillPercent())
576
+				{
577
+					for (int skillId : summonAttackSkills)
578
+					{
579
+						useMagicSkillBySummon(skillId, target);
580
+					}
581
+				}
582
+			}
583
+		}
584
+	}
585
+	
586
+	public void targetEligibleCreature()
587
+	{
588
+		if (player.getTarget() == null)
589
+		{
590
+			selectNewTarget();
591
+			return;
592
+		}
593
+		
594
+		if (committedTarget != null)
595
+		{
596
+			if (!committedTarget.isDead() && GeoEngine.getInstance().canSeeTarget(player, committedTarget))
597
+			{
598
+				attack();
599
+				return;
600
+			}
601
+			else if (!GeoEngine.getInstance().canSeeTarget(player, committedTarget))
602
+			{
603
+				committedTarget = null;
604
+				selectNewTarget();
605
+				return;
606
+			}
607
+			player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, committedTarget);
608
+			committedTarget = null;
609
+			player.setTarget(null);
610
+		}
611
+		
612
+		if (committedTarget instanceof Summon)
613
+		{
614
+			return;
615
+		}
616
+		
617
+		List<Monster> targets = getKnownMonstersInRadius(player, player.getRadius(), creature -> GeoEngine.getInstance().canMoveToTarget(player.getX(), player.getY(), player.getZ(), creature.getX(), creature.getY(), creature.getZ(), 0) && !player.ignoredMonsterContain(creature.getNpcId()) && !creature.isMinion() && !creature.isRaid() && !creature.isDead() && !(creature instanceof Chest) && !(player.isAntiKsProtected() && (creature.getTarget() != null) && (creature.getTarget() != player) && (creature.getTarget() != player.getPet())));
618
+		
619
+		if (targets.isEmpty())
620
+		{
621
+			return;
622
+		}
623
+		
624
+		Monster closestTarget = targets.stream().min((o1, o2) -> Integer.compare((int) Math.sqrt(player.getDistanceSq(o1)), (int) Math.sqrt(player.getDistanceSq(o2)))).get();
625
+		
626
+		committedTarget = closestTarget;
627
+		player.setTarget(closestTarget);
628
+	}
629
+	
630
+	private void selectNewTarget()
631
+	{
632
+		List<Monster> targets = getKnownMonstersInRadius(player, player.getRadius(), creature -> GeoEngine.getInstance().canMoveToTarget(player.getX(), player.getY(), player.getZ(), creature.getX(), creature.getY(), creature.getZ(), 0) && !player.ignoredMonsterContain(creature.getNpcId()) && !creature.isMinion() && !creature.isRaid() && !creature.isDead() && !(creature instanceof Chest) && !(player.isAntiKsProtected() && (creature.getTarget() != null) && (creature.getTarget() != player) && (creature.getTarget() != player.getPet())));
633
+		
634
+		if (targets.isEmpty())
635
+		{
636
+			return;
637
+		}
638
+		
639
+		Monster closestTarget = targets.stream().min((o1, o2) -> Integer.compare((int) Math.sqrt(player.getDistanceSq(o1)), (int) Math.sqrt(player.getDistanceSq(o2)))).get();
640
+		
641
+		committedTarget = closestTarget;
642
+		player.setTarget(closestTarget);
643
+	}
644
+	
645
+	public final static List<Monster> getKnownMonstersInRadius(Player player, int radius, Function<Monster, Boolean> condition)
646
+	{
647
+		final WorldRegion region = player.getWorldRegion();
648
+		if (region == null)
649
+		{
650
+			return Collections.emptyList();
651
+		}
652
+		
653
+		final List<Monster> result = new ArrayList<>();
654
+		
655
+		for (WorldRegion reg : region.getSurroundingRegions())
656
+		{
657
+			for (WorldObject obj : reg.getVisibleObjects())
658
+			{
659
+				if (!(obj instanceof Monster) || !Util.checkIfInRange(radius, player, obj, true) || !condition.apply((Monster) obj))
660
+				{
661
+					continue;
662
+				}
663
+				
664
+				result.add((Monster) obj);
665
+			}
666
+		}
667
+		
668
+		return result;
669
+	}
670
+	
671
+	public Monster getMonsterTarget()
672
+	{
673
+		if (!(player.getTarget() instanceof Monster))
674
+		{
675
+			return null;
676
+		}
677
+		
678
+		return (Monster) player.getTarget();
679
+	}
680
+	
681
+	private void useMagicSkill(Skill skill, Boolean forceOnSelf)
682
+	{
683
+		if ((skill.getSkillType() == SkillType.RECALL) && (player.getKarma() > 0))
684
+		{
685
+			player.sendPacket(ActionFailed.STATIC_PACKET);
686
+			return;
687
+		}
688
+		
689
+		if (skill.isToggle() && player.isMounted())
690
+		{
691
+			player.sendPacket(ActionFailed.STATIC_PACKET);
692
+			return;
693
+		}
694
+		
695
+		if (player.isOutOfControl())
696
+		{
697
+			player.sendPacket(ActionFailed.STATIC_PACKET);
698
+			return;
699
+		}
700
+		
701
+		if (player.isAttackingNow())
702
+		{
703
+			castSpellWithAppropriateTarget(skill, forceOnSelf);
704
+			// player.getAI().setIntention(CtrlIntention.AI_INTENTION_CAST);
705
+		}
706
+		else
707
+		{
708
+			castSpellWithAppropriateTarget(skill, forceOnSelf);
709
+		}
710
+	}
711
+	
712
+	private boolean useMagicSkillBySummon(int skillId, WorldObject target)
713
+	{
714
+		// No owner, or owner in shop mode.
715
+		if ((player == null) || player.isInStoreMode())
716
+		{
717
+			return false;
718
+		}
719
+		
720
+		final Summon activeSummon = player.getPet();
721
+		if (activeSummon == null)
722
+		{
723
+			return false;
724
+		}
725
+		
726
+		// Pet which is 20 levels higher than owner.
727
+		if ((activeSummon instanceof Pet) && ((activeSummon.getLevel() - player.getLevel()) > 20))
728
+		{
729
+			// player.sendPacket(SystemMessageId.PET_TOO_HIGH_TO_CONTROL);
730
+			return false;
731
+		}
732
+		
733
+		// Out of control pet.
734
+		if (activeSummon.isOutOfControl())
735
+		{
736
+			// player.sendPacket(SystemMessageId.PET_REFUSING_ORDER);
737
+			return false;
738
+		}
739
+		
740
+		// Verify if the launched skill is mastered by the summon.
741
+		final Skill skill = activeSummon.getSkill(skillId);
742
+		if (skill == null)
743
+		{
744
+			return false;
745
+		}
746
+		
747
+		// Can't launch offensive skills on owner.
748
+		if (skill.isOffensive() && (player == target))
749
+		{
750
+			return false;
751
+		}
752
+		
753
+		activeSummon.setTarget(target);
754
+		return activeSummon.useMagic(skill, false, false);
755
+	}
756
+	
757
+	private void calculatePotions()
758
+	{
759
+		if (percentageHpIsLessThan() < player.getHpPotionPercentage())
760
+		{
761
+			forceUseItem(1539);
762
+		}
763
+		
764
+		if (percentageMpIsLessThan() < player.getMpPotionPercentage())
765
+		{
766
+			forceUseItem(728);
767
+		}
768
+	}
769
+	
770
+	private void forceUseItem(int itemId)
771
+	{
772
+		final Item potion = player.getInventory().getItemByItemId(itemId);
773
+		if (potion == null)
774
+		{
775
+			return;
776
+		}
777
+		
778
+		final IItemHandler handler = ItemHandler.getInstance().getItemHandler(potion.getItemId());
779
+		if (handler != null)
780
+		{
781
+			handler.useItem(player, potion);
782
+		}
783
+	}
784
+}
785
\ No newline at end of file
786
diff --git java/Base/AutoFarm/AutofarmSpell.java java/Base/AutoFarm/AutofarmSpell.java
787
new file mode 100644
788
index 0000000..beefc8d
789
--- /dev/null
790
+++ java/Base/AutoFarm/AutofarmSpell.java
791
@@ -0,0 +1,20 @@
792
+package Base.AutoFarm;
793
+
794
+public class AutofarmSpell {
795
+	private final Integer _skillId;
796
+	private final AutofarmSpellType _spellType;
797
+	
798
+	public AutofarmSpell(Integer skillId, AutofarmSpellType spellType){
799
+		
800
+		_skillId = skillId;
801
+		_spellType = spellType;
802
+	}
803
+	
804
+	public Integer getSkillId() {
805
+		return _skillId;
806
+	}
807
+	
808
+	public AutofarmSpellType getSpellType() {
809
+		return _spellType;
810
+	}
811
+}
812
\ No newline at end of file
813
diff --git java/Base/AutoFarm/AutofarmSpellType.java java/Base/AutoFarm/AutofarmSpellType.java
814
new file mode 100644
815
index 0000000..2ec3039
816
--- /dev/null
817
+++ java/Base/AutoFarm/AutofarmSpellType.java
818
@@ -0,0 +1,8 @@
819
+package Base.AutoFarm;
820
+
821
+public enum AutofarmSpellType
822
+{
823
+    Attack,
824
+    Chance,
825
+    LowLife    
826
+}
827
\ No newline at end of file
828
diff --git java/org/l2jmobius/gameserver/handler/VoicedCommandHandler.java java/org/l2jmobius/gameserver/handler/VoicedCommandHandler.java
829
index 466e2a6..b25580e 100644
830
--- java/org/l2jmobius/gameserver/handler/VoicedCommandHandler.java
831
+++ java/org/l2jmobius/gameserver/handler/VoicedCommandHandler.java
832
@@ -30,6 +30,7 @@
833
 import org.l2jmobius.gameserver.handler.voicedcommandhandlers.Online;
834
 import org.l2jmobius.gameserver.handler.voicedcommandhandlers.StatsCmd;
835
 import org.l2jmobius.gameserver.handler.voicedcommandhandlers.VoiceCommand;
836
+import org.l2jmobius.gameserver.handler.voicedcommandhandlers.VoicedAutoFarm;
837
 import org.l2jmobius.gameserver.handler.voicedcommandhandlers.Wedding;
838
 
839
 public class VoicedCommandHandler
840
@@ -43,6 +44,7 @@
841
 		_datatable = new HashMap<>();
842
 		
843
 		registerVoicedCommandHandler(new VoiceCommand());
844
+		registerVoicedCommandHandler(new VoicedAutoFarm());
845
 		
846
 		if (Config.ENABLE_AUTO_PLAY)
847
 		{
848
diff --git java/org/l2jmobius/gameserver/handler/voicedcommandhandlers/VoicedAutoFarm.java java/org/l2jmobius/gameserver/handler/voicedcommandhandlers/VoicedAutoFarm.java
849
new file mode 100644
850
index 0000000..6501c48
851
--- /dev/null
852
+++ java/org/l2jmobius/gameserver/handler/voicedcommandhandlers/VoicedAutoFarm.java
853
@@ -0,0 +1,332 @@
854
+package org.l2jmobius.gameserver.handler.voicedcommandhandlers;
855
+
856
+import java.util.StringTokenizer;
857
+
858
+import org.l2jmobius.commons.util.StringUtil;
859
+import org.l2jmobius.gameserver.handler.IVoicedCommandHandler;
860
+import org.l2jmobius.gameserver.model.WorldObject;
861
+import org.l2jmobius.gameserver.model.actor.Player;
862
+import org.l2jmobius.gameserver.model.actor.instance.Monster;
863
+import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
864
+
865
+import Base.AutoFarm.AutofarmPlayerRoutine;
866
+
867
+public class VoicedAutoFarm implements IVoicedCommandHandler
868
+{
869
+	private final String[] VOICED_COMMANDS =
870
+	{
871
+		"autofarm",
872
+		"enableAutoFarm",
873
+		"radiusAutoFarm",
874
+		"pageAutoFarm",
875
+		"enableBuffProtect",
876
+		"healAutoFarm",
877
+		"hpAutoFarm",
878
+		"mpAutoFarm",
879
+		"enableAntiKs",
880
+		"enableSummonAttack",
881
+		"summonSkillAutoFarm",
882
+		"ignoreMonster",
883
+		"activeMonster"
884
+	};
885
+	
886
+	@Override
887
+	public boolean useVoicedCommand(final String command, final Player activeChar, final String args)
888
+	{
889
+		final AutofarmPlayerRoutine bot = activeChar.getBot();
890
+		
891
+		if (command.startsWith("autofarm"))
892
+		{
893
+			showAutoFarm(activeChar);
894
+		}
895
+		
896
+		if (command.startsWith("radiusAutoFarm"))
897
+		{
898
+			StringTokenizer st = new StringTokenizer(command, " ");
899
+			st.nextToken();
900
+			try
901
+			{
902
+				String param = st.nextToken();
903
+				
904
+				if (param.startsWith("inc_radius"))
905
+				{
906
+					activeChar.setRadius(activeChar.getRadius() + 200);
907
+					showAutoFarm(activeChar);
908
+				}
909
+				else if (param.startsWith("dec_radius"))
910
+				{
911
+					activeChar.setRadius(activeChar.getRadius() - 200);
912
+					showAutoFarm(activeChar);
913
+				}
914
+				activeChar.saveAutoFarmSettings();
915
+			}
916
+			catch (Exception e)
917
+			{
918
+				e.printStackTrace();
919
+			}
920
+		}
921
+		
922
+		if (command.startsWith("pageAutoFarm"))
923
+		{
924
+			StringTokenizer st = new StringTokenizer(command, " ");
925
+			st.nextToken();
926
+			try
927
+			{
928
+				String param = st.nextToken();
929
+				
930
+				if (param.startsWith("inc_page"))
931
+				{
932
+					activeChar.setPage(activeChar.getPage() + 1);
933
+					showAutoFarm(activeChar);
934
+				}
935
+				else if (param.startsWith("dec_page"))
936
+				{
937
+					activeChar.setPage(activeChar.getPage() - 1);
938
+					showAutoFarm(activeChar);
939
+				}
940
+				activeChar.saveAutoFarmSettings();
941
+			}
942
+			catch (Exception e)
943
+			{
944
+				e.printStackTrace();
945
+			}
946
+		}
947
+		
948
+		if (command.startsWith("healAutoFarm"))
949
+		{
950
+			StringTokenizer st = new StringTokenizer(command, " ");
951
+			st.nextToken();
952
+			try
953
+			{
954
+				String param = st.nextToken();
955
+				
956
+				if (param.startsWith("inc_heal"))
957
+				{
958
+					activeChar.setHealPercent(activeChar.getHealPercent() + 10);
959
+					showAutoFarm(activeChar);
960
+				}
961
+				else if (param.startsWith("dec_heal"))
962
+				{
963
+					activeChar.setHealPercent(activeChar.getHealPercent() - 10);
964
+					showAutoFarm(activeChar);
965
+				}
966
+				activeChar.saveAutoFarmSettings();
967
+			}
968
+			catch (Exception e)
969
+			{
970
+				e.printStackTrace();
971
+			}
972
+		}
973
+		
974
+		if (command.startsWith("hpAutoFarm"))
975
+		{
976
+			StringTokenizer st = new StringTokenizer(command, " ");
977
+			st.nextToken();
978
+			try
979
+			{
980
+				String param = st.nextToken();
981
+				
982
+				if (param.contains("inc_hp_pot"))
983
+				{
984
+					activeChar.setHpPotionPercentage(activeChar.getHpPotionPercentage() + 5);
985
+					showAutoFarm(activeChar);
986
+				}
987
+				else if (param.contains("dec_hp_pot"))
988
+				{
989
+					activeChar.setHpPotionPercentage(activeChar.getHpPotionPercentage() - 5);
990
+					showAutoFarm(activeChar);
991
+				}
992
+				activeChar.saveAutoFarmSettings();
993
+			}
994
+			catch (Exception e)
995
+			{
996
+				e.printStackTrace();
997
+			}
998
+		}
999
+		
1000
+		if (command.startsWith("mpAutoFarm"))
1001
+		{
1002
+			StringTokenizer st = new StringTokenizer(command, " ");
1003
+			st.nextToken();
1004
+			try
1005
+			{
1006
+				String param = st.nextToken();
1007
+				
1008
+				if (param.contains("inc_mp_pot"))
1009
+				{
1010
+					activeChar.setMpPotionPercentage(activeChar.getMpPotionPercentage() + 5);
1011
+					showAutoFarm(activeChar);
1012
+				}
1013
+				else if (param.contains("dec_mp_pot"))
1014
+				{
1015
+					activeChar.setMpPotionPercentage(activeChar.getMpPotionPercentage() - 5);
1016
+					showAutoFarm(activeChar);
1017
+				}
1018
+				activeChar.saveAutoFarmSettings();
1019
+			}
1020
+			catch (Exception e)
1021
+			{
1022
+				e.printStackTrace();
1023
+			}
1024
+		}
1025
+		
1026
+		if (command.startsWith("enableAutoFarm"))
1027
+		{
1028
+			if (activeChar.isAutoFarm())
1029
+			{
1030
+				bot.stop();
1031
+				activeChar.setAutoFarm(false);
1032
+				activeChar.broadcastUserInfo();
1033
+				activeChar.broadcastCharInfo();
1034
+			}
1035
+			else
1036
+			{
1037
+				bot.start();
1038
+				activeChar.setAutoFarm(true);
1039
+				activeChar.broadcastUserInfo();
1040
+				activeChar.broadcastCharInfo();
1041
+			}
1042
+			
1043
+			showAutoFarm(activeChar);
1044
+		}
1045
+		
1046
+		if (command.startsWith("enableBuffProtect"))
1047
+		{
1048
+			activeChar.setNoBuffProtection(!activeChar.isNoBuffProtected());
1049
+			showAutoFarm(activeChar);
1050
+			activeChar.saveAutoFarmSettings();
1051
+		}
1052
+		
1053
+		if (command.startsWith("enableAntiKs"))
1054
+		{
1055
+			activeChar.setAntiKsProtection(!activeChar.isAntiKsProtected());
1056
+			
1057
+			if (activeChar.isAntiKsProtected())
1058
+			{
1059
+				// activeChar.sendPacket(new SystemMessage(SystemMessageId.ACTIVATE_RESPECT_HUNT));
1060
+				// activeChar.sendPacket(new ExShowScreenMessage("Respct Hunt On" , 3*1000, SMPOS.TOP_CENTER, false));
1061
+			}
1062
+			else
1063
+			{
1064
+				// activeChar.sendPacket(new SystemMessage(SystemMessageId.DESACTIVATE_RESPECT_HUNT));
1065
+				// activeChar.sendPacket(new ExShowScreenMessage("Respct Hunt Off" , 3*1000, SMPOS.TOP_CENTER, false));
1066
+			}
1067
+			
1068
+			activeChar.saveAutoFarmSettings();
1069
+			showAutoFarm(activeChar);
1070
+		}
1071
+		
1072
+		if (command.startsWith("enableSummonAttack"))
1073
+		{
1074
+			activeChar.setSummonAttack(!activeChar.isSummonAttack());
1075
+			if (activeChar.isSummonAttack())
1076
+			{
1077
+				// activeChar.sendPacket(new SystemMessage(SystemMessageId.ACTIVATE_SUMMON_ACTACK));
1078
+				// activeChar.sendPacket(new ExShowScreenMessage("Auto Farm Summon Attack On" , 3*1000, SMPOS.TOP_CENTER, false));
1079
+			}
1080
+			else
1081
+			{
1082
+				// activeChar.sendPacket(new SystemMessage(SystemMessageId.DESACTIVATE_SUMMON_ACTACK));
1083
+				// activeChar.sendPacket(new ExShowScreenMessage("Auto Farm Summon Attack Off" , 3*1000, SMPOS.TOP_CENTER, false));
1084
+			}
1085
+			activeChar.saveAutoFarmSettings();
1086
+			showAutoFarm(activeChar);
1087
+		}
1088
+		
1089
+		if (command.startsWith("summonSkillAutoFarm"))
1090
+		{
1091
+			StringTokenizer st = new StringTokenizer(command, " ");
1092
+			st.nextToken();
1093
+			try
1094
+			{
1095
+				String param = st.nextToken();
1096
+				
1097
+				if (param.startsWith("inc_summonSkill"))
1098
+				{
1099
+					activeChar.setSummonSkillPercent(activeChar.getSummonSkillPercent() + 10);
1100
+					showAutoFarm(activeChar);
1101
+				}
1102
+				else if (param.startsWith("dec_summonSkill"))
1103
+				{
1104
+					activeChar.setSummonSkillPercent(activeChar.getSummonSkillPercent() - 10);
1105
+					showAutoFarm(activeChar);
1106
+				}
1107
+				activeChar.saveAutoFarmSettings();
1108
+			}
1109
+			catch (Exception e)
1110
+			{
1111
+				e.printStackTrace();
1112
+			}
1113
+		}
1114
+		
1115
+		if (command.startsWith("ignoreMonster"))
1116
+		{
1117
+			int monsterId = 0;
1118
+			WorldObject target = activeChar.getTarget();
1119
+			if (target instanceof Monster)
1120
+			{
1121
+				monsterId = ((Monster) target).getNpcId();
1122
+			}
1123
+			
1124
+			if (target == null)
1125
+			{
1126
+				activeChar.sendMessage("You dont have a target");
1127
+				return false;
1128
+			}
1129
+			
1130
+			activeChar.sendMessage(target.getName() + " has been added to the ignore list.");
1131
+			activeChar.ignoredMonster(monsterId);
1132
+		}
1133
+		
1134
+		if (command.startsWith("activeMonster"))
1135
+		{
1136
+			int monsterId = 0;
1137
+			WorldObject target = activeChar.getTarget();
1138
+			if (target instanceof Monster)
1139
+			{
1140
+				monsterId = ((Monster) target).getNpcId();
1141
+			}
1142
+			
1143
+			if (target == null)
1144
+			{
1145
+				activeChar.sendMessage("You dont have a target");
1146
+				return false;
1147
+			}
1148
+			
1149
+			activeChar.sendMessage(target.getName() + " has been removed from the ignore list.");
1150
+			activeChar.activeMonster(monsterId);
1151
+		}
1152
+		
1153
+		return false;
1154
+	}
1155
+	
1156
+	private static final String ACTIVED = "<font color=00FF00>STARTED</font>";
1157
+	private static final String DESATIVED = "<font color=FF0000>STOPPED</font>";
1158
+	private static final String STOP = "STOP";
1159
+	private static final String START = "START";
1160
+	
1161
+	public static void showAutoFarm(Player activeChar)
1162
+	{
1163
+		NpcHtmlMessage html = new NpcHtmlMessage(0);
1164
+		html.setFile("data/html/mods/menu/AutoFarm.htm");
1165
+		html.replace("%player%", activeChar.getName());
1166
+		html.replace("%page%", StringUtil.formatNumber(activeChar.getPage() + 1));
1167
+		html.replace("%heal%", StringUtil.formatNumber(activeChar.getHealPercent()));
1168
+		html.replace("%radius%", StringUtil.formatNumber(activeChar.getRadius()));
1169
+		html.replace("%summonSkill%", StringUtil.formatNumber(activeChar.getSummonSkillPercent()));
1170
+		html.replace("%hpPotion%", StringUtil.formatNumber(activeChar.getHpPotionPercentage()));
1171
+		html.replace("%mpPotion%", StringUtil.formatNumber(activeChar.getMpPotionPercentage()));
1172
+		html.replace("%noBuff%", activeChar.isNoBuffProtected() ? "back=L2UI.CheckBox_checked fore=L2UI.CheckBox_checked" : "back=L2UI.CheckBox fore=L2UI.CheckBox");
1173
+		html.replace("%summonAtk%", activeChar.isSummonAttack() ? "back=L2UI.CheckBox_checked fore=L2UI.CheckBox_checked" : "back=L2UI.CheckBox fore=L2UI.CheckBox");
1174
+		html.replace("%antiKs%", activeChar.isAntiKsProtected() ? "back=L2UI.CheckBox_checked fore=L2UI.CheckBox_checked" : "back=L2UI.CheckBox fore=L2UI.CheckBox");
1175
+		html.replace("%autofarm%", activeChar.isAutoFarm() ? ACTIVED : DESATIVED);
1176
+		html.replace("%button%", activeChar.isAutoFarm() ? STOP : START);
1177
+		activeChar.sendPacket(html);
1178
+	}
1179
+	
1180
+	@Override
1181
+	public String[] getVoicedCommandList()
1182
+	{
1183
+		return VOICED_COMMANDS;
1184
+	}
1185
+}
1186
\ No newline at end of file
1187
diff --git java/org/l2jmobius/gameserver/model/actor/Creature.java java/org/l2jmobius/gameserver/model/actor/Creature.java
1188
index e6fc06d..4fcd802 100644
1189
--- java/org/l2jmobius/gameserver/model/actor/Creature.java
1190
+++ java/org/l2jmobius/gameserver/model/actor/Creature.java
1191
@@ -2224,6 +2224,15 @@
1192
 	}
1193
 	
1194
 	/**
1195
+	 * @param skillId The identifier of the L2Skill to check the knowledge
1196
+	 * @return True if the skill is known by the Creature.
1197
+	 */
1198
+	public Skill getSkill(int skillId)
1199
+	{
1200
+		return getSkills().get(skillId);
1201
+	}
1202
+	
1203
+	/**
1204
 	 * Set the Creature flying mode to True.
1205
 	 * @param mode the new checks if is flying
1206
 	 */
1207
@@ -9414,6 +9423,32 @@
1208
 	}
1209
 	
1210
 	/**
1211
+	 * Return the squared distance between the current position of the Creature and the given object.
1212
+	 * @param object WorldObject
1213
+	 * @return the squared distance
1214
+	 */
1215
+	public final double getDistanceSq(WorldObject object)
1216
+	{
1217
+		return getDistanceSq(object.getX(), object.getY(), object.getZ());
1218
+	}
1219
+	
1220
+	/**
1221
+	 * Return the squared distance between the current position of the Creature and the given x, y, z.
1222
+	 * @param x X position of the target
1223
+	 * @param y Y position of the target
1224
+	 * @param z Z position of the target
1225
+	 * @return the squared distance
1226
+	 */
1227
+	public final double getDistanceSq(int x, int y, int z)
1228
+	{
1229
+		double dx = x - getX();
1230
+		double dy = y - getY();
1231
+		double dz = z - getZ();
1232
+		
1233
+		return ((dx * dx) + (dy * dy) + (dz * dz));
1234
+	}
1235
+	
1236
+	/**
1237
 	 * Gets the _triggered skills.
1238
 	 * @return the _triggeredSkills
1239
 	 */
1240
diff --git java/org/l2jmobius/gameserver/model/actor/Player.java java/org/l2jmobius/gameserver/model/actor/Player.java
1241
index ce1f47c..41f6412 100644
1242
--- java/org/l2jmobius/gameserver/model/actor/Player.java
1243
+++ java/org/l2jmobius/gameserver/model/actor/Player.java
1244
@@ -19,6 +19,7 @@
1245
 import java.sql.Connection;
1246
 import java.sql.PreparedStatement;
1247
 import java.sql.ResultSet;
1248
+import java.sql.SQLException;
1249
 import java.util.ArrayList;
1250
 import java.util.Calendar;
1251
 import java.util.Collection;
1252
@@ -240,8 +241,11 @@
1253
 import org.l2jmobius.gameserver.taskmanager.PlayerAutoSaveTaskManager;
1254
 import org.l2jmobius.gameserver.taskmanager.PvpFlagTaskManager;
1255
 import org.l2jmobius.gameserver.util.Broadcast;
1256
+import org.l2jmobius.gameserver.util.MathUtil;
1257
 import org.l2jmobius.gameserver.util.Util;
1258
 
1259
+import Base.AutoFarm.AutofarmPlayerRoutine;
1260
+
1261
 /**
1262
  * This class represents all player characters in the world.<br>
1263
  * There is always a client-thread connected to this (except if a player-store is activated upon logout).
1264
@@ -13093,6 +13105,8 @@
1265
 			getVariables().setIntegerList(PlayerVariables.AUTO_USE_SETTINGS, settings);
1266
 		}
1267
 		
1268
+		_bot.stop();
1269
+		
1270
 		// Check if the Player is in observer mode to set its position to its position before entering in observer mode
1271
 		if (inObserverMode())
1272
 		{
1273
@@ -15649,4 +15663,233 @@
1274
 	{
1275
 		return true;
1276
 	}
1277
+	
1278
+	// ------------
1279
+	// Autofarm
1280
+	// ------------
1281
+	
1282
+	private boolean _autoFarm;
1283
+	
1284
+	public void setAutoFarm(boolean comm)
1285
+	{
1286
+		_autoFarm = comm;
1287
+	}
1288
+	
1289
+	public boolean isAutoFarm()
1290
+	{
1291
+		return _autoFarm;
1292
+	}
1293
+	
1294
+	private int autoFarmRadius = 1200;
1295
+	
1296
+	public void setRadius(int value)
1297
+	{
1298
+		autoFarmRadius = MathUtil.limit(value, 200, 3000);
1299
+	}
1300
+	
1301
+	public int getRadius()
1302
+	{
1303
+		return autoFarmRadius;
1304
+	}
1305
+	
1306
+	private int autoFarmShortCut = 9;
1307
+	
1308
+	public void setPage(int value)
1309
+	{
1310
+		autoFarmShortCut = MathUtil.limit(value, 0, 9);
1311
+	}
1312
+	
1313
+	public int getPage()
1314
+	{
1315
+		return autoFarmShortCut;
1316
+	}
1317
+	
1318
+	private int autoFarmHealPercente = 30;
1319
+	
1320
+	public void setHealPercent(int value)
1321
+	{
1322
+		autoFarmHealPercente = MathUtil.limit(value, 20, 90);
1323
+	}
1324
+	
1325
+	public int getHealPercent()
1326
+	{
1327
+		return autoFarmHealPercente;
1328
+	}
1329
+	
1330
+	private boolean autoFarmBuffProtection = false;
1331
+	
1332
+	public void setNoBuffProtection(boolean val)
1333
+	{
1334
+		autoFarmBuffProtection = val;
1335
+	}
1336
+	
1337
+	public boolean isNoBuffProtected()
1338
+	{
1339
+		return autoFarmBuffProtection;
1340
+	}
1341
+	
1342
+	private boolean autoAntiKsProtection = false;
1343
+	
1344
+	public void setAntiKsProtection(boolean val)
1345
+	{
1346
+		autoAntiKsProtection = val;
1347
+	}
1348
+	
1349
+	public boolean isAntiKsProtected()
1350
+	{
1351
+		return autoAntiKsProtection;
1352
+	}
1353
+	
1354
+	private boolean autoFarmSummonAttack = false;
1355
+	
1356
+	public void setSummonAttack(boolean val)
1357
+	{
1358
+		autoFarmSummonAttack = val;
1359
+	}
1360
+	
1361
+	public boolean isSummonAttack()
1362
+	{
1363
+		return autoFarmSummonAttack;
1364
+	}
1365
+	
1366
+	private int autoFarmSummonSkillPercente = 0;
1367
+	
1368
+	public void setSummonSkillPercent(int value)
1369
+	{
1370
+		autoFarmSummonSkillPercente = MathUtil.limit(value, 0, 90);
1371
+	}
1372
+	
1373
+	public int getSummonSkillPercent()
1374
+	{
1375
+		return autoFarmSummonSkillPercente;
1376
+	}
1377
+	
1378
+	private int hpPotionPercent = 60;
1379
+	private int mpPotionPercent = 60;
1380
+	
1381
+	public void setHpPotionPercentage(int value)
1382
+	{
1383
+		hpPotionPercent = MathUtil.limit(value, 0, 100);
1384
+	}
1385
+	
1386
+	public int getHpPotionPercentage()
1387
+	{
1388
+		return hpPotionPercent;
1389
+	}
1390
+	
1391
+	public void setMpPotionPercentage(int value)
1392
+	{
1393
+		mpPotionPercent = MathUtil.limit(value, 0, 100);
1394
+	}
1395
+	
1396
+	public int getMpPotionPercentage()
1397
+	{
1398
+		return mpPotionPercent;
1399
+	}
1400
+	
1401
+	private final List<Integer> _ignoredMonster = new ArrayList<>();
1402
+	
1403
+	public void ignoredMonster(Integer npcId)
1404
+	{
1405
+		_ignoredMonster.add(npcId);
1406
+	}
1407
+	
1408
+	public void activeMonster(Integer npcId)
1409
+	{
1410
+		if (_ignoredMonster.contains(npcId))
1411
+		{
1412
+			_ignoredMonster.remove(npcId);
1413
+		}
1414
+	}
1415
+	
1416
+	public boolean ignoredMonsterContain(int npcId)
1417
+	{
1418
+		return _ignoredMonster.contains(npcId);
1419
+	}
1420
+	
1421
+	private AutofarmPlayerRoutine _bot = new AutofarmPlayerRoutine(this);
1422
+	
1423
+	public AutofarmPlayerRoutine getBot()
1424
+	{
1425
+		if (_bot == null)
1426
+		{
1427
+			_bot = new AutofarmPlayerRoutine(this);
1428
+		}
1429
+		
1430
+		return _bot;
1431
+	}
1432
+	
1433
+	public void saveAutoFarmSettings()
1434
+	{
1435
+		try (Connection con = DatabaseFactory.getConnection())
1436
+		{
1437
+			String updateSql = "REPLACE INTO character_autofarm (char_id, char_name,  radius, short_cut, heal_percent, buff_protection, anti_ks_protection, summon_attack, summon_skill_percent, hp_potion_percent, mp_potion_percent) VALUES (?, ?, ?,  ?, ?, ?, ?, ?, ?, ?, ?)";
1438
+			try (PreparedStatement updateStatement = con.prepareStatement(updateSql))
1439
+			{
1440
+				updateStatement.setInt(1, getObjectId()); // char_id
1441
+				updateStatement.setString(2, getName()); // char_name
1442
+				
1443
+				updateStatement.setInt(3, autoFarmRadius);
1444
+				updateStatement.setInt(4, autoFarmShortCut);
1445
+				updateStatement.setInt(5, autoFarmHealPercente);
1446
+				updateStatement.setBoolean(6, autoFarmBuffProtection);
1447
+				updateStatement.setBoolean(7, autoAntiKsProtection);
1448
+				updateStatement.setBoolean(8, autoFarmSummonAttack);
1449
+				updateStatement.setInt(9, autoFarmSummonSkillPercente);
1450
+				updateStatement.setInt(10, hpPotionPercent);
1451
+				updateStatement.setInt(11, mpPotionPercent);
1452
+				updateStatement.executeUpdate();
1453
+			}
1454
+		}
1455
+		catch (SQLException e)
1456
+		{
1457
+			e.printStackTrace();
1458
+		}
1459
+	}
1460
+	
1461
+	public void loadAutoFarmSettings()
1462
+	{
1463
+		try (Connection con = DatabaseFactory.getConnection())
1464
+		{
1465
+			String selectSql = "SELECT * FROM character_autofarm WHERE char_id = ?";
1466
+			try (PreparedStatement selectStatement = con.prepareStatement(selectSql))
1467
+			{
1468
+				selectStatement.setInt(1, getObjectId()); // char_id
1469
+				try (ResultSet resultSet = selectStatement.executeQuery())
1470
+				{
1471
+					if (resultSet.next())
1472
+					{
1473
+						
1474
+						autoFarmRadius = resultSet.getInt("radius");
1475
+						autoFarmShortCut = resultSet.getInt("short_cut");
1476
+						autoFarmHealPercente = resultSet.getInt("heal_percent");
1477
+						autoFarmBuffProtection = resultSet.getBoolean("buff_protection");
1478
+						autoAntiKsProtection = resultSet.getBoolean("anti_ks_protection");
1479
+						autoFarmSummonAttack = resultSet.getBoolean("summon_attack");
1480
+						autoFarmSummonSkillPercente = resultSet.getInt("summon_skill_percent");
1481
+						hpPotionPercent = resultSet.getInt("hp_potion_percent");
1482
+						mpPotionPercent = resultSet.getInt("mp_potion_percent");
1483
+					}
1484
+					else
1485
+					{
1486
+						
1487
+						autoFarmRadius = 1200;
1488
+						autoFarmShortCut = 9;
1489
+						autoFarmHealPercente = 30;
1490
+						autoFarmBuffProtection = false;
1491
+						autoAntiKsProtection = false;
1492
+						autoFarmSummonAttack = false;
1493
+						autoFarmSummonSkillPercente = 0;
1494
+						hpPotionPercent = 60;
1495
+						mpPotionPercent = 60;
1496
+					}
1497
+				}
1498
+			}
1499
+		}
1500
+		catch (SQLException e)
1501
+		{
1502
+			e.printStackTrace();
1503
+		}
1504
+	}
1505
+	
1506
 }
1507
\ No newline at end of file
1508
diff --git java/org/l2jmobius/gameserver/network/SystemMessageId.java java/org/l2jmobius/gameserver/network/SystemMessageId.java
1509
index faeaa6a..ec95ef5 100644
1510
--- java/org/l2jmobius/gameserver/network/SystemMessageId.java
1511
+++ java/org/l2jmobius/gameserver/network/SystemMessageId.java
1512
@@ -6280,6 +6280,20 @@
1513
 	@ClientString(id = 2153, message = "You are currently logged into 10 of your accounts and can no longer access your other accounts.")
1514
 	public static SystemMessageId YOU_ARE_CURRENTLY_LOGGED_INTO_10_OF_YOUR_ACCOUNTS_AND_CAN_NO_LONGER_ACCESS_YOUR_OTHER_ACCOUNTS;
1515
 	
1516
+	@ClientString(id = 2156, message = "Because of your Fatigue level, this is not allowed.")
1517
+	public static SystemMessageId ACTIVATE_SUMMON_ACTACK;
1518
+	
1519
+	@ClientString(id = 2157, message = "Because of your Fatigue level, this is not allowed.")
1520
+	public static SystemMessageId DESACTIVATE_SUMMON_ACTACK;
1521
+	@ClientString(id = 2158, message = "Because of your Fatigue level, this is not allowed.")
1522
+	public static SystemMessageId ACTIVATE_RESPECT_HUNT;
1523
+	@ClientString(id = 2159, message = "Because of your Fatigue level, this is not allowed.")
1524
+	public static SystemMessageId DESACTIVATE_RESPECT_HUNT;
1525
+	@ClientString(id = 2155, message = "Because of your Fatigue level, this is not allowed.")
1526
+	public static SystemMessageId AUTO_FARM_DESACTIVATED;
1527
+	@ClientString(id = 2160, message = "Because of your Fatigue level, this is not allowed.")
1528
+	public static SystemMessageId AUTO_FARM_ACTIVATED;
1529
+	
1530
 	static
1531
 	{
1532
 		buildFastLookupTable();
1533
diff --git java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
1534
index fb7f499..7e69579 100644
1535
--- java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
1536
+++ java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
1537
@@ -324,6 +324,19 @@
1538
 		
1539
 		PetitionManager.getInstance().checkPetitionMessages(player);
1540
 		
1541
+		player.loadAutoFarmSettings();
1542
+		
1543
+		if (player.isSummonAttack())
1544
+		{
1545
+			player.sendPacket(new SystemMessage(SystemMessageId.ACTIVATE_SUMMON_ACTACK));
1546
+			
1547
+		}
1548
+		
1549
+		if (player.isAntiKsProtected())
1550
+		{
1551
+			player.sendPacket(new SystemMessage(SystemMessageId.ACTIVATE_RESPECT_HUNT));
1552
+		}
1553
+		
1554
 		if ((player.getClanId() != 0) && (player.getClan() != null))
1555
 		{
1556
 			player.sendPacket(new PledgeShowMemberListAll(player.getClan(), player));
1557
diff --git java/org/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java java/org/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java
1558
index dcfe0f4..431c5cf 100644
1559
--- java/org/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java
1560
+++ java/org/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java
1561
@@ -16,6 +16,8 @@
1562
  */
1563
 package org.l2jmobius.gameserver.network.clientpackets;
1564
 
1565
+import java.util.StringTokenizer;
1566
+
1567
 import org.l2jmobius.Config;
1568
 import org.l2jmobius.commons.network.ReadablePacket;
1569
 import org.l2jmobius.commons.util.CommonUtil;
1570
@@ -37,10 +39,15 @@
1571
 import org.l2jmobius.gameserver.model.olympiad.Olympiad;
1572
 import org.l2jmobius.gameserver.network.GameClient;
1573
 import org.l2jmobius.gameserver.network.PacketLogger;
1574
+import org.l2jmobius.gameserver.network.SystemMessageId;
1575
 import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
1576
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
1577
 import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
1578
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
1579
 import org.l2jmobius.gameserver.util.GMAudit;
1580
 
1581
+import Base.AutoFarm.AutofarmPlayerRoutine;
1582
+
1583
 public class RequestBypassToServer implements ClientPacket
1584
 {
1585
 	// S
1586
@@ -61,6 +68,8 @@
1587
 			return;
1588
 		}
1589
 		
1590
+		final AutofarmPlayerRoutine bot = player.getBot();
1591
+		
1592
 		if (!client.getFloodProtectors().canUseServerBypass())
1593
 		{
1594
 			return;
1595
@@ -107,6 +116,123 @@
1596
 				ach.useAdminCommand(_command, player);
1597
 				player.sendPacket(ActionFailed.STATIC_PACKET);
1598
 			}
1599
+			
1600
+			else if (_command.startsWith("_autofarm"))
1601
+			{
1602
+				if (player.isAutoFarm())
1603
+				{
1604
+					bot.stop();
1605
+					player.setAutoFarm(false);
1606
+					player.broadcastUserInfo();
1607
+					player.broadcastCharInfo();
1608
+				}
1609
+				else
1610
+				{
1611
+					bot.start();
1612
+					player.setAutoFarm(true);
1613
+					player.broadcastUserInfo();
1614
+					player.broadcastCharInfo();
1615
+				}
1616
+				
1617
+			}
1618
+			
1619
+			if (_command.startsWith("_pageAutoFarm"))
1620
+			{
1621
+				StringTokenizer st = new StringTokenizer(_command, " ");
1622
+				st.nextToken();
1623
+				try
1624
+				{
1625
+					String param = st.nextToken();
1626
+					
1627
+					if (param.startsWith("inc_page") || param.startsWith("dec_page"))
1628
+					{
1629
+						int newPage;
1630
+						
1631
+						if (param.startsWith("inc_page"))
1632
+						{
1633
+							newPage = player.getPage() + 1;
1634
+						}
1635
+						else
1636
+						{
1637
+							newPage = player.getPage() - 1;
1638
+						}
1639
+						
1640
+						if ((newPage >= 0) && (newPage <= 9))
1641
+						{
1642
+							String[] pageStrings =
1643
+							{
1644
+								"F1",
1645
+								"F2",
1646
+								"F3",
1647
+								"F4",
1648
+								"F5",
1649
+								"F6",
1650
+								"F7",
1651
+								"F8",
1652
+								"F9",
1653
+								"F10"
1654
+							};
1655
+							
1656
+							player.setPage(newPage);
1657
+							player.sendPacket(new ExShowScreenMessage("Auto Farm Skill Bar " + pageStrings[newPage], 3 * 1000));
1658
+							player.saveAutoFarmSettings();
1659
+							
1660
+						}
1661
+						
1662
+					}
1663
+					
1664
+				}
1665
+				catch (Exception e)
1666
+				{
1667
+					e.printStackTrace();
1668
+				}
1669
+			}
1670
+			
1671
+			if (_command.startsWith("_enableBuffProtect"))
1672
+			{
1673
+				player.setNoBuffProtection(!player.isNoBuffProtected());
1674
+				if (player.isNoBuffProtected())
1675
+				{
1676
+					player.sendPacket(new ExShowScreenMessage("Auto Farm Buff Protect On", 3 * 1000));
1677
+				}
1678
+				else
1679
+				{
1680
+					player.sendPacket(new ExShowScreenMessage("Auto Farm Buff Protect Off", 3 * 1000));
1681
+				}
1682
+				player.saveAutoFarmSettings();
1683
+			}
1684
+			if (_command.startsWith("_enableSummonAttack"))
1685
+			{
1686
+				player.setSummonAttack(!player.isSummonAttack());
1687
+				if (player.isSummonAttack())
1688
+				{
1689
+					player.sendPacket(new SystemMessage(SystemMessageId.ACTIVATE_SUMMON_ACTACK));
1690
+					player.sendPacket(new ExShowScreenMessage("Auto Farm Summon Attack On", 3 * 1000));
1691
+				}
1692
+				else
1693
+				{
1694
+					player.sendPacket(new SystemMessage(SystemMessageId.DESACTIVATE_SUMMON_ACTACK));
1695
+					player.sendPacket(new ExShowScreenMessage("Auto Farm Summon Attack Off", 3 * 1000));
1696
+				}
1697
+				player.saveAutoFarmSettings();
1698
+			}
1699
+			
1700
+			else if (_command.startsWith("voiced_"))
1701
+			{
1702
+				String command = _command.split(" ")[0];
1703
+				
1704
+				IVoicedCommandHandler ach = VoicedCommandHandler.getInstance().getVoicedCommandHandler(_command.substring(7));
1705
+				
1706
+				if (ach == null)
1707
+				{
1708
+					player.sendMessage("The command " + command.substring(7) + " does not exist!");
1709
+					PacketLogger.warning("No handler registered for command '" + _command + "'");
1710
+					return;
1711
+				}
1712
+				
1713
+				ach.useVoicedCommand(_command.substring(7), player, null);
1714
+			}
1715
+			
1716
 			else if (_command.equals("come_here") && player.isGM())
1717
 			{
1718
 				final WorldObject obj = player.getTarget();
1719
diff --git java/org/l2jmobius/gameserver/network/serverpackets/Die.java java/org/l2jmobius/gameserver/network/serverpackets/Die.java
1720
index ee75ca2..84358ae 100644
1721
--- java/org/l2jmobius/gameserver/network/serverpackets/Die.java
1722
+++ java/org/l2jmobius/gameserver/network/serverpackets/Die.java
1723
@@ -27,6 +27,8 @@
1724
 import org.l2jmobius.gameserver.model.siege.SiegeClan;
1725
 import org.l2jmobius.gameserver.network.ServerPackets;
1726
 
1727
+import Base.AutoFarm.AutofarmPlayerRoutine;
1728
+
1729
 public class Die extends ServerPacket
1730
 {
1731
 	private final int _objectId;
1732
@@ -43,9 +45,17 @@
1733
 		if (creature instanceof Player)
1734
 		{
1735
 			final Player player = creature.getActingPlayer();
1736
+			final AutofarmPlayerRoutine bot = player.getBot();
1737
 			_allowFixedRes = player.getAccessLevel().allowFixedRes();
1738
 			_clan = player.getClan();
1739
 			_canTeleport = !player.isPendingRevive();
1740
+			
1741
+			if (player.isAutoFarm())
1742
+			{
1743
+				bot.stop();
1744
+				player.setAutoFarm(false);
1745
+			}
1746
+			
1747
 		}
1748
 		_objectId = creature.getObjectId();
1749
 		_fake = !creature.isDead();
1750