* added custom mouse cursor handler
* stuffextract update (functional: extract CharSections and renamed some fields; visual: added progress bars)
This commit is contained in:
parent
24e62993df
commit
0397d33989
BIN
bin/data/misc/cursor.png
Normal file
BIN
bin/data/misc/cursor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 298 B |
@ -3,6 +3,7 @@
|
||||
#include "DrawObject.h"
|
||||
#include "PseuWoW.h"
|
||||
#include "Object.h"
|
||||
#include "Player.h"
|
||||
|
||||
using namespace irr;
|
||||
|
||||
@ -36,6 +37,13 @@ void DrawObject::Unlink(void)
|
||||
|
||||
void DrawObject::_Init(void)
|
||||
{
|
||||
if(_obj->IsPlayer())
|
||||
{
|
||||
Player *p = (Player*)_obj;
|
||||
DEBUG(logdebug("Player: race=%u gender=%u face=%u skin=%u traits=%u hair=%u haircol=%u",
|
||||
p->GetRace(),p->GetGender(),p->GetFaceId(),p->GetSkinId(),p->GetFaceTraitsId(),p->GetHairStyleId(),p->GetHairColorId()));
|
||||
}
|
||||
|
||||
if(!cube && _obj->IsWorldObject()) // only world objects have coords and can be drawn
|
||||
{
|
||||
uint32 displayid = _obj->IsUnit() ? _obj->GetUInt32Value(UNIT_FIELD_DISPLAYID) : 0; // TODO: in case its GO get it from proto data
|
||||
|
||||
@ -190,11 +190,12 @@ void PseuGUI::Run(void)
|
||||
|
||||
_driver->beginScene(true, true, 0);
|
||||
|
||||
DrawCurrentScene();
|
||||
|
||||
_smgr->drawAll();
|
||||
_guienv->drawAll();
|
||||
|
||||
if(_scene)
|
||||
_scene->OnDraw();
|
||||
|
||||
_driver->endScene();
|
||||
}
|
||||
catch(...)
|
||||
@ -274,12 +275,6 @@ void PseuGUI::_UpdateSceneState(void)
|
||||
}
|
||||
}
|
||||
|
||||
void PseuGUI::DrawCurrentScene(void)
|
||||
{
|
||||
if(_scene && _initialized)
|
||||
_scene->OnDraw();
|
||||
}
|
||||
|
||||
// used to get our current WorldPosition
|
||||
WorldPosition PseuGUI::GetWorldPosition(void)
|
||||
{
|
||||
|
||||
@ -93,7 +93,6 @@ public:
|
||||
void NotifyObjectCreation(Object *o);
|
||||
|
||||
// scenes
|
||||
void DrawCurrentScene(void);
|
||||
void SetSceneState(SceneState);
|
||||
|
||||
// helpers
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "common.h"
|
||||
#include "PseuGUI.h"
|
||||
#include "PseuWoW.h"
|
||||
#include "CCursorController.h"
|
||||
#include "Scene.h"
|
||||
|
||||
Scene::Scene(PseuGUI *g)
|
||||
@ -10,6 +11,9 @@ Scene::Scene(PseuGUI *g)
|
||||
driver = gui->_driver;
|
||||
smgr = gui->_smgr;
|
||||
guienv = gui->_guienv;
|
||||
cursor = new CCursorController(device->getCursorControl(), driver);
|
||||
cursor->setOSCursorVisible(true);
|
||||
cursor->setVisible(false);
|
||||
}
|
||||
|
||||
void Scene::OnDraw(void)
|
||||
|
||||
@ -12,6 +12,7 @@ using namespace gui;
|
||||
|
||||
|
||||
class PseuGUI;
|
||||
class CCursorController;
|
||||
|
||||
// base class
|
||||
class Scene
|
||||
@ -32,6 +33,7 @@ protected:
|
||||
irr::video::IVideoDriver* driver;
|
||||
irr::scene::ISceneManager* smgr;
|
||||
irr::gui::IGUIEnvironment* guienv;
|
||||
CCursorController *cursor;
|
||||
SceneState _scenestate;
|
||||
};
|
||||
|
||||
@ -80,6 +82,7 @@ private:
|
||||
MapMgr *mapmgr;
|
||||
IGUIStaticText *debugText;
|
||||
bool debugmode;
|
||||
gui::IGUIImage *icursor;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "MInput.h"
|
||||
#include "WorldSession.h"
|
||||
#include "World.h"
|
||||
#include "CCursorController.h"
|
||||
|
||||
SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
|
||||
{
|
||||
@ -48,7 +49,10 @@ SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
|
||||
driver->setFog(video::SColor(0,100,101,190), true, fogdist, fogdist + 30, 0.02f);
|
||||
|
||||
// setup cursor
|
||||
device->getCursorControl()->setVisible(false);
|
||||
|
||||
cursor->setOSCursorVisible(false);
|
||||
cursor->addMouseCursorTexture("data/misc/cursor.png", true);
|
||||
cursor->setVisible(true);
|
||||
|
||||
InitTerrain();
|
||||
UpdateTerrain();
|
||||
@ -67,6 +71,17 @@ void SceneWorld::OnUpdate(s32 timediff)
|
||||
bool mouse_pressed_right = eventrecv->mouse.right_pressed();
|
||||
float timediff_f = timediff / 1000.0f;
|
||||
|
||||
if( (mouse_pressed_right || mouse_pressed_left) && cursor->isVisible())
|
||||
{
|
||||
// TODO: if mouse is hovering over a gui element, do not hide
|
||||
cursor->setVisible(false);
|
||||
}
|
||||
else if( !(mouse_pressed_right || mouse_pressed_left) && !cursor->isVisible())
|
||||
{
|
||||
cursor->setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
if(eventrecv->key.pressed(KEY_KEY_W) || (mouse_pressed_left && mouse_pressed_right))
|
||||
camera->moveForward(50 * timediff_f);
|
||||
if(eventrecv->key.pressed(KEY_KEY_S))
|
||||
@ -131,9 +146,7 @@ void SceneWorld::OnUpdate(s32 timediff)
|
||||
|
||||
if(mouse_pressed_left || mouse_pressed_right)
|
||||
{
|
||||
//if(device->getCursorControl()->isVisible())
|
||||
//device->getCursorControl()->setVisible(false);
|
||||
if(mouse_pos != device->getCursorControl()->getPosition())
|
||||
if(mouse_pos != cursor->getMousePos())
|
||||
{
|
||||
camera->turnRight(MOUSE_SENSIVITY * (device->getCursorControl()->getPosition().X - mouse_pos.X));
|
||||
// check if new camera pitch would cause camera to flip over; if thats the case keep current pitch
|
||||
@ -148,9 +161,7 @@ void SceneWorld::OnUpdate(s32 timediff)
|
||||
}
|
||||
else
|
||||
{
|
||||
device->getCursorControl()->setPosition(device->getCursorControl()->getPosition());
|
||||
//if(!device->getCursorControl()->isVisible())
|
||||
//device->getCursorControl()->setVisible(true);
|
||||
//device->getCursorControl()->setPosition(device->getCursorControl()->getPosition());
|
||||
mouse_pos = device->getCursorControl()->getPosition();
|
||||
}
|
||||
|
||||
@ -177,14 +188,18 @@ void SceneWorld::OnUpdate(s32 timediff)
|
||||
str += (int)terrain->getSectorsRendered();
|
||||
str += L" / ";
|
||||
str += (int)terrain->getSectorCount();
|
||||
str += L"\n";
|
||||
str += device->getCursorControl()->isVisible() ? L"Cursor: VISIBLE" : L"Cursor: HIDDEN";
|
||||
debugText->setText(str.c_str());
|
||||
|
||||
|
||||
gui->domgr.Update(); // iterate over DrawObjects, draw them and clean up
|
||||
|
||||
}
|
||||
|
||||
void SceneWorld::OnDraw(void)
|
||||
{
|
||||
// draw all objects
|
||||
gui->domgr.Update(); // iterate over DrawObjects, draw them and clean up
|
||||
cursor->render();
|
||||
}
|
||||
|
||||
void SceneWorld::OnDelete(void)
|
||||
@ -214,7 +229,6 @@ void SceneWorld::InitTerrain(void)
|
||||
terrain->getMaterial(0).setFlag(video::EMF_LIGHTING, true);
|
||||
terrain->getMaterial(0).setFlag(video::EMF_FOG_ENABLE, true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -167,7 +167,12 @@ class Player : public Unit
|
||||
public:
|
||||
Player();
|
||||
void Create(uint64);
|
||||
uint8 GetGender() { return GetUInt32Value(PLAYER_BYTES_3); }
|
||||
inline uint8 GetGender() { return GetUInt32Value(PLAYER_BYTES_3); }
|
||||
inline uint8 GetSkinId() { return (GetUInt32Value(PLAYER_BYTES) & 0x000000FF); }
|
||||
inline uint8 GetFaceId() { return (GetUInt32Value(PLAYER_BYTES) & 0x0000FF00) >> 8; }
|
||||
inline uint8 GetHairStyleId() { return (GetUInt32Value(PLAYER_BYTES) & 0x00FF0000) >> 16; }
|
||||
inline uint8 GetHairColorId() { return (GetUInt32Value(PLAYER_BYTES) & 0xFF000000) >> 24; }
|
||||
inline uint8 GetFaceTraitsId() { return (GetUInt32Value(PLAYER_BYTES_2) & 0x000000FF); }
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@ -417,6 +417,12 @@
|
||||
<Filter
|
||||
Name="GUI"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\Client\Gui\CCursorController.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Client\Gui\CCursorController.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Client\Gui\CM2MeshFileLoader.cpp">
|
||||
</File>
|
||||
|
||||
@ -144,6 +144,12 @@
|
||||
<File
|
||||
RelativePath=".\shared\log.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\shared\ProgressBar.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\shared\ProgressBar.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\shared\SysDefs.h">
|
||||
</File>
|
||||
|
||||
@ -303,46 +303,3 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ADT_ExportStringSetByOffset(const uint8* data, uint32 off, std::set<std::string>& st, char* stop)
|
||||
{
|
||||
data += ((uint32*)data)[off]; // seek to correct absolute offset
|
||||
data += 28; // move ptr to real start of data
|
||||
uint32 offset=0;
|
||||
std::string s;
|
||||
char c;
|
||||
while(memcmp(data+offset,stop,4))
|
||||
{
|
||||
c = data[offset];
|
||||
if(!c)
|
||||
{
|
||||
if(s.length())
|
||||
{
|
||||
DEBUG(printf("DEP: %s\n",s.c_str()));
|
||||
st.insert(s);
|
||||
s.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
s += c;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
void ADT_FillTextureData(const uint8* data,std::set<std::string>& st)
|
||||
{
|
||||
ADT_ExportStringSetByOffset(data,OFFSET_TEXTURES,st,"XDMM");
|
||||
}
|
||||
|
||||
void ADT_FillWMOData(const uint8* data,std::set<std::string>& st)
|
||||
{
|
||||
ADT_ExportStringSetByOffset(data,OFFSET_WMOS,st,"DIWM");
|
||||
}
|
||||
|
||||
void ADT_FillModelData(const uint8* data,std::set<std::string>& st)
|
||||
{
|
||||
ADT_ExportStringSetByOffset(data,OFFSET_MODELS,st,"DIMM");
|
||||
}
|
||||
|
||||
@ -25,9 +25,5 @@ public:
|
||||
uint32 _version;
|
||||
};
|
||||
|
||||
void ADT_ExportStringSetByOffset(const uint8*, uint32, std::set<std::string>&, char*);
|
||||
void ADT_FillTextureData(const uint8*,std::set<std::string>&);
|
||||
void ADT_FillWMOData(const uint8*,std::set<std::string>&);
|
||||
void ADT_FillModelData(const uint8*,std::set<std::string>&);
|
||||
|
||||
#endif
|
||||
|
||||
@ -26,6 +26,7 @@ void MapTile::ImportFromADT(ADTFile *adt)
|
||||
_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.xbase; // here converting it to (x/y) on ground and basehight as actual height.
|
||||
_chunks[ch].basey = adt->_chunks[ch].hdr.ybase; // strange coords they use... :S
|
||||
_chunks[ch].lqheight = adt->_chunks[ch].waterlevel;
|
||||
uint32 fcnt=0, rcnt=0;
|
||||
while(true) //9*9 + 8*8
|
||||
{
|
||||
@ -42,6 +43,10 @@ void MapTile::ImportFromADT(ADTFile *adt)
|
||||
fcnt++;
|
||||
}
|
||||
}
|
||||
for(uint32 i = 0; i < 81; i++)
|
||||
{
|
||||
_chunks[ch].hmap_lq[i] = adt->_chunks[ch].lqvertex[i].h;
|
||||
}
|
||||
}
|
||||
_xbase = _chunks[0].basex;
|
||||
_ybase = _chunks[0].basey;
|
||||
|
||||
@ -18,7 +18,8 @@ public:
|
||||
float hmap_rough[9*9];
|
||||
float hmap_fine[8*8];
|
||||
float hmap[17*17]; // combined rough and fine hmap
|
||||
float basex,basey,baseheight;
|
||||
float basex,basey,baseheight,lqheight;
|
||||
float hmap_lq[9*9]; // liquid (water, lava) height map
|
||||
//... TODO: implement the rest of this
|
||||
};
|
||||
|
||||
|
||||
80
src/shared/ProgressBar.cpp
Normal file
80
src/shared/ProgressBar.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ProgressBar.h"
|
||||
|
||||
barGoLink::~barGoLink()
|
||||
{
|
||||
printf( "\n" );
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
barGoLink::barGoLink( int row_count, bool fast_upd )
|
||||
{
|
||||
rec_no = 0;
|
||||
rec_pos = 0;
|
||||
indic_len = 50;
|
||||
num_rec = row_count;
|
||||
fast_update = fast_upd;
|
||||
empty = " ";
|
||||
#ifdef _WIN32
|
||||
full = "\x3D";
|
||||
#else
|
||||
full = "*";
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
printf( "\x3D" );
|
||||
#else
|
||||
printf( "[" );
|
||||
#endif
|
||||
for ( int i = 0; i < indic_len; i++ ) printf( empty );
|
||||
#ifdef _WIN32
|
||||
printf( "\x3D 0%%\r\x3D" );
|
||||
#else
|
||||
printf( "] 0%%\r[" );
|
||||
#endif
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void barGoLink::step( void )
|
||||
{
|
||||
int i, n;
|
||||
|
||||
if ( num_rec == 0 ) return;
|
||||
++rec_no;
|
||||
n = rec_no * indic_len / num_rec;
|
||||
if ( fast_update || (n != rec_pos) )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
printf( "\r\x3D" );
|
||||
#else
|
||||
printf( "\r[" );
|
||||
#endif
|
||||
for ( i = 0; i < n; i++ ) printf( full );
|
||||
for ( ; i < indic_len; i++ ) printf( empty );
|
||||
float percent = (((float)n/(float)indic_len)*100);
|
||||
#ifdef _WIN32
|
||||
printf( "\x3D %i%% (%i/%i)\r\x3D", (int)percent, rec_no, num_rec);
|
||||
#else
|
||||
printf( "] %i%% (%i/%i)\r[", (int)percent, rec_no, num_rec);
|
||||
#endif
|
||||
fflush(stdout);
|
||||
|
||||
rec_pos = n;
|
||||
}
|
||||
}
|
||||
40
src/shared/ProgressBar.h
Normal file
40
src/shared/ProgressBar.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef MANGOSSERVER_PROGRESSBAR_H
|
||||
#define MANGOSSERVER_PROGRESSBAR_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class barGoLink
|
||||
{
|
||||
char const * empty;
|
||||
char const * full;
|
||||
|
||||
int rec_no;
|
||||
int rec_pos;
|
||||
int num_rec;
|
||||
int indic_len;
|
||||
bool fast_update;
|
||||
|
||||
public:
|
||||
|
||||
void step( void );
|
||||
barGoLink( int, bool );
|
||||
~barGoLink();
|
||||
};
|
||||
#endif
|
||||
@ -270,30 +270,31 @@ enum ItemDisplayInfoEnum
|
||||
ITEMDISPLAYINFO_NAME_L = 3, // (internal name?)
|
||||
ITEMDISPLAYINFO_NAME_R = 4, // (internal name?)
|
||||
ITEMDISPLAYINFO_ICON = 5, // icon filename
|
||||
ITEMDISPLAYINFO_FLAG1 = 6, // must be some kind of flag. 0 - 5.
|
||||
ITEMDISPLAYINFO_FLAG2 = 7, // some flag? 0, 1 or 2.
|
||||
ITEMDISPLAYINFO_FLAG3 = 8, // some flag? 0 or 1.
|
||||
ITEMDISPLAYINFO_FLAG4 = 9, // some flag? 0, 1 or 2.
|
||||
ITEMDISPLAYINFO_FLAG5 = 10, // some flag? mostly 0, sometimes other values (for ex. polearms have 4081 ?!)
|
||||
ITEMDISPLAYINFO_FLAGS = 11, // these is NOT the inventorytype...
|
||||
ITEMDISPLAYINFO_HELM1 = 12, // only set if model is a helm. might be related to hair/ears/traits showing on or off.
|
||||
ITEMDISPLAYINFO_HELM2 = 13, // ^ same.
|
||||
ITEMDISPLAYINFO_AU = 14, // the following fields contain strings that end with AU, AL, HA, TU, etc.
|
||||
ITEMDISPLAYINFO_AL = 15, // sometimes they are set, sometimes not.
|
||||
ITEMDISPLAYINFO_HA = 16,
|
||||
ITEMDISPLAYINFO_TU = 17,
|
||||
ITEMDISPLAYINFO_TL = 18,
|
||||
ITEMDISPLAYINFO_LU = 19,
|
||||
ITEMDISPLAYINFO_LL = 20,
|
||||
ITEMDISPLAYINFO_FO = 21,
|
||||
ITEMDISPLAYINFO_UNK = 22, // mostly 0. quite sure this is not a string.
|
||||
ITEMDISPLAYINFO_GEOSET_1 = 6, // Geoset, which M2 submeshes this item will cover when equipped, depeding on type
|
||||
ITEMDISPLAYINFO_GEOSET_2 = 7,
|
||||
ITEMDISPLAYINFO_GEOSET_3 = 8,
|
||||
ITEMDISPLAYINFO_GEOSET_4 = 9, // some flag? 0, 1 or 2.
|
||||
ITEMDISPLAYINFO_FLAG1 = 10, // some flag? mostly 0, sometimes other values (for ex. polearms have 4081 ?!)
|
||||
ITEMDISPLAYINFO_ITEMGROUPSOUND = 11, // these is NOT the inventorytype...
|
||||
ITEMDISPLAYINFO_HELM1 = 12, // reference to HelmetGeosetVisData. only set if item is a helm
|
||||
ITEMDISPLAYINFO_HELM2 = 13, // ^ - (this ID points to a nearer specification which face parts are covered by a helm)
|
||||
// -- the following fields store texture names for different body parts
|
||||
ITEMDISPLAYINFO_AU = 14, // arm upper
|
||||
ITEMDISPLAYINFO_AL = 15, // arm lower
|
||||
ITEMDISPLAYINFO_HA = 16, // hand
|
||||
ITEMDISPLAYINFO_TU = 17, // torso upper
|
||||
ITEMDISPLAYINFO_TL = 18, // torso lower
|
||||
ITEMDISPLAYINFO_LU = 19, // leg upper
|
||||
ITEMDISPLAYINFO_LL = 20, // leg lower
|
||||
ITEMDISPLAYINFO_FO = 21, // foot
|
||||
ITEMDISPLAYINFO_VISUAL = 22, // reference to ItemVisuals: specifies the ID of up to 5 glow effects
|
||||
|
||||
ITEMDISPLAYINFO_END = 23
|
||||
};
|
||||
|
||||
static const char *ItemDisplayInfoFieldNames[] = {
|
||||
"","model_l","model_r","name_l","name_r","icon","flag1","flag2","flag3","flag4", // 0-9
|
||||
"flag5","flags","helm1","helm2","AU","AL","HA","TU","TL","LU", // 10-19
|
||||
"","model_l","model_r","tex_l","tex_r","icon","geo1","geo2","geo3","geo4", // 0-9
|
||||
"flag1","sound","helm1","helm2","AU","AL","HA","TU","TL","LU", // 10-19
|
||||
"LL","FO","unk", // 20-22
|
||||
""
|
||||
};
|
||||
@ -372,6 +373,40 @@ static const char *NPCSoundsFormat = {
|
||||
"iiiix"
|
||||
};
|
||||
|
||||
enum CharSectionsEnum
|
||||
{
|
||||
CHARSECTIONS_ID = 0, // the sectionID, not sure if this is a reference from/to other fields
|
||||
CHARSECTIONS_RACE_ID = 1,
|
||||
CHARSECTIONS_GENDER = 2, // 0=male, 1=female
|
||||
CHARSECTIONS_TYPE = 3, // 0=base skin, 1=face, 2=facial traits, 3=hair, 4=underwear
|
||||
CHARSECTIONS_SECTION = 4, // depends, see table below
|
||||
CHARSECTIONS_COLOR = 5, // skin/hair color
|
||||
CHARSECTIONS_TEXTURE1 = 6,
|
||||
CHARSECTIONS_TEXTURE2 = 7,
|
||||
CHARSECTIONS_TEXTURE3 = 8,
|
||||
CHARSECTIONS_IS_SPECIAL_NPC = 9, // 0=player, 1=special npc
|
||||
CHARSECTIONS_END
|
||||
};
|
||||
/*
|
||||
Type Description Section Color Texture 1 Texture 2 Texture 3
|
||||
0 Base skin - Skin color Skin texture Fur texture (Tauren only) -
|
||||
1 Face Face type Skin color Face lower texture Face upper texture -
|
||||
2 Facial hair / decoration Facial hair type Hair color Face lower texture Face upper texture -
|
||||
3 Hair Hair style Hair color Hair texture Face lower texture Face upper texture
|
||||
4 Underwear - Skin color Legs upper texture Chest upper texture -
|
||||
The textures are all overlaid on the base skin texture, according to the alpha channel in the sub textures. The texture region positions and sizes are fixed.
|
||||
*/
|
||||
|
||||
static const char *CharSectionsFieldNames[] = {
|
||||
"","race","gender","type","section","color","tex1","tex2","tex3","special", // 0-9
|
||||
""
|
||||
};
|
||||
|
||||
static const char *CharSectionsFormat = {
|
||||
"iiiiiisssi"
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -11,14 +11,18 @@
|
||||
#include "StuffExtract.h"
|
||||
#include "DBCFieldData.h"
|
||||
#include "Locale.h"
|
||||
#include "ProgressBar.h"
|
||||
|
||||
|
||||
std::map<uint32,std::string> mapNames;
|
||||
std::set<std::string> texNames;
|
||||
std::set<std::string> modelNames;
|
||||
std::set<std::string> wmoNames;
|
||||
std::set<std::string> soundFileSet;
|
||||
|
||||
// default config; SCPs are dont always
|
||||
std::set<NameAndAlt> texNames;
|
||||
std::set<NameAndAlt> modelNames;
|
||||
std::set<NameAndAlt> wmoNames;
|
||||
std::set<NameAndAlt> soundFileSet;
|
||||
|
||||
|
||||
// default config; SCPs are done always
|
||||
bool doMaps=true, doSounds=false, doTextures=false, doWmos=false, doModels=false, doMd5=true, doAutoclose=false;
|
||||
|
||||
|
||||
@ -117,7 +121,6 @@ void ProcessCmdArgs(int argc, char *argv[])
|
||||
// TODO: as soon as M2 model or WMO reading is done, extract those textures to, but independent from maps!!
|
||||
if(!doMaps)
|
||||
{
|
||||
doTextures = false;
|
||||
doWmos = false;
|
||||
}
|
||||
if(help)
|
||||
@ -146,7 +149,7 @@ void PrintHelp(void)
|
||||
printf("Use + or - to turn a feature on or off.\n");
|
||||
printf("Features are:\n");
|
||||
printf("maps - map extraction\n");
|
||||
printf("textures - extract textures (requires maps extraction, for now)\n");
|
||||
printf("textures - extract textures\n");
|
||||
printf("wmos - extract map WMOs (requires maps extraction)\n");
|
||||
printf("models - extract models\n");
|
||||
printf("sounds - extract sound files (wav/mp3)\n");
|
||||
@ -250,9 +253,9 @@ bool ConvertDBC(void)
|
||||
{
|
||||
std::map<uint8,std::string> racemap; // needed to extract other dbc files correctly
|
||||
SCPStorageMap EmoteDataStorage,RaceDataStorage,SoundDataStorage,MapDataStorage,ZoneDataStorage,ItemDisplayInfoStorage,
|
||||
CreatureModelStorage,CreatureDisplayInfoStorage,NPCSoundStorage; // will store the converted data from dbc files
|
||||
CreatureModelStorage,CreatureDisplayInfoStorage,NPCSoundStorage,CharSectionStorage; // will store the converted data from dbc files
|
||||
DBCFile EmotesText,EmotesTextData,EmotesTextSound,ChrRaces,SoundEntries,Map,AreaTable,ItemDisplayInfo,
|
||||
CreatureModelData,CreatureDisplayInfo,NPCSounds;
|
||||
CreatureModelData,CreatureDisplayInfo,NPCSounds,CharSections;
|
||||
printf("Opening DBC archive...\n");
|
||||
MPQHelper mpq("dbc");
|
||||
|
||||
@ -268,6 +271,7 @@ bool ConvertDBC(void)
|
||||
CreatureModelData.openmem(mpq.ExtractFile("DBFilesClient\\CreatureModelData.dbc"));
|
||||
CreatureDisplayInfo.openmem(mpq.ExtractFile("DBFilesClient\\CreatureDisplayInfo.dbc"));
|
||||
NPCSounds.openmem(mpq.ExtractFile("DBFilesClient\\NPCSounds.dbc"));
|
||||
CharSections.openmem(mpq.ExtractFile("DBFilesClient\\CharSections.dbc"));
|
||||
//...
|
||||
printf("DBC files opened.\n");
|
||||
//...
|
||||
@ -361,7 +365,7 @@ bool ConvertDBC(void)
|
||||
|
||||
// fill up file storage. not necessary if we dont want to extract sounds
|
||||
if(doSounds && field >= SOUNDENTRY_FILE_1 && field <= SOUNDENTRY_FILE_10)
|
||||
soundFileSet.insert(path + value);
|
||||
soundFileSet.insert(NameAndAlt(path + value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -406,6 +410,7 @@ bool ConvertDBC(void)
|
||||
{
|
||||
if(strlen(ItemDisplayInfoFieldNames[field]))
|
||||
{
|
||||
// TODO: need to get
|
||||
std::string value = AutoGetDataString(it,ItemDisplayInfoFormat,field);
|
||||
if(value.size()) // only store if not null
|
||||
ItemDisplayInfoStorage[id].push_back(std::string(ItemDisplayInfoFieldNames[field]) + "=" + value);
|
||||
@ -425,7 +430,7 @@ bool ConvertDBC(void)
|
||||
if(value.size()) // only store if not null
|
||||
{
|
||||
if(doModels)
|
||||
modelNames.insert(value); // we need to extract model later, store it
|
||||
modelNames.insert(NameAndAlt(value)); // we need to extract model later, store it
|
||||
std::string fn = _PathToFileName(value);
|
||||
if(stricmp(fn.c_str()+fn.length()-4, "mdx"))
|
||||
fn = fn.substr(0,fn.length()-3) + "m2";
|
||||
@ -465,6 +470,41 @@ bool ConvertDBC(void)
|
||||
}
|
||||
}
|
||||
|
||||
printf("charsections..");
|
||||
for(DBCFile::Iterator it = CharSections.begin(); it != CharSections.end(); ++it)
|
||||
{
|
||||
uint32 id = it->getUInt(CHARSECTIONS_ID);
|
||||
for(uint32 field=CHARSECTIONS_ID; field < CHARSECTIONS_END; field++)
|
||||
{
|
||||
if(strlen(CharSectionsFieldNames[field]))
|
||||
{
|
||||
std::string value = AutoGetDataString(it,CharSectionsFormat,field);
|
||||
if(value.size()) // only store if not null
|
||||
{
|
||||
// ok we have a little problem here:
|
||||
// some textures used for different races have the same file name, but we are storing them all
|
||||
// in one directory. Texture path format is: "Character\<race>\<texture>
|
||||
// so we have to use good names to store all textures without overwriting each other
|
||||
if(field >= CHARSECTIONS_TEXTURE1 && field <= CHARSECTIONS_TEXTURE3)
|
||||
{
|
||||
char buf[100];
|
||||
sprintf(buf,"charsection_%u_%u_%u_%u_%u_%u.blp",
|
||||
it->getUInt(CHARSECTIONS_RACE_ID),
|
||||
it->getUInt(CHARSECTIONS_GENDER),
|
||||
it->getUInt(CHARSECTIONS_TYPE),
|
||||
it->getUInt(CHARSECTIONS_SECTION),
|
||||
it->getUInt(CHARSECTIONS_COLOR),
|
||||
field - CHARSECTIONS_TEXTURE1); // texture ID
|
||||
texNames.insert(NameAndAlt(value,buf));
|
||||
value = buf;
|
||||
|
||||
}
|
||||
CharSectionStorage[id].push_back(std::string(CharSectionsFieldNames[field]) + "=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//...
|
||||
@ -483,6 +523,7 @@ bool ConvertDBC(void)
|
||||
printf("creaturemodeldata.."); OutSCP(SCPDIR "/creaturemodeldata.scp",CreatureModelStorage,"creaturemodeldata");
|
||||
printf("creaturedisplayinfo.."); OutSCP(SCPDIR "/creaturedisplayinfo.scp",CreatureDisplayInfoStorage,"creaturedisplayinfo");
|
||||
printf("npcsound.."); OutSCP(SCPDIR "/npcsound.scp",NPCSoundStorage,"npcsound");
|
||||
printf("charsections.."); OutSCP(SCPDIR "/charsections.scp",CharSectionStorage,"charsections");
|
||||
//...
|
||||
printf("DONE!\n");
|
||||
|
||||
@ -579,6 +620,7 @@ void ExtractMaps(void)
|
||||
|
||||
void ExtractMapDependencies(void)
|
||||
{
|
||||
barGoLink *bar;
|
||||
printf("\nExtracting map dependencies...\n\n");
|
||||
printf("- Preparing to read MPQ arcives...\n");
|
||||
MPQHelper mpqmodel("model");
|
||||
@ -588,124 +630,149 @@ void ExtractMapDependencies(void)
|
||||
std::string pathtex = path + "/texture";
|
||||
std::string pathmodel = path + "/model";
|
||||
std::string pathwmo = path + "/wmo";
|
||||
std::string mpqfn,realfn;
|
||||
std::string mpqfn,realfn,altfn;
|
||||
MD5FileMap md5Tex, md5Wmo, md5Model;
|
||||
CreateDir(pathtex.c_str());
|
||||
CreateDir(pathmodel.c_str());
|
||||
CreateDir(pathwmo.c_str());
|
||||
uint32 wmosdone=0,texdone=0,mdone=0;
|
||||
|
||||
for(std::set<std::string>::iterator i = texNames.begin(); i != texNames.end(); i++)
|
||||
if(doTextures)
|
||||
{
|
||||
mpqfn = *i;
|
||||
if(!mpqtex.FileExists((char*)mpqfn.c_str()))
|
||||
continue;
|
||||
realfn = pathtex + "/" + _PathToFileName(mpqfn);
|
||||
std::fstream fh;
|
||||
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||
if(fh.is_open())
|
||||
printf("Extracting textures...\n");
|
||||
bar = new barGoLink(texNames.size(), true);
|
||||
for(std::set<NameAndAlt>::iterator i = texNames.begin(); i != texNames.end(); i++)
|
||||
{
|
||||
ByteBuffer& bb = mpqtex.ExtractFile((char*)mpqfn.c_str());
|
||||
fh.write((const char*)bb.contents(),bb.size());
|
||||
if(doMd5)
|
||||
{
|
||||
MD5Hash h;
|
||||
h.Update((uint8*)bb.contents(), bb.size());
|
||||
h.Finalize();
|
||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||
md5Tex[_PathToFileName(realfn)] = md5ptr;
|
||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||
}
|
||||
texdone++;
|
||||
printf("- textures... %u\r",texdone);
|
||||
}
|
||||
else
|
||||
printf("Could not write texture %s\n",realfn.c_str());
|
||||
fh.close();
|
||||
}
|
||||
printf("\n");
|
||||
if(texNames.size() && doTextures)
|
||||
OutMD5((char*)pathtex.c_str(),md5Tex);
|
||||
|
||||
for(std::set<std::string>::iterator i = modelNames.begin(); i != modelNames.end(); i++)
|
||||
{
|
||||
mpqfn = *i;
|
||||
// no idea what bliz intended by this. the ADT files refer to .mdx models,
|
||||
// however there are only .m2 files in the MPQ archives.
|
||||
// so we just need to check if there is a .m2 file instead of the .mdx file, and load that one.
|
||||
if(!mpqmodel.FileExists((char*)mpqfn.c_str()))
|
||||
{
|
||||
std::string alt = i->substr(0,i->length()-3) + "m2";
|
||||
DEBUG(printf("MDX model not found, trying M2 file."));
|
||||
if(!mpqmodel.FileExists((char*)alt.c_str()))
|
||||
{
|
||||
DEBUG(printf(" fail.\n"));
|
||||
bar->step();
|
||||
mpqfn = i->name;
|
||||
altfn = i->alt;
|
||||
if(altfn.empty())
|
||||
altfn = mpqfn;
|
||||
if(!mpqtex.FileExists((char*)mpqfn.c_str()))
|
||||
continue;
|
||||
realfn = pathtex + "/" + _PathToFileName(altfn);
|
||||
std::fstream fh;
|
||||
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||
if(fh.is_open())
|
||||
{
|
||||
ByteBuffer& bb = mpqtex.ExtractFile((char*)mpqfn.c_str());
|
||||
fh.write((const char*)bb.contents(),bb.size());
|
||||
if(doMd5)
|
||||
{
|
||||
MD5Hash h;
|
||||
h.Update((uint8*)bb.contents(), bb.size());
|
||||
h.Finalize();
|
||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||
md5Tex[_PathToFileName(realfn)] = md5ptr;
|
||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||
}
|
||||
texdone++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mpqfn = alt;
|
||||
DEBUG(printf(" success.\n"));
|
||||
}
|
||||
printf("Could not write texture %s\n",realfn.c_str());
|
||||
fh.close();
|
||||
}
|
||||
realfn = pathmodel + "/" + _PathToFileName(mpqfn);
|
||||
std::fstream fh;
|
||||
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||
if(fh.is_open())
|
||||
{
|
||||
ByteBuffer& bb = mpqmodel.ExtractFile((char*)mpqfn.c_str());
|
||||
fh.write((const char*)bb.contents(),bb.size());
|
||||
if(doMd5)
|
||||
{
|
||||
MD5Hash h;
|
||||
h.Update((uint8*)bb.contents(), bb.size());
|
||||
h.Finalize();
|
||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||
md5Model[_PathToFileName(realfn)] = md5ptr;
|
||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||
}
|
||||
mdone++;
|
||||
printf("- models... %u\r",mdone);
|
||||
}
|
||||
else
|
||||
printf("Could not write model %s\n",realfn.c_str());
|
||||
fh.close();
|
||||
printf("\n");
|
||||
if(texNames.size())
|
||||
OutMD5((char*)pathtex.c_str(),md5Tex);
|
||||
delete bar;
|
||||
}
|
||||
printf("\n");
|
||||
if(modelNames.size() && doModels)
|
||||
OutMD5((char*)pathmodel.c_str(),md5Model);
|
||||
|
||||
for(std::set<std::string>::iterator i = wmoNames.begin(); i != wmoNames.end(); i++)
|
||||
if(doModels)
|
||||
{
|
||||
mpqfn = *i;
|
||||
if(!mpqwmo.FileExists((char*)mpqfn.c_str()))
|
||||
continue;
|
||||
realfn = pathwmo + "/" + _PathToFileName(mpqfn);
|
||||
std::fstream fh;
|
||||
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||
if(fh.is_open())
|
||||
printf("Extracting models...\n");
|
||||
bar = new barGoLink(modelNames.size(),true);
|
||||
for(std::set<NameAndAlt>::iterator i = modelNames.begin(); i != modelNames.end(); i++)
|
||||
{
|
||||
ByteBuffer& bb = mpqwmo.ExtractFile((char*)mpqfn.c_str());
|
||||
fh.write((const char*)bb.contents(),bb.size());
|
||||
if(doMd5)
|
||||
bar->step();
|
||||
mpqfn = i->name;
|
||||
// no idea what bliz intended by this. the ADT files refer to .mdx models,
|
||||
// however there are only .m2 files in the MPQ archives.
|
||||
// so we just need to check if there is a .m2 file instead of the .mdx file, and load that one.
|
||||
if(!mpqmodel.FileExists((char*)mpqfn.c_str()))
|
||||
{
|
||||
MD5Hash h;
|
||||
h.Update((uint8*)bb.contents(), bb.size());
|
||||
h.Finalize();
|
||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||
md5Wmo[_PathToFileName(realfn)] = md5ptr;
|
||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||
std::string alt = mpqfn.substr(0,mpqfn.length()-3) + "m2";
|
||||
if(!mpqmodel.FileExists((char*)alt.c_str()))
|
||||
{
|
||||
printf("Failed to extract model: '%s'\n",alt.c_str());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
mpqfn = alt;
|
||||
}
|
||||
}
|
||||
wmosdone++;
|
||||
printf("- WMOs... %u\r",wmosdone);
|
||||
altfn = i->alt;
|
||||
if(altfn.empty())
|
||||
altfn = mpqfn;
|
||||
realfn = pathmodel + "/" + _PathToFileName(altfn);
|
||||
std::fstream fh;
|
||||
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||
if(fh.is_open())
|
||||
{
|
||||
ByteBuffer& bb = mpqmodel.ExtractFile((char*)mpqfn.c_str());
|
||||
fh.write((const char*)bb.contents(),bb.size());
|
||||
if(doMd5)
|
||||
{
|
||||
MD5Hash h;
|
||||
h.Update((uint8*)bb.contents(), bb.size());
|
||||
h.Finalize();
|
||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||
md5Model[_PathToFileName(realfn)] = md5ptr;
|
||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||
}
|
||||
mdone++;
|
||||
}
|
||||
else
|
||||
printf("Could not write model %s\n",realfn.c_str());
|
||||
fh.close();
|
||||
}
|
||||
else
|
||||
printf("Could not write WMO %s\n",realfn.c_str());
|
||||
fh.close();
|
||||
printf("\n");
|
||||
if(modelNames.size())
|
||||
OutMD5((char*)pathmodel.c_str(),md5Model);
|
||||
delete bar;
|
||||
}
|
||||
|
||||
if(doWmos)
|
||||
{
|
||||
printf("Extracting textures...\n");
|
||||
bar = new barGoLink(wmoNames.size(),true);
|
||||
for(std::set<NameAndAlt>::iterator i = wmoNames.begin(); i != wmoNames.end(); i++)
|
||||
{
|
||||
bar->step();
|
||||
mpqfn = i->name;
|
||||
altfn = i->alt;
|
||||
if(altfn.empty())
|
||||
altfn = mpqfn;
|
||||
if(!mpqwmo.FileExists((char*)mpqfn.c_str()))
|
||||
continue;
|
||||
realfn = pathwmo + "/" + _PathToFileName(altfn);
|
||||
std::fstream fh;
|
||||
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
|
||||
if(fh.is_open())
|
||||
{
|
||||
ByteBuffer& bb = mpqwmo.ExtractFile((char*)mpqfn.c_str());
|
||||
fh.write((const char*)bb.contents(),bb.size());
|
||||
if(doMd5)
|
||||
{
|
||||
MD5Hash h;
|
||||
h.Update((uint8*)bb.contents(), bb.size());
|
||||
h.Finalize();
|
||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||
md5Wmo[_PathToFileName(realfn)] = md5ptr;
|
||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||
}
|
||||
wmosdone++;
|
||||
}
|
||||
else
|
||||
printf("Could not write WMO %s\n",realfn.c_str());
|
||||
fh.close();
|
||||
}
|
||||
printf("\n");
|
||||
if(wmoNames.size())
|
||||
OutMD5((char*)pathwmo.c_str(),md5Wmo);
|
||||
delete bar;
|
||||
}
|
||||
printf("\n");
|
||||
if(wmoNames.size() && doWmos)
|
||||
OutMD5((char*)pathwmo.c_str(),md5Wmo);
|
||||
|
||||
}
|
||||
|
||||
@ -716,21 +783,24 @@ void ExtractSoundFiles(void)
|
||||
printf("\nExtracting game audio files, %u found in DBC...\n",soundFileSet.size());
|
||||
CreateDir(SOUNDDIR);
|
||||
MPQHelper smpq("sound");
|
||||
std::string outfn;
|
||||
for(std::set<std::string>::iterator i = soundFileSet.begin(); i != soundFileSet.end(); i++)
|
||||
std::string outfn, altfn;
|
||||
barGoLink bar(soundFileSet.size(),true);
|
||||
for(std::set<NameAndAlt>::iterator i = soundFileSet.begin(); i != soundFileSet.end(); i++)
|
||||
{
|
||||
if(!smpq.FileExists((char*)(*i).c_str()))
|
||||
bar.step();
|
||||
if(!smpq.FileExists((char*)i->name.c_str()))
|
||||
{
|
||||
DEBUG( printf("MPQ: File not found: '%s'\n",(*i).c_str()) );
|
||||
DEBUG( printf("MPQ: File not found: '%s'\n",i->name.c_str()) );
|
||||
continue;
|
||||
}
|
||||
altfn = i->alt.empty() ? _PathToFileName(i->name) : i->alt;
|
||||
|
||||
outfn = std::string(SOUNDDIR) + "/" + _PathToFileName(*i);
|
||||
outfn = std::string(SOUNDDIR) + "/" + altfn;
|
||||
std::fstream fh;
|
||||
fh.open(outfn.c_str(), std::ios_base::out | std::ios_base::binary);
|
||||
if(fh.is_open())
|
||||
{
|
||||
ByteBuffer& bb = smpq.ExtractFile((char*)(*i).c_str());
|
||||
ByteBuffer& bb = smpq.ExtractFile((char*)i->name.c_str());
|
||||
if(bb.size())
|
||||
{
|
||||
fh.write((const char*)bb.contents(),bb.size());
|
||||
@ -740,11 +810,10 @@ void ExtractSoundFiles(void)
|
||||
h.Update((uint8*)bb.contents(), bb.size());
|
||||
h.Finalize();
|
||||
uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH];
|
||||
md5data[_PathToFileName(*i)] = md5ptr;
|
||||
md5data[altfn] = md5ptr;
|
||||
memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH);
|
||||
}
|
||||
done++;
|
||||
printf("- %u files done.\r",done);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -757,6 +826,44 @@ void ExtractSoundFiles(void)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void ADT_ExportStringSetByOffset(const uint8* data, uint32 off, std::set<NameAndAlt>& st, char* stop)
|
||||
{
|
||||
data += ((uint32*)data)[off]; // seek to correct absolute offset
|
||||
data += 28; // move ptr to real start of data
|
||||
uint32 offset=0;
|
||||
std::string s;
|
||||
char c;
|
||||
while(memcmp(data+offset,stop,4))
|
||||
{
|
||||
c = data[offset];
|
||||
if(!c)
|
||||
{
|
||||
if(s.length())
|
||||
{
|
||||
DEBUG(printf("DEP: %s\n",s.c_str()));
|
||||
st.insert(NameAndAlt(s));
|
||||
s.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
s += c;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
void ADT_FillTextureData(const uint8* data,std::set<NameAndAlt>& st)
|
||||
{
|
||||
ADT_ExportStringSetByOffset(data,OFFSET_TEXTURES,st,"XDMM");
|
||||
}
|
||||
|
||||
void ADT_FillWMOData(const uint8* data,std::set<NameAndAlt>& st)
|
||||
{
|
||||
ADT_ExportStringSetByOffset(data,OFFSET_WMOS,st,"DIWM");
|
||||
}
|
||||
|
||||
void ADT_FillModelData(const uint8* data,std::set<NameAndAlt>& st)
|
||||
{
|
||||
ADT_ExportStringSetByOffset(data,OFFSET_MODELS,st,"DIMM");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -14,6 +14,20 @@
|
||||
typedef std::map< uint32,std::list<std::string> > SCPStorageMap;
|
||||
typedef std::map<std::string,uint8*> MD5FileMap;
|
||||
|
||||
// this struct is used to resolve conflicting names when extracting archives.
|
||||
// the problem is that some files stored in different folders in mpq archives will be extracted into one folder,
|
||||
// overwriting each other.
|
||||
// thus thats resolved by putting the mpq file name into `name` and the name it should be saved as in `alt`.
|
||||
// leave `empty` to use filename specified in `name`
|
||||
struct NameAndAlt
|
||||
{
|
||||
NameAndAlt(std::string a) { name=a; }
|
||||
NameAndAlt(std::string a, std::string b) { name=a; alt=b; }
|
||||
bool operator<(NameAndAlt const & other) const { return name < other.name; } // required to be used in std::set
|
||||
std::string name;
|
||||
std::string alt;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
void ProcessCmdArgs(int argc, char *argv[]);
|
||||
void PrintConfig(void);
|
||||
@ -25,4 +39,10 @@ void ExtractMaps(void);
|
||||
void ExtractMapDependencies(void);
|
||||
void ExtractSoundFiles(void);
|
||||
|
||||
|
||||
void ADT_ExportStringSetByOffset(const uint8*, uint32, std::set<NameAndAlt>&, char*);
|
||||
void ADT_FillTextureData(const uint8*,std::set<NameAndAlt>&);
|
||||
void ADT_FillWMOData(const uint8*,std::set<NameAndAlt>&);
|
||||
void ADT_FillModelData(const uint8*,std::set<NameAndAlt>&);
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user