This commit is contained in:
KimLS 2017-08-09 10:42:07 -07:00
commit ffbee0ad1a
43 changed files with 1620 additions and 175 deletions

View File

@ -408,6 +408,7 @@ N(OP_ReloadUI),
N(OP_RemoveAllDoors),
N(OP_RemoveBlockedBuffs),
N(OP_RemoveNimbusEffect),
N(OP_RemoveTrap),
N(OP_Report),
N(OP_ReqClientSpawn),
N(OP_ReqNewZone),
@ -523,6 +524,7 @@ N(OP_TributeToggle),
N(OP_TributeUpdate),
N(OP_Untargetable),
N(OP_UpdateAA),
N(OP_UpdateAura),
N(OP_UpdateLeadershipAA),
N(OP_VetClaimReply),
N(OP_VetClaimRequest),

View File

@ -27,7 +27,7 @@
//SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2)
#define AT_Die 0 // this causes the client to keel over and zone to bind point (default action)
#define AT_WhoLevel 1 // the level that shows up on /who
//#define AT_2 2 // unknown
#define AT_HPMax 2 // idk
#define AT_Invis 3 // 0 = visible, 1 = invisible
#define AT_PVP 4 // 0 = blue, 1 = pvp (red)
#define AT_Light 5 // light type emitted by player (lightstone, shiny shield)
@ -36,33 +36,37 @@
#define AT_SpawnID 16 // server to client, sets player spawn id
#define AT_HP 17 // Client->Server, my HP has changed (like regen tic)
#define AT_Linkdead 18 // 0 = normal, 1 = linkdead
#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate
#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate max 5, see GravityBehavior enum
#define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM
#define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay
#define AT_GuildID 22
#define AT_GuildRank 23 // 0=member, 1=officer, 2=leader
#define AT_AFK 24 // 0 = normal, 1 = afk
#define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks
//#define AT_27 27 // unknown
#define AT_Summoned 27 // Unsure
#define AT_Split 28 // 0 = normal, 1 = autosplit on (not showing in SoF+) (client-to-server only)
#define AT_Size 29 // spawn's size (present: SoF, absent: RoF2)
//#define AT_30 30 // unknown
#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name
//#define AT_32 32 // unknown
//#define AT_33 33 // unknown
#define AT_SetType 30 // 0 = PC, 1 = NPC, 2 <= = corpse
#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name, Trader on RoF2?
#define AT_AARank 32 // AA Rank Title ID thingy, does is this the title in /who?
#define AT_CancelSneakHide 33 // Turns off Hide and Sneak
//#define AT_34 34 // unknown (present: SoF, absent: RoF2)
//#define AT_35 35 // unknown
//#define AT_36 36 // unknown
//#define AT_37 37 // unknown
//#define AT_38 38 // unknown
//#define AT_39 39 // unknown
#define AT_AreaHPRegen 35 // guild hall regen pool sets to value * 0.001
#define AT_AreaManaRegen 36 // guild hall regen pool sets to value * 0.001
#define AT_AreaEndRegen 37 // guild hall regen pool sets to value * 0.001
#define AT_FreezeBuffs 38 // Freezes beneficial buff timers
#define AT_NpcTintIndex 39 // not 100% sure
#define AT_GroupConsent 40 // auto consent group
#define AT_RaidConsent 41 // auto consent raid
#define AT_GuildConsent 42 // auto consent guild
#define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic
#define AT_DamageState 44 // The damage state of a destructible object (0 through 4)
//#define AT_46 46 // unknown
//#define AT_48 48 // unknown
//#define AT_49 49 // unknown
//#define AT_52 52 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34)
//#define AT_53 53 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34)
#define AT_DamageState 44 // The damage state of a destructible object (0 through 10) plays soundids most only have 2 or 4 states though
#define AT_EQPlayers 45 // /eqplayersupdate
#define AT_FindBits 46 // set FindBits, whatever those are!
#define AT_TextureType 48 // TextureType
#define AT_FacePick 49 // Turns off face pick window? maybe ...
#define AT_GuildShow 52 // this is what MQ2 call sit, not sure
#define AT_Offline 53 // Offline mode
//#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2)

View File

@ -5333,6 +5333,24 @@ struct fling_struct {
/* 28 */
};
// used when action == 0
struct AuraCreate_Struct {
/* 00 */ uint32 action; // 0 = add, 1 = delete, 2 = reset
/* 04 */ uint32 type; // unsure -- normal auras show 1 clicky (ex. Circle of Power) show 0
/* 08 */ char aura_name[64];
/* 72 */ uint32 entity_id;
/* 76 */ uint32 icon;
/* 80 */
};
// used when action == 1
struct AuraDestory_Struct {
/* 00 */ uint32 action; // 0 = add, 1 = delete, 2 = reset
/* 04 */ uint32 entity_id;
/* 08 */
};
// I think we can assume it's just action for 2, client doesn't seem to do anything with the rest of the data in that case
// Restore structure packing to default
#pragma pack()

View File

