2013-05-09 10:44:08 -04:00
/* EQEMu: Everquest Server Emulator
Copyright ( C ) 2001 - 2003 EQEMu Development Team ( http : //eqemulator.net)
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
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 .
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY except by those people which sell it , which
2013-02-16 16:14:39 -08:00
are required to give you total support for your newly bought product ;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
2013-05-09 10:44:08 -04:00
A PARTICULAR PURPOSE . See the GNU General Public License for more details .
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
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-16 16:14:39 -08:00
*/
2014-11-29 03:12:34 -06:00
# include <float.h>
2013-02-16 16:14:39 -08:00
# include <iostream>
2014-11-29 03:12:34 -06:00
# include <math.h>
2013-02-16 16:14:39 -08:00
# include <stdlib.h>
# include <string.h>
# ifdef _WINDOWS
2013-05-09 10:44:08 -04:00
# define snprintf _snprintf
# define vsnprintf _vsnprintf
2013-02-16 16:14:39 -08:00
# else
# include <pthread.h>
# include "../common/unix.h"
# endif
2015-01-19 04:12:09 -06:00
# include "../common/global_define.h"
2013-02-20 13:54:26 -08:00
# include "../common/features.h"
2014-11-29 03:12:34 -06:00
# include "../common/rulesys.h"
2013-02-16 16:14:39 -08:00
# include "../common/seperator.h"
2014-08-21 19:33:02 -07:00
# include "../common/string_util.h"
2015-01-10 03:44:49 -06:00
# include "../common/eqemu_logsys.h"
2014-12-15 19:14:41 -06:00
2014-11-29 03:12:34 -06:00
# include "guild_mgr.h"
2013-02-16 16:14:39 -08:00
# include "map.h"
2014-11-29 03:12:34 -06:00
# include "npc.h"
2013-02-16 16:14:39 -08:00
# include "object.h"
2017-07-18 00:01:59 -07:00
# include "pathfinder_null.h"
# include "pathfinder_nav_mesh.h"
# include "pathfinder_waypoint.h"
2014-11-29 03:12:34 -06:00
# include "petitions.h"
2014-08-21 23:46:01 -07:00
# include "quest_parser_collection.h"
2014-11-29 03:12:34 -06:00
# include "spawn2.h"
# include "spawngroup.h"
# include "water_map.h"
# include "worldserver.h"
# include "zone.h"
2014-12-15 19:14:41 -06:00
# include "zone_config.h"
2018-09-17 14:32:36 -07:00
# include "mob_movement_manager.h"
2019-01-02 02:36:12 -06:00
# include "npc_scale_manager.h"
2019-08-07 18:54:53 -05:00
# include "../common/data_verification.h"
2020-01-31 20:25:06 -06:00
# include "zone_reload.h"
2013-02-16 16:14:39 -08:00
2015-01-10 03:44:49 -06:00
# include <time.h>
# include <ctime>
# include <iostream>
2013-02-16 16:14:39 -08:00
# ifdef _WINDOWS
# define snprintf _snprintf
# define strncasecmp _strnicmp
2013-05-09 10:44:08 -04:00
# define strcasecmp _stricmp
2013-02-16 16:14:39 -08:00
# endif
2014-11-29 03:12:34 -06:00
extern bool staticzone ;
2013-02-16 16:14:39 -08:00
extern PetitionList petition_list ;
2014-11-29 03:12:34 -06:00
extern QuestParserCollection * parse ;
extern uint32 numclients ;
extern WorldServer worldserver ;
extern Zone * zone ;
2019-01-02 02:36:12 -06:00
extern NpcScaleManager * npc_scale_manager ;
2014-11-29 03:12:34 -06:00
2013-02-16 16:14:39 -08:00
Mutex MZoneShutdown ;
2014-11-29 03:12:34 -06:00
2015-10-31 20:19:57 -05:00
volatile bool is_zone_loaded = false ;
2014-11-29 03:12:34 -06:00
Zone * zone = 0 ;
2013-02-16 16:14:39 -08:00
2019-10-13 18:49:16 -07:00
void UpdateWindowTitle ( char * iNewTitle ) ;
2013-02-16 16:14:39 -08:00
bool Zone : : Bootup ( uint32 iZoneID , uint32 iInstanceID , bool iStaticZone ) {
const char * zonename = database . GetZoneName ( iZoneID ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( iZoneID = = 0 | | zonename = = 0 )
return false ;
2015-10-31 20:19:57 -05:00
if ( zone ! = 0 | | is_zone_loaded ) {
2013-05-22 16:17:19 -04:00
std : : cerr < < " Error: Zone::Bootup call when zone already booted! " < < std : : endl ;
2015-10-31 20:19:57 -05:00
worldserver . SetZoneData ( 0 ) ;
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Booting [{}] ([{}]:[{}]) " , zonename , iZoneID , iInstanceID ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
numclients = 0 ;
zone = new Zone ( iZoneID , iInstanceID , zonename ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//init the zone, loads all the data, etc
if ( ! zone - > Init ( iStaticZone ) ) {
safe_delete ( zone ) ;
2013-05-22 16:17:19 -04:00
std : : cerr < < " Zone->Init failed " < < std : : endl ;
2015-10-31 20:19:57 -05:00
worldserver . SetZoneData ( 0 ) ;
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2016-05-09 14:23:27 -04:00
std : : string tmp ;
if ( database . GetVariable ( " loglevel " , tmp ) ) {
2013-02-19 22:20:30 -08:00
int log_levels [ 4 ] ;
2016-05-09 14:23:27 -04:00
int tmp_i = atoi ( tmp . c_str ( ) ) ;
if ( tmp_i > 9 ) { //Server is using the new code
2013-02-16 16:14:39 -08:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( ( ( int ) tmp [ i ] > = 48 ) & & ( ( int ) tmp [ i ] < = 57 ) )
2013-02-19 22:20:30 -08:00
log_levels [ i ] = ( int ) tmp [ i ] - 48 ; //get the value to convert it to an int from the ascii value
2013-02-16 16:14:39 -08:00
else
2013-02-19 22:20:30 -08:00
log_levels [ i ] = 0 ; //set to zero on a bogue char
2013-02-16 16:14:39 -08:00
}
2013-02-19 22:20:30 -08:00
zone - > loglevelvar = log_levels [ 0 ] ;
2019-09-01 23:22:40 -05:00
LogInfo ( " General logging level: [{}] " , zone - > loglevelvar ) ;
2013-02-19 22:20:30 -08:00
zone - > merchantvar = log_levels [ 1 ] ;
2019-09-01 23:22:40 -05:00
LogInfo ( " Merchant logging level: [{}] " , zone - > merchantvar ) ;
2013-02-19 22:20:30 -08:00
zone - > tradevar = log_levels [ 2 ] ;
2019-09-01 23:22:40 -05:00
LogInfo ( " Trade logging level: [{}] " , zone - > tradevar ) ;
2013-02-19 22:20:30 -08:00
zone - > lootvar = log_levels [ 3 ] ;
2019-09-01 23:22:40 -05:00
LogInfo ( " Loot logging level: [{}] " , zone - > lootvar ) ;
2013-02-16 16:14:39 -08:00
}
else {
2016-05-09 14:23:27 -04:00
zone - > loglevelvar = uint8 ( tmp_i ) ; //continue supporting only command logging (for now)
2013-02-16 16:14:39 -08:00
zone - > merchantvar = 0 ;
zone - > tradevar = 0 ;
zone - > lootvar = 0 ;
}
2016-05-09 14:23:27 -04:00
}
2013-02-16 16:14:39 -08:00
2015-10-31 20:19:57 -05:00
is_zone_loaded = true ;
2013-02-16 16:14:39 -08:00
2015-10-31 20:19:57 -05:00
worldserver . SetZoneData ( iZoneID , iInstanceID ) ;
2013-02-16 16:14:39 -08:00
if ( iInstanceID ! = 0 )
{
2016-05-25 16:10:28 -04:00
auto pack = new ServerPacket ( ServerOP_AdventureZoneData , sizeof ( uint16 ) ) ;
2020-04-10 01:43:00 -05:00
* ( ( uint16 * ) pack - > pBuffer ) = iInstanceID ;
2013-02-16 16:14:39 -08:00
worldserver . SendPacket ( pack ) ;
delete pack ;
}
2019-09-02 02:18:54 -05:00
LogInfo ( " ---- Zone server [{}], listening on port:[{}] ---- " , zonename , ZoneConfig : : get ( ) - > ZonePort ) ;
2019-09-01 23:22:40 -05:00
LogInfo ( " Zone Bootup: [{}] ([{}]: [{}]) " , zonename , iZoneID , iInstanceID ) ;
2013-05-27 17:24:31 -07:00
parse - > Init ( ) ;
2019-10-13 18:49:16 -07:00
UpdateWindowTitle ( nullptr ) ;
2013-02-16 16:14:39 -08:00
zone - > GetTimeSync ( ) ;
2018-03-04 21:38:17 -05:00
zone - > RequestUCSServerStatus ( ) ;
2018-05-12 03:31:47 -05:00
/**
* Set Shutdown timer
*/
uint32 shutdown_timer = static_cast < uint32 > ( database . getZoneShutDownDelay ( zone - > GetZoneID ( ) , zone - > GetInstanceVersion ( ) ) ) ;
zone - > StartShutdownTimer ( shutdown_timer ) ;
/*
* Set Logging
*/
2017-04-01 03:51:46 -05:00
LogSys . StartFileLogs ( StringFormat ( " %s_version_%u_inst_id_%u_port_%u " , zone - > GetShortName ( ) , zone - > GetInstanceVersion ( ) , zone - > GetInstanceID ( ) , ZoneConfig : : get ( ) - > ZonePort ) ) ;
2015-01-10 03:44:49 -06:00
2013-02-16 16:14:39 -08:00
return true ;
}
//this really loads the objects into entity_list
2016-08-27 22:26:44 -04:00
bool Zone : : LoadZoneObjects ( )
{
std : : string query =
StringFormat ( " SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, "
" unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name "
" FROM object WHERE zoneid = %i AND (version = %u OR version = -1) " ,
zoneid , instanceversion ) ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2019-09-02 03:10:03 -05:00
LogError ( " Error Loading Objects from DB: [{}] " ,
2016-08-27 22:26:44 -04:00
results . ErrorMessage ( ) . c_str ( ) ) ;
2014-08-20 15:32:14 -07:00
return false ;
2016-05-25 16:10:28 -04:00
}
2014-08-20 15:32:14 -07:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading Objects from DB " ) ;
2016-08-27 22:26:44 -04:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
if ( atoi ( row [ 9 ] ) = = 0 ) {
// Type == 0 - Static Object
const char * shortname = database . GetZoneName ( atoi ( row [ 1 ] ) , false ) ; // zoneid -> zone_shortname
if ( ! shortname )
continue ;
Door d ;
memset ( & d , 0 , sizeof ( d ) ) ;
strn0cpy ( d . zone_name , shortname , sizeof ( d . zone_name ) ) ;
d . db_id = 1000000000 + atoi ( row [ 0 ] ) ; // Out of range of normal use for doors.id
d . door_id = - 1 ; // Client doesn't care if these are all the same door_id
d . pos_x = atof ( row [ 2 ] ) ; // xpos
d . pos_y = atof ( row [ 3 ] ) ; // ypos
d . pos_z = atof ( row [ 4 ] ) ; // zpos
d . heading = atof ( row [ 5 ] ) ; // heading
strn0cpy ( d . door_name , row [ 8 ] , sizeof ( d . door_name ) ) ; // objectname
// Strip trailing "_ACTORDEF" if present. Client won't accept it for doors.
int len = strlen ( d . door_name ) ;
if ( ( len > 9 ) & & ( memcmp ( & d . door_name [ len - 9 ] , " _ACTORDEF " , 10 ) = = 0 ) )
d . door_name [ len - 9 ] = ' \0 ' ;
memcpy ( d . dest_zone , " NONE " , 5 ) ;
if ( ( d . size = atoi ( row [ 11 ] ) ) = = 0 ) // unknown08 = optional size percentage
d . size = 100 ;
switch ( d . opentype = atoi ( row [ 12 ] ) ) // unknown10 = optional request_nonsolid (0 or 1 or experimental number)
{
case 0 :
d . opentype = 31 ;
break ;
case 1 :
d . opentype = 9 ;
break ;
}
d . incline = atoi ( row [ 13 ] ) ; // unknown20 = optional model incline value
d . client_version_mask = 0xFFFFFFFF ; // We should load the mask from the zone.
auto door = new Doors ( & d ) ;
entity_list . AddDoor ( door ) ;
}
Object_Struct data = { 0 } ;
uint32 id = 0 ;
uint32 icon = 0 ;
uint32 type = 0 ;
uint32 itemid = 0 ;
uint32 idx = 0 ;
int16 charges = 0 ;
id = ( uint32 ) atoi ( row [ 0 ] ) ;
data . zone_id = atoi ( row [ 1 ] ) ;
data . x = atof ( row [ 2 ] ) ;
data . y = atof ( row [ 3 ] ) ;
data . z = atof ( row [ 4 ] ) ;
data . heading = atof ( row [ 5 ] ) ;
2014-08-20 15:32:14 -07:00
itemid = ( uint32 ) atoi ( row [ 6 ] ) ;
2016-08-27 22:26:44 -04:00
charges = ( int16 ) atoi ( row [ 7 ] ) ;
strcpy ( data . object_name , row [ 8 ] ) ;
type = ( uint8 ) atoi ( row [ 9 ] ) ;
icon = ( uint32 ) atoi ( row [ 10 ] ) ;
2014-08-20 15:32:14 -07:00
data . object_type = type ;
data . linked_list_addr [ 0 ] = 0 ;
2016-08-27 22:26:44 -04:00
data . linked_list_addr [ 1 ] = 0 ;
data . solidtype = ( uint32 ) atoi ( row [ 12 ] ) ;
data . unknown020 = ( uint32 ) atoi ( row [ 13 ] ) ;
data . unknown024 = ( uint32 ) atoi ( row [ 14 ] ) ;
data . unknown076 = ( uint32 ) atoi ( row [ 15 ] ) ;
data . size = atof ( row [ 16 ] ) ;
2016-08-26 06:34:51 -07:00
data . tilt_x = atof ( row [ 17 ] ) ;
data . tilt_y = atof ( row [ 18 ] ) ;
2016-08-27 22:26:44 -04:00
data . unknown084 = 0 ;
2020-05-17 18:36:06 -07:00
EQ : : ItemInstance * inst = nullptr ;
2016-08-27 22:26:44 -04:00
// FatherNitwit: this dosent seem to work...
// tradeskill containers do not have an itemid of 0... at least what I am seeing
if ( itemid = = 0 ) {
// Generic tradeskill container
2020-05-17 18:36:06 -07:00
inst = new EQ : : ItemInstance ( ItemInstWorldContainer ) ;
2016-08-27 22:26:44 -04:00
} else {
// Groundspawn object
inst = database . CreateItem ( itemid ) ;
}
// Father Nitwit's fix... not perfect...
if ( inst = = nullptr & & type ! = OT_DROPPEDITEM ) {
2020-05-17 18:36:06 -07:00
inst = new EQ : : ItemInstance ( ItemInstWorldContainer ) ;
2016-08-27 22:26:44 -04:00
}
// Load child objects if container
2020-05-17 18:36:06 -07:00
if ( inst & & inst - > IsType ( EQ : : item : : ItemClassBag ) ) {
2016-08-27 22:26:44 -04:00
database . LoadWorldContainer ( id , inst ) ;
}
2014-08-20 15:32:14 -07:00
2016-08-27 22:26:44 -04:00
auto object = new Object ( id , type , icon , data , inst ) ;
object - > SetDisplayName ( row [ 19 ] ) ;
entity_list . AddObject ( object , false ) ;
if ( type = = OT_DROPPEDITEM & & itemid ! = 0 )
entity_list . RemoveObject ( object - > GetID ( ) ) ;
2014-08-20 15:32:14 -07:00
2016-08-27 22:26:44 -04:00
safe_delete ( inst ) ;
}
2013-02-16 16:14:39 -08:00
2014-08-20 15:32:14 -07:00
return true ;
2013-02-16 16:14:39 -08:00
}
//this also just loads into entity_list, not really into zone
bool Zone : : LoadGroundSpawns ( ) {
Ground_Spawns groundspawn ;
memset ( & groundspawn , 0 , sizeof ( groundspawn ) ) ;
int gsindex = 0 ;
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading Ground Spawns from DB " ) ;
2013-02-16 16:14:39 -08:00
database . LoadGroundSpawns ( zoneid , GetInstanceVersion ( ) , & groundspawn ) ;
uint32 ix = 0 ;
2017-03-23 04:35:36 -04:00
char * name = nullptr ;
2013-02-16 16:14:39 -08:00
uint32 gsnumber = 0 ;
for ( gsindex = 0 ; gsindex < 50 ; gsindex + + ) {
2016-01-20 22:31:35 -05:00
if ( groundspawn . spawn [ gsindex ] . item > 0 & & groundspawn . spawn [ gsindex ] . item < SAYLINK_ITEM_ID ) {
2020-05-17 18:36:06 -07:00
EQ : : ItemInstance * inst = nullptr ;
2013-02-16 16:14:39 -08:00
inst = database . CreateItem ( groundspawn . spawn [ gsindex ] . item ) ;
gsnumber = groundspawn . spawn [ gsindex ] . max_allowed ;
ix = 0 ;
if ( inst ) {
name = groundspawn . spawn [ gsindex ] . name ;
for ( ix = 0 ; ix < gsnumber ; ix + + ) {
2016-05-25 16:10:28 -04:00
auto object = new Object (
inst , name , groundspawn . spawn [ gsindex ] . max_x ,
groundspawn . spawn [ gsindex ] . min_x , groundspawn . spawn [ gsindex ] . max_y ,
groundspawn . spawn [ gsindex ] . min_y , groundspawn . spawn [ gsindex ] . max_z ,
groundspawn . spawn [ gsindex ] . heading ,
groundspawn . spawn [ gsindex ] . respawntimer ) ; // new object with id of 10000+
2013-02-16 16:14:39 -08:00
entity_list . AddObject ( object , false ) ;
}
safe_delete ( inst ) ;
}
}
}
return ( true ) ;
}
2020-04-21 00:40:18 -04:00
void Zone : : DumpMerchantList ( uint32 npcid ) {
std : : list < TempMerchantList > tmp_merlist = tmpmerchanttable [ npcid ] ;
std : : list < TempMerchantList > : : const_iterator tmp_itr ;
TempMerchantList ml ;
for ( tmp_itr = tmp_merlist . begin ( ) ; tmp_itr ! = tmp_merlist . end ( ) ; + + tmp_itr ) {
ml = * tmp_itr ;
LogInventory ( " slot[{}] Orig[{}] Item[{}] Charges[{}] " , ml . slot , ml . origslot , ml . item , ml . charges ) ;
}
}
2014-10-09 23:11:18 -04:00
int Zone : : SaveTempItem ( uint32 merchantid , uint32 npcid , uint32 item , int32 charges , bool sold ) {
2020-04-21 00:40:18 -04:00
LogInventory ( " Transaction of [{}] [{}] " , charges , item ) ;
//DumpMerchantList(npcid);
// Iterate past main items.
// If the item being transacted is in this list, return 0;
2013-02-16 16:14:39 -08:00
std : : list < MerchantList > merlist = merchanttable [ merchantid ] ;
std : : list < MerchantList > : : const_iterator itr ;
2020-04-21 00:40:18 -04:00
uint32 temp_slot_index = 1 ;
2014-01-13 22:14:02 -05:00
for ( itr = merlist . begin ( ) ; itr ! = merlist . end ( ) ; + + itr ) {
2013-02-16 16:14:39 -08:00
MerchantList ml = * itr ;
2020-04-21 00:40:18 -04:00
if ( ml . item = = item ) {
2013-02-16 16:14:39 -08:00
return 0 ;
2020-04-21 00:40:18 -04:00
}
2013-02-16 16:14:39 -08:00
// Account for merchant lists with gaps in them.
2020-04-21 00:40:18 -04:00
if ( ml . slot > = temp_slot_index ) {
temp_slot_index = ml . slot + 1 ;
}
2013-02-16 16:14:39 -08:00
}
2020-04-21 00:40:18 -04:00
LogInventory ( " Searching Temporary List. Main list ended at [{}] " , temp_slot_index - 1 ) ;
// Now search the temporary list.
2013-02-16 16:14:39 -08:00
std : : list < TempMerchantList > tmp_merlist = tmpmerchanttable [ npcid ] ;
std : : list < TempMerchantList > : : const_iterator tmp_itr ;
TempMerchantList ml ;
2020-04-21 00:40:18 -04:00
uint32 first_empty_slot = 0 ; // Save 1st vacant slot while searching..
bool found = false ;
for ( tmp_itr = tmp_merlist . begin ( ) ; tmp_itr ! = tmp_merlist . end ( ) ; + + tmp_itr ) {
ml = * tmp_itr ;
if ( ml . item = = item ) {
found = true ;
LogInventory ( " Item found in temp list at [{}] with [{}] charges " , ml . origslot , ml . charges ) ;
break ;
2013-02-16 16:14:39 -08:00
}
}
2020-04-21 00:40:18 -04:00
if ( found ) {
2013-02-16 16:14:39 -08:00
tmp_merlist . clear ( ) ;
std : : list < TempMerchantList > oldtmp_merlist = tmpmerchanttable [ npcid ] ;
2014-01-13 22:14:02 -05:00
for ( tmp_itr = oldtmp_merlist . begin ( ) ; tmp_itr ! = oldtmp_merlist . end ( ) ; + + tmp_itr ) {
2013-02-16 16:14:39 -08:00
TempMerchantList ml2 = * tmp_itr ;
if ( ml2 . item ! = item )
tmp_merlist . push_back ( ml2 ) ;
2020-04-21 00:40:18 -04:00
else {
if ( sold ) {
LogInventory ( " Total charges is [{}] + [{}] charges " , ml . charges , charges ) ;
ml . charges = ml . charges + charges ;
}
else {
ml . charges = charges ;
LogInventory ( " new charges is [{}] charges " , ml . charges ) ;
}
if ( ! ml . origslot ) {
ml . origslot = ml . slot ;
}
if ( charges > 0 ) {
database . SaveMerchantTemp ( npcid , ml . origslot , item , ml . charges ) ;
tmp_merlist . push_back ( ml ) ;
}
else {
database . DeleteMerchantTemp ( npcid , ml . origslot ) ;
}
}
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2020-04-21 00:40:18 -04:00
tmpmerchanttable [ npcid ] = tmp_merlist ;
//DumpMerchantList(npcid);
return ml . slot ;
2013-02-16 16:14:39 -08:00
}
2020-04-21 00:40:18 -04:00
else {
if ( charges < 0 ) { //sanity check only, shouldnt happen
2013-02-16 16:14:39 -08:00
charges = 0x7FFF ;
2020-04-21 00:40:18 -04:00
}
// Find an ununsed db slot #
std : : list < int > slots ;
TempMerchantList ml3 ;
for ( tmp_itr = tmp_merlist . begin ( ) ; tmp_itr ! = tmp_merlist . end ( ) ; + + tmp_itr ) {
ml3 = * tmp_itr ;
slots . push_back ( ml3 . origslot ) ;
}
slots . sort ( ) ;
std : : list < int > : : const_iterator slots_itr ;
uint32 first_empty_slot = 0 ;
uint32 idx = temp_slot_index ;
for ( slots_itr = slots . begin ( ) ; slots_itr ! = slots . end ( ) ; + + slots_itr ) {
if ( ! first_empty_slot & & * slots_itr > idx ) {
LogInventory ( " Popped [{}] " , * slots_itr ) ;
LogInventory ( " First Gap Found at [{}] " , idx ) ;
break ;
}
+ + idx ;
}
first_empty_slot = idx ;
// Find an ununsed mslot
slots . clear ( ) ;
for ( tmp_itr = tmp_merlist . begin ( ) ; tmp_itr ! = tmp_merlist . end ( ) ; + + tmp_itr ) {
ml3 = * tmp_itr ;
slots . push_back ( ml3 . slot ) ;
}
slots . sort ( ) ;
uint32 first_empty_mslot = 0 ;
idx = temp_slot_index ;
for ( slots_itr = slots . begin ( ) ; slots_itr ! = slots . end ( ) ; + + slots_itr ) {
if ( ! first_empty_mslot & & * slots_itr > idx ) {
LogInventory ( " Popped [{}] " , * slots_itr ) ;
LogInventory ( " First Gap Found at [{}] " , idx ) ;
break ;
}
+ + idx ;
}
first_empty_mslot = idx ;
database . SaveMerchantTemp ( npcid , first_empty_slot , item , charges ) ;
2013-02-16 16:14:39 -08:00
tmp_merlist = tmpmerchanttable [ npcid ] ;
TempMerchantList ml2 ;
ml2 . charges = charges ;
2020-04-21 00:40:18 -04:00
LogInventory ( " Adding slot [{}] with [{}] charges. " , first_empty_mslot , charges ) ;
2013-02-16 16:14:39 -08:00
ml2 . item = item ;
ml2 . npcid = npcid ;
2020-04-21 00:40:18 -04:00
ml2 . slot = first_empty_mslot ;
ml2 . origslot = first_empty_slot ;
2013-02-16 16:14:39 -08:00
tmp_merlist . push_back ( ml2 ) ;
tmpmerchanttable [ npcid ] = tmp_merlist ;
2020-04-21 00:40:18 -04:00
//DumpMerchantList(npcid);
return ml2 . slot ;
2013-02-16 16:14:39 -08:00
}
}
uint32 Zone : : GetTempMerchantQuantity ( uint32 NPCID , uint32 Slot ) {
2013-05-09 10:44:08 -04:00
std : : list < TempMerchantList > TmpMerchantList = tmpmerchanttable [ NPCID ] ;
2013-02-16 16:14:39 -08:00
std : : list < TempMerchantList > : : const_iterator Iterator ;
2014-01-13 22:14:02 -05:00
for ( Iterator = TmpMerchantList . begin ( ) ; Iterator ! = TmpMerchantList . end ( ) ; + + Iterator )
2020-04-21 00:40:18 -04:00
if ( ( * Iterator ) . slot = = Slot ) {
LogInventory ( " Slot [{}] has [{}] charges. " , Slot , ( * Iterator ) . charges ) ;
2013-02-16 16:14:39 -08:00
return ( * Iterator ) . charges ;
2020-04-21 00:40:18 -04:00
}
2013-02-16 16:14:39 -08:00
return 0 ;
}
2014-10-09 23:11:18 -04:00
void Zone : : LoadTempMerchantData ( ) {
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading Temporary Merchant Lists " ) ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
std : : string query = StringFormat (
" SELECT "
2014-11-16 19:04:15 -05:00
" DISTINCT ml.npcid, "
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
" ml.slot, "
" ml.charges, "
" ml.itemid "
" FROM "
" merchantlist_temp ml, "
" spawnentry se, "
" spawn2 s2 "
" WHERE "
" ml.npcid = se.npcid "
" AND se.spawngroupid = s2.spawngroupid "
2014-10-13 15:59:11 -07:00
" AND s2.zone = '%s' AND s2.version = %i "
2014-10-09 23:11:18 -04:00
" ORDER BY ml.slot " , GetShortName ( ) , GetInstanceVersion ( ) ) ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return ;
}
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
std : : map < uint32 , std : : list < TempMerchantList > > : : iterator cur ;
2013-02-16 16:14:39 -08:00
uint32 npcid = 0 ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
2013-02-16 16:14:39 -08:00
TempMerchantList ml ;
ml . npcid = atoul ( row [ 0 ] ) ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
if ( npcid ! = ml . npcid ) {
2013-02-16 16:14:39 -08:00
cur = tmpmerchanttable . find ( ml . npcid ) ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
if ( cur = = tmpmerchanttable . end ( ) ) {
2013-02-16 16:14:39 -08:00
std : : list < TempMerchantList > empty ;
tmpmerchanttable [ ml . npcid ] = empty ;
cur = tmpmerchanttable . find ( ml . npcid ) ;
}
npcid = ml . npcid ;
}
ml . slot = atoul ( row [ 1 ] ) ;
2014-09-29 16:38:18 -04:00
ml . charges = atoul ( row [ 2 ] ) ;
ml . item = atoul ( row [ 3 ] ) ;
2013-02-16 16:14:39 -08:00
ml . origslot = ml . slot ;
cur - > second . push_back ( ml ) ;
}
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
pQueuedMerchantsWorkID = 0 ;
2013-02-16 16:14:39 -08:00
}
2014-10-09 23:11:18 -04:00
void Zone : : LoadNewMerchantData ( uint32 merchantid ) {
2014-08-20 15:36:46 -07:00
2013-02-16 16:14:39 -08:00
std : : list < MerchantList > merlist ;
2014-08-20 15:36:46 -07:00
std : : string query = StringFormat ( " SELECT item, slot, faction_required, level_required, alt_currency_cost, "
2014-11-06 21:41:51 -06:00
" classes_required, probability FROM merchantlist WHERE merchantid=%d ORDER BY slot " , merchantid ) ;
2014-08-20 15:36:46 -07:00
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
MerchantList ml ;
ml . id = merchantid ;
ml . item = atoul ( row [ 0 ] ) ;
ml . slot = atoul ( row [ 1 ] ) ;
ml . faction_required = atoul ( row [ 2 ] ) ;
ml . level_required = atoul ( row [ 3 ] ) ;
2014-11-06 21:41:51 -06:00
ml . alt_currency_cost = atoul ( row [ 4 ] ) ;
ml . classes_required = atoul ( row [ 5 ] ) ;
ml . probability = atoul ( row [ 6 ] ) ;
2014-08-20 15:36:46 -07:00
merlist . push_back ( ml ) ;
}
merchanttable [ merchantid ] = merlist ;
2013-02-16 16:14:39 -08:00
}
2014-10-09 23:11:18 -04:00
void Zone : : GetMerchantDataForZoneLoad ( ) {
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading Merchant Lists " ) ;
2020-04-10 01:43:00 -05:00
std : : string query = StringFormat (
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
" SELECT "
2014-11-01 13:37:06 -04:00
" DISTINCT ml.merchantid, "
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
" ml.slot, "
" ml.item, "
" ml.faction_required, "
" ml.level_required, "
" ml.alt_currency_cost, "
" ml.classes_required, "
" ml.probability "
" FROM "
" merchantlist AS ml, "
" npc_types AS nt, "
" spawnentry AS se, "
" spawn2 AS s2 "
" WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid "
2014-10-09 23:11:18 -04:00
" AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i "
" ORDER BY ml.slot " , GetShortName ( ) , GetInstanceVersion ( ) ) ;
2014-11-30 17:32:11 -08:00
auto results = database . QueryDatabase ( query ) ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
std : : map < uint32 , std : : list < MerchantList > > : : iterator cur ;
2013-02-16 16:14:39 -08:00
uint32 npcid = 0 ;
2014-10-09 23:11:18 -04:00
if ( results . RowCount ( ) = = 0 ) {
2019-09-01 23:54:24 -05:00
LogDebug ( " No Merchant Data found for [{}] " , GetShortName ( ) ) ;
2014-10-09 23:11:18 -04:00
return ;
}
2014-11-30 17:32:11 -08:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
2013-02-16 16:14:39 -08:00
MerchantList ml ;
ml . id = atoul ( row [ 0 ] ) ;
2014-10-09 23:11:18 -04:00
if ( npcid ! = ml . id ) {
2013-02-16 16:14:39 -08:00
cur = merchanttable . find ( ml . id ) ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
if ( cur = = merchanttable . end ( ) ) {
2013-02-16 16:14:39 -08:00
std : : list < MerchantList > empty ;
merchanttable [ ml . id ] = empty ;
cur = merchanttable . find ( ml . id ) ;
}
npcid = ml . id ;
}
2016-05-25 16:10:28 -04:00
auto iter = cur - > second . begin ( ) ;
2013-05-09 10:44:08 -04:00
bool found = false ;
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
while ( iter ! = cur - > second . end ( ) ) {
if ( ( * iter ) . item = = ml . id ) {
2013-05-09 10:44:08 -04:00
found = true ;
break ;
}
2014-01-13 22:14:02 -05:00
+ + iter ;
2013-05-09 10:44:08 -04:00
}
2013-02-16 16:14:39 -08:00
Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync
Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
if ( found ) {
2013-05-09 10:44:08 -04:00
continue ;
}
2013-02-16 16:14:39 -08:00
ml . slot = atoul ( row [ 1 ] ) ;
ml . item = atoul ( row [ 2 ] ) ;
2013-05-09 10:44:08 -04:00
ml . faction_required = atoul ( row [ 3 ] ) ;
ml . level_required = atoul ( row [ 4 ] ) ;
ml . alt_currency_cost = atoul ( row [ 5 ] ) ;
2013-12-26 16:29:09 -05:00
ml . classes_required = atoul ( row [ 6 ] ) ;
2014-08-20 23:41:47 -04:00
ml . probability = atoul ( row [ 7 ] ) ;
2013-02-16 16:14:39 -08:00
cur - > second . push_back ( ml ) ;
}
}
void Zone : : LoadMercTemplates ( ) {
std : : list < MercStanceInfo > merc_stances ;
merc_templates . clear ( ) ;
2014-08-20 15:53:02 -07:00
std : : string query = " SELECT `class_id`, `proficiency_id`, `stance_id`, `isdefault` FROM "
" `merc_stance_entries` ORDER BY `class_id`, `proficiency_id`, `stance_id` " ;
2019-09-01 22:05:44 -05:00
auto results = database . QueryDatabase ( query ) ;
2017-04-01 03:51:46 -05:00
if ( ! results . Success ( ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Error in ZoneDatabase::LoadMercTemplates() " ) ;
2017-04-01 03:51:46 -05:00
}
2013-02-16 16:14:39 -08:00
else {
2014-08-20 15:53:02 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
2013-02-16 16:14:39 -08:00
MercStanceInfo tempMercStanceInfo ;
2019-09-01 22:05:44 -05:00
tempMercStanceInfo . ClassID = atoi ( row [ 0 ] ) ;
2014-08-20 15:53:02 -07:00
tempMercStanceInfo . ProficiencyID = atoi ( row [ 1 ] ) ;
2019-09-01 22:05:44 -05:00
tempMercStanceInfo . StanceID = atoi ( row [ 2 ] ) ;
tempMercStanceInfo . IsDefault = atoi ( row [ 3 ] ) ;
2013-02-16 16:14:39 -08:00
merc_stances . push_back ( tempMercStanceInfo ) ;
}
}
2014-08-20 15:53:02 -07:00
query = " SELECT DISTINCT MTem.merc_template_id, MTyp.dbstring "
" AS merc_type_id, MTem.dbstring "
" AS merc_subtype_id, MTyp.race_id, MS.class_id, MTyp.proficiency_id, MS.tier_id, 0 "
" AS CostFormula, MTem.clientversion, MTem.merc_npc_type_id "
" FROM merc_types MTyp, merc_templates MTem, merc_subtypes MS "
" WHERE MTem.merc_type_id = MTyp.merc_type_id AND MTem.merc_subtype_id = MS.merc_subtype_id "
2019-09-01 22:05:44 -05:00
" ORDER BY MTyp.race_id, MS.class_id, MTyp.proficiency_id; " ;
results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
LogError ( " Error in ZoneDatabase::LoadMercTemplates() " ) ;
return ;
2013-02-16 16:14:39 -08:00
}
2013-03-14 19:51:29 -04:00
2014-08-20 15:53:02 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
2013-02-16 16:14:39 -08:00
2014-08-20 15:53:02 -07:00
MercTemplate tempMercTemplate ;
2013-02-16 16:14:39 -08:00
2014-08-20 15:53:02 -07:00
tempMercTemplate . MercTemplateID = atoi ( row [ 0 ] ) ;
tempMercTemplate . MercType = atoi ( row [ 1 ] ) ;
tempMercTemplate . MercSubType = atoi ( row [ 2 ] ) ;
tempMercTemplate . RaceID = atoi ( row [ 3 ] ) ;
tempMercTemplate . ClassID = atoi ( row [ 4 ] ) ;
tempMercTemplate . ProficiencyID = atoi ( row [ 5 ] ) ;
tempMercTemplate . TierID = atoi ( row [ 6 ] ) ;
tempMercTemplate . CostFormula = atoi ( row [ 7 ] ) ;
tempMercTemplate . ClientVersion = atoi ( row [ 8 ] ) ;
tempMercTemplate . MercNPCID = atoi ( row [ 9 ] ) ;
2013-02-16 16:14:39 -08:00
2014-08-20 15:53:02 -07:00
for ( int i = 0 ; i < MaxMercStanceID ; i + + )
tempMercTemplate . Stances [ i ] = 0 ;
2013-02-16 16:14:39 -08:00
2014-08-20 15:53:02 -07:00
int stanceIndex = 0 ;
2014-09-04 22:51:31 -07:00
for ( auto mercStanceListItr = merc_stances . begin ( ) ; mercStanceListItr ! = merc_stances . end ( ) ; + + mercStanceListItr ) {
2014-08-20 15:53:02 -07:00
if ( mercStanceListItr - > ClassID ! = tempMercTemplate . ClassID | | mercStanceListItr - > ProficiencyID ! = tempMercTemplate . ProficiencyID )
continue ;
2013-02-16 16:14:39 -08:00
2014-08-20 15:53:02 -07:00
zone - > merc_stance_list [ tempMercTemplate . MercTemplateID ] . push_back ( ( * mercStanceListItr ) ) ;
tempMercTemplate . Stances [ stanceIndex ] = mercStanceListItr - > StanceID ;
2014-09-04 22:51:31 -07:00
+ + stanceIndex ;
2014-08-20 15:53:02 -07:00
}
2013-02-16 16:14:39 -08:00
2014-08-20 15:53:02 -07:00
merc_templates [ tempMercTemplate . MercTemplateID ] = tempMercTemplate ;
2014-09-04 22:51:31 -07:00
2014-08-20 15:53:02 -07:00
}
2013-02-16 16:14:39 -08:00
}
void Zone : : LoadLevelEXPMods ( ) {
2014-08-20 15:57:04 -07:00
level_exp_mod . clear ( ) ;
const std : : string query = " SELECT level, exp_mod, aa_exp_mod FROM level_exp_mods " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Error in ZoneDatabase::LoadEXPLevelMods() " ) ;
2014-08-20 15:57:04 -07:00
return ;
}
2013-02-16 16:14:39 -08:00
2014-08-20 15:57:04 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
uint32 index = atoi ( row [ 0 ] ) ;
float exp_mod = atof ( row [ 1 ] ) ;
float aa_exp_mod = atof ( row [ 2 ] ) ;
level_exp_mod [ index ] . ExpMod = exp_mod ;
level_exp_mod [ index ] . AAExpMod = aa_exp_mod ;
}
2013-02-16 16:14:39 -08:00
}
2014-08-20 15:57:04 -07:00
2013-02-16 16:14:39 -08:00
void Zone : : LoadMercSpells ( ) {
merc_spells_list . clear ( ) ;
2014-08-20 16:00:36 -07:00
const std : : string query = " SELECT msl.class_id, msl.proficiency_id, msle.spell_id, msle.spell_type, "
" msle.stance_id, msle.minlevel, msle.maxlevel, msle.slot, msle.procChance "
" FROM merc_spell_lists msl, merc_spell_list_entries msle "
" WHERE msle.merc_spell_list_id = msl.merc_spell_list_id "
" ORDER BY msl.class_id, msl.proficiency_id, msle.spell_type, msle.minlevel, msle.slot; " ;
2019-09-01 22:05:44 -05:00
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
LogError ( " Error in Zone::LoadMercSpells() " ) ;
return ;
}
2013-02-16 16:14:39 -08:00
2014-08-20 16:00:36 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
uint32 classid ;
MercSpellEntry tempMercSpellEntry ;
classid = atoi ( row [ 0 ] ) ;
tempMercSpellEntry . proficiencyid = atoi ( row [ 1 ] ) ;
tempMercSpellEntry . spellid = atoi ( row [ 2 ] ) ;
tempMercSpellEntry . type = atoi ( row [ 3 ] ) ;
tempMercSpellEntry . stance = atoi ( row [ 4 ] ) ;
tempMercSpellEntry . minlevel = atoi ( row [ 5 ] ) ;
tempMercSpellEntry . maxlevel = atoi ( row [ 6 ] ) ;
tempMercSpellEntry . slot = atoi ( row [ 7 ] ) ;
tempMercSpellEntry . proc_chance = atoi ( row [ 8 ] ) ;
merc_spells_list [ classid ] . push_back ( tempMercSpellEntry ) ;
}
2013-02-16 16:14:39 -08:00
2017-04-01 03:51:46 -05:00
Log ( Logs : : General , Logs : : Mercenaries , " Loaded %i merc spells. " , merc_spells_list [ 1 ] . size ( ) + merc_spells_list [ 2 ] . size ( ) + merc_spells_list [ 9 ] . size ( ) + merc_spells_list [ 12 ] . size ( ) ) ;
2013-02-16 16:14:39 -08:00
}
2014-08-24 05:42:43 -04:00
bool Zone : : IsLoaded ( ) {
2015-10-31 20:19:57 -05:00
return is_zone_loaded ;
2014-08-24 05:42:43 -04:00
}
2019-09-06 12:26:30 -05:00
void Zone : : Shutdown ( bool quiet )
2013-02-16 16:14:39 -08:00
{
2019-09-06 12:26:30 -05:00
if ( ! is_zone_loaded ) {
2013-02-16 16:14:39 -08:00
return ;
2019-09-06 12:26:30 -05:00
}
2013-02-16 16:14:39 -08:00
2015-01-10 02:34:06 -05:00
entity_list . StopMobAI ( ) ;
2014-08-24 05:42:43 -04:00
2019-09-06 12:26:30 -05:00
std : : map < uint32 , NPCType * > : : iterator itr ;
while ( ! zone - > npctable . empty ( ) ) {
itr = zone - > npctable . begin ( ) ;
2013-02-16 16:14:39 -08:00
delete itr - > second ;
zone - > npctable . erase ( itr ) ;
}
2019-09-06 12:26:30 -05:00
while ( ! zone - > merctable . empty ( ) ) {
itr = zone - > merctable . begin ( ) ;
2013-02-16 16:14:39 -08:00
delete itr - > second ;
zone - > merctable . erase ( itr ) ;
}
zone - > adventure_entry_list_flavor . clear ( ) ;
2019-09-06 12:26:30 -05:00
std : : map < uint32 , LDoNTrapTemplate * > : : iterator itr4 ;
while ( ! zone - > ldon_trap_list . empty ( ) ) {
2013-02-16 16:14:39 -08:00
itr4 = zone - > ldon_trap_list . begin ( ) ;
delete itr4 - > second ;
zone - > ldon_trap_list . erase ( itr4 ) ;
}
zone - > ldon_trap_entry_list . clear ( ) ;
2019-09-01 23:22:40 -05:00
LogInfo ( " Zone Shutdown: [{}] ([{}]) " , zone - > GetShortName ( ) , zone - > GetZoneID ( ) ) ;
2013-02-16 16:14:39 -08:00
petition_list . ClearPetitions ( ) ;
2015-05-25 23:48:11 -05:00
zone - > SetZoneHasCurrentTime ( false ) ;
2019-09-06 12:26:30 -05:00
if ( ! quiet ) {
LogInfo ( " Zone Shutdown: Going to sleep " ) ;
}
2015-10-31 20:19:57 -05:00
is_zone_loaded = false ;
2014-08-20 15:32:14 -07:00
2013-02-16 16:14:39 -08:00
zone - > ResetAuth ( ) ;
safe_delete ( zone ) ;
2013-06-22 14:23:07 -07:00
entity_list . ClearAreas ( ) ;
2013-05-15 16:01:13 -07:00
parse - > ReloadQuests ( true ) ;
2019-10-13 18:49:16 -07:00
UpdateWindowTitle ( nullptr ) ;
2015-01-10 03:44:49 -06:00
2017-04-01 03:51:46 -05:00
LogSys . CloseFileLogs ( ) ;
2019-09-06 12:26:30 -05:00
if ( RuleB ( Zone , KillProcessOnDynamicShutdown ) ) {
LogInfo ( " [KillProcessOnDynamicShutdown] Shutting down " ) ;
2020-04-14 23:28:43 -05:00
EQ : : EventLoop : : Get ( ) . Shutdown ( ) ;
2019-09-06 12:26:30 -05:00
}
2013-02-16 16:14:39 -08:00
}
void Zone : : LoadZoneDoors ( const char * zone , int16 version )
{
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading doors for [{}] " , zone ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
uint32 maxid ;
int32 count = database . GetDoorsCount ( & maxid , zone , version ) ;
if ( count < 1 ) {
2019-09-01 23:22:40 -05:00
LogInfo ( " No doors loaded " ) ;
2013-02-16 16:14:39 -08:00
return ;
}
2013-05-06 13:07:41 -04:00
2016-05-25 16:10:28 -04:00
auto dlist = new Door [ count ] ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( ! database . LoadDoors ( count , dlist , zone , version ) ) {
2019-09-01 23:22:40 -05:00
LogError ( " Failed to load doors " ) ;
2013-02-16 16:14:39 -08:00
delete [ ] dlist ;
return ;
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
int r ;
Door * d = dlist ;
for ( r = 0 ; r < count ; r + + , d + + ) {
2016-05-25 16:10:28 -04:00
auto newdoor = new Doors ( d ) ;
2013-02-16 16:14:39 -08:00
entity_list . AddDoor ( newdoor ) ;
2017-04-01 03:51:46 -05:00
Log ( Logs : : Detail , Logs : : Doors , " Door Add to Entity List, index: %u db id: %u, door_id %u " , r , dlist [ r ] . db_id , dlist [ r ] . door_id ) ;
2013-02-16 16:14:39 -08:00
}
delete [ ] dlist ;
}
Zone : : Zone ( uint32 in_zoneid , uint32 in_instanceid , const char * in_short_name )
: initgrids_timer ( 10000 ) ,
autoshutdown_timer ( ( RuleI ( Zone , AutoShutdownDelay ) ) ) ,
clientauth_timer ( AUTHENTICATION_TIMEOUT * 1000 ) ,
spawn2_timer ( 1000 ) ,
2020-01-31 20:25:06 -06:00
hot_reload_timer ( 1000 ) ,
2013-04-24 15:58:51 -05:00
qglobal_purge_timer ( 30000 ) ,
2014-12-01 22:35:46 -08:00
hotzone_timer ( 120000 ) ,
2014-12-01 23:12:19 -08:00
m_SafePoint ( 0.0f , 0.0f , 0.0f ) ,
m_Graveyard ( 0.0f , 0.0f , 0.0f , 0.0f )
2013-02-16 16:14:39 -08:00
{
zoneid = in_zoneid ;
instanceid = in_instanceid ;
instanceversion = database . GetInstanceVersion ( instanceid ) ;
2014-11-18 21:12:48 -08:00
pers_instance = false ;
2013-05-06 13:07:41 -04:00
zonemap = nullptr ;
watermap = nullptr ;
pathing = nullptr ;
2013-05-04 18:06:58 -07:00
qGlobals = nullptr ;
2013-02-16 16:14:39 -08:00
default_ruleset = 0 ;
2015-05-25 23:48:11 -05:00
is_zone_time_localized = false ;
2013-06-28 04:25:44 -04:00
loglevelvar = 0 ;
merchantvar = 0 ;
tradevar = 0 ;
lootvar = 0 ;
2013-02-16 16:14:39 -08:00
if ( RuleB ( TaskSystem , EnableTaskSystem ) ) {
taskmanager - > LoadProximities ( zoneid ) ;
}
short_name = strcpy ( new char [ strlen ( in_short_name ) + 1 ] , in_short_name ) ;
strlwr ( short_name ) ;
memset ( file_name , 0 , sizeof ( file_name ) ) ;
long_name = 0 ;
aggroedmobs = 0 ;
pgraveyard_id = 0 ;
pgraveyard_zoneid = 0 ;
pMaxClients = 0 ;
pQueuedMerchantsWorkID = 0 ;
pvpzone = false ;
if ( database . GetServerType ( ) = = 1 )
pvpzone = true ;
2015-01-23 00:01:10 -08:00
database . GetZoneLongName ( short_name , & long_name , file_name , & m_SafePoint . x , & m_SafePoint . y , & m_SafePoint . z , & pgraveyard_id , & pMaxClients ) ;
2013-02-16 16:14:39 -08:00
if ( graveyard_id ( ) > 0 )
{
2019-09-01 23:54:24 -05:00
LogDebug ( " Graveyard ID is [{}] " , graveyard_id ( ) ) ;
2015-01-23 00:01:10 -08:00
bool GraveYardLoaded = database . GetZoneGraveyard ( graveyard_id ( ) , & pgraveyard_zoneid , & m_Graveyard . x , & m_Graveyard . y , & m_Graveyard . z , & m_Graveyard . w ) ;
2020-04-10 01:43:00 -05:00
2017-04-01 03:51:46 -05:00
if ( GraveYardLoaded ) {
2019-09-01 23:54:24 -05:00
LogDebug ( " Loaded a graveyard for zone [{}]: graveyard zoneid is [{}] at [{}] " , short_name , graveyard_zoneid ( ) , to_string ( m_Graveyard ) . c_str ( ) ) ;
2017-04-01 03:51:46 -05:00
}
else {
2019-09-01 22:05:44 -05:00
LogError ( " Unable to load the graveyard id [{}] for zone [{}] " , graveyard_id ( ) , short_name ) ;
2017-04-01 03:51:46 -05:00
}
2013-02-16 16:14:39 -08:00
}
if ( long_name = = 0 ) {
long_name = strcpy ( new char [ 18 ] , " Long zone missing " ) ;
}
autoshutdown_timer . Start ( AUTHENTICATION_TIMEOUT * 1000 , false ) ;
2014-01-20 10:10:39 -08:00
Weather_Timer = new Timer ( 60000 ) ;
2013-02-16 16:14:39 -08:00
Weather_Timer - > Start ( ) ;
2019-09-01 23:54:24 -05:00
LogDebug ( " The next weather check for zone: [{}] will be in [{}] seconds " , short_name , Weather_Timer - > GetRemainingTime ( ) / 1000 ) ;
2019-09-01 16:51:39 -05:00
zone_weather = 0 ;
weather_intensity = 0 ;
blocked_spells = nullptr ;
zone_total_blocked_spells = 0 ;
zone_has_current_time = false ;
2013-05-06 13:07:41 -04:00
2013-05-04 18:06:58 -07:00
Instance_Shutdown_Timer = nullptr ;
2013-02-16 16:14:39 -08:00
bool is_perma = false ;
if ( instanceid > 0 )
{
uint32 rem = database . GetTimeRemainingInstance ( instanceid , is_perma ) ;
if ( ! is_perma )
{
if ( rem < 150 ) //give some leeway to people who are zoning in 2.5 minutes to finish zoning in and get ported out
2014-11-18 21:12:48 -08:00
rem = 150 ;
2013-02-16 16:14:39 -08:00
Instance_Timer = new Timer ( rem * 1000 ) ;
}
else
{
2014-11-18 21:12:48 -08:00
pers_instance = true ;
2013-05-04 18:06:58 -07:00
Instance_Timer = nullptr ;
2013-02-16 16:14:39 -08:00
}
}
else
{
2013-05-04 18:06:58 -07:00
Instance_Timer = nullptr ;
2013-02-16 16:14:39 -08:00
}
2013-05-04 18:06:58 -07:00
adv_data = nullptr ;
map_name = nullptr ;
Instance_Warning_timer = nullptr ;
2013-02-16 16:14:39 -08:00
did_adventure_actions = false ;
database . QGlobalPurge ( ) ;
if ( zoneid = = RuleI ( World , GuildBankZoneID ) )
GuildBanks = new GuildBankManager ;
else
2013-05-04 18:06:58 -07:00
GuildBanks = nullptr ;
2018-03-04 21:38:17 -05:00
m_ucss_available = false ;
m_last_ucss_update = 0 ;
2018-09-17 14:32:36 -07:00
mMovementManager = & MobMovementManager : : Get ( ) ;
2019-08-07 18:54:53 -05:00
SetNpcPositionUpdateDistance ( 0 ) ;
2020-01-31 20:25:06 -06:00
SetQuestHotReloadQueued ( false ) ;
2013-02-16 16:14:39 -08:00
}
Zone : : ~ Zone ( ) {
spawn2_list . Clear ( ) ;
safe_delete ( zonemap ) ;
safe_delete ( watermap ) ;
safe_delete ( pathing ) ;
if ( worldserver . Connected ( ) ) {
2015-10-31 20:19:57 -05:00
worldserver . SetZoneData ( 0 ) ;
2013-02-16 16:14:39 -08:00
}
safe_delete_array ( short_name ) ;
safe_delete_array ( long_name ) ;
safe_delete ( Weather_Timer ) ;
NPCEmoteList . Clear ( ) ;
zone_point_list . Clear ( ) ;
entity_list . Clear ( ) ;
ClearBlockedSpells ( ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
safe_delete ( Instance_Timer ) ;
safe_delete ( Instance_Shutdown_Timer ) ;
safe_delete ( Instance_Warning_timer ) ;
safe_delete ( qGlobals ) ;
safe_delete_array ( adv_data ) ;
safe_delete_array ( map_name ) ;
safe_delete ( GuildBanks ) ;
}
//Modified for timezones.
bool Zone : : Init ( bool iStaticZone ) {
SetStaticZone ( iStaticZone ) ;
2020-04-10 01:43:00 -05:00
2016-09-28 19:26:44 -07:00
//load the zone config file.
2018-12-07 12:17:27 -05:00
if ( ! LoadZoneCFG ( zone - > GetShortName ( ) , zone - > GetInstanceVersion ( ) ) ) // try loading the zone name...
2016-09-28 19:26:44 -07:00
LoadZoneCFG ( zone - > GetFileName ( ) , zone - > GetInstanceVersion ( ) ) ; // if that fails, try the file name, then load defaults
if ( RuleManager : : Instance ( ) - > GetActiveRulesetID ( ) ! = default_ruleset )
{
std : : string r_name = RuleManager : : Instance ( ) - > GetRulesetName ( & database , default_ruleset ) ;
if ( r_name . size ( ) > 0 )
{
2019-01-11 05:01:44 -05:00
RuleManager : : Instance ( ) - > LoadRules ( & database , r_name . c_str ( ) , false ) ;
2016-09-28 19:26:44 -07:00
}
}
2018-09-03 03:06:23 -05:00
zone - > zonemap = Map : : LoadMapFile ( zone - > map_name ) ;
2016-09-28 19:26:44 -07:00
zone - > watermap = WaterMap : : LoadWaterMapfile ( zone - > map_name ) ;
2018-09-03 03:06:23 -05:00
zone - > pathing = IPathfinder : : Load ( zone - > map_name ) ;
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading spawn conditions " ) ;
2013-02-16 16:14:39 -08:00
if ( ! spawn_conditions . LoadSpawnConditions ( short_name , instanceid ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Loading spawn conditions failed, continuing without them " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading static zone points " ) ;
2013-02-16 16:14:39 -08:00
if ( ! database . LoadStaticZonePoints ( & zone_point_list , short_name , GetInstanceVersion ( ) ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Loading static zone points failed " ) ;
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading spawn groups " ) ;
2013-02-16 16:14:39 -08:00
if ( ! database . LoadSpawnGroups ( short_name , GetInstanceVersion ( ) , & spawn_group_list ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Loading spawn groups failed " ) ;
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading spawn2 points " ) ;
2013-02-16 16:14:39 -08:00
if ( ! database . PopulateZoneSpawnList ( zoneid , spawn2_list , GetInstanceVersion ( ) ) )
{
2019-09-01 22:05:44 -05:00
LogError ( " Loading spawn2 points failed " ) ;
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading player corpses " ) ;
2014-11-22 17:55:48 -06:00
if ( ! database . LoadCharacterCorpses ( zoneid , instanceid ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Loading player corpses failed " ) ;
2013-02-16 16:14:39 -08:00
return false ;
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading traps " ) ;
2013-02-16 16:14:39 -08:00
if ( ! database . LoadTraps ( short_name , GetInstanceVersion ( ) ) )
{
2019-09-01 22:05:44 -05:00
LogError ( " Loading traps failed " ) ;
2013-02-16 16:14:39 -08:00
return false ;
}
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading adventure flavor text " ) ;
2013-02-16 16:14:39 -08:00
LoadAdventureFlavor ( ) ;
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading ground spawns " ) ;
2013-02-16 16:14:39 -08:00
if ( ! LoadGroundSpawns ( ) )
{
2019-09-01 22:05:44 -05:00
LogError ( " Loading ground spawns failed. continuing " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading World Objects from DB " ) ;
2013-02-16 16:14:39 -08:00
if ( ! LoadZoneObjects ( ) )
{
2019-09-01 22:05:44 -05:00
LogError ( " Loading World Objects failed. continuing " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Flushing old respawn timers " ) ;
2015-02-08 05:01:58 -06:00
database . QueryDatabase ( " DELETE FROM `respawn_times` WHERE (`start` + `duration`) < UNIX_TIMESTAMP(NOW()) " ) ;
2013-02-16 16:14:39 -08:00
//load up the zone's doors (prints inside)
zone - > LoadZoneDoors ( zone - > GetShortName ( ) , zone - > GetInstanceVersion ( ) ) ;
2019-09-01 16:51:39 -05:00
zone - > LoadZoneBlockedSpells ( zone - > GetZoneID ( ) ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//clear trader items if we are loading the bazaar
if ( strncasecmp ( short_name , " bazaar " , 6 ) = = 0 ) {
database . DeleteTraderItem ( 0 ) ;
database . DeleteBuyLines ( 0 ) ;
}
zone - > LoadLDoNTraps ( ) ;
zone - > LoadLDoNTrapEntries ( ) ;
zone - > LoadVeteranRewards ( ) ;
2013-05-09 10:44:08 -04:00
zone - > LoadAlternateCurrencies ( ) ;
2013-02-16 16:14:39 -08:00
zone - > LoadNPCEmotes ( & NPCEmoteList ) ;
2015-06-07 19:42:12 -07:00
LoadAlternateAdvancement ( ) ;
Implement global loot system Fixes #619
This should allow us to emulate lives global tables
The options available to filter tables are min_level, max_level, race,
rare, raid, race, class, bodytype, and zone.
race, class, bodytype, and zone are a pipe | separated list of IDs
2018-02-10 22:15:21 -05:00
database . LoadGlobalLoot ( ) ;
2013-02-16 16:14:39 -08:00
//Load merchant data
zone - > GetMerchantDataForZoneLoad ( ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//Load temporary merchant data
zone - > LoadTempMerchantData ( ) ;
// Merc data
if ( RuleB ( Mercs , AllowMercs ) ) {
zone - > LoadMercTemplates ( ) ;
zone - > LoadMercSpells ( ) ;
}
if ( RuleB ( Zone , LevelBasedEXPMods ) )
zone - > LoadLevelEXPMods ( ) ;
petition_list . ClearPetitions ( ) ;
petition_list . ReadDatabase ( ) ;
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Loading timezone data " ) ;
2013-02-16 16:14:39 -08:00
zone - > zone_time . setEQTimeZone ( database . GetZoneTZ ( zoneid , GetInstanceVersion ( ) ) ) ;
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Init Finished: ZoneID = [{}], Time Offset = [{}] " , zoneid , zone - > zone_time . getEQTimeZone ( ) ) ;
2013-04-24 15:58:51 -05:00
LoadTickItems ( ) ;
//MODDING HOOK FOR ZONE INIT
mod_init ( ) ;
2013-02-16 16:14:39 -08:00
return true ;
}
void Zone : : ReloadStaticData ( ) {
2019-09-01 23:22:40 -05:00
LogInfo ( " Reloading Zone Static Data " ) ;
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Reloading static zone points " ) ;
2013-02-16 16:14:39 -08:00
zone_point_list . Clear ( ) ;
if ( ! database . LoadStaticZonePoints ( & zone_point_list , GetShortName ( ) , GetInstanceVersion ( ) ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Loading static zone points failed " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Reloading traps " ) ;
2013-02-16 16:14:39 -08:00
entity_list . RemoveAllTraps ( ) ;
if ( ! database . LoadTraps ( GetShortName ( ) , GetInstanceVersion ( ) ) )
{
2019-09-01 22:05:44 -05:00
LogError ( " Reloading traps failed " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Reloading ground spawns " ) ;
2013-02-16 16:14:39 -08:00
if ( ! LoadGroundSpawns ( ) )
{
2019-09-01 22:05:44 -05:00
LogError ( " Reloading ground spawns failed. continuing " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
entity_list . RemoveAllObjects ( ) ;
2019-09-01 23:22:40 -05:00
LogInfo ( " Reloading World Objects from DB " ) ;
2013-02-16 16:14:39 -08:00
if ( ! LoadZoneObjects ( ) )
{
2019-09-01 22:05:44 -05:00
LogError ( " Reloading World Objects failed. continuing " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
entity_list . RemoveAllDoors ( ) ;
zone - > LoadZoneDoors ( zone - > GetShortName ( ) , zone - > GetInstanceVersion ( ) ) ;
entity_list . RespawnAllDoors ( ) ;
zone - > LoadVeteranRewards ( ) ;
2013-05-09 10:44:08 -04:00
zone - > LoadAlternateCurrencies ( ) ;
2013-02-16 16:14:39 -08:00
NPCEmoteList . Clear ( ) ;
zone - > LoadNPCEmotes ( & NPCEmoteList ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//load the zone config file.
2018-12-07 12:17:27 -05:00
if ( ! LoadZoneCFG ( zone - > GetShortName ( ) , zone - > GetInstanceVersion ( ) ) ) // try loading the zone name...
2013-02-16 16:14:39 -08:00
LoadZoneCFG ( zone - > GetFileName ( ) , zone - > GetInstanceVersion ( ) ) ; // if that fails, try the file name, then load defaults
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Zone Static Data Reloaded " ) ;
2013-02-16 16:14:39 -08:00
}
2018-12-07 12:17:27 -05:00
bool Zone : : LoadZoneCFG ( const char * filename , uint16 instance_id )
2013-02-16 16:14:39 -08:00
{
2018-12-07 12:17:27 -05:00
2013-02-16 16:14:39 -08:00
memset ( & newzone_data , 0 , sizeof ( NewZone_Struct ) ) ;
2018-12-07 12:17:27 -05:00
map_name = nullptr ;
if ( ! database . GetZoneCFG ( database . GetZoneID ( filename ) , instance_id , & newzone_data , can_bind ,
2019-03-13 22:55:49 -07:00
can_combat , can_levitate , can_castoutdoor , is_city , is_hotzone , allow_mercs , max_movement_update_range , zone_type , default_ruleset , & map_name ) )
2013-02-16 16:14:39 -08:00
{
2018-12-07 12:17:27 -05:00
// If loading a non-zero instance failed, try loading the default
if ( instance_id ! = 0 )
2013-02-16 16:14:39 -08:00
{
safe_delete_array ( map_name ) ;
2020-04-10 01:43:00 -05:00
if ( ! database . GetZoneCFG ( database . GetZoneID ( filename ) , 0 , & newzone_data , can_bind , can_combat , can_levitate ,
2019-03-13 22:55:49 -07:00
can_castoutdoor , is_city , is_hotzone , allow_mercs , max_movement_update_range , zone_type , default_ruleset , & map_name ) )
2018-12-07 12:17:27 -05:00
{
2019-09-01 22:05:44 -05:00
LogError ( " Error loading the Zone Config " ) ;
2013-02-16 16:14:39 -08:00
return false ;
2018-12-07 12:17:27 -05:00
}
2013-02-16 16:14:39 -08:00
}
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//overwrite with our internal variables
strcpy ( newzone_data . zone_short_name , GetShortName ( ) ) ;
strcpy ( newzone_data . zone_long_name , GetLongName ( ) ) ;
strcpy ( newzone_data . zone_short_name2 , GetShortName ( ) ) ;
2013-05-06 13:07:41 -04:00
2019-09-01 23:22:40 -05:00
LogInfo ( " Successfully loaded Zone Config " ) ;
2013-02-16 16:14:39 -08:00
return true ;
}
bool Zone : : SaveZoneCFG ( ) {
return database . SaveZoneCFG ( GetZoneID ( ) , GetInstanceVersion ( ) , & newzone_data ) ;
}
2015-01-30 15:03:02 -08:00
void Zone : : AddAuth ( ServerZoneIncomingClient_Struct * szic ) {
2016-05-25 16:10:28 -04:00
auto zca = new ZoneClientAuth_Struct ;
2013-02-16 16:14:39 -08:00
memset ( zca , 0 , sizeof ( ZoneClientAuth_Struct ) ) ;
zca - > ip = szic - > ip ;
zca - > wid = szic - > wid ;
zca - > accid = szic - > accid ;
zca - > admin = szic - > admin ;
zca - > charid = szic - > charid ;
2019-07-23 21:59:22 -07:00
zca - > lsid = szic - > lsid ;
2013-02-16 16:14:39 -08:00
zca - > tellsoff = szic - > tellsoff ;
strn0cpy ( zca - > charname , szic - > charname , sizeof ( zca - > charname ) ) ;
strn0cpy ( zca - > lskey , szic - > lskey , sizeof ( zca - > lskey ) ) ;
zca - > stale = false ;
client_auth_list . Insert ( zca ) ;
}
2019-07-24 19:20:09 -07:00
void Zone : : RemoveAuth ( const char * iCharName , const char * iLSKey )
2013-02-16 16:14:39 -08:00
{
LinkedListIterator < ZoneClientAuth_Struct * > iterator ( client_auth_list ) ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
ZoneClientAuth_Struct * zca = iterator . GetData ( ) ;
2019-07-24 19:20:09 -07:00
if ( strcasecmp ( zca - > charname , iCharName ) = = 0 & & strcasecmp ( zca - > lskey , iLSKey ) = = 0 ) {
iterator . RemoveCurrent ( ) ;
return ;
2013-02-16 16:14:39 -08:00
}
iterator . Advance ( ) ;
}
}
2019-07-23 21:59:22 -07:00
void Zone : : RemoveAuth ( uint32 lsid )
{
LinkedListIterator < ZoneClientAuth_Struct * > iterator ( client_auth_list ) ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
ZoneClientAuth_Struct * zca = iterator . GetData ( ) ;
if ( zca - > lsid = = lsid ) {
iterator . RemoveCurrent ( ) ;
2019-07-25 22:26:56 -07:00
continue ;
2019-07-23 21:59:22 -07:00
}
iterator . Advance ( ) ;
}
}
2013-02-16 16:14:39 -08:00
void Zone : : ResetAuth ( )
{
LinkedListIterator < ZoneClientAuth_Struct * > iterator ( client_auth_list ) ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
iterator . RemoveCurrent ( ) ;
}
}
bool Zone : : GetAuth ( uint32 iIP , const char * iCharName , uint32 * oWID , uint32 * oAccID , uint32 * oCharID , int16 * oStatus , char * oLSKey , bool * oTellsOff ) {
LinkedListIterator < ZoneClientAuth_Struct * > iterator ( client_auth_list ) ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
ZoneClientAuth_Struct * zca = iterator . GetData ( ) ;
if ( strcasecmp ( zca - > charname , iCharName ) = = 0 ) {
if ( oWID )
* oWID = zca - > wid ;
if ( oAccID )
* oAccID = zca - > accid ;
if ( oCharID )
* oCharID = zca - > charid ;
if ( oStatus )
* oStatus = zca - > admin ;
if ( oTellsOff )
* oTellsOff = zca - > tellsoff ;
zca - > stale = true ;
return true ;
}
iterator . Advance ( ) ;
}
return false ;
}
uint32 Zone : : CountAuth ( ) {
LinkedListIterator < ZoneClientAuth_Struct * > iterator ( client_auth_list ) ;
int x = 0 ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
x + + ;
iterator . Advance ( ) ;
}
return x ;
}
bool Zone : : Process ( ) {
spawn_conditions . Process ( ) ;
2019-08-07 18:54:53 -05:00
if ( spawn2_timer . Check ( ) ) {
2017-08-18 20:53:26 -05:00
2019-08-07 18:54:53 -05:00
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
2013-02-16 16:14:39 -08:00
2020-05-17 18:36:06 -07:00
EQ : : InventoryProfile : : CleanDirty ( ) ;
2013-06-25 14:51:06 -07:00
2019-09-02 04:10:43 -05:00
LogSpawns ( " Running Zone::Process -> Spawn2::Process " ) ;
2017-08-18 20:53:26 -05:00
2013-02-16 16:14:39 -08:00
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
if ( iterator . GetData ( ) - > Process ( ) ) {
iterator . Advance ( ) ;
}
else {
iterator . RemoveCurrent ( ) ;
}
}
2017-08-18 20:53:26 -05:00
2019-08-07 18:54:53 -05:00
if ( adv_data & & ! did_adventure_actions ) {
2013-02-16 16:14:39 -08:00
DoAdventureActions ( ) ;
2019-08-07 18:54:53 -05:00
}
2017-08-18 20:53:26 -05:00
2019-08-07 18:54:53 -05:00
if ( GetNpcPositionUpdateDistance ( ) = = 0 ) {
CalculateNpcUpdateDistanceSpread ( ) ;
}
2013-02-16 16:14:39 -08:00
}
2019-08-07 18:54:53 -05:00
2020-01-31 20:25:06 -06:00
if ( hot_reload_timer . Check ( ) & & IsQuestHotReloadQueued ( ) ) {
LogHotReloadDetail ( " Hot reload timer check... " ) ;
bool perform_reload = true ;
2020-01-31 21:51:05 -06:00
if ( RuleB ( HotReload , QuestsRepopWhenPlayersNotInCombat ) ) {
for ( auto & it : entity_list . GetClientList ( ) ) {
auto client = it . second ;
if ( client - > GetAggroCount ( ) > 0 ) {
perform_reload = false ;
break ;
}
2020-01-31 20:25:06 -06:00
}
}
if ( perform_reload ) {
ZoneReload : : HotReloadQuests ( ) ;
}
}
2013-02-16 16:14:39 -08:00
if ( initgrids_timer . Check ( ) ) {
//delayed grid loading stuff.
initgrids_timer . Disable ( ) ;
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
iterator . GetData ( ) - > LoadGrid ( ) ;
iterator . Advance ( ) ;
}
}
if ( ! staticzone ) {
if ( autoshutdown_timer . Check ( ) ) {
StartShutdownTimer ( ) ;
if ( numclients = = 0 ) {
return false ;
}
}
}
if ( GetInstanceID ( ) > 0 )
{
2013-05-04 18:06:58 -07:00
if ( Instance_Timer ! = nullptr & & Instance_Shutdown_Timer = = nullptr )
2013-02-16 16:14:39 -08:00
{
if ( Instance_Timer - > Check ( ) )
{
entity_list . GateAllClients ( ) ;
database . DeleteInstance ( GetInstanceID ( ) ) ;
Instance_Shutdown_Timer = new Timer ( 20000 ) ; //20 seconds
}
2013-05-04 18:06:58 -07:00
if ( adv_data = = nullptr )
2013-02-16 16:14:39 -08:00
{
2013-05-04 18:06:58 -07:00
if ( Instance_Warning_timer = = nullptr )
2013-02-16 16:14:39 -08:00
{
uint32 rem_time = Instance_Timer - > GetRemainingTime ( ) ;
if ( rem_time < 60000 & & rem_time > 55000 )
{
entity_list . ExpeditionWarning ( 1 ) ;
Instance_Warning_timer = new Timer ( 10000 ) ;
}
else if ( rem_time < 300000 & & rem_time > 295000 )
{
entity_list . ExpeditionWarning ( 5 ) ;
Instance_Warning_timer = new Timer ( 10000 ) ;
}
else if ( rem_time < 900000 & & rem_time > 895000 )
{
entity_list . ExpeditionWarning ( 15 ) ;
Instance_Warning_timer = new Timer ( 10000 ) ;
}
}
else if ( Instance_Warning_timer - > Check ( ) )
{
safe_delete ( Instance_Warning_timer ) ;
}
}
}
2013-05-04 18:06:58 -07:00
else if ( Instance_Shutdown_Timer ! = nullptr )
2013-02-16 16:14:39 -08:00
{
if ( Instance_Shutdown_Timer - > Check ( ) )
{
StartShutdownTimer ( ) ;
return false ;
}
}
}
2018-12-07 12:17:27 -05:00
if ( Weather_Timer - > Check ( ) )
{
2013-02-16 16:14:39 -08:00
Weather_Timer - > Disable ( ) ;
2014-01-20 10:10:39 -08:00
this - > ChangeWeather ( ) ;
2013-02-16 16:14:39 -08:00
}
if ( qGlobals )
{
if ( qglobal_purge_timer . Check ( ) )
{
qGlobals - > PurgeExpiredGlobals ( ) ;
}
}
if ( clientauth_timer . Check ( ) ) {
LinkedListIterator < ZoneClientAuth_Struct * > iterator2 ( client_auth_list ) ;
iterator2 . Reset ( ) ;
while ( iterator2 . MoreElements ( ) ) {
if ( iterator2 . GetData ( ) - > stale )
iterator2 . RemoveCurrent ( ) ;
else {
iterator2 . GetData ( ) - > stale = true ;
iterator2 . Advance ( ) ;
}
}
}
2013-05-09 10:44:08 -04:00
if ( hotzone_timer . Check ( ) ) { UpdateHotzone ( ) ; }
2013-04-24 15:58:51 -05:00
2018-09-17 14:32:36 -07:00
mMovementManager - > Process ( ) ;
2013-02-16 16:14:39 -08:00
return true ;
}
2014-08-20 15:32:14 -07:00
void Zone : : ChangeWeather ( )
2014-01-20 10:10:39 -08:00
{
if ( ! HasWeather ( ) )
{
Weather_Timer - > Disable ( ) ;
return ;
}
2014-12-01 18:13:12 -05:00
int chance = zone - > random . Int ( 0 , 3 ) ;
2014-01-20 10:10:39 -08:00
uint8 rainchance = zone - > newzone_data . rain_chance [ chance ] ;
uint8 rainduration = zone - > newzone_data . rain_duration [ chance ] ;
uint8 snowchance = zone - > newzone_data . snow_chance [ chance ] ;
uint8 snowduration = zone - > newzone_data . snow_duration [ chance ] ;
uint32 weathertimer = 0 ;
2014-12-01 18:13:12 -05:00
uint16 tmpweather = zone - > random . Int ( 0 , 100 ) ;
2014-01-20 10:10:39 -08:00
uint8 duration = 0 ;
uint8 tmpOldWeather = zone - > zone_weather ;
bool changed = false ;
if ( tmpOldWeather = = 0 )
{
if ( rainchance > 0 | | snowchance > 0 )
{
2014-12-01 18:13:12 -05:00
uint8 intensity = zone - > random . Int ( 1 , 10 ) ;
2014-01-20 10:10:39 -08:00
if ( ( rainchance > snowchance ) | | ( rainchance = = snowchance ) )
{
//It's gunna rain!
if ( rainchance > = tmpweather )
{
if ( rainduration = = 0 )
duration = 1 ;
else
duration = rainduration * 3 ; //Duration is 1 EQ hour which is 3 earth minutes.
weathertimer = ( duration * 60 ) * 1000 ;
Weather_Timer - > Start ( weathertimer ) ;
zone - > zone_weather = 1 ;
zone - > weather_intensity = intensity ;
changed = true ;
}
}
else
{
//It's gunna snow!
if ( snowchance > = tmpweather )
{
if ( snowduration = = 0 )
duration = 1 ;
else
duration = snowduration * 3 ;
weathertimer = ( duration * 60 ) * 1000 ;
Weather_Timer - > Start ( weathertimer ) ;
zone - > zone_weather = 2 ;
zone - > weather_intensity = intensity ;
changed = true ;
}
}
}
}
else
{
changed = true ;
//We've had weather, now taking a break
if ( tmpOldWeather = = 1 )
{
if ( rainduration = = 0 )
duration = 1 ;
else
duration = rainduration * 3 ; //Duration is 1 EQ hour which is 3 earth minutes.
weathertimer = ( duration * 60 ) * 1000 ;
Weather_Timer - > Start ( weathertimer ) ;
zone - > weather_intensity = 0 ;
}
else if ( tmpOldWeather = = 2 )
{
if ( snowduration = = 0 )
duration = 1 ;
else
duration = snowduration * 3 ; //Duration is 1 EQ hour which is 3 earth minutes.
weathertimer = ( duration * 60 ) * 1000 ;
Weather_Timer - > Start ( weathertimer ) ;
zone - > weather_intensity = 0 ;
}
}
if ( changed = = false )
{
if ( weathertimer = = 0 )
{
uint32 weatherTimerRule = RuleI ( Zone , WeatherTimer ) ;
weathertimer = weatherTimerRule * 1000 ;
Weather_Timer - > Start ( weathertimer ) ;
}
2019-09-01 23:54:24 -05:00
LogDebug ( " The next weather check for zone: [{}] will be in [{}] seconds " , zone - > GetShortName ( ) , Weather_Timer - > GetRemainingTime ( ) / 1000 ) ;
2014-01-20 10:10:39 -08:00
}
else
{
2019-09-01 23:54:24 -05:00
LogDebug ( " The weather for zone: [{}] has changed. Old weather was = [{}]. New weather is = [{}] The next check will be in [{}] seconds. Rain chance: [{}], Rain duration: [{}], Snow chance [{}], Snow duration: [{}] " , zone - > GetShortName ( ) , tmpOldWeather , zone_weather , Weather_Timer - > GetRemainingTime ( ) / 1000 , rainchance , rainduration , snowchance , snowduration ) ;
2014-01-20 10:10:39 -08:00
this - > weatherSend ( ) ;
2015-08-04 09:48:39 -04:00
if ( zone - > weather_intensity = = 0 )
{
zone - > zone_weather = 0 ;
}
2014-01-20 10:10:39 -08:00
}
}
bool Zone : : HasWeather ( )
{
uint8 rain1 = zone - > newzone_data . rain_chance [ 0 ] ;
uint8 rain2 = zone - > newzone_data . rain_chance [ 1 ] ;
uint8 rain3 = zone - > newzone_data . rain_chance [ 2 ] ;
uint8 rain4 = zone - > newzone_data . rain_chance [ 3 ] ;
uint8 snow1 = zone - > newzone_data . snow_chance [ 0 ] ;
uint8 snow2 = zone - > newzone_data . snow_chance [ 1 ] ;
uint8 snow3 = zone - > newzone_data . snow_chance [ 2 ] ;
uint8 snow4 = zone - > newzone_data . snow_chance [ 3 ] ;
if ( rain1 = = 0 & & rain2 = = 0 & & rain3 = = 0 & & rain4 = = 0 & & snow1 = = 0 & & snow2 = = 0 & & snow3 = = 0 & & snow4 = = 0 )
return false ;
else
return true ;
}
2013-02-16 16:14:39 -08:00
void Zone : : StartShutdownTimer ( uint32 set_time ) {
if ( set_time > autoshutdown_timer . GetRemainingTime ( ) ) {
2017-06-28 21:23:02 -05:00
if ( set_time = = ( RuleI ( Zone , AutoShutdownDelay ) ) ) {
2018-05-12 03:31:47 -05:00
set_time = static_cast < uint32 > ( database . getZoneShutDownDelay ( GetZoneID ( ) , GetInstanceVersion ( ) ) ) ;
2013-02-16 16:14:39 -08:00
}
2019-09-05 02:01:52 -05:00
2017-06-28 21:23:02 -05:00
autoshutdown_timer . SetTimer ( set_time ) ;
2019-09-05 02:01:52 -05:00
LogDebug ( " Zone::StartShutdownTimer set to {} " , set_time ) ;
2013-02-16 16:14:39 -08:00
}
2018-05-12 03:31:47 -05:00
2019-09-05 02:01:52 -05:00
LogDebug ( " Zone::StartShutdownTimer trigger - set_time: [{}] remaining_time: [{}] diff: [{}] " , set_time , autoshutdown_timer . GetRemainingTime ( ) , ( set_time - autoshutdown_timer . GetRemainingTime ( ) ) ) ;
2013-02-16 16:14:39 -08:00
}
bool Zone : : Depop ( bool StartSpawnTimer ) {
2013-08-29 15:46:40 -07:00
std : : map < uint32 , NPCType * > : : iterator itr ;
2013-02-16 16:14:39 -08:00
entity_list . Depop ( StartSpawnTimer ) ;
2017-10-27 21:24:24 -07:00
entity_list . ClearTrapPointers ( ) ;
entity_list . UpdateAllTraps ( false ) ;
2015-02-12 19:57:24 -06:00
/* Refresh npctable (cache), getting current info from database. */
2016-05-25 14:57:47 -04:00
while ( ! npctable . empty ( ) ) {
2015-02-12 19:57:24 -06:00
itr = npctable . begin ( ) ;
2013-02-16 16:14:39 -08:00
delete itr - > second ;
npctable . erase ( itr ) ;
2013-05-09 10:44:08 -04:00
}
2013-02-16 16:14:39 -08:00
2018-02-02 20:18:40 -05:00
// clear spell cache
database . ClearNPCSpells ( ) ;
2019-08-16 03:25:34 -05:00
zone - > spawn_group_list . ReloadSpawnGroups ( ) ;
2013-02-16 16:14:39 -08:00
return true ;
}
2014-01-31 20:38:32 -08:00
void Zone : : ClearNPCTypeCache ( int id ) {
if ( id < = 0 ) {
auto iter = npctable . begin ( ) ;
while ( iter ! = npctable . end ( ) ) {
delete iter - > second ;
+ + iter ;
}
npctable . clear ( ) ;
}
else {
auto iter = npctable . begin ( ) ;
while ( iter ! = npctable . end ( ) ) {
if ( iter - > first = = ( uint32 ) id ) {
delete iter - > second ;
npctable . erase ( iter ) ;
return ;
}
+ + iter ;
}
}
}
2015-11-07 13:20:24 -06:00
void Zone : : RepopClose ( const glm : : vec4 & client_position , uint32 repop_distance )
{
if ( ! Depop ( ) )
return ;
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
iterator . RemoveCurrent ( ) ;
}
quest_manager . ClearAllTimers ( ) ;
if ( ! database . PopulateZoneSpawnListClose ( zoneid , spawn2_list , GetInstanceVersion ( ) , client_position , repop_distance ) )
2019-09-01 23:54:24 -05:00
LogDebug ( " Error in Zone::Repop: database.PopulateZoneSpawnList failed " ) ;
2015-11-07 13:20:24 -06:00
initgrids_timer . Start ( ) ;
mod_repop ( ) ;
}
2019-01-02 02:36:12 -06:00
void Zone : : Repop ( uint32 delay )
{
if ( ! Depop ( ) ) {
2013-02-16 16:14:39 -08:00
return ;
2019-01-02 02:36:12 -06:00
}
2013-05-06 13:07:41 -04:00
2019-01-02 02:36:12 -06:00
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
2013-02-16 16:14:39 -08:00
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) ) {
iterator . RemoveCurrent ( ) ;
}
2019-01-02 02:36:12 -06:00
npc_scale_manager - > LoadScaleData ( ) ;
2017-10-27 21:24:24 -07:00
entity_list . ClearTrapPointers ( ) ;
2014-02-10 06:45:33 -05:00
quest_manager . ClearAllTimers ( ) ;
2013-02-16 16:14:39 -08:00
if ( ! database . PopulateZoneSpawnList ( zoneid , spawn2_list , GetInstanceVersion ( ) , delay ) )
2019-09-01 23:54:24 -05:00
LogDebug ( " Error in Zone::Repop: database.PopulateZoneSpawnList failed " ) ;
2013-02-16 16:14:39 -08:00
initgrids_timer . Start ( ) ;
2013-04-24 15:58:51 -05:00
2017-10-27 21:24:24 -07:00
entity_list . UpdateAllTraps ( true , true ) ;
2013-04-24 15:58:51 -05:00
//MODDING HOOK FOR REPOP
mod_repop ( ) ;
2013-02-16 16:14:39 -08:00
}
void Zone : : GetTimeSync ( )
{
2015-05-25 23:48:11 -05:00
if ( worldserver . Connected ( ) & & ! zone_has_current_time ) {
2018-01-08 19:15:36 -06:00
auto pack = new ServerPacket ( ServerOP_GetWorldTime , 1 ) ;
2013-02-16 16:14:39 -08:00
worldserver . SendPacket ( pack ) ;
safe_delete ( pack ) ;
}
}
void Zone : : SetDate ( uint16 year , uint8 month , uint8 day , uint8 hour , uint8 minute )
{
if ( worldserver . Connected ( ) ) {
2016-05-25 16:10:28 -04:00
auto pack = new ServerPacket ( ServerOP_SetWorldTime , sizeof ( eqTimeOfDay ) ) ;
2013-02-16 16:14:39 -08:00
eqTimeOfDay * eqtod = ( eqTimeOfDay * ) pack - > pBuffer ;
eqtod - > start_eqtime . minute = minute ;
eqtod - > start_eqtime . hour = hour ;
eqtod - > start_eqtime . day = day ;
eqtod - > start_eqtime . month = month ;
eqtod - > start_eqtime . year = year ;
eqtod - > start_realtime = time ( 0 ) ;
printf ( " Setting master date on world server to: %d-%d-%d %d:%d (%d) \n " , year , month , day , hour , minute , ( int ) eqtod - > start_realtime ) ;
worldserver . SendPacket ( pack ) ;
safe_delete ( pack ) ;
}
}
2015-05-25 23:48:11 -05:00
void Zone : : SetTime ( uint8 hour , uint8 minute , bool update_world /*= true*/ )
2013-02-16 16:14:39 -08:00
{
if ( worldserver . Connected ( ) ) {
2016-05-25 16:10:28 -04:00
auto pack = new ServerPacket ( ServerOP_SetWorldTime , sizeof ( eqTimeOfDay ) ) ;
2015-05-25 23:48:11 -05:00
eqTimeOfDay * eq_time_of_day = ( eqTimeOfDay * ) pack - > pBuffer ;
zone_time . GetCurrentEQTimeOfDay ( time ( 0 ) , & eq_time_of_day - > start_eqtime ) ;
eq_time_of_day - > start_eqtime . minute = minute ;
eq_time_of_day - > start_eqtime . hour = hour ;
eq_time_of_day - > start_realtime = time ( 0 ) ;
/* By Default we update worlds time, but we can optionally no update world which updates the rest of the zone servers */
if ( update_world ) {
2019-09-01 21:04:58 -05:00
LogInfo ( " Setting master time on world server to: {}:{} ({}) \n " , hour , minute , ( int ) eq_time_of_day - > start_realtime ) ;
2015-05-25 23:48:11 -05:00
worldserver . SendPacket ( pack ) ;
/* Set Time Localization Flag */
zone - > is_zone_time_localized = false ;
}
/* When we don't update world, we are localizing ourselves, we become disjointed from normal syncs and set time locally */
else {
2019-09-01 21:04:58 -05:00
LogInfo ( " Setting zone localized time... " ) ;
2015-05-25 23:48:11 -05:00
zone - > zone_time . SetCurrentEQTimeOfDay ( eq_time_of_day - > start_eqtime , eq_time_of_day - > start_realtime ) ;
2016-05-25 16:10:28 -04:00
auto outapp = new EQApplicationPacket ( OP_TimeOfDay , sizeof ( TimeOfDay_Struct ) ) ;
2015-05-25 23:48:11 -05:00
TimeOfDay_Struct * time_of_day = ( TimeOfDay_Struct * ) outapp - > pBuffer ;
zone - > zone_time . GetCurrentEQTimeOfDay ( time ( 0 ) , time_of_day ) ;
entity_list . QueueClients ( 0 , outapp , false ) ;
safe_delete ( outapp ) ;
/* Set Time Localization Flag */
zone - > is_zone_time_localized = true ;
}
2013-02-16 16:14:39 -08:00
safe_delete ( pack ) ;
}
}
2015-01-23 00:01:10 -08:00
ZonePoint * Zone : : GetClosestZonePoint ( const glm : : vec3 & location , uint32 to , Client * client , float max_distance ) {
2013-02-16 16:14:39 -08:00
LinkedListIterator < ZonePoint * > iterator ( zone_point_list ) ;
2017-03-23 04:35:36 -04:00
ZonePoint * closest_zp = nullptr ;
2013-02-16 16:14:39 -08:00
float closest_dist = FLT_MAX ;
float max_distance2 = max_distance * max_distance ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) )
{
ZonePoint * zp = iterator . GetData ( ) ;
2016-04-22 03:49:17 -04:00
uint32 mask_test = client - > ClientVersionBit ( ) ;
2013-02-16 16:14:39 -08:00
if ( ! ( zp - > client_version_mask & mask_test ) )
{
iterator . Advance ( ) ;
continue ;
}
if ( zp - > target_zone_id = = to )
{
2015-01-23 00:01:10 -08:00
auto dist = Distance ( glm : : vec2 ( zp - > x , zp - > y ) , glm : : vec2 ( location ) ) ;
2014-12-05 17:57:07 -08:00
if ( ( zp - > x = = 999999 | | zp - > x = = - 999999 ) & & ( zp - > y = = 999999 | | zp - > y = = - 999999 ) )
dist = 0 ;
2013-02-16 16:14:39 -08:00
if ( dist < closest_dist )
{
closest_zp = zp ;
closest_dist = dist ;
}
}
iterator . Advance ( ) ;
}
2013-05-06 13:07:41 -04:00
2016-08-05 01:07:12 -04:00
// if we have a water map and it says we're in a zoneline, lets assume it's just a really big zone line
// this shouldn't open up any exploits since those situations are detected later on
if ( ( zone - > HasWaterMap ( ) & & ! zone - > watermap - > InZoneLine ( glm : : vec3 ( client - > GetPosition ( ) ) ) ) | | ( ! zone - > HasWaterMap ( ) & & closest_dist > 400.0f & & closest_dist < max_distance2 ) )
2013-02-16 16:14:39 -08:00
{
2018-09-24 22:41:53 -07:00
//TODO cheat detection
2019-09-17 00:18:07 -05:00
LogInfo ( " WARNING: Closest zone point for zone id [{}] is [{}], you might need to update your zone_points table if you dont arrive at the right spot " , to , closest_dist ) ;
2019-09-01 23:22:40 -05:00
LogInfo ( " <Real Zone Points>. [{}] " , to_string ( location ) . c_str ( ) ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( closest_dist > max_distance2 )
2013-05-04 18:06:58 -07:00
closest_zp = nullptr ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( ! closest_zp )
2015-01-23 00:01:10 -08:00
closest_zp = GetClosestZonePointWithoutZone ( location . x , location . y , location . z , client ) ;
2013-02-16 16:14:39 -08:00
return closest_zp ;
}
2015-01-23 00:01:10 -08:00
ZonePoint * Zone : : GetClosestZonePoint ( const glm : : vec3 & location , const char * to_name , Client * client , float max_distance ) {
2013-05-04 18:06:58 -07:00
if ( to_name = = nullptr )
2015-01-23 00:01:10 -08:00
return GetClosestZonePointWithoutZone ( location . x , location . y , location . z , client , max_distance ) ;
2014-12-05 17:57:07 -08:00
return GetClosestZonePoint ( location , database . GetZoneID ( to_name ) , client , max_distance ) ;
2013-02-16 16:14:39 -08:00
}
ZonePoint * Zone : : GetClosestZonePointWithoutZone ( float x , float y , float z , Client * client , float max_distance ) {
LinkedListIterator < ZonePoint * > iterator ( zone_point_list ) ;
2017-03-23 04:35:36 -04:00
ZonePoint * closest_zp = nullptr ;
2013-02-16 16:14:39 -08:00
float closest_dist = FLT_MAX ;
float max_distance2 = max_distance * max_distance ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) )
{
ZonePoint * zp = iterator . GetData ( ) ;
2016-04-22 03:49:17 -04:00
uint32 mask_test = client - > ClientVersionBit ( ) ;
2013-02-16 16:14:39 -08:00
if ( ! ( zp - > client_version_mask & mask_test ) )
{
iterator . Advance ( ) ;
continue ;
}
float delta_x = zp - > x - x ;
float delta_y = zp - > y - y ;
if ( zp - > x = = 999999 | | zp - > x = = - 999999 )
delta_x = 0 ;
if ( zp - > y = = 999999 | | zp - > y = = - 999999 )
delta_y = 0 ;
float dist = delta_x * delta_x + delta_y * delta_y ; ///*+(zp->z-z)*(zp->z-z)*/;
if ( dist < closest_dist )
{
closest_zp = zp ;
closest_dist = dist ;
}
iterator . Advance ( ) ;
}
if ( closest_dist > max_distance2 )
2013-05-04 18:06:58 -07:00
closest_zp = nullptr ;
2013-02-16 16:14:39 -08:00
return closest_zp ;
}
bool ZoneDatabase : : LoadStaticZonePoints ( LinkedList < ZonePoint * > * zone_point_list , const char * zonename , uint32 version )
{
zone_point_list - > Clear ( ) ;
zone - > numzonepoints = 0 ;
2014-08-24 12:21:16 -07:00
std : : string query = StringFormat ( " SELECT x, y, z, target_x, target_y, "
2016-05-25 16:10:28 -04:00
" target_z, target_zone_id, heading, target_heading, "
" number, target_instance, client_version_mask "
" FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) "
" ORDER BY number " ,
zonename , version ) ;
2014-08-24 12:21:16 -07:00
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return false ;
}
2014-08-24 12:21:16 -07:00
2016-05-25 16:10:28 -04:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
auto zp = new ZonePoint ;
zp - > x = atof ( row [ 0 ] ) ;
zp - > y = atof ( row [ 1 ] ) ;
zp - > z = atof ( row [ 2 ] ) ;
zp - > target_x = atof ( row [ 3 ] ) ;
zp - > target_y = atof ( row [ 4 ] ) ;
zp - > target_z = atof ( row [ 5 ] ) ;
zp - > target_zone_id = atoi ( row [ 6 ] ) ;
zp - > heading = atof ( row [ 7 ] ) ;
zp - > target_heading = atof ( row [ 8 ] ) ;
zp - > number = atoi ( row [ 9 ] ) ;
zp - > target_zone_instance = atoi ( row [ 10 ] ) ;
zp - > client_version_mask = ( uint32 ) strtoul ( row [ 11 ] , nullptr , 0 ) ;
zone_point_list - > Insert ( zp ) ;
zone - > numzonepoints + + ;
}
2014-08-24 12:21:16 -07:00
2013-02-16 16:14:39 -08:00
return true ;
}
void Zone : : SpawnStatus ( Mob * client ) {
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
uint32 x = 0 ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) )
{
if ( iterator . GetData ( ) - > timer . GetRemainingTime ( ) = = 0xFFFFFFFF )
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %d: %1.1f, %1.1f, %1.1f: disabled " , iterator . GetData ( ) - > GetID ( ) , iterator . GetData ( ) - > GetX ( ) , iterator . GetData ( ) - > GetY ( ) , iterator . GetData ( ) - > GetZ ( ) ) ;
2013-02-16 16:14:39 -08:00
else
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %d: %1.1f, %1.1f, %1.1f: %1.2f " , iterator . GetData ( ) - > GetID ( ) , iterator . GetData ( ) - > GetX ( ) , iterator . GetData ( ) - > GetY ( ) , iterator . GetData ( ) - > GetZ ( ) , ( float ) iterator . GetData ( ) - > timer . GetRemainingTime ( ) / 1000 ) ;
2013-02-16 16:14:39 -08:00
x + + ;
iterator . Advance ( ) ;
}
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %i spawns listed. " , x ) ;
2013-02-16 16:14:39 -08:00
}
void Zone : : ShowEnabledSpawnStatus ( Mob * client )
{
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
int x = 0 ;
int iEnabledCount = 0 ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) )
{
if ( iterator . GetData ( ) - > timer . GetRemainingTime ( ) ! = 0xFFFFFFFF )
{
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %d: %1.1f, %1.1f, %1.1f: %1.2f " , iterator . GetData ( ) - > GetID ( ) , iterator . GetData ( ) - > GetX ( ) , iterator . GetData ( ) - > GetY ( ) , iterator . GetData ( ) - > GetZ ( ) , ( float ) iterator . GetData ( ) - > timer . GetRemainingTime ( ) / 1000 ) ;
2013-02-16 16:14:39 -08:00
iEnabledCount + + ;
}
x + + ;
iterator . Advance ( ) ;
}
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %i of %i spawns listed. " , iEnabledCount , x ) ;
2013-02-16 16:14:39 -08:00
}
void Zone : : ShowDisabledSpawnStatus ( Mob * client )
{
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
int x = 0 ;
int iDisabledCount = 0 ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) )
{
if ( iterator . GetData ( ) - > timer . GetRemainingTime ( ) = = 0xFFFFFFFF )
{
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %d: %1.1f, %1.1f, %1.1f: disabled " , iterator . GetData ( ) - > GetID ( ) , iterator . GetData ( ) - > GetX ( ) , iterator . GetData ( ) - > GetY ( ) , iterator . GetData ( ) - > GetZ ( ) ) ;
2013-02-16 16:14:39 -08:00
iDisabledCount + + ;
}
x + + ;
iterator . Advance ( ) ;
}
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %i of %i spawns listed. " , iDisabledCount , x ) ;
2013-02-16 16:14:39 -08:00
}
void Zone : : ShowSpawnStatusByID ( Mob * client , uint32 spawnid )
{
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
int x = 0 ;
int iSpawnIDCount = 0 ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) )
{
if ( iterator . GetData ( ) - > GetID ( ) = = spawnid )
{
if ( iterator . GetData ( ) - > timer . GetRemainingTime ( ) = = 0xFFFFFFFF )
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %d: %1.1f, %1.1f, %1.1f: disabled " , iterator . GetData ( ) - > GetID ( ) , iterator . GetData ( ) - > GetX ( ) , iterator . GetData ( ) - > GetY ( ) , iterator . GetData ( ) - > GetZ ( ) ) ;
2013-02-16 16:14:39 -08:00
else
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %d: %1.1f, %1.1f, %1.1f: %1.2f " , iterator . GetData ( ) - > GetID ( ) , iterator . GetData ( ) - > GetX ( ) , iterator . GetData ( ) - > GetY ( ) , iterator . GetData ( ) - > GetZ ( ) , ( float ) iterator . GetData ( ) - > timer . GetRemainingTime ( ) / 1000 ) ;
2013-02-16 16:14:39 -08:00
iSpawnIDCount + + ;
break ;
}
x + + ;
iterator . Advance ( ) ;
}
if ( iSpawnIDCount > 0 )
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " %i of %i spawns listed. " , iSpawnIDCount , x ) ;
2013-02-16 16:14:39 -08:00
else
2019-08-11 00:27:04 -05:00
client - > Message ( Chat : : White , " No matching spawn id was found in this zone. " ) ;
2013-02-16 16:14:39 -08:00
}
2018-11-18 16:03:38 -05:00
bool ZoneDatabase : : GetDecayTimes ( npcDecayTimes_Struct * npcCorpseDecayTimes )
{
const std : : string query =
" SELECT varname, value FROM variables WHERE varname LIKE 'decaytime%%' ORDER BY varname " ;
2014-08-20 16:05:09 -07:00
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) )
2018-11-18 16:03:38 -05:00
return false ;
2014-08-20 16:05:09 -07:00
int index = 0 ;
2018-11-18 16:03:38 -05:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row , + + index ) {
Seperator sep ( row [ 0 ] ) ;
npcCorpseDecayTimes [ index ] . minlvl = atoi ( sep . arg [ 1 ] ) ;
npcCorpseDecayTimes [ index ] . maxlvl = atoi ( sep . arg [ 2 ] ) ;
2014-08-20 16:05:09 -07:00
2018-11-18 16:06:31 -05:00
npcCorpseDecayTimes [ index ] . seconds = std : : min ( 24 * 60 * 60 , atoi ( row [ 1 ] ) ) ;
2018-11-18 16:03:38 -05:00
}
2014-08-20 16:05:09 -07:00
2013-02-16 16:14:39 -08:00
return true ;
2014-08-20 16:05:09 -07:00
}
2013-02-16 16:14:39 -08:00
2019-09-01 16:51:39 -05:00
void Zone : : weatherSend ( Client * client )
2013-02-16 16:14:39 -08:00
{
2016-05-25 16:10:28 -04:00
auto outapp = new EQApplicationPacket ( OP_Weather , 8 ) ;
2019-09-01 16:51:39 -05:00
if ( zone_weather > 0 ) {
outapp - > pBuffer [ 0 ] = zone_weather - 1 ;
}
if ( zone_weather > 0 ) {
2014-01-20 10:10:39 -08:00
outapp - > pBuffer [ 4 ] = zone - > weather_intensity ;
2019-09-01 16:51:39 -05:00
}
if ( client ) {
2018-03-04 21:38:17 -05:00
client - > QueuePacket ( outapp ) ;
2019-09-01 16:51:39 -05:00
}
else {
2018-03-04 21:38:17 -05:00
entity_list . QueueClients ( 0 , outapp ) ;
2019-09-01 16:51:39 -05:00
}
2013-02-16 16:14:39 -08:00
safe_delete ( outapp ) ;
}
bool Zone : : HasGraveyard ( ) {
bool Result = false ;
if ( graveyard_zoneid ( ) > 0 )
Result = true ;
return Result ;
}
2015-01-23 00:01:10 -08:00
void Zone : : SetGraveyard ( uint32 zoneid , const glm : : vec4 & graveyardPosition ) {
2013-02-16 16:14:39 -08:00
pgraveyard_zoneid = zoneid ;
2014-12-01 23:34:41 -08:00
m_Graveyard = graveyardPosition ;
2013-02-16 16:14:39 -08:00
}
2019-09-01 16:51:39 -05:00
void Zone : : LoadZoneBlockedSpells ( uint32 zone_id )
2013-02-16 16:14:39 -08:00
{
2019-09-01 16:51:39 -05:00
if ( ! blocked_spells ) {
zone_total_blocked_spells = database . GetBlockedSpellsCount ( zone_id ) ;
if ( zone_total_blocked_spells > 0 ) {
blocked_spells = new ZoneSpellsBlocked [ zone_total_blocked_spells ] ;
if ( ! database . LoadBlockedSpells ( zone_total_blocked_spells , blocked_spells , zone_id ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Failed to load blocked spells " ) ;
2013-02-16 16:14:39 -08:00
ClearBlockedSpells ( ) ;
}
}
}
}
void Zone : : ClearBlockedSpells ( )
{
2019-09-01 16:51:39 -05:00
if ( blocked_spells ) {
2013-02-16 16:14:39 -08:00
safe_delete_array ( blocked_spells ) ;
2019-09-01 16:51:39 -05:00
zone_total_blocked_spells = 0 ;
2013-02-16 16:14:39 -08:00
}
}
2019-09-01 16:51:39 -05:00
bool Zone : : IsSpellBlocked ( uint32 spell_id , const glm : : vec3 & location )
2013-02-16 16:14:39 -08:00
{
2019-09-01 16:51:39 -05:00
if ( blocked_spells ) {
2013-02-16 16:14:39 -08:00
bool exception = false ;
bool block_all = false ;
2019-09-01 16:51:39 -05:00
for ( int x = 0 ; x < GetZoneTotalBlockedSpells ( ) ; x + + ) {
if ( blocked_spells [ x ] . spellid = = spell_id ) {
2013-02-16 16:14:39 -08:00
exception = true ;
}
2013-05-06 13:07:41 -04:00
2019-09-01 16:51:39 -05:00
if ( blocked_spells [ x ] . spellid = = 0 ) {
2013-02-16 16:14:39 -08:00
block_all = true ;
2013-05-06 13:07:41 -04:00
}
2013-02-16 16:14:39 -08:00
}
2019-09-01 16:51:39 -05:00
// If all spells are blocked and this is an exception, it is not blocked
if ( block_all & & exception ) {
return false ;
}
2019-04-15 02:06:48 -07:00
2019-09-01 16:51:39 -05:00
for ( int x = 0 ; x < GetZoneTotalBlockedSpells ( ) ; x + + ) {
// Spellid of 0 matches all spells
if ( 0 ! = blocked_spells [ x ] . spellid & & spell_id ! = blocked_spells [ x ] . spellid ) {
2019-04-15 02:06:48 -07:00
continue ;
2013-02-16 16:14:39 -08:00
}
2019-04-15 02:06:48 -07:00
2019-09-01 16:51:39 -05:00
switch ( blocked_spells [ x ] . type ) {
case ZoneBlockedSpellTypes : : ZoneWide : {
2019-04-15 02:06:48 -07:00
return true ;
break ;
2013-02-16 16:14:39 -08:00
}
2019-09-01 16:51:39 -05:00
case ZoneBlockedSpellTypes : : Region : {
if ( IsWithinAxisAlignedBox (
location ,
blocked_spells [ x ] . m_Location - blocked_spells [ x ] . m_Difference ,
blocked_spells [ x ] . m_Location + blocked_spells [ x ] . m_Difference
) ) {
2013-02-16 16:14:39 -08:00
return true ;
2019-09-01 16:51:39 -05:00
}
2019-04-15 02:06:48 -07:00
break ;
}
2019-09-01 16:51:39 -05:00
default : {
2019-04-15 02:06:48 -07:00
continue ;
break ;
2013-02-16 16:14:39 -08:00
}
}
}
}
2019-09-01 16:51:39 -05:00
2013-02-16 16:14:39 -08:00
return false ;
}
2019-09-01 16:51:39 -05:00
const char * Zone : : GetSpellBlockedMessage ( uint32 spell_id , const glm : : vec3 & location )
2013-02-16 16:14:39 -08:00
{
2019-09-01 16:51:39 -05:00
if ( blocked_spells ) {
for ( int x = 0 ; x < GetZoneTotalBlockedSpells ( ) ; x + + ) {
if ( spell_id ! = blocked_spells [ x ] . spellid & & blocked_spells [ x ] . spellid ! = 0 ) {
2013-02-16 16:14:39 -08:00
continue ;
2019-09-01 16:51:39 -05:00
}
switch ( blocked_spells [ x ] . type ) {
case ZoneBlockedSpellTypes : : ZoneWide : {
2013-02-16 16:14:39 -08:00
return blocked_spells [ x ] . message ;
break ;
}
2019-09-01 16:51:39 -05:00
case ZoneBlockedSpellTypes : : Region : {
if ( IsWithinAxisAlignedBox (
location ,
blocked_spells [ x ] . m_Location - blocked_spells [ x ] . m_Difference ,
blocked_spells [ x ] . m_Location + blocked_spells [ x ] . m_Difference
) ) {
2013-02-16 16:14:39 -08:00
return blocked_spells [ x ] . message ;
2019-09-01 16:51:39 -05:00
}
2013-02-16 16:14:39 -08:00
break ;
}
2019-09-01 16:51:39 -05:00
default : {
2013-02-16 16:14:39 -08:00
continue ;
break ;
}
}
}
}
return " Error: Message String Not Found \0 " ;
}
void Zone : : SetInstanceTimer ( uint32 new_duration )
{
if ( Instance_Timer )
{
Instance_Timer - > Start ( new_duration * 1000 ) ;
}
}
void Zone : : LoadLDoNTraps ( )
{
2019-12-28 17:08:34 -06:00
const std : : string query = " SELECT id, type, spell_id, skill, locked FROM ldon_trap_templates " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return ;
2019-12-28 17:08:34 -06:00
}
2014-08-20 16:08:20 -07:00
2019-12-28 17:08:34 -06:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
auto lt = new LDoNTrapTemplate ;
lt - > id = atoi ( row [ 0 ] ) ;
lt - > type = ( LDoNChestTypes ) atoi ( row [ 1 ] ) ;
lt - > spell_id = atoi ( row [ 2 ] ) ;
lt - > skill = atoi ( row [ 3 ] ) ;
lt - > locked = atoi ( row [ 4 ] ) ;
ldon_trap_list [ lt - > id ] = lt ;
}
2014-08-20 16:08:20 -07:00
2013-02-16 16:14:39 -08:00
}
void Zone : : LoadLDoNTrapEntries ( )
{
2014-08-20 16:15:55 -07:00
const std : : string query = " SELECT id, trap_id FROM ldon_trap_entries " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
2013-02-16 16:14:39 -08:00
2014-08-20 16:15:55 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row )
{
uint32 id = atoi ( row [ 0 ] ) ;
uint32 trap_id = atoi ( row [ 1 ] ) ;
2013-02-16 16:14:39 -08:00
2014-08-20 16:15:55 -07:00
LDoNTrapTemplate * trapTemplate = nullptr ;
auto it = ldon_trap_list . find ( trap_id ) ;
2013-02-16 16:14:39 -08:00
2014-08-20 16:15:55 -07:00
if ( it = = ldon_trap_list . end ( ) )
continue ;
trapTemplate = ldon_trap_list [ trap_id ] ;
std : : list < LDoNTrapTemplate * > temp ;
auto iter = ldon_trap_entry_list . find ( id ) ;
if ( iter ! = ldon_trap_entry_list . end ( ) )
temp = ldon_trap_entry_list [ id ] ;
temp . push_back ( trapTemplate ) ;
ldon_trap_entry_list [ id ] = temp ;
}
2013-02-16 16:14:39 -08:00
}
void Zone : : LoadVeteranRewards ( )
{
VeteranRewards . clear ( ) ;
2014-08-20 16:20:46 -07:00
InternalVeteranReward current_reward ;
2013-02-16 16:14:39 -08:00
current_reward . claim_id = 0 ;
2013-05-06 13:07:41 -04:00
2014-08-20 16:20:46 -07:00
const std : : string query = " SELECT claim_id, name, item_id, charges "
" FROM veteran_reward_templates "
" WHERE reward_slot < 8 and claim_id > 0 "
" ORDER by claim_id, reward_slot " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
2013-02-16 16:14:39 -08:00
2014-08-20 16:20:46 -07:00
int index = 0 ;
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row , + + index )
{
uint32 claim = atoi ( row [ 0 ] ) ;
2013-02-16 16:14:39 -08:00
2014-08-20 16:20:46 -07:00
if ( claim ! = current_reward . claim_id )
{
if ( current_reward . claim_id ! = 0 )
{
current_reward . claim_count = index ;
current_reward . number_available = 1 ;
VeteranRewards . push_back ( current_reward ) ;
}
index = 0 ;
memset ( & current_reward , 0 , sizeof ( InternalVeteranReward ) ) ;
current_reward . claim_id = claim ;
}
strcpy ( current_reward . items [ index ] . item_name , row [ 1 ] ) ;
current_reward . items [ index ] . item_id = atoi ( row [ 2 ] ) ;
current_reward . items [ index ] . charges = atoi ( row [ 3 ] ) ;
}
if ( current_reward . claim_id ! = 0 )
{
current_reward . claim_count = index ;
current_reward . number_available = 1 ;
VeteranRewards . push_back ( current_reward ) ;
}
2013-02-16 16:14:39 -08:00
}
void Zone : : LoadAlternateCurrencies ( )
{
AlternateCurrencies . clear ( ) ;
2014-08-20 16:24:05 -07:00
2013-02-16 16:14:39 -08:00
AltCurrencyDefinition_Struct current_currency ;
2014-08-20 16:24:05 -07:00
const std : : string query = " SELECT id, item_id FROM alternate_currency " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row )
{
current_currency . id = atoi ( row [ 0 ] ) ;
current_currency . item_id = atoi ( row [ 1 ] ) ;
AlternateCurrencies . push_back ( current_currency ) ;
}
2013-02-16 16:14:39 -08:00
}
void Zone : : UpdateQGlobal ( uint32 qid , QGlobal newGlobal )
{
if ( newGlobal . npc_id ! = 0 )
return ;
if ( newGlobal . char_id ! = 0 )
return ;
if ( newGlobal . zone_id = = GetZoneID ( ) | | newGlobal . zone_id = = 0 )
{
if ( qGlobals )
{
qGlobals - > AddGlobal ( qid , newGlobal ) ;
}
else
{
qGlobals = new QGlobalCache ( ) ;
qGlobals - > AddGlobal ( qid , newGlobal ) ;
}
}
}
void Zone : : DeleteQGlobal ( std : : string name , uint32 npcID , uint32 charID , uint32 zoneID )
{
if ( qGlobals )
{
qGlobals - > RemoveGlobal ( name , npcID , charID , zoneID ) ;
}
}
void Zone : : LoadAdventureFlavor ( )
{
2014-08-20 16:27:12 -07:00
const std : : string query = " SELECT id, text FROM adventure_template_entry_flavor " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return ;
}
2014-08-20 16:27:12 -07:00
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
uint32 id = atoi ( row [ 0 ] ) ;
adventure_entry_list_flavor [ id ] = row [ 1 ] ;
}
2013-02-16 16:14:39 -08:00
}
void Zone : : DoAdventureCountIncrease ( )
{
ServerZoneAdventureDataReply_Struct * sr = ( ServerZoneAdventureDataReply_Struct * ) adv_data ;
if ( sr - > count < sr - > total )
{
sr - > count + + ;
2016-05-25 16:10:28 -04:00
auto pack = new ServerPacket ( ServerOP_AdventureCountUpdate , sizeof ( uint16 ) ) ;
2013-02-16 16:14:39 -08:00
* ( ( uint16 * ) pack - > pBuffer ) = instanceid ;
worldserver . SendPacket ( pack ) ;
delete pack ;
}
}
void Zone : : DoAdventureAssassinationCountIncrease ( )
{
ServerZoneAdventureDataReply_Struct * sr = ( ServerZoneAdventureDataReply_Struct * ) adv_data ;
if ( sr - > assa_count < RuleI ( Adventure , NumberKillsForBossSpawn ) )
{
sr - > assa_count + + ;
2016-05-25 16:10:28 -04:00
auto pack = new ServerPacket ( ServerOP_AdventureAssaCountUpdate , sizeof ( uint16 ) ) ;
2013-02-16 16:14:39 -08:00
* ( ( uint16 * ) pack - > pBuffer ) = instanceid ;
worldserver . SendPacket ( pack ) ;
delete pack ;
}
}
void Zone : : DoAdventureActions ( )
{
ServerZoneAdventureDataReply_Struct * ds = ( ServerZoneAdventureDataReply_Struct * ) adv_data ;
if ( ds - > type = = Adventure_Collect )
{
int count = ( ds - > total - ds - > count ) * 25 / 10 ;
entity_list . AddLootToNPCS ( ds - > data_id , count ) ;
did_adventure_actions = true ;
}
else if ( ds - > type = = Adventure_Assassinate )
{
if ( ds - > assa_count > = RuleI ( Adventure , NumberKillsForBossSpawn ) )
{
2015-02-12 19:57:24 -06:00
const NPCType * tmp = database . LoadNPCTypesData ( ds - > data_id ) ;
2013-02-16 16:14:39 -08:00
if ( tmp )
{
2018-11-09 00:54:51 -08:00
NPC * npc = new NPC ( tmp , nullptr , glm : : vec4 ( ds - > assa_x , ds - > assa_y , ds - > assa_z , ds - > assa_h ) , GravityBehavior : : Water ) ;
2013-02-16 16:14:39 -08:00
npc - > AddLootTable ( ) ;
Implement global loot system Fixes #619
This should allow us to emulate lives global tables
The options available to filter tables are min_level, max_level, race,
rare, raid, race, class, bodytype, and zone.
race, class, bodytype, and zone are a pipe | separated list of IDs
2018-02-10 22:15:21 -05:00
if ( npc - > DropsGlobalLoot ( ) )
npc - > CheckGlobalLootTables ( ) ;
2013-02-16 16:14:39 -08:00
entity_list . AddNPC ( npc ) ;
npc - > Shout ( " Rarrrgh! " ) ;
did_adventure_actions = true ;
}
}
}
else
{
did_adventure_actions = true ;
}
}
void Zone : : LoadNPCEmotes ( LinkedList < NPC_Emote_Struct * > * NPCEmoteList )
{
2014-08-20 16:31:05 -07:00
2013-02-16 16:14:39 -08:00
NPCEmoteList - > Clear ( ) ;
2014-08-20 16:31:05 -07:00
const std : : string query = " SELECT emoteid, event_, type, text FROM npc_emotes " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row )
{
2016-05-25 16:10:28 -04:00
auto nes = new NPC_Emote_Struct ;
nes - > emoteid = atoi ( row [ 0 ] ) ;
nes - > event_ = atoi ( row [ 1 ] ) ;
nes - > type = atoi ( row [ 2 ] ) ;
strn0cpy ( nes - > text , row [ 3 ] , sizeof ( nes - > text ) ) ;
NPCEmoteList - > Insert ( nes ) ;
2014-08-20 16:31:05 -07:00
}
2013-02-16 16:14:39 -08:00
}
void Zone : : ReloadWorld ( uint32 Option ) {
2014-12-22 04:39:41 -05:00
if ( Option = = 0 ) {
entity_list . ClearAreas ( ) ;
parse - > ReloadQuests ( ) ;
} else if ( Option = = 1 ) {
2013-06-22 14:23:07 -07:00
entity_list . ClearAreas ( ) ;
2013-02-16 16:14:39 -08:00
parse - > ReloadQuests ( ) ;
2015-05-25 12:35:53 -04:00
zone - > Repop ( 0 ) ;
2013-02-16 16:14:39 -08:00
}
2013-02-17 18:09:31 +00:00
}
2013-04-24 15:58:51 -05:00
void Zone : : LoadTickItems ( )
{
2013-05-09 10:44:08 -04:00
tick_items . clear ( ) ;
2014-08-20 16:34:35 -07:00
const std : : string query = " SELECT it_itemid, it_chance, it_level, it_qglobal, it_bagslot FROM item_tick " ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return ;
}
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
if ( atoi ( row [ 0 ] ) = = 0 )
continue ;
item_tick_struct ti_tmp ;
ti_tmp . itemid = atoi ( row [ 0 ] ) ;
ti_tmp . chance = atoi ( row [ 1 ] ) ;
ti_tmp . level = atoi ( row [ 2 ] ) ;
ti_tmp . bagslot = ( int16 ) atoi ( row [ 4 ] ) ;
ti_tmp . qglobal = std : : string ( row [ 3 ] ) ;
tick_items [ atoi ( row [ 0 ] ) ] = ti_tmp ;
}
2013-04-24 15:58:51 -05:00
}
uint32 Zone : : GetSpawnKillCount ( uint32 in_spawnid ) {
2013-05-09 10:44:08 -04:00
LinkedListIterator < Spawn2 * > iterator ( spawn2_list ) ;
iterator . Reset ( ) ;
while ( iterator . MoreElements ( ) )
{
if ( iterator . GetData ( ) - > GetID ( ) = = in_spawnid )
{
return ( iterator . GetData ( ) - > killcount ) ;
}
iterator . Advance ( ) ;
}
2013-05-08 21:01:15 -07:00
return 0 ;
2013-04-24 15:58:51 -05:00
}
void Zone : : UpdateHotzone ( )
{
2014-08-20 16:39:07 -07:00
std : : string query = StringFormat ( " SELECT hotzone FROM zone WHERE short_name = '%s' " , GetShortName ( ) ) ;
auto results = database . QueryDatabase ( query ) ;
if ( ! results . Success ( ) )
return ;
2013-05-09 10:44:08 -04:00
2014-08-20 16:39:07 -07:00
if ( results . RowCount ( ) = = 0 )
return ;
auto row = results . begin ( ) ;
is_hotzone = atoi ( row [ 0 ] ) = = 0 ? false : true ;
2013-04-24 15:58:51 -05:00
}
2015-01-20 00:53:52 -06:00
2018-03-04 21:38:17 -05:00
void Zone : : RequestUCSServerStatus ( ) {
auto outapp = new ServerPacket ( ServerOP_UCSServerStatusRequest , sizeof ( UCSServerStatus_Struct ) ) ;
auto ucsss = ( UCSServerStatus_Struct * ) outapp - > pBuffer ;
ucsss - > available = 0 ;
ucsss - > port = Config - > ZonePort ;
ucsss - > unused = 0 ;
worldserver . SendPacket ( outapp ) ;
safe_delete ( outapp ) ;
}
void Zone : : SetUCSServerAvailable ( bool ucss_available , uint32 update_timestamp ) {
if ( m_last_ucss_update = = update_timestamp & & m_ucss_available ! = ucss_available ) {
m_ucss_available = false ;
RequestUCSServerStatus ( ) ;
return ;
}
if ( m_last_ucss_update < update_timestamp )
m_ucss_available = ucss_available ;
}
2019-08-07 18:54:53 -05:00
int Zone : : GetNpcPositionUpdateDistance ( ) const
{
return npc_position_update_distance ;
}
void Zone : : SetNpcPositionUpdateDistance ( int in_npc_position_update_distance )
{
Zone : : npc_position_update_distance = in_npc_position_update_distance ;
}
void Zone : : CalculateNpcUpdateDistanceSpread ( )
{
float max_x = 0 ;
float max_y = 0 ;
float min_x = 0 ;
float min_y = 0 ;
auto & mob_list = entity_list . GetMobList ( ) ;
for ( auto & it : mob_list ) {
Mob * entity = it . second ;
if ( ! entity - > IsNPC ( ) ) {
continue ;
}
if ( entity - > GetX ( ) < = min_x ) {
min_x = entity - > GetX ( ) ;
}
if ( entity - > GetY ( ) < = min_y ) {
min_y = entity - > GetY ( ) ;
}
if ( entity - > GetX ( ) > = max_x ) {
max_x = entity - > GetX ( ) ;
}
if ( entity - > GetY ( ) > = max_y ) {
max_y = entity - > GetY ( ) ;
}
}
int x_spread = int ( abs ( max_x - min_x ) ) ;
int y_spread = int ( abs ( max_y - min_y ) ) ;
int combined_spread = int ( abs ( ( x_spread + y_spread ) / 2 ) ) ;
2020-05-17 18:36:06 -07:00
int update_distance = EQ : : ClampLower ( int ( combined_spread / 4 ) , int ( zone - > GetMaxMovementUpdateRange ( ) ) ) ;
2019-08-07 18:54:53 -05:00
SetNpcPositionUpdateDistance ( update_distance ) ;
Log ( Logs : : General , Logs : : Debug ,
" NPC update spread distance set to [%i] combined_spread [%i] " ,
update_distance ,
combined_spread
) ;
2019-10-13 18:49:16 -07:00
}
2020-01-31 20:25:06 -06:00
bool Zone : : IsQuestHotReloadQueued ( ) const
{
return quest_hot_reload_queued ;
}
void Zone : : SetQuestHotReloadQueued ( bool in_quest_hot_reload_queued )
{
quest_hot_reload_queued = in_quest_hot_reload_queued ;
}
2020-04-10 01:43:00 -05:00
uint32 Zone : : GetInstanceTimeRemaining ( ) const
{
return instance_time_remaining ;
}
void Zone : : SetInstanceTimeRemaining ( uint32 instance_time_remaining )
{
Zone : : instance_time_remaining = instance_time_remaining ;
}