# HG changeset patch # User mikade # Date 1308595391 -7200 # Node ID df1588234b96367f8d0ae22f22c794d1da8d60a4 # Parent 32465b4b4049f8f927b7c6bda308acf7db4c2a3b# Parent e32fc0fcaad03c3ddae44d7c62869cac65b795ca merge diff -r 32465b4b4049 -r df1588234b96 .hgignore --- a/.hgignore Fri Jun 17 18:03:12 2011 +0200 +++ b/.hgignore Mon Jun 20 20:43:11 2011 +0200 @@ -22,6 +22,7 @@ glob:vittorio.* glob:project_files/HedgewarsMobile/Data/ glob:project_files/HedgewarsMobile/build/ +glob:gameServer/dist/ glob:misc/libtremor/Xcode/build/ glob:misc/liblua/Xcode/build/ glob:misc/libfreetype/Xcode/build/ diff -r 32465b4b4049 -r df1588234b96 QTfrontend/CMakeLists.txt --- a/QTfrontend/CMakeLists.txt Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/CMakeLists.txt Mon Jun 20 20:43:11 2011 +0200 @@ -4,6 +4,7 @@ set(QT_USE_QTCORE TRUE) set(QT_USE_QTGUI TRUE) set(QT_USE_QTNETWORK TRUE) +set(QT_USE_QTWEBKIT TRUE) set(QT_USE_QTSVG FALSE) set(QT_USE_QTXML FALSE) set(QT_USE_QTOPENGL FALSE) @@ -46,6 +47,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hwconsts.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp) set(hwfr_src + HWApplication.cpp game.cpp main.cpp hwform.cpp @@ -66,6 +68,7 @@ pagenetserver.cpp pagenetgame.cpp pageinfo.cpp + pagedata.cpp pagesingleplayer.cpp pagetraining.cpp pagecampaign.cpp @@ -130,6 +133,7 @@ endif(MINGW) set(hwfr_moc_hdrs + HWApplication.h game.h hats.h hwform.h @@ -149,6 +153,7 @@ pageoptions.h pagemain.h pageinfo.h + pagedata.h pagesingleplayer.h pagenettype.h pageconnecting.h diff -r 32465b4b4049 -r df1588234b96 QTfrontend/HWApplication.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QTfrontend/HWApplication.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -0,0 +1,45 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2005-2011 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "HWApplication.h" +#include + +#include "hwform.h" + +HWApplication::HWApplication(int &argc, char **argv): + QApplication(argc, argv) +{ + +} + +bool HWApplication::event(QEvent *event) { + QFileOpenEvent *openEvent; + + switch (event->type()) { + case QEvent::FileOpen: + openEvent = (QFileOpenEvent *)event; + if (form) form->PlayDemoQuick(openEvent->file()); + return true; + break; + default: + return QApplication::event(event); + break; + } +} + + diff -r 32465b4b4049 -r df1588234b96 QTfrontend/HWApplication.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QTfrontend/HWApplication.h Mon Jun 20 20:43:11 2011 +0200 @@ -0,0 +1,41 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2005-2011 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef HWAPP_H +#define HWAPP_H + +#include +#include +#include + +class HWForm; + +class HWApplication : public QApplication +{ + Q_OBJECT +public: + HWApplication(int &argc, char **argv); + ~HWApplication() {}; + + HWForm *form; +protected: + bool event(QEvent *); +}; + +#endif + diff -r 32465b4b4049 -r df1588234b96 QTfrontend/SDLs.cpp --- a/QTfrontend/SDLs.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/SDLs.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -21,8 +21,7 @@ #include "SDL.h" #include "SDL_mixer.h" #include "hwconsts.h" - -#include +#include "HWApplication.h" extern char sdlkeys[1024][2][128]; @@ -101,38 +100,38 @@ for(int aid = 0; aid < SDL_JoystickNumAxes(joy) && i < 1021; aid++) { // Again store the part of the string not changing for multiple uses - QString axis = prefix + QApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1); + QString axis = prefix + HWApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1); // Entry for "Axis Up" sprintf(sdlkeys[i][0], "j%da%du", jid, aid); - sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + QApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + QApplication::translate("binds (keys)", "(Up)")).toStdString().c_str()); + sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + HWApplication::translate("binds (keys)", "(Up)")).toStdString().c_str()); // Entry for "Axis Down" sprintf(sdlkeys[i][0], "j%da%dd", jid, aid); - sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + QApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : axis + QApplication::translate("binds (keys)", "(Down)")).toStdString().c_str()); + sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : axis + HWApplication::translate("binds (keys)", "(Down)")).toStdString().c_str()); } // Register entries for all coolie hats of this joystick/gamepad for(int hid = 0; hid < SDL_JoystickNumHats(joy) && i < 1019; hid++) { // Again store the part of the string not changing for multiple uses - QString hat = prefix + (isxb ? (QApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : QApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1)); + QString hat = prefix + (isxb ? (HWApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : HWApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1)); // Entry for "Hat Up" sprintf(sdlkeys[i][0], "j%dh%du", jid, hid); - sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Up)")).toStdString().c_str()); + sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Up)")).toStdString().c_str()); // Entry for "Hat Down" sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid); - sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Down)")).toStdString().c_str()); + sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Down)")).toStdString().c_str()); // Entry for "Hat Left" sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid); - sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Left)")).toStdString().c_str()); + sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Left)")).toStdString().c_str()); // Entry for "Hat Right" sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid); - sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Right)")).toStdString().c_str()); + sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Right)")).toStdString().c_str()); } // Register entries for all buttons of this joystick/gamepad @@ -140,7 +139,7 @@ { // Buttons sprintf(sdlkeys[i][0], "j%db%d", jid, bid); - sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (QApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : QApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toStdString().c_str()); + sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (HWApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : HWApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toStdString().c_str()); } // Close the game controller as we no longer need it SDL_JoystickClose(joy); diff -r 32465b4b4049 -r df1588234b96 QTfrontend/chatwidget.cpp --- a/QTfrontend/chatwidget.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/chatwidget.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,6 @@ #include #include #include -#include #include "hwconsts.h" #include "SDLs.h" @@ -165,12 +163,7 @@ connect(chatNicks, SIGNAL(currentRowChanged(int)), this, SLOT(chatNickSelected(int))); - mainLayout.addWidget(chatNicks, 1, 1, 2, 1); - - lblCount = new QLabel(this); - mainLayout.addWidget(lblCount, 0, 1); - lblCount->setText("0"); - lblCount->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + mainLayout.addWidget(chatNicks, 0, 1, 3, 1); acInfo = new QAction(QAction::tr("Info"), chatNicks); acInfo->setIcon(QIcon(":/res/info.png")); @@ -398,7 +391,7 @@ updateNickItem(item); chatNicks->addItem(item); - lblCount->setText(QString::number(chatNicks->count())); + emit nickCountUpdate(chatNicks->count()); if(notifyNick && notify && gameSettings->value("frontend/sound", true).toBool()) { Mix_PlayChannel(-1, sound[rand()%4], 0); @@ -411,7 +404,7 @@ QListIterator it(items); while(it.hasNext()) chatNicks->takeItem(chatNicks->row(it.next())); - lblCount->setText(QString::number(chatNicks->count())); + emit nickCountUpdate(chatNicks->count()); } void HWChatWidget::clear() diff -r 32465b4b4049 -r df1588234b96 QTfrontend/chatwidget.h --- a/QTfrontend/chatwidget.h Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/chatwidget.h Mon Jun 20 20:43:11 2011 +0200 @@ -34,7 +34,6 @@ class QListWidget; class QSettings; class SDLInteraction; -class QLabel; // this class is for custom nick sorting class ListWidgetNickItem : public QListWidgetItem @@ -88,6 +87,7 @@ void ban(const QString & str); void info(const QString & str); void follow(const QString &); + void nickCountUpdate(int cnt); private: QGridLayout mainLayout; @@ -102,7 +102,6 @@ QAction * acIgnore; QAction * acFriend; QSettings * gameSettings; - QLabel * lblCount; SDLInteraction * sdli; Mix_Chunk *sound[4]; bool notify; diff -r 32465b4b4049 -r df1588234b96 QTfrontend/drawmapwidget.cpp --- a/QTfrontend/drawmapwidget.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/drawmapwidget.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -18,6 +18,7 @@ #include #include +#include #include "drawmapwidget.h" diff -r 32465b4b4049 -r df1588234b96 QTfrontend/drawmapwidget.h --- a/QTfrontend/drawmapwidget.h Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/drawmapwidget.h Mon Jun 20 20:43:11 2011 +0200 @@ -23,7 +23,6 @@ #include #include #include -#include #include "qaspectratiolayout.h" #include "drawmapscene.h" diff -r 32465b4b4049 -r df1588234b96 QTfrontend/gameuiconfig.cpp --- a/QTfrontend/gameuiconfig.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/gameuiconfig.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -30,6 +29,7 @@ #include "pagenetserver.h" #include "hwconsts.h" #include "fpsedit.h" +#include "HWApplication.h" GameUIConfig::GameUIConfig(HWForm * FormWidgets, const QString & fileName) : QSettings(fileName, QSettings::IniFormat) @@ -75,6 +75,8 @@ Form->ui.pageOptions->editNetNick->setText(netNick); + Form->ui.pageOptions->editNetPassword->installEventFilter(this); + int passLength = value("net/passwordlength", 0).toInt(); setNetPasswordLength(passLength); @@ -97,7 +99,7 @@ Form->ui.pageOptions->CBLanguage->setCurrentIndex(Form->ui.pageOptions->CBLanguage->findData(value("misc/locale", "").toString())); - depth = QApplication::desktop()->depth(); + depth = HWApplication::desktop()->depth(); if (depth < 16) depth = 16; else if (depth > 16) depth = 32; } @@ -327,6 +329,24 @@ return (netPasswordLength() == 0 || Form->ui.pageOptions->editNetPassword->text() != QString(netPasswordLength(), '\0')); } +// When hedgewars launches, the password field is set with null characters. If the user tries to edit the field and there are such characters, then clear the field +bool GameUIConfig::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::FocusIn) + { + if ((QLineEdit *)object == Form->ui.pageOptions->editNetPassword) + { + if (!netPasswordIsValid()) + { + Form->ui.pageOptions->editNetPassword->clear(); + } + } + } + + // Don't filter anything + return false; +} + void GameUIConfig::setNetPasswordLength(int passwordLength) { if (passwordLength > 0) diff -r 32465b4b4049 -r df1588234b96 QTfrontend/gameuiconfig.h --- a/QTfrontend/gameuiconfig.h Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/gameuiconfig.h Mon Jun 20 20:43:11 2011 +0200 @@ -22,6 +22,7 @@ #include #include #include +#include class HWForm; class QSettings; @@ -69,9 +70,9 @@ public slots: void SaveOptions(); - private: bool netPasswordIsValid(); + bool eventFilter(QObject *object, QEvent *event); quint8 depth; }; diff -r 32465b4b4049 -r df1588234b96 QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/hwform.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -182,9 +182,7 @@ connect(ui.pageOptions->BtnDeleteTeam, SIGNAL(clicked()), this, SLOT(DeleteTeam())); connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), config, SLOT(SaveOptions())); connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), this, SLOT(GoBack())); -#ifndef __APPLE__ connect(ui.pageOptions->BtnAssociateFiles, SIGNAL(clicked()), this, SLOT(AssociateFiles())); -#endif connect(ui.pageOptions->WeaponEdit, SIGNAL(clicked()), this, SLOT(GoToSelectWeapon())); connect(ui.pageOptions->WeaponNew, SIGNAL(clicked()), this, SLOT(GoToSelectNewWeapon())); @@ -460,8 +458,7 @@ #ifdef USE_XFIRE updateXfire(); #endif - if(id == ID_PAGE_DRAWMAP) - { + if (id == ID_PAGE_DRAWMAP) { DrawMapScene * scene; if(lastid == ID_PAGE_MULTIPLAYER) scene = ui.pageMultiplayer->gameCFG->pMapContainer->getDrawMapScene(); @@ -470,9 +467,9 @@ ui.pageDrawMap->drawMapWidget->setScene(scene); } - if(lastid == ID_PAGE_DRAWMAP) - { - if(id == ID_PAGE_MULTIPLAYER) + + if (lastid == ID_PAGE_DRAWMAP) { + if (id == ID_PAGE_MULTIPLAYER) ui.pageMultiplayer->gameCFG->pMapContainer->mapDrawingFinished(); else ui.pageNetGame->pGameCFG->pMapContainer->mapDrawingFinished(); @@ -487,37 +484,35 @@ ui.pageOptions->CBTeamName->setVisible(false); ui.pageOptions->LblNoEditTeam->setVisible(true); - if(id == ID_PAGE_MULTIPLAYER) { - curTeamSelWidget = ui.pageMultiplayer->teamsSelect; + if (id == ID_PAGE_MULTIPLAYER) { + curTeamSelWidget = ui.pageMultiplayer->teamsSelect; } else { - curTeamSelWidget = ui.pageNetGame->pNetTeamsWidget; + curTeamSelWidget = ui.pageNetGame->pNetTeamsWidget; } QList teamsList; - for(QStringList::iterator it = tmNames.begin(); it != tmNames.end(); it++) { - HWTeam team(*it); - team.LoadFromFile(); - teamsList.push_back(team); + for (QStringList::iterator it = tmNames.begin(); it != tmNames.end(); it++) { + HWTeam team(*it); + team.LoadFromFile(); + teamsList.push_back(team); } - if(lastid == ID_PAGE_SETUP || lastid == ID_PAGE_DRAWMAP) { // _TEAM - if (editedTeam) { - curTeamSelWidget->addTeam(*editedTeam); - } - } else if(lastid != ID_PAGE_GAMESTATS + if (lastid == ID_PAGE_SETUP || lastid == ID_PAGE_DRAWMAP) { // _TEAM + if (editedTeam) { + curTeamSelWidget->addTeam(*editedTeam); + } + } else if (lastid != ID_PAGE_GAMESTATS && lastid != ID_PAGE_INGAME && lastid != ID_PAGE_SCHEME && lastid != ID_PAGE_SELECTWEAPON) { curTeamSelWidget->resetPlayingTeams(teamsList); } } else - if (id == ID_PAGE_GAMESTATS) - { - ui.pageGameStats->renderStats(); - } + if (id == ID_PAGE_GAMESTATS) { + ui.pageGameStats->renderStats(); + } - if(id == ID_PAGE_MAIN) - { + if (id == ID_PAGE_MAIN) { ui.pageOptions->BtnNewTeam->setVisible(true); ui.pageOptions->BtnEditTeam->setVisible(true); ui.pageOptions->BtnDeleteTeam->setVisible(true); @@ -526,16 +521,16 @@ } // load and save ignore/friends lists - if(lastid == ID_PAGE_NETGAME) // leaving a room + if (lastid == ID_PAGE_NETGAME) // leaving a room ui.pageNetGame->pChatWidget->saveLists(ui.pageOptions->editNetNick->text()); else if(lastid == ID_PAGE_ROOMSLIST) // leaving the lobby ui.pageRoomsList->chatWidget->saveLists(ui.pageOptions->editNetNick->text()); - if(id == ID_PAGE_NETGAME) // joining a room + if (id == ID_PAGE_NETGAME) // joining a room ui.pageNetGame->pChatWidget->loadLists(ui.pageOptions->editNetNick->text()); // joining the lobby - else if(id == ID_PAGE_ROOMSLIST) { - if ( hwnet && game && game->gameState == gsStarted) { // abnormal exit - kick or room destruction - send kills. + else if (id == ID_PAGE_ROOMSLIST) { + if (hwnet && game && game->gameState == gsStarted) { // abnormal exit - kick or room destruction - send kills. game->netSuspend = true; game->KillAllTeams(); } @@ -713,12 +708,21 @@ tr("Error"), tr("Please select record from the list above"), tr("OK")); - return ; + return; } CreateGame(0, 0, 0); game->PlayDemo(curritem->data(Qt::UserRole).toString()); } +void HWForm::PlayDemoQuick(const QString & demofilename) +{ + if (game && game->gameState == gsStarted) return; + GoBack(); //needed to cleanly disconnect from netgame + GoToPage(ID_PAGE_MAIN); + CreateGame(0, 0, 0); + game->PlayDemo(demofilename); +} + void HWForm::NetConnectServer(const QString & host, quint16 port) { _NetConnect(host, port, ui.pageOptions->editNetNick->text().trimmed()); @@ -1253,8 +1257,10 @@ registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments); registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments); #elif defined __APPLE__ - success = false; - // TODO; also enable button in pages.cpp and signal in hwform.cpp + // only useful when other apps have taken precedence over our file extensions and you want to reset it + system("defaults write com.apple.LaunchServices LSHandlers -array-add 'LSHandlerContentTaghwdLSHandlerContentTagClasspublic.filename-extensionLSHandlerRoleAllorg.hedgewars.desktop'"); + system("defaults write com.apple.LaunchServices LSHandlers -array-add 'LSHandlerContentTaghwsLSHandlerContentTagClasspublic.filename-extensionLSHandlerRoleAllorg.hedgewars.desktop'"); + system("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -domain local -domain system -domain user"); #else // this is a little silly due to all the system commands below anyway - just use mkdir -p ? Does have the advantage of the alert I guess if (success) success = checkForDir(QDir::home().absolutePath() + "/.local"); diff -r 32465b4b4049 -r df1588234b96 QTfrontend/hwform.h --- a/QTfrontend/hwform.h Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/hwform.h Mon Jun 20 20:43:11 2011 +0200 @@ -58,6 +58,7 @@ GameUIConfig * config; QSettings * gameSettings; // Same file GameUIConfig points to but without the baggage. Needs sync() calls if you want to get GameUIConfig changes though void updateXfire(); + void PlayDemoQuick(const QString & demofilename); private slots: void GoToSaves(); @@ -161,7 +162,7 @@ QSignalMapper * pageSwitchMapper; #ifdef __APPLE__ - InstallController * panel; + InstallController * panel; #endif void OnPageShown(quint8 id, quint8 lastid=0); diff -r 32465b4b4049 -r df1588234b96 QTfrontend/main.cpp --- a/QTfrontend/main.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/main.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -16,7 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#include +#include "HWApplication.h" + #include #include #include @@ -51,7 +52,7 @@ } int main(int argc, char *argv[]) { - QApplication app(argc, argv); + HWApplication app(argc, argv); app.setAttribute(Qt::AA_DontShowIconsInMenus,false); QStringList arguments = app.arguments(); @@ -455,8 +456,8 @@ CocoaInitializer initializer; #endif - HWForm *Form = new HWForm(); + app.form = new HWForm(); - Form->show(); + app.form->show(); return app.exec(); } diff -r 32465b4b4049 -r df1588234b96 QTfrontend/mapContainer.cpp --- a/QTfrontend/mapContainer.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/mapContainer.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -35,6 +34,7 @@ #include "hwconsts.h" #include "mapContainer.h" #include "igbox.h" +#include "HWApplication.h" HWMapContainer::HWMapContainer(QWidget * parent) : QWidget(parent), @@ -46,10 +46,10 @@ hhLimit = 18; templateFilter = 0; - mainLayout.setContentsMargins(QApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin), + mainLayout.setContentsMargins(HWApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin), 1, - QApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin), - QApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin)); + HWApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin), + HWApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin)); QWidget* mapWidget = new QWidget(this); mainLayout.addWidget(mapWidget, 0, 0, Qt::AlignHCenter); diff -r 32465b4b4049 -r df1588234b96 QTfrontend/namegen.cpp --- a/QTfrontend/namegen.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/namegen.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -19,7 +19,6 @@ #include #include -#include #include #include #include "namegen.h" diff -r 32465b4b4049 -r df1588234b96 QTfrontend/pageeditteam.cpp --- a/QTfrontend/pageeditteam.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/pageeditteam.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -24,13 +24,13 @@ #include #include #include -#include #include "pageeditteam.h" #include "sdlkeys.h" #include "hwconsts.h" #include "SquareLabel.h" #include "hats.h" +#include "HWApplication.h" PageEditTeam::PageEditTeam(QWidget* parent, SDLInteraction * sdli) : AbstractPage(parent) @@ -315,24 +315,24 @@ pagelayout->addWidget(l, num++, 0, 1, 2); } curW = new QWidget(this); - BindsBox->addItem(curW, QApplication::translate("binds (categories)", cbinds[i].category)); + BindsBox->addItem(curW, HWApplication::translate("binds (categories)", cbinds[i].category)); pagelayout = new QGridLayout(curW); num = 0; } if(cbinds[i].description != NULL) { l = new QLabel(curW); - l->setText((num > 0 ? QString("\n") : QString("")) + QApplication::translate("binds (descriptions)", cbinds[i].description)); + l->setText((num > 0 ? QString("\n") : QString("")) + HWApplication::translate("binds (descriptions)", cbinds[i].description)); pagelayout->addWidget(l, num++, 0, 1, 2); } l = new QLabel(curW); - l->setText(QApplication::translate("binds", cbinds[i].name)); + l->setText(HWApplication::translate("binds", cbinds[i].name)); l->setAlignment(Qt::AlignRight); pagelayout->addWidget(l, num, 0); CBBind[i] = new QComboBox(curW); for(int j = 0; sdlkeys[j][1][0] != '\0'; j++) - CBBind[i]->addItem(QApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? QApplication::translate("binds (keys)", sdlkeys[j][1]) : QApplication::translate("binds (keys)", "Keyboard") + QString(": ") + QApplication::translate("binds (keys)", sdlkeys[j][1]), sdlkeys[j][0]); + CBBind[i]->addItem(HWApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? HWApplication::translate("binds (keys)", sdlkeys[j][1]) : HWApplication::translate("binds (keys)", "Keyboard") + QString(": ") + HWApplication::translate("binds (keys)", sdlkeys[j][1]), sdlkeys[j][0]); pagelayout->addWidget(CBBind[i++], num++, 1); } } diff -r 32465b4b4049 -r df1588234b96 QTfrontend/pageoptions.cpp --- a/QTfrontend/pageoptions.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/pageoptions.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -239,16 +239,17 @@ CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name")); MiscLayout->addWidget(CBNameWithDate, 4, 0, 1, 2); -#ifdef SPARKLE_ENABLED - CBAutoUpdate = new QCheckBox(groupMisc); - CBAutoUpdate->setText(QCheckBox::tr("Check for updates at startup")); - MiscLayout->addWidget(CBAutoUpdate, 5, 0, 1, 2); -#endif -#ifndef __APPLE__ BtnAssociateFiles = new QPushButton(groupMisc); BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions")); BtnAssociateFiles->setEnabled(!custom_data && !custom_config); MiscLayout->addWidget(BtnAssociateFiles, 5, 0, 1, 2); + +#ifdef __APPLE__ +#ifdef SPARKLE_ENABLED + CBAutoUpdate = new QCheckBox(groupMisc); + CBAutoUpdate->setText(QCheckBox::tr("Check for updates at startup")); + MiscLayout->addWidget(CBAutoUpdate, 6, 0, 1, 3); +#endif #endif gbTBLayout->addWidget(groupMisc, 2, 0); } diff -r 32465b4b4049 -r df1588234b96 QTfrontend/pageroomslist.cpp --- a/QTfrontend/pageroomslist.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/pageroomslist.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -42,7 +42,7 @@ roomName->setMaxLength(60); newRoomLayout->addWidget(roomNameLabel); newRoomLayout->addWidget(roomName); - pageLayout->addLayout(newRoomLayout, 0, 0); + pageLayout->addLayout(newRoomLayout, 0, 0, 1, 2); roomsList = new QTableWidget(this); roomsList->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -51,7 +51,7 @@ roomsList->setAlternatingRowColors(true); roomsList->setShowGrid(false); roomsList->setSelectionMode(QAbstractItemView::SingleSelection); - pageLayout->addWidget(roomsList, 1, 0, 3, 1); + pageLayout->addWidget(roomsList, 1, 0, 3, 2); pageLayout->setRowStretch(2, 100); QHBoxLayout * filterLayout = new QHBoxLayout(); @@ -97,19 +97,27 @@ filterLayout->addWidget(searchLabel); filterLayout->addWidget(searchText); - pageLayout->addLayout(filterLayout, 4, 0); + pageLayout->addLayout(filterLayout, 4, 0, 1, 2); chatWidget = new HWChatWidget(this, gameSettings, sdli, false); - pageLayout->addWidget(chatWidget, 5, 0, 1, 2); + pageLayout->addWidget(chatWidget, 5, 0, 1, 3); pageLayout->setRowStretch(5, 350); - BtnCreate = addButton(tr("Create"), pageLayout, 0, 1); - BtnJoin = addButton(tr("Join"), pageLayout, 1, 1); - BtnRefresh = addButton(tr("Refresh"), pageLayout, 3, 1); - BtnClear = addButton(tr("Clear"), pageLayout, 4, 1); + BtnCreate = addButton(tr("Create"), pageLayout, 0, 2); + BtnJoin = addButton(tr("Join"), pageLayout, 1, 2); + BtnRefresh = addButton(tr("Refresh"), pageLayout, 3, 2); + BtnClear = addButton(tr("Clear"), pageLayout, 4, 2); BtnBack = addButton(":/res/Exit.png", pageLayout, 6, 0, true); - BtnAdmin = addButton(tr("Admin features"), pageLayout, 6, 1); + + lblCount = new QLabel(this); + pageLayout->addWidget(lblCount, 6, 1, Qt::AlignHCenter); + lblCount->setText("?"); + lblCount->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + + connect(chatWidget, SIGNAL(nickCountUpdate(const int)), this, SLOT(updateNickCounter(const int))); + + BtnAdmin = addButton(tr("Admin features"), pageLayout, 6, 2); connect(BtnCreate, SIGNAL(clicked()), this, SLOT(onCreateClick())); connect(BtnJoin, SIGNAL(clicked()), this, SLOT(onJoinClick())); @@ -380,3 +388,9 @@ emit askForJoinRoom(room); } } + +void PageRoomsList::updateNickCounter(int cnt) +{ + lblCount->setText(tr("%1 players online").arg(cnt)); +} + diff -r 32465b4b4049 -r df1588234b96 QTfrontend/pageroomslist.h --- a/QTfrontend/pageroomslist.h Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/pageroomslist.h Mon Jun 20 20:43:11 2011 +0200 @@ -45,6 +45,7 @@ QComboBox * CBRules; QComboBox * CBWeapons; HWChatWidget * chatWidget; + QLabel * lblCount; private: bool gameInLobby; @@ -55,6 +56,7 @@ public slots: void setRoomsList(const QStringList & list); void setAdmin(bool); + void updateNickCounter(int cnt); private slots: void onCreateClick(); diff -r 32465b4b4049 -r df1588234b96 QTfrontend/team.cpp --- a/QTfrontend/team.cpp Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/team.cpp Mon Jun 20 20:43:11 2011 +0200 @@ -18,11 +18,11 @@ #include #include -#include #include #include #include #include + #include "team.h" #include "hwform.h" #include "pageeditteam.h" diff -r 32465b4b4049 -r df1588234b96 QTfrontend/ui_hwform.h --- a/QTfrontend/ui_hwform.h Fri Jun 17 18:03:12 2011 +0200 +++ b/QTfrontend/ui_hwform.h Mon Jun 20 20:43:11 2011 +0200 @@ -29,6 +29,7 @@ class PageNetChat; class PageNetGame; class PageInfo; +class PageDataDownload; class PageGameStats; class PageSinglePlayer; class PageTraining; @@ -62,6 +63,7 @@ PageNetChat *pageNetChat; PageNetGame *pageNetGame; PageInfo *pageInfo; + PageDataDownload *pageDataDownload; PageGameStats *pageGameStats; PageSinglePlayer *pageSinglePlayer; PageTraining *pageTraining; diff -r 32465b4b4049 -r df1588234b96 gameServer/Utils.hs --- a/gameServer/Utils.hs Fri Jun 17 18:03:12 2011 +0200 +++ b/gameServer/Utils.hs Mon Jun 20 20:43:11 2011 +0200 @@ -75,7 +75,9 @@ t : replaceTeam tm ts illegalName :: B.ByteString -> Bool -illegalName s = B.null s || B.all isSpace s || isSpace (B.head s) || isSpace (B.last s) +illegalName s = B.null s || B.all isSpace s || isSpace (B.head s) || isSpace (B.last s) || B.any isIllegalChar s + where + isIllegalChar c = c `List.elem` "$()*+?[]^{|}" protoNumber2ver :: Word16 -> B.ByteString protoNumber2ver v = Map.findWithDefault "Unknown" v vermap diff -r 32465b4b4049 -r df1588234b96 hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Fri Jun 17 18:03:12 2011 +0200 +++ b/hedgewars/uLandGraphics.pas Mon Jun 20 20:43:11 2011 +0200 @@ -30,6 +30,7 @@ function addBgColor(OldColor, NewColor: LongWord): LongWord; function SweepDirty: boolean; function Despeckle(X, Y: LongInt): boolean; +procedure Smooth(X, Y: LongInt); function CheckLandValue(X, Y: LongInt; LandFlag: Word): boolean; function DrawExplosion(X, Y, Radius: LongInt): Longword; procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte); @@ -751,9 +752,46 @@ Despeckle:= false end; +procedure Smooth(X, Y: LongInt); +begin +// a bit of AA for explosions +if ((cReducedQuality and rqBlurryLand) = 0) and (Land[Y, X] = 0) and (Y > topY+1) and + (Y < LAND_HEIGHT-2) and (X>leftX+1) and (X 0) and (((Land[y+1,x] and lfDamaged) <> 0)) or ((Land[y-1,x] and lfDamaged) <> 0)) or + (((Land[y, x+1] and lfDamaged) <> 0) and (((Land[y-1,x] and lfDamaged) <> 0) or ((Land[y+1,x] and lfDamaged) <> 0)))) then + begin + if (LandPixels[y,x] = 0) then LandPixels[y,x]:= (cExplosionBorderColor and not AMask) or (128 shl AShift) + else + LandPixels[y,x]:= + (((((LandPixels[y,x] and RMask shr RShift) div 2)+((cExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or + (((((LandPixels[y,x] and GMask shr GShift) div 2)+((cExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or + (((((LandPixels[y,x] and BMask shr BShift) div 2)+((cExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift); + Land[y,x]:= lfBasic + end + else if ((((Land[y, x-1] and lfDamaged) <> 0) and ((Land[y+1,x-1] and lfDamaged) <> 0) and ((Land[y+2,x] and lfDamaged) <> 0)) or + (((Land[y, x-1] and lfDamaged) <> 0) and ((Land[y-1,x-1] and lfDamaged) <> 0) and ((Land[y-2,x] and lfDamaged) <> 0)) or + (((Land[y, x+1] and lfDamaged) <> 0) and ((Land[y+1,x+1] and lfDamaged) <> 0) and ((Land[y+2,x] and lfDamaged) <> 0)) or + (((Land[y, x+1] and lfDamaged) <> 0) and ((Land[y-1,x+1] and lfDamaged) <> 0) and ((Land[y-2,x] and lfDamaged) <> 0)) or + (((Land[y+1, x] and lfDamaged) <> 0) and ((Land[y+1,x+1] and lfDamaged) <> 0) and ((Land[y,x+2] and lfDamaged) <> 0)) or + (((Land[y-1, x] and lfDamaged) <> 0) and ((Land[y-1,x+1] and lfDamaged) <> 0) and ((Land[y,x+2] and lfDamaged) <> 0)) or + (((Land[y+1, x] and lfDamaged) <> 0) and ((Land[y+1,x-1] and lfDamaged) <> 0) and ((Land[y,x-2] and lfDamaged) <> 0)) or + (((Land[y-1, x] and lfDamaged) <> 0) and ((Land[y-1,x-1] and lfDamaged) <> 0) and ((Land[y,x-2] and lfDamaged) <> 0))) then + begin + if (LandPixels[y,x] = 0) then LandPixels[y,x]:= (cExplosionBorderColor and not AMask) or (64 shl AShift) + else + LandPixels[y,x]:= + (((((LandPixels[y,x] and RMask shr RShift) * 3 div 4)+((cExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or + (((((LandPixels[y,x] and GMask shr GShift) * 3 div 4)+((cExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or + (((((LandPixels[y,x] and BMask shr BShift) * 3 div 4)+((cExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift); + Land[y,x]:= lfBasic + end + end +end; + function SweepDirty: boolean; var x, y, xx, yy, ty, tx: LongInt; - bRes, updateBlock, resweep, recheck: boolean; + bRes, updateBlock, resweep, recheck, firstpass: boolean; begin bRes:= false; reCheck:= true; @@ -769,6 +807,7 @@ begin updateBlock:= false; resweep:= true; + firstpass:= true; ty:= y * 32; tx:= x * 32; while(resweep) do @@ -776,6 +815,7 @@ resweep:= false; for yy:= ty to ty + 31 do for xx:= tx to tx + 31 do + begin if Despeckle(xx, yy) then begin bRes:= true; @@ -802,6 +842,9 @@ recheck:= true; end end; + if firstpass then Smooth(xx,yy); + end; + firstpass:= false end; if updateBlock then UpdateLandTexture(tx, 32, ty, 32); LandDirty[y, x]:= 0; diff -r 32465b4b4049 -r df1588234b96 hedgewars/uVisualGears.pas --- a/hedgewars/uVisualGears.pas Fri Jun 17 18:03:12 2011 +0200 +++ b/hedgewars/uVisualGears.pas Mon Jun 20 20:43:11 2011 +0200 @@ -403,21 +403,21 @@ begin Gear:= VisualGearsList; case Layer of - // this level is very distant in the background when stereo + // this layer is very distant in the background when stereo 0: while Gear <> nil do begin if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint); case Gear^.Kind of vgtFlake: if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) + if vobSDVelocity = 0 then + DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) + else + DrawRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) else - if vobVelocity = 0 then - DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); + if vobVelocity = 0 then + DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) + else + DrawRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); vgtCloud: if SuddenDeathDmg then DrawSprite(sprSDCloud, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) else @@ -425,8 +425,8 @@ end; if Gear^.Tint <> $FFFFFFFF then Tint($FF,$FF,$FF,$FF); Gear:= Gear^.NextGear - end; - // this level is on the land one when stereo + end; + // this layer is on the land level (which is close but behind the screen plane) when stereo 1: while Gear <> nil do begin tinted:= false; @@ -436,47 +436,47 @@ vgtEvilTrace: if Gear^.State < 8 then DrawSprite(sprEvilTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State); vgtLineTrail: DrawLine(Gear^.X, Gear^.Y, Gear^.dX, Gear^.dY, 1.0, $FF, min(Gear^.Timer, $C0), min(Gear^.Timer, $80), min(Gear^.Timer, $FF)); end; - if (cReducedQuality and rqAntiBoom) = 0 then - case Gear^.Kind of - vgtSmoke: DrawSprite(sprSmoke, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame); - vgtSmokeWhite: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame); - vgtDust: if Gear^.State = 1 then - DrawSprite(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame) - else - DrawSprite(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame); - vgtFire: if (Gear^.State and gstTmpFlag) = 0 then - DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8) - else - DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16); - vgtSplash: if SuddenDeathDmg then - DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)) - else - DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)); - vgtDroplet: if SuddenDeathDmg then - DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame) - else - DrawSprite(sprDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame); - vgtChunk: DrawRotatedF(sprChunk, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); - end; + if (cReducedQuality and rqAntiBoom) = 0 then + case Gear^.Kind of + vgtSmoke: DrawSprite(sprSmoke, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame); + vgtSmokeWhite: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame); + vgtDust: if Gear^.State = 1 then + DrawSprite(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame) + else + DrawSprite(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame); + vgtFire: if (Gear^.State and gstTmpFlag) = 0 then + DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8) + else + DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16); + vgtSplash: if SuddenDeathDmg then + DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)) + else + DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)); + vgtDroplet: if SuddenDeathDmg then + DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame) + else + DrawSprite(sprDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame); + vgtBubble: DrawSprite(sprBubbles, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);//(RealTicks div 64 + Gear^.Frame) mod 8); + end; if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF); Gear:= Gear^.NextGear - end; - // this level is on the screen plane when stereo (depth = 0) + end; + // this layer is on the screen plane (depth = 0) when stereo 3: while Gear <> nil do begin tinted:= false; if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint); case Gear^.Kind of vgtSpeechBubble: begin - if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then - begin - tinted:= true; - Tint($FF, $FF, $FF, $66); - DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex) - end - else if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team = CurrentTeam)) or (Gear^.State = 2)) then - DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex); - end; + if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then + begin + tinted:= true; + Tint($FF, $FF, $FF, $66); + DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex) + end + else if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team = CurrentTeam)) or (Gear^.State = 2)) then + DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex); + end; vgtSmallDamageTag: DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex); vgtHealthTag: if Gear^.Tex <> nil then DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex); vgtHealth: begin @@ -488,10 +488,14 @@ DrawSprite(sprHealth, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, 0); end; end; + if (cReducedQuality and rqAntiBoom) = 0 then + case Gear^.Kind of + vgtChunk: DrawRotatedF(sprChunk, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); + end; if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF); Gear:= Gear^.NextGear end; - // this level is outside the screen when stereo + // this layer is outside the screen when stereo 2: while Gear <> nil do begin tinted:= false; @@ -503,27 +507,26 @@ Tint($FF, $FF, $FF, round($FF * (1 - power(Gear^.Timer / 250, 4)))); DrawRotatedTextureF(SpritesData[sprBigExplosion].Texture, 0.85 * (-power(2, -10 * Int(Gear^.Timer)/250) + 1) + 0.4, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 385, 385, Gear^.Angle); end; - end; + end; if (cReducedQuality and rqAntiBoom) = 0 then case Gear^.Kind of vgtExplPart: DrawSprite(sprExplPart, round(Gear^.X) + WorldDx - 16, round(Gear^.Y) + WorldDy - 16, 7 - Gear^.Frame); vgtExplPart2: DrawSprite(sprExplPart2, round(Gear^.X) + WorldDx - 16, round(Gear^.Y) + WorldDy - 16, 7 - Gear^.Frame); - vgtBubble: DrawSprite(sprBubbles, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);//(RealTicks div 64 + Gear^.Frame) mod 8); vgtSteam: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame); vgtAmmo: begin - tinted:= true; - Tint($FF, $FF, $FF, round(Gear^.alpha * $FF)); - DrawTextureF(ropeIconTex, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 32, 32); - DrawTextureF(SpritesData[sprAMAmmos].Texture, Gear^.scale * 0.90, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame - 1, 1, 32, 32); - end; + tinted:= true; + Tint($FF, $FF, $FF, round(Gear^.alpha * $FF)); + DrawTextureF(ropeIconTex, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 32, 32); + DrawTextureF(SpritesData[sprAMAmmos].Texture, Gear^.scale * 0.90, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame - 1, 1, 32, 32); + end; vgtShell: begin - if Gear^.FrameTicks < $FF then - begin - Tint($FF, $FF, $FF, Gear^.FrameTicks); - tinted:= true - end; - DrawRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); - end; + if Gear^.FrameTicks < $FF then + begin + Tint($FF, $FF, $FF, Gear^.FrameTicks); + tinted:= true + end; + DrawRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); + end; vgtFeather: begin if Gear^.FrameTicks < 255 then begin @@ -533,40 +536,40 @@ DrawRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); end; vgtEgg: begin - if Gear^.FrameTicks < $FF then - begin + if Gear^.FrameTicks < $FF then + begin Tint($FF, $FF, $FF, Gear^.FrameTicks); tinted:= true - end; - DrawRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); end; - vgtBeeTrace: begin - if Gear^.FrameTicks < $FF then - Tint($FF, $FF, $FF, Gear^.FrameTicks div 2) - else - Tint($FF, $FF, $FF, $80); - tinted:= true; - DrawRotatedF(sprBeeTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, (RealTicks shr 4) mod cMaxAngle); - end; + DrawRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); + end; + vgtBeeTrace: begin + if Gear^.FrameTicks < $FF then + Tint($FF, $FF, $FF, Gear^.FrameTicks div 2) + else + Tint($FF, $FF, $FF, $80); + tinted:= true; + DrawRotatedF(sprBeeTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, (RealTicks shr 4) mod cMaxAngle); + end; vgtSmokeRing: begin - tinted:= true; - Tint($FF, $FF, $FF, round(Gear^.alpha * $FF)); - DrawRotatedTextureF(SpritesData[sprSmokeRing].Texture, Gear^.scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 200, 200, Gear^.Angle); - end; - vgtNote: DrawRotatedF(sprNote, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); + tinted:= true; + Tint($FF, $FF, $FF, round(Gear^.alpha * $FF)); + DrawRotatedTextureF(SpritesData[sprSmokeRing].Texture, Gear^.scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 200, 200, Gear^.Angle); + end; + vgtNote: DrawRotatedF(sprNote, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); vgtBulletHit: DrawRotatedF(sprBulletHit, round(Gear^.X) + WorldDx - 0, round(Gear^.Y) + WorldDy - 0, 7 - (Gear^.FrameTicks div 50), 1, Gear^.Angle); end; case Gear^.Kind of - vgtCircle: if gear^.Angle = 1 then - begin - tmp:= Gear^.State / 100; - DrawTexture(round(Gear^.X-24*tmp) + WorldDx, round(Gear^.Y-24*tmp) + WorldDy, SpritesData[sprVampiric].Texture, tmp) - end - else DrawCircle(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State, Gear^.Timer); + vgtCircle: if gear^.Angle = 1 then + begin + tmp:= Gear^.State / 100; + DrawTexture(round(Gear^.X-24*tmp) + WorldDx, round(Gear^.Y-24*tmp) + WorldDy, SpritesData[sprVampiric].Texture, tmp) + end + else DrawCircle(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State, Gear^.Timer); end; if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF); Gear:= Gear^.NextGear - end + end end; end; diff -r 32465b4b4049 -r df1588234b96 misc/hedgewars.png Binary file misc/hedgewars.png has changed diff -r 32465b4b4049 -r df1588234b96 project_files/hedgewars.pro --- a/project_files/hedgewars.pro Fri Jun 17 18:03:12 2011 +0200 +++ b/project_files/hedgewars.pro Mon Jun 20 20:43:11 2011 +0200 @@ -3,6 +3,7 @@ DEPENDPATH += ../QTfrontend/ INCLUDEPATH += ../QTfrontend/ INCLUDEPATH += /usr/local/include/SDL +INCLUDEPATH += /usr/include/SDL DESTDIR = . @@ -11,6 +12,7 @@ } QT += network +QT += webkit HEADERS += ../QTfrontend/KB.h ../QTfrontend/SDLs.h \ ../QTfrontend/SquareLabel.h ../QTfrontend/about.h \ @@ -24,13 +26,12 @@ ../QTfrontend/igbox.h ../QTfrontend/input_ip.h \ ../QTfrontend/itemNum.h ../QTfrontend/mapContainer.h \ ../QTfrontend/misc.h ../QTfrontend/namegen.h \ - ../QTfrontend/netregister.h ../QTfrontend/netserver.h \ + ../QTfrontend/netregister.h ../QTfrontend/netserver.h \ ../QTfrontend/netserverslist.h ../QTfrontend/netudpserver.h \ ../QTfrontend/netudpwidget.h ../QTfrontend/newnetclient.h \ - ../QTfrontend/pages.h ../QTfrontend/playrecordpage.h \ - ../QTfrontend/proto.h \ + ../QTfrontend/proto.h \ ../QTfrontend/sdlkeys.h ../QTfrontend/selectWeapon.h \ - ../QTfrontend/statsPage.h ../QTfrontend/tcpBase.h \ + ../QTfrontend/tcpBase.h \ ../QTfrontend/team.h ../QTfrontend/teamselect.h \ ../QTfrontend/teamselhelper.h ../QTfrontend/togglebutton.h \ ../QTfrontend/ui_hwform.h ../QTfrontend/vertScrollArea.h \ @@ -38,7 +39,27 @@ ../QTfrontend/achievements.h \ ../QTfrontend/drawmapwidget.h \ ../QTfrontend/drawmapscene.h \ - ../QTfrontend/qaspectratiolayout.h + ../QTfrontend/qaspectratiolayout.h \ + ../QTfrontend/pagetraining.h \ + ../QTfrontend/pagesingleplayer.h \ + ../QTfrontend/pageselectweapon.h \ + ../QTfrontend/pagescheme.h \ + ../QTfrontend/pageroomslist.h \ + ../QTfrontend/pageoptions.h \ + ../QTfrontend/pagenettype.h \ + ../QTfrontend/pagenetserver.h \ + ../QTfrontend/pagenetgame.h \ + ../QTfrontend/pagenet.h \ + ../QTfrontend/pagemultiplayer.h \ + ../QTfrontend/pagemain.h \ + ../QTfrontend/pageingame.h \ + ../QTfrontend/pageinfo.h \ + ../QTfrontend/pagedata.h \ + ../QTfrontend/pageeditteam.h \ + ../QTfrontend/pagedrawmap.h \ + ../QTfrontend/pageconnecting.h \ + ../QTfrontend/pagecampaign.h \ + ../QTfrontend/pageadmin.h SOURCES += ../QTfrontend/SDLs.cpp ../QTfrontend/SquareLabel.cpp \ ../QTfrontend/about.cpp ../QTfrontend/ammoSchemeModel.cpp \ @@ -54,9 +75,9 @@ ../QTfrontend/namegen.cpp ../QTfrontend/netregister.cpp \ ../QTfrontend/netserver.cpp ../QTfrontend/netserverslist.cpp \ ../QTfrontend/netudpserver.cpp ../QTfrontend/netudpwidget.cpp \ - ../QTfrontend/newnetclient.cpp \ - ../QTfrontend/playrecordpage.cpp ../QTfrontend/proto.cpp \ - ../QTfrontend/selectWeapon.cpp ../QTfrontend/statsPage.cpp \ + ../QTfrontend/newnetclient.cpp \ + ../QTfrontend/proto.cpp \ + ../QTfrontend/selectWeapon.cpp \ ../QTfrontend/tcpBase.cpp ../QTfrontend/team.cpp \ ../QTfrontend/teamselect.cpp ../QTfrontend/teamselhelper.cpp \ ../QTfrontend/togglebutton.cpp ../QTfrontend/ui_hwform.cpp \ @@ -80,6 +101,7 @@ ../QTfrontend/pagemain.cpp \ ../QTfrontend/pageingame.cpp \ ../QTfrontend/pageinfo.cpp \ + ../QTfrontend/pagedata.cpp \ ../QTfrontend/pageeditteam.cpp \ ../QTfrontend/pagedrawmap.cpp \ ../QTfrontend/pageconnecting.cpp \ diff -r 32465b4b4049 -r df1588234b96 share/CMakeLists.txt --- a/share/CMakeLists.txt Fri Jun 17 18:03:12 2011 +0200 +++ b/share/CMakeLists.txt Mon Jun 20 20:43:11 2011 +0200 @@ -20,6 +20,8 @@ DESTINATION ../) install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/Icon.icns" DESTINATION ../Resources/) + install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/hwico.icns" + DESTINATION ../Resources/) install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/dsa_pub.pem" DESTINATION ../Resources/) ENDIF(APPLE) diff -r 32465b4b4049 -r df1588234b96 share/Info.plist.in --- a/share/Info.plist.in Fri Jun 17 18:03:12 2011 +0200 +++ b/share/Info.plist.in Mon Jun 20 20:43:11 2011 +0200 @@ -44,8 +44,112 @@ ppc LSMinimumSystemVersion - ${minimum_macosx} + ${minimum_macosx_version} SUPublicDSAKeyFile dsa_pub.pem + CFBundleLocalizations + + ar + bg + cs + de + el + en + es + fi + fr + gl + hu + it + ja + ko + nl + pl + pt_BR + pt_PT + ru + sk + sv + tr + uk + zh_CN + zh_TW + + UTExportedTypeDeclarations + + + UTTypeIdentifier + org.hedgewars.desktop.hws + UTTypeReferenceURL + http://www.hedgewars.org/demos/ + UTTypeDescription + Hedgewars Save Game + UTTypeIconFile + public.text.icns + UTTypeConformsTo + + public.data + + UTTypeTagSpecification + + public.filename-extension + + hws + + public.mime-type + application/x-hedgewars-save + + + + UTTypeIdentifier + org.hedgewars.desktop.hwd + UTTypeReferenceURL + http://www.hedgewars.org/demos/ + UTTypeIconFile + public.text.icns + UTTypeDescription + Hedgewars Demo Game + UTTypeConformsTo + + public.data + + UTTypeTagSpecification + + public.filename-extension + + hwd + + public.mime-type + application/x-hedgewars-demo + + + + CFBundleDocumentTypes + + + CFBundleTypeIconFile + hwico.icns + CFBundleTypeName + Hedgewars Savefile + LSItemContentTypes + + org.hedgewars.desktop.hws + + CFBundleTypeRole + Editor + + + CFBundleTypeIconFile + hwico.icns + CFBundleTypeName + Hedgewars Demofile + LSItemContentTypes + + org.hedgewars.desktop.hwd + + CFBundleTypeRole + Viewer + + diff -r 32465b4b4049 -r df1588234b96 share/hedgewars/Data/Locale/pl.txt --- a/share/hedgewars/Data/Locale/pl.txt Fri Jun 17 18:03:12 2011 +0200 +++ b/share/hedgewars/Data/Locale/pl.txt Mon Jun 20 20:43:11 2011 +0200 @@ -52,6 +52,10 @@ 00:49=Wskrzeszacz 00:50=Wiertniczy nalot 00:51=Kula błotna +00:52=Nie wybrano broń +00:53=TARDIS +00:54=Struktura +00:55=Land Spray 01:00=Walczmy! 01:01=Remis @@ -142,7 +146,6 @@ 02:00=%1 się wykrwawił 02:00=%1 zginął za słuszną sprawę 02:00=%1 zostawił w domu kamizelkę kuloodporną - ; Hog (%1) drowned 02:01=%1 robi za łódź podwodną! @@ -207,6 +210,7 @@ 02:01=%1 chciał sobie pogadać z rybkami 02:01=%1, uważaj na rekiny! 02:01=%1 pływa po Warszawsku. Tyłkiem po piasku! + ; Round starts 02:02=Walczmy! 02:02=Cel! Pal! @@ -259,10 +263,13 @@ 02:02=Daj im popalić! 02:02=Nie odczuwaj strachu! 02:02=Bądź odważny i podbijaj! + ; Round ends (win; unused atm) 02:03=... + ; Round ends (draw; unused atm) 02:04=... + ; New health crate 02:05=Przybyła pomoc! 02:05=Medyk! @@ -294,6 +301,7 @@ 02:05=W Hedgewars opieka zdrowotna naprawdę wymiata! 02:05=Na zdrowie! 02:05=Szczepionka! + ; New ammo crate 02:06=Więcej broni! 02:06=Posiłki! @@ -325,6 +333,7 @@ 02:06=Wyślij SMS na numer 7400 do wygrania zawartość zasobnika! 02:06=Czy to ptak...? Czy to samolot...? 02:06=Spadające gwiazdy nie spełniają życzeń, ale zasobniki jak najbardziej + ; New utility crate 02:07=Czas na narzędzia! 02:07=To może się przydać... @@ -343,6 +352,7 @@ 02:07=Zasobniki prosto z Ameryki! 02:07=Zapasy materiałów eksploatacyjnych! 02:07=Dorwij przeciwnika szybciej z nowymi narzędziami + ; Hog (%1) skips his turn 02:08=%1 jest taki nudny... 02:08=%1 próbuje się skupić @@ -394,6 +404,7 @@ 02:08=%1 ma wszystko w nosie 02:08=%1 nie chce połamać sobie igieł 02:08=%1 ma stracha + ; Hog (%1) hurts himself only 02:09=%1 powinien potrenować celowanie! 02:09=%1 najwidoczniej nienawidzi samego siebie.. @@ -445,6 +456,7 @@ 02:09=%1 ma już dość tego świata 02:09=%1 dostał łapówkę 02:09=%1 przywalił, jak łysy czupryną o kant kuli + ; Hog shot an home run (using the bat and another hog) 02:10=Home Run! 02:10=To ptak? To samolot? @@ -455,6 +467,16 @@ 02:10=Niezły rzut! 02:10=Chyba padnie rekord Guinessa w rzucie jeżem! 02:10=To było odlotowe! + +; Hog (%1) has to leave (team is gone) +02:11=%1 musi iść do łóżka! +02:11=%1 wydaje się zbyt zajęty, by grać +02:11=Zostałeś zajęty zamrozić dla jeża, %1 +02:11=Źłe gry przestała, albo nie działa. +02:11=%1 awaria z gracza +02:11=Belka go, Szkot! +02:11=%1 musi odejść + ; Weapon Categories 03:00=Granat z zapalnikiem 03:01=Granat z zapalnikiem @@ -507,6 +529,10 @@ 03:48=Ała! Moja głowa... 03:49=Powrót z zaświatów 03:50=Krecia brygada +03:51=Znalezione na ziemi +03:52=UNUSED +03:53=Typ 40 +03:54=Zbudować coś ; Weapon Descriptions (use | as line breaks) 04:00=Atakuj przeciwników zwykłym granatem.|Wybuchnie kiedy zapalnik skończy odliczanie.|1-5: Ustawia zapalnik|Atak: Przytrzymaj by rzucić z większą siłą @@ -560,7 +586,6 @@ 04:48=Czyż walenie jeży po głowach nie|jest zabawne? Dobre uderzenie|z młotka zabierze 1/3 życia|przeciwnika i wkopie go w podłoże|Atak: Uderz 04:49=Wskrześ swoich przyjaciół!|Jednakże uważaj byś nie pomógł swojemu wrogowi.|Atak: Przytrzymaj by powoli przywracać życie|Góra: Przyspiesz wskrzeszanie - ; Game goal strings 05:00=Ustawienia gry 05:01=Obowiązują następujące zasady: @@ -583,3 +608,4 @@ 05:18=Tura nie kończy się po wykonaniu ataku 05:19=Uzbrojenie zostaje przywrócone przy kolejnej turze 05:20=Każdy z jeży ma oddzielne uzbrojenie +05:21=Zespół Tag: Zespoły w klanie na kolejnych kolejkach|Wspólna Godzina: Drużyny w akcji raz z kolei klanu diff -r 32465b4b4049 -r df1588234b96 share/hedgewars/Data/Locale/ru.txt --- a/share/hedgewars/Data/Locale/ru.txt Fri Jun 17 18:03:12 2011 +0200 +++ b/share/hedgewars/Data/Locale/ru.txt Mon Jun 20 20:43:11 2011 +0200 @@ -12,7 +12,7 @@ 00:09=Пистолет Desert Eagle 00:10=Динамит 00:11=Бейсбольная бита -00:12=Неистовый удар +00:12=Восходящий удар Дракона 00:13=сек 00:14=Парашют 00:15=Воздушная атака @@ -52,6 +52,10 @@ 00:49=Воскреситель 00:50=Сверлящий удар 00:51=Комок грязи +00:52=Оружие не выбрано +00:53=Машина времени и пространства +00:54=Структура +00:55=Земляной распылитель 01:00=Вперёд к победе! 01:01=Ничья @@ -434,6 +438,10 @@ 03:48=Время Молота! 03:49=Делает то, о чем ты подумал 03:50=Большой любитель кротов +03:51=Найденный на земле +03:52=Не используется +03:53=Модель 40 +03:54=Построй что нибудь ; Weapon Descriptions (use | as line breaks) 04:00=Атакуй своих врагов обычной гранатой.|Она взорвется сразу, как только таймер|достигнет нуля.|1-5: Установить таймер гранаты|Атака: Удерживай для более дальнего броска @@ -448,7 +456,7 @@ 04:09=Не уверен, что хорошо прицелился?|Используй пистолет Desert Eagle|с возможностью сделать до четырех|выстрелов за ход.|Атака: Выстрелить (несколько раз) 04:10=Грубая сила всегда была в цене.|Брось эту классическую взрывчатку|возле своих врагов и убегай.|Атака: Бросить динамит рядом с собой 04:11=Избавься от вражеских ежей с помощью|подачи битой, отправив их за край карты|или в воду. Или как насчет того, чтобы отправить ударом|одну из мин на карте в подарок своим друзьям?|Атака: Нанести удар по всему, что стоит перед тобой -04:12=Стань лицом к лицу со своим врагом,|чтобы обрушить на него всю мощь|смертоносной техники боевых исскуств.|Атака: Исполнить Неистовый Удар +04:12=Стань лицом к лицу со своим врагом,|чтобы обрушить на него всю мощь|смертоносной техники боевых исскуств.|Атака: Исполнить Восходящий удар Дракона 04:13=Не используется 04:14=Боишься высоты? Тогда возьми парашут.|Он раскроется, как только ты начнешь слишком|долго падать, и тем самым убережет ежа|от падения с большой высоты.|Атака: Раскрыть парашут|Длинный прыжок: Сбросить гранаты или похожее вооружение 04:15=Вызови самолет, чтобы атаковать своих врагов|с помощью воздушной бомбардировки.|Влево/Вправо: Определить направление атаки|Курсор: Выбрать бомбардируемую область @@ -467,7 +475,7 @@ 04:28=Через короткий промежуток времени после|запуска этой ракеты она начнет сверлить|твердую поверхность и взорвется как только|сработает ее плавкий предохранитель или|она высвободится на открытое пространство.|Атака: Удерживай для выстрела с большей силой 04:29=Это штука - детям не игрушка!|Шаромет стреляет огромным количеством|маленьких шариков, заполненных взрывчаткой.|Атака: Выстрелить с максимальной силой|Вверх/Вниз: Продолжать прицельную стрельбу 04:30=Вызови самолет для осуществления мощного|удара напалмом. При надлежащем прицеливании,|такая атака может нанести опустошительный урон|большим участкам поверхности, включая ежей,|которым не повезло оказаться не в то время,|не в том месте.|И еще... не забудь учесть направление и силу ветра.|Влево/Вправо: Определить направление атаки|Курсор: Выбрать область для удара напалмом -04:31=Радиоуправляемый самолет - идеальное оружие,|чтобы пополнить коллекцию старых самолетов|или атаковать далеко стоящих ежей. Направь его|прямо на своих врагов или сбрось сперва несколько|бомб.|Атака: Запустить самолет или сбросить бомбы|Длинный прыжок: Исполнить 'Полет валькирий'|Вверх/Вниз: Направлять самолет в процессе полета +04:31=Радиоуправляемый самолет - идеальное оружие,|чтобы пополнить коллекцию старых самолетов|или атаковать далеко стоящих ежей. Направь его|прямо на своих врагов или сбрось сперва несколько|бомб.|Атака: Запустить самолет или сбросить бомбы|Длинный прыжок: Исполнить 'Полет валькирий'|Вверх/Вниз: Управлять самолетом в процессе полета 04:32=Слабая гравитация более эффективна, чем диета!|Прыгай выше и на более дальние дистанции или|позволь своим врагам улететь еще дальше.|Атака: Включить слабую гравитацию 04:33=Иногда тебе нужно просто немного повысить|силу своего оружия, чтобы нанести сопернику|больший урон.|Атака: Включить дополнительный урон 04:34=Не сможете меня задеть!|Атака: Включить неуязвимость @@ -508,5 +516,6 @@ 05:17=Ежи ИИ возрождаются в момент гибели 05:18=Неограниченное количество атак 05:19=Оружие восстановится в конце хода -05:20=Оружие не разделено между ежами +05:20=Ежи не имеют общего оружия +05:21=Признак команды: Команды в клане ходят последовательно|Общее время: Команды в клане имеют общее время хода diff -r 32465b4b4049 -r df1588234b96 share/hwico.icns Binary file share/hwico.icns has changed