*Add spell_dbc table to store dbc entries not present in client
*Remove workaround from Demonic Circle code and use the sql table instead. --HG-- branch : trunk
This commit is contained in:
@@ -165,13 +165,17 @@ static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, const std::string& f
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage<T>& storage, const std::string& dbc_path, const std::string& filename)
|
||||
inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage<T>& storage, const std::string& dbc_path, const std::string& filename, const std::string * custom_entries = NULL, const std::string * idname = NULL)
|
||||
{
|
||||
// compatibility format and C++ structure sizes
|
||||
assert(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename));
|
||||
|
||||
std::string dbc_filename = dbc_path + filename;
|
||||
if(storage.Load(dbc_filename.c_str()))
|
||||
SqlDbc * sql = NULL;
|
||||
if (custom_entries)
|
||||
sql = new SqlDbc(&filename,custom_entries, idname,storage.GetFormat());
|
||||
|
||||
if(storage.Load(dbc_filename.c_str(), sql))
|
||||
{
|
||||
bar.step();
|
||||
for(uint8 i = 0; i < MAX_LOCALE; ++i)
|
||||
@@ -198,6 +202,8 @@ inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList
|
||||
else
|
||||
errlist.push_back(dbc_filename);
|
||||
}
|
||||
if (sql)
|
||||
delete sql;
|
||||
}
|
||||
|
||||
void LoadDBCStores(const std::string& dataPath)
|
||||
@@ -316,7 +322,7 @@ void LoadDBCStores(const std::string& dataPath)
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);
|
||||
for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
|
||||
{
|
||||
SpellEntry const * spell = sSpellStore.LookupEntry(i);
|
||||
|
||||
@@ -1336,7 +1336,7 @@ struct SpellEntry
|
||||
uint32 Category; // 1 m_category
|
||||
uint32 Dispel; // 2 m_dispelType
|
||||
uint32 Mechanic; // 3 m_mechanic
|
||||
uint32 Attributes; // 4 m_attribute
|
||||
uint32 Attributes; // 4 m_attributes
|
||||
uint32 AttributesEx; // 5 m_attributesEx
|
||||
uint32 AttributesEx2; // 6 m_attributesExB
|
||||
uint32 AttributesEx3; // 7 m_attributesExC
|
||||
|
||||
+3
-1
@@ -86,7 +86,9 @@ const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
|
||||
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
const char SpellCastTimefmt[]="nixx";
|
||||
const char SpellDurationfmt[]="niii";
|
||||
const char SpellEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixx";
|
||||
const char SpellEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixx";
|
||||
const std::string CustomSpellEntryfmt="pappppppppaaapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaa";
|
||||
const std::string CustomSpellEntryIndex = "Id";
|
||||
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
|
||||
const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixxx";
|
||||
const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
|
||||
|
||||
+11
-10
@@ -4468,9 +4468,6 @@ void AuraEffect::HandleAuraPeriodicDummy(bool apply, bool Real, bool changeAmoun
|
||||
if(!Real && !changeAmount)
|
||||
return;
|
||||
|
||||
// For prevent double apply bonuses
|
||||
bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
|
||||
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
SpellEntry const*spell = GetSpellProto();
|
||||
@@ -4496,17 +4493,14 @@ void AuraEffect::HandleAuraPeriodicDummy(bool apply, bool Real, bool changeAmoun
|
||||
{
|
||||
// Demonic Circle
|
||||
case 48018:
|
||||
if (apply)
|
||||
// set to false at initial cast to enable button at next enable in periodic handler
|
||||
m_target->SendAuraVisualForSelf(false,62388);
|
||||
else
|
||||
if (!apply)
|
||||
{
|
||||
// Do not remove GO when aura is removed by stack
|
||||
// to prevent remove GO added by new spell
|
||||
// old one is already removed
|
||||
if (GetParentAura()->GetRemoveMode()!=AURA_REMOVE_BY_STACK)
|
||||
m_target->RemoveGameObject(spell->Id,true);
|
||||
m_target->SendAuraVisualForSelf(false,62388);
|
||||
m_target->RemoveAura(62388);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -6380,8 +6374,15 @@ void AuraEffect::PeriodicDummyTick()
|
||||
// Demonic Circle
|
||||
case 48018:
|
||||
if(GameObject* obj = m_target->GetGameObject(spell->Id))
|
||||
// We must take a range of teleport spell, not summon.
|
||||
m_target->SendAuraVisualForSelf(m_target->IsWithinDist(obj, GetSpellMaxRange(48020, true)), 62388, 1);
|
||||
{
|
||||
if (m_target->IsWithinDist(obj, GetSpellMaxRange(48020, true)))
|
||||
{
|
||||
if (!m_target->HasAura(62388))
|
||||
m_target->CastSpell(m_target, 62388, true);
|
||||
}
|
||||
else
|
||||
m_target->RemoveAura(62388);
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3666,25 +3666,6 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_
|
||||
return modifier;
|
||||
}
|
||||
|
||||
void Unit::SendAuraVisualForSelf(bool apply, uint32 id, uint8 effmask)
|
||||
{
|
||||
WorldPacket data(SMSG_AURA_UPDATE);
|
||||
data.append(GetPackGUID());
|
||||
// use always free 64+ slots
|
||||
data << uint8(MAX_AURAS);
|
||||
if (!apply)
|
||||
{
|
||||
data << uint32(0);
|
||||
SendMessageToSet(&data, true);
|
||||
return;
|
||||
}
|
||||
data << uint32(id);
|
||||
data << uint8(AFLAG_CASTER | AFLAG_POSITIVE | effmask);
|
||||
data << uint8(getLevel());
|
||||
data << uint8(1);
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
bool Unit::AddAura(Aura *Aur, bool handleEffects)
|
||||
{
|
||||
// aura doesn't apply effects-return
|
||||
@@ -4274,9 +4255,6 @@ bool Unit::HasAura(uint32 spellId, uint64 caster) const
|
||||
//Special case for non existing spell
|
||||
if (spellId==61988)
|
||||
return HasAura(61987, caster) || HasAura(25771, caster);
|
||||
// Demonic Circle - special aura for client
|
||||
else if (spellId==62388)
|
||||
return HasAura(48018, caster);
|
||||
|
||||
if (Aura * aur = GetAura(spellId, caster))
|
||||
return true;
|
||||
|
||||
@@ -1642,7 +1642,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
||||
}
|
||||
void SetVisibleAura(uint8 slot, Aura * aur){ m_visibleAuras[slot]=aur; }
|
||||
void RemoveVisibleAura(uint8 slot){ m_visibleAuras.erase(slot); }
|
||||
void SendAuraVisualForSelf(bool apply, uint32 id, uint8 effmask = 0);
|
||||
|
||||
AuraMap & GetAuras() { return m_Auras; }
|
||||
AuraMap const& GetAuras() const { return m_Auras; }
|
||||
|
||||
@@ -137,7 +137,7 @@ uint32 DBCFileLoader::GetFormatRecordSize(const char * format,int32* index_pos)
|
||||
return recordsize;
|
||||
}
|
||||
|
||||
char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable)
|
||||
char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable)
|
||||
{
|
||||
/*
|
||||
format STRING, NA, FLOAT,NA,INT <=>
|
||||
@@ -168,6 +168,10 @@ char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**
|
||||
if(ind>maxi)maxi=ind;
|
||||
}
|
||||
|
||||
// If higher index avalible from sql - use it instead of dbcs
|
||||
if (sqlHighestIndex > maxi)
|
||||
maxi = sqlHighestIndex;
|
||||
|
||||
++maxi;
|
||||
records=maxi;
|
||||
indexTable=new ptr[maxi];
|
||||
@@ -175,15 +179,15 @@ char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**
|
||||
}
|
||||
else
|
||||
{
|
||||
records = recordCount;
|
||||
indexTable = new ptr[recordCount];
|
||||
records = recordCount + sqlRecordCount;
|
||||
indexTable = new ptr[recordCount+ sqlRecordCount];
|
||||
}
|
||||
|
||||
char* dataTable= new char[recordCount*recordsize];
|
||||
char* dataTable= new char[(recordCount + sqlRecordCount)*recordsize];
|
||||
|
||||
uint32 offset=0;
|
||||
|
||||
for(uint32 y =0;y<recordCount;y++)
|
||||
for(uint32 y =0;y<recordCount;++y)
|
||||
{
|
||||
if(i>=0)
|
||||
{
|
||||
@@ -216,6 +220,7 @@ char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlDataTable = dataTable + offset;
|
||||
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ enum
|
||||
FT_BYTE='b', //uint8
|
||||
FT_SORT='d', //sorted by this field, field is not included
|
||||
FT_IND='n', //the same,but parsed to data
|
||||
FT_LOGIC='l' //Logical (boolean)
|
||||
FT_LOGIC='l', //Logical (boolean)
|
||||
FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc
|
||||
FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc
|
||||
};
|
||||
|
||||
class DBCFileLoader
|
||||
@@ -88,10 +90,11 @@ class DBCFileLoader
|
||||
/// Get begin iterator over records
|
||||
|
||||
uint32 GetNumRows() const { return recordCount;}
|
||||
uint32 GetRowSize() const { return recordSize;}
|
||||
uint32 GetCols() const { return fieldCount; }
|
||||
uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; }
|
||||
bool IsLoaded() {return (data!=NULL);}
|
||||
char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable);
|
||||
char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable);
|
||||
char* AutoProduceStrings(const char* fmt, char* dataTable);
|
||||
static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL);
|
||||
private:
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#define DBCSTORE_H
|
||||
|
||||
#include "DBCFileLoader.h"
|
||||
#include "Log.h"
|
||||
struct SqlDbc;
|
||||
|
||||
template<class T>
|
||||
class DBCStorage
|
||||
@@ -34,17 +36,152 @@ class DBCStorage
|
||||
char const* GetFormat() const { return fmt; }
|
||||
uint32 GetFieldCount() const { return fieldCount; }
|
||||
|
||||
bool Load(char const* fn)
|
||||
bool Load(char const* fn, SqlDbc * sql)
|
||||
{
|
||||
DBCFileLoader dbc;
|
||||
// Check if load was sucessful, only then continue
|
||||
if(!dbc.Load(fn, fmt))
|
||||
return false;
|
||||
|
||||
uint32 sqlRecordCount = 0;
|
||||
uint32 sqlHighestIndex = 0;
|
||||
Field *fields = NULL;
|
||||
QueryResult *result = NULL;
|
||||
// Load data from sql
|
||||
if (sql)
|
||||
{
|
||||
std::string query = "SELECT * FROM `" + sql->sqlTableName;
|
||||
if (sql->indexPos >= 0)
|
||||
query +="` ORDER BY + `" + *sql->indexName + "` DESC";
|
||||
query += ";";
|
||||
|
||||
result = WorldDatabase.Query(query.c_str());
|
||||
if (result)
|
||||
{
|
||||
sqlRecordCount = result->GetRowCount();
|
||||
if (sql->indexPos >= 0)
|
||||
{
|
||||
fields = result->Fetch();
|
||||
sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32();
|
||||
}
|
||||
// Check if sql index pos is valid
|
||||
if (int32(result->GetFieldCount()-1) < sql->sqlIndexPos)
|
||||
{
|
||||
sLog.outError("Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
char * sqlDataTable;
|
||||
fieldCount = dbc.GetCols();
|
||||
m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable);
|
||||
m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable, sqlRecordCount, sqlHighestIndex, sqlDataTable);
|
||||
|
||||
m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable));
|
||||
|
||||
// Insert sql data into arrays
|
||||
if (result)
|
||||
{
|
||||
if (indexTable)
|
||||
{
|
||||
uint32 offset = 0;
|
||||
uint32 rowIndex = dbc.GetNumRows();
|
||||
do
|
||||
{
|
||||
if (!fields)
|
||||
fields = result->Fetch();
|
||||
|
||||
if(sql->indexPos >= 0)
|
||||
{
|
||||
uint32 id = fields[sql->sqlIndexPos].GetUInt32();
|
||||
if (indexTable[id])
|
||||
{
|
||||
sLog.outError("Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str());
|
||||
return false;
|
||||
}
|
||||
indexTable[id]=(T*)&sqlDataTable[offset];
|
||||
}
|
||||
else
|
||||
indexTable[rowIndex]=(T*)&sqlDataTable[offset];
|
||||
uint32 columnNumber = 0;
|
||||
uint32 sqlColumnNumber = 0;
|
||||
|
||||
for(;columnNumber < sql->formatString->size();++columnNumber)
|
||||
{
|
||||
if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT)
|
||||
{
|
||||
switch(fmt[columnNumber])
|
||||
{
|
||||
case FT_FLOAT:
|
||||
*((float*)(&sqlDataTable[offset]))= 0.0f;
|
||||
offset+=4;
|
||||
break;
|
||||
case FT_IND:
|
||||
case FT_INT:
|
||||
*((uint32*)(&sqlDataTable[offset]))=uint32(0);
|
||||
offset+=4;
|
||||
break;
|
||||
case FT_BYTE:
|
||||
*((uint8*)(&sqlDataTable[offset]))=uint8(0);
|
||||
offset+=1;
|
||||
break;
|
||||
case FT_STRING:
|
||||
// Beginning of the pool - empty string
|
||||
*((char**)(&sqlDataTable[offset]))=m_stringPoolList.back();
|
||||
offset+=sizeof(char*);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT)
|
||||
{
|
||||
bool validSqlColumn = true;
|
||||
switch(fmt[columnNumber])
|
||||
{
|
||||
case FT_FLOAT:
|
||||
*((float*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetFloat();
|
||||
offset+=4;
|
||||
break;
|
||||
case FT_IND:
|
||||
case FT_INT:
|
||||
*((uint32*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt32();
|
||||
offset+=4;
|
||||
break;
|
||||
case FT_BYTE:
|
||||
*((uint8*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt8();
|
||||
offset+=1;
|
||||
break;
|
||||
case FT_STRING:
|
||||
sLog.outError("Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
|
||||
delete result;
|
||||
return false;
|
||||
case FT_SORT:
|
||||
break;
|
||||
default:
|
||||
validSqlColumn = false;
|
||||
}
|
||||
if (validSqlColumn)
|
||||
sqlColumnNumber++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
|
||||
delete result;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (sqlColumnNumber != (result->GetFieldCount()-1))
|
||||
{
|
||||
sLog.outError("SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str());
|
||||
delete result;
|
||||
return false;
|
||||
}
|
||||
|
||||
fields = NULL;
|
||||
++rowIndex;
|
||||
}while (result->NextRow());
|
||||
}
|
||||
delete result;
|
||||
}
|
||||
|
||||
// error in dbc file at loading if NULL
|
||||
return indexTable!=NULL;
|
||||
}
|
||||
@@ -84,11 +221,49 @@ class DBCStorage
|
||||
}
|
||||
|
||||
private:
|
||||
char const* fmt;
|
||||
uint32 nCount;
|
||||
uint32 fieldCount;
|
||||
char const* fmt;
|
||||
T** indexTable;
|
||||
T* m_dataTable;
|
||||
StringPoolList m_stringPoolList;
|
||||
};
|
||||
|
||||
struct SqlDbc
|
||||
{
|
||||
const std::string * formatString;
|
||||
const std::string * indexName;
|
||||
std::string sqlTableName;
|
||||
int32 indexPos;
|
||||
int32 sqlIndexPos;
|
||||
SqlDbc(const std::string * _filename, const std::string * _format, const std::string * _idname, const char * fmt)
|
||||
:formatString(_format),sqlIndexPos(0), indexName (_idname)
|
||||
{
|
||||
// Convert dbc file name to sql table name
|
||||
sqlTableName = *_filename;
|
||||
for (uint32 i = 0;i< sqlTableName.size();++i)
|
||||
{
|
||||
if (isalpha(sqlTableName[i]))
|
||||
sqlTableName[i] = tolower(sqlTableName[i]);
|
||||
else if (sqlTableName[i] == '.')
|
||||
sqlTableName[i] = '_';
|
||||
}
|
||||
|
||||
// Get sql index position
|
||||
DBCFileLoader::GetFormatRecordSize(fmt, &indexPos);
|
||||
if (indexPos>=0)
|
||||
{
|
||||
for(uint32 x=0;x < formatString->size();x++)
|
||||
{
|
||||
// Count only fields present in sql
|
||||
if ((*formatString)[x] == FT_SQL_PRESENT)
|
||||
{
|
||||
if (x == indexPos)
|
||||
break;
|
||||
++sqlIndexPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -65,6 +65,17 @@ class Field
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
uint64 GetInt64() const
|
||||
{
|
||||
if(mValue)
|
||||
{
|
||||
int64 value;
|
||||
sscanf(mValue,SI64FMTD,&value);
|
||||
return value;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetType(enum DataTypes type) { mType = type; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user