2013-05-09 10:44:08 -04:00
/* EQEMu: Everquest Server Emulator
Copyright ( C ) 2001 - 2004 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-05-06 13:07:41 -04: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-05-06 13:07:41 -04: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-12-15 19:01:54 -06:00
2013-02-19 15:33:21 -08:00
# include "../common/spdat.h"
2014-08-21 19:33:02 -07:00
# include "../common/string_util.h"
2014-12-15 19:01:54 -06:00
# include "../common/types.h"
# include "client.h"
# include "entity.h"
# include "mob.h"
# include "trap.h"
2013-02-16 16:14:39 -08:00
/*
Schema :
CREATE TABLE traps (
2013-11-11 15:37:20 -05:00
id int ( 11 ) NOT NULL auto_increment ,
zone varchar ( 16 ) NOT NULL default ' ' ,
x int ( 11 ) NOT NULL default ' 0 ' ,
y int ( 11 ) NOT NULL default ' 0 ' ,
z int ( 11 ) NOT NULL default ' 0 ' ,
chance tinyint NOT NULL default ' 0 ' ,
maxzdiff float NOT NULL default ' 0 ' ,
radius float NOT NULL default ' 0 ' ,
effect int ( 11 ) NOT NULL default ' 0 ' ,
effectvalue int ( 11 ) NOT NULL default ' 0 ' ,
effectvalue2 int ( 11 ) NOT NULL default ' 0 ' ,
message varcahr ( 200 ) NOT NULL ;
skill int ( 11 ) NOT NULL default ' 0 ' ,
spawnchance int ( 11 ) NOT NULL default ' 0 ' ,
2013-05-09 10:44:08 -04:00
PRIMARY KEY ( id )
2013-02-16 16:14:39 -08:00
) TYPE = MyISAM ;
*/
Trap : : Trap ( ) :
Entity ( ) ,
respawn_timer ( 600000 ) ,
2017-10-27 21:24:24 -07:00
chkarea_timer ( 1000 ) ,
reset_timer ( 5000 ) ,
2015-01-23 00:01:10 -08:00
m_Position ( glm : : vec3 ( ) )
2013-02-16 16:14:39 -08:00
{
trap_id = 0 ;
2017-10-27 21:24:24 -07:00
db_id = 0 ;
2013-02-16 16:14:39 -08:00
maxzdiff = 0 ;
radius = 0 ;
effect = 0 ;
effectvalue = 0 ;
effectvalue2 = 0 ;
skill = 0 ;
level = 0 ;
respawn_timer . Disable ( ) ;
2017-10-27 21:24:24 -07:00
reset_timer . Disable ( ) ;
2013-02-16 16:14:39 -08:00
detected = false ;
disarmed = false ;
respawn_time = 0 ;
respawn_var = 0 ;
2013-05-04 18:06:58 -07:00
hiddenTrigger = nullptr ;
2013-02-16 16:14:39 -08:00
ownHiddenTrigger = false ;
2017-10-27 21:24:24 -07:00
chance = 0 ;
triggered_number = 0 ;
times_triggered = 0 ;
group = 0 ;
despawn_when_triggered = false ;
charid = 0 ;
2017-10-28 10:02:31 -07:00
undetectable = false ;
2013-02-16 16:14:39 -08:00
}
Trap : : ~ Trap ( )
{
//don't need to clean up mob as traps are always cleaned up same time as NPCs
//cleaning up mob here can actually cause a crash via race condition
}
bool Trap : : Process ( )
{
2017-10-27 21:24:24 -07:00
if ( chkarea_timer . Enabled ( ) & & chkarea_timer . Check ( ) & & ! reset_timer . Enabled ( ) )
2013-02-16 16:14:39 -08:00
{
Mob * trigger = entity_list . GetTrapTrigger ( this ) ;
if ( trigger & & ! ( trigger - > IsClient ( ) & & trigger - > CastToClient ( ) - > GetGM ( ) ) )
{
Trigger ( trigger ) ;
}
}
2017-10-27 21:24:24 -07:00
else if ( reset_timer . Enabled ( ) & & reset_timer . Check ( ) )
{
Log ( Logs : : General , Logs : : Traps , " Reset timer disabled in Reset Check Process for trap %d. " , trap_id ) ;
reset_timer . Disable ( ) ;
charid = 0 ;
}
2013-02-16 16:14:39 -08:00
if ( respawn_timer . Enabled ( ) & & respawn_timer . Check ( ) )
{
detected = false ;
disarmed = false ;
chkarea_timer . Enable ( ) ;
respawn_timer . Disable ( ) ;
}
2017-10-27 21:24:24 -07:00
2013-02-16 16:14:39 -08:00
return true ;
}
void Trap : : Trigger ( Mob * trigger )
{
2017-10-27 21:24:24 -07:00
Log ( Logs : : General , Logs : : Traps , " Trap %d triggered by %s for the %d time! " , trap_id , trigger - > GetName ( ) , times_triggered + 1 ) ;
2013-02-16 16:14:39 -08:00
int i = 0 ;
const NPCType * tmp = 0 ;
switch ( effect )
{
case trapTypeDebuff :
if ( message . empty ( ) )
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " %s triggers a trap! " , trigger - > GetName ( ) ) ;
}
else
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " %s " , message . c_str ( ) ) ;
}
if ( hiddenTrigger ) {
2020-05-17 18:36:06 -07:00
hiddenTrigger - > SpellFinished ( effectvalue , trigger , EQ : : spells : : CastingSlot : : Item , 0 , - 1 , spells [ effectvalue ] . ResistDiff ) ;
2013-02-16 16:14:39 -08:00
}
break ;
case trapTypeAlarm :
if ( message . empty ( ) )
{
entity_list . MessageClose ( trigger , false , effectvalue , 13 , " A loud alarm rings out through the air... " ) ;
}
else
{
entity_list . MessageClose ( trigger , false , effectvalue , 13 , " %s " , message . c_str ( ) ) ;
}
2017-10-27 21:24:24 -07:00
entity_list . SendAlarm ( this , trigger , effectvalue2 ) ;
2013-02-16 16:14:39 -08:00
break ;
case trapTypeMysticSpawn :
if ( message . empty ( ) )
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " The air shimmers... " ) ;
}
else
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " %s " , message . c_str ( ) ) ;
}
for ( i = 0 ; i < effectvalue2 ; i + + )
{
2015-02-12 19:57:24 -06:00
if ( ( tmp = database . LoadNPCTypesData ( effectvalue ) ) )
2013-02-16 16:14:39 -08:00
{
2015-01-23 00:01:10 -08:00
auto randomOffset = glm : : vec4 ( zone - > random . Int ( - 5 , 5 ) , zone - > random . Int ( - 5 , 5 ) , zone - > random . Int ( - 5 , 5 ) , zone - > random . Int ( 0 , 249 ) ) ;
auto spawnPosition = randomOffset + glm : : vec4 ( m_Position , 0.0f ) ;
2018-09-20 16:14:47 -07:00
auto new_npc = new NPC ( tmp , nullptr , spawnPosition , GravityBehavior : : Flying ) ;
2013-02-16 16:14:39 -08:00
new_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 ( new_npc - > DropsGlobalLoot ( ) )
new_npc - > CheckGlobalLootTables ( ) ;
2013-02-16 16:14:39 -08:00
entity_list . AddNPC ( new_npc ) ;
new_npc - > AddToHateList ( trigger , 1 ) ;
}
}
break ;
case trapTypeBanditSpawn :
if ( message . empty ( ) )
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " A bandit leaps out from behind a tree! " ) ;
}
else
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " %s " , message . c_str ( ) ) ;
}
for ( i = 0 ; i < effectvalue2 ; i + + )
{
2015-02-12 19:57:24 -06:00
if ( ( tmp = database . LoadNPCTypesData ( effectvalue ) ) )
2013-02-16 16:14:39 -08:00
{
2015-01-23 00:01:10 -08:00
auto randomOffset = glm : : vec4 ( zone - > random . Int ( - 2 , 2 ) , zone - > random . Int ( - 2 , 2 ) , zone - > random . Int ( - 2 , 2 ) , zone - > random . Int ( 0 , 249 ) ) ;
auto spawnPosition = randomOffset + glm : : vec4 ( m_Position , 0.0f ) ;
2018-09-20 16:14:47 -07:00
auto new_npc = new NPC ( tmp , nullptr , spawnPosition , GravityBehavior : : Flying ) ;
2013-02-16 16:14:39 -08:00
new_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 ( new_npc - > DropsGlobalLoot ( ) )
new_npc - > CheckGlobalLootTables ( ) ;
2013-02-16 16:14:39 -08:00
entity_list . AddNPC ( new_npc ) ;
new_npc - > AddToHateList ( trigger , 1 ) ;
}
}
break ;
case trapTypeDamage :
if ( message . empty ( ) )
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " %s triggers a trap! " , trigger - > GetName ( ) ) ;
}
else
{
entity_list . MessageClose ( trigger , false , 100 , 13 , " %s " , message . c_str ( ) ) ;
}
if ( trigger - > IsClient ( ) )
{
2016-05-25 16:10:28 -04:00
auto outapp = new EQApplicationPacket ( OP_Damage , sizeof ( CombatDamage_Struct ) ) ;
2013-02-16 16:14:39 -08:00
CombatDamage_Struct * a = ( CombatDamage_Struct * ) outapp - > pBuffer ;
2014-12-01 18:13:12 -05:00
int dmg = zone - > random . Int ( effectvalue , effectvalue2 ) ;
2013-02-16 16:14:39 -08:00
trigger - > SetHP ( trigger - > GetHP ( ) - dmg ) ;
a - > damage = dmg ;
2018-02-28 19:21:03 -05:00
a - > hit_heading = 0.0f ;
2013-05-04 18:06:58 -07:00
a - > source = GetHiddenTrigger ( ) ! = nullptr ? GetHiddenTrigger ( ) - > GetID ( ) : trigger - > GetID ( ) ;
2013-02-16 16:14:39 -08:00
a - > spellid = 0 ;
a - > target = trigger - > GetID ( ) ;
a - > type = 253 ;
trigger - > CastToClient ( ) - > QueuePacket ( outapp ) ;
safe_delete ( outapp ) ;
}
}
2017-10-27 21:24:24 -07:00
if ( trigger & & trigger - > IsClient ( ) )
{
trigger - > CastToClient ( ) - > trapid = trap_id ;
charid = trigger - > CastToClient ( ) - > CharacterID ( ) ;
}
bool update = false ;
if ( despawn_when_triggered )
{
Log ( Logs : : General , Logs : : Traps , " Trap %d is despawning after being triggered. " , trap_id ) ;
update = true ;
}
else
{
reset_timer . Start ( 5000 ) ;
}
if ( triggered_number > 0 )
+ + times_triggered ;
if ( triggered_number > 0 & & triggered_number < = times_triggered )
{
Log ( Logs : : General , Logs : : Traps , " Triggered number for trap %d reached. %d/%d " , trap_id , times_triggered , triggered_number ) ;
update = true ;
}
if ( update )
{
UpdateTrap ( ) ;
}
2013-02-16 16:14:39 -08:00
}
2017-10-28 10:02:31 -07:00
Trap * EntityList : : FindNearbyTrap ( Mob * searcher , float max_dist , float & trap_curdist , bool detected )
2017-10-27 21:24:24 -07:00
{
2013-02-16 16:14:39 -08:00
float dist = 999999 ;
2013-05-04 18:06:58 -07:00
Trap * current_trap = nullptr ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
float max_dist2 = max_dist * max_dist ;
Trap * cur ;
2014-11-30 18:10:30 -08:00
for ( auto it = trap_list . begin ( ) ; it ! = trap_list . end ( ) ; + + it ) {
2014-02-10 10:39:12 -05:00
cur = it - > second ;
2017-10-28 10:02:31 -07:00
if ( cur - > disarmed | | ( detected & & ! cur - > detected ) | | cur - > undetectable )
2015-01-23 00:01:10 -08:00
continue ;
2014-11-30 18:10:30 -08:00
2015-01-23 00:01:10 -08:00
auto diff = glm : : vec3 ( searcher - > GetPosition ( ) ) - cur - > m_Position ;
2017-10-28 10:02:31 -07:00
float curdist = diff . x * diff . x + diff . y * diff . y ;
diff . z = std : : abs ( diff . z ) ;
2014-11-30 18:10:30 -08:00
2017-10-28 10:02:31 -07:00
if ( curdist < max_dist2 & & curdist < dist & & diff . z < = cur - > maxzdiff )
2015-01-23 00:01:10 -08:00
{
2017-10-28 10:02:31 -07:00
Log ( Logs : : General , Logs : : Traps , " Trap %d is curdist %0.1f " , cur - > db_id , curdist ) ;
2015-01-23 00:01:10 -08:00
dist = curdist ;
current_trap = cur ;
}
2013-02-16 16:14:39 -08:00
}
2014-11-30 18:10:30 -08:00
2017-10-28 10:02:31 -07:00
if ( current_trap ! = nullptr )
{
Log ( Logs : : General , Logs : : Traps , " Trap %d is the closest trap. " , current_trap - > db_id ) ;
trap_curdist = dist ;
}
else
trap_curdist = INVALID_INDEX ;
2013-02-16 16:14:39 -08:00
return current_trap ;
}
2017-10-27 21:24:24 -07:00
Mob * EntityList : : GetTrapTrigger ( Trap * trap )
{
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
float maxdist = trap - > radius * trap - > radius ;
2017-10-27 21:24:24 -07:00
for ( auto it = client_list . begin ( ) ; it ! = client_list . end ( ) ; + + it )
{
2014-02-10 10:39:12 -05:00
Client * cur = it - > second ;
2014-11-30 18:10:30 -08:00
2015-01-23 00:01:10 -08:00
auto diff = glm : : vec3 ( cur - > GetPosition ( ) ) - trap - > m_Position ;
diff . z = std : : abs ( diff . z ) ;
2014-11-30 18:10:30 -08:00
2015-01-23 00:01:10 -08:00
if ( ( diff . x * diff . x + diff . y * diff . y ) < = maxdist
2017-10-27 21:24:24 -07:00
& & diff . z < = trap - > maxzdiff )
2013-02-16 16:14:39 -08:00
{
2017-10-27 21:24:24 -07:00
//This prevents the trap from triggering on players while zoning.
if ( strcmp ( cur - > GetName ( ) , " No name " ) = = 0 )
continue ;
if ( cur - > trapid = = 0 & & ! cur - > GetGM ( ) & & ( trap - > chance = = 0 | | zone - > random . Roll ( trap - > chance ) ) )
{
Log ( Logs : : General , Logs : : Traps , " %s is about to trigger trap %d of chance %d. diff: %0.2f maxdist: %0.2f zdiff: %0.2f maxzdiff: %0.2f " , cur - > GetName ( ) , trap - > trap_id , trap - > chance , ( diff . x * diff . x + diff . y * diff . y ) , maxdist , diff . z , trap - > maxzdiff ) ;
return cur ;
}
}
else
{
if ( cur - > trapid = = trap - > trap_id )
{
Log ( Logs : : General , Logs : : Traps , " %s is clearing trapid for trap %d " , cur - > GetName ( ) , trap - > trap_id ) ;
cur - > trapid = 0 ;
}
2013-02-16 16:14:39 -08:00
}
2017-10-27 21:24:24 -07:00
}
return nullptr ;
}
bool EntityList : : IsTrapGroupSpawned ( uint32 trap_id , uint8 group )
{
auto it = trap_list . begin ( ) ;
while ( it ! = trap_list . end ( ) )
{
Trap * cur = it - > second ;
if ( cur - > IsTrap ( ) & & cur - > group = = group & & cur - > trap_id ! = trap_id )
{
return true ;
}
+ + it ;
}
return false ;
}
void EntityList : : UpdateAllTraps ( bool respawn , bool repopnow )
{
auto it = trap_list . begin ( ) ;
while ( it ! = trap_list . end ( ) )
{
Trap * cur = it - > second ;
if ( cur - > IsTrap ( ) )
{
cur - > UpdateTrap ( respawn , repopnow ) ;
}
+ + it ;
}
2014-11-30 18:10:30 -08:00
2017-10-27 21:24:24 -07:00
Log ( Logs : : General , Logs : : Traps , " All traps updated. " ) ;
}
void EntityList : : GetTrapInfo ( Client * client )
{
uint8 count = 0 ;
auto it = trap_list . begin ( ) ;
while ( it ! = trap_list . end ( ) )
{
Trap * cur = it - > second ;
if ( cur - > IsTrap ( ) )
{
bool isset = ( cur - > chkarea_timer . Enabled ( ) & & ! cur - > reset_timer . Enabled ( ) ) ;
2019-08-11 00:00:55 -05:00
client - > Message ( Chat : : Default , " Trap: (%d) found at %0.2f,%0.2f,%0.2f. Times Triggered: %d Is Active: %d Group: %d Message: %s " , cur - > trap_id , cur - > m_Position . x , cur - > m_Position . y , cur - > m_Position . z , cur - > times_triggered , isset , cur - > group , cur - > message . c_str ( ) ) ;
2017-10-27 21:24:24 -07:00
+ + count ;
}
+ + it ;
2013-02-16 16:14:39 -08:00
}
2014-11-30 18:10:30 -08:00
2019-08-11 00:00:55 -05:00
client - > Message ( Chat : : Default , " %d traps found. " , count ) ;
2017-10-27 21:24:24 -07:00
}
void EntityList : : ClearTrapPointers ( )
{
auto it = trap_list . begin ( ) ;
while ( it ! = trap_list . end ( ) )
{
Trap * cur = it - > second ;
if ( cur - > IsTrap ( ) )
{
cur - > DestroyHiddenTrigger ( ) ;
}
+ + it ;
}
2013-02-16 16:14:39 -08:00
}
2017-10-27 21:24:24 -07:00
2013-02-16 16:14:39 -08:00
bool ZoneDatabase : : LoadTraps ( const char * zonename , int16 version ) {
2015-01-23 00:01:10 -08:00
std : : string query = StringFormat ( " SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
2017-10-27 21:24:24 -07:00
" maxzdiff, radius, chance, message, respawn_time, respawn_var, level, "
2017-10-28 10:02:31 -07:00
" `group`, triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND version=%u " , zonename , version ) ;
2017-10-27 21:24:24 -07:00
2015-01-23 00:01:10 -08:00
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
2013-02-16 16:14:39 -08:00
return false ;
2015-01-23 00:01:10 -08:00
}
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
2017-10-27 21:24:24 -07:00
uint32 tid = atoi ( row [ 0 ] ) ;
uint8 grp = atoi ( row [ 15 ] ) ;
if ( grp > 0 )
{
// If a member of our group is already spawned skip loading this trap.
if ( entity_list . IsTrapGroupSpawned ( tid , grp ) )
{
continue ;
}
}
2016-05-25 16:10:28 -04:00
auto trap = new Trap ( ) ;
2017-10-27 21:24:24 -07:00
trap - > trap_id = tid ;
trap - > db_id = tid ;
2015-01-23 00:01:10 -08:00
trap - > m_Position = glm : : vec3 ( atof ( row [ 1 ] ) , atof ( row [ 2 ] ) , atof ( row [ 3 ] ) ) ;
trap - > effect = atoi ( row [ 4 ] ) ;
trap - > effectvalue = atoi ( row [ 5 ] ) ;
trap - > effectvalue2 = atoi ( row [ 6 ] ) ;
trap - > skill = atoi ( row [ 7 ] ) ;
trap - > maxzdiff = atof ( row [ 8 ] ) ;
trap - > radius = atof ( row [ 9 ] ) ;
trap - > chance = atoi ( row [ 10 ] ) ;
trap - > message = row [ 11 ] ;
trap - > respawn_time = atoi ( row [ 12 ] ) ;
trap - > respawn_var = atoi ( row [ 13 ] ) ;
trap - > level = atoi ( row [ 14 ] ) ;
2017-10-27 21:24:24 -07:00
trap - > group = grp ;
trap - > triggered_number = atoi ( row [ 16 ] ) ;
2017-10-28 10:02:31 -07:00
trap - > despawn_when_triggered = atobool ( row [ 17 ] ) ;
trap - > undetectable = atobool ( row [ 18 ] ) ;
2015-01-23 00:01:10 -08:00
entity_list . AddTrap ( trap ) ;
trap - > CreateHiddenTrigger ( ) ;
2017-10-27 21:24:24 -07:00
Log ( Logs : : General , Logs : : Traps , " Trap %d successfully loaded. " , trap - > trap_id ) ;
2015-01-23 00:01:10 -08:00
}
2013-02-16 16:14:39 -08:00
return true ;
}
void Trap : : CreateHiddenTrigger ( )
{
if ( hiddenTrigger )
return ;
2015-02-12 19:57:24 -06:00
const NPCType * base_type = database . LoadNPCTypesData ( 500 ) ;
2016-05-25 16:10:28 -04:00
auto make_npc = new NPCType ;
2013-02-16 16:14:39 -08:00
memcpy ( make_npc , base_type , sizeof ( NPCType ) ) ;
make_npc - > max_hp = 100000 ;
2018-12-31 03:18:59 -06:00
make_npc - > current_hp = 100000 ;
2013-02-16 16:14:39 -08:00
strcpy ( make_npc - > name , " a_trap " ) ;
make_npc - > runspeed = 0.0f ;
make_npc - > bodytype = BT_Special ;
make_npc - > race = 127 ;
make_npc - > gender = 0 ;
make_npc - > loottable_id = 0 ;
make_npc - > npc_spells_id = 0 ;
2014-12-24 01:26:07 -05:00
make_npc - > d_melee_texture1 = 0 ;
make_npc - > d_melee_texture2 = 0 ;
2013-05-09 10:44:08 -04:00
make_npc - > trackable = 0 ;
2013-02-16 16:14:39 -08:00
make_npc - > level = level ;
2013-07-18 00:24:43 -07:00
strcpy ( make_npc - > special_abilities , " 19,1^20,1^24,1^25,1 " ) ;
2018-09-20 16:14:47 -07:00
NPC * npca = new NPC ( make_npc , nullptr , glm : : vec4 ( m_Position , 0.0f ) , GravityBehavior : : Flying ) ;
2013-02-16 16:14:39 -08:00
npca - > GiveNPCTypeData ( make_npc ) ;
entity_list . AddNPC ( npca ) ;
hiddenTrigger = npca ;
ownHiddenTrigger = true ;
}
2017-10-27 21:24:24 -07:00
bool ZoneDatabase : : SetTrapData ( Trap * trap , bool repopnow ) {
uint32 dbid = trap - > db_id ;
std : : string query ;
if ( trap - > group > 0 )
{
query = StringFormat ( " SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
" maxzdiff, radius, chance, message, respawn_time, respawn_var, level, "
2017-10-28 10:02:31 -07:00
" triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND `group`=%d AND id != %d ORDER BY RAND() LIMIT 1 " , zone - > GetShortName ( ) , trap - > group , dbid ) ;
2017-10-27 21:24:24 -07:00
}
else
{
// We could just use the existing data here, but querying the DB is not expensive, and allows content developers to change traps without rebooting.
query = StringFormat ( " SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
" maxzdiff, radius, chance, message, respawn_time, respawn_var, level, "
2017-10-28 10:02:31 -07:00
" triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND id = %d " , zone - > GetShortName ( ) , dbid ) ;
2017-10-27 21:24:24 -07:00
}
auto results = QueryDatabase ( query ) ;
if ( ! results . Success ( ) ) {
return false ;
}
for ( auto row = results . begin ( ) ; row ! = results . end ( ) ; + + row ) {
trap - > db_id = atoi ( row [ 0 ] ) ;
trap - > m_Position = glm : : vec3 ( atof ( row [ 1 ] ) , atof ( row [ 2 ] ) , atof ( row [ 3 ] ) ) ;
trap - > effect = atoi ( row [ 4 ] ) ;
trap - > effectvalue = atoi ( row [ 5 ] ) ;
trap - > effectvalue2 = atoi ( row [ 6 ] ) ;
trap - > skill = atoi ( row [ 7 ] ) ;
trap - > maxzdiff = atof ( row [ 8 ] ) ;
trap - > radius = atof ( row [ 9 ] ) ;
trap - > chance = atoi ( row [ 10 ] ) ;
trap - > message = row [ 11 ] ;
trap - > respawn_time = atoi ( row [ 12 ] ) ;
trap - > respawn_var = atoi ( row [ 13 ] ) ;
trap - > level = atoi ( row [ 14 ] ) ;
trap - > triggered_number = atoi ( row [ 15 ] ) ;
2017-10-28 10:02:31 -07:00
trap - > despawn_when_triggered = atobool ( row [ 16 ] ) ;
trap - > undetectable = atobool ( row [ 17 ] ) ;
2017-10-27 21:24:24 -07:00
trap - > CreateHiddenTrigger ( ) ;
if ( repopnow )
{
trap - > chkarea_timer . Enable ( ) ;
}
else
{
trap - > respawn_timer . Start ( ( trap - > respawn_time + zone - > random . Int ( 0 , trap - > respawn_var ) ) * 1000 ) ;
}
if ( trap - > trap_id ! = trap - > db_id )
Log ( Logs : : General , Logs : : Traps , " Trap (%d) DBID has changed from %d to %d " , trap - > trap_id , dbid , trap - > db_id ) ;
return true ;
}
return false ;
}
void Trap : : UpdateTrap ( bool respawn , bool repopnow )
{
respawn_timer . Disable ( ) ;
chkarea_timer . Disable ( ) ;
reset_timer . Disable ( ) ;
if ( hiddenTrigger )
{
hiddenTrigger - > Depop ( ) ;
hiddenTrigger = nullptr ;
}
times_triggered = 0 ;
Client * trigger = entity_list . GetClientByCharID ( charid ) ;
if ( trigger )
{
trigger - > trapid = 0 ;
}
charid = 0 ;
if ( respawn )
{
database . SetTrapData ( this , repopnow ) ;
}
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
}