diff options
Diffstat (limited to 'src')
68 files changed, 1368 insertions, 352 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e8654e6..b54c7c6c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -148,6 +148,8 @@ SET(SRCS gui/setup_joystick.h gui/setup_keyboard.cpp gui/setup_keyboard.h + gui/setup_players.cpp + gui/setup_players.h gui/setuptab.h gui/setup_video.cpp gui/setup_video.h @@ -165,6 +167,10 @@ SET(SRCS gui/status.h gui/tabbedcontainer.cpp gui/tabbedcontainer.h + gui/table.cpp + gui/table.h + gui/table_model.cpp + gui/table_model.h gui/textbox.cpp gui/textbox.h gui/textfield.cpp @@ -329,6 +335,8 @@ SET(SRCS particleemitterprop.h player.cpp player.h + player_relations.cpp + player_relations.h properties.h serverinfo.h shopitem.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 75434d8e..507db6f8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -289,6 +289,8 @@ aethyra_SOURCES = gui/widgets/dropdown.cpp \ openglgraphics.h \ particle.cpp \ particle.h \ + particlecontainer.cpp \ + particlecontainer.h \ particleemitter.cpp \ particleemitter.h \ particleemitterprop.h \ diff --git a/src/SDLMain.h b/src/SDLMain.h new file mode 100755 index 00000000..4683df57 --- /dev/null +++ b/src/SDLMain.h @@ -0,0 +1,11 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser <dwaliss1@purdue.edu> + Non-NIB-Code & other changes: Max Horn <max@quendi.de> + + Feel free to customize this file to suit your needs +*/ + +#import <Cocoa/Cocoa.h> + +@interface SDLMain : NSObject +@end diff --git a/src/SDLMain.m b/src/SDLMain.m new file mode 100755 index 00000000..3d02719c --- /dev/null +++ b/src/SDLMain.m @@ -0,0 +1,383 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser <dwaliss1@purdue.edu> + Non-NIB-Code & other changes: Max Horn <max@quendi.de> + + Feel free to customize this file to suit your needs + */ + +#import "SDL.h" +#import "SDLMain.h" +#import <sys/param.h> /* for MAXPATHLEN */ +#import <unistd.h> + +/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, + but the method still is there and works. To avoid warnings, we declare + it ourselves here. */ +@interface NSApplication(SDL_Missing_Methods) +- (void)setAppleMenu:(NSMenu *)menu; +@end + +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 0 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 +#ifdef SDL_USE_CPS +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum + { + UInt32 lo; + UInt32 hi; + } CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +#endif /* SDL_USE_CPS */ + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; + +static NSString *getApplicationName(void) +{ + NSDictionary *dict; + NSString *appName = 0; + + /* Determine the application name */ + dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; + + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; +} + +#if SDL_USE_NIB_FILE +/* A helper category for NSString */ +@interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; +@end +#endif + +@interface SDLApplication : NSApplication +@end + +@implementation SDLApplication +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} +@end + +/* The main class of the application, the application's delegate */ +@implementation SDLMain + +/* Set the working directory to the .app's parent directory */ +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { + assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } + +} + +#if SDL_USE_NIB_FILE + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName +{ + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; + + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } + [ aMenu sizeToFit ]; +} + +#else + +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +static void setupWindowMenu(void) +{ + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; +} + +/* Replacement for NSApplicationMain */ +static void CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [SDLApplication sharedApplication]; + +#ifdef SDL_USE_CPS + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [SDLApplication sharedApplication]; + } +#endif /* SDL_USE_CPS */ + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; +} + +#endif + + +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; + + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; + + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; + + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; +} + + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + +#if SDL_USE_NIB_FILE + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; +#endif + + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} +@end + + +@implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + +@end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } + +#if SDL_USE_NIB_FILE + [SDLApplication poseAsClass:[NSApplication class]]; + NSApplicationMain (argc, argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; +} diff --git a/src/aethyra.rc b/src/aethyra.rc index f35c547d..d2db954f 100644 --- a/src/aethyra.rc +++ b/src/aethyra.rc @@ -19,5 +19,4 @@ FILETYPE VFT_APP { VALUE "ProductVersion", PACKAGE_VERSION
}
}
-}
-
+} diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index c86c5392..ba71d0e0 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -55,7 +55,8 @@ AnimatedSprite *AnimatedSprite::load(const std::string& filename, int variant) { ResourceManager *resman = ResourceManager::getInstance(); SpriteDef *s = resman->getSprite(filename, variant); - if (!s) return NULL; + if (!s) + return NULL; AnimatedSprite *as = new AnimatedSprite(s); s->decRef(); return as; @@ -66,22 +67,18 @@ AnimatedSprite::~AnimatedSprite() mSprite->decRef(); } -void -AnimatedSprite::reset() +void AnimatedSprite::reset() { mFrameIndex = 0; mFrameTime = 0; mLastTime = 0; } -void -AnimatedSprite::play(SpriteAction spriteAction) +void AnimatedSprite::play(SpriteAction spriteAction) { Action *action = mSprite->getAction(spriteAction); if (!action) - { return; - } mAction = action; Animation *animation = mAction->getAnimation(mDirection); @@ -95,20 +92,15 @@ AnimatedSprite::play(SpriteAction spriteAction) } } -void -AnimatedSprite::update(int time) +void AnimatedSprite::update(int time) { // Avoid freaking out at first frame or when tick_time overflows if (time < mLastTime || mLastTime == 0) - { mLastTime = time; - } // If not enough time has passed yet, do nothing if (time <= mLastTime || !mAnimation) - { return; - } unsigned int dt = time - mLastTime; mLastTime = time; @@ -120,13 +112,10 @@ AnimatedSprite::update(int time) } } -bool -AnimatedSprite::updateCurrentAnimation(unsigned int time) +bool AnimatedSprite::updateCurrentAnimation(unsigned int time) { if (!mFrame || Animation::isTerminator(*mFrame)) - { return false; - } mFrameTime += time; @@ -136,9 +125,7 @@ AnimatedSprite::updateCurrentAnimation(unsigned int time) mFrameIndex++; if (mFrameIndex == mAnimation->getLength()) - { mFrameIndex = 0; - } mFrame = mAnimation->getFrame(mFrameIndex); @@ -153,30 +140,24 @@ AnimatedSprite::updateCurrentAnimation(unsigned int time) return true; } -bool -AnimatedSprite::draw(Graphics* graphics, int posX, int posY) const +bool AnimatedSprite::draw(Graphics* graphics, int posX, int posY) const { if (!mFrame || !mFrame->image) - { return false; - } return graphics->drawImage(mFrame->image, posX + mFrame->offsetX, posY + mFrame->offsetY); } -void -AnimatedSprite::setDirection(SpriteDirection direction) +void AnimatedSprite::setDirection(SpriteDirection direction) { if (mDirection != direction) { mDirection = direction; if (!mAction) - { return; - } Animation *animation = mAction->getAnimation(mDirection); @@ -189,14 +170,12 @@ AnimatedSprite::setDirection(SpriteDirection direction) } } -int -AnimatedSprite::getWidth() const +int AnimatedSprite::getWidth() const { return mFrame ? mFrame->image->getWidth() : 0; } -int -AnimatedSprite::getHeight() const +int AnimatedSprite::getHeight() const { return mFrame ? mFrame->image->getHeight() : 0; } diff --git a/src/being.cpp b/src/being.cpp index ded3abd8..d98af29c 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -49,6 +49,11 @@ #define BEING_EFFECTS_FILE "effects.xml" +#include "utils/xml.h" + +#define BEING_EFFECTS_FILE "effects.xml" +#define HAIR_FILE "hair.xml" + int Being::instances = 0; int Being::mNumberOfHairstyles = 1; ImageSet *Being::emotionSet = NULL; @@ -77,7 +82,9 @@ Being::Being(int id, int job, Map *map): mPx(0), mPy(0), mSprites(VECTOREND_SPRITE, NULL), mSpriteIDs(VECTOREND_SPRITE, 0), - mSpriteColors(VECTOREND_SPRITE, "") + mSpriteColors(VECTOREND_SPRITE, ""), + mStatusParticleEffects(&mStunParticleEffects, false), + mChildParticleEffects(&mStatusParticleEffects, false) { setMap(map); @@ -109,13 +116,6 @@ Being::~Being() delete_all(mSprites); clearPath(); - for ( std::list<Particle *>::iterator i = mChildParticleEffects.begin(); - i != mChildParticleEffects.end(); - i++) - { - (*i)->kill(); - } - setMap(NULL); instances--; @@ -250,12 +250,7 @@ void Being::setMap(Map *map) void Being::controlParticle(Particle *particle) { - if (particle) - { - // The effect may not die without the beings permission or we segfault - particle->disableAutoDelete(); - mChildParticleEffects.push_back(particle); - } + mChildParticleEffects.addLocally(particle); } void Being::setAction(Action action) @@ -323,7 +318,7 @@ void Being::setDirection(Uint8 direction) for (int i = 0; i < VECTOREND_SPRITE; i++) { - if (mSprites[i] != NULL) + if (mSprites[i] != NULL) mSprites[i]->setDirection(dir); } } @@ -402,6 +397,7 @@ void Being::logic() int oldPx = mPx; int oldPy = mPy; + // Update pixel coordinates mPx = mX * 32 + getXOffset(); mPy = mY * 32 + getYOffset(); @@ -428,24 +424,8 @@ void Being::logic() } } - if (mParticleEffects) - { - //Update particle effects - for (std::list<Particle *>::iterator i = mChildParticleEffects.begin(); - i != mChildParticleEffects.end();) - { - (*i)->setPosition((float)mPx + 16.0f, (float)mPy + 32.0f); - if ((*i)->isExtinct()) - { - (*i)->kill(); - i = mChildParticleEffects.erase(i); - } - else - { - i++; - } - } - } + //Update particle effects + mChildParticleEffects.setPositions((float)mPx + 16.0f, (float)mPy + 32.0f); } void Being::draw(Graphics *graphics, int offsetX, int offsetY) const diff --git a/src/being.h b/src/being.h index 958e8f60..7202701a 100644 --- a/src/being.h +++ b/src/being.h @@ -27,10 +27,12 @@ #include <SDL_types.h> #include <string> #include <vector> +#include <bitset> #include "animatedsprite.h" #include "effectmanager.h" #include "map.h" +#include "particlecontainer.h" #include "sprite.h" #include "gui/speechbubble.h" @@ -38,6 +40,7 @@ #include "resources/colordb.h" #define FIRST_IGNORE_EMOTE 14 +#define STATUS_EFFECTS 32 class AnimatedSprite; class Equipment; @@ -364,6 +367,12 @@ class Being : public Sprite const std::auto_ptr<Equipment> mEquipment; + static int getHairColorsNr(void); + + static int getHairStylesNr(void); + + static std::string getHairColor(int index); + protected: /** * Sets the new path for this being. @@ -393,6 +402,8 @@ class Being : public Sprite bool mIsGM; bool mParticleEffects; /**< Whether to display particles or not */ + typedef std::bitset<STATUS_EFFECTS> StatusEffects; + /** Engine-related infos about weapon. */ const ItemInfo* mEquippedWeapon; @@ -405,11 +416,15 @@ class Being : public Sprite Uint8 mGender; Uint32 mSpeechTime; Sint32 mPx, mPy; /**< Pixel coordinates */ + Uint16 mStunMode; /**< Stun mode; zero if not stunned */ + StatusEffects mStatusEffects; /**< Bitset of active status effects */ std::vector<AnimatedSprite*> mSprites; std::vector<int> mSpriteIDs; std::vector<std::string> mSpriteColors; - std::list<Particle *> mChildParticleEffects; + ParticleList mStunParticleEffects; + ParticleVector mStatusParticleEffects; + ParticleList mChildParticleEffects; private: /** diff --git a/src/engine.cpp b/src/engine.cpp index b51f4852..74e11336 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -114,6 +114,12 @@ void Engine::changeMap(const std::string &mapPath) minimap->setProportion(0.5); } } + if (newMap->hasProperty("name")) + { + minimap->setCaption(newMap->getProperty("name")); + } else { + minimap->setCaption("Map"); + } minimap->setMapImage(mapImage); beingManager->setMap(newMap); particleEngine->setMap(newMap); diff --git a/src/equipment.h b/src/equipment.h index 2427539c..e6145d12 100644 --- a/src/equipment.h +++ b/src/equipment.h @@ -17,8 +17,6 @@ * You should have received a copy of the GNU General Public License * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: equipment.h 4347 2008-06-12 09:06:01Z b_lindeijer $ */ #ifndef _TMW_EQUIPMENT_H_ @@ -45,26 +43,22 @@ class Equipment /** * Set equipment at the given slot. */ - void - setEquipment(int index, int inventoryIndex); + void setEquipment(int index, int inventoryIndex); /** * Remove equipment from the given slot. */ - void - removeEquipment(int index) { if (index >= 0 && index < EQUIPMENT_SIZE) mEquipment[index] = 0; } + void removeEquipment(int index) { if (index >= 0 && index < EQUIPMENT_SIZE) mEquipment[index] = 0; } /** - * Get the item used in the arrow slot. + * Returns the item used in the arrow slot. */ - int - getArrows() { return mArrows; } + int getArrows() const { return mArrows; } /** * Set the item used in the arrow slot. */ - void - setArrows(int arrows) {mArrows = arrows;} + void setArrows(int arrows) { mArrows = arrows; } private: int mEquipment[EQUIPMENT_SIZE]; diff --git a/src/floor_item.h b/src/floor_item.h index 7771d935..b747310b 100644 --- a/src/floor_item.h +++ b/src/floor_item.h @@ -17,8 +17,6 @@ * You should have received a copy of the GNU General Public License * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: floor_item.h 4347 2008-06-12 09:06:01Z b_lindeijer $ */ #ifndef _TMW_FLOORITEM_H_ diff --git a/src/game.cpp b/src/game.cpp index e8ba9046..93bec013 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -68,6 +68,7 @@ #include "gui/trade.h" #include "gui/viewport.h" +#include "net/protocol.h" #include "net/beinghandler.h" #include "net/buysellhandler.h" #include "net/chathandler.h" @@ -81,6 +82,7 @@ #include "net/protocol.h" #include "net/skillhandler.h" #include "net/tradehandler.h" +#include "net/messageout.h" #include "resources/imagewriter.h" @@ -489,7 +491,7 @@ void Game::handleInput() // Keys pressed together with Alt/Meta // Emotions and some internal gui windows #ifndef __APPLE__ - if (event.key.keysym.mod & KMOD_ALT) + if (event.key.keysym.mod & KMOD_LALT) #else if (event.key.keysym.mod & KMOD_LMETA) #endif @@ -580,6 +582,7 @@ void Game::handleInput() { chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL); used = true; + return; } break; @@ -837,7 +840,8 @@ void Game::handleInput() } // Target the nearest player if 'q' is pressed - if ( keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) && !keyboard.isKeyActive(keyboard.KEY_TARGET) ) + if ( keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) && + !keyboard.isKeyActive(keyboard.KEY_TARGET) ) { Being *target = beingManager->findNearestLivingBeing(player_node, 20, Being::PLAYER); @@ -845,7 +849,9 @@ void Game::handleInput() } // Target the nearest monster if 'a' pressed - if ( keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) && !keyboard.isKeyActive(keyboard.KEY_TARGET) ) + if ((keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) || + (joystick && joystick->buttonPressed(3))) && + !keyboard.isKeyActive(keyboard.KEY_TARGET)) { Being *target = beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER); @@ -853,7 +859,8 @@ void Game::handleInput() } // Target the nearest npc if 'n' pressed - if ( keyboard.isKeyActive(keyboard.KEY_TARGET_NPC) && !keyboard.isKeyActive(keyboard.KEY_TARGET) ) + if ( keyboard.isKeyActive(keyboard.KEY_TARGET_NPC) && + !keyboard.isKeyActive(keyboard.KEY_TARGET) ) { Being *target = beingManager->findNearestLivingBeing(x, y, 20, Being::NPC); diff --git a/src/gui/buddywindow.cpp b/src/gui/buddywindow.cpp new file mode 100644 index 00000000..14a941a5 --- /dev/null +++ b/src/gui/buddywindow.cpp @@ -0,0 +1,83 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "buddywindow.h" + +#include <guichan/widgets/listbox.hpp> + +#include "button.h" +#include "chat.h" +#include "scrollarea.h" + +#include "../resources/buddylist.h" + +extern ChatWindow *chatWindow; + +BuddyWindow::BuddyWindow(): + Window("Buddy") +{ + setContentSize(124, 202); + + mBuddyList = new BuddyList(); + + mListbox = new gcn::ListBox(); + mListbox->setListModel(mBuddyList); + + ScrollArea *scrollArea = new ScrollArea(mListbox); + scrollArea->setDimension(gcn::Rectangle( + 7, 5, 110, 170)); + add(scrollArea); + + Button *talk = new Button("Talk", "Talk", this); + Button *remove = new Button("Remove", "Remove", this); + Button *cancel = new Button("Cancel", "Cancel", this); + + talk->setPosition(2,180); + remove->setPosition(talk->getWidth()+2,180); + cancel->setPosition(talk->getWidth()+remove->getWidth()+2,180); + + add(talk); + add(remove); + add(cancel); +} + +void BuddyWindow::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "Talk") { + int selected = mListbox->getSelected(); + if ( selected > -1 ) + { + std::string who = mBuddyList->getElementAt(selected); + chatWindow->setInputText(who +": "); + } + } + else if (event.getId() == "Remove") { + int selected = mListbox->getSelected(); + if ( selected > -1 ) + { + std::string who = mBuddyList->getElementAt(selected); + mBuddyList->removeBuddy(who); + } + } + else if (event.getId() == "Cancel") { + setVisible(false); + } +} diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 93783ded..53cc1e8d 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -256,8 +256,6 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network, int numberOfHairColors = ColorDB::size(); - printf("%d\n", numberOfHairColors); - mPlayer->setHairStyle(rand() % mPlayer->getNumOfHairstyles(), rand() % numberOfHairColors); mNameField = new TextField(""); diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp index 8f68e6e1..054aff84 100644 --- a/src/gui/char_server.cpp +++ b/src/gui/char_server.cpp @@ -45,8 +45,10 @@ class ServerListModel : public gcn::ListModel { std::string getElementAt(int i); }; -ServerSelectDialog::ServerSelectDialog(LoginData *loginData): - Window("Select Server"), mLoginData(loginData) +ServerSelectDialog::ServerSelectDialog(LoginData *loginData, int nextState): + Window("Select Server"), + mLoginData(loginData), + mNextState(nextState) { mServerListModel = new ServerListModel(); mServerList = new ListBox(mServerListModel); @@ -103,10 +105,10 @@ ServerSelectDialog::action(const gcn::ActionEvent &event) mLoginData->hostname = iptostring(si->address); mLoginData->port = si->port; mLoginData->updateHost = si->updateHost; - state = UPDATE_STATE; + state = mNextState; } else if (event.getId() == "cancel") { - state = LOGIN_STATE; + state = LOGIN_STATE; } } diff --git a/src/gui/char_server.h b/src/gui/char_server.h index bb81d3a5..e05792f8 100644 --- a/src/gui/char_server.h +++ b/src/gui/char_server.h @@ -44,7 +44,7 @@ class ServerSelectDialog : public Window, public gcn::ActionListener { * * @see Window::Window */ - ServerSelectDialog(LoginData *loginData); + ServerSelectDialog(LoginData *loginData, int nextState); /** * Destructor. @@ -61,6 +61,7 @@ class ServerSelectDialog : public Window, public gcn::ActionListener { ServerListModel *mServerListModel; gcn::ListBox *mServerList; gcn::Button *mOkButton; + int mNextState; }; #endif diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index dd11cebb..3f12c462 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -257,7 +257,7 @@ bool ChatWindow::isInputFocused() return mChatInput->isFocused(); } -void ChatWindow::chatSend(const std::string & nick, std::string msg) +void ChatWindow::chatSend(const std::string &nick, std::string msg) { /* Some messages are managed client side, while others * require server handling by proper packet. Probably @@ -302,37 +302,42 @@ void ChatWindow::chatSend(const std::string & nick, std::string msg) trim(msg); } - if (command == "announce") { + if (command == "announce") + { MessageOut outMsg(mNetwork); outMsg.writeInt16(0x0099); outMsg.writeInt16(msg.length() + 4); outMsg.writeString(msg, msg.length()); return; } - if (command == "help") { + else if (command == "help") + { + msg.erase(0, 6); + trim(msg); std::size_t space = msg.find(" "); std::string msg1; - if (space == std::string::npos) { + if (space == std::string::npos) + { msg1 = ""; - } else { + } + else + { msg1 = msg.substr(space + 1, msg.length()); msg = msg.substr(0, space); } - if (msg != "" && msg.at(0) == '/') { + if (msg != "" && msg.at(0) == '/') + { msg.erase(0, 1); } - while (msg1 != "" && msg1.at(0) == ' ') { - msg1.erase(0, 1); - } + trim(msg1); help(msg, msg1); - return; } - if (command == "where") { + else if (command == "where") + { // Display the current map, X, and Y std::ostringstream where; - where << map_path << " " << player_node->mX << " " << player_node->mY; + where << map_path << " " << player_node->mX << "," << player_node->mY; chatLog(where.str(), BY_SERVER); - return; } if (command == "who") { MessageOut outMsg(mNetwork); @@ -648,20 +653,23 @@ void ChatWindow::help(const std::string & msg1, const std::string & msg2) chatLog("For more information, type /help <command>", BY_SERVER); return; } - if (msg1 == "announce") { + if (msg1 == "announce") + { chatLog("Command: /announce <msg>", BY_SERVER); chatLog("*** only available to a GM ***", BY_SERVER); chatLog("This command sends the message <msg> to " "all players currently online.", BY_SERVER); return; } - if (msg1 == "clear") { + if (msg1 == "clear") + { chatLog("Command: /clear", BY_SERVER); chatLog("This command clears the chat log of previous chat.", BY_SERVER); return; } - if (msg1 == "help") { + if (msg1 == "help") + { chatLog("Command: /help", BY_SERVER); chatLog("This command displays a list of all commands available.", BY_SERVER); @@ -669,22 +677,26 @@ void ChatWindow::help(const std::string & msg1, const std::string & msg2) chatLog("This command displays help on <command>.", BY_SERVER); return; } - if (msg1 == "party") { + if (msg1 == "party") + { mParty->help(msg2); return; } - if (msg1 == "present") { + if (msg1 == "present") + { chatLog("Command: /present", BY_SERVER); chatLog("This command gets a list of players within hearing " "and sends it to either the record log if recording, or the " "chat log otherwise.", BY_SERVER); return; } - if (msg1 == "record") { + if (msg1 == "record") + { mRecorder->help(msg2); return; } - if (msg1 == "toggle") { + if (msg1 == "toggle") + { chatLog("Command: /toggle <state>", BY_SERVER); chatLog("This command sets whether the return key should toggle the " "chat log, or whether the chat log turns off automatically.", @@ -696,7 +708,8 @@ void ChatWindow::help(const std::string & msg1, const std::string & msg2) chatLog("This command displays the return toggle status.", BY_SERVER); return; } - if (msg1 == "where") { + if (msg1 == "where") + { chatLog("Command: /where", BY_SERVER); chatLog("This command displays the name of the current map.", BY_SERVER); @@ -709,7 +722,8 @@ void ChatWindow::help(const std::string & msg1, const std::string & msg2) "double quotes (\").", BY_SERVER); return; } - if (msg1 == "who") { + if (msg1 == "who") + { chatLog("Command: /who", BY_SERVER); chatLog("This command displays the number of players currently " "online.", BY_SERVER); diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index bf85f033..7e1ef315 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -22,6 +22,8 @@ #include "equipmentwindow.h" #include "../equipment.h" +#include "../inventory.h" +#include "../localplayer.h" #include "../graphics.h" #include "../inventory.h" #include "../item.h" @@ -40,7 +42,7 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment): setCloseButton(true); setDefaultSize(5, 230, 200, 120); loadWindowState(); - inventory = player_node->getInventory(); + mInventory = player_node->getInventory(); } EquipmentWindow::~EquipmentWindow() @@ -62,7 +64,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) graphics->drawRectangle(gcn::Rectangle(10 + 36 * (i % 4), 36 * (i / 4) + 25, 32, 32)); - if (!(item = inventory->getItem(mEquipment->getEquipment(i)))) + if (!(item = mInventory->getItem(mEquipment->getEquipment(i)))) continue; image = item->getImage(); @@ -75,7 +77,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) graphics->drawRectangle(gcn::Rectangle(160, 25, 32, 32)); - if (!(item = inventory->getItem(mEquipment->getArrows()))) + if (!(item = mInventory->getItem(mEquipment->getArrows()))) return; image = item->getImage(); diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h index 7aacfc1e..b669f5b1 100644 --- a/src/gui/equipmentwindow.h +++ b/src/gui/equipmentwindow.h @@ -23,6 +23,7 @@ #define _TMW_EQUIPMENT_H #include "window.h" +#include "../inventory.h" #include "../guichanfwd.h" #include "../inventory.h" @@ -54,7 +55,7 @@ class EquipmentWindow : public Window private: Equipment *mEquipment; - Inventory *inventory; + Inventory *mInventory; }; extern EquipmentWindow *equipmentWindow; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a382ef85..70f82d9d 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -110,7 +110,7 @@ Gui::Gui(Graphics *graphics): Window::setWindowContainer(guiTop); setTop(guiTop); - // Set global font + // Set global font (based on ISO-8859-15) try { mGuiFont = new gcn::ImageFont("graphics/gui/sansserif8.png", " !\"#$%&'()*+,-./" diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index a8b20d40..424fca59 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -73,7 +73,7 @@ InventoryWindow::InventoryWindow(): mWeightLabel->setPosition(8, 8); mSlots = "Slots: " + toString(player_node->getInventory()->getNumberOfSlotsUsed()) + - "/" + toString(player_node->getInventory()->getSize() - 2); + "/" + toString(player_node->getInventory()->getInventorySize()); mSlotsLabel = new TextBox(); mItemEffectLabel = new TextBox(); @@ -113,7 +113,7 @@ void InventoryWindow::logic() mSlots = "Slots: " + toString(player_node->getInventory()->getNumberOfSlotsUsed()) + - "/" + toString(player_node->getInventory()->getSize() - 2); + "/" + toString(player_node->getInventory()->getInventorySize()); draw(); } diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index fca0c72d..9e17f3da 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -64,8 +64,7 @@ ItemContainer::~ItemContainer() mSelImg->decRef(); } -void -ItemContainer::logic() +void ItemContainer::logic() { gcn::Widget::logic(); @@ -78,8 +77,7 @@ ItemContainer::logic() } } -void -ItemContainer::draw(gcn::Graphics *graphics) +void ItemContainer::draw(gcn::Graphics *graphics) { int columns = getWidth() / gridWidth; @@ -146,8 +144,7 @@ void ItemContainer::recalculateHeight() setHeight(height); } -Item* -ItemContainer::getSelectedItem() +Item *ItemContainer::getSelectedItem() { refindSelectedItem(); // Make sure that we're still current @@ -157,8 +154,7 @@ ItemContainer::getSelectedItem() return mInventory->getItem(mSelectedItemIndex); } -void -ItemContainer::selectNone() +void ItemContainer::selectNone() { setSelectedItemIndex(NO_ITEM); } @@ -166,15 +162,15 @@ ItemContainer::selectNone() void ItemContainer::refindSelectedItem() { if (mSelectedItemIndex != NO_ITEM) { - + if (mInventory->getItem(mSelectedItemIndex) && mInventory->getItem(mSelectedItemIndex)->getId() == mLastSelectedItemId) return; // we're already fine - + // Otherwise ensure the invariant: we must point to an item of the specified last ID, // or nowhere at all. - for (int i = 0; i <= mMaxItems + mOffset; i++) + for (int i = 0; i <= mMaxItems + 1; i++) if (mInventory->getItem(i) && mInventory->getItem(i)->getId() == mLastSelectedItemId) { mSelectedItemIndex = i; @@ -198,7 +194,6 @@ void ItemContainer::setSelectedItemIndex(int index) newSelectedItemIndex = NO_ITEM; else newSelectedItemIndex = index; - if (mSelectedItemIndex != newSelectedItemIndex) { mSelectedItemIndex = newSelectedItemIndex; @@ -212,8 +207,7 @@ void ItemContainer::setSelectedItemIndex(int index) } } -void -ItemContainer::distributeValueChangedEvent() +void ItemContainer::distributeValueChangedEvent() { gcn::SelectionEvent event(this); std::list<gcn::SelectionListener*>::iterator i_end = mListeners.end(); @@ -225,8 +219,7 @@ ItemContainer::distributeValueChangedEvent() } } -void -ItemContainer::mousePressed(gcn::MouseEvent &event) +void ItemContainer::mousePressed(gcn::MouseEvent &event) { int button = event.getButton(); @@ -243,8 +236,6 @@ ItemContainer::mousePressed(gcn::MouseEvent &event) Item *item = mInventory->getItem(index); if (item) - { itemShortcut->setItemSelected(item->getId()); - } } } diff --git a/src/gui/itemcontainer.h b/src/gui/itemcontainer.h index 5d22b658..8927b001 100644 --- a/src/gui/itemcontainer.h +++ b/src/gui/itemcontainer.h @@ -108,29 +108,30 @@ class ItemContainer : public gcn::Widget, private: /** - * Find the current item index by the most recently used item ID + + * Sets the currently selected item. Invalid (e.g., negative) indices set `no item'. */ - void refindSelectedItem(void); + void setSelectedItemIndex(int index); /** - * Sets the currently selected item. Invalid (e.g., negative) indices set `no item'. + * Find the current item index by the most recently used item ID */ - void setSelectedItemIndex(int index); + void refindSelectedItem(void); /** * Determine and set the height of the container. */ - void recalculateHeight(); + void recalculateHeight(void); /** * Sends out selection events to the list of selection listeners. */ - void distributeValueChangedEvent(); + void distributeValueChangedEvent(void); Inventory *mInventory; Image *mSelImg; int mSelectedItemIndex; - int mLastSelectedItemId; // last selected item ID. If we lose the item, find again by ID. + int mLastSelectedItemId; // last selected item ID. If we lose the item, find again by ID. int mMaxItems; int mOffset; diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp index f8a0959a..de5e1956 100644 --- a/src/gui/itemshortcutcontainer.cpp +++ b/src/gui/itemshortcutcontainer.cpp @@ -86,7 +86,7 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics) // Draw item keyboard shortcut. const char *key = SDL_GetKeyName( - (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_0+i)); + (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_0 + i)); g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT); if (itemShortcut->getItem(i) < 0) @@ -100,6 +100,8 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics) item->isEquipped() ? "Eq." : toString(item->getQuantity()); Image* image = item->getImage(); if (image) { + const std::string label = + item->isEquipped() ? "Eq." : toString(item->getQuantity()); g->drawImage(image, itemX, itemY); g->drawText( label, diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index 3a2e483d..8339e478 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -40,17 +40,13 @@ Minimap::Minimap(): Minimap::~Minimap() { if (mMapImage) - { mMapImage->decRef(); - } } void Minimap::setMapImage(Image *img) { if (mMapImage) - { mMapImage->decRef(); - } mMapImage = img; diff --git a/src/gui/newskill.cpp b/src/gui/newskill.cpp new file mode 100644 index 00000000..20fc01bd --- /dev/null +++ b/src/gui/newskill.cpp @@ -0,0 +1,193 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + /* This file implements the new skill dialog for use under the latest + * version of the skill system as of 2005/02/20 + */ + +#include "newskill.h" + +#include <guichan/widgets/label.hpp> + +#include "button.h" +#include "progressbar.h" + +#include "../graphics.h" + +const char *skill_name[] = { + // 0-99 + // weapon skills 0-9 + "Short Blades", "Long Blades", "Hammers", "Archery", "Whip", + "Staves", "Throwing", "Piercing", "Hand to Hand", NULL, + // magic skills 10-19 + "Epyri (Fire)", "Merene (Water)", "Geon (Earth)", "Izurial (Air)", + "Lumine (Light)", "Tenebrae (Dark)", "Chronos (Time)", "Teless (Space)", + "Gen (Mana)", NULL, + // craft skills 20-29 + "Metalworking", "Woodworking", "Jeweler", "Cook", "Tailor", + "Alchemist", "Artisan", "Synthesis", NULL, NULL, + // general skills 30-39 + "Running", "Searching", "Sneak", "Trading", "Intimidate", + "Athletics", NULL, NULL, NULL,NULL, + // combat skills 40-49 + "Dodge", "Accuracy", "Critical", "Block", "Parry", "Diehard", "Magic Aura", + "Counter", NULL, NULL, + // resistance skills 50-59 + "Poison", "Silence", "Petrify", "Paralyze", "Blind", "Slow", "Zombie", + "Critical", NULL, NULL, + // element reistance 60-69 + "Heat (Fire)", "Chill (Water)", "Stone (Earth)", "Wind (Air)", + "Shine (Light)", "Shadow (Dark)", "Decay (Time)", "Chaos (Space)", NULL, + NULL, + // hunting skills 70-79 + "Insects", "Birds", "Lizards", "Amorphs", "Undead", "Machines", "Arcana", + "Humanoids", "Plantoids", NULL, + // stats 80-89 + "Strength", "Fortitude", "Vitality", "Menality", "Awareness", "Mana", + "Dexterity", NULL, NULL, NULL, + // unused (reserved) 90-99 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + + +NewSkillDialog::NewSkillDialog(): + Window("Skills") +{ + startPoint = 0; + for (int i = 0; i < N_SKILL_CAT_SIZE; i++) + { + mSkillLabel[i] = new gcn::Label("Empty "); + mSkillLevel[i] = new gcn::Label("00000"); + mSkillbar[i] = new ProgressBar(0.0f,100,15,0,0,255); + mSkillLevel[i]->setAlignment(Graphics::RIGHT); + add(mSkillLabel[i],40,5+i*25); + add(mSkillLevel[i],150,5+i*25); + add(mSkillbar[i],180,5+i*25); + } + // initialize the skills + for (int i = 0; i < N_SKILL; i++) + { + mPlayerSkill[i].level = 0; + mPlayerSkill[i].exp = 0; + } + resetNSD(); + + // create controls + Button *catButton[N_SKILL_CAT]; + catButton[0] = new Button("Weapons", "g1", this); + catButton[1] = new Button("Magic", "g2", this); + catButton[2] = new Button("Craft", "g3", this); + catButton[3] = new Button("General", "g4", this); + catButton[4] = new Button("Combat", "g5", this); + catButton[5] = new Button("E. Resist", "g6", this); + catButton[6] = new Button("S. Resist", "g7", this); + catButton[7] = new Button("Hunting", "g8", this); + catButton[8] = new Button("Stat", "g9", this); + + setContentSize(350, 250); + + for (int i = 0; i < 9; ++i) { + catButton[i]->setDimension(gcn::Rectangle(0, 0, 60, 20)); + catButton[i]->setPosition(290, 20 * i); + add(catButton[i]); + } + + Button *closeButton = new Button("Close", "close", this); + closeButton->setDimension(gcn::Rectangle(0,0,60,20)); + closeButton->setPosition(290, 230); + add(closeButton); + + // finsihing touches + setLocationRelativeTo(getParent()); +} + +void NewSkillDialog::action(const gcn::ActionEvent &event) +{ + int osp = startPoint; + if (event.getId() == "close") + { + setVisible(false); + } + else if (event.getId() == "g1") // weapons group 0-9 + { + startPoint =0; + } + else if (event.getId() == "g2") // magic group 10-19 + { + startPoint =10; + } + else if (event.getId() == "g3") // craft group 20-29 + { + startPoint =20; + } + else if (event.getId() == "g4") // general group 30-39 + { + startPoint =30; + } + else if (event.getId() == "g5") // combat group 40-49 + { + startPoint =40; + } + else if (event.getId() == "g6") // e. resist group 50-59 + { + startPoint =50; + } + else if (event.getId() == "g7") // s resist group 60-69 + { + startPoint =60; + } + else if (event.getId() == "g8") // hunting group 70-79 + { + startPoint =70; + } + else if (event.getId() == "g9") // stats group 80-89 + { + startPoint =80; + } + if (osp != startPoint) + { + resetNSD(); + } +} + +void NewSkillDialog::resetNSD() +{ + for (int a = 0; a < N_SKILL_CAT_SIZE; a++) + { + if (skill_name[a + startPoint]) + { + mSkillLabel[a]->setCaption(skill_name[a + startPoint]); + mSkillLabel[a]->setVisible(true); + char tmp[5]; + sprintf(tmp, "%d", mPlayerSkill[a+startPoint].level); + mSkillLevel[a]->setCaption(tmp); + mSkillLevel[a]->setVisible(true); + mSkillbar[a]->setProgress(0.0f); + mSkillbar[a]->setVisible(true); + } + else + { + mSkillLevel[a]->setVisible(false); + mSkillLabel[a]->setVisible(false); + mSkillbar[a]->setVisible(false); + } + } +} diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index d83e9dea..b53de828 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -59,7 +59,6 @@ void NpcTextDialog::setText(const std::string &text) { const gcn::Rectangle &area = getChildrenArea(); const int width = area.width; - const int height = area.height; mText = text; mTextBox->setMinWidth(width - 30); diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h index 04c5c4d9..099d03c0 100644 --- a/src/gui/npclistdialog.h +++ b/src/gui/npclistdialog.h @@ -86,9 +86,9 @@ class NpcListDialog : public Window, public gcn::ActionListener, private: gcn::ListBox *mItemList; - ScrollArea *scrollArea; - Button *okButton; - Button *cancelButton; + gcn::ScrollArea *scrollArea; + gcn::Button *okButton; + gcn::Button *cancelButton; std::vector<std::string> mItems; }; diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index ec5b1d0a..15841615 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -289,11 +289,12 @@ void Setup_Video::apply() bool fullscreen = mFsCheckBox->isSelected(); if (fullscreen != (config.getValue("screen", 0) == 1)) { - - /* Commented out the openGL test because - * the fullscreen mode change works fine, but - * will need to test it on windows so not - * deleting entirely until then --kraant*/ + /* The OpenGL test is only necessary on Windows, since switching + * to/from full screen works fine on Linux. On Windows we'd have to + * reinitialize the OpenGL state and reload all textures. + * + * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode + */ #ifdef WIN32 // checks for opengl usage diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 36c3a305..8e61dea4 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -87,7 +87,8 @@ public: SkillInfo const *info; char tmp[128]; - if (skill->id >= 0 && (unsigned int) skill->id < skill_db.size()) + if (skill->id >= 0 + && (unsigned int) skill->id < skill_db.size()) info = &skill_db[skill->id]; else info = &fakeSkillInfo; @@ -195,13 +196,14 @@ void SkillDialog::update() if (selectedSkill >= 0) { int skillId = mSkillList[selectedSkill]->id; bool modifiable; - + if (skillId >= 0 && (unsigned int) skillId < skill_db.size()) modifiable = skill_db[skillId].modifiable; else modifiable = false; - mIncButton->setEnabled(modifiable && player_node->mSkillPoint > 0); + mIncButton->setEnabled(modifiable + && player_node->mSkillPoint > 0); } else mIncButton->setEnabled(false); diff --git a/src/gui/skill.h b/src/gui/skill.h index ee579dd5..2095e098 100644 --- a/src/gui/skill.h +++ b/src/gui/skill.h @@ -30,6 +30,7 @@ #include "scrollarea.h" #include "table.h" #include "window.h" +#include "table.h" #include "../guichanfwd.h" diff --git a/src/gui/status.h b/src/gui/status.h index 4fbce445..eb4171c9 100644 --- a/src/gui/status.h +++ b/src/gui/status.h @@ -68,7 +68,9 @@ class StatusWindow : public Window, public gcn::ActionListener /** * Status Part */ - gcn::Label *mLvlLabel, *mJobLvlLabel, *mGpLabel, *mHpLabel, *mHpValueLabel; + gcn::Label *mLvlLabel, *mJobLvlLabel; + gcn::Label *mGpLabel; + gcn::Label *mHpLabel, *mHpValueLabel; gcn::Label *mMpLabel, *mMpValueLabel; gcn::Label *mXpLabel, *mXpValueLabel, *mJobXpLabel, *mJobValueLabel; ProgressBar *mHpBar, *mMpBar; diff --git a/src/gui/table_model.h b/src/gui/table_model.h index 4022e369..a52a7561 100644 --- a/src/gui/table_model.h +++ b/src/gui/table_model.h @@ -127,9 +127,9 @@ public: */ virtual void resize(void); - virtual int getRows(); - virtual int getColumns(); - virtual int getRowHeight(); + virtual int getRows(void); + virtual int getColumns(void); + virtual int getRowHeight(void); virtual int getColumnWidth(int index); virtual gcn::Widget *getElementAt(int row, int column); diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 1097f072..36d00bec 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -309,14 +309,15 @@ int UpdaterWindow::downloadThread(void *ptr) curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); - struct curl_slist *pHeaders=NULL; - if(uw->mDownloadStatus != UPDATE_RESOURCES){ - /*caching breaks things when resources2.txt is cached - *so caching is turned off on the proxy with this header - *change*/ - pHeaders = curl_slist_append(pHeaders, "pragma: no-cache"); - pHeaders = curl_slist_append(pHeaders, "Cache-Control: no-cache"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pHeaders); + struct curl_slist *pHeaders = NULL; + if (uw->mDownloadStatus != UPDATE_RESOURCES) + { + // Make sure the resources2.txt and news.txt aren't cached, + // in order to always get the latest version. + pHeaders = curl_slist_append(pHeaders, "pragma: no-cache"); + pHeaders = + curl_slist_append(pHeaders, "Cache-Control: no-cache"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pHeaders); } if ((res = curl_easy_perform(curl)) != 0) @@ -343,8 +344,9 @@ int UpdaterWindow::downloadThread(void *ptr) curl_easy_cleanup(curl); - if(uw->mDownloadStatus != UPDATE_RESOURCES){ - curl_slist_free_all(pHeaders); + if (uw->mDownloadStatus != UPDATE_RESOURCES) + { + curl_slist_free_all(pHeaders); } if (!uw->mStoreInMemory) diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 3f0f546e..e50903b6 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -48,6 +48,8 @@ extern volatile int tick_time; +extern volatile int tick_time; + Viewport::Viewport(): mMap(0), mPixelViewX(0.0f), @@ -196,17 +198,16 @@ Viewport::draw(gcn::Graphics *gcnGraphics) } } - // Draw names + // Draw text if (textManager) { - textManager->draw(graphics, (int) mPixelViewX, (int) mPixelViewY); + textManager->draw(graphics, mPixelViewX, mPixelViewY); } - // Draw player speech, and emotion sprite as needed + // Draw player names, speech, and emotion sprite as needed Beings &beings = beingManager->getAll(); for (BeingIterator i = beings.begin(); i != beings.end(); i++) { - (*i)->drawSpeech(graphics, -(int) mPixelViewX, -(int) mPixelViewY); (*i)->drawEmotion(graphics, -(int) mPixelViewX, -(int) mPixelViewY); } diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 48964121..30456a81 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -22,6 +22,7 @@ #include <algorithm> #include <cassert> #include <climits> +#include <cassert> #include <guichan/exception.hpp> diff --git a/src/inventory.cpp b/src/inventory.cpp index d346a50b..da9aed02 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -50,7 +50,7 @@ Inventory::~Inventory() Item* Inventory::getItem(int index) const { - if (index < 0 || index >= mSize) + if (index < 0 || index >= INVENTORY_SIZE || !mItems[index] || mItems[index]->getQuantity() <= 0) return 0; return mItems[index]; @@ -146,3 +146,8 @@ int Inventory::getLastUsedSlot() const return -1; } + +int Inventory::getInventorySize() const +{ + return INVENTORY_SIZE - 2; +} diff --git a/src/inventory.h b/src/inventory.h index 566ca17c..91bb7d04 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -24,6 +24,8 @@ class Item; +#define INVENTORY_SIZE 102 + class Inventory { public: @@ -100,6 +102,11 @@ class Inventory */ int getLastUsedSlot() const; + /** + * Returns the number of slots available in the inventory. + */ + int getInventorySize() const; + protected: Item **mItems; /**< The holder of items */ int mSize; /**< The max number of inventory items */ diff --git a/src/joystick.cpp b/src/joystick.cpp index b3aba4fc..4cee4464 100644 --- a/src/joystick.cpp +++ b/src/joystick.cpp @@ -25,6 +25,8 @@ #include "joystick.h" #include "log.h" +#include <cassert> + int Joystick::joystickCount = 0; void Joystick::init() diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 7fdbc09b..292f70e0 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -30,6 +30,7 @@ #include "monster.h" #include "particle.h" #include "sound.h" +#include "monster.h" #include "gui/gui.h" @@ -508,9 +509,9 @@ void LocalPlayer::stopAttack() { setAction(STAND); mLastTarget = -1; - setTarget(NULL); - mLastTarget = -1; } + setTarget(NULL); + mLastTarget = -1; } Being* LocalPlayer::getTarget() const @@ -68,8 +68,8 @@ class Logger ; /** - * Log an error and quit. The error will pop-up in Windows and will be - * printed to standard error everywhere else. + * Log an error and quit. The error will pop-up on Windows and Mac, and + * will be printed to standard error everywhere else. */ void error(const std::string &error_text); diff --git a/src/logindata.h b/src/logindata.h index d2fe3043..6b733269 100644 --- a/src/logindata.h +++ b/src/logindata.h @@ -17,8 +17,6 @@ * You should have received a copy of the GNU General Public License * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: logindata.h 3606 2007-09-27 14:54:09Z b_lindeijer $ */ #ifndef _TMW_LOGINDATA_H diff --git a/src/main.cpp b/src/main.cpp index 279bae71..4049aa78 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,6 +60,7 @@ #include "gui/progressbar.h" #include "gui/register.h" #include "gui/setup.h" +#include "gui/updatewindow.h" #include "gui/textfield.h" #include "gui/updatewindow.h" @@ -185,6 +186,10 @@ void setUpdatesDir() config.getValue("updatehost", "http://www.aethyra.org/updates"); } + // Remove any trailing slash at the end of the update host + if (updateHost.at(updateHost.size() - 1) == '/') + updateHost.resize(updateHost.size() - 1); + // Parse out any "http://" or "ftp://", and set the updates directory size_t pos; pos = updateHost.find("://"); @@ -478,7 +483,7 @@ void printVersion() void parseOptions(int argc, char *argv[], Options &options) { - const char *optstring = "hvuU:P:Dp:C:H:"; + const char *optstring = "hvud:U:P:Dp:C:H:"; const struct option long_options[] = { { "configfile", required_argument, 0, 'C' }, @@ -498,9 +503,8 @@ void parseOptions(int argc, char *argv[], Options &options) int result = getopt_long(argc, argv, optstring, long_options, NULL); - if (result == -1) { + if (result == -1) break; - } switch (result) { case 'C': @@ -583,9 +587,10 @@ void accountLogin(Network *network, LoginData *loginData) outMsg.writeString(loginData->password, 24); /* - * eAthena calls the last byte "client version 2", but it isn't - * used at all. We're retasking it, with bit 0 to indicate whether - * the client can handle the 0x63 "update host" packet + * eAthena calls the last byte "client version 2", but it isn't used at + * at all. We're retasking it, with bit 0 to indicate whether the client + * can handle the 0x63 "update host" packet. Clients prior to 0.0.25 send + * 0 here. */ outMsg.writeInt8(0x01); @@ -903,17 +908,25 @@ int main(int argc, char *argv[]) case CHAR_SERVER_STATE: logger->log("State: CHAR_SERVER"); - if (n_server == 1) { + + if (n_server == 1) + { SERVER_INFO *si = *server_info; loginData.hostname = iptostring(si->address); loginData.port = si->port; loginData.updateHost = si->updateHost; state = UPDATE_STATE; - } else { - currentDialog = new ServerSelectDialog(&loginData); + } + else + { + int nextState = (options.skipUpdate) ? + LOADDATA_STATE : UPDATE_STATE; + currentDialog = new ServerSelectDialog(&loginData, + nextState); positionDialog(currentDialog, screenWidth, screenHeight); - if (options.chooseDefault || options.playername != "") { + if (options.chooseDefault || options.playername != "") + { ((ServerSelectDialog*) currentDialog)->action( gcn::ActionEvent(NULL, "ok")); } @@ -964,7 +977,7 @@ int main(int argc, char *argv[]) case UPDATE_STATE: // Determine which source to use for the update host - if(!options.updateHost.empty()) + if (!options.updateHost.empty()) updateHost = options.updateHost; else updateHost = loginData.updateHost; diff --git a/src/map.cpp b/src/map.cpp index 612d9020..02b046fb 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -71,22 +71,22 @@ MapLayer::MapLayer(int x, int y, int width, int height, bool isFringeLayer): mTiles = new Image*[size]; std::fill_n(mTiles, size, (Image*) 0); } - + MapLayer::~MapLayer() { delete[] mTiles; } - + void MapLayer::setTile(int x, int y, Image *img) { mTiles[x + y * mWidth] = img; } - + Image* MapLayer::getTile(int x, int y) const { return mTiles[x + y * mWidth]; } - + void MapLayer::draw(Graphics *graphics, int startX, int startY, int endX, int endY, @@ -97,43 +97,43 @@ void MapLayer::draw(Graphics *graphics, startY -= mY; endX -= mX; endY -= mY; - + if (startX < 0) startX = 0; if (startY < 0) startY = 0; if (endX > mWidth) endX = mWidth; if (endY > mHeight) endY = mHeight; - + Sprites::const_iterator si = sprites.begin(); - + for (int y = startY; y < endY; y++) { // If drawing the fringe layer, make sure all sprites above this row of // tiles have been drawn if (mIsFringeLayer) { - player_node->drawTargetCursor(graphics, scrollX, scrollY); - while (si != sprites.end() && (*si)->getPixelY() <= y * 32 - 32) { - (*si)->draw(graphics, -scrollX, -scrollY); - si++; - } + player_node->drawTargetCursor(graphics, scrollX, scrollY); + while (si != sprites.end() && (*si)->getPixelY() <= y * 32 - 32) { + (*si)->draw(graphics, -scrollX, -scrollY); + si++; + } } for (int x = startX; x < endX; x++) { - Image *img = getTile(x, y); - if (img) { - const int px = (x + mX) * 32 - scrollX; - const int py = (y + mY) * 32 - scrollY + 32 - img->getHeight(); - graphics->drawImage(img, px, py); - } - } + Image *img = getTile(x, y); + if (img) { + const int px = (x + mX) * 32 - scrollX; + const int py = (y + mY) * 32 - scrollY + 32 - img->getHeight(); + graphics->drawImage(img, px, py); + } + } } - + // Draw any remaining sprites if (mIsFringeLayer) { - while (si != sprites.end()) { - (*si)->draw(graphics, -scrollX, -scrollY); - si++; - } + while (si != sprites.end()) { + (*si)->draw(graphics, -scrollX, -scrollY); + si++; + } } } @@ -186,7 +186,7 @@ void Map::initializeOverlays() void Map::addLayer(MapLayer *layer) { - mLayers.push_back(layer); + mLayers.push_back(layer); } void Map::addTileset(Tileset *tileset) @@ -273,7 +273,7 @@ void Map::drawOverlay(Graphics *graphics, class ContainsGidFunctor { public: - bool operator() (Tileset* set) const + bool operator() (const Tileset* set) const { return (set->getFirstGid() <= gid && gid - set->getFirstGid() < (int)set->size()); diff --git a/src/monster.cpp b/src/monster.cpp index 62be513d..04624b8c 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -21,6 +21,7 @@ #include "animatedsprite.h" #include "game.h" +#include "localplayer.h" #include "monster.h" #include "particle.h" #include "sound.h" @@ -43,8 +44,8 @@ Monster::Monster(Uint32 id, Uint16 job, Map *map): // Setup Monster sprites int c = BASE_SPRITE; - const std::list<std::string> &sprites = info.getSprites(); + for (std::list<std::string>::const_iterator i = sprites.begin(); i != sprites.end(); i++) @@ -77,7 +78,10 @@ Monster::Monster(Uint32 id, Uint16 job, Map *map): Monster::~Monster() { if (mText) + { delete mText; + player_node->setTarget(NULL); + } } void Monster::logic() @@ -166,7 +170,8 @@ void Monster::handleAttack(Being *victim, int damage) Being::handleAttack(victim, damage); const MonsterInfo &mi = getInfo(); - sound.playSfx(mi.getSound((damage > 0) ? MONSTER_EVENT_HIT : MONSTER_EVENT_MISS)); + sound.playSfx(mi.getSound((damage > 0) ? + MONSTER_EVENT_HIT : MONSTER_EVENT_MISS)); } void Monster::takeDamage(int amount) diff --git a/src/monster.h b/src/monster.h index 0906dff3..cb8f7f18 100644 --- a/src/monster.h +++ b/src/monster.h @@ -75,8 +75,12 @@ class Monster : public Being * Update the text when the monster moves */ void updateCoords(); + private: - Text *mText; /**< holds a text object when the mod displays it's name, 0 otherwise */ + /** + * holds a text object when the mod displays it's name, 0 otherwise + */ + Text *mText; }; #endif diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index b016b5cf..3c022af6 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -204,21 +204,15 @@ void BeingHandler::handleMessage(MessageIn *msg) // If this is player's current target, clear it. if (dstBeing == player_node->getTarget()) - { player_node->stopAttack(); - } if (dstBeing == current_npc) current_npc = NULL; if (msg->readInt8() == 1) - { dstBeing->setAction(Being::DEAD); - } else - { beingManager->destroyBeing(dstBeing); - } break; @@ -236,27 +230,26 @@ void BeingHandler::handleMessage(MessageIn *msg) switch (type) { case 0x0a: // Critical Damage - if (dstBeing) { + if (dstBeing) dstBeing->showCrit(); - } - case 0x00: // Damage - if (dstBeing) { + case 0x00: // Damage + if (dstBeing) dstBeing->takeDamage(param1); - } - if (srcBeing) { + if (srcBeing) srcBeing->handleAttack(dstBeing, param1); - } break; case 0x02: // Sit - if (srcBeing) { + if (srcBeing) + { srcBeing->mFrame = 0; srcBeing->setAction(Being::SIT); } break; case 0x03: // Stand up - if (srcBeing) { + if (srcBeing) + { srcBeing->mFrame = 0; srcBeing->setAction(Being::STAND); } @@ -518,3 +511,4 @@ void BeingHandler::handleMessage(MessageIn *msg) break; } } + diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp index ad613889..b2fe99b9 100644 --- a/src/net/buysellhandler.cpp +++ b/src/net/buysellhandler.cpp @@ -113,6 +113,8 @@ void BuySellHandler::handleMessage(MessageIn *msg) if (msg->readInt8() == 0) { chatWindow->chatLog("Thanks for buying", BY_SERVER); } else { + // Reset player money since buy dialog already assumed purchase + // would go fine buyDialog->setMoney(player_node->mGp); chatWindow->chatLog("Unable to buy", BY_SERVER); } diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp index 833732db..281923f8 100644 --- a/src/net/charserverhandler.cpp +++ b/src/net/charserverhandler.cpp @@ -178,7 +178,7 @@ void CharServerHandler::handleMessage(MessageIn *msg) errorMessage = "Duplicated login"; break; default: - errorMessage = "Unkown error with 0x0081"; + errorMessage = "Unknown error with 0x0081"; break; } mCharInfo->unlock(); diff --git a/src/net/equipmenthandler.cpp b/src/net/equipmenthandler.cpp index 23a8063f..2e0cc562 100644 --- a/src/net/equipmenthandler.cpp +++ b/src/net/equipmenthandler.cpp @@ -117,6 +117,7 @@ void EquipmentHandler::handleMessage(MessageIn *msg) position++; } logger->log("Position %i", position); + item = player_node->getInventory()->getItem(player_node->mEquipment->getEquipment(position)); // Unequip any existing equipped item in this position @@ -155,6 +156,7 @@ void EquipmentHandler::handleMessage(MessageIn *msg) break; item->setEquipped(false); + if (equipPoint & 0x8000) { // Arrows player_node->mEquipment->setArrows(0); } @@ -176,6 +178,7 @@ void EquipmentHandler::handleMessage(MessageIn *msg) break; item = inventory->getItem(index); + if (item) { item->setEquipped(true); player_node->mEquipment->setArrows(index); diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp index 9a7aaabd..2b98e4e4 100644 --- a/src/net/loginhandler.cpp +++ b/src/net/loginhandler.cpp @@ -48,11 +48,11 @@ void LoginHandler::handleMessage(MessageIn *msg) { case 0x0063: int len; - - len = msg->readInt16() - 4; + + len = msg->readInt16() - 4; mUpdateHost = msg->readString(len); - logger->log("Received update host \"%s\" from login server", + logger->log("Received update host \"%s\" from login server", mUpdateHost.c_str()); break; @@ -107,10 +107,12 @@ void LoginHandler::handleMessage(MessageIn *msg) errorMessage = "Rejected from server"; break; case 4: - errorMessage = "You have been blocked by the GM Team"; + + errorMessage = "You have been permanently banned from the game. Please contact the GM Team"; break; case 6: - errorMessage = "You have been temporarily banned from the game until " + msg->readString(20) + ".\n Please contact the GM team"; + errorMessage = "You have been temporarily banned from the game until " + + msg->readString(20) + ".\n Please contact the GM team via the forums"; break; case 9: errorMessage = "This user name is already taken"; diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h index 1e087619..047434b4 100644 --- a/src/net/loginhandler.h +++ b/src/net/loginhandler.h @@ -25,6 +25,7 @@ #include <string> #include "messagehandler.h" +#include <string> struct LoginData; @@ -37,10 +38,8 @@ class LoginHandler : public MessageHandler void setLoginData(LoginData *loginData) { mLoginData = loginData; }; - protected: - LoginData *mLoginData; - private: + LoginData *mLoginData; std::string mUpdateHost; }; diff --git a/src/net/network.h b/src/net/network.h index 856808a2..43b4dbbc 100644 --- a/src/net/network.h +++ b/src/net/network.h @@ -27,9 +27,9 @@ #include <SDL_thread.h> #include <string> -#define TMW_CLIENT_PROTOCOL_VERSION 1 - /***< Protocol version, reported to the eAthena char and mapserver who - can adjust the protocol accordingly */ +#define TMW_CLIENT_PROTOCOL_VERSION 1 + /**< Protocol version, reported to the eAthena char and mapserver who + can adjust the protocol accordingly */ class MessageHandler; class MessageIn; diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index c8442a89..a4a2dcc9 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -133,7 +133,8 @@ void PlayerHandler::handleMessage(MessageIn *msg) player_node->stopAttack(); nearby = (engine->getCurrentMapName() == mapPath); - // Switch the actual map, deleting the previous one + + // Switch the actual map, deleting the previous one if necessary engine->changeMap(mapPath); current_npc = 0; diff --git a/src/net/protocol.h b/src/net/protocol.h index fabe6911..783283ba 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -27,6 +27,7 @@ *********************************/ #define SMSG_LOGIN_SUCCESS 0x0073 /**< Contains starting location */ #define SMSG_SERVER_PING 0x007f /**< Contains server tick */ +#define SMSG_UPDATE_HOST 0x0063 /**< Custom update host packet */ #define SMSG_PLAYER_UPDATE_1 0x01d8 #define SMSG_PLAYER_UPDATE_2 0x01d9 #define SMSG_PLAYER_MOVE 0x01da /**< A nearby player moves */ diff --git a/src/net/tradehandler.cpp b/src/net/tradehandler.cpp index 11fe2c19..746e1d06 100644 --- a/src/net/tradehandler.cpp +++ b/src/net/tradehandler.cpp @@ -127,7 +127,7 @@ void TradeHandler::handleMessage(MessageIn *msg) chatWindow->chatLog("Trade with " + tradePartnerName + " cancelled", BY_SERVER); // otherwise ignore silently - + tradeWindow->setVisible(false); player_node->setTrading(false); break; @@ -186,7 +186,7 @@ void TradeHandler::handleMessage(MessageIn *msg) "partner is over weighted.", BY_SERVER); break; - case 2: + case 2: // Add item failed - player has no free slot chatWindow->chatLog("Failed adding item. Trade " "partner has no free slot.", diff --git a/src/npc.cpp b/src/npc.cpp index 78670581..8dbbf83c 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -21,6 +21,7 @@ #include "animatedsprite.h" #include "graphics.h" +#include "localplayer.h" #include "npc.h" #include "particle.h" #include "text.h" @@ -42,7 +43,7 @@ NPC::NPC(Uint32 id, Uint16 job, Map *map, Network *network): { NPCInfo info = NPCDB::get(job); - //setup NPC sprites + // Setup NPC sprites int c = BASE_SPRITE; for (std::list<NPCsprite*>::const_iterator i = info.sprites.begin(); i != info.sprites.end(); @@ -75,6 +76,7 @@ NPC::~NPC() if (mName) { delete mName; + player_node->setTarget(NULL); } } diff --git a/src/particlecontainer.cpp b/src/particlecontainer.cpp new file mode 100644 index 00000000..12ef5733 --- /dev/null +++ b/src/particlecontainer.cpp @@ -0,0 +1,177 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <cassert> + +#include "particlecontainer.h" + + +ParticleContainer::ParticleContainer(ParticleContainer *parent, bool delParent) : + mDelParent(delParent), + mNext(parent) +{}; + +ParticleContainer::~ParticleContainer() +{ + clearLocally(); + if (mNext && mDelParent) + delete mNext; +} + +void +ParticleContainer::clear() +{ + clearLocally(); + if (mNext) + mNext->clear(); +} + + +void +ParticleContainer::setPositions(float x, float y) +{ + if (mNext) + mNext->setPositions(x, y); +} + +// -- particle list ---------------------------------------- + +ParticleList::ParticleList(ParticleContainer *parent, bool delParent) : + ParticleContainer(parent, delParent) {}; + +ParticleList::~ParticleList() {} + +void +ParticleList::addLocally(Particle *particle) +{ + if (particle) + { + // The effect may not die without the beings permission or we segfault + particle->disableAutoDelete(); + mElements.push_back(particle); + } +} + +void +ParticleList::removeLocally(Particle *particle) +{ + for (std::list<Particle *>::iterator it = mElements.begin(); + it != mElements.end(); it++) + if (*it == particle) { + (*it)->kill(); + mElements.erase(it); + } +} + +void +ParticleList::clearLocally() +{ + for (std::list<Particle *>::iterator it = mElements.begin(); + it != mElements.end(); it++) + (*it)->kill(); + + mElements.clear(); +} + +void +ParticleList::setPositions(float x, float y) +{ + ParticleContainer::setPositions(x, y); + + for (std::list<Particle *>::iterator it = mElements.begin(); + it != mElements.end();) + { + (*it)->setPosition(x, y); + if ((*it)->isExtinct()) + { + (*it)->kill(); + it = mElements.erase(it); + } + else + it++; + } +} + + + + +// -- particle vector ---------------------------------------- + +ParticleVector::ParticleVector(ParticleContainer *parent, bool delParent) : + ParticleContainer(parent, delParent) {}; + +ParticleVector::~ParticleVector() {}; + +void +ParticleVector::setLocally(int index, Particle *particle) +{ + assert(index >= 0); + + delLocally(index); + + if (mIndexedElements.size() <= (unsigned) index) + mIndexedElements.resize(index + 1, NULL); + + mIndexedElements[index] = particle; +} + +void +ParticleVector::delLocally(int index) +{ + assert(index >= 0); + + if (mIndexedElements.size() <= (unsigned) index) + return; + + Particle *p = mIndexedElements[index]; + if (p) + { + mIndexedElements[index] = NULL; + p->kill(); + } +} + +void +ParticleVector::clearLocally() +{ + for (unsigned int i = 0; i < mIndexedElements.size(); i++) + delLocally(i); +} + +void +ParticleVector::setPositions(float x, float y) +{ + ParticleContainer::setPositions(x, y); + + for (std::vector<Particle *>::iterator it = mIndexedElements.begin(); + it != mIndexedElements.end(); it++) + if (*it) + { + (*it)->setPosition(x, y); + + if ((*it)->isExtinct()) + { + (*it)->kill(); + *it = NULL; + } + } +} + diff --git a/src/particlecontainer.h b/src/particlecontainer.h new file mode 100644 index 00000000..cf002fbc --- /dev/null +++ b/src/particlecontainer.h @@ -0,0 +1,125 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PARTICLE_CONTAINER_H +#define _PARTICLE_CONTAINER_H + +#include <list> +#include <vector> + +#include "particle.h" + + +/** + * Set of particle effects. May be stacked with other ParticleContainers. All + * operations herein affect such stacked containers, unless the operations end + * in `Locally'. + */ +class ParticleContainer +{ +public: + /** + * Constructs a new particle container and assumes responsibility for + * its parent (for all operations defined herein, except when ending in `Locally') + * + * delParent means that the destructor should also free the parent. + */ + ParticleContainer(ParticleContainer *parent = NULL, bool delParent = true); + virtual ~ParticleContainer(); + + /** + * Kills and removes all particle effects + */ + void clear(); + + /** + * Kills and removes all particle effects (only in this container) + */ + virtual void clearLocally() {}; + + /** + * Sets the positions of all elements + */ + virtual void setPositions(float x, float y); + +protected: + bool mDelParent; /**< Delete mNext in destructor */ + ParticleContainer *mNext; /**< Contained container, if any */ +}; + + + +/** + * Linked list of particle effects. + */ +class ParticleList : public ParticleContainer +{ +public: + ParticleList(ParticleContainer *parent = NULL, bool delParent = true); + virtual ~ParticleList(); + + /** + * Takes control of and adds a particle + */ + void addLocally(Particle *); + + /** + * `kills' and removes a particle + */ + void removeLocally(Particle *); + + virtual void clearLocally(); + + virtual void setPositions(float x, float y); + +protected: + std::list<Particle *> mElements; /**< Contained particle effects */ +}; + + +/** + * Particle container with indexing facilities + */ +class ParticleVector : public ParticleContainer +{ +public: + ParticleVector(ParticleContainer *parent = NULL, bool delParent = true); + virtual ~ParticleVector(); + + /** + * Sets a particle at a specified index. Kills the previous particle + * there, if needed. + */ + virtual void setLocally(int index, Particle *particle); + + /** + * Removes a particle at a specified index + */ + virtual void delLocally(int index); + + virtual void clearLocally(); + virtual void setPositions(float x, float y); + +protected: + std::vector<Particle *> mIndexedElements; +}; + +#endif diff --git a/src/player.cpp b/src/player.cpp index 1a7480db..e6244bb5 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -212,3 +212,4 @@ void Player::updateCoords() mName->adviseXY(mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET); } } + diff --git a/src/player_relations.cpp b/src/player_relations.cpp index 157cc09b..ef00a738 100644 --- a/src/player_relations.cpp +++ b/src/player_relations.cpp @@ -337,9 +337,9 @@ public: virtual void ignore(Player *player, unsigned int flags) - { - player->flash(200); - } + { + player->flash(200); + } }; class PIS_emote : public PlayerIgnoreStrategy diff --git a/src/resources/colordb.cpp b/src/resources/colordb.cpp index 46acaf39..3d2e15e0 100644 --- a/src/resources/colordb.cpp +++ b/src/resources/colordb.cpp @@ -56,8 +56,7 @@ void ColorDB::load() TMWHair = true; - if (doc) - delete doc; + delete doc; doc = new XML::Document(TMW_COLOR_FILE); root = doc->rootNode(); @@ -67,8 +66,7 @@ void ColorDB::load() mColors[0] = mFail; mLoaded = true; - if (doc) - delete doc; + delete doc; return; } @@ -91,8 +89,7 @@ void ColorDB::load() } } - if (doc) - delete doc; + delete doc; mLoaded = true; } diff --git a/src/resources/imageset.h b/src/resources/imageset.h index c7915212..26ce99ea 100644 --- a/src/resources/imageset.h +++ b/src/resources/imageset.h @@ -47,17 +47,17 @@ class ImageSet : public Resource /** * Returns the width of the images in the image set. */ - int getWidth() { return mWidth; }; + int getWidth() const { return mWidth; }; /** * Returns the height of the images in the image set. */ - int getHeight() { return mHeight; }; + int getHeight() const { return mHeight; }; typedef std::vector<Image*>::size_type size_type; Image* get(size_type i) const; - size_type size() { return mImages.size(); } + size_type size() const { return mImages.size(); } private: std::vector<Image*> mImages; diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 894cc4fc..b4beb558 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -240,7 +240,8 @@ MapReader::readMap(xmlNodePtr node, const std::string &path) { if (xmlStrEqual(objectNode->name, BAD_CAST "object")) { - const std::string objType = XML::getProperty(objectNode, "type", ""); + const std::string objType = + XML::getProperty(objectNode, "type", ""); if (objType == "WARP" || objType == "NPC" || objType == "SCRIPT" || objType == "SPAWN") @@ -249,12 +250,14 @@ MapReader::readMap(xmlNodePtr node, const std::string &path) continue; } - const std::string objName = XML::getProperty(objectNode, "name", ""); + const std::string objName = + XML::getProperty(objectNode, "name", ""); const int objX = XML::getProperty(objectNode, "x", 0); const int objY = XML::getProperty(objectNode, "y", 0); logger->log("- Loading object name: %s type: %s at %d:%d", - objName.c_str(), objType.c_str(), objX, objY); + objName.c_str(), objType.c_str(), + objX, objY); if (objType == "PARTICLE_EFFECT") { @@ -263,7 +266,9 @@ MapReader::readMap(xmlNodePtr node, const std::string &path) continue; } - map->addParticleEffect(objName, objX + offsetX, objY + offsetY); + map->addParticleEffect(objName, + objX + offsetX, + objY + offsetY); } else { @@ -302,13 +307,14 @@ static void setTile(Map *map, MapLayer *layer, int x, int y, int gid) // Set regular tile on a layer Image * const img = set ? set->get(gid - set->getFirstGid()) : 0; layer->setTile(x, y, img); - } else { + } else { // Set collision tile map->setWalk(x, y, (!set || (gid - set->getFirstGid() == 0))); - } + } } -void MapReader::readLayer(xmlNodePtr node, Map *map) +void +MapReader::readLayer(xmlNodePtr node, Map *map) { // Layers are not necessarily the same size as the map const int w = XML::getProperty(node, "width", map->getWidth()); @@ -323,25 +329,25 @@ void MapReader::readLayer(xmlNodePtr node, Map *map) MapLayer *layer = 0; if (!isCollisionLayer) { - layer = new MapLayer(offsetX, offsetY, w, h, isFringeLayer); - map->addLayer(layer); + layer = new MapLayer(offsetX, offsetY, w, h, isFringeLayer); + map->addLayer(layer); } logger->log("- Loading layer \"%s\"", name.c_str()); int x = 0; int y = 0; - + // Load the tile data for_each_xml_child_node(childNode, node) { if (!xmlStrEqual(childNode->name, BAD_CAST "data")) - continue; - + continue; + const std::string encoding = - XML::getProperty(childNode, "encoding", ""); + XML::getProperty(childNode, "encoding", ""); const std::string compression = - XML::getProperty(childNode, "compression", ""); - + XML::getProperty(childNode, "compression", ""); + if (encoding == "base64") { if (!compression.empty() && compression != "gzip") { @@ -382,11 +388,11 @@ void MapReader::readLayer(xmlNodePtr node, Map *map) unsigned char *inflated; unsigned int inflatedSize = inflateMemory(binData, binLen, inflated); - + free(binData); binData = inflated; binLen = inflatedSize; - + if (!inflated) { logger->log("Error: Could not decompress layer!"); return; @@ -400,11 +406,12 @@ void MapReader::readLayer(xmlNodePtr node, Map *map) binData[i + 3] << 24; setTile(map, layer, x, y, gid); - + x++; - if (x == w) - { + if (x == w) { x = 0; y++; + + // When we're done, don't crash on too much data if (y == h) break; } @@ -418,17 +425,17 @@ void MapReader::readLayer(xmlNodePtr node, Map *map) { if (!xmlStrEqual(childNode2->name, BAD_CAST "tile")) continue; - - const int gid = XML::getProperty(childNode2, "gid", -1); - setTile(map, layer, x, y, gid); - - x++; - if (x == w) { - x = 0; y++; - if (y >= h) - break; - } - } + + const int gid = XML::getProperty(childNode2, "gid", -1); + setTile(map, layer, x, y, gid); + + x++; + if (x == w) { + x = 0; y++; + if (y >= h) + break; + } + } } if (y < h) @@ -31,43 +31,41 @@ class TextManager; class Text { - friend class TextManager; + friend class TextManager; + public: /** - * Constructor creates a text object to display on the screen + * Constructor creates a text object to display on the screen. */ Text(const std::string &text, int x, int y, gcn::Graphics::Alignment alignment, gcn::Font *font, gcn::Color colour); /** - * Allows the originator of the text to specify the ideal coordinates + * Destructor. The text is removed from the screen. */ - void - adviseXY(int x, int y); + virtual ~Text(); /** - * Remove the text from the screen + * Allows the originator of the text to specify the ideal coordinates. */ - virtual ~Text(); + void adviseXY(int x, int y); /** - * Draws the text + * Draws the text. */ - virtual void - draw(Graphics *graphics, int xOff, int yOff); - - protected: + virtual void draw(Graphics *graphics, int xOff, int yOff); - int mX; /**< Actual x-value of left of text written */ - int mY; /**< Actual y-value of top of text written */ - int mWidth; /**< The width of the text */ - int mHeight; /**< The height of the text */ - int mXOffset; /**< The offset of mX from the desired x */ - static int mInstances; /**< Instances of text */ - gcn::Font *mFont; /**< The font used */ - std::string mText; /**< The text to display */ - gcn::Color mColour; /**< The colour of the text */ + private: + int mX; /**< Actual x-value of left of text written. */ + int mY; /**< Actual y-value of top of text written. */ + int mWidth; /**< The width of the text. */ + int mHeight; /**< The height of the text. */ + int mXOffset; /**< The offset of mX from the desired x. */ + static int mInstances; /**< Instances of text. */ + gcn::Font *mFont; /**< The font used. */ + std::string mText; /**< The text to display. */ + gcn::Color mColour; /**< The colour of the text. */ }; class FlashText : public Text @@ -90,10 +88,9 @@ class FlashText : public Text /** * Draws the text */ - virtual void - draw(Graphics *graphics, int xOff, int yOff); + virtual void draw(Graphics *graphics, int xOff, int yOff); private: - int mTime; /**< Time left for flashing */ + int mTime; /**< Time left for flashing */ }; #endif diff --git a/src/tileset.h b/src/tileset.h index fb5593ef..fb855831 100644 --- a/src/tileset.h +++ b/src/tileset.h @@ -17,8 +17,6 @@ * You should have received a copy of the GNU General Public License * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: tileset.h 3753 2007-11-20 12:27:56Z b_lindeijer $ */ #ifndef _TMW_TILESET_H_ diff --git a/src/utils/fastsqrt.h b/src/utils/fastsqrt.h index 8da1d354..78768149 100644 --- a/src/utils/fastsqrt.h +++ b/src/utils/fastsqrt.h @@ -1,24 +1,24 @@ -/* A very fast function to calculate the approximate inverse square root of a
- * floating point value and a helper function that uses it for getting the
- * normal squareroot. For an explanation of the inverse squareroot function
- * read:
- * http://www.math.purdue.edu/~clomont/Math/Papers/2003/InvSqrt.pdf
- *
- * Unfortunately the original creator of this function seems to be unknown.
- */
-
-float fastInvSqrt(float x)
-{
- union { int i; float x; } tmp;
- float xhalf = 0.5f * x;
- tmp.x = x;
- tmp.i = 0x5f375a86 - (tmp.i >> 1);
- x = tmp.x;
- x = x * (1.5f - xhalf * x * x);
- return x;
-}
-
-float fastSqrt(float x)
-{
- return 1.0f / fastInvSqrt(x);
-}
+/* A very fast function to calculate the approximate inverse square root of a + * floating point value and a helper function that uses it for getting the + * normal squareroot. For an explanation of the inverse squareroot function + * read: + * http://www.math.purdue.edu/~clomont/Math/Papers/2003/InvSqrt.pdf + * + * Unfortunately the original creator of this function seems to be unknown. + */ + +float fastInvSqrt(float x) +{ + union { int i; float x; } tmp; + float xhalf = 0.5f * x; + tmp.x = x; + tmp.i = 0x5f375a86 - (tmp.i >> 1); + x = tmp.x; + x = x * (1.5f - xhalf * x * x); + return x; +} + +float fastSqrt(float x) +{ + return 1.0f / fastInvSqrt(x); +} diff --git a/src/winver.h b/src/winver.h index 3c6e7aed..f56d0c6b 100644 --- a/src/winver.h +++ b/src/winver.h @@ -3,4 +3,4 @@ #define VER_MINOR 0
#define VER_RELEASE 27
#define VER_BUILD 0
-#define PACKAGE_VERSION "0.0.27"
+#define PACKAGE_VERSION "0.0.27" |