diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index 3a635d0..612d457 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -43,6 +43,7 @@ PseuGUI::PseuGUI() _guienv = NULL; _scene = NULL; _passtime = _lastpasstime = _passtimediff = 0; + _updateWorldPos = false; } PseuGUI::~PseuGUI() @@ -177,7 +178,11 @@ void PseuGUI::Run(void) _UpdateSceneState(); if(_scene && _initialized) + { + if(_updateWorldPos) + SetWorldPosition(_worldpos_tmp); _scene->OnUpdate(_passtimediff); + } _driver->beginScene(true, true, 0); @@ -205,7 +210,6 @@ void PseuGUI::Run(void) _device->setWindowCaption(str.c_str()); lastFPS = fps; - DEBUG(logdebug("PseuGUI: Current FPS: %u",fps)); } } @@ -258,6 +262,7 @@ void PseuGUI::_UpdateSceneState(void) case SCENESTATE_WORLD: _scene = new SceneWorld(this); break; default: _scene = new Scene(this); // will draw nothing, just yield the gui } + _scene->SetState(_scenestate); logdebug("PseuGUI: scene created."); } @@ -269,6 +274,32 @@ void PseuGUI::DrawCurrentScene(void) _scene->OnDraw(); } +// used to get our current WorldPosition +WorldPosition PseuGUI::GetWorldPosition(void) +{ + if(_scene && _scene->GetState() == SCENESTATE_WORLD) + { + return ((SceneWorld*)_scene)->GetWorldPosition(); + } + return WorldPosition(); +} + +// used to notify the SceneWorld about a position change the server sent to us +void PseuGUI::SetWorldPosition(WorldPosition wp) +{ + // buffer new position if the scene is not (yet) a world scene + _worldpos_tmp = wp; + if(_scene && _scene->GetState() == SCENESTATE_WORLD) + { + _updateWorldPos = false; + ((SceneWorld*)_scene)->SetWorldPosition(wp); + } + else + { + _updateWorldPos = true; + } +} + void PseuGUI::_HandleWindowResize(void) { dimension2d scrn = _driver->getScreenSize(); diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index e36fd6b..17e4e9a 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -3,6 +3,7 @@ #include "irrlicht/irrlicht.h" #include "DrawObjMgr.h" +#include "World.h" class PseuGUI; class Object; @@ -75,6 +76,10 @@ public: void DrawCurrentScene(void); void SetSceneState(SceneState); + // helpers + WorldPosition GetWorldPosition(void); + void SetWorldPosition(WorldPosition); + private: void _Init(void); void _UpdateSceneState(void); @@ -94,6 +99,8 @@ private: irr::ITimer *_timer; uint32 _passtime, _lastpasstime, _passtimediff; irr::core::dimension2d _screendimension; + WorldPosition _worldpos_tmp; + bool _updateWorldPos; }; diff --git a/src/Client/GUI/Scene.h b/src/Client/GUI/Scene.h index 6140b14..ef8d958 100644 --- a/src/Client/GUI/Scene.h +++ b/src/Client/GUI/Scene.h @@ -19,6 +19,8 @@ class Scene public: Scene(PseuGUI *g); ~Scene(); + inline void SetState(SceneState sc) { _scenestate = sc; } + inline SceneState GetState(void) { return _scenestate; } virtual void OnUpdate(s32); virtual void OnDraw(void); virtual void OnDelete(void); @@ -29,6 +31,7 @@ protected: irr::video::IVideoDriver* driver; irr::scene::ISceneManager* smgr; irr::gui::IGUIEnvironment* guienv; + SceneState _scenestate; }; class SceneGuiStart : public Scene @@ -58,6 +61,10 @@ public: void OnUpdate(s32); void UpdateTerrain(void); void InitTerrain(void); + + WorldPosition GetWorldPosition(void); + void SetWorldPosition(WorldPosition); + private: ShTlTerrainSceneNode *terrain; MCameraFPS *camera; diff --git a/src/Client/GUI/SceneWorld.cpp b/src/Client/GUI/SceneWorld.cpp index d81f75c..ec1cdd1 100644 --- a/src/Client/GUI/SceneWorld.cpp +++ b/src/Client/GUI/SceneWorld.cpp @@ -13,6 +13,9 @@ #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) @@ -157,14 +160,19 @@ void SceneWorld::OnUpdate(s32 timediff) if (eventrecv->mouse.wheel < 10) eventrecv->mouse.wheel = 10; camera->setHeight( eventrecv->mouse.wheel + terrain->getHeight(camera->getPosition()) ); + WorldPosition wp = GetWorldPosition(); core::stringw str = L"Camera: pitch:"; str += camera->getPitch(); str += L" dir:"; str += camera->getDirection().X; str += L","; str += camera->getDirection().Y; + str += L","; + str += camera->getDirection().Z; + str += " ## o: "; + str += DEG_TO_RAD(camera->getHeading()); str += L" Pos: "; - str = (((((str + camera->getPosition().X) + L" | ") + camera->getPosition().Y) + L" | ") + camera->getPosition().Z); + str = ((((((str + wp.x) + L" | ") + wp.y) + L" | ") + wp.z) + L" | ") + wp.o; str += L" -- Terrain: Sectors: "; str += (int)terrain->getSectorsRendered(); str += L" / "; @@ -260,10 +268,10 @@ void SceneWorld::UpdateTerrain(void) { for(uint32 hx = 0; hx < 9; hx++) { - f32 h = chunk->hmap_rough[hx * 9 + hy] + chunk->baseheight; // not sure if hx and hy are used correctly here - u32 terrainx = (144 * tiley) + (9 * chx) + hx; - u32 terrainy = (144 * tilex) + (9 * chy) + hy; - terrain->setHeight(terrainx, terrainy, h); + f32 h = chunk->hmap_rough[hy * 9 + hx] + chunk->baseheight; // not sure if hx and hy are used correctly here + u32 terrainx = (144 * tilex) + (9 * chx) + hx; + u32 terrainy = (144 * tiley) + (9 * chy) + hy; + terrain->setHeight(terrainy, terrainx, h); } } } @@ -289,7 +297,7 @@ void SceneWorld::UpdateTerrain(void) } f32 heightdiff = highest - lowest; - // randomize terrain color dependng on height + // randomize terrain color depending on height for(s32 j=0; jgetSize().Height+1; j++) for(s32 i=0; igetSize().Width+1; i++) { @@ -304,3 +312,47 @@ void SceneWorld::UpdateTerrain(void) logdebug("SceneWorld: Smoothing terrain normals..."); terrain->smoothNormals(); } + +WorldPosition SceneWorld::GetWorldPosition(void) +{ + // TODO: later do not use CAMERA, but CHARACTER position, as soon as camera is changed from 1st to 3rd person view + // and floating around character in the middle + vector3df cam = camera->getPosition(); + // TODO: need to correct camera values, the coords irrlicht returns are not suitable + + // get the current maptile and use the coords of the top-left corner as relative positions + MapTile *tile = mapmgr->GetCurrentTile(); + float mapx = tile->GetBaseX(); + float mapy = tile->GetBaseY(); + return WorldPosition(cam.X + mapx, cam.Z + mapy, cam.Y, DEG_TO_RAD(camera->getHeading())); +} + +void SceneWorld::SetWorldPosition(WorldPosition wp) +{ + UpdateTerrain(); + vector3df cam; + dimension2d tsize = terrain->getSize(); + MapTile *tile = mapmgr->GetTile(MapMgr::GetGridCoord(wp.x), MapMgr::GetGridCoord(wp.y)); + ASSERT(tile == mapmgr->GetCurrentTile()); // for debugging; we should already be located on the new tile + if(!tile) + { + logerror("SceneWorld::SetWorldPosition(): MapTile not loaded!"); + return; + } + cam.X = tile->GetBaseX() - wp.x + (tsize.Width * UNITSIZE); + cam.Y = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE); + float heading = RAD_TO_DEG(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); + + // TODO: + // - correct the above formulas + // - find out terrain height where the camera should be set + // - set camera to correct position + // - correct camera turning + //camera->setPosition(cam); + //camera->turnRight(heading_diff); +} + + + diff --git a/src/Client/World/CacheHandler.cpp b/src/Client/World/CacheHandler.cpp index 68f4782..326890c 100644 --- a/src/Client/World/CacheHandler.cpp +++ b/src/Client/World/CacheHandler.cpp @@ -151,6 +151,7 @@ uint32 PlayerNameCache::GetSize(void) void ItemProtoCache_InsertDataToSession(WorldSession *session) { + logdetail("ItemProtoCache: Loading..."); char* fn = "./cache/ItemPrototypes.cache"; std::fstream fh; fh.open(fn, std::ios_base::in | std::ios_base::binary); @@ -176,6 +177,11 @@ void ItemProtoCache_InsertDataToSession(WorldSession *session) buf.clear(); fh.read((char*)&datasize,sizeof(uint32)); buf.resize(datasize); + if(buf.size() < datasize) + { + logerror("ItemProtoCache: Failed to resize ByteBuffer!"); + return; + } fh.read((char*)buf.contents(),datasize); ItemProto *proto = new ItemProto; buf >> proto->Id; @@ -274,7 +280,7 @@ void ItemProtoCache_InsertDataToSession(WorldSession *session) delete proto; } fh.close(); - log("ItemProtoCache: Loaded %u Item Prototypes",counter); + logdetail("ItemProtoCache: Loaded %u Item Prototypes",counter); } void ItemProtoCache_WriteDataToCache(WorldSession *session) diff --git a/src/Client/World/MapMgr.cpp b/src/Client/World/MapMgr.cpp index 4563ee4..e6e0483 100644 --- a/src/Client/World/MapMgr.cpp +++ b/src/Client/World/MapMgr.cpp @@ -36,12 +36,11 @@ void MapMgr::Update(float x, float y, uint32 m) GridCoordPair gcoords = GetTransformGridCoordPair(x,y); if(gcoords.x != _gridx || gcoords.y != _gridy) { - _LoadNearTiles(gcoords.x,gcoords.y,m); _gridx = gcoords.x; _gridy = gcoords.y; + _LoadNearTiles(_gridx,_gridy,m); _UnloadOldTiles(); } - _mapid = m; } void MapMgr::Flush(void) @@ -100,9 +99,9 @@ void MapMgr::_LoadTile(uint32 gx, uint32 gy, uint32 m) void MapMgr::_UnloadOldTiles(void) { - for(uint32 gx=0; gx<64; gx++) + for(uint32 gy=0; gy<64; gy++) { - for(uint32 gy=0; gy<64; gy++) + for(uint32 gx=0; gx<64; gx++) { if( (_gridx < gx-1 || _gridx > gx+1) && (_gridy < gy-1 || _gridy > gy+1) ) { @@ -145,7 +144,7 @@ uint32 MapMgr::GetGridCoord(float f) GridCoordPair MapMgr::GetTransformGridCoordPair(float x, float y) { - return GridCoordPair(GetGridCoord(y), GetGridCoord(x)); // i have no idea why they are swapping x and y map coords in ADT files... + return GridCoordPair(GetGridCoord(x), GetGridCoord(y)); } uint32 MapMgr::GetLoadedMapsCount(void) diff --git a/src/Client/World/Object.h b/src/Client/World/Object.h index e4a80d6..630a2f1 100644 --- a/src/Client/World/Object.h +++ b/src/Client/World/Object.h @@ -44,6 +44,7 @@ public: inline uint16 GetValuesCount(void) { return _valuescount; } inline const uint8 GetTypeId() { return _typeid; } + inline const uint8 GetTypeMask() { return _type; } inline bool isType(uint8 mask) { return (mask & _type) ? true : false; } inline const uint32 GetUInt32Value( uint16 index ) const { diff --git a/src/Client/World/UpdateData.cpp b/src/Client/World/UpdateData.cpp index 011cb7f..b5473ba 100644 --- a/src/Client/World/UpdateData.cpp +++ b/src/Client/World/UpdateData.cpp @@ -60,7 +60,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket) if(obj) this->_MovementUpdate(obj->GetTypeId(),uguid,recvPacket); else - logcustom(2,RED,"Got UpdateObject_Movement for unknown object "I64FMT,uguid); + logerror("Got UpdateObject_Movement for unknown object "I64FMT,uguid); } break; @@ -77,7 +77,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket) { if(uguid != GetGuid()) { - logdev("- already exists, deleting old , creating new object"); + logdev("- already exists, deleting old, creating new object"); objmgr.Remove(uguid); // do not call script here, since the object does not really get deleted } @@ -332,7 +332,7 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket) { if (umask.GetBit(i)) { - if(IsFloatField(obj->GetTypeId(),i)) + if(IsFloatField(obj->GetTypeMask(),i)) { recvPacket >> fvalue; obj->SetFloatValue(i, fvalue); @@ -389,16 +389,14 @@ void WorldSession::_QueryObjectInfo(uint64 guid) } // helper to determine if an updatefield should store float or int values, depending on TypeId -bool IsFloatField(uint8 tyid, uint32 f) +bool IsFloatField(uint8 ty, uint32 f) { - static bool first_use = true; - static uint32 *ty[TYPEID_CORPSE+1]; - static uint32 floats_object[] = { (uint32)OBJECT_FIELD_SCALE_X, (uint32)-1 }; + /* static uint32 floats_item[] = { (uint32)-1 @@ -407,6 +405,7 @@ bool IsFloatField(uint8 tyid, uint32 f) { (uint32)-1 }; + */ static uint32 floats_unit[] = { (uint32)UNIT_FIELD_BOUNDINGRADIUS, @@ -467,22 +466,40 @@ bool IsFloatField(uint8 tyid, uint32 f) (uint32)-1 }; - if(first_use) - { - first_use = true; - ty[TYPEID_OBJECT] = &floats_object[0]; - ty[TYPEID_ITEM] = &floats_item[0]; - ty[TYPEID_CONTAINER] = &floats_container[0]; - ty[TYPEID_UNIT] = &floats_unit[0]; - ty[TYPEID_PLAYER] = &floats_player[0]; - ty[TYPEID_GAMEOBJECT] = &floats_gameobject[0]; - ty[TYPEID_DYNAMICOBJECT] = &floats_dynobject[0]; - ty[TYPEID_CORPSE] = &floats_corpse[0]; - } - - for(uint32 i = 0; ty[tyid][i] != (-1); i++) - if(ty[tyid][i] == f) - return true; + if(ty & TYPE_OBJECT) + for(uint32 i = 0; floats_object[i] != (-1); i++) + if(floats_object[i] == f) + return true; + /* + if(ty & TYPE_ITEM) + for(uint32 i = 0; floats_item[i] != (-1); i++) + if(floats_object[i] == f) + return true; + if(ty & TYPE_CONTAINER) + for(uint32 i = 0; floats_container[i] != (-1); i++) + if(floats_object[i] == f) + return true; + */ + if(ty & TYPE_UNIT) + for(uint32 i = 0; floats_unit[i] != (-1); i++) + if(floats_unit[i] == f) + return true; + if(ty & TYPE_PLAYER) + for(uint32 i = 0; floats_player[i] != (-1); i++) + if(floats_player[i] == f) + return true; + if(ty & TYPE_GAMEOBJECT) + for(uint32 i = 0; floats_gameobject[i] != (-1); i++) + if(floats_gameobject[i] == f) + return true; + if(ty & TYPE_DYNAMICOBJECT) + for(uint32 i = 0; floats_dynobject[i] != (-1); i++) + if(floats_dynobject[i] == f) + return true; + if(ty & TYPE_CORPSE) + for(uint32 i = 0; floats_corpse[i] != (-1); i++) + if(floats_corpse[i] == f) + return true; return false; } diff --git a/src/Client/World/World.h b/src/Client/World/World.h index f933d7c..79a66fe 100644 --- a/src/Client/World/World.h +++ b/src/Client/World/World.h @@ -4,6 +4,15 @@ class WorldSession; class MapMgr; +struct WorldPosition +{ + WorldPosition() : x(0.0f), y(0.0f), z(0.0f), o(0.0f) {}; + WorldPosition(float px, float py) : x(px), y(py), z(0.0f), o(0.0f) {}; + WorldPosition(float px, float py, float pz) : x(px), y(py), z(pz), o(0.0f) {}; + WorldPosition(float px, float py, float pz, float po) : x(px), y(py), z(pz), o(po) {}; + float x,y,z,o; +}; + // used as interface for movement, map data, class World { diff --git a/src/Client/World/WorldSession.cpp b/src/Client/World/WorldSession.cpp index e01d56c..eaf4559 100644 --- a/src/Client/World/WorldSession.cpp +++ b/src/Client/World/WorldSession.cpp @@ -99,7 +99,7 @@ void WorldSession::AddToPktQueue(WorldPacket *pkt) void WorldSession::SendWorldPacket(WorldPacket &pkt) { if(GetInstance()->GetConf()->showmyopcodes) - logcustom(0,BROWN,"<< Opcode %u [%s]", pkt.GetOpcode(), GetOpcodeName(pkt.GetOpcode())); + logcustom(0,BROWN,"<< Opcode %u [%s] (%u bytes)", pkt.GetOpcode(), GetOpcodeName(pkt.GetOpcode()), pkt.size()); if(_socket && _socket->IsOk()) _socket->SendWorldPacket(pkt); else @@ -637,7 +637,6 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket) // TODO: also _onwhisper must be replaced by this! if(!isCmd && GetInstance()->GetScripts()->GetScript("_onchatmessage")) { - DEBUG(logdebug("DefScript chat handler found, executing _onchatmessage")); CmdSet Set; Set.arg[0] = toString(type); Set.arg[1] = toString(lang); @@ -795,8 +794,13 @@ void WorldSession::_HandleTelePortAckOpcode(WorldPacket& recvPacket) response << uint32(0) << (uint32)getMSTime(); // no flags; time correct? response << x << y << z << o << uint32(0); SendWorldPacket(response); - if(_world) - _world->UpdatePos(x,y); + + _world->UpdatePos(x,y); + + if(PseuGUI *gui = GetInstance()->GetGUI()) + { + gui->SetWorldPosition(WorldPosition(x,y,z,o)); + } if(GetInstance()->GetScripts()->ScriptExists("_onteleport")) { @@ -824,6 +828,14 @@ void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket) _world->UpdatePos(x,y,mapid); _world->Update(); + // TODO: need to switch to SCENESTATE_LOGINSCREEN here, and after everything is loaded, back to SCENESTATE_WORLD + if(PseuGUI *gui = GetInstance()->GetGUI()) + { + //gui->SetSceneState(SCENESTATE_WORLD); + // commented out, should be world scene anyway at this point... + gui->SetWorldPosition(WorldPosition(x,y,z,o)); + } + if(GetInstance()->GetScripts()->ScriptExists("_onteleport")) { CmdSet Set; @@ -866,10 +878,9 @@ void WorldSession::_HandleInitialSpellsOpcode(WorldPacket& recvPacket) logdebug("Got initial spells list, %u spells.",count); for(uint16 i = 0; i < count; i++) { - recvPacket >> spellid >> spellslot; - logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot); - - GetMyChar()->AddSpell(spellid, spellslot); + recvPacket >> spellid >> spellslot; + logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot); + GetMyChar()->AddSpell(spellid, spellslot); } } @@ -1030,6 +1041,7 @@ void WorldSession::_HandleLoginVerifyWorldOpcode(WorldPacket& recvPacket) if(PseuGUI *gui = GetInstance()->GetGUI()) { gui->SetSceneState(SCENESTATE_WORLD); + gui->SetWorldPosition(WorldPosition(x,y,z,o)); } } diff --git a/src/shared/ADTFile.cpp b/src/shared/ADTFile.cpp index e0a8194..8cb6e54 100644 --- a/src/shared/ADTFile.cpp +++ b/src/shared/ADTFile.cpp @@ -37,9 +37,11 @@ bool ADTFile::LoadMem(ByteBuffer& buf) uint32 texturecnt=0,modelcnt=0,wmocnt=0; uint32 size; // used for every chunk uint32 mcnkid=0; - uint8 *fourcc = new uint8[5]; fourcc[4]=0; + uint8 _cc[5]; + uint8 *fourcc = &_cc[0]; + fourcc[4]=0; - while(buf.rpos()(); - uint8 *mfcc = new uint8[5]; mfcc[4]=0; + uint8 _cc2[5]; + uint8 *mfcc = &_cc2[0]; + mfcc[4]=0; uint32 msize; while(buf.rpos() _wmos; std::vector _models; - float _xbase,_ybase; + float _xbase,_ybase,_hbase; };