/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "StdAfx.h"
/** Table formats converted to strings
*/
const char * gItemPrototypeFormat = "uuuussssuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuffuffuffuffuffuuuuuuuuuufuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuusuuuuuuuuuuuuuuuuuuuuuuuuuuu";
const char * gCreatureNameFormat = "ussuuuuuuuffcc";
const char * gGameObjectNameFormat = "uuusuuuuuuuuuuuuuuuuuuuuuuuu";
const char * gCreatureProtoFormat = "uuuuuuufuuffuffuuuuuuuuuuuuuuuuuuffsuuuu";
const char * gAreaTriggerFormat = "uuuusffffuu";
const char * gItemPageFormat = "usu";
const char * gNpcTextFormat = "ufssuuuuuuufssuuuuuuufssuuuuuuufssuuuuuuufssuuuuuuufssuuuuuuufssuuuuuuufssuuuuuuu";
const char * gQuestFormat = "uuuuuuuuuuuuuuuuuussssssssssuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu";
const char * gSpellExtraFormat = "uuuu";
const char * gGraveyardFormat = "uffffuuuux";
const char * gTeleportCoordFormat = "uxufffx";
const char * gPvPAreaFormat = "ush";
const char * gFishingFormat = "uuu";
const char * gWorldMapInfoFormat = "uuuuufffusuuuuu";
const char * gZoneGuardsFormat = "uuu";
/** SQLStorage symbols
*/
SERVER_DECL SQLStorage > ItemPrototypeStorage;
SERVER_DECL SQLStorage > CreatureNameStorage;
SERVER_DECL SQLStorage > GameObjectNameStorage;
SERVER_DECL SQLStorage > CreatureProtoStorage;
SERVER_DECL SQLStorage > AreaTriggerStorage;
SERVER_DECL SQLStorage > ItemPageStorage;
SERVER_DECL SQLStorage > QuestStorage;
SERVER_DECL SQLStorage > NpcTextStorage;
SERVER_DECL SQLStorage > SpellExtraStorage;
SERVER_DECL SQLStorage > GraveyardStorage;
SERVER_DECL SQLStorage > TeleportCoordStorage;
SERVER_DECL SQLStorage > FishingZoneStorage;
SERVER_DECL SQLStorage > WorldMapInfoStorage;
SERVER_DECL SQLStorage > ZoneGuardStorage;
void ObjectMgr::LoadExtraCreatureProtoStuff()
{
{
StorageContainerIterator * itr = CreatureProtoStorage.MakeIterator();
CreatureProto * cn;
while(!itr->AtEnd())
{
cn = itr->Get();
string auras = itr->Get()->aura_string;
vector aurs = StrSplit(auras, " ");
for(vector::iterator it = aurs.begin(); it != aurs.end(); ++it)
{
uint32 id = atol((*it).c_str());
if(id)
itr->Get()->start_auras.insert( id );
}
if(!itr->Get()->MinHealth)
itr->Get()->MinHealth = 1;
if(!itr->Get()->MaxHealth)
itr->Get()->MaxHealth = 1;
cn->m_canFlee = cn->m_canRangedAttack = cn->m_canCallForHelp = false;
cn->m_fleeHealth = 0.0f;
// please.... m_fleeDuration is a uint32...
//cn->m_fleeDuration = 0.0f;
cn->m_fleeDuration = 0;
if(!itr->Inc())
break;
}
itr->Destruct();
}
{
StorageContainerIterator * itr = CreatureNameStorage.MakeIterator();
CreatureInfo * ci;
while(!itr->AtEnd())
{
ci = itr->Get();
ci->lowercase_name = string(ci->Name);
for(uint32 j = 0; j < ci->lowercase_name.length(); ++j)
ci->lowercase_name[j] = tolower(ci->lowercase_name[j]); // Darvaleo 2008/08/15 - Copied lowercase conversion logic from ItemPrototype task
if(!itr->Inc())
break;
}
itr->Destruct();
}
// Load AI Agents
QueryResult * result = WorldDatabase.Query( "SELECT * FROM ai_agents" );
CreatureProto * cn;
if( !result )
return;
AI_Spell *sp;
uint32 entry;
do
{
Field *fields = result->Fetch();
entry = fields[0].GetUInt32();
cn = CreatureProtoStorage.LookupEntry(entry);
if(!cn)
continue;
sp = new AI_Spell;
sp->entryId = fields[0].GetUInt32();
sp->agent = fields[1].GetUInt16();
sp->procChance = fields[3].GetUInt32();
//sp->procCountDB = fields[4].GetUInt32();
sp->spell = ((FastIndexedDataStore*)SpellStore::getSingletonPtr())->LookupEntryForced(fields[5].GetUInt32());
sp->spellType = fields[6].GetUInt32();
sp->spelltargetType = fields[7].GetUInt32();
sp->cooldown = fields[8].GetFloat();
sp->floatMisc1 = fields[9].GetFloat();
/* if (!sp->procCountDB)
sp->procCount = uint32(-1);
else sp->procCount = sp->procCountDB;*/
sp->Misc2 = fields[10].GetUInt32();
if(sp->agent == AGENT_SPELL)
{
if(!sp->spell)
{
//printf("SpellId %u in ai_agent for %u is invalid.\n", (unsigned int)fields[5].GetUInt32(), (unsigned int)sp->entryId);
delete sp;
continue;
}
if(sp->spell->Effect[0] == SPELL_EFFECT_LEARN_SPELL || sp->spell->Effect[1] == SPELL_EFFECT_LEARN_SPELL ||
sp->spell->Effect[2] == SPELL_EFFECT_LEARN_SPELL)
{
//printf("Teaching spell %u in ai_agent for %u\n", (unsigned int)fields[5].GetUInt32(), (unsigned int)sp->entryId);
delete sp;
continue;
}
sp->minrange = GetMinRange(sSpellRange.LookupEntry(sp->spell->rangeIndex));
sp->maxrange = GetMaxRange(sSpellRange.LookupEntry(sp->spell->rangeIndex));
//omg the poor darling has no clue about making ai_agents
if(sp->cooldown==-1)
{
//now this will not be exact cooldown but maybe a bigger one to not make him spam spells to often
int cooldown;
SpellDuration *sd=sSpellDuration.LookupEntry(sp->spell->DurationIndex);
int Dur=0;
int Casttime=0;//most of the time 0
int RecoveryTime=sp->spell->RecoveryTime;
if(sp->spell->DurationIndex)
Dur =::GetDuration(sd);
Casttime=GetCastTime(sCastTime.LookupEntry(sp->spell->CastingTimeIndex));
cooldown=Dur+Casttime+RecoveryTime;
if(cooldown<0)
sp->cooldown=0x00FFFFFF;//huge value that should not loop while adding some timestamp to it
else sp->cooldown=cooldown;
}
/*
//now apply the morron filter
if(sp->procChance==0)
{
//printf("SpellId %u in ai_agent for %u is invalid.\n", (unsigned int)fields[5].GetUInt32(), (unsigned int)sp->entryId);
delete sp;
continue;
}
if(sp->spellType==0)
{
//right now only these 2 are used
if(IsBeneficSpell(sp->spell))
sp->spellType==STYPE_HEAL;
else sp->spellType==STYPE_BUFF;
}
if(sp->spelltargetType==0)
sp->spelltargetType = RecommandAISpellTargetType(sp->spell);
*/
}
if(sp->agent == AGENT_RANGED)
{
cn->m_canRangedAttack = true;
delete sp;
}
else if(sp->agent == AGENT_FLEE)
{
cn->m_canFlee = true;
if(sp->floatMisc1)
cn->m_canFlee = sp->floatMisc1;
else
cn->m_fleeHealth = 0.2f;
if(sp->Misc2)
cn->m_fleeDuration = sp->Misc2;
else
cn->m_fleeDuration = 10000;
delete sp;
}
else if(sp->agent == AGENT_CALLFORHELP)
{
cn->m_canCallForHelp = true;
if(sp->floatMisc1)
cn->m_callForHelpHealth = 0.2f;
delete sp;
}
else
{
cn->spells.push_back(sp);
}
} while( result->NextRow() );
delete result;
}
void ObjectMgr::LoadExtraItemStuff()
{
StorageContainerIterator * itr = ItemPrototypeStorage.MakeIterator();
ItemPrototype * pItemPrototype;
while(!itr->AtEnd())
{
pItemPrototype = itr->Get();
if(pItemPrototype->ItemSet > 0)
{
ItemSetContentMap::iterator itr = mItemSets.find(pItemPrototype->ItemSet);
std::list* l;
if(itr == mItemSets.end())
{
l = new std::list;
mItemSets.insert( ItemSetContentMap::value_type( pItemPrototype->ItemSet, l) );
} else {
l = itr->second;
}
l->push_back(pItemPrototype);
}
// lowercase name, used for searches
pItemPrototype->lowercase_name = pItemPrototype->Name1;
for(uint32 j = 0; j < pItemPrototype->lowercase_name.length(); ++j)
pItemPrototype->lowercase_name[j] = tolower(pItemPrototype->lowercase_name[j]);
if(!itr->Inc())
break;
}
itr->Destruct();
}
#define make_task(storage, itype, storagetype, tablename, format) tl.AddTask( new Task( \
new CallbackP2< SQLStorage< itype, storagetype< itype > >, const char *, const char *> \
(&storage, &SQLStorage< itype, storagetype< itype > >::Load, tablename, format) ) )
void Storage_FillTaskList(TaskList & tl)
{
make_task(ItemPrototypeStorage, ItemPrototype, ArrayStorageContainer, "items", gItemPrototypeFormat);
make_task(CreatureNameStorage, CreatureInfo, HashMapStorageContainer, "creature_names", gCreatureNameFormat);
make_task(GameObjectNameStorage, GameObjectInfo, HashMapStorageContainer, "gameobject_names", gGameObjectNameFormat);
make_task(CreatureProtoStorage, CreatureProto, HashMapStorageContainer, "creature_proto", gCreatureProtoFormat);
make_task(AreaTriggerStorage, AreaTrigger, HashMapStorageContainer, "areatriggers", gAreaTriggerFormat);
make_task(ItemPageStorage, ItemPage, HashMapStorageContainer, "itempages", gItemPageFormat);
make_task(QuestStorage, Quest, HashMapStorageContainer, "quests", gQuestFormat);
make_task(SpellExtraStorage, SpellExtraInfo, HashMapStorageContainer, "spellextra", gSpellExtraFormat);
make_task(GraveyardStorage, GraveyardTeleport, HashMapStorageContainer, "graveyards", gGraveyardFormat);
make_task(TeleportCoordStorage, TeleportCoords, HashMapStorageContainer, "teleport_coords", gTeleportCoordFormat);
make_task(FishingZoneStorage, FishingZoneEntry, HashMapStorageContainer, "fishing", gFishingFormat);
make_task(NpcTextStorage, GossipText, HashMapStorageContainer, "npc_text", gNpcTextFormat);
make_task(WorldMapInfoStorage, MapInfo, ArrayStorageContainer, "worldmap_info", gWorldMapInfoFormat);
make_task(ZoneGuardStorage, ZoneGuardEntry, HashMapStorageContainer, "zoneguards", gZoneGuardsFormat);
}
void Storage_Cleanup()
{
{
StorageContainerIterator * itr = CreatureProtoStorage.MakeIterator();
CreatureProto * p;
while(!itr->AtEnd())
{
p = itr->Get();
for(list::iterator it = p->spells.begin(); it != p->spells.end(); ++it)
delete (*it);
p->spells.clear();
p->start_auras.clear();
if(!itr->Inc())
break;
}
itr->Destruct();
}
ItemPrototypeStorage.Cleanup();
CreatureNameStorage.Cleanup();
GameObjectNameStorage.Cleanup();
CreatureProtoStorage.Cleanup();
AreaTriggerStorage.Cleanup();
ItemPageStorage.Cleanup();
QuestStorage.Cleanup();
SpellExtraStorage.Cleanup();
GraveyardStorage.Cleanup();
TeleportCoordStorage.Cleanup();
FishingZoneStorage.Cleanup();
NpcTextStorage.Cleanup();
WorldMapInfoStorage.Cleanup();
ZoneGuardStorage.Cleanup();
}
bool Storage_ReloadTable(const char * TableName)
{
// bur: mah god this is ugly :P
if(!stricmp(TableName, "items")) // Items
ItemPrototypeStorage.Reload();
else if(!stricmp(TableName, "creature_proto")) // Creature Proto
CreatureProtoStorage.Reload();
else if(!stricmp(TableName, "creature_names")) // Creature Names
CreatureNameStorage.Reload();
else if(!stricmp(TableName, "gameobject_names")) // GO Names
GameObjectNameStorage.Reload();
else if(!stricmp(TableName, "areatriggers")) // Areatriggers
AreaTriggerStorage.Reload();
else if(!stricmp(TableName, "itempages")) // Item Pages
ItemPageStorage.Reload();
else if(!stricmp(TableName, "spellextra")) // Spell Extra Info
SpellExtraStorage.Reload();
else if(!stricmp(TableName, "quests")) // Quests
QuestStorage.Reload();
else if(!stricmp(TableName, "npc_text")) // NPC Text Storage
NpcTextStorage.Reload();
else if(!stricmp(TableName, "fishing")) // Fishing Zones
FishingZoneStorage.Reload();
else if(!stricmp(TableName, "teleport_coords")) // Teleport coords
TeleportCoordStorage.Reload();
else if(!stricmp(TableName, "graveyards")) // Graveyards
TeleportCoordStorage.Reload();
else if(!stricmp(TableName, "worldmap_info")) // WorldMapInfo
WorldMapInfoStorage.Reload();
else if(!stricmp(TableName, "zoneguards"))
ZoneGuardStorage.Reload();
else
return false;
return true;
}