@ -1883,35 +1883,34 @@ namespace RoF2
eq->FogDensity = emu->fog_density;
/*fill in some unknowns with observed values, hopefully it will help */
eq->unknown569 = 0;
eq->ZoneTimeZone = 0;
eq->unknown571 = 0;
eq->unknown572 = 4;
eq->unknown576 = 2;
eq->unknown580 = 0;
eq->WaterMidi = 4;
eq->DayMidi = 2;
eq->NightMidi = 0;
eq->unknown800 = -1;
eq->unknown844 = 600;
eq->unknown848 = 2008; // Guild Lobby observed value
eq->unknown880 = 50;
eq->unknown884 = 10;
eq->unknown888 = 1;
eq->unknown889 = 0;
eq->unknown890 = 1;
eq->unknown891 = 0;
eq->unknown892 = 0;
eq->unknown893 = 0;
eq->SkyRelated2 = -1;
eq->NPCAggroMaxDist = 600;
eq->FilterID = 2008; // Guild Lobby observed value
eq->LavaDamage = 50;
eq->MinLavaDamage = 10;
eq->bDisallowManaStone = 1;
eq->bNoBind = 0;
eq->bNoAttack = 0;
eq->bNoCallOfHero = 0;
eq->bNoFlux = 0;
eq->bNoFear = 0;
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0;
eq->unknown896 = 180;
eq->unknown900 = 180;
eq->unknown904 = 180;
eq->unknown908 = 2;
eq->unknown912 = 2;
eq->unknown932 = -1; // Set from PoK Example
eq->unknown936 = -1; // Set from PoK Example
eq->unknown944 = 1.0; // Set from PoK Example
eq->unknown948 = 0; // New on Live as of Dec 15 2014
eq->unknown952 = 100; // New on Live as of Dec 15 2014
eq->FastRegenHP = 180;
eq->FastRegenMana = 180;
eq->FastRegenEndurance = 180;
eq->CanPlaceCampsite = 2;
eq->CanPlaceGuildBanner = 2;
eq->FishingRelated = -1; // Set from PoK Example
eq->ForageRelated = -1; // Set from PoK Example
eq->bNoLevitate = 0;
eq->Blooming = 1.0; // Set from PoK Example
FINISH_ENCODE();
}
@ -4120,6 +4119,7 @@ namespace RoF2
VARSTRUCT_ENCODE_STRING(Buffer, emu->name);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level);
// actually melee range variable, this probably screws the shit out of melee ranges :D
if (emu->DestructibleObject)
{
VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000
@ -4128,7 +4128,7 @@ namespace RoF2
{
VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); // 0 PC, 1 NPC etc
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
@ -4159,6 +4159,7 @@ namespace RoF2
Buffer += sizeof(structs::Spawn_Struct_Bitfields);
// actually part of bitfields
uint8 OtherData = 0;
if (emu->class_ == 62) //LDoN Chest
@ -4174,6 +4175,7 @@ namespace RoF2
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
// float EmitterScalingRadius
if (emu->DestructibleObject)
{
@ -4183,6 +4185,7 @@ namespace RoF2
{
VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3
}
// int DefaultEmitterID
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
if (emu->DestructibleObject || emu->class_ == 62)
@ -4192,8 +4195,9 @@ namespace RoF2
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleString);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleAppearance);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1); // ObjectAnimationID
// these 10 are SoundIDs
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID1);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID2);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID3);
@ -4205,8 +4209,8 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk5);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk6);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk7);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8); // bInteractiveObjectCollidable
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9); // IteractiveObjectType
}
@ -4214,6 +4218,7 @@ namespace RoF2
{
// Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not
// present. Will sort that out later.
// This is the CharacterPropertyHash, it can have multiple fields
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype);
}
@ -4233,10 +4238,10 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown9
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown10
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // unknown11
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); // InNonPCRaceIllusion
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // material
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // variation
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // headtype
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face);
@ -4244,6 +4249,7 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->runspeed);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->race);
// From MQ2: todo: create enum for this byte. Holding: Nothing=0 A RightHand Weapon=1 A Shield=2 Dual Wielding Two Weapons=3 A Spear=4 A LeftHand Weapon=5 A Two Handed Weapon=6 A bow=7
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // ShowEQ calls this 'Holding'
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity);
if (emu->NPC)
@ -4276,19 +4282,19 @@ namespace RoF2
VARSTRUCT_ENCODE_STRING(Buffer, emu->lastName);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle ??
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC ? 0 : 1); // unknown - Must be 1 for guild name to be shown abover players head.
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // TempPet
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // FindBits MQ2 name
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // NpcTintIndex
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // PrimaryTintIndex
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // SecondaryTintIndex
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
{
@ -4356,12 +4362,16 @@ namespace RoF2
VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix);
}
// skipping two ints
// unknown, maybe some sort of spawn ID
// SplineID -- no idea
Buffer += 8;
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->IsMercenary);
VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000");
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff);
VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000"); // RealEstateItemGuid
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // RealEstateID
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // RealEstateItemID
// 29 zero bytes follow
// PhysicsEffects follow here ... unsure what they are but it's a count followed by a struct like {spellid, casterid, effectid, baseeffect}
Buffer += 29;
if (Buffer != (BufferStart + PacketSize))
{

View File

@ -328,38 +328,43 @@ showeq -> eqemu
sed -e 's/_t//g' -e 's/seto_0xFF/set_to_0xFF/g'
*/
// I think this is actually 5 bytes
// IDA's pseudocode reads this as 5 bytes pulled into 2 DWORDs
struct Spawn_Struct_Bitfields
{
// byte 1
/*00*/ unsigned gender:2; // Gender (0=male, 1=female, 2=monster)
/*02*/ unsigned ispet:1; // Guessed based on observing live spawns
/*03*/ unsigned afk:1; // 0=no, 1=afk
/*04*/ unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
/*06*/ unsigned gm:1;
/*06*/ unsigned sneak:1;
/*07*/ unsigned sneak:1;
// byte 2
/*08*/ unsigned lfg:1;
/*09*/ unsigned unknown09:1;
/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which
/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below
/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis
/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis
/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis
/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis
/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis
/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis
/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis
/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis
/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis
/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis
/*09*/ unsigned betabuffed:1;
/*10*/ unsigned invis:12; // there are 3000 different (non-GM) invis levels
/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF2
/*23*/ unsigned showhelm:1;
// byte 4
/*24*/ unsigned unknown24:1; // Prefixes name with !
/*25*/ unsigned trader:1;
/*26*/ unsigned unknown26:1;
/*26*/ unsigned animationonpop:1;
/*27*/ unsigned targetable:1;
/*28*/ unsigned targetable_with_hotkey:1;
/*29*/ unsigned showname:1;
/*30*/ unsigned unknown30:1;
/*30*/ unsigned untargetable:1; // Untargetable with mouse
/*30*/ unsigned idleanimationsoff:1; // what we called statue?
/*31*/ unsigned untargetable:1; // bClickThrough
/* do these later
32 unsigned buyer:1;
33 unsigned offline:1;
34 unsigned interactiveobject:1;
35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
36 unsigned title:1;
37 unsigned suffix:1;
38 unsigned padding1:1;
39 unsigned padding2:1;
40 unsinged padding3:1;
*/
/*
// Unknown in RoF2
unsigned betabuffed:1;
@ -498,7 +503,7 @@ struct Spawn_Struct
/*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4)
/*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8)
char unknown20[8];
char unknown20[8]; // 2 ints, first unknown, 2nd SplineID
uint8 IsMercenary; // If NPC == 1 and this == 1, then the NPC name is Orange.
/*0000*/ char unknown21[55];
};
@ -556,74 +561,100 @@ struct ServerZoneEntry_Struct //Adjusted from SEQ Everquest.h Struct
//New Zone Struct - Size: 948
struct NewZone_Struct {
/*0000*/ char char_name[64]; // Character Name
/*0064*/ char zone_short_name[32]; // Zone Short Name
/*0096*/ char unknown0096[96];
/*0192*/ char zone_long_name[278]; // Zone Long Name
/*0470*/ uint8 ztype; // Zone type (usually FF)
/*0471*/ uint8 fog_red[4]; // Zone fog (red)
/*0475*/ uint8 fog_green[4]; // Zone fog (green)
/*0479*/ uint8 fog_blue[4]; // Zone fog (blue)
/*0483*/ uint8 unknown323;
/*0484*/ float fog_minclip[4];
/*0064*/ char zone_short_name[128]; // Zone Short Name
/*0192*/ char zone_long_name[128]; // Zone Long Name
/*0320*/ char zone_desc[5][30]; // mostly just empty strings
/*0470*/ uint8 ztype; // Zone type (usually FF) FogOnOff
/*0471*/ uint8 fog_red[4]; // Zone fog (red) ARGBCOLOR
/*0475*/ uint8 fog_green[4]; // Zone fog (green) ARGBCOLOR
/*0479*/ uint8 fog_blue[4]; // Zone fog (blue) ARGBCOLO
/*0483*/ uint8 unknown323; // padding?
/*0484*/ float fog_minclip[4]; // MQ2 has this starting at this offset, must be padding above
/*0500*/ float fog_maxclip[4];
/*0516*/ float gravity;
/*0520*/ uint8 time_type;
/*0520*/ uint8 time_type; // OutDoor flag 0 = IndoorDungeon, 1 = OUtdoor, 2 = OutdoorCity, 3 = DungeonCity, 4 = IndoorCity, 5 = OutdoorDungeon
/*0521*/ uint8 rain_chance[4];
/*0525*/ uint8 rain_duration[4];
/*0529*/ uint8 snow_chance[4];
/*0533*/ uint8 snow_duration[4];
/*0537*/ uint8 unknown537[32]; // Seen all 0xff
/*0569*/ uint8 unknown569; // Unknown - Seen 0
/*0537*/ uint8 unknown537[32]; // this is removed on live, specialdates and specialcodes probably macro'd out
/*0569*/ uint8 ZoneTimeZone; // MQ2 "in hours from worldserver, can be negative"
/*0570*/ uint8 sky; // Sky Type
/*0571*/ uint8 unknown571; // Unknown - Seen 0
/*0572*/ uint32 unknown572; // Unknown - Seen 4 in Guild Lobby
/*0576*/ uint32 unknown576; // Unknown - Seen 2 in Guild Lobby
/*0580*/ uint32 unknown580; // Unknown - Seen 0 in Guild Lobby
/*0571*/ uint8 unknown571; // Padding I think
/*0572*/ uint32 WaterMidi; // Unknown - Seen 4 in Guild Lobby
/*0576*/ uint32 DayMidi; // Unknown - Seen 2 in Guild Lobby
/*0580*/ uint32 NightMidi; // Unknown - Seen 0 in Guild Lobby
/*0584*/ float zone_exp_multiplier; // Experience Multiplier
/*0588*/ float safe_y; // Zone Safe Y
/*0592*/ float safe_x; // Zone Safe X
/*0596*/ float safe_z; // Zone Safe Z
/*0600*/ float min_z; // Guessed - NEW - Seen 0
/*0604*/ float max_z; // Guessed
/*0608*/ float underworld; // Underworld, min z (Not Sure?)
/*0600*/ float min_z; // This isn't safe heading like live -- could be default heading rather than succor heading
/*0604*/ float max_z; // Ceiling
/*0608*/ float underworld; // Underworld, min z (Not Sure?) Floor
/*0612*/ float minclip; // Minimum View Distance
/*0616*/ float maxclip; // Maximum View DIstance
/*0620*/ uint8 unknown620[84]; // ***Placeholder
/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version.
/*0800*/ int32 unknown800; //seen -1
/*0804*/ char unknown804[40]; //
/*0844*/ int32 unknown844; //seen 600
/*0848*/ int32 unknown848; //seen 2008
/*0852*/ uint16 zone_id;
/*0620*/ uint32 ForageLow; // Forage loot table ID?
/*0624*/ uint32 ForageMedium; // Forage loot table ID?
/*0628*/ uint32 ForageHigh; // Forage loot table ID?
/*0632*/ uint32 FishingLow; // Fishing loot table ID?
/*0636*/ uint32 FishingMedium; // Fishing loot table ID?
/*0640*/ uint32 FishingHigh; // Fishing loot table ID?
/*0644*/ uint32 sky_lock; // MQ2 skyrelated
/*0648*/ uint32 graveyard_timer; // minutes until corpse pop to graveyard
/*0652*/ uint32 scriptIDHour; // These are IDs of scripts
/*0656*/ uint32 scriptIDMinute; // These are IDs of scripts
/*0660*/ uint32 scriptIDTick; // These are IDs of scripts
/*0664*/ uint32 scriptIDOnPlayerDeath; // These are IDs of scripts
/*0668*/ uint32 scriptIDOnNPCDeath; // These are IDs of scripts
/*0672*/ uint32 scriptIDPlayerEnteringZone; // These are IDs of scripts
/*0676*/ uint32 scriptIDOnZonePop; // These are IDs of scripts
/*0680*/ uint32 scriptIDNPCLoot; // These are IDs of scripts
/*0684*/ uint32 scriptIDAdventureFailed; // These are IDs of scripts
/*0688*/ uint32 CanExploreTasks;
/*0692*/ uint32 UnknownFlag; // not sure, neither is MQ2!
/*0696*/ uint32 scriptIDOnFishing; // THese are IDs of scripts
/*0700*/ uint32 scriptIDOnForage; // THese are IDs of scripts
/*0704*/ char zone_short_name2[32]; //zone file name? excludes instance number which can be in previous version.
/*0736*/ char WeatherString[32];
/*0768*/ char SkyString2[32];
/*0800*/ int32 SkyRelated2; //seen -1
/*0804*/ char WeatherString2[32]; //
/*0836*/ float WeatherChangeTime; // not sure :P
/*0840*/ uint32 Climate;
/*0844*/ int32 NPCAggroMaxDist; //seen 600
/*0848*/ int32 FilterID; //seen 2008 -- maybe zone guide related?
/*0852*/ uint16 zone_id; // this might just be instance ID got 1736 for time
/*0854*/ uint16 zone_instance;
/*0856*/ char unknown856[20];
/*0876*/ uint32 SuspendBuffs;
/*0880*/ uint32 unknown880; // Seen 50
/*0884*/ uint32 unknown884; // Seen 10
/*0888*/ uint8 unknown888; // Seen 1
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
/*0890*/ uint8 unknown890; // Seen 1
/*0891*/ uint8 unknown891; // Seen 0
/*0892*/ uint8 unknown892; // Seen 0
/*0893*/ uint8 unknown893; // Seen 0 - 00
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
/*0895*/ uint8 unknown895; // Seen 0 - 00
/*0896*/ uint32 unknown896; // Seen 180
/*0900*/ uint32 unknown900; // Seen 180
/*0904*/ uint32 unknown904; // Seen 180
/*0908*/ uint32 unknown908; // Seen 2
/*0912*/ uint32 unknown912; // Seen 2
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 unknown920; // Seen 0
/*0924*/ uint32 unknown924; // Seen 0
/*0928*/ uint32 unknown928; // Seen 0
/*0932*/ int32 unknown932; // Seen -1
/*0936*/ int32 unknown936; // Seen -1
/*0940*/ uint32 unknown940; // Seen 0
/*0944*/ float unknown944; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
/*0948*/ uint32 unknown948; // Seen 0 - New on Live as of Dec 15 2014
/*0952*/ uint32 unknown952; // Seen 100 - New on Live as of Dec 15 2014
/*0956*/
/*0856*/ uint32 scriptNPCReceivedanItem;
/*0860*/ uint32 bCheck; // padded bool
/*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 scriptIDSomething2;
/*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 SuspendBuffs; // padded bool
/*0880*/ uint32 LavaDamage; // LavaDamage value
/*0884*/ uint32 MinLavaDamage; // min cap after resist calcs
/*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone
/*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can!
/*0890*/ uint8 bNoAttack; // non-attack zone
/*0891*/ uint8 bNoCallOfHero; // coth line disabled
/*0892*/ uint8 bNoFlux; // gflux no worky
/*0893*/ uint8 bNoFear; // fear spells no worky
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber
/*0895*/ uint8 unknown895; // padding
/*0896*/ uint32 FastRegenHP; // percentage I think?
/*0900*/ uint32 FastRegenMana; // percentage I think?
/*0904*/ uint32 FastRegenEndurance; // percentage I think?
/*0908*/ uint32 CanPlaceCampsite; // 0 = no, 1 = can place, 2 = place and goto
/*0912*/ uint32 CanPlaceGuildBanner; // ^
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 bAdjustGamma; // padded bool
/*0924*/ uint32 TimeStringID; // Seen 0
/*0928*/ uint32 bNoMercenaries; // padded bool
/*0932*/ int32 FishingRelated; // Seen -1 idk
/*0936*/ int32 ForageRelated; // Seen -1 idk
/*0940*/ uint32 bNoLevitate; // padded bool
/*0944*/ float Blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
/*0948*/
};
/*

View File

@ -339,18 +339,7 @@ struct Spawn_Struct_Bitfields
/*06*/ unsigned sneak:1;
/*08*/ unsigned lfg:1;
/*09*/ unsigned unknown09:1;
/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which
/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below
/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis
/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis
/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis
/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis
/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis
/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis
/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis
/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis
/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis
/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis
/*10*/ unsigned invis:12; // there are 3000 different (non-GM) invis levels
/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF
/*23*/ unsigned showhelm:1;
/*24*/ unsigned unknown24:1; // Prefixes name with !

View File

@ -250,8 +250,7 @@ struct Spawn_Struct_Bitfields
unsigned sneak:1;
unsigned lfg:1;
unsigned padding5:1;
unsigned invis:1; // 0 = visible, 1 = invis/sneaking
unsigned padding7:11;
unsigned invis:12; // there are 3000 different (non-GM) invis levels
unsigned gm:1;
unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
unsigned gender:2; // Gender (0=male, 1=female, 2=monster)

View File

@ -250,8 +250,7 @@ struct Spawn_Struct_Bitfields
unsigned sneak:1;
unsigned lfg:1;
unsigned padding5:1;
unsigned invis:1; // 0 = visible, 1 = invis/sneaking
unsigned padding7:11;
unsigned invis:12; // there are 3000 different (non-GM) invis levels
unsigned gm:1;
unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
unsigned gender:2; // Gender (0=male, 1=female, 2=monster)

View File

@ -1674,6 +1674,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
for (y = 0; y < 16; y++)
sp[tempid].deities[y]=atoi(row[126+y]);
sp[tempid].new_icon=atoi(row[144]);
sp[tempid].uninterruptable=atoi(row[146]) != 0;
sp[tempid].ResistDiff=atoi(row[147]);
sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0;

View File

@ -562,9 +562,9 @@ typedef enum {
#define SE_LimitManaMin 348 // implemented
#define SE_ShieldEquipDmgMod 349 // implemented[AA] Increase melee base damage (indirectly increasing hate) when wearing a shield.
#define SE_ManaBurn 350 // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana.
//#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this
//#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755)
//#define SE_AdditionalAura 353 // *not implemented - allows use of more than 1 aura, aa effect
#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this
#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755)
#define SE_AdditionalAura 353 // *not implemented - allows use of more than 1 aura, aa effect
//#define SE_DeactivateAllTraps 354 // *not implemented - looks to be some type of invulnerability? Test DAT (8757)
//#define SE_LearnTrap 355 // *not implemented - looks to be some type of invulnerability? Test LT (8758)
//#define SE_ChangeTriggerType 356 // not used
@ -757,7 +757,7 @@ struct SPDat_Spell_Struct
// -- DIETY_BERTOXXULOUS ... DIETY_VEESHAN
/* 142 */ //int8 npc_no_cast; // 142: between 0 & 100 -- NPC_NO_CAST
/* 143 */ //int ai_pt_bonus; // 143: always set to 0, client doesn't save this -- AI_PT_BONUS
/* 144 */ //int16 new_icon // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -- NEW_ICON
/* 144 */ int16 new_icon; // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -- NEW_ICON
/* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is, particles I think -- SPELL_EFFECT_INDEX
/* 146 */ bool uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) -- NO_INTERRUPT
/* 147 */ int16 ResistDiff; // -- RESIST_MOD

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9113
#define CURRENT_BINARY_DATABASE_VERSION 9114
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017
#else

View File

@ -672,3 +672,7 @@ OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
OP_InitialHPUpdate=0x0000
OP_ItemRecastDelay=0x57ed
#aura related
OP_UpdateAura=0x1fa9
OP_RemoveTrap=0x6a4d

View File

@ -675,3 +675,7 @@ OP_RAWOutOfSession=0x0000
# we need to document the differences between these packets to make identifying them easier
OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
OP_InitialHPUpdate=0x0000
#aura related
OP_UpdateAura=0x1456
OP_RemoveTrap=0x71da

View File

@ -669,3 +669,7 @@ OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
OP_InitialHPUpdate=0x0000 #
OP_ItemRecastDelay=0x15c4
#aura related
OP_UpdateAura=0x169a
OP_RemoveTrap=0x4bb6

View File

@ -658,3 +658,7 @@ OP_ItemRecastDelay=0x0ada
#OP_NpcMoveUpdate=0x0d11 #SEQ 10/07/08 --NEW FROM SEQ
#OP_Zone_MissingName01=0x0000 #
#new titles avaliable: #
#aura related
OP_UpdateAura=0x62a9
OP_RemoveTrap=0x7bd9

View File

@ -685,3 +685,7 @@ OP_ItemRecastDelay=0x82d7
# unhandled
OP_ShieldGroup=0x23a1
#aura related
OP_UpdateAura=0x2480
OP_RemoveTrap=0x0115

View File

@ -367,6 +367,7 @@
9111|2017_06_24_saylink_index.sql|SHOW INDEX FROM `saylink` WHERE `key_name` = 'phrase_index'|empty|
9112|2017_06_24_rule_values_expand.sql|SHOW COLUMNS FROM rule_values WHERE Field = 'rule_value' and Type = 'varchar(30)'|empty|
9113|2017_07_19_show_name.sql|SHOW COLUMNS FROM `npc_types` LIKE 'show_name'|empty|
9114|2017_07_22_aura.sql|SHOW TABLES LIKE 'auras'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,127 @@
CREATE TABLE `auras` (
`type` INT(10) NOT NULL,
`npc_type` INT(10) NOT NULL,
`name` VARCHAR(64) NOT NULL,
`spell_id` INT(10) NOT NULL,
`distance` INT(10) NOT NULL DEFAULT 60,
`aura_type` INT(10) NOT NULL DEFAULT 1,
`spawn_type` INT(10) NOT NULL DEFAULT 0,
`movement` INT(10) NOT NULL DEFAULT 0,
`duration` INT(10) NOT NULL DEFAULT 5400,
`icon` INT(10) NOT NULL DEFAULT -1,
`cast_time` INT(10) NOT NULL DEFAULT 0,
PRIMARY KEY(`type`)
);
CREATE TABLE `character_auras` (
`id` INT(10) NOT NULL,
`slot` TINYINT(10) NOT NULL,
`spell_id` INT(10) NOT NULL,
PRIMARY KEY (`id`, `slot`)
);
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8926, npc_type=@suggestedid, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=99, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8488, npc_type=@suggestedid, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8921, npc_type=@suggestedid, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8468, npc_type=@suggestedid, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8925, npc_type=@suggestedid, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8481, npc_type=@suggestedid, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8923, npc_type=@suggestedid, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8474, npc_type=@suggestedid, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8933, npc_type=@suggestedid, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8518, npc_type=@suggestedid, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8931, npc_type=@suggestedid, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8509, npc_type=@suggestedid, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8929, npc_type=@suggestedid, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8499, npc_type=@suggestedid, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8928, npc_type=@suggestedid, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8495, npc_type=@suggestedid, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8924, npc_type=@suggestedid, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8477, npc_type=@suggestedid, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8930, npc_type=@suggestedid, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8504, npc_type=@suggestedid, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8934, npc_type=@suggestedid, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8523, npc_type=@suggestedid, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap55", lastname="", level="55", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8922, npc_type=@suggestedid, name="poison_spurs", spell_id=8936, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1;
SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___';
INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap", lastname="", level="70", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0";
INSERT INTO auras SET type=8471, npc_type=@suggestedid, name="Poison Spikes", spell_id=8472, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1;
UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities);

