From 9ddb37c6c18672a5bd68b65bce3d5e7c4ad60977 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 18 Mar 2009 10:50:27 +0300 Subject: [PATCH 1/7] [7484] Cast proper triggred spell at spell 27808 tick. --- src/game/SpellAuras.cpp | 9 +++++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index e27374f83..10a6dfe6d 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1484,8 +1484,13 @@ void Aura::TriggerSpell() // case 27746: break; // // Steam Tank Passive // case 27747: break; -// // Frost Blast -// case 27808: break; + // Frost Blast + case 27808: + { + int32 bpDamage = target->GetMaxHealth()*26/100; + caster->CastCustomSpell(target,29879,&bpDamage,NULL,NULL,true,NULL,this); + return; + } // // Detonate Mana // case 27819: break; // // Controller Timer diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b84930cc1..bb7e6d2a1 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 "7483" + #define REVISION_NR "7484" #endif // __REVISION_NR_H__ From 3c819a626932927866f5511b205d3182c9c01cef Mon Sep 17 00:00:00 2001 From: ApoC Date: Wed, 18 Mar 2009 12:06:11 +0100 Subject: [PATCH 2/7] [7485] Added support for PostgreSQL connection using Unix sockets. For using socket connection specify host name as . and port as path to Unix socket directory or . for default path specified in PostgreSQL compile time. Signed-off-by: ApoC --- src/mangosd/mangosd.conf.dist.in | 14 +++++++++----- src/shared/Database/DatabasePostgre.cpp | 9 ++++++--- src/shared/revision_nr.h | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 86c600194..03d14e2cd 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -25,11 +25,15 @@ ConfVersion=2008080101 # WorldDatabaseInfo # CharacterDatabaseInfo # Database connection settings for the world server. -# Default: hostname;port;username;password;database -# .;somenumber;username;password;database - use named pipes at Windows -# Named pipes: mySQL required adding "enable-named-pipe" to [mysqld] section my.ini -# .;/path/to/unix_socket;username;password;database - use Unix sockets at Unix/Linux -# Unix sockets: experimental, not tested +# Default: +# ---MYSQL--- +# hostname;port;username;password;database +# .;somenumber;username;password;database - use named pipes at Windows +# Named pipes: mySQL required adding "enable-named-pipe" to [mysqld] section my.ini +# .;/path/to/unix_socket;username;password;database - use Unix sockets at Unix/Linux +# ---PGSQL--- +# hostname;port;username;password;database +# .;/path/to/unix_socket/DIRECTORY or . for default path;username;password;database - use Unix sockets at Unix/Linux # # MaxPingTime # Settings for maximum database-ping interval (minutes between pings) diff --git a/src/shared/Database/DatabasePostgre.cpp b/src/shared/Database/DatabasePostgre.cpp index a572a8320..e8f713ee9 100644 --- a/src/shared/Database/DatabasePostgre.cpp +++ b/src/shared/Database/DatabasePostgre.cpp @@ -77,14 +77,14 @@ bool DatabasePostgre::Initialize(const char *infoString) Tokens::iterator iter; - std::string host, port_or_socket, user, password, database; + std::string host, port_or_socket_dir, user, password, database; iter = tokens.begin(); if(iter != tokens.end()) host = *iter++; if(iter != tokens.end()) - port_or_socket = *iter++; + port_or_socket_dir = *iter++; if(iter != tokens.end()) user = *iter++; if(iter != tokens.end()) @@ -92,7 +92,10 @@ bool DatabasePostgre::Initialize(const char *infoString) if(iter != tokens.end()) database = *iter++; - mPGconn = PQsetdbLogin(host.c_str(), port_or_socket.c_str(), NULL, NULL, database.c_str(), user.c_str(), password.c_str()); + if (host == ".") + mPGconn = PQsetdbLogin(NULL, port_or_socket_dir == "." ? NULL : port_or_socket_dir.c_str(), NULL, NULL, database.c_str(), user.c_str(), password.c_str()); + else + mPGconn = PQsetdbLogin(host.c_str(), port_or_socket_dir.c_str(), NULL, NULL, database.c_str(), user.c_str(), password.c_str()); /* check to see that the backend connection was successfully made */ if (PQstatus(mPGconn) != CONNECTION_OK) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index bb7e6d2a1..dd78d4e99 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 "7484" + #define REVISION_NR "7485" #endif // __REVISION_NR_H__ From b3490d3b74c697c4d42c9441beff6648c9605550 Mon Sep 17 00:00:00 2001 From: zhenya Date: Wed, 18 Mar 2009 15:40:22 +0300 Subject: [PATCH 3/7] [7486] Fixed possible crash and wrong data in instance state save (or not save). Signed-off-by: VladimirMangos --- src/game/InstanceSaveMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index 200068aa1..f3fb36a6c 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -156,7 +156,7 @@ void InstanceSave::SaveToDB() // save instance data too std::string data; - Map *map = MapManager::Instance().FindMap(m_instanceid, GetMapId()); + Map *map = MapManager::Instance().FindMap(GetMapId(),m_instanceid); if(map) { assert(map->IsDungeon()); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index dd78d4e99..94ab34092 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 "7485" + #define REVISION_NR "7486" #endif // __REVISION_NR_H__ From a7fd57cc74d2caa8f409fce4abf3dd825ca7dbe9 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 18 Mar 2009 15:57:13 +0300 Subject: [PATCH 4/7] [7487] Avoid attempt use InstanceSave data for non-dungeons. Also check map existance and correctness at instance data loading. Removed unused and totally bugged InstanceMap::GetResetTime. --- src/game/Level1.cpp | 2 +- src/game/Map.cpp | 133 ++++++++++++++++++++------------------- src/game/Map.h | 1 - src/game/ObjectMgr.cpp | 9 ++- src/game/Player.cpp | 8 +++ src/shared/revision_nr.h | 2 +- 6 files changed, 85 insertions(+), 70 deletions(-) diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index fd97a033a..db016a1ce 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -511,7 +511,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) // remember current position as entry point for return at bg end teleportation _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); } - else if(cMap->IsDungeon() && cMap->Instanceable()) + else if(cMap->IsDungeon()) { // we have to go to instance, and can go to player only if: // 1) we are in his group (either as leader or as member) diff --git a/src/game/Map.cpp b/src/game/Map.cpp index f7d5ab2d6..ad9bb65d3 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -2137,76 +2137,80 @@ bool InstanceMap::Add(Player *player) if(!CanEnter(player)) return false; - // get or create an instance save for the map - InstanceSave *mapSave = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); - if(!mapSave) + // Dungeon only code + if(IsDungeon()) { - sLog.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId()); - mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), GetSpawnMode(), 0, true); - } - - // check for existing instance binds - InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), GetSpawnMode()); - if(playerBind && playerBind->perm) - { - // cannot enter other instances if bound permanently - if(playerBind->save != mapSave) + // get or create an instance save for the map + InstanceSave *mapSave = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + if(!mapSave) { - sLog.outError("InstanceMap::Add: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put in instance %d,%d,%d,%d,%d,%d", player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); - assert(false); + sLog.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId()); + mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), GetSpawnMode(), 0, true); } - } - else - { - Group *pGroup = player->GetGroup(); - if(pGroup) + + // check for existing instance binds + InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), GetSpawnMode()); + if(playerBind && playerBind->perm) { - // solo saves should be reset when entering a group - InstanceGroupBind *groupBind = pGroup->GetBoundInstance(GetId(), GetSpawnMode()); - if(playerBind) + // cannot enter other instances if bound permanently + if(playerBind->save != mapSave) { - sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); - if(groupBind) sLog.outError("InstanceMap::Add: the group is bound to instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); + sLog.outError("InstanceMap::Add: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put in instance %d,%d,%d,%d,%d,%d", player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); assert(false); } - // bind to the group or keep using the group save - if(!groupBind) - pGroup->BindToInstance(mapSave, false); - else - { - // cannot jump to a different instance without resetting it - if(groupBind->save != mapSave) - { - sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d but he is in group %d which is bound to instance %d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); - if(mapSave) - sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); - else - sLog.outError("MapSave NULL"); - if(groupBind->save) - sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); - else - sLog.outError("GroupBind save NULL"); - assert(false); - } - // if the group/leader is permanently bound to the instance - // players also become permanently bound when they enter - if(groupBind->perm) - { - WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); - data << uint32(0); - player->GetSession()->SendPacket(&data); - player->BindToInstance(mapSave, true); - } - } } else { - // set up a solo bind or continue using it - if(!playerBind) - player->BindToInstance(mapSave, false); + Group *pGroup = player->GetGroup(); + if(pGroup) + { + // solo saves should be reset when entering a group + InstanceGroupBind *groupBind = pGroup->GetBoundInstance(GetId(), GetSpawnMode()); + if(playerBind) + { + sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); + if(groupBind) sLog.outError("InstanceMap::Add: the group is bound to instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); + assert(false); + } + // bind to the group or keep using the group save + if(!groupBind) + pGroup->BindToInstance(mapSave, false); + else + { + // cannot jump to a different instance without resetting it + if(groupBind->save != mapSave) + { + sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d but he is in group %d which is bound to instance %d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); + if(mapSave) + sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); + else + sLog.outError("MapSave NULL"); + if(groupBind->save) + sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); + else + sLog.outError("GroupBind save NULL"); + assert(false); + } + // if the group/leader is permanently bound to the instance + // players also become permanently bound when they enter + if(groupBind->perm) + { + WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); + data << uint32(0); + player->GetSession()->SendPacket(&data); + player->BindToInstance(mapSave, true); + } + } + } else - // cannot jump to a different instance without resetting it - assert(playerBind->save == mapSave); + { + // set up a solo bind or continue using it + if(!playerBind) + player->BindToInstance(mapSave, false); + else + // cannot jump to a different instance without resetting it + assert(playerBind->save == mapSave); + } } } @@ -2327,6 +2331,9 @@ bool InstanceMap::Reset(uint8 method) void InstanceMap::PermBindAllPlayers(Player *player) { + if(!IsDungeon()) + return; + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); if(!save) { @@ -2356,12 +2363,6 @@ void InstanceMap::PermBindAllPlayers(Player *player) } } -time_t InstanceMap::GetResetTime() -{ - InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); - return save ? save->GetDifficulty() : DIFFICULTY_NORMAL; -} - void InstanceMap::UnloadAll(bool pForce) { if(HavePlayers()) @@ -2391,7 +2392,7 @@ void InstanceMap::SetResetSchedule(bool on) // only for normal instances // the reset time is only scheduled when there are no payers inside // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled - if(!HavePlayers() && !IsRaid() && !IsHeroic()) + if(IsDungeon() && !HavePlayers() && !IsRaid() && !IsHeroic()) { InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); if(!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId()); diff --git a/src/game/Map.h b/src/game/Map.h index b40a46a4a..ca027b8ec 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -530,7 +530,6 @@ class MANGOS_DLL_SPEC InstanceMap : public Map uint32 GetScriptId() { return i_script_id; } InstanceData* GetInstanceData() { return i_data; } void PermBindAllPlayers(Player *player); - time_t GetResetTime(); void UnloadAll(bool pForce); bool CanEnter(Player* player); void SendResetWarnings(uint32 timeLeft) const; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 89b38c220..1bcc742c1 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2709,7 +2709,14 @@ void ObjectMgr::LoadGroups() } } - InstanceSave *save = sInstanceSaveManager.AddInstanceSave(fields[1].GetUInt32(), fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true); + MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt32()); + if(!mapEntry || !mapEntry->IsDungeon()) + { + sLog.outErrorDb("Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt32()); + continue; + } + + InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true); group->BindToInstance(save, fields[3].GetBool(), true); }while( result->NextRow() ); delete result; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 2a46a5e2b..277149e5a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -15469,6 +15469,14 @@ void Player::_LoadBoundInstances(QueryResult *result) // so the value read from the DB may be wrong here but only if the InstanceSave is loaded // and in that case it is not used + MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); + if(!mapEntry || !mapEntry->IsDungeon()) + { + sLog.outError("_LoadBoundInstances: player %s(%d) has bind to not existed or not dungeon map %d", GetName(), GetGUIDLow(), mapId); + CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND instance = '%d'", GetGUIDLow(), instanceId); + continue; + } + if(!perm && group) { sLog.outError("_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d,%d,%d", GetName(), GetGUIDLow(), GUID_LOPART(group->GetLeaderGUID()), mapId, instanceId, difficulty); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 94ab34092..f93f50e47 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 "7486" + #define REVISION_NR "7487" #endif // __REVISION_NR_H__ From 071a24562ae490dc46941d6c2d8590dda0964fcc Mon Sep 17 00:00:00 2001 From: arrai Date: Wed, 18 Mar 2009 16:43:48 +0100 Subject: [PATCH 5/7] [7488] Fixed map extractor on platforms with 2GB fopen() limit --- contrib/extractor/System.cpp | 21 +++++++++++++++++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp index 9dffa0048..57dc16b22 100644 --- a/contrib/extractor/System.cpp +++ b/contrib/extractor/System.cpp @@ -16,7 +16,23 @@ #include "loadlib/adt.h" #include "loadlib/wdt.h" +#include +#if defined( __GNUC__ ) + #define _open open + #define _close close + #ifndef O_BINARY + #define O_BINARY 0 + #endif +#else + #include +#endif + +#ifdef O_LARGEFILE + #define OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE) +#else + #define OPEN_FLAGS (O_RDONLY | O_BINARY) +#endif extern ArchiveSet gOpenArchives; typedef struct @@ -81,9 +97,10 @@ void CreateDir( const std::string& Path ) bool FileExists( const char* FileName ) { - if(FILE* fp = fopen( FileName, "rb" )) + int fp = _open(FileName, OPEN_FLAGS); + if(fp != -1) { - fclose(fp); + _close(fp); return true; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index f93f50e47..77ec91445 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 "7487" + #define REVISION_NR "7488" #endif // __REVISION_NR_H__ From 7589bf7263c8134a7b9f9f509c648a79df4cb47a Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 18 Mar 2009 20:48:22 +0300 Subject: [PATCH 6/7] [7489] Update gameobject rotation fields if need. * Fixed update absent in ".gobject turn" command * Propetly set rotation fields for summoned objects * Check rotation/coordinates fields values at server loading --- src/game/GameObject.cpp | 43 ++++++++++++++++++++++----------------- src/game/GameObject.h | 2 ++ src/game/Level2.cpp | 13 ++---------- src/game/ObjectMgr.cpp | 18 ++++++++++++++++ src/game/SpellEffects.cpp | 21 +++++++------------ src/shared/revision_nr.h | 2 +- 6 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 9d206a617..ae9689216 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -121,28 +121,11 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa SetFloatValue(GAMEOBJECT_POS_X, x); SetFloatValue(GAMEOBJECT_POS_Y, y); SetFloatValue(GAMEOBJECT_POS_Z, z); - SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle - - int64 rotation = 0; - - double f_rot1 = sin(ang / 2.0f); - int64 i_rot1 = int64(f_rot1 / atan(pow(2.0f, -20.0f))); - rotation |= (i_rot1 << 43 >> 43) & 0x00000000001FFFFF; - - //float f_rot2 = sin(0.0f / 2.0f); - //int64 i_rot2 = f_rot2 / atan(pow(2.0f, -20.0f)); - //rotation |= (((i_rot2 << 22) >> 32) >> 11) & 0x000003FFFFE00000; - - //float f_rot3 = sin(0.0f / 2.0f); - //int64 i_rot3 = f_rot3 / atan(pow(2.0f, -21.0f)); - //rotation |= (i_rot3 >> 42) & 0x7FFFFC0000000000; - - SetUInt64Value(GAMEOBJECT_ROTATION, rotation); SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0); SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1); - SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); - SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); + + UpdateRotationFields(rotation2,rotation3); // GAMEOBJECT_FACING, GAMEOBJECT_ROTATION, GAMEOBJECT_PARENTROTATION+2/3 SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); @@ -1317,3 +1300,25 @@ const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const return GetName(); } + +void GameObject::UpdateRotationFields(float rotation2 /*=0.0f*/, float rotation3 /*=0.0f*/) +{ + SetFloatValue(GAMEOBJECT_FACING, GetOrientation()); + + int64 rotation = 0; + + double f_rot1 = sin(GetOrientation() / 2.0f); + int64 i_rot1 = int64(f_rot1 / atan(pow(2.0f, -20.0f))); + rotation |= (i_rot1 << 43 >> 43) & 0x00000000001FFFFF; + + SetUInt64Value(GAMEOBJECT_ROTATION, rotation); + + if(rotation2==0.0f && rotation3==0.0f) + { + rotation2 = sin(GetOrientation()/2); + rotation3 = cos(GetOrientation()/2); + } + + SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); + SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); +} diff --git a/src/game/GameObject.h b/src/game/GameObject.h index f34364bc5..a3f729817 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -441,6 +441,8 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; } + void UpdateRotationFields(float rotation2 = 0.0f, float rotation3 = 0.0f); + void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 2654ecb15..e97a50f98 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -1787,17 +1787,11 @@ bool ChatHandler::HandleTurnObjectCommand(const char* args) o = chr->GetOrientation(); } - float rot2 = sin(o/2); - float rot3 = cos(o/2); - Map* map = obj->GetMap(); map->Remove(obj,false); obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); - - obj->SetFloatValue(GAMEOBJECT_FACING, o); - obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2); - obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3); + obj->UpdateRotationFields(); map->Add(obj); @@ -3660,13 +3654,10 @@ bool ChatHandler::HandleGameObjectCommand(const char* args) float o = float(chr->GetOrientation()); Map *map = chr->GetMap(); - float rot2 = sin(o/2); - float rot3 = cos(o/2); - GameObject* pGameObj = new GameObject; uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0, 0, rot2, rot3, 0, 1)) + if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, 1)) { delete pGameObj; return false; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 1bcc742c1..21925cc29 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1075,6 +1075,24 @@ void ObjectMgr::LoadGameobjects() int16 gameEvent = fields[16].GetInt16(); int16 PoolId = fields[17].GetInt16(); + if(data.rotation2 < -1.0f || data.rotation2 > 1.0f) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation2 (%f) value, skip",guid,data.id,data.rotation2 ); + continue; + } + + if(data.rotation3 < -1.0f || data.rotation3 > 1.0f) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation3 (%f) value, skip",guid,data.id,data.rotation3 ); + continue; + } + + if(!MapManager::IsValidMapCoord(data.mapid,data.posX,data.posY,data.posZ,data.orientation)) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid coordinates, skip",guid,data.id ); + continue; + } + if(data.phaseMask==0) { sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id ); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 52a3a50f7..d5ea754dc 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -793,7 +793,7 @@ void Spell::EffectDummy(uint32 i) // create before death for get proper coordinates if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(), creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), - creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) ) + creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1) ) { delete pGameObj; return; @@ -4587,7 +4587,7 @@ void Spell::EffectSummonObjectWild(uint32 i) Map *map = target->GetMap(); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, - m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) { delete pGameObj; return; @@ -4635,7 +4635,7 @@ void Spell::EffectSummonObjectWild(uint32 i) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, - m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) { linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); @@ -5260,7 +5260,7 @@ void Spell::EffectDuel(uint32 i) m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 , m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 , m_caster->GetPositionZ(), - m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1)) + m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1)) { delete pGameObj; return; @@ -5635,9 +5635,6 @@ void Spell::EffectSummonObject(uint32 i) GameObject* pGameObj = new GameObject; - float rot2 = sin(m_caster->GetOrientation()/2); - float rot3 = cos(m_caster->GetOrientation()/2); - float x,y,z; // If dest location if present if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) @@ -5652,7 +5649,7 @@ void Spell::EffectSummonObject(uint32 i) Map *map = m_caster->GetMap(); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, - m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) + m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1)) { delete pGameObj; return; @@ -6242,7 +6239,7 @@ void Spell::EffectTransmitted(uint32 effIndex) GameObject* pGameObj = new GameObject; if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap, - m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) { delete pGameObj; return; @@ -6255,10 +6252,6 @@ void Spell::EffectTransmitted(uint32 effIndex) case GAMEOBJECT_TYPE_FISHINGNODE: { m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID()); - // Orientation3 - pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 ); - // Orientation4 - pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 ); m_caster->AddGameObject(pGameObj); // will removed at spell cancel // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo)) @@ -6313,7 +6306,7 @@ void Spell::EffectTransmitted(uint32 effIndex) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, - m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) { linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 77ec91445..731f51e90 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 "7488" + #define REVISION_NR "7489" #endif // __REVISION_NR_H__ From 82281611978eb6446dfc849aa3a3eb922051b544 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 19 Mar 2009 00:18:48 +0300 Subject: [PATCH 7/7] [7490] Implement expected multiply summon case support with proper duration for EffectSummonDemon --- src/game/SpellEffects.cpp | 59 +++++++++++++++++++++++++++++---------- src/shared/revision_nr.h | 2 +- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index d5ea754dc..e0edc0812 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -6375,26 +6375,55 @@ void Spell::EffectSkill(uint32 /*i*/) void Spell::EffectSummonDemon(uint32 i) { - float px = m_targets.m_destX; - float py = m_targets.m_destY; - float pz = m_targets.m_destZ; + // select center of summon position + float center_x = m_targets.m_destX; + float center_y = m_targets.m_destY; + float center_z = m_targets.m_destZ; - Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000); - if (!Charmed) - return; + float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); - // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster? - Charmed->SetLevel(m_caster->getLevel()); + int32 amount = damage > 0 ? damage : 1; - // TODO: Add damage/mana/hp according to level - - if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon + for(int32 count = 0; count < amount; ++count) { - // Enslave demon effect, without mana cost and cooldown - m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved + float px, py, pz; + // If dest location if present + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + // Summon 1 unit in dest location + if (count == 0) + { + px = m_targets.m_destX; + py = m_targets.m_destY; + pz = m_targets.m_destZ; + } + // Summon in random point all other units if location present + else + m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz); + } + // Summon if dest location not present near caster + else + m_caster->GetClosePoint(px,py,pz,3.0f); - // Inferno effect - Charmed->CastSpell(Charmed, 22703, true, 0); + int32 duration = GetSpellDuration(m_spellInfo); + + Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration); + if (!Charmed) // something fatal, not attempt more + return; + + // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster? + Charmed->SetLevel(m_caster->getLevel()); + + // TODO: Add damage/mana/hp according to level + + if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon + { + // Enslave demon effect, without mana cost and cooldown + m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved + + // Inferno effect + Charmed->CastSpell(Charmed, 22703, true, 0); + } } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 731f51e90..016a30ddf 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 "7489" + #define REVISION_NR "7490" #endif // __REVISION_NR_H__