2022-04-30 09:41:17 -04:00
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
2023-08-03 08:27:08 -04:00
package engine.gameManager ;
2022-04-30 09:41:17 -04:00
2023-04-06 20:07:24 -05:00
import engine.Enum ;
2023-08-03 09:43:30 -04:00
import engine.loot.* ;
2023-04-06 20:07:24 -05:00
import engine.net.DispatchMessage ;
2023-08-09 17:52:39 -04:00
import engine.net.client.msg.ErrorPopupMsg ;
2023-04-06 20:07:24 -05:00
import engine.net.client.msg.chat.ChatSystemMsg ;
import engine.objects.* ;
2023-08-02 19:57:32 -05:00
import org.pmw.tinylog.Logger ;
2023-04-06 20:07:24 -05:00
import java.util.ArrayList ;
2024-07-04 19:49:24 -05:00
import java.util.Arrays ;
2022-04-30 09:41:17 -04:00
import java.util.HashMap ;
2024-06-15 16:51:46 -05:00
import java.util.List ;
2022-04-30 09:41:17 -04:00
import java.util.concurrent.ThreadLocalRandom ;
/**
* Class contains static methods for data from Magicbane's loot tables
*/
2023-08-03 09:04:20 -04:00
public enum LootManager {
LOOTMANAGER ;
2022-04-30 09:41:17 -04:00
2023-08-06 17:44:30 -04:00
// Newer tables
2023-08-06 18:09:34 -04:00
public static HashMap < Integer , ArrayList < GenTableEntry >> _genTables = new HashMap <> ();
2023-08-07 08:39:08 -04:00
public static HashMap < Integer , ArrayList < ItemTableEntry >> _itemTables = new HashMap <> ();
2023-08-07 08:49:43 -04:00
public static HashMap < Integer , ArrayList < ModTableEntry >> _modTables = new HashMap <> ();
2023-08-07 08:58:44 -04:00
public static HashMap < Integer , ArrayList < ModTypeTableEntry >> _modTypeTables = new HashMap <> ();
2023-08-06 17:44:30 -04:00
2024-07-04 19:49:24 -05:00
public static final ArrayList < Integer > vorg_ha_uuids = new ArrayList <> ( Arrays . asList ( 27580 , 27590 , 188500 , 188510 , 188520 , 188530 , 188540 , 188550 , 189510 ));
public static final ArrayList < Integer > vorg_ma_uuids = new ArrayList <> ( Arrays . asList ( 27570 , 188900 , 188910 , 188920 , 188930 , 188940 , 188950 , 189500 ));
public static final ArrayList < Integer > vorg_la_uuids = new ArrayList <> ( Arrays . asList ( 27550 , 27560 , 189100 , 189110 , 189120 , 189130 , 189140 , 189150 ));
public static final ArrayList < Integer > vorg_cloth_uuids = new ArrayList <> ( Arrays . asList ( 27600 , 188700 , 188720 , 189550 , 189560 ));
2023-08-03 09:04:20 -04:00
// Drop Rates
public static float NORMAL_DROP_RATE ;
public static float NORMAL_EXP_RATE ;
public static float NORMAL_GOLD_RATE ;
public static float HOTZONE_DROP_RATE ;
public static float HOTZONE_EXP_RATE ;
public static float HOTZONE_GOLD_RATE ;
2023-08-08 18:30:21 -04:00
public static HashMap < Integer , ArrayList < BootySetEntry >> _bootySetMap = new HashMap <> ();
2023-08-03 09:04:20 -04:00
// Bootstrap routine to initialize the Loot Manager
public static void init () {
2022-04-30 09:41:17 -04:00
2023-08-03 15:20:31 -04:00
// Load loot tables from database.
2023-08-07 08:22:37 -04:00
_genTables = DbManager . LootQueries . LOAD_GEN_ITEM_TABLES ();
2023-08-07 08:39:08 -04:00
_itemTables = DbManager . LootQueries . LOAD_ITEM_TABLES ();
2023-08-07 08:49:43 -04:00
_modTables = DbManager . LootQueries . LOAD_MOD_TABLES ();
2023-08-07 08:58:44 -04:00
_modTypeTables = DbManager . LootQueries . LOAD_MOD_TYPE_TABLES ();
2023-08-03 15:20:31 -04:00
// Cache drop rate values from Config manager.
2023-08-03 09:04:20 -04:00
NORMAL_DROP_RATE = Float . parseFloat ( ConfigManager . MB_NORMAL_DROP_RATE . getValue ());
NORMAL_EXP_RATE = Float . parseFloat ( ConfigManager . MB_NORMAL_EXP_RATE . getValue ());
NORMAL_GOLD_RATE = Float . parseFloat ( ConfigManager . MB_NORMAL_GOLD_RATE . getValue ());
HOTZONE_DROP_RATE = Float . parseFloat ( ConfigManager . MB_HOTZONE_DROP_RATE . getValue ());
HOTZONE_EXP_RATE = Float . parseFloat ( ConfigManager . MB_HOTZONE_EXP_RATE . getValue ());
HOTZONE_GOLD_RATE = Float . parseFloat ( ConfigManager . MB_HOTZONE_GOLD_RATE . getValue ());
2022-04-30 09:41:17 -04:00
}
2023-07-15 09:23:48 -04:00
2023-08-21 19:36:46 -05:00
public static void GenerateMobLoot ( Mob mob ) {
2023-04-06 20:07:24 -05:00
//determine if mob is in hotzone
2024-06-15 16:51:46 -05:00
boolean inHotzone = false ;
2023-08-03 09:04:20 -04:00
2023-04-06 20:07:24 -05:00
//iterate the booty sets
2023-08-03 09:04:20 -04:00
2024-07-18 19:42:23 -05:00
if ( mob . mobBase == null || mob . getMobBaseID () == 253003 ){
int i = 0 ;
}
if ( mob . getMobBase (). bootySet != 0 && _bootySetMap . containsKey ( mob . getMobBase (). bootySet ))
2023-08-21 19:36:46 -05:00
RunBootySet ( _bootySetMap . get ( mob . getMobBase (). bootySet ), mob , inHotzone );
2023-08-03 09:04:20 -04:00
2024-07-18 19:11:27 -05:00
if ( mob . bootySet != 0 && _bootySetMap . containsKey ( mob . bootySet )) {
2023-08-21 19:36:46 -05:00
RunBootySet ( _bootySetMap . get ( mob . bootySet ), mob , inHotzone );
2024-07-18 19:11:27 -05:00
} else if ( mob . bootySet != 0 && ItemBase . getItemBase ( mob . bootySet ) != null ){
MobLoot specialDrop = null ;
2024-07-18 19:42:23 -05:00
specialDrop = new MobLoot ( mob , ItemBase . getItemBase ( mob . bootySet ), true );
2024-07-18 19:11:27 -05:00
if ( specialDrop != null ) {
ChatSystemMsg chatMsg = new ChatSystemMsg ( null , mob . getName () + " in " + mob . getParentZone (). getName () + " has found the " + specialDrop . getName () + ". Are you tough enough to take it?" );
chatMsg . setMessageType ( 10 );
chatMsg . setChannel ( Enum . ChatChannelType . SYSTEM . getChannelID ());
DispatchMessage . dispatchMsgToAll ( chatMsg );
mob . getCharItemManager (). addItemToInventory ( specialDrop );
mob . setResists ( new Resists ( "Dropper" ));
2024-07-18 19:42:23 -05:00
if ( ! Mob . discDroppers . contains ( mob ))
Mob . AddDiscDropper ( mob );
2024-07-18 19:11:27 -05:00
}
2024-07-18 19:42:23 -05:00
2024-07-18 19:11:27 -05:00
}
2023-08-03 09:04:20 -04:00
2023-04-07 12:22:33 -05:00
//lastly, check mobs inventory for godly or disc runes to send a server announcement
2024-06-15 16:54:20 -05:00
for ( Item it : mob . getInventory ()) {
2023-08-03 09:04:20 -04:00
2024-06-15 16:54:20 -05:00
ItemBase ib = it . getItemBase ();
if ( ib == null )
break ;
if ( ib . isDiscRune () || ib . getName (). toLowerCase (). contains ( "of the gods" )) {
ChatSystemMsg chatMsg = new ChatSystemMsg ( null , mob . getName () + " in " + mob . getParentZone (). getName () + " has found the " + ib . getName () + ". Are you tough enough to take it?" );
chatMsg . setMessageType ( 10 );
chatMsg . setChannel ( Enum . ChatChannelType . SYSTEM . getChannelID ());
DispatchMessage . dispatchMsgToAll ( chatMsg );
2023-04-06 20:07:24 -05:00
}
2024-06-15 16:54:20 -05:00
}
2023-08-04 13:25:13 -04:00
2023-04-07 12:22:33 -05:00
}
2023-08-03 09:04:20 -04:00
2023-08-21 19:36:46 -05:00
private static void RunBootySet ( ArrayList < BootySetEntry > entries , Mob mob , boolean inHotzone ) {
2023-08-03 09:04:20 -04:00
2023-08-04 12:21:22 -04:00
boolean hotzoneWasRan = false ;
2024-06-15 16:54:20 -05:00
float dropRate ;
2023-08-04 12:21:22 -04:00
2024-08-26 21:10:25 -05:00
if ( ! mob . getSafeZone ()) {
2024-08-31 16:26:08 -05:00
int specialCaseRoll = ThreadLocalRandom . current (). nextInt ( 1 , 100000 );
//Special Case Contract Drop
if ( specialCaseRoll < 100 ){
SpecialCaseResourceDrop ( mob , entries );
} else if ( specialCaseRoll > 100 && specialCaseRoll < 500 ){
SpecialCaseContractDrop ( mob , entries );
} else if ( specialCaseRoll > 500 && specialCaseRoll < 900 ){
SpecialCaseRuneDrop ( mob , entries );
} else if ( specialCaseRoll > 900 && specialCaseRoll < 910 ){
2024-08-26 21:10:25 -05:00
int glassID = rollRandomItem ( 126 );
ItemBase glassItem = ItemBase . getItemBase ( glassID );
if ( glassItem != null ) {
MobLoot toAddGlass = new MobLoot ( mob , glassItem , false );
if ( toAddGlass != null )
mob . getCharItemManager (). addItemToInventory ( toAddGlass );
}
2024-06-15 16:51:46 -05:00
}
}
2024-07-05 19:28:05 -05:00
2023-08-04 14:01:12 -04:00
// Iterate all entries in this bootySet and process accordingly
2023-08-04 12:21:22 -04:00
for ( BootySetEntry bse : entries ) {
switch ( bse . bootyType ) {
case "GOLD" :
GenerateGoldDrop ( mob , bse , inHotzone );
break ;
case "LOOT" :
2024-06-15 16:51:46 -05:00
if ( mob . getSafeZone ())
return ; // no loot to drop in safezones
dropRate = LootManager . NORMAL_DROP_RATE ;
2023-08-18 12:00:28 -04:00
2023-08-05 19:23:58 -04:00
if ( inHotzone == true )
dropRate = LootManager . HOTZONE_DROP_RATE ;
if ( ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 ) < ( bse . dropChance * dropRate ))
2023-08-06 07:53:33 -04:00
GenerateLootDrop ( mob , bse . genTable , false ); //generate normal loot drop
2023-08-03 09:04:20 -04:00
2023-08-04 12:21:22 -04:00
// Generate hotzone loot if in hotzone
2023-08-04 13:25:13 -04:00
// Only one bite at the hotzone apple per bootyset.
2023-08-04 12:21:22 -04:00
if ( inHotzone == true && hotzoneWasRan == false )
2023-08-07 10:16:30 -04:00
if ( _genTables . containsKey ( bse . genTable + 1 ) && ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 ) < ( bse . dropChance * dropRate )) {
2023-08-06 07:53:33 -04:00
GenerateLootDrop ( mob , bse . genTable + 1 , true ); //generate loot drop from hotzone table
2023-08-04 12:21:22 -04:00
hotzoneWasRan = true ;
}
break ;
case "ITEM" :
2023-08-04 13:16:44 -04:00
GenerateInventoryDrop ( mob , bse );
2023-08-04 12:21:22 -04:00
break ;
2023-07-30 19:52:11 -05:00
}
2023-07-31 21:28:41 -05:00
}
2023-07-31 19:20:41 -05:00
}
2023-08-03 09:04:20 -04:00
2024-08-26 21:29:41 -05:00
public static void SpecialCaseContractDrop ( Mob mob , ArrayList < BootySetEntry > entries ){
int lootTableID = 0 ;
for ( BootySetEntry entry : entries ){
if ( entry . bootyType . equals ( "LOOT" )){
lootTableID = entry . genTable ;
break ;
}
}
if ( lootTableID == 0 )
return ;
int ContractTableID = 0 ;
for ( GenTableEntry entry : _genTables . get ( lootTableID )){
2024-08-27 19:30:02 -05:00
try {
if ( ItemBase . getItemBase ( _itemTables . get ( entry . itemTableID ). get ( 0 ). cacheID ). getType (). equals ( Enum . ItemType . CONTRACT )) {
ContractTableID = entry . itemTableID ;
break ;
}
} catch ( Exception e ){
2024-08-26 21:29:41 -05:00
}
}
if ( ContractTableID == 0 )
return ;
ItemBase ib = ItemBase . getItemBase ( rollRandomItem ( ContractTableID ));
if ( ib != null ){
MobLoot toAdd = new MobLoot ( mob , ib , false );
mob . getCharItemManager (). addItemToInventory ( toAdd );
}
}
public static void SpecialCaseRuneDrop ( Mob mob , ArrayList < BootySetEntry > entries ){
int lootTableID = 0 ;
for ( BootySetEntry entry : entries ){
if ( entry . bootyType . equals ( "LOOT" )){
lootTableID = entry . genTable ;
break ;
}
}
if ( lootTableID == 0 )
return ;
int RuneTableID = 0 ;
for ( GenTableEntry entry : _genTables . get ( lootTableID )){
2024-08-27 19:30:02 -05:00
try {
if ( ItemBase . getItemBase ( _itemTables . get ( entry . itemTableID ). get ( 0 ). cacheID ). getType (). equals ( Enum . ItemType . RUNE )) {
RuneTableID = entry . itemTableID ;
break ;
}
} catch ( Exception e ){
2024-08-26 21:29:41 -05:00
}
}
if ( RuneTableID == 0 )
return ;
ItemBase ib = ItemBase . getItemBase ( rollRandomItem ( RuneTableID ));
if ( ib != null ){
MobLoot toAdd = new MobLoot ( mob , ib , false );
mob . getCharItemManager (). addItemToInventory ( toAdd );
}
}
public static void SpecialCaseResourceDrop ( Mob mob , ArrayList < BootySetEntry > entries ){
int lootTableID = 0 ;
for ( BootySetEntry entry : entries ){
if ( entry . bootyType . equals ( "LOOT" )){
lootTableID = entry . genTable ;
break ;
}
}
if ( lootTableID == 0 )
return ;
int ResourceTableID = 0 ;
for ( GenTableEntry entry : _genTables . get ( lootTableID )){
2024-08-27 19:30:02 -05:00
try {
if ( ItemBase . getItemBase ( _itemTables . get ( entry . itemTableID ). get ( 0 ). cacheID ). getType (). equals ( Enum . ItemType . RESOURCE )) {
ResourceTableID = entry . itemTableID ;
break ;
}
} catch ( Exception e ){
2024-08-26 21:29:41 -05:00
}
}
if ( ResourceTableID == 0 )
return ;
ItemBase ib = ItemBase . getItemBase ( rollRandomItem ( ResourceTableID ));
if ( ib != null ){
MobLoot toAdd = new MobLoot ( mob , ib , false );
mob . getCharItemManager (). addItemToInventory ( toAdd );
}
}
2023-08-08 19:32:39 -05:00
public static MobLoot getGenTableItem ( int genTableID , AbstractCharacter mob , Boolean inHotzone ) {
2023-08-03 09:04:20 -04:00
2023-08-07 10:16:30 -04:00
if ( mob == null || _genTables . containsKey ( genTableID ) == false )
2023-08-03 09:04:20 -04:00
return null ;
MobLoot outItem ;
2023-08-08 20:37:31 -05:00
int genRoll = ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 );
2023-08-03 19:18:05 -05:00
2023-08-16 08:29:29 -04:00
GenTableEntry selectedRow = GenTableEntry . rollTable ( genTableID , genRoll , 1 . 0f );
2023-08-04 13:25:13 -04:00
2023-08-03 09:04:20 -04:00
if ( selectedRow == null )
return null ;
int itemTableId = selectedRow . itemTableID ;
2023-08-07 10:16:30 -04:00
if ( _itemTables . containsKey ( itemTableId ) == false )
2023-08-03 19:18:05 -05:00
return null ;
2023-08-03 09:04:20 -04:00
//gets the 1-320 roll for this mob
2023-08-08 20:37:31 -05:00
int itemTableRoll = 0 ;
if ( mob . getObjectType (). ordinal () == 52 ) { //52 = player character
itemTableRoll = ThreadLocalRandom . current (). nextInt ( 1 , 320 + 1 );
} else {
itemTableRoll = TableRoll ( mob . level , inHotzone );
}
2023-08-07 10:16:30 -04:00
ItemTableEntry tableRow = ItemTableEntry . rollTable ( itemTableId , itemTableRoll );
2023-08-03 09:04:20 -04:00
if ( tableRow == null )
return null ;
int itemUUID = tableRow . cacheID ;
if ( itemUUID == 0 )
return null ;
if ( ItemBase . getItemBase ( itemUUID ). getType (). ordinal () == Enum . ItemType . RESOURCE . ordinal ()) {
2024-06-15 20:03:09 -05:00
if ( ThreadLocalRandom . current (). nextInt ( 1 , 101 ) < 91 )
return null ; // cut down world drops rates of resources by 90%
2023-08-08 15:43:24 -05:00
int amount = ThreadLocalRandom . current (). nextInt ( tableRow . minSpawn , tableRow . maxSpawn + 1 );
2023-08-03 09:04:20 -04:00
return new MobLoot ( mob , ItemBase . getItemBase ( itemUUID ), amount , false );
}
2024-06-15 20:03:09 -05:00
if ( ItemBase . getItemBase ( itemUUID ). getType (). equals ( Enum . ItemType . RUNE )){
2024-06-15 19:44:37 -05:00
int randomRune = rollRandomItem ( itemTableId );
2024-06-15 19:36:13 -05:00
if ( randomRune != 0 ) {
itemUUID = randomRune ;
}
} else if ( ItemBase . getItemBase ( itemUUID ). getType (). equals ( Enum . ItemType . CONTRACT )){
2024-06-15 19:44:37 -05:00
int randomContract = rollRandomItem ( itemTableId );
2024-06-15 19:36:13 -05:00
if ( randomContract != 0 ) {
itemUUID = randomContract ;
}
}
2023-08-03 09:04:20 -04:00
outItem = new MobLoot ( mob , ItemBase . getItemBase ( itemUUID ), false );
2023-08-04 13:25:13 -04:00
2023-08-08 19:32:39 -05:00
if ( selectedRow . pModTable != 0 ){
try {
outItem = GeneratePrefix ( mob , outItem , genTableID , genRoll , inHotzone );
outItem . setIsID ( false );
} catch ( Exception e ) {
Logger . error ( "Failed to GeneratePrefix for item: " + outItem . getName ());
}
}
if ( selectedRow . sModTable != 0 ){
try {
outItem = GenerateSuffix ( mob , outItem , genTableID , genRoll , inHotzone );
outItem . setIsID ( false );
} catch ( Exception e ) {
Logger . error ( "Failed to GenerateSuffix for item: " + outItem . getName ());
2023-07-15 09:23:48 -04:00
}
2023-08-03 09:04:20 -04:00
}
2024-06-15 16:51:46 -05:00
if ( outItem . getItemBase (). getType (). equals ( Enum . ItemType . CONTRACT ) || outItem . getItemBase (). getType (). equals ( Enum . ItemType . RUNE )){
2024-06-15 20:03:09 -05:00
if ( ThreadLocalRandom . current (). nextInt ( 1 , 101 ) < 66 )
return null ; // cut down world drops rates of resources by 65%
2024-06-15 16:51:46 -05:00
}
2023-08-03 09:04:20 -04:00
return outItem ;
2023-04-06 20:07:24 -05:00
}
2023-08-03 09:04:20 -04:00
2023-08-08 19:32:39 -05:00
private static MobLoot GeneratePrefix ( AbstractCharacter mob , MobLoot inItem , int genTableID , int genRoll , Boolean inHotzone ) {
2023-08-03 09:04:20 -04:00
2023-08-16 08:29:29 -04:00
GenTableEntry selectedRow = GenTableEntry . rollTable ( genTableID , genRoll , 1 . 0f );
2023-08-04 13:25:13 -04:00
2023-08-05 19:28:53 -04:00
if ( selectedRow == null )
return inItem ;
2023-08-03 19:18:05 -05:00
2023-08-07 10:16:30 -04:00
int prefixroll = ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 );
ModTypeTableEntry prefixTable = ModTypeTableEntry . rollTable ( selectedRow . pModTable , prefixroll );
2023-08-04 13:25:13 -04:00
2023-08-05 19:28:53 -04:00
if ( prefixTable == null )
return inItem ;
2023-08-08 20:37:31 -05:00
int prefixTableRoll = 0 ;
if ( mob . getObjectType (). ordinal () == 52 ) {
prefixTableRoll = ThreadLocalRandom . current (). nextInt ( 1 , 320 + 1 );
} else {
prefixTableRoll = TableRoll ( mob . level , inHotzone );
}
ModTableEntry prefixMod = ModTableEntry . rollTable ( prefixTable . modTableID , prefixTableRoll );
2023-08-03 09:04:20 -04:00
2023-08-07 10:16:30 -04:00
if ( prefixMod == null )
return inItem ;
2023-08-04 13:25:13 -04:00
2023-08-07 10:16:30 -04:00
if ( prefixMod . action . length () > 0 ) {
inItem . setPrefix ( prefixMod . action );
inItem . addPermanentEnchantment ( prefixMod . action , 0 , prefixMod . level , true );
2023-08-05 19:28:53 -04:00
}
2023-08-07 10:16:30 -04:00
2023-08-02 19:45:18 -05:00
return inItem ;
}
2023-08-03 09:04:20 -04:00
2023-08-08 19:32:39 -05:00
private static MobLoot GenerateSuffix ( AbstractCharacter mob , MobLoot inItem , int genTableID , int genRoll , Boolean inHotzone ) {
2023-08-03 09:04:20 -04:00
2023-08-16 08:29:29 -04:00
GenTableEntry selectedRow = GenTableEntry . rollTable ( genTableID , genRoll , 1 . 0f );
2023-08-04 13:25:13 -04:00
2023-08-05 19:28:53 -04:00
if ( selectedRow == null )
return inItem ;
2023-08-03 19:18:05 -05:00
2023-08-07 10:16:30 -04:00
int suffixRoll = ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 );
2023-08-03 19:18:05 -05:00
2023-08-07 10:16:30 -04:00
ModTypeTableEntry suffixTable = ModTypeTableEntry . rollTable ( selectedRow . sModTable , suffixRoll );
2023-08-04 13:25:13 -04:00
2023-08-05 19:28:53 -04:00
if ( suffixTable == null )
return inItem ;
2023-08-08 20:37:31 -05:00
int suffixTableRoll = 0 ;
if ( mob . getObjectType (). ordinal () == 52 ) {
suffixTableRoll = ThreadLocalRandom . current (). nextInt ( 1 , 320 + 1 );
} else {
suffixTableRoll = TableRoll ( mob . level , inHotzone );
}
ModTableEntry suffixMod = ModTableEntry . rollTable ( suffixTable . modTableID , suffixTableRoll );
2023-08-05 19:28:53 -04:00
2023-08-07 10:16:30 -04:00
if ( suffixMod == null )
return inItem ;
2023-08-05 19:28:53 -04:00
2023-08-07 10:16:30 -04:00
if ( suffixMod . action . length () > 0 ) {
2023-08-09 07:39:10 -04:00
inItem . setSuffix ( suffixMod . action );
2023-08-17 17:53:31 -04:00
inItem . addPermanentEnchantment ( suffixMod . action , 0 , suffixMod . level , false );
2023-08-05 19:28:53 -04:00
}
2023-08-07 10:16:30 -04:00
2023-08-02 19:45:18 -05:00
return inItem ;
}
2023-08-03 09:04:20 -04:00
2023-08-07 13:53:16 -04:00
public static int TableRoll ( int mobLevel , Boolean inHotzone ) {
2023-08-03 09:04:20 -04:00
if ( mobLevel > 65 )
2023-07-30 13:55:08 -05:00
mobLevel = 65 ;
2023-08-03 09:04:20 -04:00
int max = ( int ) ( 4 . 882 * mobLevel + 127 . 0 );
if ( max > 319 )
max = 319 ;
2023-08-04 13:25:13 -04:00
int min = ( int ) ( 4 . 469 * mobLevel - 3 . 469 );
if ( min < 70 )
2023-08-03 21:07:07 -05:00
min = 70 ;
2023-08-04 13:25:13 -04:00
if ( inHotzone )
2023-08-03 19:21:35 -05:00
min += mobLevel ;
2023-08-03 19:18:05 -05:00
2023-08-08 15:43:24 -05:00
int roll = ThreadLocalRandom . current (). nextInt ( min , max + 1 );
2023-08-03 09:04:20 -04:00
2023-07-17 22:25:54 -05:00
return roll ;
}
2023-08-03 09:04:20 -04:00
public static void GenerateGoldDrop ( Mob mob , BootySetEntry bse , Boolean inHotzone ) {
2023-08-05 09:39:16 -04:00
int chanceRoll = ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 );
2023-08-03 09:04:20 -04:00
2023-08-03 19:18:05 -05:00
//early exit, failed to hit minimum chance roll
2023-08-03 09:04:20 -04:00
if ( chanceRoll > bse . dropChance )
2023-07-30 11:43:26 -05:00
return ;
2023-08-03 09:04:20 -04:00
2023-07-30 11:43:26 -05:00
//determine and add gold to mob inventory
2023-08-03 09:04:20 -04:00
2023-08-02 19:45:18 -05:00
int high = bse . highGold ;
int low = bse . lowGold ;
2024-07-04 19:49:24 -05:00
int gold = ( int ) ( ThreadLocalRandom . current (). nextInt ( low , high + 1 ) * NORMAL_GOLD_RATE );
2023-08-03 09:04:20 -04:00
2023-07-30 11:43:26 -05:00
if ( gold > 0 ) {
2023-08-02 19:45:18 -05:00
MobLoot goldAmount = new MobLoot ( mob , gold );
2023-07-30 11:43:26 -05:00
mob . getCharItemManager (). addItemToInventory ( goldAmount );
}
2023-08-03 09:04:20 -04:00
2023-07-30 11:43:26 -05:00
}
2023-08-03 09:04:20 -04:00
2023-08-04 14:01:12 -04:00
public static void GenerateLootDrop ( Mob mob , int tableID , Boolean inHotzone ) {
2023-08-03 09:04:20 -04:00
2024-07-04 19:49:24 -05:00
MobLoot toAdd = getGenTableItem ( tableID , mob , inHotzone );
2024-08-26 21:10:25 -05:00
if ( toAdd != null ){
2024-08-26 21:29:41 -05:00
ItemBase ib = toAdd . getItemBase ();
switch ( ib . getType ()){
case CONTRACT :
case RUNE :
case RESOURCE :
return ;
}
2024-07-04 19:49:24 -05:00
toAdd . setIsID ( true );
mob . getCharItemManager (). addItemToInventory ( toAdd );
2023-07-30 13:55:08 -05:00
}
2023-07-30 11:43:26 -05:00
}
2023-08-03 09:04:20 -04:00
2024-07-04 19:49:24 -05:00
2023-08-04 13:04:57 -04:00
public static void GenerateEquipmentDrop ( Mob mob ) {
2023-08-03 09:04:20 -04:00
2024-06-15 16:51:46 -05:00
if ( mob == null || mob . getSafeZone ())
return ; // no equipment to drop in safezones
2024-07-15 20:05:36 -05:00
if ( mob . StrongholdGuardian || mob . StrongholdCommander || mob . StrongholdEpic )
return ; // stronghold mobs don't drop equipment
2023-07-30 11:43:26 -05:00
//do equipment here
2024-07-04 19:49:24 -05:00
if ( mob . getEquip () != null ) {
boolean isVorg = false ;
2023-07-30 11:43:26 -05:00
for ( MobEquipment me : mob . getEquip (). values ()) {
2023-08-03 09:04:20 -04:00
2023-07-30 11:43:26 -05:00
if ( me . getDropChance () == 0 )
continue ;
2023-08-03 09:04:20 -04:00
2024-07-04 19:49:24 -05:00
String name = me . getItemBase (). getName (). toLowerCase ();
if ( name . contains ( "vorgrim legionnaire's" ) || name . contains ( "vorgrim auxiliary's" ) || name . contains ( "bellugh nuathal" ) || name . contains ( "crimson circle" ))
isVorg = true ;
2023-08-05 09:39:16 -04:00
float equipmentRoll = ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 );
2023-07-30 11:43:26 -05:00
float dropChance = me . getDropChance () * 100 ;
2024-07-04 19:49:24 -05:00
ItemBase itemBase = me . getItemBase ();
if ( isVorg ) {
mob . spawnTime = ThreadLocalRandom . current (). nextInt ( 300 , 2700 );
dropChance = 10 ;
itemBase = getRandomVorg ( itemBase );
}
2023-08-04 13:04:57 -04:00
if ( equipmentRoll > dropChance )
2023-08-03 19:18:05 -05:00
continue ;
2023-08-04 13:04:57 -04:00
2024-07-04 19:49:24 -05:00
MobLoot ml = new MobLoot ( mob , itemBase , false );
2023-08-04 13:09:09 -04:00
2024-07-04 19:49:24 -05:00
ml . setIsID ( true );
ml . setDurabilityCurrent (( short ) ( ml . getDurabilityCurrent () - ThreadLocalRandom . current (). nextInt ( 5 ) + 1 ));
mob . getCharItemManager (). addItemToInventory ( ml );
2023-07-30 11:43:26 -05:00
}
2024-07-04 19:49:24 -05:00
}
2023-07-30 11:43:26 -05:00
}
2023-08-03 09:04:20 -04:00
2023-08-04 13:16:44 -04:00
public static void GenerateInventoryDrop ( Mob mob , BootySetEntry bse ) {
2023-08-03 09:04:20 -04:00
2023-08-05 09:39:16 -04:00
int chanceRoll = ThreadLocalRandom . current (). nextInt ( 1 , 100 + 1 );
2023-08-03 09:04:20 -04:00
//early exit, failed to hit minimum chance roll
2023-08-04 13:16:44 -04:00
if ( chanceRoll > bse . dropChance )
2023-07-30 15:57:01 -05:00
return ;
2023-08-03 09:04:20 -04:00
2023-08-03 19:18:05 -05:00
MobLoot lootItem = new MobLoot ( mob , ItemBase . getItemBase ( bse . itemBase ), true );
2023-08-03 09:04:20 -04:00
2024-07-04 19:14:00 -05:00
if ( lootItem != null ) {
2023-08-03 19:18:05 -05:00
mob . getCharItemManager (). addItemToInventory ( lootItem );
2024-07-04 19:14:00 -05:00
if ( lootItem . getItemBase (). isDiscRune () && ! Mob . discDroppers . contains ( mob ))
2024-07-06 20:43:03 -05:00
Mob . AddDiscDropper ( mob );
2024-07-04 19:14:00 -05:00
}
2023-07-30 11:43:26 -05:00
}
2023-08-09 17:52:39 -04:00
public static void peddleFate ( PlayerCharacter playerCharacter , Item gift ) {
2023-08-09 15:50:56 -05:00
//get table ID for the itembase ID
2023-08-09 17:52:39 -04:00
2023-08-09 15:50:56 -05:00
int tableID = 0 ;
2023-08-09 17:52:39 -04:00
if ( _bootySetMap . get ( gift . getItemBaseID ()) != null )
2023-08-09 15:50:56 -05:00
tableID = _bootySetMap . get ( gift . getItemBaseID ()). get ( ThreadLocalRandom . current (). nextInt ( _bootySetMap . get ( gift . getItemBaseID ()). size ())). genTable ;
2023-08-08 20:37:31 -05:00
2023-08-09 17:52:39 -04:00
if ( tableID == 0 )
2023-08-09 14:48:22 -05:00
return ;
//get the character item manager
2023-08-09 17:52:39 -04:00
CharacterItemManager itemMan = playerCharacter . getCharItemManager ();
if ( itemMan == null )
2023-08-09 14:48:22 -05:00
return ;
//check if player owns the gift he is trying to open
2023-08-09 17:52:39 -04:00
2024-07-04 20:06:15 -05:00
if ( ! itemMan . doesCharOwnThisItem ( gift . getObjectUUID ()))
2023-08-09 14:48:22 -05:00
return ;
//roll 1-100 for the gen table selection
2023-08-09 17:52:39 -04:00
2024-07-08 20:41:16 -05:00
int genRoll = ThreadLocalRandom . current (). nextInt ( 94 , 100 ) + 1 ;
2023-08-16 08:29:29 -04:00
GenTableEntry selectedRow = GenTableEntry . rollTable ( tableID , genRoll , LootManager . NORMAL_DROP_RATE );
2023-08-09 17:52:39 -04:00
2023-08-09 14:48:22 -05:00
if ( selectedRow == null )
2023-08-09 15:50:56 -05:00
return ;
2023-08-09 14:48:22 -05:00
//roll 220-320 for the item table selection
2023-08-09 17:52:39 -04:00
int itemRoll = ThreadLocalRandom . current (). nextInt ( 220 , 320 + 1 );
ItemTableEntry selectedItem = ItemTableEntry . rollTable ( selectedRow . itemTableID , itemRoll );
if ( selectedItem == null )
2023-08-09 14:48:22 -05:00
return ;
//create the item from the table, quantity is always 1
2023-08-09 17:52:39 -04:00
2024-07-04 20:06:15 -05:00
ItemBase ib = ItemBase . getItemBase ( selectedItem . cacheID );
if ( ib . getUUID () == Warehouse . coalIB . getUUID ()){
//no more coal, give gold instead
if ( itemMan . getGoldInventory (). getNumOfItems () + 250000 > 10000000 ) {
ErrorPopupMsg . sendErrorPopup ( playerCharacter , 21 );
return ;
}
itemMan . addGoldToInventory ( 250000 , false );
itemMan . updateInventory ();
} else {
MobLoot winnings = new MobLoot ( playerCharacter , ib , 1 , false );
2023-08-09 17:52:39 -04:00
2024-07-04 20:06:15 -05:00
if ( winnings == null )
return ;
2023-08-09 14:48:22 -05:00
2024-07-04 20:06:15 -05:00
//early exit if the inventory of the player will not hold the item
2023-08-09 17:52:39 -04:00
2024-07-04 20:06:15 -05:00
if ( itemMan . hasRoomInventory ( winnings . getItemBase (). getWeight ()) == false ) {
ErrorPopupMsg . sendErrorPopup ( playerCharacter , 21 );
return ;
}
//determine if the winning item needs a prefix
if ( selectedRow . pModTable != 0 ) {
int prefixRoll = ThreadLocalRandom . current (). nextInt ( 220 , 320 + 1 );
ModTableEntry prefix = ModTableEntry . rollTable ( selectedRow . pModTable , prefixRoll );
if ( prefix != null )
winnings . addPermanentEnchantment ( prefix . action , 0 , prefix . level , true );
}
//determine if the winning item needs a suffix
if ( selectedRow . sModTable != 0 ) {
int suffixRoll = ThreadLocalRandom . current (). nextInt ( 220 , 320 + 1 );
ModTableEntry suffix = ModTableEntry . rollTable ( selectedRow . sModTable , suffixRoll );
if ( suffix != null )
winnings . addPermanentEnchantment ( suffix . action , 0 , suffix . level , true );
}
winnings . setIsID ( true );
//remove gift from inventory
itemMan . consume ( gift );
//add winnings to player inventory
Item playerWinnings = winnings . promoteToItem ( playerCharacter );
itemMan . addItemToInventory ( playerWinnings );
itemMan . updateInventory ();
2023-08-09 15:50:56 -05:00
}
2023-08-08 19:32:39 -05:00
}
2024-06-15 16:51:46 -05:00
2024-06-15 19:44:37 -05:00
public static int rollRandomItem ( int itemTable ){
2024-06-15 19:54:45 -05:00
int returnedID = ItemTableEntry . getRandomItem ( itemTable );
return returnedID ;
2024-06-15 16:51:46 -05:00
}
2024-07-04 19:49:24 -05:00
public static ItemBase getRandomVorg ( ItemBase itemBase ){
int roll = 0 ;
if ( vorg_ha_uuids . contains ( itemBase . getUUID ())) {
roll = ThreadLocalRandom . current (). nextInt ( 0 , 10 );
switch ( roll ) {
case 1 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 0 ));
case 2 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 1 ));
case 3 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 2 ));
case 4 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 3 ));
case 5 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 4 ));
case 6 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 5 ));
case 7 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 6 ));
case 8 :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 7 ));
default :
return ItemBase . getItemBase ( vorg_ha_uuids . get ( 8 ));
}
}
if ( vorg_ma_uuids . contains ( itemBase . getUUID ())) {
roll = ThreadLocalRandom . current (). nextInt ( 0 , 10 );
switch ( roll ) {
case 1 :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 0 ));
case 2 :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 1 ));
case 3 :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 2 ));
case 4 :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 3 ));
case 5 :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 4 ));
case 6 :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 5 ));
case 7 :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 6 ));
default :
return ItemBase . getItemBase ( vorg_ma_uuids . get ( 7 ));
}
}
if ( vorg_la_uuids . contains ( itemBase . getUUID ())) {
roll = ThreadLocalRandom . current (). nextInt ( 0 , 10 );
switch ( roll ) {
case 1 :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 0 ));
case 2 :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 1 ));
case 3 :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 2 ));
case 4 :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 3 ));
case 5 :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 4 ));
case 6 :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 5 ));
case 7 :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 6 ));
default :
return ItemBase . getItemBase ( vorg_la_uuids . get ( 7 ));
}
}
if ( vorg_cloth_uuids . contains ( itemBase . getUUID ())) {
roll = ThreadLocalRandom . current (). nextInt ( 0 , 10 );
switch ( roll ) {
case 1 :
return ItemBase . getItemBase ( vorg_cloth_uuids . get ( 0 ));
case 2 :
return ItemBase . getItemBase ( vorg_cloth_uuids . get ( 1 ));
case 3 :
return ItemBase . getItemBase ( vorg_cloth_uuids . get ( 2 ));
case 4 :
return ItemBase . getItemBase ( vorg_cloth_uuids . get ( 3 ));
default :
return ItemBase . getItemBase ( vorg_cloth_uuids . get ( 4 ));
}
}
return null ;
}
2024-07-04 20:06:15 -05:00
public static void DropPresent ( Mob mob ){
2024-07-08 20:41:16 -05:00
int random = 971049 + ThreadLocalRandom . current (). nextInt ( 24 );
if ( random > 971071 )
random = 971071 ;
2024-07-04 20:06:15 -05:00
2024-07-08 21:58:17 -05:00
ItemBase present = ItemBase . getItemBase ( random );
if ( present != null ) {
MobLoot toAdd = new MobLoot ( mob , present , true );
2024-07-08 20:41:16 -05:00
if ( toAdd != null )
mob . getCharItemManager (). addItemToInventory ( toAdd );
}
2024-07-04 20:06:15 -05:00
}
2024-07-07 20:44:24 -05:00
2024-07-09 19:47:14 -05:00
public static void GenerateStrongholdLoot ( Mob mob , boolean commander , boolean epic ) {
2024-07-07 20:44:24 -05:00
mob . getCharItemManager (). clearInventory ();
int multiplier = 1 ;
2024-07-07 21:14:09 -05:00
if ( commander )
2024-07-07 20:44:24 -05:00
multiplier = 2 ;
2024-07-09 19:47:14 -05:00
if ( epic )
multiplier = 10 ;
2024-07-07 20:44:24 -05:00
2024-07-09 19:25:02 -05:00
int high = 125000 ;
int low = 50000 ;
2024-07-07 20:44:24 -05:00
int gold = ThreadLocalRandom . current (). nextInt ( low , high + 1 ) * multiplier ;
if ( gold > 0 ) {
MobLoot goldAmount = new MobLoot ( mob , gold );
mob . getCharItemManager (). addItemToInventory ( goldAmount );
}
2024-07-09 19:25:02 -05:00
//present drop chance for all
2024-07-08 22:08:50 -05:00
if ( ThreadLocalRandom . current (). nextInt ( 100 ) < 35 )
2024-07-08 20:41:16 -05:00
DropPresent ( mob );
2024-07-07 20:44:24 -05:00
2024-07-09 19:25:02 -05:00
//random contract drop chance for all
2024-07-15 19:13:40 -05:00
if ( ThreadLocalRandom . current (). nextInt ( 100 ) < 40 ) {
2024-07-09 19:25:02 -05:00
int contractTableID = 250 ;
2024-08-24 20:13:11 -05:00
contractTableID += ThreadLocalRandom . current (). nextInt ( 0 , 11 );
2024-07-09 19:25:02 -05:00
if ( contractTableID > 259 )
contractTableID = 659 ;
int id = rollRandomItem ( contractTableID );
ItemBase ib = ItemBase . getItemBase ( id );
if ( ib != null ) {
MobLoot contract = new MobLoot ( mob , ib , true );
if ( contract != null )
mob . getCharItemManager (). addItemToInventory ( contract );
}
}
//special commander drop chances
2024-07-09 19:47:14 -05:00
if ( commander )
2024-08-24 20:13:11 -05:00
GenerateCommanderLoot ( mob , false );
2024-07-07 20:44:24 -05:00
2024-07-09 19:47:14 -05:00
//special epic drop chances
if ( epic ) {
2024-08-24 20:13:11 -05:00
GenerateCommanderLoot ( mob , true );
GenerateCommanderLoot ( mob , false );
2024-07-09 19:47:14 -05:00
}
}
2024-07-09 19:25:02 -05:00
2024-08-24 20:13:11 -05:00
public static void GenerateCommanderLoot ( Mob mob , boolean epic ){
2024-07-09 19:47:14 -05:00
//present chance
if ( ThreadLocalRandom . current (). nextInt ( 100 ) < 25 )
DropPresent ( mob );
2024-07-08 22:08:50 -05:00
2024-07-09 19:47:14 -05:00
//present chance
if ( ThreadLocalRandom . current (). nextInt ( 100 ) < 25 )
DropPresent ( mob );
2024-07-08 22:08:50 -05:00
2024-07-09 19:47:14 -05:00
//chance for glass
if ( ThreadLocalRandom . current (). nextInt ( 100 ) < 75 ) {
int glassID = rollRandomItem ( 126 );
ItemBase glassItem = ItemBase . getItemBase ( glassID );
if ( glassItem != null ) {
MobLoot toAdd2 = new MobLoot ( mob , glassItem , true );
2024-07-07 21:14:09 -05:00
2024-07-09 19:47:14 -05:00
if ( toAdd2 != null )
mob . getCharItemManager (). addItemToInventory ( toAdd2 );
2024-07-08 20:41:16 -05:00
}
2024-07-09 19:47:14 -05:00
}
2024-07-07 21:26:37 -05:00
2024-07-09 19:47:14 -05:00
//chance for disc
if ( ThreadLocalRandom . current (). nextInt ( 100 ) < 75 ) {
int discID = rollRandomItem ( 3202 );
ItemBase discItem = ItemBase . getItemBase ( discID );
if ( discItem != null ) {
MobLoot toAdd3 = new MobLoot ( mob , discItem , true );
2024-07-07 21:26:37 -05:00
2024-07-09 19:47:14 -05:00
if ( toAdd3 != null )
mob . getCharItemManager (). addItemToInventory ( toAdd3 );
2024-07-08 20:41:16 -05:00
}
2024-07-09 19:47:14 -05:00
}
2024-07-07 21:26:37 -05:00
2024-07-09 19:47:14 -05:00
//chance for stat rune
if ( ThreadLocalRandom . current (). nextInt ( 100 ) < 75 ) {
int runeID = rollRandomItem ( 3201 );
ItemBase runeItem = ItemBase . getItemBase ( runeID );
if ( runeItem != null ) {
MobLoot toAdd4 = new MobLoot ( mob , runeItem , true );
2024-07-07 21:26:37 -05:00
2024-07-09 19:47:14 -05:00
if ( toAdd4 != null )
mob . getCharItemManager (). addItemToInventory ( toAdd4 );
2024-07-07 21:14:09 -05:00
}
}
2024-08-24 20:13:11 -05:00
if ( epic ){
int contractTableID = 250 ;
contractTableID += ThreadLocalRandom . current (). nextInt ( 0 , 11 );
if ( contractTableID > 259 )
contractTableID = 659 ;
int id = rollRandomItem ( contractTableID );
ItemBase ib = ItemBase . getItemBase ( id );
if ( ib != null ) {
MobLoot contract = new MobLoot ( mob , ib , true );
if ( contract != null )
mob . getCharItemManager (). addItemToInventory ( contract );
}
}
2024-07-07 20:44:24 -05:00
}
2023-08-07 10:16:30 -04:00
}