* corrected terrain placement
* corrected object placement * corrected grid formulas * update MyCharacter position when beeing teleported * tested in dun morogh, stormwind, thrallmar and arathi basin, object placement on the map is just fine now ;) * cleanups not yet done, old unused funcs are still there
This commit is contained in:
parent
cc5cf995fd
commit
6d5b8de2d5
@ -34,7 +34,7 @@ void DrawObject::_Init(void)
|
|||||||
{
|
{
|
||||||
if(!cube && _obj->IsWorldObject()) // only world objects have coords and can be drawn
|
if(!cube && _obj->IsWorldObject()) // only world objects have coords and can be drawn
|
||||||
{
|
{
|
||||||
cube = _smgr->addCubeSceneNode(10);
|
cube = _smgr->addCubeSceneNode(2);
|
||||||
cube->setName("CUBE");
|
cube->setName("CUBE");
|
||||||
//cube->setPosition(irr::core::vector3di(100,100,100));
|
//cube->setPosition(irr::core::vector3di(100,100,100));
|
||||||
cube->setRotation(irr::core::vector3df(0,0,0));
|
cube->setRotation(irr::core::vector3df(0,0,0));
|
||||||
@ -63,13 +63,7 @@ void DrawObject::Draw(void)
|
|||||||
if(cube)
|
if(cube)
|
||||||
{
|
{
|
||||||
WorldPosition pos = ((WorldObject*)_obj)->GetPosition();
|
WorldPosition pos = ((WorldObject*)_obj)->GetPosition();
|
||||||
// TODO: these formulas are horribly wrong! FIXME ASAP!
|
cube->setPosition(irr::core::vector3df(-pos.x,pos.z,-pos.y));
|
||||||
// they work best for ".tele dunmorogh"
|
|
||||||
float dx=pos.x * -5.0f - 26830.0f;
|
|
||||||
float dy=pos.z;
|
|
||||||
float dz=pos.y * -3.5f - 566.0f;
|
|
||||||
|
|
||||||
cube->setPosition(irr::core::vector3df(dx,dy,dz));
|
|
||||||
if(_obj->IsPlayer())
|
if(_obj->IsPlayer())
|
||||||
{
|
{
|
||||||
cube->getMaterial(0).DiffuseColor.set(255,255,0,0);
|
cube->getMaterial(0).DiffuseColor.set(255,255,0,0);
|
||||||
|
|||||||
@ -36,6 +36,8 @@ enum DriverIDs
|
|||||||
#define RAD_TO_DEG(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 RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) )
|
||||||
#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) )
|
#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) )
|
||||||
|
#define IRR_TO_O(x) (DEG_TO_RAD(x) + ((M_PI*3.0f)/2.0f))
|
||||||
|
#define O_TO_IRR(x) (((M_PI/3.0f)*2.0f) - DEG_TO_RAD(x))
|
||||||
|
|
||||||
#define COORD_SCALE_VALUE_X 0.336f
|
#define COORD_SCALE_VALUE_X 0.336f
|
||||||
#define COORD_SCALE_VALUE_Y 0.2f
|
#define COORD_SCALE_VALUE_Y 0.2f
|
||||||
|
|||||||
@ -62,6 +62,7 @@ public:
|
|||||||
void OnUpdate(s32);
|
void OnUpdate(s32);
|
||||||
void UpdateTerrain(void);
|
void UpdateTerrain(void);
|
||||||
void InitTerrain(void);
|
void InitTerrain(void);
|
||||||
|
void RelocateCamera(void);
|
||||||
|
|
||||||
WorldPosition GetWorldPosition(void);
|
WorldPosition GetWorldPosition(void);
|
||||||
void SetWorldPosition(WorldPosition);
|
void SetWorldPosition(WorldPosition);
|
||||||
@ -76,6 +77,7 @@ private:
|
|||||||
s32 mapsize, meshsize;
|
s32 mapsize, meshsize;
|
||||||
f32 tilesize;
|
f32 tilesize;
|
||||||
WorldSession *wsession;
|
WorldSession *wsession;
|
||||||
|
World *world;
|
||||||
MapMgr *mapmgr;
|
MapMgr *mapmgr;
|
||||||
IGUIStaticText *debugText;
|
IGUIStaticText *debugText;
|
||||||
bool debugmode;
|
bool debugmode;
|
||||||
|
|||||||
@ -20,7 +20,8 @@ SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
|
|||||||
// store some pointers right now to prevent repeated ptr dereferencing later (speeds up code)
|
// store some pointers right now to prevent repeated ptr dereferencing later (speeds up code)
|
||||||
gui = g;
|
gui = g;
|
||||||
wsession = gui->GetInstance()->GetWSession();
|
wsession = gui->GetInstance()->GetWSession();
|
||||||
mapmgr = wsession->GetWorld()->GetMapMgr();
|
world = wsession->GetWorld();
|
||||||
|
mapmgr = world->GetMapMgr();
|
||||||
|
|
||||||
// TODO: hardcoded for now, make this adjustable later
|
// TODO: hardcoded for now, make this adjustable later
|
||||||
float fogdist = 150;
|
float fogdist = 150;
|
||||||
@ -51,6 +52,7 @@ SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
|
|||||||
|
|
||||||
InitTerrain();
|
InitTerrain();
|
||||||
UpdateTerrain();
|
UpdateTerrain();
|
||||||
|
RelocateCamera();
|
||||||
|
|
||||||
DEBUG(logdebug("SceneWorld: Init done!"));
|
DEBUG(logdebug("SceneWorld: Init done!"));
|
||||||
}
|
}
|
||||||
@ -123,6 +125,9 @@ void SceneWorld::OnUpdate(s32 timediff)
|
|||||||
scrnshot->drop();
|
scrnshot->drop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(camera->getPitch() < 270 && camera->getPitch() > 90)
|
||||||
|
camera->turnUp(90);
|
||||||
|
|
||||||
if(mouse_pressed_left || mouse_pressed_right)
|
if(mouse_pressed_left || mouse_pressed_right)
|
||||||
{
|
{
|
||||||
@ -150,7 +155,8 @@ void SceneWorld::OnUpdate(s32 timediff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// camera height control
|
// camera height control
|
||||||
if (eventrecv->mouse.wheel < 10) eventrecv->mouse.wheel = 10;
|
if (eventrecv->mouse.wheel < 10)
|
||||||
|
eventrecv->mouse.wheel = 10;
|
||||||
camera->setHeight( eventrecv->mouse.wheel + terrain->getHeight(camera->getPosition()) );
|
camera->setHeight( eventrecv->mouse.wheel + terrain->getHeight(camera->getPosition()) );
|
||||||
|
|
||||||
WorldPosition wp = GetWorldPosition();
|
WorldPosition wp = GetWorldPosition();
|
||||||
@ -162,6 +168,7 @@ void SceneWorld::OnUpdate(s32 timediff)
|
|||||||
str += camera->getPosition().Y;
|
str += camera->getPosition().Y;
|
||||||
str += L",";
|
str += L",";
|
||||||
str += camera->getPosition().Z;
|
str += camera->getPosition().Z;
|
||||||
|
str += L"\n";
|
||||||
str += " ## HEAD: ";
|
str += " ## HEAD: ";
|
||||||
str += DEG_TO_RAD(camera->getHeading());
|
str += DEG_TO_RAD(camera->getHeading());
|
||||||
str += L" Pos: ";
|
str += L" Pos: ";
|
||||||
@ -194,12 +201,11 @@ void SceneWorld::InitTerrain(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapsize = 8 * 16 * 3; // 9-1 height floats in 16 chunks per tile per axis in 3 MapTiles
|
mapsize = (8 * 16 * 3) - 1; // 9-1 height floats in 16 chunks per tile per axis in 3 MapTiles
|
||||||
tilesize = UNITSIZE;
|
tilesize = UNITSIZE;
|
||||||
meshsize = (s32)CHUNKSIZE*3;
|
meshsize = (s32)CHUNKSIZE*3;
|
||||||
vector3df terrainPos(0.0f, 0.0f, 0.0f); // TODO: use PseuWoW's world coords here?
|
|
||||||
|
|
||||||
camera->setPosition(core::vector3df(mapsize*tilesize/2, 0, mapsize*tilesize/2) + terrainPos);
|
//camera->setPosition(core::vector3df(mapsize*tilesize/2, 0, mapsize*tilesize/2) + terrainPos);
|
||||||
|
|
||||||
terrain = new ShTlTerrainSceneNode(smgr,mapsize,mapsize,tilesize,meshsize);
|
terrain = new ShTlTerrainSceneNode(smgr,mapsize,mapsize,tilesize,meshsize);
|
||||||
terrain->drop();
|
terrain->drop();
|
||||||
@ -207,7 +213,7 @@ void SceneWorld::InitTerrain(void)
|
|||||||
terrain->setMaterialTexture(0, driver->getTexture("data/misc/dirt_test.jpg"));
|
terrain->setMaterialTexture(0, driver->getTexture("data/misc/dirt_test.jpg"));
|
||||||
terrain->setMaterialFlag(video::EMF_LIGHTING, true);
|
terrain->setMaterialFlag(video::EMF_LIGHTING, true);
|
||||||
terrain->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
terrain->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||||
terrain->setPosition(terrainPos);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,8 +308,40 @@ void SceneWorld::UpdateTerrain(void)
|
|||||||
terrain->setColor(i,j, video::SColor(255,r,g,b));
|
terrain->setColor(i,j, video::SColor(255,r,g,b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// to set the correct position of the terrain, we have to use the top-left tile's coords as terrain base pos
|
||||||
|
MapTile *maptile = mapmgr->GetNearTile(-1, -1);
|
||||||
|
if(maptile)
|
||||||
|
{
|
||||||
|
vector3df tpos;
|
||||||
|
tpos.X = -maptile->GetBaseX();
|
||||||
|
tpos.Y = 0; // height already managed when building up terrain
|
||||||
|
tpos.Z = -maptile->GetBaseY();
|
||||||
|
logdebug("SceneWorld: Setting position of terrain (x:%.2f y:%.2f z:%.2f)", tpos.X, tpos.Y, tpos.Z);
|
||||||
|
terrain->setPosition(tpos);
|
||||||
|
}
|
||||||
|
|
||||||
logdebug("SceneWorld: Smoothing terrain normals...");
|
logdebug("SceneWorld: Smoothing terrain normals...");
|
||||||
terrain->smoothNormals();
|
terrain->smoothNormals();
|
||||||
|
|
||||||
|
// TODO: check if camera should really be relocated -> in case we got teleported
|
||||||
|
// do NOT relocate camera if we moved around and triggered the map loading code by ourself!
|
||||||
|
RelocateCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneWorld::RelocateCamera(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
MyCharacter *my = wsession->GetMyChar();
|
||||||
|
if(my)
|
||||||
|
{
|
||||||
|
logdebug("SceneWorld: Relocating camera to MyCharacter");
|
||||||
|
camera->setPosition(vector3df(-my->GetX(),my->GetZ(),-my->GetY()));
|
||||||
|
camera->turnLeft(camera->getHeading() - O_TO_IRR(my->GetO()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logerror("SceneWorld: Relocating camera to MyCharacter - not found!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldPosition SceneWorld::GetWorldPosition(void)
|
WorldPosition SceneWorld::GetWorldPosition(void)
|
||||||
@ -328,12 +366,13 @@ WorldPosition SceneWorld::GetWorldPosition(void)
|
|||||||
float relx = cam.X * COORD_SCALE_VALUE_X + CHUNKSIZE;
|
float relx = cam.X * COORD_SCALE_VALUE_X + CHUNKSIZE;
|
||||||
float rely = cam.Z * COORD_SCALE_VALUE_Y + CHUNKSIZE;
|
float rely = cam.Z * COORD_SCALE_VALUE_Y + CHUNKSIZE;
|
||||||
|
|
||||||
float o = DEG_TO_RAD(camera->getHeading()) + ((M_PI*3.0f)/2.0f);
|
float o = IRR_TO_O(camera->getHeading()) + ((M_PI*3.0f)/2.0f);
|
||||||
return WorldPosition(mapx - relx, mapy - rely, cam.Y, RAD_FIX(o) );
|
return WorldPosition(mapx - relx, mapy - rely, cam.Y, RAD_FIX(o) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneWorld::SetWorldPosition(WorldPosition wp)
|
void SceneWorld::SetWorldPosition(WorldPosition wp)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
UpdateTerrain();
|
UpdateTerrain();
|
||||||
vector3df cam;
|
vector3df cam;
|
||||||
dimension2d<s32> tsize = terrain->getSize();
|
dimension2d<s32> tsize = terrain->getSize();
|
||||||
@ -346,7 +385,7 @@ void SceneWorld::SetWorldPosition(WorldPosition wp)
|
|||||||
}
|
}
|
||||||
cam.X = tile->GetBaseX() - wp.x + (tsize.Width * UNITSIZE);
|
cam.X = tile->GetBaseX() - wp.x + (tsize.Width * UNITSIZE);
|
||||||
cam.Z = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE);
|
cam.Z = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE);
|
||||||
float heading = RAD_TO_DEG(((M_PI*3.0f)/2.0f) - wp.o);
|
float heading = O_TO_IRR(wp.o);
|
||||||
float heading_diff = camera->getHeading() - heading;
|
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);
|
//logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading);
|
||||||
//camera->turnLeft(heading_diff);
|
//camera->turnLeft(heading_diff);
|
||||||
|
|||||||
@ -3,6 +3,19 @@
|
|||||||
#include "MapTile.h"
|
#include "MapTile.h"
|
||||||
#include "MapMgr.h"
|
#include "MapMgr.h"
|
||||||
|
|
||||||
|
void MakeMapFilename(char *fn, uint32 m, uint32 x, uint32 y)
|
||||||
|
{
|
||||||
|
sprintf(fn,"./data/maps/%u_%u_%u.adt",m,x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TileExistsInFile(uint32 m, uint32 x, uint32 y)
|
||||||
|
{
|
||||||
|
char buf[50];
|
||||||
|
MakeMapFilename(buf,m,x,y);
|
||||||
|
return GetFileSize(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MapMgr::MapMgr()
|
MapMgr::MapMgr()
|
||||||
{
|
{
|
||||||
DEBUG(logdebug("Creating MapMgr with TILESIZE=%.3f CHUNKSIZE=%.3f UNITSIZE=%.3f",TILESIZE,CHUNKSIZE,UNITSIZE));
|
DEBUG(logdebug("Creating MapMgr with TILESIZE=%.3f CHUNKSIZE=%.3f UNITSIZE=%.3f",TILESIZE,CHUNKSIZE,UNITSIZE));
|
||||||
@ -69,15 +82,23 @@ void MapMgr::_LoadTile(uint32 gx, uint32 gy, uint32 m)
|
|||||||
{
|
{
|
||||||
if(!_tiles->TileExists(gx,gy))
|
if(!_tiles->TileExists(gx,gy))
|
||||||
{
|
{
|
||||||
logerror("MAPMGR: Not loading MapTile (%u, %u) map %u, no entry in WDT tile map",gx,gy,m);
|
if(TileExistsInFile(m,gx,gy))
|
||||||
return;
|
{
|
||||||
|
logerror("MapMgr: Tile (%u, %u) exists not in WDT, but as file?!",gx,gy);
|
||||||
|
// continue loading...
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logerror("MAPMGR: Not loading MapTile (%u, %u) map %u, no entry in WDT tile map",gx,gy,m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !_tiles->GetTile(gx,gy) )
|
if( !_tiles->GetTile(gx,gy) )
|
||||||
{
|
{
|
||||||
ADTFile *adt = new ADTFile();
|
ADTFile *adt = new ADTFile();
|
||||||
char buf[300];
|
char buf[300];
|
||||||
sprintf(buf,"data/maps/%u_%u_%u.adt",m,gx,gy);
|
MakeMapFilename(buf,m,gx,gy);
|
||||||
if(adt->Load(buf))
|
if(adt->Load(buf))
|
||||||
{
|
{
|
||||||
logdebug("MAPMGR: Loaded ADT '%s'",buf);
|
logdebug("MAPMGR: Loaded ADT '%s'",buf);
|
||||||
@ -120,7 +141,7 @@ void MapMgr::_UnloadOldTiles(void)
|
|||||||
MapTile *MapMgr::GetTile(uint32 xg, uint32 yg, bool forceLoad)
|
MapTile *MapMgr::GetTile(uint32 xg, uint32 yg, bool forceLoad)
|
||||||
{
|
{
|
||||||
MapTile *tile = _tiles->GetTile(xg,yg);
|
MapTile *tile = _tiles->GetTile(xg,yg);
|
||||||
if(!tile)
|
if(!tile && forceLoad)
|
||||||
{
|
{
|
||||||
_LoadTile(xg,yg,_mapid);
|
_LoadTile(xg,yg,_mapid);
|
||||||
tile = _tiles->GetTile(xg,yg);
|
tile = _tiles->GetTile(xg,yg);
|
||||||
@ -145,7 +166,7 @@ uint32 MapMgr::GetGridCoord(float f)
|
|||||||
|
|
||||||
GridCoordPair MapMgr::GetTransformGridCoordPair(float x, float y)
|
GridCoordPair MapMgr::GetTransformGridCoordPair(float x, float y)
|
||||||
{
|
{
|
||||||
return GridCoordPair(GetGridCoord(x), GetGridCoord(y));
|
return GridCoordPair(GetGridCoord(y), GetGridCoord(x)); // yes, they are reversed. definitely.
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MapMgr::GetLoadedMapsCount(void)
|
uint32 MapMgr::GetLoadedMapsCount(void)
|
||||||
|
|||||||
@ -919,10 +919,11 @@ void WorldSession::_HandleTelePortAckOpcode(WorldPacket& recvPacket)
|
|||||||
SendWorldPacket(response);
|
SendWorldPacket(response);
|
||||||
|
|
||||||
_world->UpdatePos(x,y);
|
_world->UpdatePos(x,y);
|
||||||
|
_world->Update();
|
||||||
|
|
||||||
if(PseuGUI *gui = GetInstance()->GetGUI())
|
if(MyCharacter *my = GetMyChar())
|
||||||
{
|
{
|
||||||
gui->SetWorldPosition(WorldPosition(x,y,z,o));
|
my->SetPosition(x,y,z,o);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetInstance()->GetScripts()->ScriptExists("_onteleport"))
|
if(GetInstance()->GetScripts()->ScriptExists("_onteleport"))
|
||||||
@ -947,8 +948,6 @@ void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket)
|
|||||||
// else we had to do the following before:
|
// else we had to do the following before:
|
||||||
// recvPacket >> tmapid >> tx >> ty >> tz >> to;
|
// recvPacket >> tmapid >> tx >> ty >> tz >> to;
|
||||||
recvPacket >> mapid >> x >> y >> z >> o;
|
recvPacket >> mapid >> x >> y >> z >> o;
|
||||||
if(GetMyChar())
|
|
||||||
GetMyChar()->ClearSpells(); // will be resent by server
|
|
||||||
|
|
||||||
// when getting teleported, the client sends CMSG_CANCEL_TRADE 2 times.. dont ask me why.
|
// when getting teleported, the client sends CMSG_CANCEL_TRADE 2 times.. dont ask me why.
|
||||||
WorldPacket wp(CMSG_CANCEL_TRADE,8);
|
WorldPacket wp(CMSG_CANCEL_TRADE,8);
|
||||||
@ -978,14 +977,14 @@ void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket)
|
|||||||
_world->UpdatePos(x,y,mapid);
|
_world->UpdatePos(x,y,mapid);
|
||||||
_world->Update();
|
_world->Update();
|
||||||
|
|
||||||
// TODO: need to switch to SCENESTATE_LOGINSCREEN here, and after everything is loaded, back to SCENESTATE_WORLD
|
if(MyCharacter *my = GetMyChar())
|
||||||
if(PseuGUI *gui = GetInstance()->GetGUI())
|
|
||||||
{
|
{
|
||||||
//gui->SetSceneState(SCENESTATE_WORLD);
|
my->ClearSpells(); // will be resent by server
|
||||||
// commented out, should be world scene anyway at this point...
|
my->SetPosition(x,y,z,o,mapid);
|
||||||
gui->SetWorldPosition(WorldPosition(x,y,z,o));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: need to switch to SCENESTATE_LOGINSCREEN here, and after everything is loaded, back to SCENESTATE_WORLD
|
||||||
|
|
||||||
if(GetInstance()->GetScripts()->ScriptExists("_onteleport"))
|
if(GetInstance()->GetScripts()->ScriptExists("_onteleport"))
|
||||||
{
|
{
|
||||||
CmdSet Set;
|
CmdSet Set;
|
||||||
|
|||||||
@ -24,8 +24,8 @@ void MapTile::ImportFromADT(ADTFile *adt)
|
|||||||
for(uint32 ch=0; ch<CHUNKS_PER_TILE; ch++)
|
for(uint32 ch=0; ch<CHUNKS_PER_TILE; ch++)
|
||||||
{
|
{
|
||||||
_chunks[ch].baseheight = adt->_chunks[ch].hdr.zbase; // ADT files store (x/z) as ground coords and (y) as the height!
|
_chunks[ch].baseheight = adt->_chunks[ch].hdr.zbase; // ADT files store (x/z) as ground coords and (y) as the height!
|
||||||
_chunks[ch].basex = adt->_chunks[ch].hdr.ybase; // here converting it to (x/y) on ground and basehight as actual height.
|
_chunks[ch].basex = adt->_chunks[ch].hdr.xbase; // here converting it to (x/y) on ground and basehight as actual height.
|
||||||
_chunks[ch].basey = adt->_chunks[ch].hdr.xbase; // strange coords they use... :S
|
_chunks[ch].basey = adt->_chunks[ch].hdr.ybase; // strange coords they use... :S
|
||||||
uint32 fcnt=0, rcnt=0;
|
uint32 fcnt=0, rcnt=0;
|
||||||
while(true) //9*9 + 8*8
|
while(true) //9*9 + 8*8
|
||||||
{
|
{
|
||||||
@ -128,3 +128,4 @@ void MapTile::DebugDumpToFile(void)
|
|||||||
fprintf(fh, out.c_str());
|
fprintf(fh, out.c_str());
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user