View File

@ -5,6 +5,7 @@ SET(zone_sources
aa_ability.cpp
aggro.cpp
aggromanager.cpp
aura.cpp
attack.cpp
beacon.cpp
bonuses.cpp
@ -140,6 +141,7 @@ SET(zone_headers
aa.h
aa_ability.h
aggromanager.h
aura.h
basic_functions.h
beacon.h
bot.h

936
zone/aura.cpp Normal file
View File

@ -0,0 +1,936 @@
#include "../common/string_util.h"
#include "aura.h"
#include "client.h"
#include "string_ids.h"
#include "raids.h"
Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record)
: NPC(type_data, 0, owner->GetPosition(), FlyMode3), spell_id(record.spell_id), distance(record.distance),
remove_timer(record.duration), movement_timer(100), process_timer(100), aura_id(-1)
{
GiveNPCTypeData(type_data); // we will delete this later on
m_owner = owner->GetID();
if (record.cast_time) {
cast_timer.SetTimer(record.cast_time);
cast_timer.Disable(); // we don't want to be enabled yet
}
if (record.aura_type < static_cast<int>(AuraType::Max))
type = static_cast<AuraType>(record.aura_type);
else
type = AuraType::OnAllGroupMembers;
if (record.spawn_type < static_cast<int>(AuraSpawns::Max))
spawn_type = static_cast<AuraSpawns>(record.spawn_type);
else
spawn_type = AuraSpawns::GroupMembers;
if (record.movement < static_cast<int>(AuraMovement::Max))
movement_type = static_cast<AuraMovement>(record.movement);
else
movement_type = AuraMovement::Follow;
switch (type) {
case AuraType::OnAllFriendlies:
process_func = &Aura::ProcessOnAllFriendlies;
break;
case AuraType::OnAllGroupMembers:
process_func = &Aura::ProcessOnAllGroupMembers;
break;
case AuraType::OnGroupMembersPets:
process_func = &Aura::ProcessOnGroupMembersPets;
break;
case AuraType::Totem:
process_func = &Aura::ProcessTotem;
break;
case AuraType::EnterTrap:
process_func = &Aura::ProcessEnterTrap;
break;
case AuraType::ExitTrap:
process_func = &Aura::ProcessExitTrap;
break;
default:
process_func = nullptr;
}
}
Mob *Aura::GetOwner()
{
return entity_list.GetMob(m_owner);
}
// not 100% sure how this one should work and PVP affects ...
void Aura::ProcessOnAllFriendlies(Mob *owner)
{
auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline
std::set<int> delayed_remove;
bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter
for (auto &e : mob_list) {
auto mob = e.second;
if (mob->IsClient() || mob->IsPetOwnerClient() || mob->IsMerc()) {
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) { // we are already on the list, let's check for removal
if (DistanceSquared(GetPosition(), mob->GetPosition()) > distance)
delayed_remove.insert(mob->GetID());
} else { // not on list, lets check if we're in range
if (DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
}
}
}
}
for (auto &e : delayed_remove) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove
mob->BuffFadeBySpellIDAndCaster(spell_id, GetID());
casted_on.erase(e);
}
// so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it
if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty())
cast_timer.Start();
if (!cast_timer.Enabled() || !cast_timer.Check())
return;
for (auto &e : casted_on) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr)
SpellFinished(spell_id, mob);
}
}
void Aura::ProcessOnAllGroupMembers(Mob *owner)
{
auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline
std::set<int> delayed_remove;
bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter
if (owner->IsRaidGrouped() && owner->IsClient()) { // currently raids are just client, but safety check
auto raid = owner->GetRaid();
if (raid == nullptr) { // well shit
owner->RemoveAura(GetID(), false, true);
return;
}
auto group_id = raid->GetGroup(owner->CastToClient());
// some lambdas so the for loop is less horrible ...
auto verify_raid_client = [&raid, &group_id, this](Client *c) {
auto idx = raid->GetPlayerIndex(c);
if (c->GetID() == m_owner) {
return DistanceSquared(GetPosition(), c->GetPosition()) <= distance;
} else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) {
return false;
} else if (DistanceSquared(GetPosition(), c->GetPosition()) > distance) {
return false;
}
return true;
};
auto verify_raid_client_pet = [&raid, &group_id, this](Mob *m) {
auto idx = raid->GetPlayerIndex(m->GetOwner()->CastToClient());
if (m->GetOwner()->GetID() == m_owner) {
return DistanceSquared(GetPosition(), m->GetPosition()) <= distance;
} else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) {
return false;
} else if (DistanceSquared(GetPosition(), m->GetPosition()) > distance) {
return false;
}
return true;
};
auto verify_raid_client_swarm = [&raid, &group_id, this](NPC *n) {
auto owner = entity_list.GetMob(n->GetSwarmOwner());
if (owner == nullptr)
return false;
auto idx = raid->GetPlayerIndex(owner->CastToClient());
if (owner->GetID() == m_owner) {
return DistanceSquared(GetPosition(), n->GetPosition()) <= distance;
} else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) {
return false;
} else if (DistanceSquared(GetPosition(), n->GetPosition()) > distance) {
return false;
}
return true;
};
for (auto &e : mob_list) {
auto mob = e.second;
// step 1: check if we're already managing this NPC's buff
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) {
// verify still good!
if (mob->IsClient()) {
if (!verify_raid_client(mob->CastToClient()))
delayed_remove.insert(mob->GetID());
} else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner()) {
if (!verify_raid_client_pet(mob))
delayed_remove.insert(mob->GetID());
} else if (mob->IsNPC() && mob->IsPetOwnerClient()) {
auto npc = mob->CastToNPC();
if (!verify_raid_client_swarm(npc))
delayed_remove.insert(mob->GetID());
}
} else { // we're not on it!
if (mob->IsClient() && verify_raid_client(mob->CastToClient())) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
} else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner() && verify_raid_client_pet(mob)) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
} else if (mob->IsNPC() && mob->IsPetOwnerClient()) {
auto npc = mob->CastToNPC();
if (verify_raid_client_swarm(npc)) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
}
}
}
}
} else if (owner->IsGrouped()) {
auto group = owner->GetGroup();
if (group == nullptr) { // uh oh
owner->RemoveAura(GetID(), false, true);
return;
}
// lambdas to make for loop less ugly
auto verify_group_pet = [&group, this](Mob *m) {
auto owner = m->GetOwner();
if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), m->GetPosition()) <= distance)
return true;
return false;
};
auto verify_group_swarm = [&group, this](NPC *n) {
auto owner = entity_list.GetMob(n->GetSwarmOwner());
if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), n->GetPosition()) <= distance)
return true;
return false;
};
for (auto &e : mob_list) {
auto mob = e.second;
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) { // make sure we're still valid
if (mob->IsPet()) {
if (!verify_group_pet(mob))
delayed_remove.insert(mob->GetID());
} else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo()) {
if (!verify_group_swarm(mob->CastToNPC()))
delayed_remove.insert(mob->GetID());
} else if (!group->IsGroupMember(mob) || DistanceSquared(GetPosition(), mob->GetPosition()) > distance) {
delayed_remove.insert(mob->GetID());
}
} else { // not on, check if we should be!
if (mob->IsPet() && verify_group_pet(mob)) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
} else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo() && verify_group_swarm(mob->CastToNPC())) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
} else if (group->IsGroupMember(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
}
}
}
} else {
auto verify_solo = [&owner, this](Mob *m) {
if (m->IsPet() && m->GetOwnerID() == owner->GetID())
return true;
else if (m->IsNPC() && m->CastToNPC()->GetSwarmOwner() == owner->GetID())
return true;
else if (m->GetID() == owner->GetID())
return true;
else
return false;
};
for (auto &e : mob_list) {
auto mob = e.second;
auto it = casted_on.find(mob->GetID());
bool good = verify_solo(mob);
if (it != casted_on.end()) { // make sure still valid
if (!good || DistanceSquared(GetPosition(), mob->GetPosition()) > distance) {
delayed_remove.insert(mob->GetID());
}
} else if (good && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
}
}
}
for (auto &e : delayed_remove) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove
mob->BuffFadeBySpellIDAndCaster(spell_id, GetID());
casted_on.erase(e);
}
// so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it
if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty())
cast_timer.Start();
if (!cast_timer.Enabled() || !cast_timer.Check())
return;
// some auras have to recast (DRU for example, non-buff too)
for (auto &e : casted_on) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr)
SpellFinished(spell_id, mob);
}
}
void Aura::ProcessOnGroupMembersPets(Mob *owner)
{
auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline
std::set<int> delayed_remove;
bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter
// This type can either live on the pet (level 55/70 MAG aura) or on the pet owner (level 85 MAG aura)
auto group_member = owner->GetOwnerOrSelf();
if (group_member->IsRaidGrouped() && group_member->IsClient()) { // currently raids are just client, but safety check
auto raid = group_member->GetRaid();
if (raid == nullptr) { // well shit
owner->RemoveAura(GetID(), false, true);
return;
}
auto group_id = raid->GetGroup(group_member->CastToClient());
// some lambdas so the for loop is less horrible ...
auto verify_raid_client_pet = [&raid, &group_id, &group_member, this](Mob *m) {
auto idx = raid->GetPlayerIndex(m->GetOwner()->CastToClient());
if (m->GetOwner()->GetID() == group_member->GetID()) {
return DistanceSquared(GetPosition(), m->GetPosition()) <= distance;
} else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) {
return false;
} else if (DistanceSquared(GetPosition(), m->GetPosition()) > distance) {
return false;
}
return true;
};
auto verify_raid_client_swarm = [&raid, &group_id, &group_member, this](NPC *n) {
auto owner = entity_list.GetMob(n->GetSwarmOwner());
if (owner == nullptr)
return false;
auto idx = raid->GetPlayerIndex(owner->CastToClient());
if (owner->GetID() == group_member->GetID()) {
return DistanceSquared(GetPosition(), n->GetPosition()) <= distance;
} else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) {
return false;
} else if (DistanceSquared(GetPosition(), n->GetPosition()) > distance) {
return false;
}
return true;
};
for (auto &e : mob_list) {
auto mob = e.second;
// step 1: check if we're already managing this NPC's buff
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) {
// verify still good!
if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner()) {
if (!verify_raid_client_pet(mob))
delayed_remove.insert(mob->GetID());
} else if (mob->IsNPC() && mob->IsPetOwnerClient()) {
auto npc = mob->CastToNPC();
if (!verify_raid_client_swarm(npc))
delayed_remove.insert(mob->GetID());
}
} else { // we're not on it!
if (mob->IsClient()) {
continue; // never hit client
} else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner() && verify_raid_client_pet(mob)) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
} else if (mob->IsNPC() && mob->IsPetOwnerClient()) {
auto npc = mob->CastToNPC();
if (verify_raid_client_swarm(npc)) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
}
}
}
}
} else if (group_member->IsGrouped()) {
auto group = group_member->GetGroup();
if (group == nullptr) { // uh oh
owner->RemoveAura(GetID(), false, true);
return;
}
// lambdas to make for loop less ugly
auto verify_group_pet = [&group, this](Mob *m) {
auto owner = m->GetOwner();
if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), m->GetPosition()) <= distance)
return true;
return false;
};
auto verify_group_swarm = [&group, this](NPC *n) {
auto owner = entity_list.GetMob(n->GetSwarmOwner());
if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), n->GetPosition()) <= distance)
return true;
return false;
};
for (auto &e : mob_list) {
auto mob = e.second;
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) { // make sure we're still valid
if (mob->IsPet()) {
if (!verify_group_pet(mob))
delayed_remove.insert(mob->GetID());
} else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo()) {
if (!verify_group_swarm(mob->CastToNPC()))
delayed_remove.insert(mob->GetID());
}
} else { // not on, check if we should be!
if (mob->IsClient()) {
continue;
} else if (mob->IsPet() && verify_group_pet(mob)) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
} else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo() && verify_group_swarm(mob->CastToNPC())) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
}
}
}
} else {
auto verify_solo = [&group_member, this](Mob *m) {
if (m->IsPet() && m->GetOwnerID() == group_member->GetID())
return true;
else if (m->IsNPC() && m->CastToNPC()->GetSwarmOwner() == group_member->GetID())
return true;
else
return false;
};
for (auto &e : mob_list) {
auto mob = e.second;
auto it = casted_on.find(mob->GetID());
bool good = verify_solo(mob);
if (it != casted_on.end()) { // make sure still valid
if (!good || DistanceSquared(GetPosition(), mob->GetPosition()) > distance) {
delayed_remove.insert(mob->GetID());
}
} else if (good && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) {
casted_on.insert(mob->GetID());
if (is_buff)
SpellFinished(spell_id, mob);
}
}
}
for (auto &e : delayed_remove) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove
mob->BuffFadeBySpellIDAndCaster(spell_id, GetID());
casted_on.erase(e);
}
// so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it
if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty())
cast_timer.Start();
if (!cast_timer.Enabled() || !cast_timer.Check())
return;
// some auras have to recast (DRU for example, non-buff too)
for (auto &e : casted_on) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr)
SpellFinished(spell_id, mob);
}
}
void Aura::ProcessTotem(Mob *owner)
{
auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline
std::set<int> delayed_remove;
bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter
for (auto &e : mob_list) {
auto mob = e.second;
if (mob == this)
continue;
if (mob == owner)
continue;
if (owner->IsAttackAllowed(mob)) { // might need more checks ...
bool in_range = DistanceSquared(GetPosition(), mob->GetPosition()) <= distance;
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) {
if (!in_range)
delayed_remove.insert(mob->GetID());
} else if (in_range) {
casted_on.insert(mob->GetID());
SpellFinished(spell_id, mob);
}
}
}
for (auto &e : delayed_remove) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove
mob->BuffFadeBySpellIDAndCaster(spell_id, GetID());
casted_on.erase(e);
}
// so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it
if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty())
cast_timer.Start();
if (!cast_timer.Enabled() || !cast_timer.Check())
return;
for (auto &e : casted_on) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr)
SpellFinished(spell_id, mob);
}
}
void Aura::ProcessEnterTrap(Mob *owner)
{
auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline
for (auto &e : mob_list) {
auto mob = e.second;
if (mob == this)
continue;
// might need more checks ...
if (owner->IsAttackAllowed(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) {
SpellFinished(spell_id, mob);
owner->RemoveAura(GetID(), false); // if we're a buff (ex. NEC) we don't want to strip :P
break;
}
}
}
void Aura::ProcessExitTrap(Mob *owner)
{
auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline
for (auto &e : mob_list) {
auto mob = e.second;
if (mob == this)
continue;
// might need more checks ...
if (owner->IsAttackAllowed(mob)) {
bool in_range = DistanceSquared(GetPosition(), mob->GetPosition()) <= distance;
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) {
if (!in_range) {
SpellFinished(spell_id, mob);
owner->RemoveAura(GetID(), false); // if we're a buff we don't want to strip :P
break;
}
} else if (in_range) {
casted_on.insert(mob->GetID());
}
}
}
}
// this is less than ideal, but other solutions are a bit all over the place
// and hard to reason about
void Aura::ProcessSpawns()
{
const auto &clients = entity_list.GetClientList();
for (auto &e : clients) {
auto c = e.second;
bool spawned = spawned_for.find(c->GetID()) != spawned_for.end();
if (ShouldISpawnFor(c)) {
if (!spawned) {
EQApplicationPacket app;
CreateSpawnPacket(&app, this);
c->QueuePacket(&app);
SendArmorAppearance(c);
spawned_for.insert(c->GetID());
}
} else if (spawned) {
EQApplicationPacket app;
CreateDespawnPacket(&app, false);
c->QueuePacket(&app);
spawned_for.erase(c->GetID());
}
}
return;
}
bool Aura::Process()
{
// Aura::Depop clears buffs
if (p_depop)
return false;
auto owner = entity_list.GetMob(m_owner);
if (owner == nullptr) {
Depop();
return true;
}
if (remove_timer.Check()) {
owner->RemoveAura(GetID(), false, true);
return true;
}
if (movement_type == AuraMovement::Follow && GetPosition() != owner->GetPosition() && movement_timer.Check()) {
m_Position = owner->GetPosition();
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
auto spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
MakeSpawnUpdate(spu);
auto it = spawned_for.begin();
while (it != spawned_for.end()) {
auto client = entity_list.GetClientByID(*it);
if (client) {
client->QueuePacket(app);
++it;
} else {
it = spawned_for.erase(it);
}
}
}
// TODO: waypoints?
if (!process_timer.Check())
return true;
if (spawn_type != AuraSpawns::Noone)
ProcessSpawns(); // bit of a hack
if (process_func)
process_func(*this, owner);
// TODO: quest calls
return true;
}
bool Aura::ShouldISpawnFor(Client *c)
{
if (spawn_type == AuraSpawns::Noone)
return false;
if (spawn_type == AuraSpawns::Everyone)
return true;
// hey, it's our owner!
if (c->GetID() == m_owner)
return true;
// so this one is a bit trickier
auto owner = GetOwner();
if (owner == nullptr)
return false; // hmm
owner = owner->GetOwnerOrSelf(); // pet auras we need the pet's owner
if (owner == nullptr) // shouldn't really be needed
return false;
// gotta check again for pet aura case -.-
if (owner == c)
return true;
if (owner->IsRaidGrouped() && owner->IsClient()) {
auto raid = owner->GetRaid();
if (raid == nullptr)
return false; // hmm
auto group_id = raid->GetGroup(owner->CastToClient());
if (group_id == 0xFFFFFFFF) // owner handled above, and they're in a raid and groupless
return false;
auto idx = raid->GetPlayerIndex(c);
if (idx == 0xFFFFFFFF) // they're not in our raid!
return false;
if (raid->members[idx].GroupNumber != group_id) // in our raid, but not our group
return false;
return true; // we got here so we know that 1 they're in our raid and 2 they're in our group!
} else if (owner->IsGrouped()) {
auto group = owner->GetGroup();
if (group == nullptr)
return false; // hmm
// easy, in our group
return group->IsGroupMember(c);
}
// our owner is not raided or grouped, and they're handled above so we don't spawn!
return false;
}
void Aura::Depop(bool skip_strip)
{
// NEC trap casts a dot, so we need some way to not strip :P
if (!skip_strip && IsBuffSpell(spell_id)) {
for (auto &e : casted_on) {
auto mob = entity_list.GetMob(e);
if (mob != nullptr)
mob->BuffFadeBySpellIDAndCaster(spell_id, GetID());
}
}
casted_on.clear();
p_depop = true;
}
// This creates an aura from a casted spell
void Mob::MakeAura(uint16 spell_id)
{
// TODO: verify room in AuraMgr
if (!IsValidSpell(spell_id))
return;
AuraRecord record;
if (!database.GetAuraEntry(spell_id, record)) {
Message(13, "Unable to find data for aura %s", spells[spell_id].name);
Log(Logs::General, Logs::Error, "Unable to find data for aura %d, check auras table.", spell_id);
return;
}
if (!IsValidSpell(record.spell_id)) {
Message(13, "Casted spell (%d) is not valid for aura %s", record.spell_id, spells[spell_id].name);
Log(Logs::General, Logs::Error, "Casted spell (%d) is not valid for aura %d, check auras table.",
record.spell_id, spell_id);
return;
}
if (record.aura_type > static_cast<int>(AuraType::Max)) {
return; // TODO: log
}
bool trap = false;
switch (static_cast<AuraType>(record.aura_type)) {
case AuraType::ExitTrap:
case AuraType::EnterTrap:
case AuraType::Totem:
trap = true;
break;
default:
trap = false;
break;
}
if (!CanSpawnAura(trap))
return;
const auto base = database.LoadNPCTypesData(record.npc_type);
if (base == nullptr) {
Message(13, "Unable to load NPC data for aura %s", spells[spell_id].teleport_zone);
Log(Logs::General, Logs::Error,
"Unable to load NPC data for aura %s (NPC ID %d), check auras and npc_types tables.",
spells[spell_id].teleport_zone, record.npc_type);
return;
}
auto npc_type = new NPCType;
memcpy(npc_type, base, sizeof(NPCType));
strn0cpy(npc_type->name, record.name, 64);
auto npc = new Aura(npc_type, this, record);
npc->SetAuraID(spell_id);
entity_list.AddNPC(npc, false);
if (trap)
AddTrap(npc, record);
else
AddAura(npc, record);
}
bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord &record)
{
auto query = StringFormat("SELECT npc_type, name, spell_id, distance, aura_type, spawn_type, movement, "
"duration, icon, cast_time FROM auras WHERE type='%d'",
spell_id);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() != 1)
return false;
auto row = results.begin();
record.npc_type = atoi(row[0]);
strn0cpy(record.name, row[1], 64);
record.spell_id = atoi(row[2]);
record.distance = atoi(row[3]);
record.distance *= record.distance; // so we can avoid sqrt
record.aura_type = atoi(row[4]);
record.spawn_type = atoi(row[5]);
record.movement = atoi(row[6]);
record.duration = atoi(row[7]) * 1000; // DB is in seconds
record.icon = atoi(row[8]);
record.cast_time = atoi(row[9]) * 1000; // DB is in seconds
return true;
}
void Mob::AddAura(Aura *aura, AuraRecord &record)
{
// this is called only when it's safe
assert(aura != nullptr);
strn0cpy(aura_mgr.auras[aura_mgr.count].name, aura->GetCleanName(), 64);
aura_mgr.auras[aura_mgr.count].spawn_id = aura->GetID();
aura_mgr.auras[aura_mgr.count].aura = aura;
if (record.icon == -1)
aura_mgr.auras[aura_mgr.count].icon = spells[record.spell_id].new_icon;
else
aura_mgr.auras[aura_mgr.count].icon = record.icon;
if (IsClient()) {
auto outapp = new EQApplicationPacket(OP_UpdateAura, sizeof(AuraCreate_Struct));
auto aura_create = (AuraCreate_Struct *)outapp->pBuffer;
aura_create->action = 0;
aura_create->type = 1; // this can be 0 sometimes too
strn0cpy(aura_create->aura_name, aura_mgr.auras[aura_mgr.count].name, 64);
aura_create->entity_id = aura_mgr.auras[aura_mgr.count].spawn_id;
aura_create->icon = aura_mgr.auras[aura_mgr.count].icon;
CastToClient()->FastQueuePacket(&outapp);
}
// we can increment this now
aura_mgr.count++;
}
void Mob::AddTrap(Aura *aura, AuraRecord &record)
{
// this is called only when it's safe
assert(aura != nullptr);
strn0cpy(trap_mgr.auras[trap_mgr.count].name, aura->GetCleanName(), 64);
trap_mgr.auras[trap_mgr.count].spawn_id = aura->GetID();
trap_mgr.auras[trap_mgr.count].aura = aura;
if (record.icon == -1)
trap_mgr.auras[trap_mgr.count].icon = spells[record.spell_id].new_icon;
else
trap_mgr.auras[trap_mgr.count].icon = record.icon;
// doesn't send to client
trap_mgr.count++;
}
bool Mob::CanSpawnAura(bool trap)
{
if (trap && !HasFreeTrapSlots()) {
Message_StringID(MT_SpellFailure, NO_MORE_TRAPS);
return false;
} else if (!trap && !HasFreeAuraSlots()) {
Message_StringID(MT_SpellFailure, NO_MORE_AURAS);
return false;
}
return true;
}
void Mob::RemoveAllAuras()
{
if (IsClient()) {
database.SaveAuras(CastToClient());
EQApplicationPacket outapp(OP_UpdateAura, 4);
outapp.WriteUInt32(2);
CastToClient()->QueuePacket(&outapp);
}
// this is sent on camp/zone, so it just despawns?
if (aura_mgr.count) {
for (auto &e : aura_mgr.auras) {
if (e.aura)
e.aura->Depop();
}
}
aura_mgr.count = 0;
if (trap_mgr.count) {
for (auto &e : trap_mgr.auras) {
if (e.aura)
e.aura->Depop();
}
}
trap_mgr.count = 0;
return;
}
void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired)
{
for (int i = 0; i < aura_mgr.count; ++i) {
auto &aura = aura_mgr.auras[i];
if (aura.spawn_id == spawn_id) {
if (aura.aura)
aura.aura->Depop(skip_strip);
if (expired && IsClient()) {
CastToClient()->SendColoredText(
CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color
// need to update client UI too
auto app = new EQApplicationPacket(OP_UpdateAura, sizeof(AuraDestory_Struct));
auto ads = (AuraDestory_Struct *)app->pBuffer;
ads->action = 1; // delete
ads->entity_id = spawn_id;
CastToClient()->QueuePacket(app);
safe_delete(app);
}
while (aura_mgr.count - 1 > i) {
i++;
aura.spawn_id = aura_mgr.auras[i].spawn_id;
aura.icon = aura_mgr.auras[i].icon;
aura.aura = aura_mgr.auras[i].aura;
aura_mgr.auras[i].aura = nullptr;
strn0cpy(aura.name, aura_mgr.auras[i].name, 64);
}
aura_mgr.count--;
return;
}
}
for (int i = 0; i < trap_mgr.count; ++i) {
auto &aura = trap_mgr.auras[i];
if (aura.spawn_id == spawn_id) {
if (aura.aura)
aura.aura->Depop(skip_strip);
if (expired && IsClient())
CastToClient()->SendColoredText(
CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color
while (trap_mgr.count - 1 > i) {
i++;
aura.spawn_id = trap_mgr.auras[i].spawn_id;
aura.icon = trap_mgr.auras[i].icon;
aura.aura = trap_mgr.auras[i].aura;
trap_mgr.auras[i].aura = nullptr;
strn0cpy(aura.name, trap_mgr.auras[i].name, 64);
}
trap_mgr.count--;
return;
}
}
return;
}

91
zone/aura.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef AURA_H
#define AURA_H
#include <functional>
#include <set>
#include "mob.h"
#include "npc.h"
#include "../common/types.h"
#include "../common/timer.h"
class Group;
class Raid;
class Mob;
struct NPCType;
enum class AuraType {
OnAllFriendlies, // AE PC/Pet basically (ex. Circle of Power)
OnAllGroupMembers, // Normal buffing aura (ex. Champion's Aura)
OnGroupMembersPets, // Hits just pets (ex. Rathe's Strength)
Totem, // Starts pulsing on a timer when an enemy enters (ex. Idol of Malos)
EnterTrap, // Casts once when an enemy enters (ex. Fire Rune)
ExitTrap, // Casts when they start to flee (ex. Poison Spikes Trap)
FullyScripted, // We just call script function not a predefined
Max
};
enum class AuraSpawns {
GroupMembers, // most auras use this
Everyone, // this is like traps and clickies who cast on everyone
Noone, // custom!
Max
};
enum class AuraMovement {
Follow, // follows caster
Stationary,
Pathing, // some sorted pathing TODO: implement
Max
};
class Aura : public NPC
{
// NOTE: We may have to override more virtual functions if they're causing issues
public:
Aura(NPCType *type_data, Mob *owner, AuraRecord &record);
~Aura() { };
bool IsAura() const { return true; }
bool Process();
void Depop(bool skip_strip = false);
Mob *GetOwner();
void ProcessOnAllFriendlies(Mob *owner);
void ProcessOnAllGroupMembers(Mob *owner);
void ProcessOnGroupMembersPets(Mob *owner);
void ProcessTotem(Mob *owner);
void ProcessEnterTrap(Mob *owner);
void ProcessExitTrap(Mob *owner);
void ProcessSpawns();
// we only save auras that follow you, and player casted
inline bool AuraZones() { return movement_type == AuraMovement::Follow && aura_id > -1; }
inline int GetSpellID() { return spell_id; }
inline int GetAuraID() { return aura_id; }
inline void SetAuraID(int in) { aura_id = in; }
bool ShouldISpawnFor(Client *c);
// so when we join a group, we need to spawn not already spawned auras
// This is only possible when spawn type is GroupMembers
inline bool JoinGroupSpawnCheck() { return spawn_type == AuraSpawns::GroupMembers; }
private:
int m_owner;
int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell
int spell_id; // spell we cast
int distance; // distance we remove
Timer remove_timer; // when we depop
Timer process_timer; // rate limit process calls
Timer cast_timer; // some auras pulse
Timer movement_timer; // rate limit movement updates
AuraType type;
AuraSpawns spawn_type;
AuraMovement movement_type;
std::function<void(Aura &, Mob *)> process_func;
std::set<int> casted_on; // we keep track of the other entities we've casted on
std::set<int> spawned_for;
};
#endif /* !AURA_H */

View File

@ -1460,6 +1460,14 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
newbon->FeignedMinionChance = base1;
break;
case SE_AdditionalAura:
newbon->aura_slots += base1;
break;
case SE_IncreaseTrapCount:
newbon->trap_slots += base1;
break;
// to do
case SE_PetDiscipline:
break;
@ -3201,6 +3209,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
if (new_bonus->FeignedCastOnChance < effect_value)
new_bonus->FeignedCastOnChance = effect_value;
break;
case SE_AdditionalAura:
if (new_bonus->aura_slots < effect_value)
new_bonus->aura_slots = effect_value;
break;
case SE_IncreaseTrapCount:
if (new_bonus->trap_slots < effect_value)
new_bonus->trap_slots = effect_value;
break;
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
if (IsAISpellEffect) {

View File

@ -2929,6 +2929,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive];
ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF;
ns->spawn.equip_chest2 = texture; //0xFF;
ns->spawn.show_name = true;
const EQEmu::ItemData* item = nullptr;
const EQEmu::ItemInstance* inst = nullptr;
uint32 spawnedbotid = 0;

View File

@ -299,6 +299,7 @@ public:
const char* GetBuyerWelcomeMessage() { return BuyerWelcomeMessage.c_str(); }
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
bool ShouldISpawnFor(Client *c) { return !GMHideMe(c) && !IsHoveringForRespawn(); }
virtual bool Process();
void ProcessPackets();
void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemData* item, bool buying);

View File

@ -323,6 +323,7 @@ void MapOpcodes()
ConnectedOpcodes[OP_RecipesSearch] = &Client::Handle_OP_RecipesSearch;
ConnectedOpcodes[OP_ReloadUI] = &Client::Handle_OP_ReloadUI;
ConnectedOpcodes[OP_RemoveBlockedBuffs] = &Client::Handle_OP_RemoveBlockedBuffs;
ConnectedOpcodes[OP_RemoveTrap] = &Client::Handle_OP_RemoveTrap;
ConnectedOpcodes[OP_Report] = &Client::Handle_OP_Report;
ConnectedOpcodes[OP_RequestDuel] = &Client::Handle_OP_RequestDuel;
ConnectedOpcodes[OP_RequestTitles] = &Client::Handle_OP_RequestTitles;
@ -383,6 +384,7 @@ void MapOpcodes()
ConnectedOpcodes[OP_TributeUpdate] = &Client::Handle_OP_TributeUpdate;
ConnectedOpcodes[OP_VetClaimRequest] = &Client::Handle_OP_VetClaimRequest;
ConnectedOpcodes[OP_VoiceMacroIn] = &Client::Handle_OP_VoiceMacroIn;
ConnectedOpcodes[OP_UpdateAura] = &Client::Handle_OP_UpdateAura;;
ConnectedOpcodes[OP_WearChange] = &Client::Handle_OP_WearChange;
ConnectedOpcodes[OP_WhoAllRequest] = &Client::Handle_OP_WhoAllRequest;
ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore;
@ -882,6 +884,8 @@ void Client::CompleteConnect()
SetPetCommandState(PET_BUTTON_SPELLHOLD, 0);
}
database.LoadAuras(this); // this ends up spawning them so probably safer to load this later (here)
entity_list.RefreshClientXTargets(this);
worldserver.RequestTellQueue(GetName());
@ -11776,6 +11780,28 @@ void Client::Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app)
}
}
void Client::Handle_OP_RemoveTrap(const EQApplicationPacket *app)
{
if (app->size != 4) {// just an int
Log(Logs::General, Logs::None, "Size mismatch in OP_RemoveTrap expected 4 got %i", app->size);
DumpPacket(app);
return;
}
auto id = app->ReadUInt32(0);
bool good = false;
for (int i = 0; i < trap_mgr.count; ++i) {
if (trap_mgr.auras[i].spawn_id == id) {
good = true;
break;
}
}
if (good)
RemoveAura(id);
else
Message_StringID(MT_SpellFailure, NOT_YOUR_TRAP); // pretty sure this was red
}
void Client::Handle_OP_Report(const EQApplicationPacket *app)
{
if (!CanUseReport)
@ -14294,6 +14320,24 @@ void Client::Handle_OP_VoiceMacroIn(const EQApplicationPacket *app)
}
void Client::Handle_OP_UpdateAura(const EQApplicationPacket *app)
{
if (app->size != sizeof(AuraDestory_Struct)) {
Log(Logs::General, Logs::None, "Size mismatch in OP_UpdateAura expected %i got %i",
sizeof(AuraDestory_Struct), app->size);
return;
}
// client only sends this for removing
auto aura = (AuraDestory_Struct *)app->pBuffer;
if (aura->action != 1)
return; // could log I guess, but should only ever get this action
RemoveAura(aura->entity_id);
QueuePacket(app); // if we don't resend this, the client gets confused
return;
}
void Client::Handle_OP_WearChange(const EQApplicationPacket *app)
{
if (app->size != sizeof(WearChange_Struct)) {

View File

@ -236,6 +236,7 @@
void Handle_OP_RecipesSearch(const EQApplicationPacket *app);
void Handle_OP_ReloadUI(const EQApplicationPacket *app);
void Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app);
void Handle_OP_RemoveTrap(const EQApplicationPacket *app);
void Handle_OP_Report(const EQApplicationPacket *app);
void Handle_OP_RequestDuel(const EQApplicationPacket *app);
void Handle_OP_RequestTitles(const EQApplicationPacket *app);
@ -288,6 +289,7 @@
void Handle_OP_TributeNPC(const EQApplicationPacket *app);
void Handle_OP_TributeToggle(const EQApplicationPacket *app);
void Handle_OP_TributeUpdate(const EQApplicationPacket *app);
void Handle_OP_UpdateAura(const EQApplicationPacket *app);
void Handle_OP_VetClaimRequest(const EQApplicationPacket *app);
void Handle_OP_VoiceMacroIn(const EQApplicationPacket *app);
void Handle_OP_WearChange(const EQApplicationPacket *app);

View File

@ -722,6 +722,8 @@ void Client::OnDisconnect(bool hard_disconnect) {
}
}
RemoveAllAuras();
Mob *Other = trade->With();
if(Other)
{

View File

@ -105,6 +105,8 @@
#define PET_BUTTON_FOCUS 8
#define PET_BUTTON_SPELLHOLD 9
#define AURA_HARDCAP 2
typedef enum { //focus types
focusSpellHaste = 1,
focusSpellDuration,
@ -205,6 +207,16 @@ typedef enum { //fear states
enum { FlyMode0 = 0, FlyMode1 = 1, Flymode2 = 2, FlyMode3 = 3 };
// This is actually FlyMode, from MQ2
enum GravityBehavior {
Ground,
Flying,
Levitating,
Water,
Floating, // boat
LevitateWhileRunning
};
struct TradeEntity;
class Trade;
enum TradeState {
@ -536,6 +548,8 @@ struct StatBonuses {
int16 FeignedCastOnChance; // Percent Value
bool PetCommands[PET_MAXCOMMANDS]; // SPA 267
int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD
int aura_slots;
int trap_slots;
};
typedef struct

View File

@ -1246,12 +1246,9 @@ void EntityList::SendZoneSpawns(Client *client)
auto it = mob_list.begin();
while (it != mob_list.end()) {
Mob *ent = it->second;
if (!(ent->InZone()) || (ent->IsClient())) {
if (ent->CastToClient()->GMHideMe(client) ||
ent->CastToClient()->IsHoveringForRespawn()) {
++it;
continue;
}
if (!ent->InZone() || !ent->ShouldISpawnFor(client)) {
++it;
continue;
}
app = new EQApplicationPacket;
@ -1279,17 +1276,16 @@ void EntityList::SendZoneSpawnsBulk(Client *client)
for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
spawn = it->second;
if (spawn && spawn->GetID() > 0 && spawn->Spawned()) {
if (spawn->IsClient() && (spawn->CastToClient()->GMHideMe(client) ||
spawn->CastToClient()->IsHoveringForRespawn()))
if (!spawn->ShouldISpawnFor(client))
continue;
#if 1
const glm::vec4& spos = spawn->GetPosition();
delaypkt = false;
if (DistanceSquared(cpos, spos) > dmax || (spawn->IsClient() && (spawn->GetRace() == MINOR_ILL_OBJ || spawn->GetRace() == TREE)))
delaypkt = true;
if (delaypkt) {
app = new EQApplicationPacket;
spawn->CreateSpawnPacket(app);
@ -2659,7 +2655,7 @@ void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, float u
mob && !mob->IsCorpse()
&& (it->second != client)
&& (mob->IsClient() || iSendEvenIfNotChanged || (mob->LastChange() >= cLastUpdate))
&& (!it->second->IsClient() || !it->second->CastToClient()->GMHideMe(client))
&& (it->second->ShouldISpawnFor(client))
) {
if (
update_range == 0

View File

@ -80,6 +80,7 @@ public:
virtual bool IsBeacon() const { return false; }
virtual bool IsEncounter() const { return false; }
virtual bool IsBot() const { return false; }
virtual bool IsAura() const { return false; }
virtual bool Process() { return false; }
virtual bool Save() { return true; }

View File

@ -142,7 +142,8 @@ void Mob::CalculateNewFearpoint()
int loop = 0;
float ranx, rany, ranz;
currently_fleeing = false;
currently_fleeing = true;
while (loop < 100) //Max 100 tries
{
int ran = 250 - (loop*2);
@ -155,7 +156,6 @@ void Mob::CalculateNewFearpoint()
float fdist = ranz - GetZ();
if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz))
{
currently_fleeing = true;
break;
}
}

View File

@ -1211,6 +1211,7 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.flymode = 0;
ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse
ns->spawn.IsMercenary = 1;
ns->spawn.show_name = true;
UpdateActiveLight();
ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive];

View File

@ -45,6 +45,8 @@ class EQApplicationPacket;
class Group;
class NPC;
class Raid;
class Aura;
struct AuraRecord;
struct NewSpawn_Struct;
struct PlayerPositionUpdateServer_Struct;
@ -85,6 +87,23 @@ public:
int params[MAX_SPECIAL_ATTACK_PARAMS];
};
struct AuraInfo {
char name[64];
int spawn_id;
int icon;
Aura *aura;
AuraInfo() : spawn_id(0), icon(0), aura(nullptr)
{
memset(name, 0, 64);
}
};
struct AuraMgr {
int count; // active auras
AuraInfo auras[AURA_HARDCAP];
AuraMgr() : count(0) { }
};
Mob(const char* in_name,
const char* in_lastname,
int32 in_cur_hp,
@ -308,6 +327,7 @@ public:
void BuffProcess();
virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr);
void BuffFadeBySpellID(uint16 spell_id);
void BuffFadeBySpellIDAndCaster(uint16 spell_id, uint16 caster_id);
void BuffFadeByEffect(int effectid, int skipslot = -1);
void BuffFadeAll();
void BuffFadeNonPersistDeath();
@ -315,6 +335,7 @@ public:
void BuffFadeBySlot(int slot, bool iRecalcBonuses = true);
void BuffFadeDetrimentalByCaster(Mob *caster);
void BuffFadeBySitModifier();
bool IsAffectedByBuff(uint16 spell_id);
void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration);
int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1);
int CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite = false);
@ -528,6 +549,7 @@ public:
void SendPosition();
void SetSpawned() { spawned = true; };
bool Spawned() { return spawned; };
virtual bool ShouldISpawnFor(Client *c) { return true; }
void SetFlyMode(uint8 flymode);
inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y;
m_Position.z = NewPosition.z; };
@ -604,6 +626,19 @@ public:
bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest,
bool lookForAftArc = true);
// aura functions
void MakeAura(uint16 spell_id);
inline int GetAuraSlots() { return 1 + aabonuses.aura_slots + itembonuses.aura_slots + spellbonuses.aura_slots; }
inline int GetTrapSlots() { return 1 + aabonuses.trap_slots + itembonuses.trap_slots + spellbonuses.trap_slots; }
inline bool HasFreeAuraSlots() { return aura_mgr.count < GetAuraSlots(); }
inline bool HasFreeTrapSlots() { return trap_mgr.count < GetTrapSlots(); }
void AddAura(Aura *aura, AuraRecord &record);
void AddTrap(Aura *aura, AuraRecord &record);
bool CanSpawnAura(bool trap);
void RemoveAura(int spawn_id, bool skip_strip = false, bool expired = false);
void RemoveAllAuras();
inline AuraMgr &GetAuraMgr() { return aura_mgr; } // mainly used for zone db loading/saving
//Procs
void TriggerDefensiveProcs(Mob *on, uint16 hand = EQEmu::inventory::slotPrimary, bool FromSkillProc = false, int damage = 0);
bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN);
@ -1090,7 +1125,7 @@ protected:
int _GetWalkSpeed() const;
int _GetRunSpeed() const;
int _GetFearSpeed() const;
virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ);
virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, int speed);
virtual bool AI_EngagedCastCheck() { return(false); }
virtual bool AI_PursueCastCheck() { return(false); }
@ -1455,6 +1490,9 @@ protected:
bool IsHorse;
AuraMgr aura_mgr;
AuraMgr trap_mgr;
private:
void _StopSong(); //this is not what you think it is
Mob* target;

