Ejemplo n.º 1
0
InputManager::InputManager()
{
    keyboard.init();
    Joystick::init();
    // TODO: The user should be able to choose which one to use
    // Open the first device
    if (Joystick::getNumberOfJoysticks() > 0)
        joystick = new Joystick(0);
}
Ejemplo n.º 2
0
const QIcon Flags::getIconWithText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig)
{
    QString keySuffix(getPixmapKey(keyboardConfig));
    QString key(layoutUnit.toString() + keySuffix);
    if( iconOrTextMap.contains(key) ) {
        return iconOrTextMap[ key ];
    }

    if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_FLAG ) {
        QIcon icon = getIcon(layoutUnit.layout);
        if( ! icon.isNull() ) {
            iconOrTextMap[ key ] = icon;
            return icon;
        }
    }

    QString layoutText = Flags::getShortText(layoutUnit, keyboardConfig);

    const QSize TRAY_ICON_SIZE(21, 14);
    QPixmap pixmap = QPixmap(TRAY_ICON_SIZE);
    pixmap.fill(Qt::transparent);

    QPainter painter(&pixmap);
//	p.setRenderHint(QPainter::SmoothPixmapTransform);
//	p.setRenderHint(QPainter::Antialiasing);

    if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_LABEL_ON_FLAG ) {
        QIcon iconf = createIcon(layoutUnit.layout);
        iconf.paint(&painter, painter.window(), Qt::AlignCenter);
    }

    drawLabel(painter, layoutText, keyboardConfig.isFlagShown());

    painter.end();

    QIcon icon(pixmap);
    iconOrTextMap[ key ] = icon;

    return icon;
}
Ejemplo n.º 3
0
bool InputManager::handleKeyboardInput(const SDL_Event &event)
{
    bool used = false;
    bool metaKeyHeld = false;

    // Key press events
    if (event.type == SDL_KEYDOWN)
    {
        if (setupWindow->isVisible() &&
            keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
        {
            keyboard.setNewKey((int) event.key.keysym.sym);
            keyboard.callbackNewKey();
            keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
            return false;
        }

        // If the user is configuring the keys then don't respond.
        if (!keyboard.isEnabled())
            return false;

        const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);

        // Ignore input if either "ignore" key is pressed
        // Stops the character moving about if the user's window manager
        // uses "ignore+arrow key" to switch virtual desktops.
        if (keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_1) ||
            keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_2))
        {
            return false;
        }

        if (keyboard.isKeyLocked(event.key.keysym.sym))
            return false;

        gcn::Window *requestedWindow = NULL;

        switch (tKey)
        {
            // In-game Help
            case KeyboardConfig::KEY_WINDOW_HELP:
                requestedWindow = helpDialog;
                break;
            // Quitting confirmation dialog
            case KeyboardConfig::KEY_QUIT:
                stateManager->promptForQuit();
                used = true;
                break;
            case KeyboardConfig::KEY_WINDOW_DEBUG:
                requestedWindow = debugWindow;
                break;
            case KeyboardConfig::KEY_WINDOW_SETUP:
                requestedWindow = setupWindow;
                break;
            // Screenshot (picture, hence the p)
            case KeyboardConfig::KEY_SCREENSHOT:
                saveScreenshot();
                used = true;
                break;
        }

        if (stateManager->isInGame())
        {
            switch (tKey)
            {
                case KeyboardConfig::KEY_SCROLL_CHAT_UP:
                    if (chatWindow && chatWindow->isVisible())
                    {
                        chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
                        used = true;
                    }
                    break;
                case KeyboardConfig::KEY_SCROLL_CHAT_DOWN:
                    if (chatWindow && chatWindow->isVisible())
                    {
                        chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
                        used = true;
                    }
                    break;
                case KeyboardConfig::KEY_WINDOW_STATUS:
                    requestedWindow = statusWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_INVENTORY:
                    requestedWindow = inventoryWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_EQUIPMENT:
                    requestedWindow = equipmentWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_SKILL:
                    requestedWindow = skillDialog;
                    break;
                case KeyboardConfig::KEY_WINDOW_MINIMAP:
                    minimap->toggle();
                    break;
                case KeyboardConfig::KEY_WINDOW_CHAT:
                    requestedWindow = chatWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_EMOTE:
                    requestedWindow = emoteWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_ITEM_SHORTCUT:
                    requestedWindow = itemShortcutWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_EMOTE_SHORTCUT:
                    requestedWindow = emoteShortcutWindow;
                    break;
                // Hide certain windows
                case KeyboardConfig::KEY_HIDE_WINDOWS:
                    statusWindow->hide();
                    inventoryWindow->hide();
                    equipmentWindow->hide();
                    skillDialog->hide();
                    chatWindow->hide();
                    itemShortcutWindow->hide();
                    setupWindow->hide();
                    debugWindow->hide();
                    emoteWindow->hide();
                    helpDialog->hide();
                    emoteShortcutWindow->hide();
                    minimap->hide();
                    used = true;
                    break;
                // Find path to mouse (debug purpose)
                case KeyboardConfig::KEY_PATHFIND:
                    viewport->toggleDebugPath();
                    used = true;
                    break;
                default:
                    break;
            }

            metaKeyHeld = keyboard.isKeyActive(keyboard.KEY_METAKEY);

            for (int i = 0; i <= SHORTCUTS; i++)
            {
                ShortcutHandler *shortcut = metaKeyHeld ? (ShortcutHandler *) emoteShortcut :
                                                          (ShortcutHandler *) itemShortcut;
                const int offset = metaKeyHeld ? KeyboardConfig::KEY_EMOTE_SHORTCUT_1 :
                                                 KeyboardConfig::KEY_ITEM_SHORTCUT_1;

                if (keyboard.isKeyActive(i + offset))
                {
                    shortcut->useShortcut(i);
                    used = true;
                    break;
                }
            }

            if (keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT) && chatWindow)
            {
                chatWindow->requestChatFocus();
                used = true;
            }

            // Player actions
            if (player_node && player_node->mAction != Being::DEAD)
            {
                Being *target = player_node->getTarget();
                const Uint16 x = player_node->mX;
                const Uint16 y = player_node->mY;

                if (!keyboard.isKeyActive(keyboard.KEY_CLEAR_TARGET))
                {
                    Being::Type type = Being::INVALID;

                    // Target the nearest monster
                    if (keyboard.isKeyActive(keyboard.KEY_TARGET_MONSTER))
                        type = Being::MONSTER;
                    // Target the nearest player
                    else if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER))
                        type = Being::PLAYER;
                    // Target the nearest npc
                    else if (keyboard.isKeyActive(keyboard.KEY_TARGET_NPC))
                        type = Being::NPC;

                    target = beingManager->findNearestLivingBeing(x, y, 20,
                                           type != Being::INVALID ? type :
                                                   Being::UNKNOWN);

                    if (type != Being::INVALID && !targetKeyHeld)
                    {
                        player_node->setTarget(target);
                        targetKeyHeld = true;
                        used = true;
                    }
                    else if (player_node->isAttacking())
                        target = NULL;

                    if (keyboard.isKeyActive(keyboard.KEY_ATTACK) && target)
                    {
                        player_node->attack(player_node->getTarget() ?
                                            player_node->getTarget() : target,
                                            target->getType() != Being::NPC);
                        used = true;
                    }
                }
                // Stop attacking
                else if (keyboard.isKeyActive(keyboard.KEY_CLEAR_TARGET))
                {
                    player_node->stopAttack();
                    targetKeyHeld = false;
                }

                if (keyboard.isKeyActive(keyboard.KEY_BEING_MENU))
                {
                    target = player_node->getTarget();

                    if (!target)
                        target = beingManager->findNearestLivingBeing(x, y, 20);

                    if (target)
                    {
                        Map *map = viewport->getMap();
                        viewport->showPopup(target->mX * map->getTileWidth() -
                                            viewport->getCameraX() +
                                           (map->getTileWidth() / 2),
                                            target->mY * map->getTileHeight() -
                                            viewport->getCameraY(), target);
                    }
                    used = true;
                }

                switch (tKey)
                {
                    case KeyboardConfig::KEY_PICKUP:
                        {
                            Uint16 x = player_node->mX;
                            Uint16 y = player_node->mY;
                            FloorItem *item = floorItemManager->
                                                  findNearestItem(x, y);

                            if (item)
                                player_node->pickUp(item);

                            used = true;
                        }
                        break;
                    // Player sit action
                    case KeyboardConfig::KEY_SIT:
                        player_node->toggleSit();
                        used = true;
                        break;
                    // Toggle accepting of incoming trade requests
                    case KeyboardConfig::KEY_TRADE:
                        {
                            unsigned int deflt = player_relations.getDefault();
                            if (deflt & PlayerRelation::TRADE)
                            {
                                chatWindow->chatLog(_("Ignoring incoming "
                                                      "trade requests"),
                                                      Palette::SYSTEM);
                                deflt &= ~PlayerRelation::TRADE;
                            }
                            else
                            {
                                chatWindow->chatLog(_("Accepting incoming "
                                                      "trade requests"),
                                                      Palette::SYSTEM);
                                deflt |= PlayerRelation::TRADE;
                            }

                            player_relations.setDefault(deflt);
                            used = true;
                        }
                        break;
               }
            }
        }

        if (requestedWindow)
        {
            requestedWindow->setVisible(!requestedWindow->isVisible());
            used = true;
        }
    }
    else if (event.type == SDL_KEYUP)
    {
        const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);

        // Stop protecting the target keys
        if (tKey == KeyboardConfig::KEY_TARGET_MONSTER ||
            tKey == KeyboardConfig::KEY_TARGET_PLAYER || 
            tKey == KeyboardConfig::KEY_TARGET_NPC)
        {
            targetKeyHeld = false;
        }
    }

    // At the moment, this is the only bit of logic left not assigned to a
    // specific SDL input poll, because it was causing continuous walking
    // without stopping. It would be better in the long run if this would get
    // fixed and then moved to one of them (in case we ever use other input
    // libraries. If everything is already grouped together, it'd be easier to
    // adapt to a new library, instead of having to rely on special cases)
    if (stateManager->isInGame() && player_node->mAction != Being::DEAD && !used)
    {
        unsigned char direction = 0;

        // Get the state of the keyboard keys
        keyboard.refreshActiveKeys();

        // Translate pressed keys to movement and direction
        if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP))
            direction |= Being::UP;
        else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN))
            direction |= Being::DOWN;

        if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT))
            direction |= Being::LEFT;
        else if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT))
            direction |= Being::RIGHT;

        if (metaKeyHeld && direction != 0)
            player_node->setDirection(direction);
        else
            player_node->setWalkingDir(direction);
    }

    return used;
}
Ejemplo n.º 4
0
void InputManager::handleJoystickInput(const SDL_Event &event)
{
    if (joystick)
        joystick->update();
    else
        return;

    if (!stateManager->isInGame())
        return;

    if (event.type == SDL_JOYBUTTONUP && !joystick->buttonPressed(3))
    {
        targetKeyHeld = false; // Stop protecting the target key
    }
    else if (player_node && player_node->mAction != Being::DEAD)
    {
        const Uint16 x = player_node->mX;
        const Uint16 y = player_node->mY;

        if (!keyboard.isKeyActive(keyboard.KEY_CLEAR_TARGET))
        {
            Being *target = player_node->getTarget();

            // Target the nearest monster
            if (joystick->buttonPressed(3) && !targetKeyHeld)
            {
                target = beingManager->findNearestLivingBeing(x, y, 20,
                                                              Being::MONSTER);
                player_node->setTarget(target);
                targetKeyHeld = true;
            }

            if (joystick->buttonPressed(0) && target &&
                target->getType() != Being::NPC)
            {
                player_node->attack(target, true);
            }
        }

        if (joystick->buttonPressed(1))
        {
            FloorItem *item = floorItemManager->findByCoordinates(x, y);

            if (item)
                player_node->pickUp(item);
        }

        if (joystick->buttonPressed(2))
            player_node->toggleSit();

        unsigned char direction = 0;

        // Translate pressed keys to movement and direction
        if (joystick->isUp())
            direction |= Being::UP;
        else if (joystick->isDown())
            direction |= Being::DOWN;

        if (joystick->isLeft())
            direction |= Being::LEFT;
        else if (joystick->isRight())
            direction |= Being::RIGHT;

        player_node->setWalkingDir(direction);
    }
}
Ejemplo n.º 5
0
void Keyboard::mousePressEvent(QMouseEvent *e)
{
    clearHighlight(); // typing fast?

    int i2 = ((e->x() - xoffs) * 2) / defaultKeyWidth;
    int j = (e->y() - picks->height()) / keyHeight;

    int k = keycode( i2, j, (const uchar **)((useOptiKeys) ? keyboard_opti : keyboard_standard) );
    bool need_repaint = FALSE;
    unicode = -1;
    qkeycode = 0;
    if ( k >= 0x80 ) {
	if ( k == ShiftCode ) {
	    shift = !shift;
	    need_repaint = TRUE;
	} else if ( k == AltCode ){
	    alt = !alt;
	    need_repaint = TRUE;
	} else if ( k == CapsCode ) {
	    lock = !lock;
	    need_repaint = TRUE;
	} else if ( k == CtrlCode ) {
	    ctrl = !ctrl;
	    need_repaint = TRUE;
	} else if ( k == 0224 /* Expand */ ) {
	    useLargeKeys = !useLargeKeys;
	    resizeEvent(0);
	    repaint( TRUE ); // need it to clear first
	} else if ( k == 0225 /* Opti/Toggle */ ) {
	    useOptiKeys = !useOptiKeys;
	    resizeEvent(0);
	    repaint( TRUE ); // need it to clear first
	} else {
	    qkeycode = specialM[ k - 0x80 ].qcode;
	    unicode = specialM[ k - 0x80 ].unicode;
	}
    } else {
#if defined(Q_WS_QWS) || defined(_WS_QWS_)
/*
	qk = QWSServer::keyMap()[k].key_code;
	if ( qk != Key_unknown ) {
		if ( ctrl )
		    u = QWSServer::keyMap()[k].ctrl_unicode;
		else if ( shift^lock )
		    u = QWSServer::keyMap()[k].shift_unicode;
		else
		    u = QWSServer::keyMap()[k].unicode;
	}
*/
	char shifted = k;
	if ( !isalpha( k ) ) {
	    // ### Fixme, bad code, needs improving, whole thing needs to
	    // be re-coded to get rid of the way it did things with scancodes etc
	    for ( unsigned i = 0; i < sizeof(shiftMap)/sizeof(ShiftMap); i++ )
		if ( shiftMap[i].normal == k )
		    shifted = shiftMap[i].shifted;
	} else {
	    shifted = toupper( k );
	}
	QChar tempChar( shift^lock ? shifted : k );
	unicode = tempChar.unicode();
#endif
    }
    if  ( unicode != -1 ) {
	modifiers = (shift ? Qt::ShiftButton : 0) | (ctrl ? Qt::ControlButton : 0) |
		  (alt ? Qt::AltButton : 0);
#if defined(Q_WS_QWS) || defined(_WS_QWS_)
	emit key( unicode, qkeycode, modifiers, true, false );
	repeatTimer->start( 500 );
#endif
	need_repaint = shift || alt || ctrl;
	shift = alt = ctrl = FALSE;
	//qDebug( "pressed %d -> %04x ('%c')", k, u, u&0xffff < 256 ? u&0xff : 0 );

	KeyboardConfig *dc = picks->dc;

	if (dc) {
	    if (qkeycode == Qt::Key_Backspace) {
		dc->input.remove(dc->input.last()); // remove last input
		dc->decBackspaces();
	    } else if ( k == 0226 || qkeycode == Qt::Key_Return ||
		        qkeycode == Qt::Key_Space ||
			QChar(unicode).isPunct() ) {
		dc->input.clear();
		dc->resetBackspaces();
	    } else {
		dc->add(QString(QChar(unicode)));
		dc->incBackspaces();
	    }
	}

	picks->repaint();

    }
    pressedKey = k;
    if ( need_repaint ) {
	repaint( FALSE );
    } else {
	QPainter p(this);
	drawKeyboard( p, pressedKey );
    }
    pressTid = startTimer(80);
    pressed = TRUE;
}
Ejemplo n.º 6
0
void OptionsScreenInput2::gotSensedInput(const Input& sensed_input)
{
    const bool keyboard = (m_config->getType() == DEVICE_CONFIG_TYPE_KEYBOARD&&
                           sensed_input.m_type == Input::IT_KEYBOARD);
    const bool gamepad =  (sensed_input.m_type == Input::IT_STICKMOTION ||
                           sensed_input.m_type == Input::IT_STICKBUTTON) &&
                           m_config->getType() == DEVICE_CONFIG_TYPE_GAMEPAD;

    if (keyboard)
    {
        if (UserConfigParams::logMisc())
        {
            Log::info("OptionsScreenInput2", "Binding %s: setting to keyboard key %d",
                KartActionStrings[binding_to_set].c_str(), sensed_input.m_button_id);
        }

        KeyboardConfig* keyboard = (KeyboardConfig*)m_config;
        keyboard->setBinding(binding_to_set, Input::IT_KEYBOARD,
                             sensed_input.m_button_id, Input::AD_NEUTRAL,
                             Input::AR_HALF,
                             sensed_input.m_character);

        // refresh display
        updateInputButtons();
    }
    else if (gamepad)
    {
        if (UserConfigParams::logMisc())
        {
            Log::info("OptionsScreenInput2", "Binding %s: setting to gamepad #%d",
                KartActionStrings[binding_to_set].c_str(), sensed_input.m_device_id);

            if (sensed_input.m_type == Input::IT_STICKMOTION)
            {
                Log::info("OptionsScreenInput2", "Axis %d; direction %s", sensed_input.m_button_id,
                    sensed_input.m_axis_direction == Input::AD_NEGATIVE ? "-" : "+");
            }
            else if (sensed_input.m_type == Input::IT_STICKBUTTON)
            {
                Log::info("OptionsScreenInput2", "Button %d", sensed_input.m_button_id);
            }
            else
            {
                Log::info("OptionsScreenInput2", "Sensed unknown gamepad event type??");
            }
        }


        std::string gamepad_name = input_manager->getDeviceList()->getGamePadFromIrrID(sensed_input.m_device_id)->m_name;
        if (m_config->getName() == gamepad_name)
        {
            GamepadConfig* config =  (GamepadConfig*)m_config;
            config->setBinding(binding_to_set, sensed_input.m_type,
                               sensed_input.m_button_id,
                              (Input::AxisDirection)sensed_input.m_axis_direction,
                              (Input::AxisRange)sensed_input.m_axis_range);

            // refresh display
            updateInputButtons();
        }
    }
    else if (sensed_input.m_type == Input::IT_NONE)
    {
        if (UserConfigParams::logMisc())
        {
            Log::info("OptionsScreenInput2", "Binding %s: setting to keyboard key NONE",
                KartActionStrings[binding_to_set].c_str());
        }

        KeyboardConfig* keyboard = (KeyboardConfig*)m_config;
        keyboard->setBinding(binding_to_set, Input::IT_NONE,
                             sensed_input.m_button_id, Input::AD_NEUTRAL,
                             Input::AR_HALF,
                             sensed_input.m_character);

        // refresh display
        updateInputButtons();
    }
    else
    {
        return;
    }

    ModalDialog::dismiss();
    input_manager->setMode(InputManager::MENU);

    if (keyboard && (sensed_input.m_button_id == irr::KEY_SHIFT ||
                     sensed_input.m_button_id == irr::KEY_LSHIFT ||
                     sensed_input.m_button_id == irr::KEY_RSHIFT))
    {
        new MessageDialog(_("Warning, 'Shift' is not a recommended key : when "
                            "shift is pressed down, all keys that contain a "
                            "character that is different in upper-case will "
                            "stop working."));
    }

    // re-select the previous button (TODO!)
    //ButtonWidget* btn =
    //    getWidget<ButtonWidget>(binding_to_set_button.c_str());
    //if(btn != NULL) btn->setFocusForPlayer(PLAYER_ID_GAME_MASTER);

    // save new binding to file
    input_manager->getDeviceList()->serialize();
}   // gotSensedInput
Ejemplo n.º 7
0
Client::Client(const Options &options):
    mOptions(options),
    mGame(0),
    mCurrentDialog(0),
    mQuitDialog(0),
    mDesktop(0),
    mSetupButton(0),
    mState(STATE_CHOOSE_SERVER),
    mOldState(STATE_START),
    mStateAfterOkDialog(mState),
    mIcon(0),
    mLogicCounterId(0),
    mSecondsCounterId(0),
    mLimitFps(false)
{
    assert(!mInstance);
    mInstance = this;

    logger = new Logger;

    // Set default values for configuration files
    branding.setDefaultValues(getBrandingDefaults());
    paths.setDefaultValues(getPathsDefaults());
    config.setDefaultValues(getConfigDefaults());

    // Load branding information
    if (!options.brandingPath.empty())
    {
        branding.init(options.brandingPath);
    }

    initRootDir();
    initHomeDir();
    initConfiguration();

    chatLogger = new ChatLogger;
    if (options.chatLogDir.empty())
        chatLogger->setLogDir(mLocalDataDir + std::string("/logs/"));
    else
        chatLogger->setLogDir(options.chatLogDir);

    // Configure logger
    logger->setLogFile(mLocalDataDir + std::string("/mana.log"));
    logger->setLogToStandardOut(config.getBoolValue("logToStandardOut"));

    // Log the mana version
    logger->log("Mana %s", FULL_VERSION);

    initScreenshotDir();

    // Initialize SDL
    logger->log("Initializing SDL...");
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
    {
        logger->error(strprintf("Could not initialize SDL: %s",
                      SDL_GetError()));
    }
    atexit(SDL_Quit);

    SDL_EnableUNICODE(1);
    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);

    SDL_WM_SetCaption(branding.getValue("appName", "Mana").c_str(), NULL);

    ResourceManager *resman = ResourceManager::getInstance();

    if (!resman->setWriteDir(mLocalDataDir))
    {
        logger->error(strprintf("%s couldn't be set as home directory! "
                                "Exiting.", mLocalDataDir.c_str()));
    }

    Image::SDLsetEnableAlphaCache(config.getValue("alphaCache", 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, false);
    mPackageDir = path;
#else
    resman->addToSearchPath(PKG_DATADIR "data", false);
    mPackageDir = PKG_DATADIR "data";
#endif

    resman->addToSearchPath("data", false);

    // Add branding/data to PhysFS search path
    if (!options.brandingPath.empty())
    {
        std::string path = options.brandingPath;

        // Strip blah.mana from the path
#ifdef _WIN32
        int loc1 = path.find_last_of('/');
        int loc2 = path.find_last_of('\\');
        int loc = std::max(loc1, loc2);
#else
        int loc = path.find_last_of('/');
#endif
        if (loc > 0)
            resman->addToSearchPath(path.substr(0, loc + 1) + "data", false);
    }

    // Add the main data directories to our PhysicsFS search path
    if (!options.dataPath.empty())
        resman->addToSearchPath(options.dataPath, false);

    // Add the local data directory to PhysicsFS search path
    resman->addToSearchPath(mLocalDataDir, false);

    std::string iconFile = branding.getValue("appIcon", "icons/mana");
#ifdef _WIN32
    iconFile += ".ico";
#else
    iconFile += ".png";
#endif
    iconFile = resman->getPath(iconFile);
    logger->log("Loading icon from file: %s", iconFile.c_str());
#ifdef _WIN32
    static SDL_SysWMinfo pInfo;
    SDL_GetWMInfo(&pInfo);
    // Attempt to load icon from .ico file
    HICON icon = (HICON) LoadImage(NULL,
                                   iconFile.c_str(),
                                   IMAGE_ICON, 64, 64, LR_LOADFROMFILE);
    // If it's failing, we load the default resource file.
    if (!icon)
        icon = LoadIcon(GetModuleHandle(NULL), "A");

    if (icon)
        SetClassLong(pInfo.window, GCL_HICON, (LONG) icon);
#else
    mIcon = IMG_Load(iconFile.c_str());
    if (mIcon)
    {
        SDL_SetAlpha(mIcon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
        SDL_WM_SetIcon(mIcon, NULL);
    }
#endif

    bool useOpenGL = !mOptions.noOpenGL && (config.getValue("opengl", 1) == 1);

    // Set up the transparency option for low CPU when not using OpenGL.
    if (!useOpenGL && (config.getValue("disableTransparency", 0) == 1))
        Image::SDLdisableTransparency();

#ifdef USE_OPENGL

    // Setup image loading for the right image format
    Image::setLoadAsOpenGL(useOpenGL);

    // Create the graphics context
    graphics = useOpenGL ? new OpenGLGraphics : new Graphics;
#else
    // Create the graphics context
    graphics = new Graphics;
#endif

    const int width = config.getIntValue("screenwidth");
    const int height = config.getIntValue("screenheight");
    const int bpp = 0;
    const bool fullscreen = config.getBoolValue("screen");
    const bool hwaccel = config.getBoolValue("hwaccel");

    // Try to set the desired video mode
    if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
    {
        logger->error(strprintf("Couldn't set %dx%dx%d video mode: %s",
            width, height, bpp, SDL_GetError()));
    }

    // Initialize for drawing
    graphics->_beginDraw();

    Theme::prepareThemePath();

    // Initialize the item and emote shortcuts.
    itemShortcut = new ItemShortcut;
    emoteShortcut = new EmoteShortcut;

    gui = new Gui(graphics);

    // Initialize sound engine
    try
    {
        if (config.getBoolValue("sound"))
            sound.init();

        sound.setSfxVolume(config.getIntValue("sfxVolume"));
        sound.setNotificationsVolume(config.getIntValue("notificationsVolume"));
        sound.setMusicVolume(config.getIntValue("musicVolume"));
    }
    catch (const char *err)
    {
        mState = STATE_ERROR;
        errorMessage = err;
        logger->log("Warning: %s", err);
    }

    // Initialize keyboard
    keyboard.init();

    // Initialise player relations
    player_relations.init();

    userPalette = new UserPalette;
    setupWindow = new Setup;

    sound.playMusic(branding.getStringValue("loginMusic"));

    // Initialize default server
    mCurrentServer.hostname = options.serverName;
    mCurrentServer.port = options.serverPort;
    loginData.username = options.username;
    loginData.password = options.password;
    loginData.remember = config.getBoolValue("remember");
    loginData.registerLogin = false;

    if (mCurrentServer.hostname.empty())
        mCurrentServer.hostname = branding.getValue("defaultServer","").c_str();

    if (mCurrentServer.port == 0)
    {
        mCurrentServer.port = (short) branding.getValue("defaultPort",
                                                                  DEFAULT_PORT);
        mCurrentServer.type = ServerInfo::parseType(
                           branding.getValue("defaultServerType", "tmwathena"));
    }

    if (chatLogger)
        chatLogger->setServerName(mCurrentServer.hostname);

    if (loginData.username.empty() && loginData.remember)
        loginData.username = config.getStringValue("username");

    if (mState != STATE_ERROR)
        mState = STATE_CHOOSE_SERVER;

    // Initialize logic and seconds counters
    tick_time = 0;
    mLogicCounterId = SDL_AddTimer(MILLISECONDS_IN_A_TICK, nextTick, NULL);
    mSecondsCounterId = SDL_AddTimer(1000, nextSecond, NULL);

    // Initialize frame limiting
    SDL_initFramerate(&mFpsManager);

    listen(Event::ConfigChannel);

    //TODO: fix having to fake a option changed event
    Event fakeevent(Event::ConfigOptionChanged);
    fakeevent.setString("option", "fpslimit");
    event(Event::ConfigChannel, fakeevent);

    // Initialize PlayerInfo
    PlayerInfo::init();
}