2016-03-24 18:50:31 -04:00
/* EQEMu: Everquest Server Emulator
Copyright ( C ) 2001 - 2016 EQEMu Development Team ( http : //eqemulator.org)
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; version 2 of the License .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY except by those people which sell it , which
are required to give you total support for your newly bought product ;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE . See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2013-02-20 13:54:26 -08:00
# include <iostream>
# include <cstring>
2013-05-21 18:08:21 -07:00
2016-01-01 01:12:49 -06:00
# if defined(_MSC_VER) && _MSC_VER >= 1800
2015-12-30 02:17:09 -05:00
# include <algorithm>
# endif
2013-02-20 13:54:26 -08:00
# include "classes.h"
2013-02-16 16:14:39 -08:00
# include "eq_packet_structs.h"
2013-02-20 13:54:26 -08:00
# include "eqemu_exception.h"
2013-02-23 13:45:19 -08:00
# include "faction.h"
# include "features.h"
2014-12-15 22:42:34 -06:00
# include "ipc_mutex.h"
2016-10-17 02:41:09 -04:00
# include "inventory_profile.h"
2014-12-15 22:42:34 -06:00
# include "loottable.h"
# include "memory_mapped_file.h"
# include "mysql.h"
# include "rulesys.h"
# include "shareddb.h"
# include "string_util.h"
2016-05-24 23:49:25 -07:00
# include "eqemu_config.h"
2013-02-16 16:14:39 -08:00
2016-10-17 01:03:40 -04:00
namespace ItemField
{
enum {
source = 0 ,
# define F(x) x,
# include "item_fieldlist.h"
# undef F
updated
} ;
}
2013-02-16 16:14:39 -08:00
SharedDatabase : : SharedDatabase ( )
2015-06-23 17:39:06 -07:00
: Database ( )
2013-02-16 16:14:39 -08:00
{
}
SharedDatabase : : SharedDatabase ( const char * host , const char * user , const char * passwd , const char * database , uint32 port )
2015-06-23 17:39:06 -07:00
: Database ( host , user , passwd , database , port )
2013-02-16 16:14:39 -08:00
{
}
SharedDatabase : : ~ SharedDatabase ( ) {
}
bool SharedDatabase : : SetHideMe ( uint32 account_id , uint8 hideme )
{
2014-10-04 13:23:52 -07:00
std : : string query = StringFormat ( " UPDATE account SET hideme = %i WHERE id = %i " , hideme , account_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
return true ;
}
uint8 SharedDatabase : : GetGMSpeed ( uint32 account_id )
{
2014-10-04 13:26:45 -07:00
std : : string query = StringFormat ( " SELECT gmspeed FROM account WHERE id = '%i' " , account_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return 0 ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:26:45 -07:00
if ( results . RowCount ( ) ! = 1 )
return 0 ;
2013-05-06 13:07:41 -04:00
2014-10-04 13:26:45 -07:00
auto row = results . begin ( ) ;
2013-02-16 16:14:39 -08:00
2014-10-04 13:26:45 -07:00
return atoi ( row [ 0 ] ) ;
2013-02-16 16:14:39 -08:00
}
bool SharedDatabase : : SetGMSpeed ( uint32 account_id , uint8 gmspeed )
{
2014-10-04 13:27:26 -07:00
std : : string query = StringFormat ( " UPDATE account SET gmspeed = %i WHERE id = %i " , gmspeed , account_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
return true ;
}
uint32 SharedDatabase : : GetTotalTimeEntitledOnAccount ( uint32 AccountID ) {
uint32 EntitledTime = 0 ;
2014-09-06 21:50:29 -05:00
std : : string query = StringFormat ( " SELECT `time_played` FROM `character_data` WHERE `account_id` = %u " , AccountID ) ;
auto results = QueryDatabase ( query ) ;
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
EntitledTime + = atoi ( row [ 0 ] ) ;
2013-02-16 16:14:39 -08:00
}
return EntitledTime ;
}
2016-10-16 05:10:54 -04:00
bool SharedDatabase : : SaveCursor ( uint32 char_id , std : : list < EQEmu : : ItemInstance * > : : const_iterator & start , std : : list < EQEmu : : ItemInstance * > : : const_iterator & end )
2013-02-16 16:14:39 -08:00
{
// Delete cursor items
2014-10-04 13:31:06 -07:00
std : : string query = StringFormat ( " DELETE FROM inventory WHERE charid = %i "
" AND ((slotid >= 8000 AND slotid <= 8999) "
" OR slotid = %i OR (slotid >= %i AND slotid <= %i) ) " ,
2016-10-16 21:36:39 -04:00
char_id , EQEmu : : inventory : : slotCursor ,
2016-04-22 07:34:55 -04:00
EQEmu : : legacy : : CURSOR_BAG_BEGIN , EQEmu : : legacy : : CURSOR_BAG_END ) ;
2014-10-04 13:31:06 -07:00
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
std : : cout < < " Clearing cursor failed: " < < results . ErrorMessage ( ) < < std : : endl ;
return false ;
}
int i = 8000 ;
for ( auto it = start ; it ! = end ; + + it , i + + ) {
2015-01-13 23:48:34 -05:00
if ( i > 8999 ) { break ; } // shouldn't be anything in the queue that indexes this high
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * inst = * it ;
2016-10-16 21:36:39 -04:00
int16 use_slot = ( i = = 8000 ) ? EQEmu : : inventory : : slotCursor : i ;
2015-01-15 21:24:26 -05:00
if ( ! SaveInventory ( char_id , inst , use_slot ) ) {
return false ;
}
2014-10-04 13:31:06 -07:00
}
2013-02-16 16:14:39 -08:00
2014-10-04 13:31:06 -07:00
return true ;
2013-02-16 16:14:39 -08:00
}
2016-10-16 05:10:54 -04:00
bool SharedDatabase : : VerifyInventory ( uint32 account_id , int16 slot_id , const EQEmu : : ItemInstance * inst )
2013-02-16 16:14:39 -08:00
{
// Delete cursor items
2014-10-04 13:32:01 -07:00
std : : string query = StringFormat ( " SELECT itemid, charges FROM sharedbank "
" WHERE acctid = %d AND slotid = %d " ,
account_id , slot_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
//returning true is less harmful in the face of a query error
2014-10-04 13:32:01 -07:00
return true ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:32:01 -07:00
if ( results . RowCount ( ) = = 0 )
return false ;
2013-05-06 13:07:41 -04:00
2014-10-04 13:32:01 -07:00
auto row = results . begin ( ) ;
2013-05-06 13:07:41 -04:00
2014-10-04 13:32:01 -07:00
uint32 id = atoi ( row [ 0 ] ) ;
uint16 charges = atoi ( row [ 1 ] ) ;
uint16 expect_charges = 0 ;
if ( inst - > GetCharges ( ) > = 0 )
expect_charges = inst - > GetCharges ( ) ;
else
expect_charges = 0x7FFF ;
if ( id ! = inst - > GetItem ( ) - > ID | | charges ! = expect_charges )
return false ;
return true ;
2013-02-16 16:14:39 -08:00
}
2016-10-16 05:10:54 -04:00
bool SharedDatabase : : SaveInventory ( uint32 char_id , const EQEmu : : ItemInstance * inst , int16 slot_id ) {
2013-02-16 16:14:39 -08:00
//never save tribute slots:
2016-04-22 07:34:55 -04:00
if ( slot_id > = EQEmu : : legacy : : TRIBUTE_BEGIN & & slot_id < = EQEmu : : legacy : : TRIBUTE_END )
2014-10-04 13:45:50 -07:00
return true ;
2016-04-22 07:34:55 -04:00
if ( slot_id > = EQEmu : : legacy : : SHARED_BANK_BEGIN & & slot_id < = EQEmu : : legacy : : SHARED_BANK_BAGS_END ) {
2014-10-04 13:45:50 -07:00
// Shared bank inventory
2015-03-03 04:08:52 -05:00
if ( ! inst ) {
return DeleteSharedBankSlot ( char_id , slot_id ) ;
}
else {
// Needed to clear out bag slots that 'REPLACE' in UpdateSharedBankSlot does not overwrite..otherwise, duplication occurs
// (This requires that parent then child items be sent..which should be how they are currently passed)
2016-10-17 04:59:00 -04:00
if ( EQEmu : : InventoryProfile : : SupportsContainers ( slot_id ) )
2015-03-03 04:08:52 -05:00
DeleteSharedBankSlot ( char_id , slot_id ) ;
return UpdateSharedBankSlot ( char_id , inst , slot_id ) ;
}
2014-10-04 13:45:50 -07:00
}
2015-01-15 21:24:26 -05:00
else if ( ! inst ) { // All other inventory
return DeleteInventorySlot ( char_id , slot_id ) ;
}
2013-05-06 13:07:41 -04:00
2015-03-03 04:08:52 -05:00
// Needed to clear out bag slots that 'REPLACE' in UpdateInventorySlot does not overwrite..otherwise, duplication occurs
// (This requires that parent then child items be sent..which should be how they are currently passed)
2016-10-17 04:59:00 -04:00
if ( EQEmu : : InventoryProfile : : SupportsContainers ( slot_id ) )
2015-03-03 04:08:52 -05:00
DeleteInventorySlot ( char_id , slot_id ) ;
2014-10-04 13:45:50 -07:00
return UpdateInventorySlot ( char_id , inst , slot_id ) ;
}
2016-10-16 05:10:54 -04:00
bool SharedDatabase : : UpdateInventorySlot ( uint32 char_id , const EQEmu : : ItemInstance * inst , int16 slot_id ) {
2014-12-23 10:14:45 -05:00
// need to check 'inst' argument for valid pointer
2014-10-04 13:45:50 -07:00
2016-10-16 21:36:39 -04:00
uint32 augslot [ EQEmu : : inventory : : SocketCount ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2016-05-21 04:54:18 -04:00
if ( inst - > IsClassCommon ( ) ) {
2016-10-16 21:36:39 -04:00
for ( int i = EQEmu : : inventory : : socketBegin ; i < EQEmu : : inventory : : SocketCount ; i + + ) {
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * auginst = inst - > GetItem ( i ) ;
2016-05-21 04:54:18 -04:00
augslot [ i ] = ( auginst & & auginst - > GetItem ( ) ) ? auginst - > GetItem ( ) - > ID : 0 ;
2013-02-16 16:14:39 -08:00
}
2015-01-15 21:24:26 -05:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
uint16 charges = 0 ;
if ( inst - > GetCharges ( ) > = 0 )
charges = inst - > GetCharges ( ) ;
else
charges = 0x7FFF ;
// Update/Insert item
std : : string query = StringFormat ( " REPLACE INTO inventory "
" (charid, slotid, itemid, charges, instnodrop, custom_data, color, "
2014-12-15 17:55:23 -06:00
" augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) "
2014-10-04 13:45:50 -07:00
" VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
2014-12-15 17:55:23 -06:00
" %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu) " ,
2014-10-04 13:45:50 -07:00
( unsigned long ) char_id , ( unsigned long ) slot_id , ( unsigned long ) inst - > GetItem ( ) - > ID ,
2014-12-15 17:55:23 -06:00
( unsigned long ) charges , ( unsigned long ) ( inst - > IsAttuned ( ) ? 1 : 0 ) ,
2014-10-04 13:45:50 -07:00
inst - > GetCustomDataString ( ) . c_str ( ) , ( unsigned long ) inst - > GetColor ( ) ,
( unsigned long ) augslot [ 0 ] , ( unsigned long ) augslot [ 1 ] , ( unsigned long ) augslot [ 2 ] ,
2014-12-15 17:55:23 -06:00
( unsigned long ) augslot [ 3 ] , ( unsigned long ) augslot [ 4 ] , ( unsigned long ) augslot [ 5 ] , ( unsigned long ) inst - > GetOrnamentationIcon ( ) ,
2014-12-13 13:53:55 -06:00
( unsigned long ) inst - > GetOrnamentationIDFile ( ) , ( unsigned long ) inst - > GetOrnamentHeroModel ( ) ) ;
2014-10-04 13:45:50 -07:00
auto results = QueryDatabase ( query ) ;
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
// Save bag contents, if slot supports bag contents
2016-10-17 04:59:00 -04:00
if ( inst - > IsClassBag ( ) & & EQEmu : : InventoryProfile : : SupportsContainers ( slot_id ) )
2015-03-03 04:08:52 -05:00
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
// messages through attrition (and the modded code in SaveInventory)
2016-10-16 21:36:39 -04:00
for ( uint8 idx = EQEmu : : inventory : : containerBegin ; idx < inst - > GetItem ( ) - > BagSlots & & idx < EQEmu : : inventory : : ContainerCount ; idx + + ) {
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemInstance * baginst = inst - > GetItem ( idx ) ;
2016-10-17 04:59:00 -04:00
SaveInventory ( char_id , baginst , EQEmu : : InventoryProfile : : CalcSlotId ( slot_id , idx ) ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
if ( ! results . Success ( ) ) {
return false ;
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
return true ;
}
2016-10-16 05:10:54 -04:00
bool SharedDatabase : : UpdateSharedBankSlot ( uint32 char_id , const EQEmu : : ItemInstance * inst , int16 slot_id ) {
2014-12-23 10:14:45 -05:00
// need to check 'inst' argument for valid pointer
2013-05-06 13:07:41 -04:00
2016-10-16 21:36:39 -04:00
uint32 augslot [ EQEmu : : inventory : : SocketCount ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2016-05-21 04:54:18 -04:00
if ( inst - > IsClassCommon ( ) ) {
2016-10-16 21:36:39 -04:00
for ( int i = EQEmu : : inventory : : socketBegin ; i < EQEmu : : inventory : : SocketCount ; i + + ) {
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * auginst = inst - > GetItem ( i ) ;
2016-05-21 04:54:18 -04:00
augslot [ i ] = ( auginst & & auginst - > GetItem ( ) ) ? auginst - > GetItem ( ) - > ID : 0 ;
2013-02-16 16:14:39 -08:00
}
2015-01-15 21:24:26 -05:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
// Update/Insert item
uint32 account_id = GetAccountIDByChar ( char_id ) ;
uint16 charges = 0 ;
if ( inst - > GetCharges ( ) > = 0 )
charges = inst - > GetCharges ( ) ;
else
charges = 0x7FFF ;
std : : string query = StringFormat ( " REPLACE INTO sharedbank "
" (acctid, slotid, itemid, charges, custom_data, "
2014-12-15 17:55:23 -06:00
" augslot1, augslot2, augslot3, augslot4, augslot5, augslot6) "
2014-10-04 13:45:50 -07:00
" VALUES( %lu, %lu, %lu, %lu, '%s', "
2014-12-15 17:55:23 -06:00
" %lu, %lu, %lu, %lu, %lu, %lu) " ,
2014-10-04 13:45:50 -07:00
( unsigned long ) account_id , ( unsigned long ) slot_id , ( unsigned long ) inst - > GetItem ( ) - > ID ,
( unsigned long ) charges , inst - > GetCustomDataString ( ) . c_str ( ) , ( unsigned long ) augslot [ 0 ] ,
2014-12-15 17:55:23 -06:00
( unsigned long ) augslot [ 1 ] , ( unsigned long ) augslot [ 2 ] , ( unsigned long ) augslot [ 3 ] , ( unsigned long ) augslot [ 4 ] ,
( unsigned long ) augslot [ 5 ] ) ;
2014-10-04 13:45:50 -07:00
auto results = QueryDatabase ( query ) ;
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
// Save bag contents, if slot supports bag contents
2016-10-17 04:59:00 -04:00
if ( inst - > IsClassBag ( ) & & EQEmu : : InventoryProfile : : SupportsContainers ( slot_id ) ) {
2015-03-03 04:08:52 -05:00
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
// messages through attrition (and the modded code in SaveInventory)
2016-10-16 21:36:39 -04:00
for ( uint8 idx = EQEmu : : inventory : : containerBegin ; idx < inst - > GetItem ( ) - > BagSlots & & idx < EQEmu : : inventory : : ContainerCount ; idx + + ) {
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemInstance * baginst = inst - > GetItem ( idx ) ;
2016-10-17 04:59:00 -04:00
SaveInventory ( char_id , baginst , EQEmu : : InventoryProfile : : CalcSlotId ( slot_id , idx ) ) ;
2013-02-16 16:14:39 -08:00
}
2015-01-15 21:24:26 -05:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
if ( ! results . Success ( ) ) {
return false ;
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:45:50 -07:00
return true ;
2013-02-16 16:14:39 -08:00
}
2014-10-04 13:45:50 -07:00
bool SharedDatabase : : DeleteInventorySlot ( uint32 char_id , int16 slot_id ) {
// Delete item
std : : string query = StringFormat ( " DELETE FROM inventory WHERE charid = %i AND slotid = %i " , char_id , slot_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return false ;
}
// Delete bag slots, if need be
2016-10-17 04:59:00 -04:00
if ( ! EQEmu : : InventoryProfile : : SupportsContainers ( slot_id ) )
2014-10-04 13:45:50 -07:00
return true ;
2016-10-17 04:59:00 -04:00
int16 base_slot_id = EQEmu : : InventoryProfile : : CalcSlotId ( slot_id , EQEmu : : inventory : : containerBegin ) ;
2014-10-04 13:45:50 -07:00
query = StringFormat ( " DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i " ,
char_id , base_slot_id , ( base_slot_id + 10 ) ) ;
results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return false ;
}
// @merth: need to delete augments here
return true ;
2013-02-16 16:14:39 -08:00
}
2014-10-04 13:45:50 -07:00
bool SharedDatabase : : DeleteSharedBankSlot ( uint32 char_id , int16 slot_id ) {
// Delete item
uint32 account_id = GetAccountIDByChar ( char_id ) ;
std : : string query = StringFormat ( " DELETE FROM sharedbank WHERE acctid=%i AND slotid=%i " , account_id , slot_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return false ;
}
// Delete bag slots, if need be
2016-10-17 04:59:00 -04:00
if ( ! EQEmu : : InventoryProfile : : SupportsContainers ( slot_id ) )
2014-10-04 13:45:50 -07:00
return true ;
2016-10-17 04:59:00 -04:00
int16 base_slot_id = EQEmu : : InventoryProfile : : CalcSlotId ( slot_id , EQEmu : : inventory : : containerBegin ) ;
2014-10-04 13:45:50 -07:00
query = StringFormat ( " DELETE FROM sharedbank WHERE acctid = %i "
" AND slotid >= %i AND slotid < %i " ,
account_id , base_slot_id , ( base_slot_id + 10 ) ) ;
results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return false ;
}
// @merth: need to delete augments here
return true ;
}
2013-02-16 16:14:39 -08:00
int32 SharedDatabase : : GetSharedPlatinum ( uint32 account_id )
{
2014-10-04 13:50:01 -07:00
std : : string query = StringFormat ( " SELECT sharedplat FROM account WHERE id = '%i' " , account_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return false ;
2014-10-04 13:50:01 -07:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:50:01 -07:00
if ( results . RowCount ( ) ! = 1 )
return 0 ;
2013-05-06 13:07:41 -04:00
2014-10-04 13:50:01 -07:00
auto row = results . begin ( ) ;
return atoi ( row [ 0 ] ) ;
2013-02-16 16:14:39 -08:00
}
State of Commit: Testable if you ask me (Akkadius) what you need to do
- Need to convert a list of functions and columns and should be ready to start intensive testing phase
- All preliminary tests show things working great
- All of player profile is saved and loaded from the database
- DBAsync has been completely removed from all code
- Removed zone/dbasync.cpp/.h
- Removed common/dbasync.cpp/.h
- Removed dbasync from cmake commmon and zone
- Cleaned up a ton of functions
- Added several tables to world CheckDatabaseConversions script:
- `character_skills`
- `character_languages`
- `character_bind`
- `character_alternate_abilities`
- `character_currency`
- `character_data`
- `character_spells`
- `character_memmed_spells`
- `character_disciplines`
- `character_material`
- `character_tribute`
- `character_bandolier`
- `character_potionbelt`
- Character select now loads from `character_data`
- Character creation now creates to `character_data`
- Updated function Database::UpdateName to use `character_data`
- Updated function Database::CheckUsedName to use `character_data`
- Updated function Database::MoveCharacterToZone to use `character_data`
- Updated function Database::SetLoginFlags to use `character_data`
- Updated function Database::SetFirstLogon to use `character_data`
- Updated function Database::SetLFG to use `character_data`
- Removed CopyCharacter functions and commands, to be recreated later since it never worked to begin with
- Removed SharedDatabase::SetPlayerProfile
- Trimmed down redundant case switch statements for World sendpackets to QueryServ
- Added Character Methods to Database class:
Loads:
bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
Saves:
bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
bool SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
Deletes:
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
2014-09-04 07:24:17 -05:00
bool SharedDatabase : : SetSharedPlatinum ( uint32 account_id , int32 amount_to_add ) {
2014-10-04 13:53:28 -07:00
std : : string query = StringFormat ( " UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i " , amount_to_add , account_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
return true ;
}
2016-10-17 04:59:00 -04:00
bool SharedDatabase : : SetStartingItems ( PlayerProfile_Struct * pp , EQEmu : : InventoryProfile * inv , uint32 si_race , uint32 si_class , uint32 si_deity , uint32 si_current_zone , char * si_name , int admin_level ) {
2014-10-04 13:54:33 -07:00
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemData * myitem ;
2014-10-04 13:54:33 -07:00
std : : string query = StringFormat ( " SELECT itemid, item_charges, slot FROM starting_items "
" WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
" (deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND "
" gm <= %i ORDER BY id " ,
si_race , si_class , si_deity , si_current_zone , admin_level ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) )
return false ;
State of Commit: Testable if you ask me (Akkadius) what you need to do
- Need to convert a list of functions and columns and should be ready to start intensive testing phase
- All preliminary tests show things working great
- All of player profile is saved and loaded from the database
- DBAsync has been completely removed from all code
- Removed zone/dbasync.cpp/.h
- Removed common/dbasync.cpp/.h
- Removed dbasync from cmake commmon and zone
- Cleaned up a ton of functions
- Added several tables to world CheckDatabaseConversions script:
- `character_skills`
- `character_languages`
- `character_bind`
- `character_alternate_abilities`
- `character_currency`
- `character_data`
- `character_spells`
- `character_memmed_spells`
- `character_disciplines`
- `character_material`
- `character_tribute`
- `character_bandolier`
- `character_potionbelt`
- Character select now loads from `character_data`
- Character creation now creates to `character_data`
- Updated function Database::UpdateName to use `character_data`
- Updated function Database::CheckUsedName to use `character_data`
- Updated function Database::MoveCharacterToZone to use `character_data`
- Updated function Database::SetLoginFlags to use `character_data`
- Updated function Database::SetFirstLogon to use `character_data`
- Updated function Database::SetLFG to use `character_data`
- Removed CopyCharacter functions and commands, to be recreated later since it never worked to begin with
- Removed SharedDatabase::SetPlayerProfile
- Trimmed down redundant case switch statements for World sendpackets to QueryServ
- Added Character Methods to Database class:
Loads:
bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
Saves:
bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
bool SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
Deletes:
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
2014-09-04 07:24:17 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
2014-10-04 13:54:33 -07:00
int32 itemid = atoi ( row [ 0 ] ) ;
int32 charges = atoi ( row [ 1 ] ) ;
int32 slot = atoi ( row [ 2 ] ) ;
2013-02-16 16:14:39 -08:00
myitem = GetItem ( itemid ) ;
2014-10-04 13:54:33 -07:00
2014-10-04 13:23:52 -07:00
if ( ! myitem )
2013-02-16 16:14:39 -08:00
continue ;
2014-10-04 13:54:33 -07:00
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * myinst = CreateBaseItem ( myitem , charges ) ;
2014-10-04 13:54:33 -07:00
2013-02-16 16:14:39 -08:00
if ( slot < 0 )
2014-10-04 13:54:33 -07:00
slot = inv - > FindFreeSlot ( 0 , 0 ) ;
2013-02-16 16:14:39 -08:00
inv - > PutItem ( slot , * myinst ) ;
safe_delete ( myinst ) ;
}
2014-10-04 13:54:33 -07:00
2013-02-16 16:14:39 -08:00
return true ;
}
// Retrieve shared bank inventory based on either account or character
2016-10-17 04:59:00 -04:00
bool SharedDatabase : : GetSharedBank ( uint32 id , EQEmu : : InventoryProfile * inv , bool is_charid )
2015-01-31 01:22:40 -05:00
{
2014-10-04 13:55:43 -07:00
std : : string query ;
if ( is_charid )
query = StringFormat ( " SELECT sb.slotid, sb.itemid, sb.charges, "
2015-01-31 01:22:40 -05:00
" sb.augslot1, sb.augslot2, sb.augslot3, "
" sb.augslot4, sb.augslot5, sb.augslot6, sb.custom_data "
" FROM sharedbank sb INNER JOIN character_data ch "
2016-05-21 05:21:03 -04:00
" ON ch.account_id=sb.acctid WHERE ch.id = %i ORDER BY sb.slotid " ,
2015-01-31 01:22:40 -05:00
id ) ;
2014-10-04 13:55:43 -07:00
else
query = StringFormat ( " SELECT slotid, itemid, charges, "
2015-01-31 01:22:40 -05:00
" augslot1, augslot2, augslot3, "
" augslot4, augslot5, augslot6, custom_data "
2016-05-21 05:21:03 -04:00
" FROM sharedbank WHERE acctid=%i ORDER BY slotid " ,
2015-01-31 01:22:40 -05:00
id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Database::GetSharedBank(uint32 account_id): %s " ,
2015-01-31 01:22:40 -05:00
results . ErrorMessage ( ) . c_str ( ) ) ;
return false ;
}
2013-05-06 13:07:41 -04:00
2015-01-31 01:22:40 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
int16 slot_id = ( int16 ) atoi ( row [ 0 ] ) ;
uint32 item_id = ( uint32 ) atoi ( row [ 1 ] ) ;
int8 charges = ( int8 ) atoi ( row [ 2 ] ) ;
2013-05-06 13:07:41 -04:00
2016-10-16 21:36:39 -04:00
uint32 aug [ EQEmu : : inventory : : SocketCount ] ;
2014-12-15 17:55:23 -06:00
aug [ 0 ] = ( uint32 ) atoi ( row [ 3 ] ) ;
aug [ 1 ] = ( uint32 ) atoi ( row [ 4 ] ) ;
2015-01-31 01:22:40 -05:00
aug [ 2 ] = ( uint32 ) atoi ( row [ 5 ] ) ;
aug [ 3 ] = ( uint32 ) atoi ( row [ 6 ] ) ;
aug [ 4 ] = ( uint32 ) atoi ( row [ 7 ] ) ;
2014-12-15 17:55:23 -06:00
aug [ 5 ] = ( uint32 ) atoi ( row [ 8 ] ) ;
2014-10-04 13:55:43 -07:00
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemData * item = GetItem ( item_id ) ;
2014-10-04 13:55:43 -07:00
2015-01-31 01:22:40 -05:00
if ( ! item ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error ,
2015-01-31 01:22:40 -05:00
" Warning: %s %i has an invalid item_id %i in inventory slot %i " ,
( ( is_charid = = true ) ? " charid " : " acctid " ) , id , item_id , slot_id ) ;
continue ;
}
2013-05-06 13:07:41 -04:00
2015-01-31 01:22:40 -05:00
int16 put_slot_id = INVALID_INDEX ;
2014-10-04 13:55:43 -07:00
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * inst = CreateBaseItem ( item , charges ) ;
2016-05-21 04:54:18 -04:00
if ( inst & & item - > IsClassCommon ( ) ) {
2016-10-16 21:36:39 -04:00
for ( int i = EQEmu : : inventory : : socketBegin ; i < EQEmu : : inventory : : SocketCount ; i + + ) {
2015-01-31 01:22:40 -05:00
if ( aug [ i ] )
2015-01-15 21:24:26 -05:00
inst - > PutAugment ( this , i , aug [ i ] ) ;
2015-01-31 01:22:40 -05:00
}
}
2016-08-13 15:09:43 -04:00
if ( inst & & row [ 9 ] ) {
2015-01-31 03:48:59 -05:00
std : : string data_str ( row [ 9 ] ) ;
std : : string idAsString ;
std : : string value ;
bool use_id = true ;
for ( int i = 0 ; i < data_str . length ( ) ; + + i ) {
if ( data_str [ i ] = = ' ^ ' ) {
if ( ! use_id ) {
inst - > SetCustomData ( idAsString , value ) ;
idAsString . clear ( ) ;
value . clear ( ) ;
}
use_id = ! use_id ;
continue ;
2015-01-31 01:22:40 -05:00
}
2015-01-31 03:48:59 -05:00
char v = data_str [ i ] ;
if ( use_id )
idAsString . push_back ( v ) ;
else
value . push_back ( v ) ;
}
2015-01-31 01:22:40 -05:00
}
2016-08-13 15:09:43 -04:00
// theoretically inst can be nullptr ... this would be very bad ...
2015-01-31 01:22:40 -05:00
put_slot_id = inv - > PutItem ( slot_id , * inst ) ;
safe_delete ( inst ) ;
// Save ptr to item in inventory
if ( put_slot_id ! = INVALID_INDEX )
continue ;
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error ,
2015-01-31 01:22:40 -05:00
" Warning: Invalid slot_id for item in shared bank inventory: %s=%i, item_id=%i, slot_id=%i " ,
( ( is_charid = = true ) ? " charid " : " acctid " ) , id , item_id , slot_id ) ;
if ( is_charid )
SaveInventory ( id , nullptr , slot_id ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2014-10-04 13:55:43 -07:00
return true ;
2013-02-16 16:14:39 -08:00
}
// Overloaded: Retrieve character inventory based on character id
2016-10-17 04:59:00 -04:00
bool SharedDatabase : : GetInventory ( uint32 char_id , EQEmu : : InventoryProfile * inv )
2015-01-31 00:00:02 -05:00
{
2013-02-16 16:14:39 -08:00
// Retrieve character inventory
2015-01-31 00:00:02 -05:00
std : : string query =
StringFormat ( " SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, "
" augslot6, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model FROM "
" inventory WHERE charid = %i ORDER BY slotid " ,
char_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " If you got an error related to the 'instnodrop' field, run the "
2015-01-31 00:00:02 -05:00
" following SQL Queries: \n alter table inventory add instnodrop "
" tinyint(1) unsigned default 0 not null; \n " ) ;
return false ;
}
2013-05-06 13:07:41 -04:00
2015-01-31 17:53:50 -05:00
auto timestamps = GetItemRecastTimestamps ( char_id ) ;
2015-01-31 00:00:02 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
int16 slot_id = atoi ( row [ 0 ] ) ;
uint32 item_id = atoi ( row [ 1 ] ) ;
uint16 charges = atoi ( row [ 2 ] ) ;
uint32 color = atoul ( row [ 3 ] ) ;
2016-10-16 21:36:39 -04:00
uint32 aug [ EQEmu : : inventory : : SocketCount ] ;
2015-01-31 00:00:02 -05:00
aug [ 0 ] = ( uint32 ) atoul ( row [ 4 ] ) ;
aug [ 1 ] = ( uint32 ) atoul ( row [ 5 ] ) ;
aug [ 2 ] = ( uint32 ) atoul ( row [ 6 ] ) ;
aug [ 3 ] = ( uint32 ) atoul ( row [ 7 ] ) ;
aug [ 4 ] = ( uint32 ) atoul ( row [ 8 ] ) ;
2014-12-15 17:55:23 -06:00
aug [ 5 ] = ( uint32 ) atoul ( row [ 9 ] ) ;
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
bool instnodrop = ( row [ 10 ] & & ( uint16 ) atoi ( row [ 10 ] ) ) ? true : false ;
2014-10-04 14:04:19 -07:00
2014-12-15 17:55:23 -06:00
uint32 ornament_icon = ( uint32 ) atoul ( row [ 12 ] ) ;
uint32 ornament_idfile = ( uint32 ) atoul ( row [ 13 ] ) ;
uint32 ornament_hero_model = ( uint32 ) atoul ( row [ 14 ] ) ;
2014-11-26 13:57:18 -08:00
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemData * item = GetItem ( item_id ) ;
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
if ( ! item ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error ,
2015-01-31 00:00:02 -05:00
" Warning: charid %i has an invalid item_id %i in inventory slot %i " , char_id , item_id ,
slot_id ) ;
continue ;
}
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
int16 put_slot_id = INVALID_INDEX ;
2014-10-04 14:04:19 -07:00
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * inst = CreateBaseItem ( item , charges ) ;
2014-10-04 14:04:19 -07:00
2014-12-23 10:14:45 -05:00
if ( inst = = nullptr )
continue ;
2015-01-31 00:00:02 -05:00
if ( row [ 11 ] ) {
std : : string data_str ( row [ 11 ] ) ;
std : : string idAsString ;
std : : string value ;
bool use_id = true ;
for ( int i = 0 ; i < data_str . length ( ) ; + + i ) {
if ( data_str [ i ] = = ' ^ ' ) {
if ( ! use_id ) {
inst - > SetCustomData ( idAsString , value ) ;
idAsString . clear ( ) ;
value . clear ( ) ;
}
use_id = ! use_id ;
continue ;
}
char v = data_str [ i ] ;
if ( use_id )
idAsString . push_back ( v ) ;
else
value . push_back ( v ) ;
}
}
2014-11-26 13:57:18 -08:00
2014-12-13 13:53:55 -06:00
inst - > SetOrnamentIcon ( ornament_icon ) ;
inst - > SetOrnamentationIDFile ( ornament_idfile ) ;
2016-12-18 05:36:30 -06:00
inst - > SetOrnamentHeroModel ( item - > HerosForgeModel ) ;
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
if ( instnodrop | |
2016-04-22 07:34:55 -04:00
( ( ( slot_id > = EQEmu : : legacy : : EQUIPMENT_BEGIN & & slot_id < = EQEmu : : legacy : : EQUIPMENT_END ) | |
2016-10-16 21:36:39 -04:00
slot_id = = EQEmu : : inventory : : slotPowerSource ) & &
2015-01-31 00:00:02 -05:00
inst - > GetItem ( ) - > Attuneable ) )
inst - > SetAttuned ( true ) ;
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
if ( color > 0 )
inst - > SetColor ( color ) ;
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
if ( charges = = 0x7FFF )
inst - > SetCharges ( - 1 ) ;
2016-06-28 07:58:38 -04:00
else if ( charges = = 0 & & inst - > IsStackable ( ) ) // Stackable items need a minimum charge of 1 remain moveable.
2014-12-17 00:24:47 +01:00
inst - > SetCharges ( 1 ) ;
else
2015-01-31 00:00:02 -05:00
inst - > SetCharges ( charges ) ;
2014-10-04 14:04:19 -07:00
2015-01-31 17:53:50 -05:00
if ( item - > RecastDelay ) {
if ( timestamps . count ( item - > RecastType ) )
inst - > SetRecastTimestamp ( timestamps . at ( item - > RecastType ) ) ;
else
inst - > SetRecastTimestamp ( 0 ) ;
}
2016-05-21 04:54:18 -04:00
if ( item - > IsClassCommon ( ) ) {
2016-10-16 21:36:39 -04:00
for ( int i = EQEmu : : inventory : : socketBegin ; i < EQEmu : : inventory : : SocketCount ; i + + ) {
2015-01-15 21:24:26 -05:00
if ( aug [ i ] )
inst - > PutAugment ( this , i , aug [ i ] ) ;
}
}
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
if ( slot_id > = 8000 & & slot_id < = 8999 ) {
put_slot_id = inv - > PushCursor ( * inst ) ;
} else if ( slot_id > = 3111 & & slot_id < = 3179 ) {
// Admins: please report any occurrences of this error
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Warning: Defunct location for item in inventory: "
2015-01-31 00:00:02 -05:00
" charid=%i, item_id=%i, slot_id=%i .. pushing to cursor... " ,
char_id , item_id , slot_id ) ;
put_slot_id = inv - > PushCursor ( * inst ) ;
} else {
2015-01-07 22:20:44 -06:00
put_slot_id = inv - > PutItem ( slot_id , * inst ) ;
}
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
safe_delete ( inst ) ;
2014-10-04 14:04:19 -07:00
2015-01-31 00:00:02 -05:00
// Save ptr to item in inventory
if ( put_slot_id = = INVALID_INDEX ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error ,
2015-01-31 00:00:02 -05:00
" Warning: Invalid slot_id for item in inventory: charid=%i, item_id=%i, slot_id=%i " ,
char_id , item_id , slot_id ) ;
}
}
2013-05-06 13:07:41 -04:00
2015-01-31 00:00:02 -05:00
// Retrieve shared inventory
2014-10-04 14:04:19 -07:00
return GetSharedBank ( char_id , inv , true ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
// Overloaded: Retrieve character inventory based on account_id and character name
2016-10-17 04:59:00 -04:00
bool SharedDatabase : : GetInventory ( uint32 account_id , char * name , EQEmu : : InventoryProfile * inv )
2015-01-31 00:00:02 -05:00
{
2013-02-16 16:14:39 -08:00
// Retrieve character inventory
2015-01-31 00:00:02 -05:00
std : : string query =
StringFormat ( " SELECT slotid, itemid, charges, color, augslot1, "
" augslot2, augslot3, augslot4, augslot5, augslot6, instnodrop, custom_data, ornamenticon, "
" ornamentidfile, ornament_hero_model "
" FROM inventory INNER JOIN character_data ch "
" ON ch.id = charid WHERE ch.name = '%s' AND ch.account_id = %i ORDER BY slotid " ,
name , account_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " If you got an error related to the 'instnodrop' field, run the "
2015-01-31 00:00:02 -05:00
" following SQL Queries: \n alter table inventory add instnodrop "
" tinyint(1) unsigned default 0 not null; \n " ) ;
return false ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2015-01-31 00:00:02 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
int16 slot_id = atoi ( row [ 0 ] ) ;
uint32 item_id = atoi ( row [ 1 ] ) ;
int8 charges = atoi ( row [ 2 ] ) ;
uint32 color = atoul ( row [ 3 ] ) ;
2013-02-16 16:14:39 -08:00
2016-10-16 21:36:39 -04:00
uint32 aug [ EQEmu : : inventory : : SocketCount ] ;
2015-01-31 00:00:02 -05:00
aug [ 0 ] = ( uint32 ) atoi ( row [ 4 ] ) ;
aug [ 1 ] = ( uint32 ) atoi ( row [ 5 ] ) ;
aug [ 2 ] = ( uint32 ) atoi ( row [ 6 ] ) ;
aug [ 3 ] = ( uint32 ) atoi ( row [ 7 ] ) ;
aug [ 4 ] = ( uint32 ) atoi ( row [ 8 ] ) ;
2014-12-15 17:55:23 -06:00
aug [ 5 ] = ( uint32 ) atoi ( row [ 9 ] ) ;
2015-01-31 00:00:02 -05:00
bool instnodrop = ( row [ 10 ] & & ( uint16 ) atoi ( row [ 10 ] ) ) ? true : false ;
2014-12-15 17:55:23 -06:00
uint32 ornament_icon = ( uint32 ) atoul ( row [ 12 ] ) ;
uint32 ornament_idfile = ( uint32 ) atoul ( row [ 13 ] ) ;
uint32 ornament_hero_model = ( uint32 ) atoul ( row [ 14 ] ) ;
2013-02-16 16:14:39 -08:00
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemData * item = GetItem ( item_id ) ;
2015-01-31 00:00:02 -05:00
int16 put_slot_id = INVALID_INDEX ;
if ( ! item )
2014-12-23 10:14:45 -05:00
continue ;
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * inst = CreateBaseItem ( item , charges ) ;
2013-05-06 13:07:41 -04:00
2015-01-31 00:00:02 -05:00
if ( inst = = nullptr )
continue ;
2013-05-06 13:07:41 -04:00
2015-01-31 00:00:02 -05:00
inst - > SetAttuned ( instnodrop ) ;
if ( row [ 11 ] ) {
std : : string data_str ( row [ 11 ] ) ;
std : : string idAsString ;
std : : string value ;
bool use_id = true ;
for ( int i = 0 ; i < data_str . length ( ) ; + + i ) {
if ( data_str [ i ] = = ' ^ ' ) {
if ( ! use_id ) {
inst - > SetCustomData ( idAsString , value ) ;
idAsString . clear ( ) ;
value . clear ( ) ;
}
use_id = ! use_id ;
continue ;
}
char v = data_str [ i ] ;
if ( use_id )
idAsString . push_back ( v ) ;
else
value . push_back ( v ) ;
}
}
2014-10-04 14:02:43 -07:00
2014-12-13 13:53:55 -06:00
inst - > SetOrnamentIcon ( ornament_icon ) ;
inst - > SetOrnamentationIDFile ( ornament_idfile ) ;
2016-12-18 05:36:30 -06:00
inst - > SetOrnamentHeroModel ( item - > HerosForgeModel ) ;
2014-10-04 14:02:43 -07:00
2015-01-31 00:00:02 -05:00
if ( color > 0 )
inst - > SetColor ( color ) ;
2014-10-04 14:02:43 -07:00
2015-01-31 00:00:02 -05:00
inst - > SetCharges ( charges ) ;
2014-10-04 14:02:43 -07:00
2016-05-21 04:54:18 -04:00
if ( item - > IsClassCommon ( ) ) {
2016-10-16 21:36:39 -04:00
for ( int i = EQEmu : : inventory : : socketBegin ; i < EQEmu : : inventory : : SocketCount ; i + + ) {
2015-01-15 21:24:26 -05:00
if ( aug [ i ] )
inst - > PutAugment ( this , i , aug [ i ] ) ;
}
}
2014-10-04 14:02:43 -07:00
2015-01-31 00:00:02 -05:00
if ( slot_id > = 8000 & & slot_id < = 8999 )
put_slot_id = inv - > PushCursor ( * inst ) ;
else
put_slot_id = inv - > PutItem ( slot_id , * inst ) ;
2014-10-04 14:02:43 -07:00
2015-01-31 00:00:02 -05:00
safe_delete ( inst ) ;
2014-10-04 14:02:43 -07:00
2015-01-31 00:00:02 -05:00
// Save ptr to item in inventory
if ( put_slot_id = = INVALID_INDEX )
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Warning: Invalid slot_id for item in inventory: name=%s, "
2015-01-31 00:00:02 -05:00
" acctid=%i, item_id=%i, slot_id=%i " ,
name , account_id , item_id , slot_id ) ;
}
2014-10-04 14:02:43 -07:00
2015-01-31 00:00:02 -05:00
// Retrieve shared inventory
2014-10-04 14:02:43 -07:00
return GetSharedBank ( account_id , inv , false ) ;
2013-02-16 16:14:39 -08:00
}
2015-01-31 17:53:50 -05:00
std : : map < uint32 , uint32 > SharedDatabase : : GetItemRecastTimestamps ( uint32 char_id )
{
std : : map < uint32 , uint32 > timers ;
std : : string query = StringFormat ( " SELECT recast_type,timestamp FROM character_item_recast WHERE id=%u " , char_id ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) | | results . RowCount ( ) = = 0 )
return timers ;
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row )
timers [ atoul ( row [ 0 ] ) ] = atoul ( row [ 1 ] ) ;
return timers ; // RVO or move assigned
}
2015-01-31 20:54:56 -05:00
uint32 SharedDatabase : : GetItemRecastTimestamp ( uint32 char_id , uint32 recast_type )
{
std : : string query = StringFormat ( " SELECT timestamp FROM character_item_recast WHERE id=%u AND recast_type=%u " ,
char_id , recast_type ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) | | results . RowCount ( ) = = 0 )
return 0 ;
auto row = results . begin ( ) ;
return static_cast < uint32 > ( atoul ( row [ 0 ] ) ) ;
}
2015-01-31 17:53:50 -05:00
void SharedDatabase : : ClearOldRecastTimestamps ( uint32 char_id )
{
// This actually isn't strictly live-like. Live your recast timestamps are forever
std : : string query =
StringFormat ( " DELETE FROM character_item_recast WHERE id = %u and timestamp < UNIX_TIMESTAMP() " , char_id ) ;
QueryDatabase ( query ) ;
}
2015-01-31 00:00:02 -05:00
void SharedDatabase : : GetItemsCount ( int32 & item_count , uint32 & max_id )
{
2013-02-23 13:45:19 -08:00
item_count = - 1 ;
2013-05-09 10:44:08 -04:00
max_id = 0 ;
2013-05-06 13:07:41 -04:00
2014-10-04 14:05:07 -07:00
const std : : string query = " SELECT MAX(id), count(*) FROM items " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2015-01-31 00:00:02 -05:00
return ;
2013-02-16 16:14:39 -08:00
}
2014-10-04 14:05:07 -07:00
if ( results . RowCount ( ) = = 0 )
2015-01-31 00:00:02 -05:00
return ;
2014-10-04 14:05:07 -07:00
2015-01-31 00:00:02 -05:00
auto row = results . begin ( ) ;
2014-10-04 14:05:07 -07:00
2015-01-31 00:00:02 -05:00
if ( row [ 0 ] )
max_id = atoi ( row [ 0 ] ) ;
2014-10-04 14:05:07 -07:00
2015-01-31 00:00:02 -05:00
if ( row [ 1 ] )
2014-10-04 14:05:07 -07:00
item_count = atoi ( row [ 1 ] ) ;
2013-02-16 16:14:39 -08:00
}
2015-06-23 17:39:06 -07:00
bool SharedDatabase : : LoadItems ( const std : : string & prefix ) {
items_mmf . reset ( nullptr ) ;
2013-05-09 10:44:08 -04:00
try {
2016-05-24 23:49:25 -07:00
auto Config = EQEmuConfig : : get ( ) ;
2013-05-09 10:44:08 -04:00
EQEmu : : IPCMutex mutex ( " items " ) ;
mutex . Lock ( ) ;
2016-05-20 21:03:34 -05:00
std : : string file_name = Config - > SharedMemDir + prefix + std : : string ( " items " ) ;
2015-06-23 17:39:06 -07:00
items_mmf = std : : unique_ptr < EQEmu : : MemoryMappedFile > ( new EQEmu : : MemoryMappedFile ( file_name ) ) ;
2016-10-16 05:10:54 -04:00
items_hash = std : : unique_ptr < EQEmu : : FixedMemoryHashSet < EQEmu : : ItemData > > ( new EQEmu : : FixedMemoryHashSet < EQEmu : : ItemData > ( reinterpret_cast < uint8 * > ( items_mmf - > Get ( ) ) , items_mmf - > Size ( ) ) ) ;
2013-05-09 10:44:08 -04:00
mutex . Unlock ( ) ;
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error Loading Items: %s " , ex . what ( ) ) ;
2013-05-09 10:44:08 -04:00
return false ;
}
2013-02-20 22:36:30 -08:00
return true ;
2013-02-16 16:14:39 -08:00
}
2015-12-21 12:33:32 -05:00
void SharedDatabase : : LoadItems ( void * data , uint32 size , int32 items , uint32 max_item_id )
{
2016-10-16 05:10:54 -04:00
EQEmu : : FixedMemoryHashSet < EQEmu : : ItemData > hash ( reinterpret_cast < uint8 * > ( data ) , size , items , max_item_id ) ;
2013-02-20 22:36:30 -08:00
2016-05-09 14:23:27 -04:00
std : : string ndbuffer ;
2013-05-09 10:44:08 -04:00
bool disableNoRent = false ;
2016-05-09 14:23:27 -04:00
if ( GetVariable ( " disablenorent " , ndbuffer ) ) {
2015-12-21 12:33:32 -05:00
if ( ndbuffer [ 0 ] = = ' 1 ' & & ndbuffer [ 1 ] = = ' \0 ' ) {
2013-05-09 10:44:08 -04:00
disableNoRent = true ;
}
}
bool disableNoDrop = false ;
2016-05-09 14:23:27 -04:00
if ( GetVariable ( " disablenodrop " , ndbuffer ) ) {
2015-12-21 12:33:32 -05:00
if ( ndbuffer [ 0 ] = = ' 1 ' & & ndbuffer [ 1 ] = = ' \0 ' ) {
2013-05-09 10:44:08 -04:00
disableNoDrop = true ;
}
}
bool disableLoreGroup = false ;
2016-05-09 14:23:27 -04:00
if ( GetVariable ( " disablelore " , ndbuffer ) ) {
2015-12-21 12:33:32 -05:00
if ( ndbuffer [ 0 ] = = ' 1 ' & & ndbuffer [ 1 ] = = ' \0 ' ) {
2013-05-09 10:44:08 -04:00
disableLoreGroup = true ;
}
}
bool disableNoTransfer = false ;
2016-05-09 14:23:27 -04:00
if ( GetVariable ( " disablenotransfer " , ndbuffer ) ) {
2015-12-21 12:33:32 -05:00
if ( ndbuffer [ 0 ] = = ' 1 ' & & ndbuffer [ 1 ] = = ' \0 ' ) {
2013-05-09 10:44:08 -04:00
disableNoTransfer = true ;
}
}
2016-10-16 05:10:54 -04:00
EQEmu : : ItemData item ;
2014-10-04 14:06:37 -07:00
const std : : string query = " SELECT source, "
2015-12-21 12:41:49 -05:00
# define F(x) "`"#x"`,"
2013-02-16 16:14:39 -08:00
# include "item_fieldlist.h"
# undef F
2014-10-04 14:06:37 -07:00
" updated FROM items ORDER BY id " ;
auto results = QueryDatabase ( query ) ;
2015-12-21 12:33:32 -05:00
if ( ! results . Success ( ) ) {
return ;
}
2014-10-04 14:06:37 -07:00
2015-12-21 12:33:32 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
2016-10-16 05:10:54 -04:00
memset ( & item , 0 , sizeof ( EQEmu : : ItemData ) ) ;
2015-12-21 12:33:32 -05:00
item . ItemClass = ( uint8 ) atoi ( row [ ItemField : : itemclass ] ) ;
strcpy ( item . Name , row [ ItemField : : name ] ) ;
strcpy ( item . Lore , row [ ItemField : : lore ] ) ;
strcpy ( item . IDFile , row [ ItemField : : idfile ] ) ;
item . ID = ( uint32 ) atoul ( row [ ItemField : : id ] ) ;
2016-01-26 16:44:11 -05:00
item . Weight = ( int32 ) atoi ( row [ ItemField : : weight ] ) ;
2015-12-21 12:33:32 -05:00
item . NoRent = disableNoRent ? ( uint8 ) atoi ( " 255 " ) : ( uint8 ) atoi ( row [ ItemField : : norent ] ) ;
item . NoDrop = disableNoDrop ? ( uint8 ) atoi ( " 255 " ) : ( uint8 ) atoi ( row [ ItemField : : nodrop ] ) ;
item . Size = ( uint8 ) atoi ( row [ ItemField : : size ] ) ;
item . Slots = ( uint32 ) atoul ( row [ ItemField : : slots ] ) ;
item . Price = ( uint32 ) atoul ( row [ ItemField : : price ] ) ;
item . Icon = ( uint32 ) atoul ( row [ ItemField : : icon ] ) ;
item . BenefitFlag = ( atoul ( row [ ItemField : : benefitflag ] ) ! = 0 ) ;
item . Tradeskills = ( atoi ( row [ ItemField : : tradeskills ] ) = = 0 ) ? false : true ;
item . CR = ( int8 ) atoi ( row [ ItemField : : cr ] ) ;
item . DR = ( int8 ) atoi ( row [ ItemField : : dr ] ) ;
item . PR = ( int8 ) atoi ( row [ ItemField : : pr ] ) ;
item . MR = ( int8 ) atoi ( row [ ItemField : : mr ] ) ;
item . FR = ( int8 ) atoi ( row [ ItemField : : fr ] ) ;
item . AStr = ( int8 ) atoi ( row [ ItemField : : astr ] ) ;
item . ASta = ( int8 ) atoi ( row [ ItemField : : asta ] ) ;
item . AAgi = ( int8 ) atoi ( row [ ItemField : : aagi ] ) ;
item . ADex = ( int8 ) atoi ( row [ ItemField : : adex ] ) ;
item . ACha = ( int8 ) atoi ( row [ ItemField : : acha ] ) ;
item . AInt = ( int8 ) atoi ( row [ ItemField : : aint ] ) ;
item . AWis = ( int8 ) atoi ( row [ ItemField : : awis ] ) ;
item . HP = ( int32 ) atoul ( row [ ItemField : : hp ] ) ;
item . Mana = ( int32 ) atoul ( row [ ItemField : : mana ] ) ;
item . AC = ( int32 ) atoul ( row [ ItemField : : ac ] ) ;
item . Deity = ( uint32 ) atoul ( row [ ItemField : : deity ] ) ;
item . SkillModValue = ( int32 ) atoul ( row [ ItemField : : skillmodvalue ] ) ;
2015-12-21 05:27:20 -08:00
item . SkillModMax = ( int32 ) atoul ( row [ ItemField : : skillmodmax ] ) ;
2015-12-21 12:33:32 -05:00
item . SkillModType = ( uint32 ) atoul ( row [ ItemField : : skillmodtype ] ) ;
item . BaneDmgRace = ( uint32 ) atoul ( row [ ItemField : : banedmgrace ] ) ;
item . BaneDmgAmt = ( int8 ) atoi ( row [ ItemField : : banedmgamt ] ) ;
item . BaneDmgBody = ( uint32 ) atoul ( row [ ItemField : : banedmgbody ] ) ;
item . Magic = ( atoi ( row [ ItemField : : magic ] ) = = 0 ) ? false : true ;
item . CastTime_ = ( int32 ) atoul ( row [ ItemField : : casttime_ ] ) ;
item . ReqLevel = ( uint8 ) atoi ( row [ ItemField : : reqlevel ] ) ;
item . BardType = ( uint32 ) atoul ( row [ ItemField : : bardtype ] ) ;
item . BardValue = ( int32 ) atoul ( row [ ItemField : : bardvalue ] ) ;
item . Light = ( int8 ) atoi ( row [ ItemField : : light ] ) ;
item . Delay = ( uint8 ) atoi ( row [ ItemField : : delay ] ) ;
item . RecLevel = ( uint8 ) atoi ( row [ ItemField : : reclevel ] ) ;
item . RecSkill = ( uint8 ) atoi ( row [ ItemField : : recskill ] ) ;
item . ElemDmgType = ( uint8 ) atoi ( row [ ItemField : : elemdmgtype ] ) ;
item . ElemDmgAmt = ( uint8 ) atoi ( row [ ItemField : : elemdmgamt ] ) ;
item . Range = ( uint8 ) atoi ( row [ ItemField : : range ] ) ;
item . Damage = ( uint32 ) atoi ( row [ ItemField : : damage ] ) ;
item . Color = ( uint32 ) atoul ( row [ ItemField : : color ] ) ;
item . Classes = ( uint32 ) atoul ( row [ ItemField : : classes ] ) ;
item . Races = ( uint32 ) atoul ( row [ ItemField : : races ] ) ;
item . MaxCharges = ( int16 ) atoi ( row [ ItemField : : maxcharges ] ) ;
item . ItemType = ( uint8 ) atoi ( row [ ItemField : : itemtype ] ) ;
2014-12-09 21:18:56 -06:00
item . Material = ( uint8 ) atoi ( row [ ItemField : : material ] ) ;
item . HerosForgeModel = ( uint32 ) atoi ( row [ ItemField : : herosforgemodel ] ) ;
2015-12-21 12:33:32 -05:00
item . SellRate = ( float ) atof ( row [ ItemField : : sellrate ] ) ;
item . CastTime = ( uint32 ) atoul ( row [ ItemField : : casttime ] ) ;
item . EliteMaterial = ( uint32 ) atoul ( row [ ItemField : : elitematerial ] ) ;
item . ProcRate = ( int32 ) atoi ( row [ ItemField : : procrate ] ) ;
item . CombatEffects = ( int8 ) atoi ( row [ ItemField : : combateffects ] ) ;
item . Shielding = ( int8 ) atoi ( row [ ItemField : : shielding ] ) ;
item . StunResist = ( int8 ) atoi ( row [ ItemField : : stunresist ] ) ;
item . StrikeThrough = ( int8 ) atoi ( row [ ItemField : : strikethrough ] ) ;
item . ExtraDmgSkill = ( uint32 ) atoul ( row [ ItemField : : extradmgskill ] ) ;
item . ExtraDmgAmt = ( uint32 ) atoul ( row [ ItemField : : extradmgamt ] ) ;
item . SpellShield = ( int8 ) atoi ( row [ ItemField : : spellshield ] ) ;
item . Avoidance = ( int8 ) atoi ( row [ ItemField : : avoidance ] ) ;
item . Accuracy = ( int8 ) atoi ( row [ ItemField : : accuracy ] ) ;
item . CharmFileID = ( uint32 ) atoul ( row [ ItemField : : charmfileid ] ) ;
item . FactionMod1 = ( int32 ) atoul ( row [ ItemField : : factionmod1 ] ) ;
item . FactionMod2 = ( int32 ) atoul ( row [ ItemField : : factionmod2 ] ) ;
item . FactionMod3 = ( int32 ) atoul ( row [ ItemField : : factionmod3 ] ) ;
item . FactionMod4 = ( int32 ) atoul ( row [ ItemField : : factionmod4 ] ) ;
item . FactionAmt1 = ( int32 ) atoul ( row [ ItemField : : factionamt1 ] ) ;
item . FactionAmt2 = ( int32 ) atoul ( row [ ItemField : : factionamt2 ] ) ;
item . FactionAmt3 = ( int32 ) atoul ( row [ ItemField : : factionamt3 ] ) ;
item . FactionAmt4 = ( int32 ) atoul ( row [ ItemField : : factionamt4 ] ) ;
strcpy ( item . CharmFile , row [ ItemField : : charmfile ] ) ;
item . AugType = ( uint32 ) atoul ( row [ ItemField : : augtype ] ) ;
item . AugSlotType [ 0 ] = ( uint8 ) atoi ( row [ ItemField : : augslot1type ] ) ;
item . AugSlotVisible [ 0 ] = ( uint8 ) atoi ( row [ ItemField : : augslot1visible ] ) ;
item . AugSlotUnk2 [ 0 ] = 0 ;
item . AugSlotType [ 1 ] = ( uint8 ) atoi ( row [ ItemField : : augslot2type ] ) ;
item . AugSlotVisible [ 1 ] = ( uint8 ) atoi ( row [ ItemField : : augslot2visible ] ) ;
item . AugSlotUnk2 [ 1 ] = 0 ;
item . AugSlotType [ 2 ] = ( uint8 ) atoi ( row [ ItemField : : augslot3type ] ) ;
item . AugSlotVisible [ 2 ] = ( uint8 ) atoi ( row [ ItemField : : augslot3visible ] ) ;
item . AugSlotUnk2 [ 2 ] = 0 ;
item . AugSlotType [ 3 ] = ( uint8 ) atoi ( row [ ItemField : : augslot4type ] ) ;
item . AugSlotVisible [ 3 ] = ( uint8 ) atoi ( row [ ItemField : : augslot4visible ] ) ;
item . AugSlotUnk2 [ 3 ] = 0 ;
item . AugSlotType [ 4 ] = ( uint8 ) atoi ( row [ ItemField : : augslot5type ] ) ;
item . AugSlotVisible [ 4 ] = ( uint8 ) atoi ( row [ ItemField : : augslot5visible ] ) ;
item . AugSlotUnk2 [ 4 ] = 0 ;
2014-12-15 17:55:23 -06:00
item . AugSlotType [ 5 ] = ( uint8 ) atoi ( row [ ItemField : : augslot6type ] ) ;
item . AugSlotVisible [ 5 ] = ( uint8 ) atoi ( row [ ItemField : : augslot6visible ] ) ;
item . AugSlotUnk2 [ 5 ] = 0 ;
2014-10-04 14:06:37 -07:00
2015-12-21 12:33:32 -05:00
item . LDoNTheme = ( uint32 ) atoul ( row [ ItemField : : ldontheme ] ) ;
item . LDoNPrice = ( uint32 ) atoul ( row [ ItemField : : ldonprice ] ) ;
item . LDoNSold = ( uint32 ) atoul ( row [ ItemField : : ldonsold ] ) ;
item . BagType = ( uint8 ) atoi ( row [ ItemField : : bagtype ] ) ;
2015-12-29 15:22:09 -05:00
item . BagSlots = ( uint8 ) std : : min ( atoi ( row [ ItemField : : bagslots ] ) , 10 ) ; // FIXME: remove when big bags supported
2015-12-21 12:33:32 -05:00
item . BagSize = ( uint8 ) atoi ( row [ ItemField : : bagsize ] ) ;
item . BagWR = ( uint8 ) atoi ( row [ ItemField : : bagwr ] ) ;
item . Book = ( uint8 ) atoi ( row [ ItemField : : book ] ) ;
item . BookType = ( uint32 ) atoul ( row [ ItemField : : booktype ] ) ;
strcpy ( item . Filename , row [ ItemField : : filename ] ) ;
item . BaneDmgRaceAmt = ( uint32 ) atoul ( row [ ItemField : : banedmgraceamt ] ) ;
item . AugRestrict = ( uint32 ) atoul ( row [ ItemField : : augrestrict ] ) ;
item . LoreGroup = disableLoreGroup ? ( uint8 ) atoi ( " 0 " ) : atoi ( row [ ItemField : : loregroup ] ) ;
item . LoreFlag = item . LoreGroup ! = 0 ;
item . PendingLoreFlag = ( atoi ( row [ ItemField : : pendingloreflag ] ) = = 0 ) ? false : true ;
item . ArtifactFlag = ( atoi ( row [ ItemField : : artifactflag ] ) = = 0 ) ? false : true ;
item . SummonedFlag = ( atoi ( row [ ItemField : : summonedflag ] ) = = 0 ) ? false : true ;
item . Favor = ( uint32 ) atoul ( row [ ItemField : : favor ] ) ;
item . FVNoDrop = ( atoi ( row [ ItemField : : fvnodrop ] ) = = 0 ) ? false : true ;
item . Endur = ( uint32 ) atoul ( row [ ItemField : : endur ] ) ;
item . DotShielding = ( uint32 ) atoul ( row [ ItemField : : dotshielding ] ) ;
item . Attack = ( uint32 ) atoul ( row [ ItemField : : attack ] ) ;
item . Regen = ( uint32 ) atoul ( row [ ItemField : : regen ] ) ;
item . ManaRegen = ( uint32 ) atoul ( row [ ItemField : : manaregen ] ) ;
item . EnduranceRegen = ( uint32 ) atoul ( row [ ItemField : : enduranceregen ] ) ;
item . Haste = ( uint32 ) atoul ( row [ ItemField : : haste ] ) ;
item . DamageShield = ( uint32 ) atoul ( row [ ItemField : : damageshield ] ) ;
item . RecastDelay = ( uint32 ) atoul ( row [ ItemField : : recastdelay ] ) ;
item . RecastType = ( uint32 ) atoul ( row [ ItemField : : recasttype ] ) ;
item . GuildFavor = ( uint32 ) atoul ( row [ ItemField : : guildfavor ] ) ;
item . AugDistiller = ( uint32 ) atoul ( row [ ItemField : : augdistiller ] ) ;
item . Attuneable = ( atoi ( row [ ItemField : : attuneable ] ) = = 0 ) ? false : true ;
item . NoPet = ( atoi ( row [ ItemField : : nopet ] ) = = 0 ) ? false : true ;
item . PointType = ( uint32 ) atoul ( row [ ItemField : : pointtype ] ) ;
item . PotionBelt = ( atoi ( row [ ItemField : : potionbelt ] ) = = 0 ) ? false : true ;
item . PotionBeltSlots = ( atoi ( row [ ItemField : : potionbeltslots ] ) = = 0 ) ? false : true ;
item . StackSize = ( uint16 ) atoi ( row [ ItemField : : stacksize ] ) ;
item . NoTransfer = disableNoTransfer ? false : ( atoi ( row [ ItemField : : notransfer ] ) = = 0 ) ? false : true ;
item . Stackable = ( atoi ( row [ ItemField : : stackable ] ) = = 0 ) ? false : true ;
item . Click . Effect = ( uint32 ) atoul ( row [ ItemField : : clickeffect ] ) ;
item . Click . Type = ( uint8 ) atoul ( row [ ItemField : : clicktype ] ) ;
item . Click . Level = ( uint8 ) atoul ( row [ ItemField : : clicklevel ] ) ;
item . Click . Level2 = ( uint8 ) atoul ( row [ ItemField : : clicklevel2 ] ) ;
strcpy ( item . CharmFile , row [ ItemField : : charmfile ] ) ;
item . Proc . Effect = ( int32 ) atoul ( row [ ItemField : : proceffect ] ) ;
item . Proc . Type = ( uint8 ) atoul ( row [ ItemField : : proctype ] ) ;
item . Proc . Level = ( uint8 ) atoul ( row [ ItemField : : proclevel ] ) ;
item . Proc . Level2 = ( uint8 ) atoul ( row [ ItemField : : proclevel2 ] ) ;
item . Worn . Effect = ( int32 ) atoul ( row [ ItemField : : worneffect ] ) ;
item . Worn . Type = ( uint8 ) atoul ( row [ ItemField : : worntype ] ) ;
item . Worn . Level = ( uint8 ) atoul ( row [ ItemField : : wornlevel ] ) ;
item . Worn . Level2 = ( uint8 ) atoul ( row [ ItemField : : wornlevel2 ] ) ;
item . Focus . Effect = ( int32 ) atoul ( row [ ItemField : : focuseffect ] ) ;
item . Focus . Type = ( uint8 ) atoul ( row [ ItemField : : focustype ] ) ;
item . Focus . Level = ( uint8 ) atoul ( row [ ItemField : : focuslevel ] ) ;
item . Focus . Level2 = ( uint8 ) atoul ( row [ ItemField : : focuslevel2 ] ) ;
item . Scroll . Effect = ( int32 ) atoul ( row [ ItemField : : scrolleffect ] ) ;
item . Scroll . Type = ( uint8 ) atoul ( row [ ItemField : : scrolltype ] ) ;
item . Scroll . Level = ( uint8 ) atoul ( row [ ItemField : : scrolllevel ] ) ;
item . Scroll . Level2 = ( uint8 ) atoul ( row [ ItemField : : scrolllevel2 ] ) ;
item . Bard . Effect = ( int32 ) atoul ( row [ ItemField : : bardeffect ] ) ;
item . Bard . Type = ( uint8 ) atoul ( row [ ItemField : : bardtype ] ) ;
item . Bard . Level = ( uint8 ) atoul ( row [ ItemField : : bardlevel ] ) ;
item . Bard . Level2 = ( uint8 ) atoul ( row [ ItemField : : bardlevel2 ] ) ;
item . QuestItemFlag = ( atoi ( row [ ItemField : : questitemflag ] ) = = 0 ) ? false : true ;
item . SVCorruption = ( int32 ) atoi ( row [ ItemField : : svcorruption ] ) ;
item . Purity = ( uint32 ) atoul ( row [ ItemField : : purity ] ) ;
2015-12-21 05:27:20 -08:00
item . EvolvingItem = ( uint8 ) atoul ( row [ ItemField : : evoitem ] ) ;
item . EvolvingID = ( uint8 ) atoul ( row [ ItemField : : evoid ] ) ;
2015-12-21 12:33:32 -05:00
item . EvolvingLevel = ( uint8 ) atoul ( row [ ItemField : : evolvinglevel ] ) ;
2015-12-21 05:27:20 -08:00
item . EvolvingMax = ( uint8 ) atoul ( row [ ItemField : : evomax ] ) ;
2015-12-21 12:33:32 -05:00
item . BackstabDmg = ( uint32 ) atoul ( row [ ItemField : : backstabdmg ] ) ;
item . DSMitigation = ( uint32 ) atoul ( row [ ItemField : : dsmitigation ] ) ;
item . HeroicStr = ( int32 ) atoi ( row [ ItemField : : heroic_str ] ) ;
item . HeroicInt = ( int32 ) atoi ( row [ ItemField : : heroic_int ] ) ;
item . HeroicWis = ( int32 ) atoi ( row [ ItemField : : heroic_wis ] ) ;
item . HeroicAgi = ( int32 ) atoi ( row [ ItemField : : heroic_agi ] ) ;
item . HeroicDex = ( int32 ) atoi ( row [ ItemField : : heroic_dex ] ) ;
item . HeroicSta = ( int32 ) atoi ( row [ ItemField : : heroic_sta ] ) ;
item . HeroicCha = ( int32 ) atoi ( row [ ItemField : : heroic_cha ] ) ;
item . HeroicMR = ( int32 ) atoi ( row [ ItemField : : heroic_mr ] ) ;
item . HeroicFR = ( int32 ) atoi ( row [ ItemField : : heroic_fr ] ) ;
item . HeroicCR = ( int32 ) atoi ( row [ ItemField : : heroic_cr ] ) ;
item . HeroicDR = ( int32 ) atoi ( row [ ItemField : : heroic_dr ] ) ;
item . HeroicPR = ( int32 ) atoi ( row [ ItemField : : heroic_pr ] ) ;
item . HeroicSVCorrup = ( int32 ) atoi ( row [ ItemField : : heroic_svcorrup ] ) ;
item . HealAmt = ( int32 ) atoi ( row [ ItemField : : healamt ] ) ;
item . SpellDmg = ( int32 ) atoi ( row [ ItemField : : spelldmg ] ) ;
item . LDoNSellBackRate = ( uint32 ) atoul ( row [ ItemField : : ldonsellbackrate ] ) ;
item . ScriptFileID = ( uint32 ) atoul ( row [ ItemField : : scriptfileid ] ) ;
item . ExpendableArrow = ( uint16 ) atoul ( row [ ItemField : : expendablearrow ] ) ;
item . Clairvoyance = ( uint32 ) atoul ( row [ ItemField : : clairvoyance ] ) ;
strcpy ( item . ClickName , row [ ItemField : : clickname ] ) ;
strcpy ( item . ProcName , row [ ItemField : : procname ] ) ;
strcpy ( item . WornName , row [ ItemField : : wornname ] ) ;
strcpy ( item . FocusName , row [ ItemField : : focusname ] ) ;
strcpy ( item . ScrollName , row [ ItemField : : scrollname ] ) ;
try {
hash . insert ( item . ID , item ) ;
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Database::LoadItems: %s " , ex . what ( ) ) ;
2015-12-21 12:33:32 -05:00
break ;
}
}
2013-02-16 16:14:39 -08:00
}
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemData * SharedDatabase : : GetItem ( uint32 id ) {
2014-12-13 13:53:55 -06:00
if ( id = = 0 )
{
return nullptr ;
}
if ( ! items_hash | | id > items_hash - > max_key ( ) )
{
2013-05-09 10:44:08 -04:00
return nullptr ;
}
2013-02-16 16:14:39 -08:00
2014-12-13 13:53:55 -06:00
if ( items_hash - > exists ( id ) )
{
2013-05-09 10:44:08 -04:00
return & ( items_hash - > at ( id ) ) ;
}
2013-02-20 22:36:30 -08:00
2013-05-09 10:44:08 -04:00
return nullptr ;
2013-02-16 16:14:39 -08:00
}
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemData * SharedDatabase : : IterateItems ( uint32 * id ) {
2013-05-09 10:44:08 -04:00
if ( ! items_hash | | ! id ) {
return nullptr ;
}
for ( ; ; ) {
if ( * id > items_hash - > max_key ( ) ) {
break ;
}
if ( items_hash - > exists ( * id ) ) {
return & ( items_hash - > at ( ( * id ) + + ) ) ;
} else {
+ + ( * id ) ;
}
}
return nullptr ;
2013-02-20 22:36:30 -08:00
}
2013-02-16 16:14:39 -08:00
2017-01-10 20:18:16 -05:00
std : : string SharedDatabase : : GetBook ( const char * txtfile , int16 * language )
2013-02-16 16:14:39 -08:00
{
char txtfile2 [ 20 ] ;
2013-05-22 16:17:19 -04:00
std : : string txtout ;
2014-10-04 14:07:55 -07:00
strcpy ( txtfile2 , txtfile ) ;
2017-01-10 20:18:16 -05:00
std : : string query = StringFormat ( " SELECT txtfile, language FROM books WHERE name = '%s' " , txtfile2 ) ;
2014-10-04 14:07:55 -07:00
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
txtout . assign ( " " , 1 ) ;
return txtout ;
}
2014-10-04 14:07:55 -07:00
if ( results . RowCount ( ) = = 0 ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " No book to send, (%s) " , txtfile ) ;
2014-10-04 14:07:55 -07:00
txtout . assign ( " " , 1 ) ;
return txtout ;
}
auto row = results . begin ( ) ;
txtout . assign ( row [ 0 ] , strlen ( row [ 0 ] ) ) ;
2017-01-10 20:18:16 -05:00
* language = static_cast < int16 > ( atoi ( row [ 1 ] ) ) ;
2014-10-04 14:07:55 -07:00
return txtout ;
2013-02-16 16:14:39 -08:00
}
2013-02-23 13:45:19 -08:00
void SharedDatabase : : GetFactionListInfo ( uint32 & list_count , uint32 & max_lists ) {
2013-05-09 10:44:08 -04:00
list_count = 0 ;
max_lists = 0 ;
2014-10-04 14:08:53 -07:00
const std : : string query = " SELECT COUNT(*), MAX(id) FROM npc_faction " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
2013-05-09 10:44:08 -04:00
}
2014-10-04 14:08:53 -07:00
if ( results . RowCount ( ) = = 0 )
return ;
auto row = results . begin ( ) ;
list_count = static_cast < uint32 > ( atoul ( row [ 0 ] ) ) ;
2015-02-10 11:53:16 -08:00
max_lists = static_cast < uint32 > ( atoul ( row [ 1 ] ? row [ 1 ] : " 0 " ) ) ;
2013-02-16 16:14:39 -08:00
}
const NPCFactionList * SharedDatabase : : GetNPCFactionEntry ( uint32 id ) {
2013-02-23 13:45:19 -08:00
if ( ! faction_hash ) {
2013-05-09 10:44:08 -04:00
return nullptr ;
}
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
if ( faction_hash - > exists ( id ) ) {
return & ( faction_hash - > at ( id ) ) ;
}
2013-02-23 13:45:19 -08:00
2013-05-09 10:44:08 -04:00
return nullptr ;
2013-02-16 16:14:39 -08:00
}
2013-02-23 13:45:19 -08:00
void SharedDatabase : : LoadNPCFactionLists ( void * data , uint32 size , uint32 list_count , uint32 max_lists ) {
2013-05-09 10:44:08 -04:00
EQEmu : : FixedMemoryHashSet < NPCFactionList > hash ( reinterpret_cast < uint8 * > ( data ) , size , list_count , max_lists ) ;
NPCFactionList faction ;
2014-10-04 14:10:00 -07:00
const std : : string query = " SELECT npc_faction.id, npc_faction.primaryfaction, npc_faction.ignore_primary_assist, "
" npc_faction_entries.faction_id, npc_faction_entries.value, npc_faction_entries.npc_value, "
" npc_faction_entries.temp FROM npc_faction LEFT JOIN npc_faction_entries "
" ON npc_faction.id = npc_faction_entries.npc_faction_id ORDER BY npc_faction.id; " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
uint32 current_id = 0 ;
uint32 current_entry = 0 ;
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
uint32 id = static_cast < uint32 > ( atoul ( row [ 0 ] ) ) ;
if ( id ! = current_id ) {
if ( current_id ! = 0 ) {
hash . insert ( current_id , faction ) ;
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:10:00 -07:00
memset ( & faction , 0 , sizeof ( faction ) ) ;
current_entry = 0 ;
current_id = id ;
faction . id = id ;
faction . primaryfaction = static_cast < uint32 > ( atoul ( row [ 1 ] ) ) ;
faction . assistprimaryfaction = ( atoi ( row [ 2 ] ) = = 0 ) ;
}
if ( ! row [ 3 ] )
continue ;
if ( current_entry > = MAX_NPC_FACTIONS )
2013-05-09 10:44:08 -04:00
continue ;
2014-10-04 14:10:00 -07:00
faction . factionid [ current_entry ] = static_cast < uint32 > ( atoul ( row [ 3 ] ) ) ;
faction . factionvalue [ current_entry ] = static_cast < int32 > ( atoi ( row [ 4 ] ) ) ;
faction . factionnpcvalue [ current_entry ] = static_cast < int8 > ( atoi ( row [ 5 ] ) ) ;
faction . factiontemp [ current_entry ] = static_cast < uint8 > ( atoi ( row [ 6 ] ) ) ;
+ + current_entry ;
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:10:00 -07:00
if ( current_id ! = 0 )
hash . insert ( current_id , faction ) ;
2013-05-09 10:44:08 -04:00
2013-02-23 13:45:19 -08:00
}
2015-06-23 17:39:06 -07:00
bool SharedDatabase : : LoadNPCFactionLists ( const std : : string & prefix ) {
faction_mmf . reset ( nullptr ) ;
faction_hash . reset ( nullptr ) ;
2013-05-09 10:44:08 -04:00
try {
2016-05-24 23:49:25 -07:00
auto Config = EQEmuConfig : : get ( ) ;
2013-05-09 10:44:08 -04:00
EQEmu : : IPCMutex mutex ( " faction " ) ;
mutex . Lock ( ) ;
2016-05-20 21:03:34 -05:00
std : : string file_name = Config - > SharedMemDir + prefix + std : : string ( " faction " ) ;
2015-06-23 17:39:06 -07:00
faction_mmf = std : : unique_ptr < EQEmu : : MemoryMappedFile > ( new EQEmu : : MemoryMappedFile ( file_name ) ) ;
faction_hash = std : : unique_ptr < EQEmu : : FixedMemoryHashSet < NPCFactionList > > ( new EQEmu : : FixedMemoryHashSet < NPCFactionList > ( reinterpret_cast < uint8 * > ( faction_mmf - > Get ( ) ) , faction_mmf - > Size ( ) ) ) ;
2013-05-09 10:44:08 -04:00
mutex . Unlock ( ) ;
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error Loading npc factions: %s " , ex . what ( ) ) ;
2013-05-09 10:44:08 -04:00
return false ;
}
return true ;
2013-02-16 16:14:39 -08:00
}
2016-10-16 05:10:54 -04:00
// Create appropriate EQEmu::ItemInstance class
EQEmu : : ItemInstance * SharedDatabase : : CreateItem ( uint32 item_id , int16 charges , uint32 aug1 , uint32 aug2 , uint32 aug3 , uint32 aug4 , uint32 aug5 , uint32 aug6 , uint8 attuned )
2013-02-16 16:14:39 -08:00
{
2016-10-16 05:10:54 -04:00
const EQEmu : : ItemData * item = nullptr ;
EQEmu : : ItemInstance * inst = nullptr ;
2014-12-23 10:14:45 -05:00
2013-02-16 16:14:39 -08:00
item = GetItem ( item_id ) ;
if ( item ) {
inst = CreateBaseItem ( item , charges ) ;
2014-12-23 10:14:45 -05:00
if ( inst = = nullptr ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem() " ) ;
Log ( Logs : : General , Logs : : Error , " Item Data = ID: %u, Name: %s, Charges: %i " , item - > ID , item - > Name , charges ) ;
2014-12-23 10:14:45 -05:00
return nullptr ;
}
2013-02-16 16:14:39 -08:00
inst - > PutAugment ( this , 0 , aug1 ) ;
inst - > PutAugment ( this , 1 , aug2 ) ;
inst - > PutAugment ( this , 2 , aug3 ) ;
inst - > PutAugment ( this , 3 , aug4 ) ;
inst - > PutAugment ( this , 4 , aug5 ) ;
2014-12-15 17:55:23 -06:00
inst - > PutAugment ( this , 5 , aug6 ) ;
inst - > SetAttuned ( attuned ) ;
2013-02-16 16:14:39 -08:00
}
return inst ;
}
2016-10-16 05:10:54 -04:00
// Create appropriate EQEmu::ItemInstance class
EQEmu : : ItemInstance * SharedDatabase : : CreateItem ( const EQEmu : : ItemData * item , int16 charges , uint32 aug1 , uint32 aug2 , uint32 aug3 , uint32 aug4 , uint32 aug5 , uint32 aug6 , uint8 attuned )
2013-02-16 16:14:39 -08:00
{
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * inst = nullptr ;
2013-02-16 16:14:39 -08:00
if ( item ) {
inst = CreateBaseItem ( item , charges ) ;
2014-12-23 10:14:45 -05:00
if ( inst = = nullptr ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem() " ) ;
Log ( Logs : : General , Logs : : Error , " Item Data = ID: %u, Name: %s, Charges: %i " , item - > ID , item - > Name , charges ) ;
2014-12-23 10:14:45 -05:00
return nullptr ;
}
2013-02-16 16:14:39 -08:00
inst - > PutAugment ( this , 0 , aug1 ) ;
inst - > PutAugment ( this , 1 , aug2 ) ;
inst - > PutAugment ( this , 2 , aug3 ) ;
inst - > PutAugment ( this , 3 , aug4 ) ;
inst - > PutAugment ( this , 4 , aug5 ) ;
2014-12-15 17:55:23 -06:00
inst - > PutAugment ( this , 5 , aug6 ) ;
inst - > SetAttuned ( attuned ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
return inst ;
}
2016-10-16 05:10:54 -04:00
EQEmu : : ItemInstance * SharedDatabase : : CreateBaseItem ( const EQEmu : : ItemData * item , int16 charges ) {
EQEmu : : ItemInstance * inst = nullptr ;
2013-02-16 16:14:39 -08:00
if ( item ) {
2013-05-06 13:07:41 -04:00
// if maxcharges is -1 that means it is an unlimited use item.
2013-02-16 16:14:39 -08:00
// set it to 1 charge so that it is usable on creation
if ( charges = = 0 & & item - > MaxCharges = = - 1 )
charges = 1 ;
2014-12-17 00:24:47 +01:00
// Stackable items need a minimum charge of 1 to remain moveable.
if ( charges < = 0 & & item - > Stackable )
charges = 1 ;
2013-02-16 16:14:39 -08:00
2016-10-16 05:10:54 -04:00
inst = new EQEmu : : ItemInstance ( item , charges ) ;
2013-06-22 01:32:41 -07:00
2014-12-23 10:14:45 -05:00
if ( inst = = nullptr ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateBaseItem() " ) ;
Log ( Logs : : General , Logs : : Error , " Item Data = ID: %u, Name: %s, Charges: %i " , item - > ID , item - > Name , charges ) ;
2014-12-23 10:14:45 -05:00
return nullptr ;
}
2013-02-16 16:14:39 -08:00
if ( item - > CharmFileID ! = 0 | | ( item - > LoreGroup > = 1000 & & item - > LoreGroup ! = - 1 ) ) {
2013-06-22 01:32:41 -07:00
inst - > Initialize ( this ) ;
2013-02-16 16:14:39 -08:00
}
}
return inst ;
}
int32 SharedDatabase : : DeleteStalePlayerCorpses ( ) {
2014-11-23 23:46:06 -06:00
if ( RuleB ( Zone , EnableShadowrest ) ) {
std : : string query = StringFormat (
" UPDATE `character_corpses` SET `is_buried` = 1 WHERE `is_buried` = 0 AND "
" (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) > %d AND NOT time_of_death = 0 " ,
( RuleI ( Character , CorpseDecayTimeMS ) / 1000 ) ) ;
2014-10-04 14:10:57 -07:00
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) )
2013-02-16 16:14:39 -08:00
return - 1 ;
2014-10-04 14:10:57 -07:00
return results . RowsAffected ( ) ;
2013-02-16 16:14:39 -08:00
}
2014-11-23 23:46:06 -06:00
std : : string query = StringFormat (
" DELETE FROM `character_corpses` WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) > %d "
" AND NOT time_of_death = 0 " , ( RuleI ( Character , CorpseDecayTimeMS ) / 1000 ) ) ;
2014-10-04 14:10:57 -07:00
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) )
return - 1 ;
return results . RowsAffected ( ) ;
2013-02-16 16:14:39 -08:00
}
2015-12-07 19:28:13 -05:00
bool SharedDatabase : : GetCommandSettings ( std : : map < std : : string , std : : pair < uint8 , std : : vector < std : : string > > > & command_settings )
{
command_settings . clear ( ) ;
2014-10-04 14:12:16 -07:00
2015-12-07 19:28:13 -05:00
std : : string query = " SELECT `command`, `access`, `aliases` FROM `command_settings` " ;
2014-10-04 14:12:16 -07:00
auto results = QueryDatabase ( query ) ;
2015-12-07 19:28:13 -05:00
if ( ! results . Success ( ) )
2013-02-16 16:14:39 -08:00
return false ;
2015-12-07 19:28:13 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
command_settings [ row [ 0 ] ] . first = atoi ( row [ 1 ] ) ;
if ( row [ 2 ] [ 0 ] = = 0 )
continue ;
2014-10-04 14:12:16 -07:00
2015-12-07 19:28:13 -05:00
std : : vector < std : : string > aliases = SplitString ( row [ 2 ] , ' | ' ) ;
2016-05-25 16:10:28 -04:00
for ( auto iter = aliases . begin ( ) ; iter ! = aliases . end ( ) ; + + iter ) {
2015-12-07 19:28:13 -05:00
if ( iter - > empty ( ) )
continue ;
command_settings [ row [ 0 ] ] . second . push_back ( * iter ) ;
}
}
2014-10-04 14:12:16 -07:00
return true ;
2013-02-16 16:14:39 -08:00
}
2015-06-23 17:39:06 -07:00
bool SharedDatabase : : LoadSkillCaps ( const std : : string & prefix ) {
skill_caps_mmf . reset ( nullptr ) ;
2013-02-20 13:54:26 -08:00
uint32 class_count = PLAYER_CLASS_COUNT ;
2016-05-25 18:50:26 -04:00
uint32 skill_count = EQEmu : : skills : : HIGHEST_SKILL + 1 ;
2013-02-20 13:54:26 -08:00
uint32 level_count = HARD_LEVEL_CAP + 1 ;
2013-05-09 10:44:08 -04:00
uint32 size = ( class_count * skill_count * level_count * sizeof ( uint16 ) ) ;
try {
2016-05-24 23:49:25 -07:00
auto Config = EQEmuConfig : : get ( ) ;
2013-05-09 10:44:08 -04:00
EQEmu : : IPCMutex mutex ( " skill_caps " ) ;
mutex . Lock ( ) ;
2016-05-20 21:03:34 -05:00
std : : string file_name = Config - > SharedMemDir + prefix + std : : string ( " skill_caps " ) ;
2015-06-23 17:39:06 -07:00
skill_caps_mmf = std : : unique_ptr < EQEmu : : MemoryMappedFile > ( new EQEmu : : MemoryMappedFile ( file_name ) ) ;
2013-05-09 10:44:08 -04:00
mutex . Unlock ( ) ;
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error loading skill caps: %s " , ex . what ( ) ) ;
2013-05-09 10:44:08 -04:00
return false ;
}
return true ;
2013-02-20 13:54:26 -08:00
}
void SharedDatabase : : LoadSkillCaps ( void * data ) {
2013-05-09 10:44:08 -04:00
uint32 class_count = PLAYER_CLASS_COUNT ;
2016-05-25 18:50:26 -04:00
uint32 skill_count = EQEmu : : skills : : HIGHEST_SKILL + 1 ;
2013-02-20 13:54:26 -08:00
uint32 level_count = HARD_LEVEL_CAP + 1 ;
2013-05-09 10:44:08 -04:00
uint16 * skill_caps_table = reinterpret_cast < uint16 * > ( data ) ;
2013-02-20 13:54:26 -08:00
2014-10-04 14:13:05 -07:00
const std : : string query = " SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error loading skill caps from database: %s " , results . ErrorMessage ( ) . c_str ( ) ) ;
2014-10-04 14:13:05 -07:00
return ;
2013-05-09 10:44:08 -04:00
}
2014-10-04 14:13:05 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
uint8 skillID = atoi ( row [ 0 ] ) ;
uint8 class_ = atoi ( row [ 1 ] ) - 1 ;
uint8 level = atoi ( row [ 2 ] ) ;
uint16 cap = atoi ( row [ 3 ] ) ;
if ( skillID > = skill_count | | class_ > = class_count | | level > = level_count )
continue ;
uint32 index = ( ( ( class_ * skill_count ) + skillID ) * level_count ) + level ;
skill_caps_table [ index ] = cap ;
}
2013-02-16 16:14:39 -08:00
}
2016-05-25 18:50:26 -04:00
uint16 SharedDatabase : : GetSkillCap ( uint8 Class_ , EQEmu : : skills : : SkillType Skill , uint8 Level ) {
2013-05-09 10:44:08 -04:00
if ( ! skill_caps_mmf ) {
return 0 ;
}
2013-02-20 13:54:26 -08:00
2013-05-09 10:44:08 -04:00
if ( Class_ = = 0 )
return 0 ;
2013-02-20 13:54:26 -08:00
2013-05-09 10:44:08 -04:00
int SkillMaxLevel = RuleI ( Character , SkillCapMaxLevel ) ;
if ( SkillMaxLevel < 1 ) {
SkillMaxLevel = RuleI ( Character , MaxLevel ) ;
}
2013-02-20 13:54:26 -08:00
2013-05-09 10:44:08 -04:00
uint32 class_count = PLAYER_CLASS_COUNT ;
2016-05-25 18:50:26 -04:00
uint32 skill_count = EQEmu : : skills : : HIGHEST_SKILL + 1 ;
2013-02-20 13:54:26 -08:00
uint32 level_count = HARD_LEVEL_CAP + 1 ;
2013-05-09 10:44:08 -04:00
if ( Class_ > class_count | | static_cast < uint32 > ( Skill ) > skill_count | | Level > level_count ) {
return 0 ;
}
2013-02-20 22:36:30 -08:00
2013-05-09 10:44:08 -04:00
if ( Level > static_cast < uint8 > ( SkillMaxLevel ) ) {
Level = static_cast < uint8 > ( SkillMaxLevel ) ;
}
2013-02-20 13:54:26 -08:00
2013-05-09 10:44:08 -04:00
uint32 index = ( ( ( ( Class_ - 1 ) * skill_count ) + Skill ) * level_count ) + Level ;
uint16 * skill_caps_table = reinterpret_cast < uint16 * > ( skill_caps_mmf - > Get ( ) ) ;
return skill_caps_table [ index ] ;
2013-02-16 16:14:39 -08:00
}
2016-05-25 18:50:26 -04:00
uint8 SharedDatabase : : GetTrainLevel ( uint8 Class_ , EQEmu : : skills : : SkillType Skill , uint8 Level ) {
2013-05-09 10:44:08 -04:00
if ( ! skill_caps_mmf ) {
return 0 ;
}
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
if ( Class_ = = 0 )
return 0 ;
2013-02-20 13:54:26 -08:00
2013-05-09 10:44:08 -04:00
int SkillMaxLevel = RuleI ( Character , SkillCapMaxLevel ) ;
if ( SkillMaxLevel < 1 ) {
SkillMaxLevel = RuleI ( Character , MaxLevel ) ;
}
2013-02-20 13:54:26 -08:00
2013-05-09 10:44:08 -04:00
uint32 class_count = PLAYER_CLASS_COUNT ;
2016-05-25 18:50:26 -04:00
uint32 skill_count = EQEmu : : skills : : HIGHEST_SKILL + 1 ;
2013-02-20 13:54:26 -08:00
uint32 level_count = HARD_LEVEL_CAP + 1 ;
2013-05-09 10:44:08 -04:00
if ( Class_ > class_count | | static_cast < uint32 > ( Skill ) > skill_count | | Level > level_count ) {
return 0 ;
}
2013-05-06 13:07:41 -04:00
2013-05-09 10:44:08 -04:00
uint8 ret = 0 ;
2013-02-20 13:54:26 -08:00
if ( Level > static_cast < uint8 > ( SkillMaxLevel ) ) {
2013-05-09 10:44:08 -04:00
uint32 index = ( ( ( ( Class_ - 1 ) * skill_count ) + Skill ) * level_count ) ;
uint16 * skill_caps_table = reinterpret_cast < uint16 * > ( skill_caps_mmf - > Get ( ) ) ;
for ( uint8 x = 0 ; x < Level ; x + + ) {
if ( skill_caps_table [ index + x ] ) {
ret = x ;
break ;
}
}
2013-02-16 16:14:39 -08:00
}
else
{
2013-05-09 10:44:08 -04:00
uint32 index = ( ( ( ( Class_ - 1 ) * skill_count ) + Skill ) * level_count ) ;
uint16 * skill_caps_table = reinterpret_cast < uint16 * > ( skill_caps_mmf - > Get ( ) ) ;
for ( int x = 0 ; x < SkillMaxLevel ; x + + ) {
if ( skill_caps_table [ index + x ] ) {
ret = x ;
break ;
}
}
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-05-09 10:44:08 -04:00
if ( ret > GetSkillCap ( Class_ , Skill , Level ) )
ret = static_cast < uint8 > ( GetSkillCap ( Class_ , Skill , Level ) ) ;
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
return ret ;
2013-02-16 16:14:39 -08:00
}
2013-02-20 13:54:26 -08:00
void SharedDatabase : : LoadDamageShieldTypes ( SPDat_Spell_Struct * sp , int32 iMaxSpellID ) {
2013-02-16 16:14:39 -08:00
2014-10-04 14:14:27 -07:00
std : : string query = StringFormat ( " SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 "
" AND `spellid` <= %i " , iMaxSpellID ) ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
2013-02-16 16:14:39 -08:00
2014-10-04 14:14:27 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
int spellID = atoi ( row [ 0 ] ) ;
if ( ( spellID > 0 ) & & ( spellID < = iMaxSpellID ) )
sp [ spellID ] . DamageShieldType = atoi ( row [ 1 ] ) ;
}
2013-02-16 16:14:39 -08:00
}
const EvolveInfo * SharedDatabase : : GetEvolveInfo ( uint32 loregroup ) {
2013-05-04 18:06:58 -07:00
return nullptr ; // nothing here for now... database and/or sharemem pulls later
2013-02-16 16:14:39 -08:00
}
2013-02-19 16:50:05 -08:00
int SharedDatabase : : GetMaxSpellID ( ) {
2014-10-04 14:16:00 -07:00
std : : string query = " SELECT MAX(id) FROM spells_new " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return - 1 ;
}
auto row = results . begin ( ) ;
return atoi ( row [ 0 ] ) ;
2013-02-19 16:50:05 -08:00
}
2015-06-23 17:39:06 -07:00
bool SharedDatabase : : LoadSpells ( const std : : string & prefix , int32 * records , const SPDat_Spell_Struct * * sp ) {
spells_mmf . reset ( nullptr ) ;
try {
2016-05-24 23:49:25 -07:00
auto Config = EQEmuConfig : : get ( ) ;
2015-06-23 17:39:06 -07:00
EQEmu : : IPCMutex mutex ( " spells " ) ;
mutex . Lock ( ) ;
2016-05-20 21:03:34 -05:00
std : : string file_name = Config - > SharedMemDir + prefix + std : : string ( " spells " ) ;
2015-06-23 17:39:06 -07:00
spells_mmf = std : : unique_ptr < EQEmu : : MemoryMappedFile > ( new EQEmu : : MemoryMappedFile ( file_name ) ) ;
* records = * reinterpret_cast < uint32 * > ( spells_mmf - > Get ( ) ) ;
* sp = reinterpret_cast < const SPDat_Spell_Struct * > ( ( char * ) spells_mmf - > Get ( ) + 4 ) ;
mutex . Unlock ( ) ;
}
catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error Loading Spells: %s " , ex . what ( ) ) ;
2015-06-23 17:39:06 -07:00
return false ;
}
return true ;
}
2013-02-19 16:50:05 -08:00
void SharedDatabase : : LoadSpells ( void * data , int max_spells ) {
2015-06-23 17:39:06 -07:00
* ( uint32 * ) data = max_spells ;
SPDat_Spell_Struct * sp = reinterpret_cast < SPDat_Spell_Struct * > ( ( char * ) data + sizeof ( uint32 ) ) ;
2014-08-28 03:47:28 -07:00
2014-10-04 14:16:54 -07:00
const std : : string query = " SELECT * FROM spells_new ORDER BY id ASC " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
2013-05-06 13:07:41 -04:00
2014-10-04 14:16:54 -07:00
if ( results . ColumnCount ( ) < = SPELL_LOAD_FIELD_COUNT ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : Detail , Logs : : Spells , " Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT(%u) " , SPELL_LOAD_FIELD_COUNT ) ;
2014-10-04 14:16:54 -07:00
return ;
}
2014-08-28 03:47:28 -07:00
2014-10-04 14:16:54 -07:00
int tempid = 0 ;
int counter = 0 ;
2014-08-28 03:47:28 -07:00
2014-10-04 14:16:54 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
tempid = atoi ( row [ 0 ] ) ;
if ( tempid > = max_spells ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : Detail , Logs : : Spells , " Non fatal error: spell.id >= max_spells, ignoring. " ) ;
2014-10-04 14:16:54 -07:00
continue ;
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:16:54 -07:00
+ + counter ;
sp [ tempid ] . id = tempid ;
strn0cpy ( sp [ tempid ] . name , row [ 1 ] , sizeof ( sp [ tempid ] . name ) ) ;
strn0cpy ( sp [ tempid ] . player_1 , row [ 2 ] , sizeof ( sp [ tempid ] . player_1 ) ) ;
strn0cpy ( sp [ tempid ] . teleport_zone , row [ 3 ] , sizeof ( sp [ tempid ] . teleport_zone ) ) ;
strn0cpy ( sp [ tempid ] . you_cast , row [ 4 ] , sizeof ( sp [ tempid ] . you_cast ) ) ;
strn0cpy ( sp [ tempid ] . other_casts , row [ 5 ] , sizeof ( sp [ tempid ] . other_casts ) ) ;
strn0cpy ( sp [ tempid ] . cast_on_you , row [ 6 ] , sizeof ( sp [ tempid ] . cast_on_you ) ) ;
strn0cpy ( sp [ tempid ] . cast_on_other , row [ 7 ] , sizeof ( sp [ tempid ] . cast_on_other ) ) ;
strn0cpy ( sp [ tempid ] . spell_fades , row [ 8 ] , sizeof ( sp [ tempid ] . spell_fades ) ) ;
sp [ tempid ] . range = static_cast < float > ( atof ( row [ 9 ] ) ) ;
sp [ tempid ] . aoerange = static_cast < float > ( atof ( row [ 10 ] ) ) ;
sp [ tempid ] . pushback = static_cast < float > ( atof ( row [ 11 ] ) ) ;
sp [ tempid ] . pushup = static_cast < float > ( atof ( row [ 12 ] ) ) ;
sp [ tempid ] . cast_time = atoi ( row [ 13 ] ) ;
sp [ tempid ] . recovery_time = atoi ( row [ 14 ] ) ;
sp [ tempid ] . recast_time = atoi ( row [ 15 ] ) ;
sp [ tempid ] . buffdurationformula = atoi ( row [ 16 ] ) ;
sp [ tempid ] . buffduration = atoi ( row [ 17 ] ) ;
sp [ tempid ] . AEDuration = atoi ( row [ 18 ] ) ;
sp [ tempid ] . mana = atoi ( row [ 19 ] ) ;
int y = 0 ;
for ( y = 0 ; y < EFFECT_COUNT ; y + + )
sp [ tempid ] . base [ y ] = atoi ( row [ 20 + y ] ) ; // effect_base_value
for ( y = 0 ; y < EFFECT_COUNT ; y + + )
sp [ tempid ] . base2 [ y ] = atoi ( row [ 32 + y ] ) ; // effect_limit_value
for ( y = 0 ; y < EFFECT_COUNT ; y + + )
sp [ tempid ] . max [ y ] = atoi ( row [ 44 + y ] ) ;
for ( y = 0 ; y < 4 ; y + + )
sp [ tempid ] . components [ y ] = atoi ( row [ 58 + y ] ) ;
for ( y = 0 ; y < 4 ; y + + )
sp [ tempid ] . component_counts [ y ] = atoi ( row [ 62 + y ] ) ;
for ( y = 0 ; y < 4 ; y + + )
sp [ tempid ] . NoexpendReagent [ y ] = atoi ( row [ 66 + y ] ) ;
for ( y = 0 ; y < EFFECT_COUNT ; y + + )
sp [ tempid ] . formula [ y ] = atoi ( row [ 70 + y ] ) ;
sp [ tempid ] . goodEffect = atoi ( row [ 83 ] ) ;
sp [ tempid ] . Activated = atoi ( row [ 84 ] ) ;
sp [ tempid ] . resisttype = atoi ( row [ 85 ] ) ;
for ( y = 0 ; y < EFFECT_COUNT ; y + + )
sp [ tempid ] . effectid [ y ] = atoi ( row [ 86 + y ] ) ;
sp [ tempid ] . targettype = ( SpellTargetType ) atoi ( row [ 98 ] ) ;
sp [ tempid ] . basediff = atoi ( row [ 99 ] ) ;
int tmp_skill = atoi ( row [ 100 ] ) ; ;
2016-05-25 18:50:26 -04:00
if ( tmp_skill < 0 | | tmp_skill > EQEmu : : skills : : HIGHEST_SKILL )
sp [ tempid ] . skill = EQEmu : : skills : : SkillBegging ; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated
2014-10-04 14:16:54 -07:00
else
2016-05-25 18:50:26 -04:00
sp [ tempid ] . skill = ( EQEmu : : skills : : SkillType ) tmp_skill ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . zonetype = atoi ( row [ 101 ] ) ;
sp [ tempid ] . EnvironmentType = atoi ( row [ 102 ] ) ;
sp [ tempid ] . TimeOfDay = atoi ( row [ 103 ] ) ;
for ( y = 0 ; y < PLAYER_CLASS_COUNT ; y + + )
sp [ tempid ] . classes [ y ] = atoi ( row [ 104 + y ] ) ;
sp [ tempid ] . CastingAnim = atoi ( row [ 120 ] ) ;
sp [ tempid ] . SpellAffectIndex = atoi ( row [ 123 ] ) ;
sp [ tempid ] . disallow_sit = atoi ( row [ 124 ] ) ;
2014-11-14 00:23:26 -05:00
sp [ tempid ] . diety_agnostic = atoi ( row [ 125 ] ) ;
2014-10-04 14:16:54 -07:00
for ( y = 0 ; y < 16 ; y + + )
sp [ tempid ] . deities [ y ] = atoi ( row [ 126 + y ] ) ;
2017-07-14 02:05:35 -04:00
sp [ tempid ] . new_icon = atoi ( row [ 144 ] ) ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . uninterruptable = atoi ( row [ 146 ] ) ! = 0 ;
sp [ tempid ] . ResistDiff = atoi ( row [ 147 ] ) ;
2016-07-16 18:18:10 -04:00
sp [ tempid ] . dot_stacking_exempt = atoi ( row [ 148 ] ) ! = 0 ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . RecourseLink = atoi ( row [ 150 ] ) ;
sp [ tempid ] . no_partial_resist = atoi ( row [ 151 ] ) ! = 0 ;
sp [ tempid ] . short_buff_box = atoi ( row [ 154 ] ) ;
sp [ tempid ] . descnum = atoi ( row [ 155 ] ) ;
2016-03-24 18:50:31 -04:00
sp [ tempid ] . typedescnum = atoi ( row [ 156 ] ) ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . effectdescnum = atoi ( row [ 157 ] ) ;
sp [ tempid ] . npc_no_los = atoi ( row [ 159 ] ) ! = 0 ;
sp [ tempid ] . reflectable = atoi ( row [ 161 ] ) ! = 0 ;
sp [ tempid ] . bonushate = atoi ( row [ 162 ] ) ;
2014-11-14 00:23:26 -05:00
sp [ tempid ] . ldon_trap = atoi ( row [ 165 ] ) ! = 0 ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . EndurCost = atoi ( row [ 166 ] ) ;
sp [ tempid ] . EndurTimerIndex = atoi ( row [ 167 ] ) ;
sp [ tempid ] . IsDisciplineBuff = atoi ( row [ 168 ] ) ! = 0 ;
sp [ tempid ] . HateAdded = atoi ( row [ 173 ] ) ;
sp [ tempid ] . EndurUpkeep = atoi ( row [ 174 ] ) ;
sp [ tempid ] . numhitstype = atoi ( row [ 175 ] ) ;
sp [ tempid ] . numhits = atoi ( row [ 176 ] ) ;
sp [ tempid ] . pvpresistbase = atoi ( row [ 177 ] ) ;
sp [ tempid ] . pvpresistcalc = atoi ( row [ 178 ] ) ;
sp [ tempid ] . pvpresistcap = atoi ( row [ 179 ] ) ;
sp [ tempid ] . spell_category = atoi ( row [ 180 ] ) ;
2016-11-30 20:53:39 -05:00
sp [ tempid ] . pcnpc_only_flag = atoi ( row [ 183 ] ) ;
2016-07-23 18:40:17 -04:00
sp [ tempid ] . cast_not_standing = atoi ( row [ 184 ] ) ! = 0 ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . can_mgb = atoi ( row [ 185 ] ) ;
sp [ tempid ] . dispel_flag = atoi ( row [ 186 ] ) ;
sp [ tempid ] . MinResist = atoi ( row [ 189 ] ) ;
sp [ tempid ] . MaxResist = atoi ( row [ 190 ] ) ;
sp [ tempid ] . viral_targets = atoi ( row [ 191 ] ) ;
sp [ tempid ] . viral_timer = atoi ( row [ 192 ] ) ;
sp [ tempid ] . NimbusEffect = atoi ( row [ 193 ] ) ;
sp [ tempid ] . directional_start = static_cast < float > ( atoi ( row [ 194 ] ) ) ;
sp [ tempid ] . directional_end = static_cast < float > ( atoi ( row [ 195 ] ) ) ;
2014-11-13 21:45:19 -05:00
sp [ tempid ] . sneak = atoi ( row [ 196 ] ) ! = 0 ;
2015-10-08 11:49:21 -04:00
sp [ tempid ] . not_focusable = atoi ( row [ 197 ] ) ! = 0 ;
2015-10-08 16:05:14 -04:00
sp [ tempid ] . no_detrimental_spell_aggro = atoi ( row [ 198 ] ) ! = 0 ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . suspendable = atoi ( row [ 200 ] ) ! = 0 ;
sp [ tempid ] . viral_range = atoi ( row [ 201 ] ) ;
2015-06-17 02:47:05 -04:00
sp [ tempid ] . songcap = atoi ( row [ 202 ] ) ;
2014-11-14 00:23:26 -05:00
sp [ tempid ] . no_block = atoi ( row [ 205 ] ) ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . spellgroup = atoi ( row [ 207 ] ) ;
sp [ tempid ] . rank = atoi ( row [ 208 ] ) ;
2015-10-08 11:49:21 -04:00
sp [ tempid ] . no_resist = atoi ( row [ 209 ] ) ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . CastRestriction = atoi ( row [ 211 ] ) ;
sp [ tempid ] . AllowRest = atoi ( row [ 212 ] ) ! = 0 ;
sp [ tempid ] . InCombat = atoi ( row [ 213 ] ) ! = 0 ;
sp [ tempid ] . OutofCombat = atoi ( row [ 214 ] ) ! = 0 ;
2015-09-22 03:02:24 -04:00
sp [ tempid ] . override_crit_chance = atoi ( row [ 217 ] ) ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . aemaxtargets = atoi ( row [ 218 ] ) ;
2015-10-08 11:49:21 -04:00
sp [ tempid ] . no_heal_damage_item_mod = atoi ( row [ 219 ] ) ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . persistdeath = atoi ( row [ 224 ] ) ! = 0 ;
sp [ tempid ] . min_dist = atof ( row [ 227 ] ) ;
sp [ tempid ] . min_dist_mod = atof ( row [ 228 ] ) ;
sp [ tempid ] . max_dist = atof ( row [ 229 ] ) ;
sp [ tempid ] . max_dist_mod = atof ( row [ 230 ] ) ;
sp [ tempid ] . min_range = static_cast < float > ( atoi ( row [ 231 ] ) ) ;
2015-10-08 11:49:21 -04:00
sp [ tempid ] . no_remove = atoi ( row [ 232 ] ) ! = 0 ;
2014-10-04 14:16:54 -07:00
sp [ tempid ] . DamageShieldType = 0 ;
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:16:54 -07:00
LoadDamageShieldTypes ( sp , max_spells ) ;
2013-02-19 23:06:00 -08:00
}
2013-02-21 22:13:33 -08:00
2013-10-18 00:09:00 -07:00
int SharedDatabase : : GetMaxBaseDataLevel ( ) {
2014-10-04 14:18:11 -07:00
const std : : string query = " SELECT MAX(level) FROM base_data " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return - 1 ;
2013-10-18 00:09:00 -07:00
}
2014-10-04 14:18:11 -07:00
if ( results . RowCount ( ) = = 0 )
return - 1 ;
auto row = results . begin ( ) ;
return atoi ( row [ 0 ] ) ;
2013-10-18 00:09:00 -07:00
}
2015-06-23 17:39:06 -07:00
bool SharedDatabase : : LoadBaseData ( const std : : string & prefix ) {
base_data_mmf . reset ( nullptr ) ;
2013-10-18 00:09:00 -07:00
try {
2016-05-24 23:49:25 -07:00
auto Config = EQEmuConfig : : get ( ) ;
2013-10-18 00:09:00 -07:00
EQEmu : : IPCMutex mutex ( " base_data " ) ;
mutex . Lock ( ) ;
2016-05-20 21:03:34 -05:00
std : : string file_name = Config - > SharedMemDir + prefix + std : : string ( " base_data " ) ;
2015-06-23 17:39:06 -07:00
base_data_mmf = std : : unique_ptr < EQEmu : : MemoryMappedFile > ( new EQEmu : : MemoryMappedFile ( file_name ) ) ;
2013-10-18 00:09:00 -07:00
mutex . Unlock ( ) ;
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error Loading Base Data: %s " , ex . what ( ) ) ;
2013-10-18 00:09:00 -07:00
return false ;
}
return true ;
}
void SharedDatabase : : LoadBaseData ( void * data , int max_level ) {
char * base_ptr = reinterpret_cast < char * > ( data ) ;
2014-10-04 14:19:04 -07:00
const std : : string query = " SELECT * FROM base_data ORDER BY level, class ASC " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
2014-10-04 13:23:52 -07:00
2014-10-04 14:19:04 -07:00
int lvl = 0 ;
int cl = 0 ;
2013-10-18 00:09:00 -07:00
2014-10-04 14:19:04 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
lvl = atoi ( row [ 0 ] ) ;
cl = atoi ( row [ 1 ] ) ;
2013-10-18 00:09:00 -07:00
2014-10-04 14:19:04 -07:00
if ( lvl < = 0 ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Non fatal error: base_data.level <= 0, ignoring. " ) ;
2014-10-04 14:19:04 -07:00
continue ;
}
2013-10-18 00:09:00 -07:00
2014-10-04 14:19:04 -07:00
if ( lvl > = max_level ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Non fatal error: base_data.level >= max_level, ignoring. " ) ;
2014-10-04 14:19:04 -07:00
continue ;
}
if ( cl < = 0 ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Non fatal error: base_data.cl <= 0, ignoring. " ) ;
2014-10-04 14:19:04 -07:00
continue ;
}
if ( cl > 16 ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Non fatal error: base_data.class > 16, ignoring. " ) ;
2014-10-04 14:19:04 -07:00
continue ;
}
BaseDataStruct * bd = reinterpret_cast < BaseDataStruct * > ( base_ptr + ( ( ( 16 * ( lvl - 1 ) ) + ( cl - 1 ) ) * sizeof ( BaseDataStruct ) ) ) ;
bd - > base_hp = atof ( row [ 2 ] ) ;
bd - > base_mana = atof ( row [ 3 ] ) ;
bd - > base_end = atof ( row [ 4 ] ) ;
2017-10-08 00:13:53 -04:00
bd - > hp_regen = atof ( row [ 5 ] ) ;
bd - > end_regen = atof ( row [ 6 ] ) ;
2014-10-04 14:19:04 -07:00
bd - > hp_factor = atof ( row [ 7 ] ) ;
bd - > mana_factor = atof ( row [ 8 ] ) ;
bd - > endurance_factor = atof ( row [ 9 ] ) ;
}
2013-10-18 00:09:00 -07:00
}
const BaseDataStruct * SharedDatabase : : GetBaseData ( int lvl , int cl ) {
if ( ! base_data_mmf ) {
return nullptr ;
}
if ( lvl < = 0 ) {
return nullptr ;
}
if ( cl < = 0 ) {
return nullptr ;
}
if ( cl > 16 ) {
return nullptr ;
}
char * base_ptr = reinterpret_cast < char * > ( base_data_mmf - > Get ( ) ) ;
uint32 offset = ( ( 16 * ( lvl - 1 ) ) + ( cl - 1 ) ) * sizeof ( BaseDataStruct ) ;
if ( offset > = base_data_mmf - > Size ( ) ) {
return nullptr ;
}
BaseDataStruct * bd = reinterpret_cast < BaseDataStruct * > ( base_ptr + offset ) ;
return bd ;
}
2013-02-22 18:25:17 -08:00
void SharedDatabase : : GetLootTableInfo ( uint32 & loot_table_count , uint32 & max_loot_table , uint32 & loot_table_entries ) {
2013-05-09 10:44:08 -04:00
loot_table_count = 0 ;
max_loot_table = 0 ;
loot_table_entries = 0 ;
2014-10-04 14:20:46 -07:00
const std : : string query = " SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM loottable_entries) FROM loottable " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:20:46 -07:00
if ( results . RowCount ( ) = = 0 )
return ;
auto row = results . begin ( ) ;
loot_table_count = static_cast < uint32 > ( atoul ( row [ 0 ] ) ) ;
2015-02-10 11:53:16 -08:00
max_loot_table = static_cast < uint32 > ( atoul ( row [ 1 ] ? row [ 1 ] : " 0 " ) ) ;
2014-10-04 14:20:46 -07:00
loot_table_entries = static_cast < uint32 > ( atoul ( row [ 2 ] ) ) ;
2013-02-21 22:13:33 -08:00
}
2013-02-22 18:25:17 -08:00
void SharedDatabase : : GetLootDropInfo ( uint32 & loot_drop_count , uint32 & max_loot_drop , uint32 & loot_drop_entries ) {
2013-05-09 10:44:08 -04:00
loot_drop_count = 0 ;
max_loot_drop = 0 ;
loot_drop_entries = 0 ;
2014-10-04 14:20:46 -07:00
const std : : string query = " SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM lootdrop_entries) FROM lootdrop " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
if ( results . RowCount ( ) = = 0 )
return ;
auto row = results . begin ( ) ;
loot_drop_count = static_cast < uint32 > ( atoul ( row [ 0 ] ) ) ;
2015-02-10 11:53:16 -08:00
max_loot_drop = static_cast < uint32 > ( atoul ( row [ 1 ] ? row [ 1 ] : " 0 " ) ) ;
2014-10-04 14:20:46 -07:00
loot_drop_entries = static_cast < uint32 > ( atoul ( row [ 2 ] ) ) ;
2013-02-22 18:25:17 -08:00
}
2013-02-21 22:13:33 -08:00
2013-02-22 18:25:17 -08:00
void SharedDatabase : : LoadLootTables ( void * data , uint32 size ) {
2013-05-09 10:44:08 -04:00
EQEmu : : FixedMemoryVariableHashSet < LootTable_Struct > hash ( reinterpret_cast < uint8 * > ( data ) , size ) ;
2014-10-04 14:21:25 -07:00
2013-05-09 10:44:08 -04:00
uint8 loot_table [ sizeof ( LootTable_Struct ) + ( sizeof ( LootTableEntries_Struct ) * 128 ) ] ;
LootTable_Struct * lt = reinterpret_cast < LootTable_Struct * > ( loot_table ) ;
2014-10-04 14:21:25 -07:00
const std : : string query = " SELECT loottable.id, loottable.mincash, loottable.maxcash, loottable.avgcoin, "
" loottable_entries.lootdrop_id, loottable_entries.multiplier, loottable_entries.droplimit, "
" loottable_entries.mindrop, loottable_entries.probability FROM loottable LEFT JOIN loottable_entries "
" ON loottable.id = loottable_entries.loottable_id ORDER BY id " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:21:25 -07:00
uint32 current_id = 0 ;
uint32 current_entry = 0 ;
2013-05-09 10:44:08 -04:00
2014-10-04 14:21:25 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
uint32 id = static_cast < uint32 > ( atoul ( row [ 0 ] ) ) ;
if ( id ! = current_id ) {
if ( current_id ! = 0 )
hash . insert ( current_id , loot_table , ( sizeof ( LootTable_Struct ) + ( sizeof ( LootTableEntries_Struct ) * lt - > NumEntries ) ) ) ;
2013-05-09 10:44:08 -04:00
2014-10-04 14:21:25 -07:00
memset ( loot_table , 0 , sizeof ( LootTable_Struct ) + ( sizeof ( LootTableEntries_Struct ) * 128 ) ) ;
current_entry = 0 ;
current_id = id ;
lt - > mincash = static_cast < uint32 > ( atoul ( row [ 1 ] ) ) ;
lt - > maxcash = static_cast < uint32 > ( atoul ( row [ 2 ] ) ) ;
lt - > avgcoin = static_cast < uint32 > ( atoul ( row [ 3 ] ) ) ;
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:21:25 -07:00
if ( current_entry > 128 )
continue ;
if ( ! row [ 4 ] )
continue ;
lt - > Entries [ current_entry ] . lootdrop_id = static_cast < uint32 > ( atoul ( row [ 4 ] ) ) ;
lt - > Entries [ current_entry ] . multiplier = static_cast < uint8 > ( atoi ( row [ 5 ] ) ) ;
lt - > Entries [ current_entry ] . droplimit = static_cast < uint8 > ( atoi ( row [ 6 ] ) ) ;
lt - > Entries [ current_entry ] . mindrop = static_cast < uint8 > ( atoi ( row [ 7 ] ) ) ;
lt - > Entries [ current_entry ] . probability = static_cast < float > ( atof ( row [ 8 ] ) ) ;
+ + ( lt - > NumEntries ) ;
+ + current_entry ;
}
if ( current_id ! = 0 )
hash . insert ( current_id , loot_table , ( sizeof ( LootTable_Struct ) + ( sizeof ( LootTableEntries_Struct ) * lt - > NumEntries ) ) ) ;
2013-05-09 10:44:08 -04:00
2013-02-22 18:25:17 -08:00
}
2013-02-21 22:13:33 -08:00
2013-02-22 18:25:17 -08:00
void SharedDatabase : : LoadLootDrops ( void * data , uint32 size ) {
2013-05-09 10:44:08 -04:00
2014-10-04 14:22:27 -07:00
EQEmu : : FixedMemoryVariableHashSet < LootDrop_Struct > hash ( reinterpret_cast < uint8 * > ( data ) , size ) ;
2013-05-09 10:44:08 -04:00
uint8 loot_drop [ sizeof ( LootDrop_Struct ) + ( sizeof ( LootDropEntries_Struct ) * 1260 ) ] ;
LootDrop_Struct * ld = reinterpret_cast < LootDrop_Struct * > ( loot_drop ) ;
2014-10-04 14:22:27 -07:00
const std : : string query = " SELECT lootdrop.id, lootdrop_entries.item_id, lootdrop_entries.item_charges, "
" lootdrop_entries.equip_item, lootdrop_entries.chance, lootdrop_entries.minlevel, "
" lootdrop_entries.maxlevel, lootdrop_entries.multiplier FROM lootdrop JOIN lootdrop_entries "
" ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id " ;
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2016-01-21 11:53:14 -05:00
return ;
2014-10-04 14:22:27 -07:00
}
2013-05-09 10:44:08 -04:00
2014-10-04 14:22:27 -07:00
uint32 current_id = 0 ;
uint32 current_entry = 0 ;
2013-05-09 10:44:08 -04:00
2014-10-04 14:22:27 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
uint32 id = static_cast < uint32 > ( atoul ( row [ 0 ] ) ) ;
if ( id ! = current_id ) {
if ( current_id ! = 0 )
hash . insert ( current_id , loot_drop , ( sizeof ( LootDrop_Struct ) + ( sizeof ( LootDropEntries_Struct ) * ld - > NumEntries ) ) ) ;
memset ( loot_drop , 0 , sizeof ( LootDrop_Struct ) + ( sizeof ( LootDropEntries_Struct ) * 1260 ) ) ;
current_entry = 0 ;
current_id = id ;
}
if ( current_entry > = 1260 )
continue ;
ld - > Entries [ current_entry ] . item_id = static_cast < uint32 > ( atoul ( row [ 1 ] ) ) ;
ld - > Entries [ current_entry ] . item_charges = static_cast < int8 > ( atoi ( row [ 2 ] ) ) ;
ld - > Entries [ current_entry ] . equip_item = static_cast < uint8 > ( atoi ( row [ 3 ] ) ) ;
ld - > Entries [ current_entry ] . chance = static_cast < float > ( atof ( row [ 4 ] ) ) ;
ld - > Entries [ current_entry ] . minlevel = static_cast < uint8 > ( atoi ( row [ 5 ] ) ) ;
ld - > Entries [ current_entry ] . maxlevel = static_cast < uint8 > ( atoi ( row [ 6 ] ) ) ;
ld - > Entries [ current_entry ] . multiplier = static_cast < uint8 > ( atoi ( row [ 7 ] ) ) ;
+ + ( ld - > NumEntries ) ;
+ + current_entry ;
}
if ( current_id ! = 0 )
hash . insert ( current_id , loot_drop , ( sizeof ( LootDrop_Struct ) + ( sizeof ( LootDropEntries_Struct ) * ld - > NumEntries ) ) ) ;
2013-05-09 10:44:08 -04:00
2013-02-21 22:13:33 -08:00
}
2015-06-23 17:39:06 -07:00
bool SharedDatabase : : LoadLoot ( const std : : string & prefix ) {
loot_table_mmf . reset ( nullptr ) ;
loot_drop_mmf . reset ( nullptr ) ;
2013-05-09 10:44:08 -04:00
try {
2016-05-24 23:49:25 -07:00
auto Config = EQEmuConfig : : get ( ) ;
2013-05-09 10:44:08 -04:00
EQEmu : : IPCMutex mutex ( " loot " ) ;
mutex . Lock ( ) ;
2016-05-20 21:03:34 -05:00
std : : string file_name_lt = Config - > SharedMemDir + prefix + std : : string ( " loot_table " ) ;
2015-06-23 17:39:06 -07:00
loot_table_mmf = std : : unique_ptr < EQEmu : : MemoryMappedFile > ( new EQEmu : : MemoryMappedFile ( file_name_lt ) ) ;
loot_table_hash = std : : unique_ptr < EQEmu : : FixedMemoryVariableHashSet < LootTable_Struct > > ( new EQEmu : : FixedMemoryVariableHashSet < LootTable_Struct > (
2013-05-09 10:44:08 -04:00
reinterpret_cast < uint8 * > ( loot_table_mmf - > Get ( ) ) ,
2015-06-23 17:39:06 -07:00
loot_table_mmf - > Size ( ) ) ) ;
2016-05-20 21:03:34 -05:00
std : : string file_name_ld = Config - > SharedMemDir + prefix + std : : string ( " loot_drop " ) ;
2015-06-23 17:39:06 -07:00
loot_drop_mmf = std : : unique_ptr < EQEmu : : MemoryMappedFile > ( new EQEmu : : MemoryMappedFile ( file_name_ld ) ) ;
loot_drop_hash = std : : unique_ptr < EQEmu : : FixedMemoryVariableHashSet < LootDrop_Struct > > ( new EQEmu : : FixedMemoryVariableHashSet < LootDrop_Struct > (
2013-05-09 10:44:08 -04:00
reinterpret_cast < uint8 * > ( loot_drop_mmf - > Get ( ) ) ,
2015-06-23 17:39:06 -07:00
loot_drop_mmf - > Size ( ) ) ) ;
2013-05-09 10:44:08 -04:00
mutex . Unlock ( ) ;
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Error loading loot: %s " , ex . what ( ) ) ;
2013-05-09 10:44:08 -04:00
return false ;
}
return true ;
2013-02-21 22:13:33 -08:00
}
const LootTable_Struct * SharedDatabase : : GetLootTable ( uint32 loottable_id ) {
2013-02-22 18:25:17 -08:00
if ( ! loot_table_hash )
2013-05-09 10:44:08 -04:00
return nullptr ;
try {
if ( loot_table_hash - > exists ( loottable_id ) ) {
return & loot_table_hash - > at ( loottable_id ) ;
}
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Could not get loot table: %s " , ex . what ( ) ) ;
2013-05-09 10:44:08 -04:00
}
return nullptr ;
2013-02-21 22:13:33 -08:00
}
const LootDrop_Struct * SharedDatabase : : GetLootDrop ( uint32 lootdrop_id ) {
2013-02-22 18:25:17 -08:00
if ( ! loot_drop_hash )
2013-05-09 10:44:08 -04:00
return nullptr ;
try {
if ( loot_drop_hash - > exists ( lootdrop_id ) ) {
return & loot_drop_hash - > at ( lootdrop_id ) ;
}
} catch ( std : : exception & ex ) {
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Error , " Could not get loot drop: %s " , ex . what ( ) ) ;
2013-05-09 10:44:08 -04:00
}
return nullptr ;
2013-02-21 22:13:33 -08:00
}
2014-10-04 13:23:52 -07:00
void SharedDatabase : : LoadCharacterInspectMessage ( uint32 character_id , InspectMessage_Struct * message ) {
2014-09-06 21:50:29 -05:00
std : : string query = StringFormat ( " SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1 " , character_id ) ;
2015-06-17 02:47:05 -04:00
auto results = QueryDatabase ( query ) ;
2014-10-04 13:23:52 -07:00
auto row = results . begin ( ) ;
2015-01-12 16:57:41 -05:00
memset ( message , ' \0 ' , sizeof ( InspectMessage_Struct ) ) ;
2014-09-06 21:50:29 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
memcpy ( message , row [ 0 ] , sizeof ( InspectMessage_Struct ) ) ;
2013-02-21 22:13:33 -08:00
}
}
2014-09-06 21:50:29 -05:00
void SharedDatabase : : SaveCharacterInspectMessage ( uint32 character_id , const InspectMessage_Struct * message ) {
std : : string query = StringFormat ( " REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s') " , character_id , EscapeString ( message - > text ) . c_str ( ) ) ;
2015-06-17 02:47:05 -04:00
auto results = QueryDatabase ( query ) ;
2013-02-21 22:13:33 -08:00
}