* some map loading formula (x/y) corrections

* first preparations to correctly position gui camera on real location, not just somewhere. formulas are still crap, need some help here.
* fixed bug with IsFloatField(), thx bLuma!
* misc code cleanups
This commit is contained in:
false_genesis 2008-01-14 17:46:33 +00:00
parent 5019a95392
commit f879006477
13 changed files with 205 additions and 57 deletions

View File

@ -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<s32> scrn = _driver->getScreenSize();

View File

@ -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<irr::s32> _screendimension;
WorldPosition _worldpos_tmp;
bool _updateWorldPos;
};

View File

@ -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;

View File

@ -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; j<terrain->getSize().Height+1; j++)
for(s32 i=0; i<terrain->getSize().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<s32> 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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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
{

View File

@ -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;
}

View File

@ -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
{

View File

@ -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));
}
}

View File

@ -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()<buf.size())
while(buf.rpos() < buf.size())
{
buf.read(fourcc,4); flipcc(fourcc);
buf.read((uint8*)&size,4);
@ -150,7 +152,9 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
else if(!strcmp((char*)fourcc,"MCNK"))
{
_chunks[mcnkid].hdr = buf.read<ADTMapChunkHeader>();
uint8 *mfcc = new uint8[5]; mfcc[4]=0;
uint8 _cc2[5];
uint8 *mfcc = &_cc2[0];
mfcc[4]=0;
uint32 msize;
while(buf.rpos()<buf.size())
{
@ -204,7 +208,8 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
}
else if(!strcmp((char*)mfcc,"MCLQ"))
{
uint8 *fcc1 = new uint8[5];
uint8 _cc3[5];
uint8 *fcc1 = &_cc3[0];
buf.read(fcc1,4);
flipcc(fcc1);
fcc1[4]=0;
@ -213,7 +218,6 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
_chunks[mcnkid].haswater = false;
//DEBUG(printf("ADT: MCNK: MCLQ not present\n"));
buf.rpos(buf.rpos()-4);
delete [] fcc1;
continue; // next block read will be the MCSE block
}
else
@ -248,7 +252,6 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
diffbytes = (msize-8) - rbytes; // dont forget to skip the 8 initial bytes
buf.rpos(buf.rpos()+diffbytes);
//DEBUG(printf("ADT: MCNK: MCLQ - %u junk bytes skipped\n",diffbytes));
delete [] fcc1;
}
}
else if(!strcmp((char*)mfcc,"MCSE"))
@ -266,14 +269,13 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
if(!(isalnum(mfcc[0]) && isalnum(mfcc[1]) && isalnum(mfcc[2]) && isalnum(mfcc[3])))
{
printf("Error loading ADT file (chunk %u error).\n",mcnkid);
return false; // dont care about those few mem leaks
return false;
}
buf.rpos(buf.rpos()+msize);
}
}
delete [] mfcc;
mcnkid++;
}
else
@ -282,13 +284,12 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
if(!(isalnum(fourcc[0]) && isalnum(fourcc[1]) && isalnum(fourcc[2]) && isalnum(fourcc[3])))
{
printf("Error loading ADT file.\n");
return false; // dont care about those few mem leaks
return false;
}
buf.rpos(buf.rpos()+size);
}
}
delete [] fourcc;
return true;
}

View File

@ -43,7 +43,10 @@ void MapTile::ImportFromADT(ADTFile *adt)
}
}
}
DEBUG(logdebug("MapTile first chunk base: h=%f x=%f y=%f",_chunks[0].baseheight,_chunks[0].basex,_chunks[0].basey));
_xbase = _chunks[0].basex;
_ybase = _chunks[0].basey;
_hbase = _chunks[0].baseheight;
DEBUG(logdebug("MapTile first chunk base: h=%f x=%f y=%f",_hbase,_xbase,_ybase));
}
void MapTileStorage::_DebugDump(void)

View File

@ -32,7 +32,10 @@ public:
void ImportFromADT(ADTFile*);
float GetZ(float,float);
void DebugDumpToFile(void);
inline MapChunk *GetChunk(uint32 x, uint32 y) { return &_chunks[x * 16 + y]; }
inline MapChunk *GetChunk(uint32 x, uint32 y) { return &_chunks[y * 16 + x]; }
inline float GetBaseX(void) { return _xbase; }
inline float GetBaseY(void) { return _ybase; }
inline float GetBaseHeight(void) { return _hbase; }
private:
MapChunk _chunks[256]; // 16x16
@ -40,7 +43,7 @@ private:
std::vector<std::string> _wmos;
std::vector<std::string> _models;
float _xbase,_ybase;
float _xbase,_ybase,_hbase;
};