View File

@ -1532,7 +1532,11 @@ void NPC::AI_DoMovement() {
Log(Logs::Detail, Logs::AI, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y);
if (!CalculateNewPosition(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true))
float new_z = this->FindGroundZ(m_Position.x, m_Position.y, 5);
new_z += (this->GetSize() / 1.55);
if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, new_z, walksp, true))
{
roambox_movingto_x = roambox_max_x + 1; // force update
pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay);

View File

@ -90,6 +90,7 @@ class Client;
class Group;
class Raid;
class Spawn2;
class Aura;
namespace EQEmu
{
@ -425,6 +426,7 @@ protected:
NPCType* NPCTypedata_ours; //special case for npcs with uniquely created data.
friend class EntityList;
friend class Aura;
std::list<struct NPCFaction*> faction_list;
uint32 copper;
uint32 silver;

View File

@ -491,6 +491,14 @@ uint32 Raid::GetPlayerIndex(const char *name){
return 0; //should never get to here if we do everything else right, set it to 0 so we never crash things that rely on it.
}
uint32 Raid::GetPlayerIndex(Client *c)
{
for (int i = 0; i < MAX_RAID_MEMBERS; ++i)
if (c == members[i].member)
return i;
return 0xFFFFFFFF; // return sentinel value, make sure you check it unlike the above function
}
Client *Raid::GetClientByIndex(uint16 index)
{
if(index > MAX_RAID_MEMBERS)

View File

@ -142,6 +142,7 @@ public:
//keeps me from having to keep iterating through the list
//when I want lots of data from the same entry
uint32 GetPlayerIndex(const char *name);
uint32 GetPlayerIndex(Client *c);
//for perl interface
Client *GetClientByIndex(uint16 index);
const char *GetClientNameByIndex(uint8 index);

View File

@ -2791,6 +2791,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
break;
}
case SE_PersistentEffect:
MakeAura(spell_id);
break;
// Handled Elsewhere
case SE_ImmuneFleeing:
case SE_NegateSpellEffect:
@ -5959,7 +5963,8 @@ bool Mob::TryDeathSave() {
bool Mob::AffectedBySpellExcludingSlot(int slot, int effect)
{
for (int i = 0; i <= EFFECT_COUNT; i++)
int buff_count = GetMaxTotalSlots();
for (int i = 0; i < buff_count; i++)
{
if (i == slot)
continue;

View File

@ -3447,7 +3447,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
if(spelltar->IsClient() && spelltar->CastToClient()->IsHoveringForRespawn())
return false;
if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar) && !IsResurrectionEffects(spell_id)) {
if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id)) {
if(!IsClient() || !CastToClient()->GetGM()) {
Message_StringID(MT_SpellFailure, SPELL_NO_HOLD);
return false;
@ -4189,6 +4189,21 @@ void Mob::BuffFadeBySpellID(uint16 spell_id)
CalcBonuses();
}
void Mob::BuffFadeBySpellIDAndCaster(uint16 spell_id, uint16 caster_id)
{
bool recalc_bonus = false;
auto buff_count = GetMaxTotalSlots();
for (int i = 0; i < buff_count; ++i) {
if (buffs[i].spellid == spell_id && buffs[i].casterid == caster_id) {
BuffFadeBySlot(i, false);
recalc_bonus = true;
}
}
if (recalc_bonus)
CalcBonuses();
}
// removes buffs containing effectid, skipping skipslot
void Mob::BuffFadeByEffect(int effectid, int skipslot)
{
@ -4207,6 +4222,16 @@ void Mob::BuffFadeByEffect(int effectid, int skipslot)
CalcBonuses();
}
bool Mob::IsAffectedByBuff(uint16 spell_id)
{
int buff_count = GetMaxTotalSlots();
for (int i = 0; i < buff_count; ++i)
if (buffs[i].spellid == spell_id)
return true;
return false;
}
// checks if 'this' can be affected by spell_id from caster
// returns true if the spell should fail, false otherwise
bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)

View File

@ -286,6 +286,7 @@
#define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1!
#define EXPEDITION_MIN_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end.
#define LOOT_NOT_ALLOWED 3562 //You are not allowed to loot the item: %1.
#define NOT_YOUR_TRAP 3671 //You cannot remove this, you are only allowed to remove traps you have set.
#define NO_CAST_ON_PET 4045 //You cannot cast this spell on your pet.
#define REWIND_WAIT 4059 //You must wait a bit longer before using the rewind command again.
#define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can!
@ -361,6 +362,7 @@
#define GAIN_GROUP_LEADERSHIP_EXP 8788 //
#define GAIN_RAID_LEADERSHIP_EXP 8789 //
#define BUFF_MINUTES_REMAINING 8799 //%1 (%2 minutes remaining)
#define NO_MORE_TRAPS 9002 //You have already placed your maximum number of traps.
#define FEAR_TOO_HIGH 9035 //Your target is too high of a level for your fear spell.
#define SLOW_MOSTLY_SUCCESSFUL 9029 //Your spell was mostly successful.
#define SLOW_PARTIALLY_SUCCESSFUL 9030 // Your spell was partially successful.
@ -375,6 +377,7 @@
#define SHAKE_OFF_STUN 9077 //You shake off the stun effect!
#define STRIKETHROUGH_STRING 9078 //You strike through your opponent's defenses!
#define SPELL_REFLECT 9082 //%1's spell has been reflected by %2.
#define NO_MORE_AURAS 9160 //You do not have sufficient focus to maintain that ability.
#define NEW_SPELLS_AVAIL 9149 //You have new spells available to you. Check the merchants near your guild master.
#define FD_CAST_ON_NO_BREAK 9174 //The strength of your will allows you to resume feigning death.
#define SNEAK_RESTRICT 9240 //You can not use this ability because you have not been hidden for long enough.

View File

@ -451,7 +451,7 @@ float Mob::CalculateHeadingToTarget(float in_x, float in_y) {
return (256 * (360 - angle) / 360.0f);
}
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ) {
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed) {
if (GetID() == 0)
return true;
@ -495,7 +495,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
m_Position.y = new_y;
m_Position.z = new_z;
if(fix_z_timer.Check() && !this->IsEngaged())
if(fix_z_timer.Check() &&
(!this->IsEngaged() || flee_mode || currently_fleeing))
this->FixZ();
tar_ndx++;
@ -1048,4 +1049,4 @@ void NPC::SaveGuardSpotCharm()
void NPC::RestoreGuardSpotCharm()
{
m_GuardPoint = m_GuardPointSaved;
}
}

