diff --git a/src/Client/DefScriptInterface.cpp b/src/Client/DefScriptInterface.cpp index d517132..ab02421 100644 --- a/src/Client/DefScriptInterface.cpp +++ b/src/Client/DefScriptInterface.cpp @@ -1016,7 +1016,10 @@ DefReturnResult DefScriptPackage::SCGui(CmdSet &Set) // TODO: not sure if this piece of code will work as intended, needs some testing if(ins->GetWSession() && ins->GetWSession()->InWorld()) + { ins->GetGUI()->SetSceneState(SCENESTATE_WORLD); + ins->GetWSession()->objmgr.ReNotifyGUI(); + } else ins->GetGUI()->SetSceneState(SCENESTATE_GUISTART); diff --git a/src/Client/GUI/DrawObjMgr.cpp b/src/Client/GUI/DrawObjMgr.cpp index 925576f..05cce72 100644 --- a/src/Client/GUI/DrawObjMgr.cpp +++ b/src/Client/GUI/DrawObjMgr.cpp @@ -46,6 +46,7 @@ void DrawObjMgr::Update(void) while(_add.size()) { std::pair p = _add.next(); + DEBUG(logdebug("DrawObjMgr: adding DrawObj 0x%X guid "I64FMT" to main storage",p.second,p.first)); _storage[p.first] = p.second; } @@ -55,10 +56,16 @@ void DrawObjMgr::Update(void) uint64 guid = _del.next(); if(_storage.find(guid) != _storage.end()) { + DrawObject *o = _storage[guid]; + DEBUG(logdebug("DrawObjMgr: removing DrawObj 0x%X guid "I64FMT" from main storage",o,guid)); _storage.erase(guid); delete o; } + else + { + DEBUG(logdebug("DrawObjMgr: ERROR: removable DrawObject "I64FMT" not exising",guid)); + } } // now draw everything diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index d4bf407..f25b33f 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -226,7 +226,7 @@ void PseuGUI::NotifyObjectDeletion(uint64 guid) // called from ObjMgr::Add(Object*) void PseuGUI::NotifyObjectCreation(Object *o) { - DrawObject *d = new DrawObject(_smgr,o); + DrawObject *d = new DrawObject(_device,o); domgr.Add(o->GetGUID(),d); } diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index e338aa9..a02bdff 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -30,6 +30,16 @@ enum DriverIDs DIRECTX9 = 5, }; +#define MOUSE_SENSIVITY 0.5f +#define ANGLE_STEP (M_PI/180.0f) +#define DEG_TO_RAD(x) ((x)*ANGLE_STEP) +#define RAD_TO_DEG(x) ((x)/ANGLE_STEP) +#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) ) +#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) ) + +#define COORD_SCALE_VALUE_X 0.336f +#define COORD_SCALE_VALUE_Y 0.2f + class PseuGUIRunnable : public ZThread::Runnable { public: diff --git a/src/Client/GUI/SceneWorld.cpp b/src/Client/GUI/SceneWorld.cpp index 4b5bbce..dcb7c60 100644 --- a/src/Client/GUI/SceneWorld.cpp +++ b/src/Client/GUI/SceneWorld.cpp @@ -12,18 +12,6 @@ #include "WorldSession.h" #include "World.h" -#define MOUSE_SENSIVITY 0.5f -#define ANGLE_STEP (M_PI/180) -#define DEG_TO_RAD(x) ((x)*ANGLE_STEP) -#define RAD_TO_DEG(x) ((x)/ANGLE_STEP) -#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) ) -#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) ) - -#define COORD_SCALE_VALUE_X 0.336f -#define COORD_SCALE_VALUE_Y 0.2f - - - SceneWorld::SceneWorld(PseuGUI *g) : Scene(g) { DEBUG(logdebug("SceneWorld: Initializing...")); @@ -360,8 +348,8 @@ void SceneWorld::SetWorldPosition(WorldPosition wp) cam.Z = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE); float heading = RAD_TO_DEG(((M_PI*3.0f)/2.0f) - wp.o); float heading_diff = camera->getHeading() - heading; - logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading); - camera->turnLeft(heading_diff); + //logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading); + //camera->turnLeft(heading_diff); // TODO: // - correct the above formulas diff --git a/src/Client/World/DynamicObject.cpp b/src/Client/World/DynamicObject.cpp index 5a6ba8d..5a77498 100644 --- a/src/Client/World/DynamicObject.cpp +++ b/src/Client/World/DynamicObject.cpp @@ -1,6 +1,6 @@ #include "DynamicObject.h" -DynamicObject::DynamicObject() +DynamicObject::DynamicObject() : WorldObject() { _uint32values=NULL; _type=TYPE_DYNAMICOBJECT; diff --git a/src/Client/World/GameObject.cpp b/src/Client/World/GameObject.cpp index 20e2ce8..e25a3a1 100644 --- a/src/Client/World/GameObject.cpp +++ b/src/Client/World/GameObject.cpp @@ -1,6 +1,6 @@ #include "GameObject.h" -GameObject::GameObject() +GameObject::GameObject() : WorldObject() { _uint32values=NULL; _type=TYPE_GAMEOBJECT; diff --git a/src/Client/World/Item.cpp b/src/Client/World/Item.cpp index 8c20de5..e56216a 100644 --- a/src/Client/World/Item.cpp +++ b/src/Client/World/Item.cpp @@ -114,6 +114,7 @@ void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket) Item::Item() { + _depleted = false; _type |= TYPE_ITEM; _typeid = TYPEID_ITEM; diff --git a/src/Client/World/ObjMgr.cpp b/src/Client/World/ObjMgr.cpp index 4539382..57a5c28 100644 --- a/src/Client/World/ObjMgr.cpp +++ b/src/Client/World/ObjMgr.cpp @@ -32,24 +32,29 @@ void ObjMgr::RemoveAll(void) } while(_obj.size()) { - Remove(_obj.begin()->first); + Remove(_obj.begin()->first, true); } } -void ObjMgr::Remove(uint64 guid) +void ObjMgr::Remove(uint64 guid, bool del) { - Object *o = GetObj(guid); + Object *o = GetObj(guid, true); // here get also depleted objs and delete if necessary if(o) { + o->_SetDepleted(); PseuGUI *gui = _instance->GetGUI(); if(gui) gui->NotifyObjectDeletion(guid); // we have a gui, which must delete linked DrawObject - _obj.erase(guid); // now delete the obj from the mgr - delete o; // and delete the obj itself + if(del) + { + _obj.erase(guid); // now delete the obj from the mgr + delete o; // and delete the obj itself + } } else { - _obj.erase(guid); + _obj.erase(guid); // we can safely erase an object that does not exist + // - if we reach this point there was a bug anyway logcustom(2,LRED,"ObjMgr::Remove("I64FMT") - not existing",guid); } } @@ -58,20 +63,29 @@ void ObjMgr::Remove(uint64 guid) void ObjMgr::Add(Object *o) { - _obj[o->GetGUID()] = o; + Object *ox = GetObj(o->GetGUID(),true); // if an object already exists in the mgr, store old ptr... + _obj[o->GetGUID()] = o; // ...assign new one... + if(ox) // and if != NULL, delete the old object (completely, from memory) + { + Remove(ox->GetGUID(),true); + } PseuGUI *gui = _instance->GetGUI(); if(gui) gui->NotifyObjectCreation(o); } -Object *ObjMgr::GetObj(uint64 guid) +Object *ObjMgr::GetObj(uint64 guid, bool also_depleted) { if(!guid) return NULL; for(ObjectMap::iterator i = _obj.begin(); i!=_obj.end(); i++) if(i->second->GetGUID() == guid) + { + if(i->second->_IsDepleted() && !also_depleted) + return NULL; return i->second; + } return NULL; } @@ -90,6 +104,22 @@ uint32 ObjMgr::AssignNameToObj(uint32 entry, uint8 type, std::string name) return changed; } +void ObjMgr::ReNotifyGUI(void) +{ + PseuGUI *gui = _instance->GetGUI(); + if(!gui) + return; + for(ObjectMap::iterator it = _obj.begin(); it != _obj.end(); it++) + { + Object *o = it->second; + if(o->_IsDepleted()) + continue; + gui->NotifyObjectCreation(o); + } +} + + + // -- Item part -- void ObjMgr::Add(ItemProto *proto) diff --git a/src/Client/World/ObjMgr.h b/src/Client/World/ObjMgr.h index 5c42a87..a892e64 100644 --- a/src/Client/World/ObjMgr.h +++ b/src/Client/World/ObjMgr.h @@ -49,10 +49,11 @@ public: // Object functions void Add(Object*); - void Remove(uint64); // remove all objects with that guid (should be only 1 object in total anyway) - Object *GetObj(uint64 guid); + void Remove(uint64 guid, bool del); // remove all objects with that guid (should be only 1 object in total anyway) + Object *GetObj(uint64 guid, bool also_depleted = false); inline uint32 GetObjectCount(void) { return _obj.size(); } uint32 AssignNameToObj(uint32 entry, uint8 type, std::string name); + void ReNotifyGUI(void); private: ItemProtoMap _iproto; diff --git a/src/Client/World/Object.cpp b/src/Client/World/Object.cpp index 423d1cd..5efb0c8 100644 --- a/src/Client/World/Object.cpp +++ b/src/Client/World/Object.cpp @@ -5,6 +5,7 @@ Object::Object() { + _depleted = false; _uint32values=NULL; _type=TYPE_OBJECT; _typeid=TYPEID_OBJECT; @@ -39,6 +40,7 @@ void Object::Create( uint64 guid ) WorldObject::WorldObject() { + _depleted = false; _m = 0; } @@ -121,7 +123,7 @@ void WorldSession::_HandleDestroyObjectOpcode(WorldPacket& recvPacket) GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set); } - objmgr.Remove(guid); + objmgr.Remove(guid, false); } diff --git a/src/Client/World/Object.h b/src/Client/World/Object.h index 9119cf7..cbfe5e8 100644 --- a/src/Client/World/Object.h +++ b/src/Client/World/Object.h @@ -92,6 +92,8 @@ public: } void Create(uint64 guid); + inline bool _IsDepleted(void) { return _depleted; } + inline void _SetDepleted(void) { _depleted = true; } protected: Object(); @@ -106,6 +108,7 @@ protected: uint8 _type; uint8 _typeid; std::string _name; + bool _depleted : 1; // true if the object was deleted from the objmgr, but not from memory }; class WorldObject : public Object diff --git a/src/Client/World/UpdateData.cpp b/src/Client/World/UpdateData.cpp index f64231b..01c245a 100644 --- a/src/Client/World/UpdateData.cpp +++ b/src/Client/World/UpdateData.cpp @@ -86,7 +86,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket) if(uguid != GetGuid()) { logdev("- already exists, deleting old, creating new object"); - objmgr.Remove(uguid); + objmgr.Remove(uguid, false); // do not call script here, since the object does not really get deleted } else @@ -128,6 +128,8 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket) } case TYPEID_PLAYER: { + if(GetGuid() == uguid) // objmgr.Add() would cause quite some trouble if we added ourself again + break; Player *player = new Player(); player->Create(uguid); objmgr.Add(player); @@ -201,7 +203,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket) GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set); } - objmgr.Remove(uguid); + objmgr.Remove(uguid, false); } } break; diff --git a/src/Client/World/WorldSession.cpp b/src/Client/World/WorldSession.cpp index 94dc920..4c8a8f5 100644 --- a/src/Client/World/WorldSession.cpp +++ b/src/Client/World/WorldSession.cpp @@ -597,8 +597,8 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket) // that means even if the server sends create object with that guid, do NOT recreate it!! MyCharacter *my = new MyCharacter(); my->Create(_myGUID); - objmgr.Add(my); my->SetName(plr[charId]._name); + objmgr.Add(my); // TODO: initialize the world here, and load required maps. // must remove appropriate code from _HandleLoginVerifyWorldOpcode() then!!