summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2007-03-11 19:59:55 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2007-03-11 19:59:55 +0000
commitfc63e88f869919a8b035a5c41db8d05626526bde (patch)
tree8f1928d082ebbffc549c712a3f406c2141f43e01 /src
parent7b0f0ec315e66dcbdda58ada8b09a59bc5dcf6c9 (diff)
downloadmana-fc63e88f869919a8b035a5c41db8d05626526bde.tar.gz
mana-fc63e88f869919a8b035a5c41db8d05626526bde.tar.bz2
mana-fc63e88f869919a8b035a5c41db8d05626526bde.tar.xz
mana-fc63e88f869919a8b035a5c41db8d05626526bde.zip
Merged 0.0 changes from revision 3065 to 3177 to trunk.
Diffstat (limited to 'src')
-rw-r--r--src/being.cpp35
-rw-r--r--src/being.h24
-rw-r--r--src/engine.cpp11
-rw-r--r--src/engine.h7
-rw-r--r--src/gui/menuwindow.cpp25
-rw-r--r--src/gui/register.cpp1
-rw-r--r--src/gui/updatewindow.cpp131
-rw-r--r--src/gui/updatewindow.h64
-rw-r--r--src/gui/viewport.cpp14
-rw-r--r--src/localplayer.h11
-rw-r--r--src/log.cpp17
-rw-r--r--src/logindata.h1
-rw-r--r--src/main.cpp56
-rw-r--r--src/main.h1
-rw-r--r--src/map.cpp4
-rw-r--r--src/monster.cpp22
-rw-r--r--src/monster.h15
-rw-r--r--src/net/beinghandler.cpp33
-rw-r--r--src/resources/resourcemanager.cpp27
-rw-r--r--src/resources/resourcemanager.h8
20 files changed, 330 insertions, 177 deletions
diff --git a/src/being.cpp b/src/being.cpp
index 33ee7e7a..e4a1e9fc 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -33,6 +33,7 @@
#include "log.h"
#include "map.h"
+#include "resources/resourcemanager.h"
#include "resources/spriteset.h"
#include "gui/gui.h"
@@ -40,12 +41,8 @@
#include "utils/dtor.h"
#include "utils/tostring.h"
-extern Spriteset *emotionset;
-
-PATH_NODE::PATH_NODE(unsigned short x, unsigned short y):
- x(x), y(y)
-{
-}
+int Being::instances = 0;
+Spriteset *Being::emotionset = NULL;
Being::Being(Uint16 id, Uint16 job, Map *map):
mJob(job),
@@ -70,6 +67,16 @@ Being::Being(Uint16 id, Uint16 job, Map *map):
mEquipmentSpriteIDs(VECTOREND_SPRITE, 0)
{
setMap(map);
+
+ if (instances == 0)
+ {
+ // Load the emotion set
+ ResourceManager *rm = ResourceManager::getInstance();
+ emotionset = rm->getSpriteset("graphics/sprites/emotions.png", 30, 32);
+ if (!emotionset) logger->error("Unable to load emotions spriteset!");
+ }
+
+ instances++;
}
Being::~Being()
@@ -77,6 +84,14 @@ Being::~Being()
std::for_each(mSprites.begin(), mSprites.end(), make_dtor(mSprites));
clearPath();
setMap(NULL);
+
+ instances--;
+
+ if (instances == 0)
+ {
+ emotionset->decRef();
+ emotionset = NULL;
+ }
}
void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY)
@@ -275,13 +290,19 @@ Being::setSpeech(const std::string &text, Uint32 time)
}
void
-Being::setDamage(Sint16 amount, Uint32 time)
+Being::takeDamage(int amount)
{
mDamage = amount ? toString(amount) : "miss";
mDamageTime = 300;
}
void
+Being::handleAttack()
+{
+ setAction(Being::ATTACK);
+}
+
+void
Being::setMap(Map *map)
{
// Remove sprite from potential previous map
diff --git a/src/being.h b/src/being.h
index 3c6b14c6..c3cba247 100644
--- a/src/being.h
+++ b/src/being.h
@@ -43,12 +43,17 @@ class Map;
class Graphics;
class Spriteset;
+/**
+ * A position along a being's path.
+ */
struct PATH_NODE
{
/**
* Constructor.
*/
- PATH_NODE(unsigned short x, unsigned short y);
+ PATH_NODE(unsigned short x, unsigned short y):
+ x(x), y(y)
+ { }
unsigned short x;
unsigned short y;
@@ -148,13 +153,19 @@ class Being : public Sprite
void setSpeech(const std::string &text, Uint32 time);
/**
- * Puts a damage bubble above this being for the specified amount
- * of time.
+ * Puts a damage bubble above this being for the specified amount of
+ * time.
*
* @param amount The amount of damage.
- * @param time The amount of time the text should stay in milliseconds.
*/
- void setDamage(Sint16 amount, Uint32 time);
+ virtual void
+ takeDamage(int amount);
+
+ /**
+ * Handles an attack of another being by this being.
+ */
+ virtual void
+ handleAttack();
/**
* Returns the name of the being.
@@ -384,6 +395,9 @@ class Being : public Sprite
Sint16 mStepX, mStepY;
Uint16 mStepTime;
+
+ static int instances; /**< Number of Being instances */
+ static Spriteset *emotionset; /**< Emoticons used by beings */
};
#endif
diff --git a/src/engine.cpp b/src/engine.cpp
index d2ce6d6f..a3097d49 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -53,20 +53,9 @@ extern Minimap *minimap;
char itemCurrenyQ[10] = "0";
-Spriteset *emotionset;
-
Engine::Engine():
mCurrentMap(NULL)
{
- // Load the emotion set
- ResourceManager *resman = ResourceManager::getInstance();
- emotionset = resman->getSpriteset("graphics/sprites/emotions.png", 30, 32);
- if (!emotionset) logger->error("Unable to load emotions spriteset!");
-}
-
-Engine::~Engine()
-{
- emotionset->decRef();
}
void Engine::changeMap(const std::string &mapPath)
diff --git a/src/engine.h b/src/engine.h
index b16b7c13..161a1e63 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -30,7 +30,7 @@ class Map;
/**
* Game engine. Actually hardly does anything anymore except keeping track of
- * the current map and loading the emotes.
+ * the current map.
*/
class Engine
{
@@ -41,11 +41,6 @@ class Engine
Engine();
/**
- * Destructor.
- */
- ~Engine();
-
- /**
* Returns the currently active map.
*/
Map *getCurrentMap() { return mCurrentMap; }
diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp
index a5b5c99e..943cc6f0 100644
--- a/src/gui/menuwindow.cpp
+++ b/src/gui/menuwindow.cpp
@@ -30,8 +30,11 @@
#include "button.h"
#include "windowcontainer.h"
-extern Window *setupWindow, *inventoryWindow, *equipmentWindow,
- *skillDialog, *statusWindow;
+extern Window *setupWindow;
+extern Window *inventoryWindow;
+extern Window *equipmentWindow;
+extern Window *skillDialog;
+extern Window *statusWindow;
namespace {
struct MenuWindowListener : public gcn::ActionListener
@@ -52,9 +55,14 @@ MenuWindow::MenuWindow():
setTitleBarHeight(0);
// Buttons
- // ------------
- const char *buttonNames[] = {
- "Status", "Equipment", "Inventory", "Skills", "Setup", 0
+ const char *buttonNames[] =
+ {
+ "Status",
+ "Equipment",
+ "Inventory",
+ "Skills",
+ "Setup",
+ 0
};
int x = 0, y = 3, h = 0;
@@ -67,7 +75,11 @@ MenuWindow::MenuWindow():
h = btn->getHeight();
}
- setDefaultSize((windowContainer->getWidth() - x - 2), 0, x, (y + h));
+ setContentSize(x - 3, h);
+ setDefaultSize(windowContainer->getWidth() - getWidth() - 1,
+ 0,
+ x - 3,
+ y + h);
}
void MenuWindow::draw(gcn::Graphics *graphics)
@@ -79,6 +91,7 @@ void MenuWindow::draw(gcn::Graphics *graphics)
void MenuWindowListener::action(const gcn::ActionEvent &event)
{
Window *window = NULL;
+
if (event.getId() == "Status")
{
window = statusWindow;
diff --git a/src/gui/register.cpp b/src/gui/register.cpp
index 4539e48e..be15747d 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -195,6 +195,7 @@ RegisterDialog::action(const gcn::ActionEvent &event)
mLoginData->username = mUserField->getText();
mLoginData->password = mPasswordField->getText();
mLoginData->email = mEmailField->getText();
+ mLoginData->registerLogin = true;
state = STATE_REGISTER_ATTEMPT;
}
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index fe78a27b..d8130cd3 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -46,13 +46,41 @@
#include "../resources/resourcemanager.h"
+/**
+ * Calculates the Alder-32 checksum for the given file.
+ */
+unsigned long fadler32(FILE *file)
+{
+ // Obtain file size
+ fseek(file, 0, SEEK_END);
+ long fileSize = ftell(file);
+ rewind(file);
+
+ // Calculate Adler-32 checksum
+ char *buffer = (char*) malloc(fileSize);
+ fread(buffer, 1, fileSize, file);
+ unsigned long adler = adler32(0L, Z_NULL, 0);
+ adler = adler32(adler, (Bytef*) buffer, fileSize);
+ free(buffer);
+
+ return adler;
+}
+
UpdaterWindow::UpdaterWindow():
Window("Updating..."),
- mThread(NULL), mMutex(NULL), mDownloadStatus(UPDATE_NEWS),
- mUpdateHost(""), mCurrentFile("news.txt"), mBasePath(""),
- mStoreInMemory(true), mDownloadComplete(true), mUserCancel(false),
- mDownloadedBytes(0), mMemoryBuffer(NULL),
- mCurlError(new char[CURL_ERROR_SIZE]), mLineIndex(0)
+ mThread(NULL),
+ mDownloadStatus(UPDATE_NEWS),
+ mUpdateHost(""),
+ mCurrentFile("news.txt"),
+ mCurrentChecksum(0),
+ mBasePath(""),
+ mStoreInMemory(true),
+ mDownloadComplete(true),
+ mUserCancel(false),
+ mDownloadedBytes(0),
+ mMemoryBuffer(NULL),
+ mCurlError(new char[CURL_ERROR_SIZE]),
+ mLineIndex(0)
{
mCurlError[0] = 0;
@@ -151,7 +179,7 @@ void UpdaterWindow::action(const gcn::ActionEvent &event)
}
else if (event.getId() == "play")
{
- state = STATE_LOGIN;
+ state = STATE_LOADDATA;
}
}
@@ -206,22 +234,17 @@ int UpdaterWindow::updateProgress(void *ptr,
return 0;
}
-size_t UpdaterWindow::memoryWrite(void *ptr,
- size_t size, size_t nmemb, FILE *stream)
+size_t
+UpdaterWindow::memoryWrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
UpdaterWindow *uw = reinterpret_cast<UpdaterWindow *>(stream);
size_t totalMem = size * nmemb;
- uw->mMemoryBuffer = (char*)realloc(uw->mMemoryBuffer,
- uw->mDownloadedBytes + totalMem + 1);
+ uw->mMemoryBuffer = (char*) realloc(uw->mMemoryBuffer,
+ uw->mDownloadedBytes + totalMem);
if (uw->mMemoryBuffer)
{
memcpy(&(uw->mMemoryBuffer[uw->mDownloadedBytes]), ptr, totalMem);
uw->mDownloadedBytes += totalMem;
-
- // Make sure the memory buffer is NULL terminated, because this
- // function is used to download text files that are later parsed as a
- // string.
- uw->mMemoryBuffer[uw->mDownloadedBytes] = 0;
}
return totalMem;
@@ -236,8 +259,10 @@ int UpdaterWindow::downloadThread(void *ptr)
std::string outFilename;
std::string url(uw->mUpdateHost + "/" + uw->mCurrentFile);
- while (attempts < 3 && !uw->mDownloadComplete) {
+ while (attempts < 3 && !uw->mDownloadComplete)
+ {
FILE *outfile = NULL;
+ FILE *newfile = NULL;
uw->setLabel(uw->mCurrentFile + " (0%)");
curl = curl_easy_init();
@@ -282,61 +307,67 @@ int UpdaterWindow::downloadThread(void *ptr)
uw->mDownloadStatus = UPDATE_ERROR;
switch (res)
{
- case CURLE_COULDNT_CONNECT: // give more debug info on that error
- std::cerr << "curl error " << res << " : " << uw->mCurlError << " " << url.c_str()
- << std::endl;
+ case CURLE_COULDNT_CONNECT:
+ // give more debug info on that error
+ std::cerr << "curl error " << res << ": "
+ << uw->mCurlError << " " << url.c_str()
+ << std::endl;
break;
default:
- std::cerr << "curl error " << res << " : " << uw->mCurlError << " host: " << url.c_str()
- << std::endl;
+ std::cerr << "curl error " << res << ": "
+ << uw->mCurlError << " host: " << url.c_str()
+ << std::endl;
}
}
curl_easy_cleanup(curl);
- uw->mDownloadComplete = true;
-
if (!uw->mStoreInMemory)
{
- long fileSize;
- char *buffer;
- // Obtain file size.
- fseek(outfile, 0, SEEK_END);
- fileSize = ftell(outfile);
- rewind(outfile);
- buffer = (char*)malloc(fileSize);
- fread(buffer, 1, fileSize, outfile);
- fclose(outfile);
-
- // Give the file the proper name
- std::string newName(uw->mBasePath + "/updates/" +
- uw->mCurrentFile.c_str());
-
- // Any existing file with this name is deleted first, otherwise the
- // rename will fail on Windows.
- ::remove(newName.c_str());
- ::rename(outFilename.c_str(), newName.c_str());
-
// Don't check resources2.txt checksum
if (uw->mDownloadStatus == UPDATE_RESOURCES)
{
- // Calculate Adler-32 checksum
- unsigned long adler = adler32(0L, Z_NULL, 0);
- adler = adler32(adler, (Bytef *)buffer, fileSize);
- free(buffer);
+ unsigned long adler = fadler32(outfile);
+
+ if (uw->mCurrentChecksum != adler)
+ {
+ fclose(outfile);
- if (uw->mCurrentChecksum != adler) {
- uw->mDownloadComplete = false;
// Remove the corrupted file
- ::remove(newName.c_str());
+ ::remove(outFilename.c_str());
logger->log(
"Checksum for file %s failed: (%lx/%lx)",
uw->mCurrentFile.c_str(),
adler, uw->mCurrentChecksum);
+ attempts++;
+ continue; // Bail out here to avoid the renaming
}
}
+ fclose(outfile);
+
+ // Give the file the proper name
+ std::string newName(uw->mBasePath + "/updates/" +
+ uw->mCurrentFile.c_str());
+ // Any existing file with this name is deleted first, otherwise
+ // the rename will fail on Windows.
+ ::remove(newName.c_str());
+ ::rename(outFilename.c_str(), newName.c_str());
+
+ // Check if we can open it and no errors were encountered
+ // during renaming
+ newfile = fopen(newName.c_str(), "rb");
+ if (newfile)
+ {
+ fclose(newfile);
+ uw->mDownloadComplete = true;
+ }
+ }
+ else
+ {
+ // It's stored in memory, we're done
+ uw->mDownloadComplete = true;
}
}
attempts++;
@@ -398,8 +429,8 @@ void UpdaterWindow::logic()
mCurrentFile = "resources2.txt";
mStoreInMemory = false;
- download();
mDownloadStatus = UPDATE_LIST;
+ download(); // download() changes mDownloadComplete to false
}
break;
case UPDATE_LIST:
diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h
index 8c54be27..b5f6a6df 100644
--- a/src/gui/updatewindow.h
+++ b/src/gui/updatewindow.h
@@ -89,7 +89,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener
void download();
/**
- * The tread function that download the files.
+ * The thread function that download the files.
*/
static int downloadThread(void *ptr);
@@ -115,80 +115,46 @@ class UpdaterWindow : public Window, public gcn::ActionListener
UPDATE_RESOURCES
};
- /**
- * A thread that use libcurl to download updates.
- */
+ /** A thread that use libcurl to download updates. */
SDL_Thread *mThread;
- /**
- * A mutex to protect shared data between the threads.
- */
- SDL_mutex *mMutex;
-
- /**
- * Status of the current download.
- */
+ /** Status of the current download. */
DownloadStatus mDownloadStatus;
- /**
- * Host where we get the updated files.
- */
+ /** Host where we get the updated files. */
std::string mUpdateHost;
- /**
- * The file currently downloading.
- */
+ /** The file currently downloading. */
std::string mCurrentFile;
- /**
- * The Adler32 checksum of the file currently downloading.
- */
+ /** The Adler32 checksum of the file currently downloading. */
unsigned long mCurrentChecksum;
- /**
- * Absolute path to locally save downloaded files.
- */
+ /** Absolute path to locally save downloaded files. */
std::string mBasePath;
- /**
- * A flag to know if we must write the downloaded file to a memory buffer
- * instead of a regular file.
- */
+ /** A flag to indicate whether to use a memory buffer or a regular file. */
bool mStoreInMemory;
- /**
- * Flag that show if current download is complete.
- */
+ /** Flag that show if current download is complete. */
bool mDownloadComplete;
- /**
- * Flag that show if the user has canceled the update
- */
+ /** Flag that show if the user has canceled the update. */
bool mUserCancel;
- /**
- * Byte count currently downloaded in mMemoryBuffer.
- */
+ /** Byte count currently downloaded in mMemoryBuffer. */
int mDownloadedBytes;
- /**
- * Buffer where to put downloaded file which are not stored in file system.
- */
+ /** Buffer for files downloaded to memory. */
char *mMemoryBuffer;
- /**
- * Buffer to handler human readable error provided by curl.
- */
+ /** Buffer to handler human readable error provided by curl. */
char *mCurlError;
- /**
- * List of files to download
- */
+ /** List of files to download. */
std::vector<std::string> mLines;
- /**
- * Index of the file to be downloaded
- */
+ /** Index of the file to be downloaded. */
unsigned int mLineIndex;
gcn::Label *mLabel; /**< Progress bar caption. */
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index 5f316aea..bc635cce 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -132,18 +132,22 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
mViewY = player_y;
};
- if (mMap) {
+ // Don't move camera so that the end of the map is on screen
+ int viewXmax = mMap->getWidth() * 32 - graphics->getWidth();
+ int viewYmax = mMap->getHeight() * 32 - graphics->getHeight();
+ if (mMap)
+ {
if (mViewX < 0) {
mViewX = 0;
}
if (mViewY < 0) {
mViewY = 0;
}
- if (mViewX > mMap->getWidth() * 32 - midTileX) {
- mViewX = mMap->getWidth() * 32 - midTileX;
+ if (mViewX > viewXmax) {
+ mViewX = viewXmax;
}
- if (mViewY > mMap->getHeight() * 32 - midTileY) {
- mViewY = mMap->getHeight() * 32 - midTileY;
+ if (mViewY > viewYmax) {
+ mViewY = viewYmax;
}
}
diff --git a/src/localplayer.h b/src/localplayer.h
index 980b1aff..9ce67d13 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -35,6 +35,9 @@ class FloorItem;
class Inventory;
class Item;
+/**
+ * The local player character.
+ */
class LocalPlayer : public Player
{
public:
@@ -110,9 +113,17 @@ class LocalPlayer : public Player
void setTrading(bool trading) { mTrading = trading; }
void attack();
+
Being* getTarget() const;
/**
+ * Overridden to do nothing. The attacks of the local player are
+ * displayed as soon as the player attacks, not when the server says
+ * the player does.
+ */
+ virtual void handleAttack() {}
+
+ /**
* Sets the target being of the player.
*/
void setTarget(Being* target) { mTarget = target; }
diff --git a/src/log.cpp b/src/log.cpp
index 3a3c91b8..224736bd 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -20,11 +20,13 @@
*/
#include "log.h"
+
#ifdef WIN32
- #include "utils/wingettimeofday.h"
+#include "utils/wingettimeofday.h"
#else
- #include <sys/time.h>
+#include <sys/time.h>
#endif
+
#ifdef __APPLE__
#include <Carbon/Carbon.h>
#endif
@@ -110,9 +112,14 @@ void Logger::error(const std::string &error_text)
MessageBox(NULL, error_text.c_str(), "Error", MB_ICONERROR | MB_OK);
#elif defined __APPLE__
Str255 msg;
- c2pstrcpy(msg, error_text.c_str());
- StandardAlert(kAlertStopAlert, "\pError",
- (ConstStr255Param)msg, NULL, NULL);
+ CFStringRef error;
+ error = CFStringCreateWithCString(NULL,
+ error_text.c_str(),
+ kCFStringEncodingMacRoman);
+ CFStringGetPascalString(error, msg, 255, kCFStringEncodingMacRoman);
+ StandardAlert(kAlertStopAlert,
+ "\pError",
+ (ConstStr255Param) msg, NULL, NULL);
#else
std::cerr << "Error: " << error_text << std::endl;
#endif
diff --git a/src/logindata.h b/src/logindata.h
index f9b520eb..0a01331c 100644
--- a/src/logindata.h
+++ b/src/logindata.h
@@ -37,6 +37,7 @@ struct LoginData
int session_ID2;
bool remember;
+ bool registerLogin;
void clear()
{
diff --git a/src/main.cpp b/src/main.cpp
index 1e7ae32d..aad6a68c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -36,10 +36,13 @@
#include <libxml/parser.h>
-#if (defined __USE_UNIX98 || defined __FreeBSD__)
+#if (defined __USE_UNIX98 || defined __FreeBSD__ || defined __APPLE__)
#include <cerrno>
#include <sys/stat.h>
#endif
+#if defined __APPLE__
+#include <CoreFoundation/CFBundle.h>
+#endif
#include "configuration.h"
#include "game.h"
@@ -150,7 +153,7 @@ struct Options
*/
void initHomeDir()
{
-#if !(defined __USE_UNIX98 || defined __FreeBSD__)
+#if !(defined __USE_UNIX98 || defined __FreeBSD__ || defined __APPLE__)
homeDir = ".";
#else
homeDir = std::string(PHYSFS_getUserDir()) + "/.tmw";
@@ -160,7 +163,7 @@ void initHomeDir()
(errno != EEXIST))
{
std::cout << homeDir
- << " can't be made, but it doesn't exist! Exitting."
+ << " can't be made, but it doesn't exist! Exiting."
<< std::endl;
exit(1);
}
@@ -259,7 +262,21 @@ void initEngine()
// Add the main data directory to our PhysicsFS search path
resman->addToSearchPath("data", true);
+#if defined __APPLE__
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
+ char path[PATH_MAX];
+ if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path,
+ PATH_MAX))
+ {
+ fprintf(stderr, "Can't find Resources directory\n");
+ }
+ CFRelease(resourcesURL);
+ strncat(path, "/data", PATH_MAX - 1);
+ resman->addToSearchPath(path, true);
+#else
resman->addToSearchPath(TMW_DATADIR "data", true);
+#endif
#ifdef USE_OPENGL
bool useOpenGL = (config.getValue("opengl", 0) == 1);
@@ -449,6 +466,12 @@ void accountLogin(LoginData *loginData)
// Clear the password, avoids auto login when returning to login
loginData->password = "";
+ //remove _M or _F from username after a login for registration purpose
+ if (loginData->registerLogin)
+ {
+ loginData->registerLogin = false;
+ loginData->username = loginData->username.substr(0, loginData->username.length() - 2);
+ }
// TODO This is not the best place to save the config, but at least better
// than the login gui window
if (loginData->remember) {
@@ -657,6 +680,7 @@ int main(int argc, char *argv[])
}
loginData.remember = config.getValue("remember", 0);
+ loginData.registerLogin = false;
Net::initialize();
accountServerConnection = Net::getConnection();
@@ -717,7 +741,7 @@ int main(int argc, char *argv[])
accountServerConnection->isConnected())
{
if (options.skipUpdate) {
- state = STATE_LOGIN;
+ state = STATE_LOADDATA;
} else {
state = STATE_UPDATE;
}
@@ -794,17 +818,11 @@ int main(int argc, char *argv[])
logger->log("State: UPDATE");
// TODO: Revive later
//currentDialog = new UpdaterWindow();
- state = STATE_LOGIN;
+ state = STATE_LOADDATA;
break;
case STATE_LOGIN:
logger->log("State: LOGIN");
-
- // Load XML databases
- EquipmentDB::load();
- ItemDB::load();
- MonsterDB::load();
-
currentDialog = new LoginDialog(&loginData);
// TODO: Restore autologin
//if (!loginData.password.empty()) {
@@ -812,6 +830,22 @@ int main(int argc, char *argv[])
//}
break;
+ case STATE_LOADDATA:
+ logger->log("State: LOADDATA");
+
+ // Add customdata directory
+ ResourceManager::getInstance()->searchAndAddArchives(
+ "customdata/",
+ "zip",
+ false);
+
+ // Load XML databases
+ EquipmentDB::load();
+ ItemDB::load();
+ MonsterDB::load();
+ state = STATE_LOGIN;
+ break;
+
case STATE_LOGIN_ATTEMPT:
accountLogin(&loginData);
break;
diff --git a/src/main.h b/src/main.h
index 4dd93ae8..1e9f8c09 100644
--- a/src/main.h
+++ b/src/main.h
@@ -72,6 +72,7 @@ enum {
STATE_CHOOSE_SERVER,
STATE_CONNECT_ACCOUNT,
STATE_UPDATE,
+ STATE_LOADDATA,
STATE_LOGIN,
STATE_LOGIN_ATTEMPT,
STATE_REGISTER,
diff --git a/src/map.cpp b/src/map.cpp
index a88926d7..a6beb951 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -147,8 +147,8 @@ Map::draw(Graphics *graphics, int scrollX, int scrollY, int layer)
if (startX < 0) startX = 0;
if (startY < 0) startY = 0;
- if (endX >= mWidth) endX = mWidth - 1;
- if (endY >= mHeight) endY = mHeight - 1;
+ if (endX > mWidth) endX = mWidth;
+ if (endY > mHeight) endY = mHeight;
for (int y = startY; y < endY; y++)
{
diff --git a/src/monster.cpp b/src/monster.cpp
index dd4a321c..bea5b7a5 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -57,11 +57,10 @@ Monster::setAction(Action action)
break;
case DEAD:
currentAction = ACTION_DEAD;
- sound.playSfx(MonsterDB::get(mJob - 1002).getSound(EVENT_DIE));
+ sound.playSfx(getInfo().getSound(EVENT_DIE));
break;
case ATTACK:
currentAction = ACTION_ATTACK;
- sound.playSfx(MonsterDB::get(mJob - 1002).getSound(EVENT_HIT));
mSprites[BASE_SPRITE]->reset();
break;
case STAND:
@@ -80,3 +79,22 @@ Monster::setAction(Action action)
mAction = action;
}
}
+
+void
+Monster::handleAttack()
+{
+ Being::handleAttack();
+
+ const MonsterInfo &mi = getInfo();
+
+ // TODO: It's not possible to determine hit or miss here, so this stuff probably needs
+ // to be moved somewhere else. We may lose synchronization between attack animation and
+ // the sound, unless we adapt the protocol...
+ sound.playSfx(mi.getSound(EVENT_HIT));
+}
+
+const MonsterInfo&
+Monster::getInfo() const
+{
+ return MonsterDB::get(mJob - 1002);
+}
diff --git a/src/monster.h b/src/monster.h
index 3e9cdb05..18fa703e 100644
--- a/src/monster.h
+++ b/src/monster.h
@@ -26,6 +26,8 @@
#include "being.h"
+class MonsterInfo;
+
class Monster : public Being
{
public:
@@ -34,6 +36,19 @@ class Monster : public Being
virtual void setAction(Action action);
virtual Type getType() const;
+
+ /**
+ * Handles an attack of another being by this monster. Plays a hit or
+ * miss sound when appropriate.
+ */
+ virtual void handleAttack();
+
+ protected:
+ /**
+ * Returns the MonsterInfo, with static data about this monster.
+ */
+ const MonsterInfo&
+ getInfo() const;
};
#endif
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index 32c78b39..53746671 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -215,29 +215,26 @@ void BeingHandler::handleMessage(MessageIn &msg)
switch (type)
{
case 0: // Damage
- if (dstBeing == NULL) break;
-
- dstBeing->setDamage(param1, SPEECH_TIME);
-
- if (srcBeing != NULL &&
- srcBeing != player_node)
- {
- srcBeing->setAction(Being::ATTACK);
- srcBeing->mFrame = 0;
- srcBeing->mWalkTime = tick_time;
+ if (dstBeing) {
+ dstBeing->takeDamage(param1);
+ }
+ if (srcBeing) {
+ srcBeing->handleAttack(dstBeing, param1);
}
break;
case 2: // Sit
- if (srcBeing == NULL) break;
- srcBeing->mFrame = 0;
- srcBeing->setAction(Being::SIT);
+ if (srcBeing) {
+ srcBeing->mFrame = 0;
+ srcBeing->setAction(Being::SIT);
+ }
break;
case 3: // Stand up
- if (srcBeing == NULL) break;
- srcBeing->mFrame = 0;
- srcBeing->setAction(Being::STAND);
+ if (srcBeing) {
+ srcBeing->mFrame = 0;
+ srcBeing->setAction(Being::STAND);
+ }
break;
}
break;
@@ -525,7 +522,7 @@ void BeingHandler::handleBeingsDamageMessage(MessageIn &msg)
int damage = msg.readShort();
if (being)
{
- being->setDamage(damage, 0);
+ being->takeDamage(damage);
}
}
}
@@ -535,5 +532,5 @@ void BeingHandler::handleBeingActionChangeMessage(MessageIn &msg)
Being* being = beingManager->findBeing(msg.readShort());
if (!being) return;
- being->setAction((Being::Action)msg.readByte());
+ being->setAction((Being::Action) msg.readByte());
}
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index 45067302..2059a5c3 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -112,6 +112,33 @@ ResourceManager::addToSearchPath(const std::string &path, bool append)
PHYSFS_addToSearchPath(path.c_str(), append ? 1 : 0);
}
+void
+ResourceManager::searchAndAddArchives(const std::string &path,
+ const std::string &ext,
+ bool append)
+{
+ const char *dirSep = PHYSFS_getDirSeparator();
+ char **list = PHYSFS_enumerateFiles(path.c_str());
+
+ for (char **i = list; *i != NULL; i++)
+ {
+ size_t len = strlen(*i);
+
+ if (len > ext.length() && !ext.compare((*i)+(len - ext.length())))
+ {
+ std::string file, realPath, archive;
+
+ file = path + (*i);
+ realPath = std::string(PHYSFS_getRealDir(file.c_str()));
+ archive = realPath + dirSep + file;
+
+ addToSearchPath(archive, append);
+ }
+ }
+
+ PHYSFS_freeList(list);
+}
+
bool
ResourceManager::mkdir(const std::string &path)
{
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index d458f96e..e176e337 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -83,6 +83,14 @@ class ResourceManager
addToSearchPath(const std::string &path, bool append);
/**
+ * Searches for zip files and adds them to the search path.
+ */
+ void
+ searchAndAddArchives(const std::string &path,
+ const std::string &ext,
+ bool append);
+
+ /**
* Creates a directory in the write path
*/
bool