View File

@ -11,6 +11,7 @@
#include "merc.h"
#include "zone.h"
#include "zonedb.h"
#include "aura.h"
#include <ctime>
#include <iostream>
@ -3152,6 +3153,37 @@ void ZoneDatabase::LoadBuffs(Client *client)
}
}
void ZoneDatabase::SaveAuras(Client *c)
{
auto query = StringFormat("DELETE FROM `character_auras` WHERE `id` = %u", c->CharacterID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
const auto &auras = c->GetAuraMgr();
for (int i = 0; i < auras.count; ++i) {
auto aura = auras.auras[i].aura;
if (aura && aura->AuraZones()) {
query = StringFormat("INSERT INTO `character_auras` (id, slot, spell_id) VALUES(%u, %d, %d)",
c->CharacterID(), i, aura->GetAuraID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
}
}
}
void ZoneDatabase::LoadAuras(Client *c)
{
auto query = StringFormat("SELECT `spell_id` FROM `character_auras` WHERE `id` = %u ORDER BY `slot`", c->CharacterID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
c->MakeAura(atoi(row[0]));
}
void ZoneDatabase::SavePetInfo(Client *client)
{
PetInfo *petinfo = nullptr;

View File

@ -123,6 +123,19 @@ struct PetRecord {
uint32 equipmentset; // default equipment for the pet
};
struct AuraRecord {
uint32 npc_type;
char name[64]; // name shown in UI if shown and spawn name
int spell_id;
int distance;
int aura_type;
int spawn_type;
int movement;
int duration; // seconds some live for 90 mins (normal) others for 2 mins (traps)
int icon; // -1 will use the buffs NEW_ICON
int cast_time; // seconds some auras recast on a timer, most seem to be every 12 seconds
};
// Actual pet info for a client.
struct PetInfo {
uint16 SpellID;
@ -260,6 +273,8 @@ public:
void SaveBuffs(Client *c);
void LoadBuffs(Client *c);
void SaveAuras(Client *c);
void LoadAuras(Client *c);
void LoadPetInfo(Client *c);
void SavePetInfo(Client *c);
void RemoveTempFactions(Client *c);
@ -404,6 +419,7 @@ public:
void AddLootDropToNPC(NPC* npc, uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop);
uint32 GetMaxNPCSpellsID();
uint32 GetMaxNPCSpellsEffectsID();
bool GetAuraEntry(uint16 spell_id, AuraRecord &record);
DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID);
DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID);