diff --git a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe index a1e982f0c..213705f6c 100644 Binary files a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe and b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe differ diff --git a/contrib/vmap_extractor_v2/stormlib/StormPortMac.cpp b/contrib/vmap_extractor_v2/stormlib/StormPortMac.cpp index 26f67872a..2477333ae 100644 --- a/contrib/vmap_extractor_v2/stormlib/StormPortMac.cpp +++ b/contrib/vmap_extractor_v2/stormlib/StormPortMac.cpp @@ -15,7 +15,7 @@ * ********************************************************************/ -#ifndef _WIN32 || _WIN64 +#ifndef _WIN32 #include "StormPort.h" #include "StormLib.h" diff --git a/contrib/vmap_extractor_v2/vmapextract/adtfile.cpp b/contrib/vmap_extractor_v2/vmapextract/adtfile.cpp index 2de3aa751..cd9ba7219 100644 --- a/contrib/vmap_extractor_v2/vmapextract/adtfile.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/adtfile.cpp @@ -1,5 +1,6 @@ #include "adtfile.h" +#include char * GetPlainName(char * FileName) { char * szTemp; @@ -22,6 +23,7 @@ void fixnamen(char *name, size_t len) } } } + void fixname2(char *name, size_t len) { for (size_t i=0; i= 4 ? path.substr(path.size()-4,4) : ""; + std::transform( ext3.begin(), ext3.end(), ext3.begin(), ::tolower ); + if(ext3 == ".mdx") + { + // replace .mdx -> .m2 + path.erase(path.length()-2,2); + path.append("2"); + } + // >= 3.1.0 ADT MMDX section store filename.m2 filenames for corresponded .m2 file + // nothing do + + char szLocalFile[MAX_PATH]; + sprintf(szLocalFile, ".\\buildings\\%s", s); + FILE * output = fopen(szLocalFile,"rb"); if(!output) { Model * m2 = new Model(path); if(m2->open()) - { - m2->ConvertToVMAPModel((char*)szLocalFile); - } + m2->ConvertToVMAPModel(szLocalFile); delete m2; } else @@ -129,7 +140,7 @@ bool ADTFile::init(char *map_id) char *p=buf; int q = 0; WmoInstansName = new string[size]; - while (p ArchiveSet; -ArchiveSet gOpenArchives; +MPQArchiveSet gOpenArchives; +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx MPQArchive::MPQArchive(const char* filename) { BOOL succ = SFileOpenArchive(filename, 0, 0,&hMPQ); if (succ) - { - MPQArchive*ar = (MPQArchive*)(hMPQ); printf("Opening %s\n", filename); - gOpenArchives.push_back(ar); - succ = true; - } else - { printf("Error!!!Not open archive %s\n", filename); - } } void MPQArchive::close() @@ -27,16 +20,35 @@ void MPQArchive::close() SFileCloseArchive(hMPQ); } +bool MPQArchiveSet::Open( std::vector const& archiveNames ) +{ + for (size_t i=0; i < archiveNames.size(); ++i) + { + MPQArchive mpqarch(archiveNames[i].c_str()); + if(mpqarch.isOpen()) + archives.push_back(mpqarch); + } + + return !archives.empty(); +} + +MPQArchiveSet::~MPQArchiveSet() +{ + // close archives + for (ArchiveSet::iterator ar_itr = archives.begin(); ar_itr != archives.end(); ++ar_itr) + ar_itr->close(); +} + MPQFile::MPQFile(const char* filename): eof(false), buffer(0), pointer(0), size(0) { - for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) + for(ArchiveSet::const_iterator i=gOpenArchives.archives.begin(); i!=gOpenArchives.archives.end();++i) { HANDLE hFile = ""; - MPQArchive*(hMPQ) = *i; + hMPQ = i->hMPQ; BOOL succ = SFileOpenFileEx(hMPQ,filename,0, &hFile); if (succ) { @@ -54,7 +66,7 @@ MPQFile::MPQFile(const char* filename): eof = false; return; - } + } } eof = true; diff --git a/contrib/vmap_extractor_v2/vmapextract/mpq.h b/contrib/vmap_extractor_v2/vmapextract/mpq.h index 8fc885667..0d1d14851 100644 --- a/contrib/vmap_extractor_v2/vmapextract/mpq.h +++ b/contrib/vmap_extractor_v2/vmapextract/mpq.h @@ -17,12 +17,28 @@ typedef unsigned int uint32; class MPQArchive { -public: - HANDLE hMPQ; - MPQArchive(const char* filename); - void close(); + public: + HANDLE hMPQ; + MPQArchive(const char* filename); + void close(); + bool isOpen() const { return hMPQ != 0; } }; +typedef std::vector ArchiveSet; + +class MPQArchiveSet +{ + public: + MPQArchiveSet() {} + ~MPQArchiveSet(); + + bool Open(std::vector const& archiveNames); + + ArchiveSet archives; +}; + +extern MPQArchiveSet gOpenArchives; + class MPQFile { HANDLE hFile; diff --git a/contrib/vmap_extractor_v2/vmapextract/vec3d.h b/contrib/vmap_extractor_v2/vmapextract/vec3d.h index fd966138d..405135521 100644 --- a/contrib/vmap_extractor_v2/vmapextract/vec3d.h +++ b/contrib/vmap_extractor_v2/vmapextract/vec3d.h @@ -118,7 +118,7 @@ class Vec2D { public: float x,y; - + Vec2D(float x0 = 0.0f, float y0 = 0.0f) : x(x0), y(y0) {} Vec2D(const Vec2D& v) : x(v.x), y(v.y) {} diff --git a/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp index 24ca6414c..a96a404f6 100644 --- a/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp @@ -90,6 +90,7 @@ static const char * GetPlainName(const char * szFileName) static void ShowProcessedFile(const char * szFileName) { +/* not truncate file names in output char szLine[80]; size_t nLength = strlen(szFileName); @@ -100,13 +101,14 @@ static void ShowProcessedFile(const char * szFileName) nLength = sizeof(szLine)-1; memcpy(szLine, szFileName, nLength); printf("\r%s\n", szLine); +*/ + printf("\r%s\n", szFileName); } -int ExtractWmo(const std::vector& pArchiveNames) +int ExtractWmo() { char* szListFile = ""; char szLocalFile[MAX_PATH] = ""; - HANDLE hMpq = ""; BOOL bResult = FALSE; //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"}; @@ -114,20 +116,14 @@ int ExtractWmo(const std::vector& pArchiveNames) int nError = ERROR_SUCCESS; if(szListFile == NULL || *szListFile == 0) szListFile = NULL; - //char tmp[1024]; - //for (size_t i=0; i<4; i++) - for (size_t i=0; ihMPQ,"*.wmo*", &wf, szListFile); bResult = TRUE; while(hFind != NULL && bResult == TRUE) @@ -171,10 +167,10 @@ int ExtractWmo(const std::vector& pArchiveNames) { for (int i=0; inGroups; ++i) { - char temp[512]; + char temp[MAX_PATH]; strcpy(temp, wf.cFileName); temp[strlen(wf.cFileName)-4] = 0; - char groupFileName[512]; + char groupFileName[MAX_PATH]; sprintf(groupFileName,"%s_%03d.wmo",temp, i); printf("%s\n",groupFileName); //printf("GroupWmo!\n"); @@ -212,12 +208,6 @@ int ExtractWmo(const std::vector& pArchiveNames) } } - // Close both archives - if(hMpq != NULL) - { - //SFileCloseArchive(hMpq); - } - if(nError == ERROR_SUCCESS) printf("\nExtract wmo complete (No errors)\n"); @@ -533,26 +523,30 @@ int main(int argc, char ** argv) if(nError == ERROR_ALREADY_EXISTS) nError = ERROR_SUCCESS; } - //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - // patch goes first -> fake priority handling - std::vector archives; - //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // prepare archive name list std::vector archiveNames; - fillArchiveNameVector(archiveNames); - for (size_t i=0; iopen(); + if(!dbc->open()) + { + delete dbc; + printf("FATAL ERROR: Map.dbc not found in data file.\n"); + return 1; + } map_count=dbc->getRecordCount (); map_ids=new map_id[map_count]; for(unsigned int x=0;x> 8 +WHERE ct.entry=c.id AND ct.unit_class=0; + +UPDATE creature_template ct +JOIN creature_template_addon ad ON ct.entry=ad.entry +SET ct.unit_class=(ad.bytes0 & 0x0000FF00) >> 8 +WHERE ct.entry=ad.entry AND ct.unit_class=0; + +UPDATE creature_template a1, creature_template a2 SET a1.unit_class=a2.unit_class WHERE a1.unit_class=0 AND a2.unit_class!=0 AND a1.entry=a2.heroic_entry; +UPDATE creature_template a1, creature_template a2 SET a1.unit_class=a2.unit_class WHERE a1.unit_class=0 AND a2.unit_class!=0 AND a2.entry=a1.heroic_entry; diff --git a/sql/updates/7908_02_mangos_creature_addon.sql b/sql/updates/7908_02_mangos_creature_addon.sql new file mode 100644 index 000000000..f72630957 --- /dev/null +++ b/sql/updates/7908_02_mangos_creature_addon.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_7908_01_mangos_creature_template required_7908_02_mangos_creature_addon bit; + +ALTER TABLE creature_addon + DROP COLUMN bytes0; diff --git a/sql/updates/7908_03_mangos_creature_template_addon.sql b/sql/updates/7908_03_mangos_creature_template_addon.sql new file mode 100644 index 000000000..7dcea58fe --- /dev/null +++ b/sql/updates/7908_03_mangos_creature_template_addon.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_7908_02_mangos_creature_addon required_7908_03_mangos_creature_template_addon bit; + +ALTER TABLE creature_template_addon + DROP COLUMN bytes0; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 6e18e6493..acd664849 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -204,6 +204,10 @@ pkgdata_DATA = \ 7902_01_mangos_pool_creature.sql \ 7902_02_mangos_pool_gameobject.sql \ 7903_01_characters_character_pet.sql \ + 7904_01_mangos_creature_template.sql \ + 7908_01_mangos_creature_template.sql \ + 7908_02_mangos_creature_addon.sql \ + 7908_03_mangos_creature_template_addon.sql \ README ## Additional files to include when running 'make dist' @@ -388,4 +392,8 @@ EXTRA_DIST = \ 7902_01_mangos_pool_creature.sql \ 7902_02_mangos_pool_gameobject.sql \ 7903_01_characters_character_pet.sql \ + 7904_01_mangos_creature_template.sql \ + 7908_01_mangos_creature_template.sql \ + 7908_02_mangos_creature_addon.sql \ + 7908_03_mangos_creature_template_addon.sql \ README diff --git a/src/game/CombatHandler.cpp b/src/game/CombatHandler.cpp index 12fedd89a..ddc6748e2 100644 --- a/src/game/CombatHandler.cpp +++ b/src/game/CombatHandler.cpp @@ -81,7 +81,13 @@ void WorldSession::HandleSetSheathedOpcode( WorldPacket & recv_data ) //sLog.outDebug( "WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUIDLow(), sheathed ); - GetPlayer()->SetSheath(sheathed); + if(sheathed >= MAX_SHEATH_STATE) + { + sLog.outError("Unknown sheath state %u ??",sheathed); + return; + } + + GetPlayer()->SetSheath(SheathState(sheathed)); } void WorldSession::SendAttackStop(Unit const* enemy) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index f8eade957..cee3d9c15 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -197,6 +197,12 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data ) SetEntry(Entry); // normal entry always m_creatureInfo = cinfo; // map mode related always + // equal to player Race field, but creature does not have race + SetByteValue(UNIT_FIELD_BYTES_0, 0, 0); + + // known valid are: CLASS_WARRIOR,CLASS_PALADIN,CLASS_ROGUE,CLASS_MAGE + SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class)); + if (cinfo->DisplayID_A == 0 || cinfo->DisplayID_H == 0) // Cancel load if no model defined { sLog.outErrorDb("Creature (Entry: %u) has no model defined for Horde or Alliance in table `creature_template`, can't load. ",Entry); @@ -256,7 +262,7 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) m_regenHealth = GetCreatureInfo()->RegenHealth; // creatures always have melee weapon ready if any - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); + SetSheath(SHEATH_STATE_MELEE); SelectLevel(GetCreatureInfo()); if (team == HORDE) @@ -1204,6 +1210,8 @@ void Creature::SelectLevel(const CreatureInfo *cinfo) SetMaxPower(POWER_MANA, mana); //MAX Mana SetPower(POWER_MANA, mana); + // TODO: set UNIT_FIELD_POWER*, for some creature class case (energy, etc) + SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, health); SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, mana); @@ -1860,9 +1868,6 @@ bool Creature::LoadCreaturesAddon(bool reload) if (cainfo->mount != 0) Mount(cainfo->mount); - if (cainfo->bytes0 != 0) - SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); - if (cainfo->bytes1 != 0) SetUInt32Value(UNIT_FIELD_BYTES_1, cainfo->bytes1); diff --git a/src/game/Creature.h b/src/game/Creature.h index c33da87ba..5f412c208 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -183,8 +183,10 @@ struct CreatureInfo float maxdmg; uint32 dmgschool; uint32 attackpower; + float dmg_multiplier; uint32 baseattacktime; uint32 rangeattacktime; + uint32 unit_class; // enum Classes. Note only 4 classes are known for creatures. uint32 unit_flags; // enum UnitFlags mask values uint32 dynamicflags; uint32 family; // enum CreatureFamily values (optional) @@ -299,7 +301,6 @@ struct CreatureDataAddon { uint32 guidOrEntry; uint32 mount; - uint32 bytes0; uint32 bytes1; uint32 bytes2; uint32 emote; diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 5a1cf5716..bb4b5f139 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -613,7 +613,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above %u. Phase mask cannot be used with phases past %u. CreatureEntry = %d", EventId, MAX_PHASE-1, MAX_PHASE-1, m_creature->GetEntry()); Phase = MAX_PHASE-1; } - else + else Phase = new_phase; break; @@ -783,6 +783,11 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap()); break; } + case ACTION_T_SET_SHEATH: + { + m_creature->SetSheath(SheathState(action.set_sheath.sheath)); + break; + } } } diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index 5f967c51d..b5b98e0ca 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -102,7 +102,7 @@ enum EventAI_ActionType ACTION_T_DIE = 37, // No Params ACTION_T_ZONE_COMBAT_PULSE = 38, // No Params ACTION_T_CALL_FOR_HELP = 39, // Radius - + ACTION_T_SET_SHEATH = 40, // Sheath (0-passive,1-melee,2-ranged) ACTION_T_END, }; @@ -197,69 +197,69 @@ struct CreatureEventAI_Action uint32 modelId; } morph; // ACTION_T_SOUND = 4 - struct + struct { uint32 soundId; } sound; // ACTION_T_EMOTE = 5 - struct + struct { uint32 emoteId; } emote; // ACTION_T_RANDOM_SOUND = 9 - struct + struct { int32 soundId1; // (-1 in any field means no output if randomed that field) int32 soundId2; int32 soundId3; } random_sound; // ACTION_T_RANDOM_EMOTE = 10 - struct + struct { int32 emoteId1; // (-1 in any field means no output if randomed that field) int32 emoteId2; int32 emoteId3; } random_emote; // ACTION_T_CAST = 11 - struct + struct { uint32 spellId; uint32 target; uint32 castFlags; } cast; // ACTION_T_SUMMON = 12 - struct + struct { uint32 creatured; uint32 target; uint32 duration; } summon; // ACTION_T_THREAT_SINGLE_PCT = 13 - struct + struct { int32 percent; uint32 target; } threat_single_pct; // ACTION_T_THREAT_ALL_PCT = 14 - struct + struct { int32 percent; } threat_all_pct; // ACTION_T_QUEST_EVENT = 15 - struct + struct { uint32 questId; uint32 target; } quest_event; // ACTION_T_CAST_EVENT = 16 - struct + struct { uint32 creatureId; uint32 spellId; uint32 target; } cast_event; // ACTION_T_SET_UNIT_FIELD = 17 - struct + struct { uint32 field; uint32 value; @@ -267,94 +267,94 @@ struct CreatureEventAI_Action } set_unit_field; // ACTION_T_SET_UNIT_FLAG = 18, // value provided mask bits that will be set // ACTION_T_REMOVE_UNIT_FLAG = 19, // value provided mask bits that will be clear - struct + struct { uint32 value; uint32 target; } unit_flag; // ACTION_T_AUTO_ATTACK = 20 - struct + struct { uint32 state; // 0 = stop attack, anything else means continue attacking } auto_attack; // ACTION_T_COMBAT_MOVEMENT = 21 - struct + struct { uint32 state; // 0 = stop combat based movement, anything else continue attacking } combat_movement; // ACTION_T_SET_PHASE = 22 - struct + struct { uint32 phase; } set_phase; // ACTION_T_INC_PHASE = 23 - struct + struct { int32 step; } set_inc_phase; // ACTION_T_QUEST_EVENT_ALL = 26 - struct + struct { uint32 questId; } quest_event_all; // ACTION_T_CAST_EVENT_ALL = 27 - struct + struct { uint32 creatureId; uint32 spellId; } cast_event_all; // ACTION_T_REMOVEAURASFROMSPELL = 28 - struct + struct { uint32 target; uint32 spellId; } remove_aura; // ACTION_T_RANGED_MOVEMENT = 29 - struct + struct { uint32 distance; int32 angle; } ranged_movement; // ACTION_T_RANDOM_PHASE = 30 - struct + struct { uint32 phase1; uint32 phase2; uint32 phase3; } random_phase; // ACTION_T_RANDOM_PHASE_RANGE = 31 - struct + struct { uint32 phaseMin; uint32 phaseMax; } random_phase_range; // ACTION_T_SUMMON_ID = 32 - struct + struct { uint32 creatureId; uint32 target; uint32 spawnId; } summon_id; // ACTION_T_KILLED_MONSTER = 33 - struct + struct { uint32 creatureId; uint32 target; } killed_monster; // ACTION_T_SET_INST_DATA = 34 - struct + struct { uint32 field; uint32 value; } set_inst_data; // ACTION_T_SET_INST_DATA64 = 35 - struct + struct { uint32 field; uint32 target; } set_inst_data64; // ACTION_T_UPDATE_TEMPLATE = 36 - struct + struct { uint32 creatureId; uint32 team; @@ -364,6 +364,11 @@ struct CreatureEventAI_Action { uint32 radius; } call_for_help; + // ACTION_T_SET_SHEATH = 40 + struct + { + uint32 sheath; + } set_sheath; // RAW struct { @@ -497,7 +502,7 @@ struct CreatureEventAI_Event } receive_emote; // RAW - struct + struct { uint32 param1; uint32 param2; diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index b3678dad6..5caaa2311 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -641,6 +641,13 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (!sCreatureStorage.LookupEntry(action.update_template.creatureId)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.update_template.creatureId); break; + case ACTION_T_SET_SHEATH: + if (action.set_sheath.sheath >= MAX_SHEATH_STATE) + { + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses wrong sheath state %u.", i, j+1, action.set_sheath.sheath); + action.set_sheath.sheath = SHEATH_STATE_UNARMED; + } + break; case ACTION_T_EVADE: //No Params case ACTION_T_FLEE_FOR_ASSIST: //No Params case ACTION_T_DIE: //No Params diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index b7b04ef5e..18de7f857 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -926,10 +926,10 @@ namespace MaNGOS return false; if(!u->CanAssistTo(i_obj,i_enemy)) return false; - + if(!i_obj->IsWithinDistInMap(u, i_range)) return false; - + if(!i_obj->IsWithinLOSInMap(u)) return false; diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 9c9623268..699cb275b 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -2000,7 +2000,7 @@ bool ChatHandler::HandleTeleNameCommand(const char * args) extractOptFirstArg((char*)args,&nameStr,&teleStr); if(!teleStr) return false; - + Player* target; uint64 target_guid; std::string target_name; diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 3426b6bc3..aa1a392a3 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3170,7 +3170,7 @@ bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) bool ChatHandler::HandleGuildCreateCommand(const char* args) { if(!*args) - return false; + return false; // if not guild name only (in "") then player name Player* target; @@ -3209,7 +3209,7 @@ bool ChatHandler::HandleGuildCreateCommand(const char* args) bool ChatHandler::HandleGuildInviteCommand(const char *args) { if(!*args) - return false; + return false; // if not guild name only (in "") then player name uint64 target_guid; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index ed6656832..707b97061 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -491,6 +491,12 @@ void ObjectMgr::LoadCreatureTemplates() continue; } + if(cInfo->unit_class != heroicInfo->unit_class) + { + sLog.outErrorDb("Creature (Entry: %u, class %u) has different `unit_class` in heroic mode (Entry: %u, class %u).",i, cInfo->unit_class, cInfo->HeroicEntry, heroicInfo->unit_class); + continue; + } + if(cInfo->npcflag != heroicInfo->npcflag) { sLog.outErrorDb("Creature (Entry: %u) has different `npcflag` in heroic mode (Entry: %u).",i,cInfo->HeroicEntry); @@ -552,6 +558,9 @@ void ObjectMgr::LoadCreatureTemplates() if (!minfo) sLog.outErrorDb("Creature (Entry: %u) has non-existing modelId_H (%u)", cInfo->Entry, cInfo->DisplayID_H); + if (cInfo->unit_class && ((1 << (cInfo->unit_class-1)) & CLASSMASK_ALL_CREATURES) == 0) + sLog.outErrorDb("Creature (Entry: %u) has invalid unit_class(%u) for creature_template", cInfo->Entry, cInfo->unit_class); + if(cInfo->dmgschool >= MAX_SPELL_SCHOOL) { sLog.outErrorDb("Creature (Entry: %u) has invalid spell school value (%u) in `dmgschool`",cInfo->Entry,cInfo->dmgschool); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 019f020a5..99e420e20 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -197,7 +197,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool break; case HUNTER_PET: SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + SetSheath(SHEATH_STATE_MELEE); SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); @@ -783,7 +783,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature) if(cinfo->type == CREATURE_TYPE_BEAST) { SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); + SetSheath(SHEATH_STATE_MELEE); SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED)); } @@ -1762,7 +1762,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint3 if(!InitEntry(Entry)) return false; - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + SetSheath(SHEATH_STATE_MELEE); if(getPetType() == MINI_PET) // always non-attackable SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 3a315cbb3..76b6c6409 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -7906,7 +7906,7 @@ void Player::SetVirtualItemSlot( uint8 i, Item* item) } } -void Player::SetSheath( uint32 sheathed ) +void Player::SetSheath( SheathState sheathed ) { switch (sheathed) { @@ -7932,7 +7932,7 @@ void Player::SetSheath( uint32 sheathed ) SetVirtualItemSlot(2,NULL); break; } - SetByteValue(UNIT_FIELD_BYTES_2, 0, sheathed); // this must visualize Sheath changing for other players... + Unit::SetSheath(sheathed); // this must visualize Sheath changing for other players... } uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const diff --git a/src/game/Player.h b/src/game/Player.h index 54e5f8cdb..7d0858dda 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1006,7 +1006,7 @@ class MANGOS_DLL_SPEC Player : public Unit /*********************************************************/ void SetVirtualItemSlot( uint8 i, Item* item); - void SetSheath( uint32 sheathed ); + void SetSheath( SheathState sheathed ); // overwrite Unit version uint8 FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const; uint32 GetItemCount( uint32 item, bool inBankAlso = false, Item* skipItem = NULL ) const; Item* GetItemByGuid( uint64 guid ) const; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 8234a9317..5e6b90b1c 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -89,6 +89,8 @@ enum Classes (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) | \ (1<<(CLASS_DEATH_KNIGHT-1)) ) +#define CLASSMASK_ALL_CREATURES ((1<<(CLASS_WARRIOR-1)) | (1<<(CLASS_PALADIN-1)) | (1<<(CLASS_ROGUE-1)) | (1<<(CLASS_MAGE-1)) ) + #define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) #define PLAYER_MAX_BATTLEGROUND_QUEUES 3 diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 523324a60..74e9446f3 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3222,8 +3222,9 @@ void Aura::HandleModCharm(bool apply, bool Real) CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) { + //does not appear to have relevance. Why code added initially? See note below at !apply //to prevent client crash - m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); + //m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); //just to enable stat window charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); //if charmed two demons the same session, the 2nd gets the 1st one's name @@ -3261,11 +3262,13 @@ void Aura::HandleModCharm(bool apply, bool Real) // restore UNIT_FIELD_BYTES_0 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) { - CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); + //does not appear to have relevance. Why code added initially? Class, gender, powertype should be same. + //db field removed and replaced with better way to set class, restore using this if problems + /*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); if(cainfo && cainfo->bytes0 != 0) m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); else - m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048); + m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/ if(m_target->GetCharmInfo()) m_target->GetCharmInfo()->SetPetNumber(0, true); diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 849f90575..8ca0ee1a8 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -796,18 +796,17 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; - float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f; - - float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; + float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType); float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); + float dmg_multiplier = GetCreatureInfo()->dmg_multiplier; float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); - float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct ; - float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct ; + float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct * dmg_multiplier; + float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct * dmg_multiplier; SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 407314ed7..3883bbfb0 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -10420,7 +10420,7 @@ bool CharmInfo::AddSpellToActionBar(uint32 spell_id, ActiveStates newstate) } } - // or use empty slot in other case + // or use empty slot in other case for(uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) { if (!PetActionBar[i].SpellOrAction && PetActionBar[i].IsActionBarForSpell()) diff --git a/src/game/Unit.h b/src/game/Unit.h index cc7627600..b54c96317 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -191,6 +191,8 @@ enum SheathState SHEATH_STATE_RANGED = 2 // prepared ranged weapon }; +#define MAX_SHEATH_STATE 3 + // byte (1 from 0..3) of UNIT_FIELD_BYTES_2 enum UnitBytes2_Flags { @@ -967,6 +969,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void ApplyAttackTimePercentMod(WeaponAttackType att,float val, bool apply); void ApplyCastTimePercentMod(float val, bool apply); + SheathState GetSheath() const { return SheathState(GetByteValue(UNIT_FIELD_BYTES_2, 0)); } + virtual void SetSheath( SheathState sheathed ) { SetByteValue(UNIT_FIELD_BYTES_2, 0, sheathed); } + // faction template id uint32 getFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } void setFaction(uint32 faction) { SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction ); } diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index 9c552516d..06ffbee9f 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -25,11 +25,11 @@ extern DatabasePostgre WorldDatabase; extern DatabaseMysql WorldDatabase; #endif -const char CreatureInfosrcfmt[]="iiiiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiliiis"; -const char CreatureInfodstfmt[]="iiiiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiliiii"; -const char CreatureDataAddonInfofmt[]="iiiiiiis"; +const char CreatureInfosrcfmt[]="iiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiliiis"; +const char CreatureInfodstfmt[]="iiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiliiii"; +const char CreatureDataAddonInfofmt[]="iiiiiis"; const char CreatureModelfmt[]="iffbi"; -const char CreatureInfoAddonInfofmt[]="iiiiiiis"; +const char CreatureInfoAddonInfofmt[]="iiiiiis"; const char EquipmentInfofmt[]="iiii"; const char GameObjectInfosrcfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiis"; const char GameObjectInfodstfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiii"; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index de1b34343..f19858cdd 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7903" + #define REVISION_NR "7910" #endif // __REVISION_NR_H__