RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
NpcDropManager.java
1package com.osroyale.game.world.entity.mob.npc.drop;
2
3import com.osroyale.Config;
4import com.osroyale.content.CrystalChest;
5import com.osroyale.content.ItemCreation;
6import com.osroyale.content.achievement.AchievementHandler;
7import com.osroyale.content.achievement.AchievementKey;
8import com.osroyale.content.collectionlog.CollectionLog;
9import com.osroyale.content.pet.PetData;
10import com.osroyale.content.pet.Pets;
11import com.osroyale.content.skill.impl.prayer.AshData;
12import com.osroyale.content.skill.impl.prayer.BoneData;
13import com.osroyale.game.world.World;
14import com.osroyale.game.world.entity.mob.npc.Npc;
15import com.osroyale.game.world.entity.mob.player.Player;
16import com.osroyale.game.world.entity.mob.player.PlayerRight;
17import com.osroyale.game.world.entity.skill.Skill;
18import com.osroyale.game.world.items.Item;
19import com.osroyale.game.world.items.ground.GroundItem;
20import com.osroyale.game.world.position.Position;
21import com.osroyale.net.discord.DiscordPlugin;
22import com.osroyale.net.packet.out.SendMessage;
23import com.osroyale.net.packet.out.SendScreenshot;
24import com.osroyale.util.Items;
25import com.osroyale.util.RandomGen;
26import com.osroyale.util.Utility;
27import plugin.itemon.item.LootingBagPlugin;
28
29import java.util.Arrays;
30import java.util.HashMap;
31import java.util.List;
32import java.util.Map;
33
69
70* The manager class which holds the static entries of drop tables and has
71 * a method to execute a drop table from the specified npc.
72 *
73 * @author <a href="http://www.rune-server.org/members/stand+up/">Stand Up</a>
74 * @since 29-1-2017.
75 */
76public final class NpcDropManager {
77
81 public static final Map<Integer, NpcDropTable> NPC_DROPS = new HashMap<>();
82
86 private static final int[] ALTERNATIVE_POSITION = {2044, 2043, 2042, 494, 8060};
87
88 // use new drop system
89 private static final boolean USE_NEW_SYSTEM = true;
90
94 public static void drop(Player killer, Npc npc) {
95 if (killer == null) {
96 return;
97 }
98
99 if (npc == null) {
100 return;
101 }
102
103 if (USE_NEW_SYSTEM) {
104 rollDrop(killer, npc);
105 AchievementHandler.activate(killer, AchievementKey.NPCS);
106 return;
107 }
108
109 NpcDropTable table = NPC_DROPS.get(npc.id);
110
111 if (table == null) {
112 return;
113 }
114
115 RandomGen gen = new RandomGen();
116 List<NpcDrop> npc_drops = table.generate(killer, false);
117 Position dropPosition = npc.getPosition().copy();
118
119 // special drop positions
120 if (checkAlternativePosition(npc.id)) {
121 dropPosition = killer.getPosition().copy();
122 }
123
124 // crystal key drop
125 if (npc.getMaximumHealth() > 50 && Utility.random(150) <= 5) {
126 Item crystal_key = Utility.randomElement(CrystalChest.KEY_HALVES);
127 GroundItem.create(killer, crystal_key, dropPosition);
128 killer.send(new SendMessage("<col=BA383E>Rare Drop Notification: </col>" + crystal_key.getName()));
129 AchievementHandler.activate(killer, AchievementKey.RARE_DROPS);
130 }
131
132 // casket drop
133 if (npc.getMaximumHealth() > 10 && Utility.random(200) <= 10) {
134 Item casket = new Item(405);
135 GroundItem.create(killer, casket, dropPosition);
136 killer.send(new SendMessage("<col=BA383E>Rare Drop Notification: </col>" + casket.getName(), true));
137 AchievementHandler.activate(killer, AchievementKey.RARE_DROPS);
138 }
139
140 // drop table
141 for (NpcDrop drop : npc_drops) {
142 Item item = drop.toItem(gen);
143
144 if (item.getId() == 11941 && (killer.playerAssistant.contains(new Item(LootingBagPlugin.OPENED_ID)) || killer.playerAssistant.contains(item))) { // looting bag
145 killer.message(true, "You have missed out on " + Utility.getAOrAn(item.getName()) + " " + item.getName() + " since you already have on on your account.");
146 continue;
147 }
148
149// if (killer.clanChannel != null && killer.clanChannel.lootshareEnabled()) {
150// killer.forClan(channel -> channel.splitLoot(killer, npc, item));
151// return;
152// }
153
154 if (killer.settings.dropNotification && item.getValue() > 1_000_000) {
155 String name = item.getName();
156 killer.send(new SendMessage("<col=BA383E>Exotic Drop Notification: </col>" + name + " (" + Utility.formatDigits(item.getValue()) + " coins)"));
157 World.sendMessage("<col=BA383E>Tarnish: <col=" + killer.right.getColor() + ">" + killer.getName() + " </col>has just received " + Utility.getAOrAn(name) + " <col=BA383E>" + name + " </col>from <col=BA383E>" + npc.getName() + "</col>!");
158 DiscordPlugin.sendSimpleMessage(killer.getName() + " has just received " + Utility.getAOrAn(name) + " " + name + " from " + npc.getName() + "!");
159 if (killer.settings.screenshotKill) {
160 killer.getPlayer().send(new SendScreenshot());
161 }
162 } else if (killer.settings.dropNotification && item.getValue() > 100_000) {
163 String name = item.getName();
164 killer.send(new SendMessage("<col=BA383E>Rare Drop Notification: </col>" + name + " (" + Utility.formatDigits(item.getValue()) + " coins)"));
165 AchievementHandler.activate(killer, AchievementKey.RARE_DROPS);
166 } else if (killer.settings.untradeableNotification && !item.isTradeable()) {
167 killer.send(new SendMessage("<col=F5424B>Untradeable Drop Notification: </col>" + item.getName()));
168 }
169
170 CollectionLog.checkItemDrop(killer, npc.id, item.getId(), item.getAmount());
171
172 if (npc.id == 494 && item.getId() == 11907) {
173 tridentRunes(killer, dropPosition);
174 }
175
176 if (!item.isStackable()) {
177 Item single = item.createWithAmount(1);
178 for (int i = 0; i < item.getAmount(); i++)
179 GroundItem.create(killer, single, dropPosition);
180 } else {
181 GroundItem.create(killer, item, dropPosition);
182 }
183 }
184 }
185
186 private static void tridentRunes(Player killer, Position dropPosition) {
187 List<Item> fullChargeItems = Arrays.asList(
188 new Item(Items.DEATH_RUNE, 2500), new Item(Items.CHAOS_RUNE, 2500),
189 new Item(Items.FIRE_RUNE, 12500), new Item(Items.COINS, 25000)
190 );
191
192 fullChargeItems.forEach(item -> GroundItem.create(killer, item, dropPosition));
193 }
194
195 private static void handleBoneCrusher(Player player, BoneData bone) {
196 if (bone == null) { return; }
197
198 var exp = (bone.getExperience() * Config.PRAYER_MODIFICATION);
199 player.skills.addExperience(Skill.PRAYER, exp);
200 AchievementHandler.activate(player, AchievementKey.BURY_BONES, 1);
201
202 if (player.equipment.hasAmulet() && player.equipment.getAmuletSlot().getId() == 22111) {
203 int current = player.skills.getLevel(Skill.PRAYER);
204 int maximum = player.skills.getMaxLevel(Skill.PRAYER);
205
206 if (current < maximum) {
207 int points = bone.getBoneAmulet();
208
209 if (current + points > maximum) {
210 points = maximum - current;
211 }
212
213 player.skills.get(Skill.PRAYER).addLevel(points);
214 player.skills.refresh(Skill.PRAYER);
215 player.message("You feel your " + player.equipment.getAmuletSlot().getName() + " vibrate as you bury the bone.");
216 }
217 }
218 }
219
220 private static void handleAshSanctifier(Player player, AshData ashes) {
221 if (ashes == null) { return; }
222 var exp = (ashes.getExperience() * Config.PRAYER_MODIFICATION);
223 player.skills.addExperience(Skill.PRAYER, exp);
224 }
225
226 private static NpcDrop rollDrop(Player player, Npc npc) {
227 // player.send(new SendMessage("Called rollDrop"));
228 NpcDropTable table = NPC_DROPS.get(npc.id);
229 Position dropPos = npc.getPosition().copy();
230 if (checkAlternativePosition(npc.id)) {
231 dropPos = player.getPosition().copy();
232 }
233 if (table == null) {
234 return null;
235 }
236 handleMiscDrops(player, npc);
237 NpcDrop[] drops = table.drops;
238 for (NpcDrop drop : drops) {
239 if (drop.getWeight() == 0) {
240 Item item = drop.toItem(new RandomGen());
241 if (BoneData.forId(item.getId()).isPresent() && !item.isNoted() && player.inventory.contains(Items.BONECRUSHER)) {
242 handleBoneCrusher(player, BoneData.forId(item.getId()).get());
243 continue;
244 }
245 if (AshData.forId(item.getId()).isPresent() && !item.isNoted() && player.inventory.contains(25781)) {
246 handleAshSanctifier(player, AshData.forId(item.getId()).get());
247 continue;
248 }
252 if(PetData.forItem(item.getId()).isPresent()) {
253 Pets.onReward(player, item.getId());
254 } else {
255 GroundItem.create(player, item, dropPos);
256 }
257 }
258 }
259 WeightedCollection<NpcDrop> rc = new WeightedCollection<>();
260 for (NpcDrop drop : drops) {
261 double drOffset = 1 + (PlayerRight.getDropRateBonus(player) / 100.0); // dr bonus is in percent, conversion is 1 + (percent / 100.0)
262 int weightMultiplier = 1;
263 double dropChance = (drop.getWeight() * weightMultiplier) / drOffset;
264 if (dropChance < 1) {
265 dropChance = 1;
266 }
267 double weight = 1.0 / dropChance;
268 if (drop.getWeight() != 0) {
269 rc.add(weight, drop);
270 }
271 }
272
273 double weightSum = rc.getTotal();
274
275 if (Math.random() <= weightSum) {
276 NpcDrop selectedDrop = rc.next();
277 Item item = selectedDrop.toItem(new RandomGen());
278 handleMessages(player, npc, item);
282 if (npc.id == 494 && item.getId() == 11907) {
283 tridentRunes(player, dropPos);
284 }
285 if(PetData.forItem(item.getId()).isPresent()) {
286 Pets.onReward(player, item.getId());
287 } else {
288 GroundItem.create(player, item, dropPos);
289 }
290 CollectionLog.checkItemDrop(player, npc.id, item.getId(), item.getAmount());
291 return selectedDrop;
292 }
293
294 return null;
295 }
296
297 private static void handleMiscDrops(Player player, Npc npc) {
298 Position dropPosition = npc.getPosition().copy();
299 if (checkAlternativePosition(npc.id)) {
300 dropPosition = player.getPosition().copy();
301 }
302 if (npc.getMaximumHealth() > 50 && Utility.random(150) <= 5) {
303 Item crystal_key = Utility.randomElement(CrystalChest.KEY_HALVES);
304 GroundItem.create(player, crystal_key, dropPosition);
305 player.send(new SendMessage("<col=BA383E>Rare Drop Notification: </col>" + crystal_key.getName()));
306 AchievementHandler.activate(player, AchievementKey.RARE_DROPS);
307 }
308
309 // casket drop
310 if (npc.getMaximumHealth() > 10 && Utility.random(200) <= 10) {
311 Item casket = new Item(405);
312 GroundItem.create(player, casket, dropPosition);
313 player.send(new SendMessage("<col=BA383E>Rare Drop Notification: </col>" + casket.getName(), true));
314 AchievementHandler.activate(player, AchievementKey.RARE_DROPS);
315 }
316 }
317
318 private static void handleMessages(Player player, Npc npc, Item item) {
319 if (item.getId() == 11941 && (player.playerAssistant.contains(new Item(LootingBagPlugin.OPENED_ID)) || player.playerAssistant.contains(item))) { // looting bag
320 player.message("You have missed out on " + Utility.getAOrAn(item.getName()) + " " + item.getName() + " since you already have on on your account.");
321 return;
322 }
323
324 if (player.settings.dropNotification && item.getValue() > 1_000_000) {
325 String name = item.getName();
326 player.send(new SendMessage("<col=BA383E>Exotic Drop Notification: </col>" + name + " (" + Utility.formatDigits(item.getValue()) + " coins)"));
327 World.sendMessage("<col=BA383E>Tarnish: <col=" + player.right.getColor() + ">" + player.getName() + " </col>has just received " + Utility.getAOrAn(name) + " <col=BA383E>" + name + " </col>from <col=BA383E>" + npc.getName() + "</col>!");
328 DiscordPlugin.sendSimpleMessage("Exotic drop: " + player.getName() + " has just received " + Utility.getAOrAn(name) + " " + name + " from " + npc.getName() + "!");
329 AchievementHandler.activate(player, AchievementKey.RARE_DROPS);
330 if (player.settings.screenshotKill) {
331 player.getPlayer().send(new SendScreenshot());
332 }
333 } else if (player.settings.dropNotification && item.getValue() > 100_000) {
334 String name = item.getName();
335 player.send(new SendMessage("<col=BA383E>Rare Drop Notification: </col>" + name + " (" + Utility.formatDigits(item.getValue()) + " coins)"));
336 AchievementHandler.activate(player, AchievementKey.RARE_DROPS);
337 } else if (player.settings.untradeableNotification && !item.isTradeable()) {
338 player.send(new SendMessage("<col=F5424B>Untradeable Drop Notification: </col>" + item.getName()));
339 }
340 }
341
342 private static boolean checkAlternativePosition(int npc) {
343 for (int alternative : ALTERNATIVE_POSITION) {
344 if (alternative == npc)
345 return true;
346 }
347 return false;
348 }
349}