# HG changeset patch # User koda # Date 1366417215 -7200 # Node ID 13ac594990667828890711cbb9d4e7963cb4ee1c # Parent 6ea838b8dcd5afe7374f41d03e3dae0d810fc866# Parent 2dfe7c57667c603be6f16be1dff17f15245dbb21 update 0.9.19 with dev branch diff -r 6ea838b8dcd5 -r 13ac59499066 CMakeLists.txt --- a/CMakeLists.txt Sat Apr 20 02:17:53 2013 +0200 +++ b/CMakeLists.txt Sat Apr 20 02:20:15 2013 +0200 @@ -225,15 +225,26 @@ set(CMAKE_CXX_FLAGS_DEBUG "-Wall -DDEBUG") endif() -#TODO: find out why we need this... + +#TESTING TIME include(CheckCCompilerFlag) + +#check for noexecstack on ELF, should be set on Gentoo and similar set(CMAKE_REQUIRED_FLAGS "-Wl,-z -Wl,noexecstack") check_c_compiler_flag("" HAVE_NOEXECSTACK) #empty because we are testing a linker flag if(HAVE_NOEXECSTACK) list(APPEND pascal_flags "-k-z" "-knoexecstack") - if(NOT ${MINIMAL_FLAGS}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_REQUIRED_FLAGS}") - endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_REQUIRED_FLAGS}") +endif() +unset(CMAKE_REQUIRED_FLAGS) + +#check for ASLR and DEP security features on Windows +#both supported in binutils >= 2.20, available since Vista and XP SP2 respectively +set(CMAKE_REQUIRED_FLAGS "-Wl,--nxcompat -Wl,--dynamicbase") +check_c_compiler_flag("" HAVE_WINASLRDEP) #empty because we are testing a linker flag +if(HAVE_WINASLRDEP) + list(APPEND pascal_flags "-k--nxcompat" "-k--dynamicbase") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_REQUIRED_FLAGS}") endif() unset(CMAKE_REQUIRED_FLAGS) diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/game.cpp --- a/QTfrontend/game.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/game.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -38,6 +38,13 @@ #include #include "ThemeModel.h" +// last game info +QList lastGameStartArgs = QList(); +GameType lastGameType = gtNone; +GameCFGWidget * lastGameCfg = NULL; +QString lastGameAmmo = NULL; +TeamSelWidget * lastGameTeamSel = NULL; + QString training, campaign, campaignScript, campaignTeam; // TODO: Cleaner solution? HWGame::HWGame(GameUIConfig * config, GameCFGWidget * gamecfg, QString ammo, TeamSelWidget* pTeamSelWidget) : @@ -48,6 +55,10 @@ this->config = config; this->gamecfg = gamecfg; netSuspend = false; + + lastGameCfg = gamecfg; + lastGameAmmo = ammo; + lastGameTeamSel = pTeamSelWidget; } HWGame::~HWGame() @@ -228,6 +239,7 @@ SendQuickConfig(); break; } + case gtNone: case gtSave: case gtDemo: break; @@ -343,7 +355,7 @@ readbuffer.remove(0, msglen + 1); ParseMessage(msg); } - + flushNetBuffer(); } @@ -352,7 +364,7 @@ if(m_netSendBuffer.size()) { emit SendNet(m_netSendBuffer); - + m_netSendBuffer.clear(); } } @@ -435,6 +447,9 @@ void HWGame::StartLocal() { + lastGameStartArgs.clear(); + lastGameType = gtLocal; + gameType = gtLocal; demo.clear(); Start(false); @@ -443,6 +458,9 @@ void HWGame::StartQuick() { + lastGameStartArgs.clear(); + lastGameType = gtQLocal; + gameType = gtQLocal; demo.clear(); Start(false); @@ -451,6 +469,10 @@ void HWGame::StartTraining(const QString & file) { + lastGameStartArgs.clear(); + lastGameStartArgs.append(file); + lastGameType = gtTraining; + gameType = gtTraining; training = "Missions/Training/" + file + ".lua"; demo.clear(); @@ -460,6 +482,12 @@ void HWGame::StartCampaign(const QString & camp, const QString & campScript, const QString & campTeam) { + lastGameStartArgs.clear(); + lastGameStartArgs.append(camp); + lastGameStartArgs.append(campScript); + lastGameStartArgs.append(campTeam); + lastGameType = gtCampaign; + gameType = gtCampaign; campaign = camp; campaignScript = "Missions/Campaign/" + camp + "/" + campScript; diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/game.h --- a/QTfrontend/game.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/game.h Sat Apr 20 02:20:15 2013 +0200 @@ -29,6 +29,18 @@ class GameCFGWidget; class TeamSelWidget; +enum GameType +{ + gtNone = 0, + gtLocal = 1, + gtQLocal = 2, + gtDemo = 3, + gtNet = 4, + gtTraining = 5, + gtCampaign = 6, + gtSave = 7, +}; + enum GameState { gsNotStarted = 0, @@ -49,6 +61,13 @@ bool checkForDir(const QString & dir); +// last game info +extern QList lastGameStartArgs; +extern GameType lastGameType; +extern GameCFGWidget * lastGameCfg; +extern QString lastGameAmmo; +extern TeamSelWidget * lastGameTeamSel; + class HWGame : public TCPBase { Q_OBJECT @@ -86,16 +105,6 @@ void FromNetChat(const QString & msg); private: - enum GameType - { - gtLocal = 1, - gtQLocal = 2, - gtDemo = 3, - gtNet = 4, - gtTraining = 5, - gtCampaign = 6, - gtSave = 7, - }; char msgbuf[MAXMSGCHARS]; QString ammostr; GameUIConfig * config; diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/gameuiconfig.cpp --- a/QTfrontend/gameuiconfig.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/gameuiconfig.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -25,6 +25,7 @@ #include #include #include +#include #include "gameuiconfig.h" #include "hwform.h" @@ -156,7 +157,7 @@ { // load colors QStandardItemModel * model = DataManager::instance().colorsModel(); for(int i = model->rowCount() - 1; i >= 0; --i) - model->item(i)->setData(value(QString("colors/color%1").arg(i), model->item(i)->data())); + model->item(i)->setData(QColor(value(QString("colors/color%1").arg(i), model->item(i)->data()).toString())); } { // load binds @@ -319,7 +320,7 @@ { // save colors QStandardItemModel * model = DataManager::instance().colorsModel(); for(int i = model->rowCount() - 1; i >= 0; --i) - setValue(QString("colors/color%1").arg(i), model->item(i)->data()); + setValue(QString("colors/color%1").arg(i), model->item(i)->data().value().name()); } sync(); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/hwform.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -45,6 +45,7 @@ #include #include #include +#include #if (QT_VERSION >= 0x040600) #include @@ -150,7 +151,7 @@ ui.pageOptions->CBResolution->addItems(SDLInteraction::instance().getResolutions()); - config = new GameUIConfig(this, "physfs://hedgewars.ini"); + config = new GameUIConfig(this, DataManager::instance().settingsFileName()); frontendEffects = config->value("frontend/effects", true).toBool(); playerHash = QString(QCryptographicHash::hash(config->value("net/nick","").toString().toUtf8(), QCryptographicHash::Md5).toHex()); @@ -285,6 +286,7 @@ connect(ui.pageInfo->BtnSnapshots, SIGNAL(clicked()), this, SLOT(OpenSnapshotFolder())); connect(ui.pageGameStats, SIGNAL(saveDemoRequested()), this, SLOT(saveDemoWithCustomName())); + connect(ui.pageGameStats, SIGNAL(restartGameRequested()), this, SLOT(restartGame())); connect(ui.pageSinglePlayer->BtnSimpleGamePage, SIGNAL(clicked()), this, SLOT(SimpleGame())); connect(ui.pageSinglePlayer->BtnTrainPage, SIGNAL(clicked()), pageSwitchMapper, SLOT(map())); @@ -673,6 +675,21 @@ } } + if (id == ID_PAGE_GAMESTATS) + { + switch(lastGameType) { + case gtLocal: + case gtQLocal: + case gtTraining: + case gtCampaign: + ui.pageGameStats->restartBtnVisible(true); + break; + default: + ui.pageGameStats->restartBtnVisible(false); + break; + } + } + if (id == ID_PAGE_MAIN) { ui.pageOptions->setTeamOptionsEnabled(true); @@ -1246,20 +1263,20 @@ // room status stuff connect(hwnet, SIGNAL(roomMaster(bool)), - this, SLOT(NetGameChangeStatus(bool)), Qt::QueuedConnection); + this, SLOT(NetGameChangeStatus(bool))); // net page stuff connect(hwnet, SIGNAL(roomNameUpdated(const QString &)), ui.pageNetGame, SLOT(setRoomName(const QString &)), Qt::QueuedConnection); - connect(hwnet, SIGNAL(chatStringFromNet(const QString&)), - ui.pageNetGame->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection); + connect(hwnet, SIGNAL(roomChatAction(const QString&, const QString&)), + ui.pageNetGame->chatWidget, SLOT(onChatAction(const QString&, const QString&)), Qt::QueuedConnection); + connect(hwnet, SIGNAL(roomChatMessage(const QString&, const QString&)), + ui.pageNetGame->chatWidget, SLOT(onChatMessage(const QString&, const QString&)), Qt::QueuedConnection); - connect(hwnet, SIGNAL(chatStringFromMe(const QString&)), - ui.pageNetGame->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection); connect(hwnet, SIGNAL(roomMaster(bool)), ui.pageNetGame->chatWidget, SLOT(adminAccess(bool)), Qt::QueuedConnection); connect(ui.pageNetGame->chatWidget, SIGNAL(chatLine(const QString&)), - hwnet, SLOT(chatLineToNet(const QString&))); + hwnet, SLOT(chatLineToNetWithEcho(const QString&))); connect(ui.pageNetGame->BtnGo, SIGNAL(clicked()), hwnet, SLOT(ToggleReady())); connect(hwnet, SIGNAL(setMyReadyStatus(bool)), ui.pageNetGame, SLOT(setReadyStatus(bool)), Qt::QueuedConnection); @@ -1286,25 +1303,38 @@ connect(ui.pageRoomsList->chatWidget, SIGNAL(consoleCommand(const QString&)), hwnet, SLOT(consoleCommand(const QString&))); +// player info + connect(hwnet, SIGNAL(playerInfo(const QString&, const QString&, const QString&, const QString&)), + ui.pageRoomsList->chatWidget, SLOT(onPlayerInfo(const QString&, const QString&, const QString&, const QString&)), Qt::QueuedConnection); + connect(hwnet, SIGNAL(playerInfo(const QString&, const QString&, const QString&, const QString&)), + ui.pageNetGame->chatWidget, SLOT(onPlayerInfo(const QString&, const QString&, const QString&, const QString&)), Qt::QueuedConnection); + // chatting connect(ui.pageRoomsList->chatWidget, SIGNAL(chatLine(const QString&)), hwnet, SLOT(chatLineToLobby(const QString&))); - connect(hwnet, SIGNAL(chatStringLobby(const QString&)), - ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection); - connect(hwnet, SIGNAL(chatStringLobby(const QString&, const QString&)), - ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&, const QString&)), Qt::QueuedConnection); - connect(hwnet, SIGNAL(chatStringFromMeLobby(const QString&)), - ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection); + connect(hwnet, SIGNAL(lobbyChatAction(const QString&,const QString&)), + ui.pageRoomsList->chatWidget, SLOT(onChatAction(const QString&,const QString&)), Qt::QueuedConnection); + connect(hwnet, SIGNAL(lobbyChatMessage(const QString&, const QString&)), + ui.pageRoomsList->chatWidget, SLOT(onChatMessage(const QString&, const QString&)), Qt::QueuedConnection); // nick list stuff - connect(hwnet, SIGNAL(nickAdded(const QString&, bool)), - ui.pageNetGame->chatWidget, SLOT(nickAdded(const QString&, bool)), Qt::QueuedConnection); - connect(hwnet, SIGNAL(nickRemoved(const QString&)), - ui.pageNetGame->chatWidget, SLOT(nickRemoved(const QString&)), Qt::QueuedConnection); - connect(hwnet, SIGNAL(nickAddedLobby(const QString&, bool)), - ui.pageRoomsList->chatWidget, SLOT(nickAdded(const QString&, bool)), Qt::QueuedConnection); - connect(hwnet, SIGNAL(nickRemovedLobby(const QString&)), - ui.pageRoomsList->chatWidget, SLOT(nickRemoved(const QString&)), Qt::QueuedConnection); + { + QSortFilterProxyModel * playersSortFilterModel = qobject_cast(hwnet->lobbyPlayersModel()); + if(playersSortFilterModel) + { + PlayersListModel * players = qobject_cast(playersSortFilterModel->sourceModel()); + connect(players, SIGNAL(nickAdded(const QString&, bool)), + ui.pageNetGame->chatWidget, SLOT(nickAdded(const QString&, bool))); + connect(players, SIGNAL(nickRemoved(const QString&)), + ui.pageNetGame->chatWidget, SLOT(nickRemoved(const QString&))); + connect(players, SIGNAL(nickAddedLobby(const QString&, bool)), + ui.pageRoomsList->chatWidget, SLOT(nickAdded(const QString&, bool))); + connect(players, SIGNAL(nickRemovedLobby(const QString&)), + ui.pageRoomsList->chatWidget, SLOT(nickRemoved(const QString&))); + connect(players, SIGNAL(nickRemovedLobby(const QString&, const QString&)), + ui.pageRoomsList->chatWidget, SLOT(nickRemoved(const QString&, const QString&))); + } + } // teams selecting stuff connect(ui.pageNetGame->pNetTeamsWidget, SIGNAL(hhogsNumChanged(const HWTeam&)), @@ -1740,9 +1770,6 @@ void HWForm::NetGameChangeStatus(bool isMaster) { - ui.pageNetGame->pGameCFG->setMaster(isMaster); - ui.pageNetGame->pNetTeamsWidget->setInteractivity(isMaster); - if (isMaster) NetGameMaster(); else @@ -1794,6 +1821,7 @@ { NetAmmoSchemeModel * netAmmo = new NetAmmoSchemeModel(hwnet); connect(hwnet, SIGNAL(netSchemeConfig(QStringList &)), netAmmo, SLOT(setNetSchemeConfig(QStringList &))); + ui.pageNetGame->pGameCFG->GameSchemes->setModel(netAmmo); ui.pageNetGame->setRoomName(hwnet->getRoom()); @@ -2002,6 +2030,31 @@ } } +void HWForm::restartGame() +{ + // get rid off old game stats page + if(ui.Pages->currentIndex() == ID_PAGE_GAMESTATS) + GoBack(); + + CreateGame(lastGameCfg, lastGameTeamSel, lastGameAmmo); + + switch(lastGameType) { + case gtTraining: + game->StartTraining(lastGameStartArgs.at(0).toString()); + break; + case gtQLocal: + game->StartQuick(); + break; + case gtCampaign: + game->StartCampaign(lastGameStartArgs.at(0).toString(), lastGameStartArgs.at(1).toString(), lastGameStartArgs.at(2).toString()); + break; + case gtLocal: + game->StartLocal(); + break; + default: + break; + } +} void HWForm::ShowErrorMessage(const QString & msg) { @@ -2010,8 +2063,22 @@ void HWForm::showFeedbackDialog() { - FeedbackDialog dialog(this); - dialog.exec(); + QNetworkRequest newRequest(QUrl("http://www.hedgewars.org")); + + QNetworkAccessManager *manager = new QNetworkAccessManager(this); + QNetworkReply *reply = manager->get(newRequest); + connect(reply, SIGNAL(finished()), this, SLOT(showFeedbackDialogNetChecked())); +} + +void HWForm::showFeedbackDialogNetChecked() +{ + QNetworkReply *reply = qobject_cast(sender()); + + if (reply && (reply->error() == QNetworkReply::NoError)) { + FeedbackDialog dialog(this); + dialog.exec(); + } else + MessageDialog::ShowErrorMessage(tr("This page requires an internet connection."), this); } void HWForm::startGame() diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/hwform.h --- a/QTfrontend/hwform.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/hwform.h Sat Apr 20 02:20:15 2013 +0200 @@ -129,6 +129,7 @@ void UpdateCampaignPageProgress(int index); void InitCampaignPage(); void showFeedbackDialog(); + void showFeedbackDialogNetChecked(); void NetGameChangeStatus(bool isMaster); void NetGameMaster(); @@ -142,6 +143,7 @@ void openRegistrationPage(); void startGame(); + void restartGame(); private: void _NetConnect(const QString & hostName, quint16 port, QString nick); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/main.cpp --- a/QTfrontend/main.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/main.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -261,18 +261,19 @@ engine->setWriteDir(cfgdir->absolutePath()); engine->mountPacks(); - DataManager::ensureFileExists("physfs://hedgewars.ini"); - QTranslator Translator; { - QSettings settings("physfs://hedgewars.ini", QSettings::IniFormat); + QSettings settings(DataManager::instance().settingsFileName(), QSettings::IniFormat); + settings.setIniCodec("UTF-8"); + QString cc = settings.value("misc/locale", QString()).toString(); - if(cc.isEmpty()) - cc = QLocale::system().name(); + if (cc.isEmpty()) + cc = HWApplication::keyboardInputLocale().name(); + // QLocale::system().name() returns only "C"... // load locale file into translator - if(!Translator.load(QString("physfs://Locale/hedgewars_%1").arg(cc))) - qWarning("Failed to install translation"); + if (!Translator.load(QString("physfs://Locale/hedgewars_%1").arg(cc))) + qWarning("Failed to install translation (%s)", qPrintable(cc)); app.installTranslator(&Translator); } diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/model/playerslistmodel.cpp --- a/QTfrontend/model/playerslistmodel.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/model/playerslistmodel.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -84,7 +84,7 @@ } -void PlayersListModel::addPlayer(const QString & nickname) +void PlayersListModel::addPlayer(const QString & nickname, bool notify) { insertRow(rowCount()); @@ -92,11 +92,18 @@ setData(mi, nickname); checkFriendIgnore(mi); + + emit nickAddedLobby(nickname, notify); } -void PlayersListModel::removePlayer(const QString & nickname) +void PlayersListModel::removePlayer(const QString & nickname, const QString &msg) { + if(msg.isEmpty()) + emit nickRemovedLobby(nickname); + else + emit nickRemovedLobby(nickname, msg); + QModelIndexList mil = match(index(0), Qt::DisplayRole, nickname, 1, Qt::MatchExactly); if(mil.size()) @@ -104,7 +111,7 @@ } -void PlayersListModel::playerJoinedRoom(const QString & nickname) +void PlayersListModel::playerJoinedRoom(const QString & nickname, bool notify) { QModelIndexList mil = match(index(0), Qt::DisplayRole, nickname, 1, Qt::MatchExactly); @@ -114,11 +121,15 @@ updateIcon(mil[0]); updateSortData(mil[0]); } + + emit nickAdded(nickname, notify); } void PlayersListModel::playerLeftRoom(const QString & nickname) { + emit nickRemoved(nickname); + QModelIndexList mil = match(index(0), Qt::DisplayRole, nickname, 1, Qt::MatchExactly); if(mil.size()) diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/model/playerslistmodel.h --- a/QTfrontend/model/playerslistmodel.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/model/playerslistmodel.h Sat Apr 20 02:20:15 2013 +0200 @@ -41,13 +41,20 @@ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); public slots: - void addPlayer(const QString & nickname); - void removePlayer(const QString & nickname); - void playerJoinedRoom(const QString & nickname); + void addPlayer(const QString & nickname, bool notify); + void removePlayer(const QString & nickname, const QString & msg = QString()); + void playerJoinedRoom(const QString & nickname, bool notify); void playerLeftRoom(const QString & nickname); void resetRoomFlags(); void setNickname(const QString & nickname); +signals: + void nickAdded(const QString& nick, bool notifyNick); + void nickRemoved(const QString& nick); + void nickAddedLobby(const QString& nick, bool notifyNick); + void nickRemovedLobby(const QString& nick); + void nickRemovedLobby(const QString& nick, const QString& message); + private: QHash & m_icons(); typedef QHash DataEntry; diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/net/newnetclient.cpp --- a/QTfrontend/net/newnetclient.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/net/newnetclient.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -336,10 +336,24 @@ qWarning("Net: Empty CHAT message"); return; } + + QString action = HWProto::chatStringToAction(lst[2]); + if (netClientState == InLobby) - emit chatStringLobby(lst[1], HWProto::formatChatMsgForFrontend(lst[2])); + { + if (action != NULL) + emit lobbyChatAction(lst[1], action); + else + emit lobbyChatMessage(lst[1], lst[2]); + } else + { emit chatStringFromNet(HWProto::formatChatMsg(lst[1], lst[2])); + if (action != NULL) + emit roomChatAction(lst[1], action); + else + emit roomChatMessage(lst[1], lst[2]); + } return; } @@ -350,12 +364,13 @@ qWarning("Net: Malformed INFO message"); return; } - QStringList tmp = lst; - tmp.removeFirst(); - if (netClientState == InLobby) - emit chatStringLobby(tmp.join("\n").prepend('\x01')); - else - emit chatStringFromNet(tmp.join("\n").prepend('\x01')); + emit playerInfo(lst[1], lst[2], lst[3], lst[4]); + if (netClientState != InLobby) + { + QStringList tmp = lst; + tmp.removeFirst(); + emit chatStringFromNet(tmp.join(" ").prepend('\x01')); + } return; } @@ -490,9 +505,7 @@ emit connected(); } - m_playersModel->addPlayer(lst[i]); - emit nickAddedLobby(lst[i], false); - emit chatStringLobby(lst[i], tr("%1 *** %2 has joined").arg('\x03').arg("|nick|")); + m_playersModel->addPlayer(lst[i], false); } return; } @@ -539,13 +552,11 @@ qWarning("Net: Bad LOBBY:LEFT message"); return; } - emit nickRemovedLobby(lst[1]); + if (lst.size() < 3) - emit chatStringLobby(tr("%1 *** %2 has left").arg('\x03').arg(lst[1])); + m_playersModel->removePlayer(lst[1]); else - emit chatStringLobby(lst[1], tr("%1 *** %2 has left (%3)").arg('\x03').arg("|nick|", lst[2])); - - m_playersModel->removePlayer(lst[1]); + m_playersModel->removePlayer(lst[1], lst[2]); return; } @@ -636,8 +647,8 @@ emit configAsked(); } - m_playersModel->playerJoinedRoom(lst[i]); - emit nickAdded(lst[i], isChief && (lst[i] != mynick)); + m_playersModel->playerJoinedRoom(lst[i], isChief && (lst[i] != mynick)); + emit chatStringFromNet(tr("%1 *** %2 has joined the room").arg('\x03').arg(lst[i])); } return; @@ -769,9 +780,8 @@ for(int i = 1; i < lst.size(); ++i) { - emit nickAdded(lst[i], isChief && (lst[i] != mynick)); emit chatStringFromNet(tr("%1 *** %2 has joined the room").arg('\x03').arg(lst[i])); - m_playersModel->playerJoinedRoom(lst[i]); + m_playersModel->playerJoinedRoom(lst[i], isChief && (lst[i] != mynick)); } return; } @@ -783,7 +793,7 @@ qWarning("Net: Bad LEFT message"); return; } - emit nickRemoved(lst[1]); + if (lst.size() < 3) emit chatStringFromNet(tr("%1 *** %2 has left").arg('\x03').arg(lst[1])); else @@ -836,12 +846,25 @@ ); } +void HWNewNet::chatLineToNetWithEcho(const QString& str) +{ + if(str != "") + { + emit chatStringFromNet(HWProto::formatChatMsg(mynick, str)); + chatLineToNet(str); + } +} + void HWNewNet::chatLineToNet(const QString& str) { if(str != "") { RawSendNet(QString("CHAT") + delimeter + str); - emit(chatStringFromMe(HWProto::formatChatMsg(mynick, str))); + QString action = HWProto::chatStringToAction(str); + if (action != NULL) + emit(roomChatAction(mynick, action)); + else + emit(roomChatMessage(mynick, str)); } } @@ -850,7 +873,11 @@ if(str != "") { RawSendNet(QString("CHAT") + delimeter + str); - emit chatStringLobby(mynick, HWProto::formatChatMsgForFrontend(str)); + QString action = HWProto::chatStringToAction(str); + if (action != NULL) + emit(lobbyChatAction(mynick, action)); + else + emit(lobbyChatMessage(mynick, str)); } } diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/net/newnetclient.h --- a/QTfrontend/net/newnetclient.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/net/newnetclient.h Sat Apr 20 02:20:15 2013 +0200 @@ -99,10 +99,6 @@ void AuthFailed(); void EnteredGame(); void LeftRoom(const QString & reason); - void nickAdded(const QString& nick, bool notifyNick); - void nickRemoved(const QString& nick); - void nickAddedLobby(const QString& nick, bool notifyNick); - void nickRemovedLobby(const QString& nick); void FromNet(const QByteArray & buf); void adminAccess(bool); void roomMaster(bool); @@ -117,11 +113,16 @@ void RemoveNetTeam(const HWTeam&); void hhnumChanged(const HWTeam&); void teamColorChanged(const HWTeam&); - void chatStringLobby(const QString&); - void chatStringLobby(const QString&, const QString&); + void playerInfo( + const QString & nick, + const QString & ip, + const QString & version, + const QString & roomInfo); + void lobbyChatMessage(const QString & nick, const QString & message); + void lobbyChatAction(const QString & nick, const QString & action); + void roomChatMessage(const QString & nick, const QString & message); + void roomChatAction(const QString & nick, const QString & action); void chatStringFromNet(const QString&); - void chatStringFromMe(const QString&); - void chatStringFromMeLobby(const QString&); void roomsList(const QStringList&); void serverMessage(const QString &); @@ -137,6 +138,7 @@ public slots: void ToggleReady(); void chatLineToNet(const QString& str); + void chatLineToNetWithEcho(const QString&); void chatLineToLobby(const QString& str); void SendTeamMessage(const QString& str); void SendNet(const QByteArray & buf); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/net/proto.cpp --- a/QTfrontend/net/proto.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/net/proto.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -45,11 +45,6 @@ return buf; } -QString HWProto::formatChatMsgForFrontend(const QString & msg) -{ - return formatChatMsg("|nick|", msg); -} - QString HWProto::formatChatMsg(const QString & nick, const QString & msg) { if(msg.left(4) == "/me ") @@ -57,3 +52,11 @@ else return QString("\x01%1: %2").arg(nick).arg(msg); } + +QString HWProto::chatStringToAction(const QString & string) +{ + if(string.left(4) == "/me ") + return string.mid(4); + else + return NULL; +} diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/net/proto.h --- a/QTfrontend/net/proto.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/net/proto.h Sat Apr 20 02:20:15 2013 +0200 @@ -35,6 +35,12 @@ static QByteArray & addStringListToBuffer(QByteArray & buf, const QStringList & strList); static QString formatChatMsg(const QString & nick, const QString & msg); static QString formatChatMsgForFrontend(const QString & msg); + /** + * @brief Determines if a chat string represents a chat action and returns the action. + * @param string chat string + * @return the action-message or NULL if message is no action + */ + static QString chatStringToAction(const QString & string); }; #endif // _PROTO_H diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/res/css/chat.css --- a/QTfrontend/res/css/chat.css Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/res/css/chat.css Sat Apr 20 02:20:15 2013 +0200 @@ -61,15 +61,20 @@ .msg_FriendChat .nick { color: #30ff30; } .msg_UserJoin { color: #c0c0c0; } .msg_UserJoin .nick { color: #d0d0d0; } +.msg_UserLeave { color: #b8b8b8; } +.msg_UserLeave .nick { color: #c8c8c8; } .msg_FriendJoin { font-weight: bold; color: #c0f0c0; } .msg_FriendJoin .nick { color: #d8f0d8; } +.msg_FriendLeave { font-weight: bold; color: #ffe090; } +.msg_FriendLeave .nick { color: #f8e878; } .msg_UserAction { color: #ff80ff; } .msg_UserAction .nick { color: #ffa0ff;} .msg_FriendAction { color: #ff00ff; } .msg_FriendAction .nick { color: #ff30ff; } -/* uncomment next line to disable join and leave messages of non-friends */ +/* uncomment next lines to disable join and leave messages of non-friends */ /* .msg_UserJoin { display:none; } */ +/* .msg_UserLeave { display:none; } */ /* timestamps */ .timestamp { diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/page/pagedata.cpp --- a/QTfrontend/ui/page/pagedata.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/page/pagedata.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -60,7 +60,10 @@ web->setOpenLinks(false); // fetchList(); - + web->setHtml(QString( + "

Hedgewars Downloadable Content



" + "%1
") + .arg(tr("Loading, please wait."))); m_contentDownloaded = false; } @@ -106,8 +109,7 @@ { QNetworkReply * reply = qobject_cast(sender()); - if(reply) - { + if (reply && (reply->error() == QNetworkReply::NoError)) { QString html = QString::fromUtf8(reply->readAll()); int begin = html.indexOf(""); int end = html.indexOf(""); @@ -117,7 +119,11 @@ html.remove(0, begin); } web->setHtml(html); - } + } else + web->setHtml(QString( + "

Hedgewars Downloadable Content



" + "

%1

") + .arg(tr("This page requires an internet connection."))); } void PageDataDownload::fileDownloaded() diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/page/pageeditteam.cpp --- a/QTfrontend/ui/page/pageeditteam.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/page/pageeditteam.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -320,7 +320,7 @@ ); if (!list.isEmpty()) - SDLInteraction::instance().playSoundFile("physfs://" + voiceDir + "/" + + SDLInteraction::instance().playSoundFile("/" + voiceDir + "/" + list[rand() % list.size()]); } diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/page/pagegamestats.cpp --- a/QTfrontend/ui/page/pagegamestats.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/page/pagegamestats.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -97,10 +97,12 @@ return pageLayout; } +//TODO button placement, image etc QLayout * PageGameStats::footerLayoutDefinition() { QHBoxLayout * bottomLayout = new QHBoxLayout(); + btnRestart = addButton(":/res/Start.png", bottomLayout, 0, true); btnSave = addButton(":/res/Save.png", bottomLayout, 0, true); btnSave->setStyleSheet("QPushButton{margin: 24px 0 0 0;}"); bottomLayout->setAlignment(btnSave, Qt::AlignRight | Qt::AlignBottom); @@ -112,6 +114,7 @@ { connect(this, SIGNAL(pageEnter()), this, SLOT(renderStats())); connect(btnSave, SIGNAL(clicked()), this, SIGNAL(saveDemoRequested())); + connect(btnRestart, SIGNAL(clicked()), this, SIGNAL(restartGameRequested())); } PageGameStats::PageGameStats(QWidget* parent) : AbstractPage(parent) @@ -133,6 +136,11 @@ lastColor = 0; } +void PageGameStats::restartBtnVisible(bool visible) +{ + btnRestart->setVisible(visible); +} + void PageGameStats::renderStats() { QGraphicsScene * scene = new QGraphicsScene(); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/page/pagegamestats.h --- a/QTfrontend/ui/page/pagegamestats.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/page/pagegamestats.h Sat Apr 20 02:20:15 2013 +0200 @@ -44,6 +44,7 @@ PageGameStats(QWidget* parent = 0); QPushButton *btnSave; + QPushButton *btnRestart; QLabel *labelGameStats; QLabel *labelGameWin; QLabel *labelGameRank; @@ -53,9 +54,11 @@ void GameStats(char type, const QString & info); void clear(); void renderStats(); + void restartBtnVisible(bool visible); signals: void saveDemoRequested(); + void restartGameRequested(); private: void AddStatText(const QString & msg); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/page/pagemultiplayer.cpp --- a/QTfrontend/ui/page/pagemultiplayer.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/page/pagemultiplayer.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -31,15 +31,13 @@ QLayout * PageMultiplayer::bodyLayoutDefinition() { - QGridLayout * pageLayout = new QGridLayout(); + QHBoxLayout * pageLayout = new QHBoxLayout(); gameCFG = new GameCFGWidget(this); - pageLayout->addWidget(gameCFG, 0, 0, 1, 2); - - pageLayout->setRowStretch(2, 1); + pageLayout->addWidget(gameCFG, 3, Qt::AlignTop); teamsSelect = new TeamSelWidget(this); - pageLayout->addWidget(teamsSelect, 0, 2, 3, 2); + pageLayout->addWidget(teamsSelect, 2, Qt::AlignTop); return pageLayout; } diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/page/pageoptions.cpp --- a/QTfrontend/ui/page/pageoptions.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/page/pageoptions.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -594,6 +594,11 @@ CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name()); } + QLabel *restartNoticeLabel = new QLabel(groupMisc); + restartNoticeLabel->setText(QLabel::tr("This setting will be effective at next restart.")); + groupMisc->layout()->addWidget(restartNoticeLabel, 1, 1); + + // Divider groupMisc->addDivider(); // row 1 @@ -602,14 +607,14 @@ CBNameWithDate = new QCheckBox(groupMisc); CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name")); - groupMisc->layout()->addWidget(CBNameWithDate, 2, 0, 1, 2); + groupMisc->layout()->addWidget(CBNameWithDate, 3, 0, 1, 2); // Associate file extensions BtnAssociateFiles = new QPushButton(groupMisc); BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions")); BtnAssociateFiles->setVisible(!custom_data && !custom_config); - groupMisc->layout()->addWidget(BtnAssociateFiles, 3, 0, 1, 2); + groupMisc->layout()->addWidget(BtnAssociateFiles, 4, 0, 1, 2); } #ifdef __APPLE__ diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/page/pagetraining.cpp --- a/QTfrontend/ui/page/pagetraining.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/page/pagetraining.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -118,7 +118,7 @@ DataManager & dataMgr = DataManager::instance(); // get locale - QSettings settings("physfs://hedgewars.ini", + QSettings settings(dataMgr.settingsFileName(), QSettings::IniFormat); QString loc = settings.value("misc/locale", "").toString(); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/widget/chatwidget.cpp --- a/QTfrontend/ui/widget/chatwidget.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/widget/chatwidget.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -295,9 +295,9 @@ void HWChatWidget::linkClicked(const QUrl & link) { - if (link.scheme() == "http") + if ((link.scheme() == "http") or (link.scheme() == "https")) QDesktopServices::openUrl(link); - if (link.scheme() == "hwnick") + else if (link.scheme() == "hwnick") { // decode nick QString nick = QString::fromUtf8(QByteArray::fromBase64(link.encodedQuery())); @@ -368,15 +368,43 @@ return QString("%1").arg(Qt::escape(nickname)); } +const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http(s)?://)?(www\\.)?((hedgewars\\.org|code\\.google\\.com|googlecode\\.com|hh\\.unit22\\.org)(/[^ ]*)?)"); -void HWChatWidget::onChatString(const QString& str) +bool HWChatWidget::containsHighlight(const QString & sender, const QString & message) { - onChatString("", str); + if ((sender != m_userNick) && (!m_userNick.isEmpty())) + { + QString lcStr = message.toLower(); + + foreach (const QRegExp & hl, m_highlights) + { + if (lcStr.contains(hl)) + return true; + } + } + return false; } -const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http://)?(www\\.)?(hedgewars\\.org(/[^ ]*)?)"); +QString HWChatWidget::messageToHTML(const QString & message) +{ + QString formattedStr = Qt::escape(message); + // link some urls + formattedStr = formattedStr.replace(URLREGEXP, "\\4"); + return formattedStr; +} -void HWChatWidget::onChatString(const QString& nick, const QString& str) +void HWChatWidget::onChatAction(const QString & nick, const QString & action) +{ + printChatString(nick, "* " + linkedNick(nick) + " " + messageToHTML(action), "Action", containsHighlight(nick, action)); +} + +void HWChatWidget::onChatMessage(const QString & nick, const QString & message) +{ + printChatString(nick, linkedNick(nick) + ": " + messageToHTML(message), "Chat", containsHighlight(nick, message)); +} + +void HWChatWidget::printChatString( + const QString & nick, const QString & str, const QString & cssClassPart, bool highlight) { QSortFilterProxyModel * playersSortFilterModel = qobject_cast(chatNicks->model()); if(!playersSortFilterModel) @@ -387,58 +415,15 @@ if(!players) return; - if (!nick.isEmpty()) - { - // don't show chat lines that are from ignored nicks - if (players->isFlagSet(nick, PlayersListModel::Ignore)) - return; - } + // don't show chat lines that are from ignored nicks + if (players->isFlagSet(nick, PlayersListModel::Ignore)) + return; bool isFriend = (!nick.isEmpty()) && players->isFlagSet(nick, PlayersListModel::Friend); - QString formattedStr = Qt::escape(str.mid(1)); - // make hedgewars.org urls actual links - formattedStr = formattedStr.replace(URLREGEXP, "\\3"); - - // link the nick - if(!nick.isEmpty()) - formattedStr.replace("|nick|", linkedNick(nick)); - - QString cssClass("msg_UserChat"); + QString cssClass = (isFriend ? "msg_Friend" : "msg_User") + cssClassPart; - // check first character for color code and set color properly - char c = str[0].toAscii(); - switch (c) - { - case 3: - cssClass = (isFriend ? "msg_FriendJoin" : "msg_UserJoin"); - break; - case 2: - cssClass = (isFriend ? "msg_FriendAction" : "msg_UserAction"); - break; - default: - if (isFriend) - cssClass = "msg_FriendChat"; - } - - bool isHL = false; - - if ((c != 3) && (!nick.isEmpty()) && - (nick != m_userNick) && (!m_userNick.isEmpty())) - { - QString lcStr = str.toLower(); - - foreach (const QRegExp & hl, m_highlights) - { - if (lcStr.contains(hl)) - { - isHL = true; - break; - } - } - } - - addLine(cssClass, formattedStr, isHL); + addLine(cssClass, str, highlight); } void HWChatWidget::addLine(const QString & cssClass, QString line, bool isHighlight) @@ -513,6 +498,9 @@ emit nickCountUpdate(chatNicks->model()->rowCount()); + if (!isIgnored) + printChatString(nick, QString("*** ") + tr("%1 has joined").arg(linkedNick(nick)), "Join", false); + if (notifyNick && notify && (m_helloSounds.size() > 0)) { SDLInteraction::instance().playSoundFile( @@ -522,9 +510,19 @@ void HWChatWidget::nickRemoved(const QString& nick) { + nickRemoved(nick, ""); +} + +void HWChatWidget::nickRemoved(const QString& nick, const QString & message) +{ chatEditLine->removeNickname(nick); emit nickCountUpdate(chatNicks->model()->rowCount()); + + if (message.isEmpty()) + printChatString(nick, QString("*** ") + tr("%1 has left").arg(linkedNick(nick)), "Leave", false); + else + printChatString(nick, QString("*** ") + tr("%1 has left (%2)").arg(linkedNick(nick)).arg(messageToHTML(message)), "Leave", false); } void HWChatWidget::clear() @@ -583,6 +581,19 @@ } } +void HWChatWidget::onPlayerInfo( + const QString & nick, + const QString & ip, + const QString & version, + const QString & roomInfo) +{ + addLine("msg_PlayerInfo", QString(" >>> %1 - %2 %3 %4") + .arg(linkedNick(nick)) + .arg(ip) + .arg(version) + .arg(roomInfo)); +} + void HWChatWidget::onKick() { QModelIndexList mil = chatNicks->selectionModel()->selectedRows(); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/widget/chatwidget.h --- a/QTfrontend/ui/widget/chatwidget.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/widget/chatwidget.h Sat Apr 20 02:20:15 2013 +0200 @@ -86,14 +86,39 @@ void beforeContentAdd(); void afterContentAdd(); + /** + * @brief Checks whether the message contains a highlight. + * @param sender the sender of the message + * @param message the message + * @return true if the sender is somebody else and the message contains a highlight, otherwise false + */ + bool containsHighlight(const QString & sender, const QString & message); + /** + * @brief Escapes HTML chars in the message and converts URls to HTML links. + * @param message the message to be converted to HTML + * @return the HTML message + */ + QString messageToHTML(const QString & message); + void printChatString( + const QString & nick, + const QString & str, + const QString & cssClassPart, + bool highlight); + public slots: - void onChatString(const QString& str); - void onChatString(const QString& nick, const QString& str); + void onChatAction(const QString & nick, const QString & str); + void onChatMessage(const QString & nick, const QString & str); void onServerMessage(const QString& str); void nickAdded(const QString& nick, bool notifyNick); void nickRemoved(const QString& nick); + void nickRemoved(const QString& nick, const QString& message); void clear(); void adminAccess(bool); + void onPlayerInfo( + const QString & nick, + const QString & ip, + const QString & version, + const QString & roomInfo); signals: void chatLine(const QString& str); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/widget/feedbackdialog.cpp --- a/QTfrontend/ui/widget/feedbackdialog.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/widget/feedbackdialog.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -84,10 +84,10 @@ "

%3 known bugs

" "

%4

" "") - .arg(tr("Please give us feedback!")) + .arg(tr("Send us feedback!")) .arg(tr("We are always happy about suggestions, ideas, or bug reports.")) - .arg(tr("If you found a bug, you can see if it's already known here (english): ")) - .arg(tr("Your email address is optional, but we may want to contact you.")) + .arg(tr("If you found a bug, you can see if it's already been reported here: ")) + .arg(tr("Your email address is optional, but necessary if you want us to get back at you.")) ); info->setOpenExternalLinks(true); pageLayout->addWidget(info); @@ -244,12 +244,14 @@ MEMORYSTATUSEX status; status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); - total_ram += QString::number(status.ullTotalPhys) + "\n"; + total_ram += QString::number(status.ullTotalPhys/1024/1024) + " MB\n"; - switch(QSysInfo::WinVersion()) + switch(QSysInfo::windowsVersion()) { + case QSysInfo::WV_NT: os_version += "Windows NT\n"; break; case QSysInfo::WV_2000: os_version += "Windows 2000\n"; break; case QSysInfo::WV_XP: os_version += "Windows XP\n"; break; + case QSysInfo::WV_2003: os_version += "Windows Server 2003\n"; break; case QSysInfo::WV_VISTA: os_version += "Windows Vista\n"; break; case QSysInfo::WV_WINDOWS7: os_version += "Windows 7\n"; break; //case QSysInfo::WV_WINDOWS8: os_version += "Windows 8\n"; break; //QT 5+ @@ -266,8 +268,8 @@ #else available_pages = 0, #endif*/ - page_size = sysconf(_SC_PAGE_SIZE); - total_ram += QString::number(pages * page_size) + "\n"; + page_size = sysconf(_SC_PAGE_SIZE); + total_ram += QString::number(pages*page_size/1024/1024) + " MB\n"; os_version += "GNU/Linux or BSD\n"; #endif @@ -456,7 +458,7 @@ QString email = this->email->text(); QString captchaCode = this->captcha_code->text(); QString captchaID = QString::number(this->captchaID); - QString version = "HedgewarsFoundation-Hedgewars-v" + *cVersionString + "_r" + + QString version = "HedgewarsFoundation-Hedgewars-v" + *cVersionString + "_r" + *cRevisionString + "|" + *cHashString; if (summary.isEmpty() || description.isEmpty()) diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/widget/gamecfgwidget.cpp --- a/QTfrontend/ui/widget/gamecfgwidget.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/widget/gamecfgwidget.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -599,7 +599,7 @@ GameSchemes->setEnabled(false); GameSchemes->setCurrentIndex(GameSchemes->findText("Default")); } - else + else if (m_master) { GameSchemes->setEnabled(true); int num = GameSchemes->findText(scheme); @@ -614,7 +614,7 @@ WeaponsName->setEnabled(false); WeaponsName->setCurrentIndex(WeaponsName->findText("Default")); } - else + else if (m_master) { WeaponsName->setEnabled(true); int num = WeaponsName->findText(weapons); diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/widget/mapContainer.cpp --- a/QTfrontend/ui/widget/mapContainer.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/widget/mapContainer.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -75,8 +75,11 @@ /* Layouts */ - QHBoxLayout * typeLayout = new QHBoxLayout(); - QHBoxLayout * seedLayout = new QHBoxLayout(); + QWidget * topWidget = new QWidget(); + QHBoxLayout * topLayout = new QHBoxLayout(topWidget); + topWidget->setContentsMargins(0, 0, 0, 0); + topLayout->setContentsMargins(0, 0, 0, 0); + QHBoxLayout * twoColumnLayout = new QHBoxLayout(); QVBoxLayout * leftLayout = new QVBoxLayout(); QVBoxLayout * rightLayout = new QVBoxLayout(); @@ -84,15 +87,13 @@ twoColumnLayout->addStretch(1); twoColumnLayout->addLayout(rightLayout, 0); QVBoxLayout * drawnControls = new QVBoxLayout(); - leftLayout->addLayout(typeLayout, 0); - rightLayout->addLayout(seedLayout, 0); /* Map type combobox */ - typeLayout->setSpacing(10); - typeLayout->addWidget(new QLabel(tr("Map type:")), 0); + topLayout->setSpacing(10); + topLayout->addWidget(new QLabel(tr("Map type:")), 0); cType = new QComboBox(this); - typeLayout->addWidget(cType, 1); + topLayout->addWidget(cType, 1); cType->insertItem(0, tr("Image map"), MapModel::StaticMap); cType->insertItem(1, tr("Mission map"), MapModel::MissionMap); cType->insertItem(2, tr("Hand-drawn"), MapModel::HandDrawnMap); @@ -103,7 +104,7 @@ /* Randomize button */ - seedLayout->addStretch(1); + topLayout->addStretch(1); const QIcon& lp = QIcon(":/res/dice.png"); QSize sz = lp.actualSize(QSize(65535, 65535)); btnRandomize = new QPushButton(); @@ -117,15 +118,16 @@ m_childWidgets << btnRandomize; btnRandomize->setStyleSheet("padding: 5px;"); btnRandomize->setFixedHeight(cType->height()); - seedLayout->addWidget(btnRandomize, 1); + topLayout->addWidget(btnRandomize, 1); /* Seed button */ + btnSeed = new QPushButton(parentWidget()->parentWidget()); btnSeed->setText(tr("Seed")); btnSeed->setStyleSheet("padding: 5px;"); btnSeed->setFixedHeight(cType->height()); connect(btnSeed, SIGNAL(clicked()), this, SLOT(showSeedPrompt())); - seedLayout->addWidget(btnSeed, 0); + topLayout->addWidget(btnSeed, 0); /* Map preview label */ @@ -137,6 +139,7 @@ mapPreview = new QPushButton(this); mapPreview->setObjectName("mapPreview"); + mapPreview->setFlat(true); mapPreview->setFixedSize(256, 128); mapPreview->setContentsMargins(0, 0, 0, 0); leftLayout->addWidget(mapPreview, 0); @@ -240,13 +243,15 @@ /* Theme chooser */ btnTheme = new QPushButton(); + btnTheme->setFlat(true); connect(btnTheme, SIGNAL(clicked()), this, SLOT(showThemePrompt())); m_childWidgets << btnTheme; bottomLeftLayout->addWidget(btnTheme, 0); /* Add everything to main layout */ - mainLayout.addLayout(twoColumnLayout, 0); + mainLayout.addWidget(topWidget, 0); + mainLayout.addLayout(twoColumnLayout, 1); /* Set defaults */ @@ -463,7 +468,7 @@ void HWMapContainer::setRandomMap() { if (!m_master) return; - + setRandomSeed(); switch(m_mapInfo.type) { diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/ui/widget/teamselect.cpp --- a/QTfrontend/ui/widget/teamselect.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/ui/widget/teamselect.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -38,7 +38,9 @@ curPlayingTeams.push_back(team); connect(framePlaying->getTeamWidget(team), SIGNAL(hhNmChanged(const HWTeam&)), this, SLOT(hhNumChanged(const HWTeam&))); + blockSignals(true); dynamic_cast(framePlaying->getTeamWidget(team))->hhNumChanged(); + blockSignals(false); connect(framePlaying->getTeamWidget(team), SIGNAL(teamColorChanged(const HWTeam&)), this, SLOT(proxyTeamColorChanged(const HWTeam&))); } @@ -210,7 +212,9 @@ { connect(framePlaying->getTeamWidget(team), SIGNAL(hhNmChanged(const HWTeam&)), this, SLOT(hhNumChanged(const HWTeam&))); + blockSignals(true); dynamic_cast(framePlaying->getTeamWidget(team))->hhNumChanged(); + blockSignals(false); connect(framePlaying->getTeamWidget(team), SIGNAL(teamColorChanged(const HWTeam&)), this, SLOT(proxyTeamColorChanged(const HWTeam&))); emit teamColorChanged(((TeamShowWidget*)framePlaying->getTeamWidget(team))->getTeam()); @@ -258,12 +262,16 @@ // Add notice about number of required teams. numTeamNotice = new QLabel(tr("At least two teams are required to play!")); + numTeamNotice->setWordWrap(true); mainLayout.addWidget(numTeamNotice); QPalette p; p.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00)); addScrArea(framePlaying, p.color(QPalette::Window).light(105), 150); addScrArea(frameDontPlaying, p.color(QPalette::Window).dark(105), 0); + + this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + this->setMinimumWidth(200); } void TeamSelWidget::setAcceptOuter(bool acceptOuter) diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/util/DataManager.cpp --- a/QTfrontend/util/DataManager.cpp Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/util/DataManager.cpp Sat Apr 20 02:20:15 2013 +0200 @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "hwconsts.h" #include "HWApplication.h" @@ -162,6 +164,41 @@ return m_bindsModel; } +QString DataManager::settingsFileName() +{ + if(m_settingsFileName.isEmpty()) + { + QFile settingsFile("physfs://settings.ini"); + + if(!settingsFile.exists()) + { + QFile oldSettingsFile("physfs://hedgewars.ini"); + + settingsFile.open(QFile::WriteOnly); + settingsFile.close(); + + if(oldSettingsFile.exists()) + { + QSettings sOld(oldSettingsFile.fileName(), QSettings::IniFormat); + QSettings sNew(settingsFile.fileName(), QSettings::IniFormat); + sNew.setIniCodec("UTF-8"); + + foreach(const QString & key, sOld.allKeys()) + { + if(key.startsWith("colors/color")) + sNew.setValue(key, sOld.value(key).value().name()); + else + sNew.setValue(key, sOld.value(key)); + } + } + } + + m_settingsFileName = settingsFile.fileName(); + } + + return m_settingsFileName; +} + void DataManager::reload() { // removed for now (also code was a bit unclean, could lead to segfault if diff -r 6ea838b8dcd5 -r 13ac59499066 QTfrontend/util/DataManager.h --- a/QTfrontend/util/DataManager.h Sat Apr 20 02:17:53 2013 +0200 +++ b/QTfrontend/util/DataManager.h Sat Apr 20 02:20:15 2013 +0200 @@ -117,6 +117,8 @@ QStandardItemModel * colorsModel(); QStandardItemModel * bindsModel(); + QString settingsFileName(); + static bool ensureFileExists(const QString & fileName); public slots: @@ -148,6 +150,7 @@ ThemeModel * m_themeModel; ///< theme model instance QStandardItemModel * m_colorsModel; QStandardItemModel * m_bindsModel; + QString m_settingsFileName; }; #endif // HEDGEWARS_DATAMANAGER_H diff -r 6ea838b8dcd5 -r 13ac59499066 gameServer/CoreTypes.hs --- a/gameServer/CoreTypes.hs Sat Apr 20 02:17:53 2013 +0200 +++ b/gameServer/CoreTypes.hs Sat Apr 20 02:20:15 2013 +0200 @@ -108,8 +108,7 @@ isKickedFromServer :: Bool, clientClan :: !(Maybe B.ByteString), checkInfo :: Maybe CheckInfo, - teamsInGame :: Word, - actionsPending :: [Action] + teamsInGame :: Word } instance Eq ClientInfo where diff -r 6ea838b8dcd5 -r 13ac59499066 gameServer/HWProtoCore.hs --- a/gameServer/HWProtoCore.hs Sat Apr 20 02:17:53 2013 +0200 +++ b/gameServer/HWProtoCore.hs Sat Apr 20 02:20:15 2013 +0200 @@ -30,7 +30,7 @@ handleCmd ["PONG"] = do cl <- thisClient if pingsQueue cl == 0 then - return $ actionsPending cl ++ [ModifyClient (\c -> c{actionsPending = []})] + return [ProtocolError "Protocol violation"] else return [ModifyClient (\c -> c{pingsQueue = pingsQueue c - 1})] diff -r 6ea838b8dcd5 -r 13ac59499066 gameServer/HWProtoInRoomState.hs --- a/gameServer/HWProtoInRoomState.hs Sat Apr 20 02:17:53 2013 +0200 +++ b/gameServer/HWProtoInRoomState.hs Sat Apr 20 02:20:15 2013 +0200 @@ -54,12 +54,12 @@ roomChans <- roomClientsChans cl <- thisClient teamColor <- - if clientProto cl < 42 then + if clientProto cl < 42 then return color else liftM (head . (L.\\) (map B.singleton ['0'..]) . map teamcolor . teams) thisRoom let roomTeams = teams rm - let hhNum = let p = if not $ null roomTeams then hhnum $ head roomTeams else 4 in newTeamHHNum roomTeams p + let hhNum = let p = if not $ null roomTeams then minimum [hhnum $ head roomTeams, canAddNumber roomTeams] else 4 in newTeamHHNum roomTeams p let newTeam = clNick `seq` TeamInfo ci clNick tName teamColor grave fort voicepack flag dif hhNum (hhsList hhsInfo) return $ if not . null . drop (maxTeams rm - 1) $ roomTeams then @@ -79,10 +79,7 @@ AnswerClients clChan ["TEAM_ACCEPTED", tName], AnswerClients othChans $ teamToNet $ newTeam, AnswerClients roomChans ["TEAM_COLOR", tName, teamColor], - ModifyClient $ \c -> c{actionsPending = actionsPending cl - ++ [AnswerClients clChan ["HH_NUM", tName, showB $ hhnum newTeam]] - }, - AnswerClients [sendChan cl] ["PING"] + AnswerClients roomChans ["HH_NUM", tName, showB $ hhnum newTeam] ] where canAddNumber rt = (48::Int) - (sum $ map hhnum rt) diff -r 6ea838b8dcd5 -r 13ac59499066 gameServer/HWProtoLobbyState.hs --- a/gameServer/HWProtoLobbyState.hs Sat Apr 20 02:17:53 2013 +0200 +++ b/gameServer/HWProtoLobbyState.hs Sat Apr 20 02:20:15 2013 +0200 @@ -92,12 +92,9 @@ , AnswerClients [sendChan cl] $ ["CLIENT_FLAGS", "+h", ownerNick] ] ++ (if clientProto cl < 38 then map (readynessMessage cl) jRoomClients else [sendStateFlags cl jRoomClients]) - ++ [AnswerClients [sendChan cl] ["PING"] - , ModifyClient $ \c -> c{actionsPending = actionsPending cl - ++ answerFullConfig cl (mapParams jRoom) (params jRoom) - ++ answerTeams cl jRoom - ++ watchRound cl jRoom chans} - ] + ++ answerFullConfig cl (mapParams jRoom) (params jRoom) + ++ answerTeams cl jRoom + ++ watchRound cl jRoom chans where readynessMessage cl c = AnswerClients [sendChan cl] [if isReady c then "READY" else "NOT_READY", nick c] diff -r 6ea838b8dcd5 -r 13ac59499066 gameServer/NetRoutines.hs --- a/gameServer/NetRoutines.hs Sat Apr 20 02:17:53 2013 +0200 +++ b/gameServer/NetRoutines.hs Sat Apr 20 02:20:15 2013 +0200 @@ -47,7 +47,6 @@ Nothing Nothing 0 - [] ) writeChan chan $ Accept newClient diff -r 6ea838b8dcd5 -r 13ac59499066 gameServer/OfficialServer/extdbinterface.hs --- a/gameServer/OfficialServer/extdbinterface.hs Sat Apr 20 02:17:53 2013 +0200 +++ b/gameServer/OfficialServer/extdbinterface.hs Sat Apr 20 02:20:15 2013 +0200 @@ -14,7 +14,7 @@ dbQueryAccount = - "SELECT users.pass, users_roles.rid FROM users LEFT JOIN users_roles ON users.uid = users_roles.uid WHERE users.name = ?" + "SELECT users.pass, users_roles.rid FROM users LEFT JOIN users_roles ON (users.uid = users_roles.uid AND users_roles.rid = 3) WHERE users.name = ?" dbQueryStats = "INSERT INTO gameserver_stats (players, rooms, last_update) VALUES (?, ?, UNIX_TIMESTAMP())" @@ -29,7 +29,7 @@ execute statement [SqlByteString clNick] passAndRole <- fetchRow statement finish statement - let response = + let response = if isJust passAndRole then ( clId, diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/ArgParsers.inc --- a/hedgewars/ArgParsers.inc Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/ArgParsers.inc Sat Apr 20 02:20:15 2013 +0200 @@ -170,9 +170,9 @@ mediaArray: Array [1..10] of String = ('--fullscreen-width', '--fullscreen-height', '--width', '--height', '--depth', '--volume','--nomusic','--nosound','--locale','--fullscreen'); allArray: Array [1..14] of String = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--frame-interval','--low-quality'); reallyAll: array[0..30] of shortstring = ( - '--prefix', '--user-prefix', '--locale', '--fullscreen-width', '--fullscreen-height', '--width', + '--prefix', '--user-prefix', '--locale', '--fullscreen-width', '--fullscreen-height', '--width', '--height', '--frame-interval', '--volume','--nomusic', '--nosound', - '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality', '--stereo', '--nick', + '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality', '--stereo', '--nick', {deprecated} '--depth', '--set-video', '--set-audio', '--set-other', '--set-multimedia', '--set-everything', {internal} '--internal', '--port', '--recorder', '--landpreview', {misc} '--stats-only', '--gci', '--help'); @@ -191,8 +191,8 @@ {--locale} 2 : cLocaleFName := getStringParameter (arg, paramIndex, parseParameter); {--fullscreen-width} 3 : cFullscreenWidth := getLongIntParameter(arg, paramIndex, parseParameter); {--fullscreen-height} 4 : cFullscreenHeight := getLongIntParameter(arg, paramIndex, parseParameter); - {--width} 5 : cWindowedWidth := getLongIntParameter(arg, paramIndex, parseParameter); - {--height} 6 : cWindowedHeight := getLongIntParameter(arg, paramIndex, parseParameter); + {--width} 5 : cWindowedWidth := max(2 * (getLongIntParameter(arg, paramIndex, parseParameter) div 2), cMinScreenWidth); + {--height} 6 : cWindowedHeight := max(2 * (getLongIntParameter(arg, paramIndex, parseParameter) div 2), cMinScreenHeight); {--frame-interval} 7 : cTimerInterval := getLongIntParameter(arg, paramIndex, parseParameter); {--volume} 8 : SetVolume ( getLongIntParameter(arg, paramIndex, parseParameter) ); {--nomusic} 9 : SetMusic ( false ); @@ -270,7 +270,7 @@ end; inc(index); end; - + WriteLn(stdout, 'Attempted to automatically convert to the new syntax:'); WriteLn(stdout, newSyntax); WriteLn(stdout, ''); diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/GSHandlers.inc Sat Apr 20 02:20:15 2013 +0200 @@ -417,14 +417,13 @@ CalcRotationDirAngle(Gear); // let's add some smoke depending on speed - s:= max(32,152 - hwRound(Distance(Gear^.dX,Gear^.dY)*120))+random(10); + s:= max(32,152 - round((abs(hwFloat2FLoat(Gear^.dX))+abs(hwFloat2Float(Gear^.dY)))*120))+random(10); if (GameTicks mod s) = 0 then begin // adjust angle to match the texture if Gear^.dX.isNegative then - i:= 130 - else - i:= 50; + i:= 130 + else i:= 50; smoke:= AddVisualGear(hwRound(Gear^.X)-round(cos((Gear^.DirAngle+i) * pi / 180)*20), hwRound(Gear^.Y)-round(sin((Gear^.DirAngle+i) * pi / 180)*20), vgtSmoke); if smoke <> nil then diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/SDLh.pas --- a/hedgewars/SDLh.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/SDLh.pas Sat Apr 20 02:20:15 2013 +0200 @@ -946,12 +946,11 @@ procedure SDL_StartTextInput; cdecl; external SDLLibName; function SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; minType, maxType: LongWord): LongInt; cdecl; external SDLLibName; -function SDL_CreateThread(fn: Pointer; name: PChar; data: Pointer): PSDL_Thread; cdecl; external SDLLibName; {$ELSE} -function SDL_CreateThread(fn: Pointer; data: Pointer): PSDL_Thread; cdecl; external SDLLibName; function SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; mask: LongWord): LongInt; cdecl; external SDLLibName; {$ENDIF} + function SDL_GetMouseState(x, y: PLongInt): Byte; cdecl; external SDLLibName; function SDL_GetKeyName(key: LongWord): PChar; cdecl; external SDLLibName; function SDL_GetScancodeName(key: LongWord): PChar; cdecl; external SDLLibName; @@ -969,7 +968,13 @@ procedure SDL_WM_SetCaption(title: PChar; icon: PChar); cdecl; external SDLLibName; function SDL_WM_ToggleFullScreen(surface: PSDL_Surface): LongInt; cdecl; external SDLLibName; + +// remember to mark the threaded functions as 'cdecl; export;' +// (or have fun debugging nil arguments) +function SDL_CreateThread(fn: Pointer; {$IFDEF SDL13}name: PChar;{$ENDIF} data: Pointer): PSDL_Thread; cdecl; external SDLLibName; procedure SDL_WaitThread(thread: PSDL_Thread; status: PLongInt); cdecl; external SDLLibName; +procedure SDL_KillThread(thread: PSDL_Thread); cdecl; external SDLLibName; + function SDL_CreateMutex: PSDL_mutex; cdecl; external SDLLibName; procedure SDL_DestroyMutex(mutex: PSDL_mutex); cdecl; external SDLLibName; function SDL_LockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName name 'SDL_mutexP'; diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/hwengine.pas Sat Apr 20 02:20:15 2013 +0200 @@ -32,7 +32,7 @@ uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler , uSound, uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uAILandMarks, uLandTexture, uCollisions , SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted - , uPhysFSLayer, uCursor + , uPhysFSLayer, uCursor, uRandom {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}, uTouch {$ENDIF} {$IFDEF ANDROID}, GLUnit{$ENDIF} @@ -79,6 +79,7 @@ DisableSomeWeapons; AddClouds; AddFlakes; + SetRandomSeed(cSeed, false); AssignHHCoords; AddMiscGears; StoreLoad(false); @@ -156,7 +157,7 @@ while isTerminated = false do begin SDL_PumpEvents(); - + while SDL_PeepEvents(@event, 1, SDL_GETEVENT, {$IFDEF SDL13}SDL_FIRSTEVENT, SDL_LASTEVENT{$ELSE}SDL_ALLEVENTS{$ENDIF}) > 0 do begin case event.type_ of @@ -172,7 +173,7 @@ SDL_KEYUP: if GameState <> gsChat then ProcessKey(event.key); - + SDL_WINDOWEVENT: if event.window.event = SDL_WINDOWEVENT_SHOWN then begin @@ -198,13 +199,13 @@ cNewScreenHeight:= max(2 * (event.window.data2 div 2), cMinScreenHeight); cScreenResizeDelay:= RealTicks + 500{$IFDEF IPHONEOS}div 2{$ENDIF}; end; - + SDL_FINGERMOTION: onTouchMotion(event.tfinger.x, event.tfinger.y,event.tfinger.dx, event.tfinger.dy, event.tfinger.fingerId); - + SDL_FINGERDOWN: onTouchDown(event.tfinger.x, event.tfinger.y, event.tfinger.fingerId); - + SDL_FINGERUP: onTouchUp(event.tfinger.x, event.tfinger.y, event.tfinger.fingerId); {$ELSE} @@ -216,7 +217,7 @@ SDL_KEYUP: if GameState <> gsChat then ProcessKey(event.key); - + SDL_MOUSEBUTTONDOWN: if GameState = gsConfirm then begin @@ -225,10 +226,10 @@ end else ProcessMouse(event.button, true); - + SDL_MOUSEBUTTONUP: - ProcessMouse(event.button, false); - + ProcessMouse(event.button, false); + SDL_ACTIVEEVENT: if (event.active.state and SDL_APPINPUTFOCUS) <> 0 then begin @@ -237,7 +238,7 @@ if prevFocusState xor cHasFocus then onFocusStateChanged() end; - + SDL_VIDEORESIZE: begin // using lower values than cMinScreenWidth or cMinScreenHeight causes widget overlap and off-screen widget parts @@ -341,7 +342,7 @@ ' (' + cHashString + ') with protocol #' + inttostr(cNetProtoVersion)); AddFileLog('Prefix: "' + PathPrefix +'"'); AddFileLog('UserPrefix: "' + UserPathPrefix +'"'); - + for i:= 0 to ParamCount do AddFileLog(inttostr(i) + ': ' + ParamStr(i)); @@ -361,7 +362,7 @@ InitOffscreenOpenGL() else {$ENDIF} - begin + begin // show main window if cFullScreen then ParseCommand('fullscr 1', true) diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/options.inc --- a/hedgewars/options.inc Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/options.inc Sat Apr 20 02:20:15 2013 +0200 @@ -29,10 +29,8 @@ {$DEFINE USE_LUA_SCRIPT} - {$IFDEF ANDROID} {$DEFINE MOBILE} - {$DEFINE USE_SDLTHREADS} {$DEFINE USE_CONTEXT_RESTORE} {$DEFINE Java_Prefix:= 'Java_org_hedgewars_hedgeroid_EngineProtocol_PascalExports_'} {$ENDIF} diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uAI.pas --- a/hedgewars/uAI.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uAI.pas Sat Apr 20 02:20:15 2013 +0200 @@ -30,31 +30,27 @@ implementation uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions, - uAmmos, SysUtils{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes, + uAmmos, SysUtils, uTypes, uVariables, uCommands, uUtils, uDebug, uAILandMarks; var BestActions: TActions; CanUseAmmo: array [TAmmoType] of boolean; StopThinking: boolean; -{$IFDEF USE_SDLTHREADS} - ThinkThread: PSDL_Thread = nil; -{$ELSE} - ThinkThread: TThreadID; -{$ENDIF} - hasThread: LongInt; StartTicks: Longword; + ThinkThread: PSDL_Thread; + ThreadLock: PSDL_Mutex; procedure FreeActionsList; begin AddFileLog('FreeActionsList called'); - if hasThread <> 0 then - begin - AddFileLog('Waiting AI thread to finish'); + if (ThinkThread <> nil) then + begin StopThinking:= true; - repeat - SDL_Delay(10) - until hasThread = 0 - end; + SDL_WaitThread(ThinkThread, nil); + end; + SDL_LockMutex(ThreadLock); + ThinkThread:= nil; + SDL_UnlockMutex(ThreadLock); with CurrentHedgehog^ do if Gear <> nil then @@ -66,7 +62,6 @@ end; - const cBranchStackSize = 12; type TStackEntry = record WastedTicks: Longword; @@ -123,15 +118,11 @@ with Me^.Hedgehog^ do a:= CurAmmoType; aa:= a; -{$IFDEF USE_SDLTHREADS} - SDL_delay(0); //ThreadSwitch was only a hint -{$ELSE} - ThreadSwitch(); -{$ENDIF} + SDL_delay(0); // hint to let the context switch run repeat - if (CanUseAmmo[a]) - and ((not rareChecks) or ((AmmoTests[a].flags and amtest_Rare) = 0)) - and ((i = 0) or ((AmmoTests[a].flags and amtest_NoTarget) = 0)) + if (CanUseAmmo[a]) + and ((not rareChecks) or ((AmmoTests[a].flags and amtest_Rare) = 0)) + and ((i = 0) or ((AmmoTests[a].flags and amtest_NoTarget) = 0)) then begin {$HINTS OFF} @@ -150,10 +141,10 @@ AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) else if (ap.Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0); - + if (Ammoz[a].Ammo.Propz and ammoprop_Timerable) <> 0 then AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0); - + if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then begin dAngle:= LongInt(Me^.Angle) - Abs(ap.Angle); @@ -168,23 +159,23 @@ AddAction(BestActions, aia_Down, aim_release, -dAngle, 0, 0) end end; - + if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then begin AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY) end; - + if (Ammoz[a].Ammo.Propz and ammoprop_OscAim) <> 0 then begin AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0); AddAction(BestActions, aia_attack, aim_release, 1, 0, 0); - + if abs(ap.Angle) > 32 then begin AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0); AddAction(BestActions, aia_Down, aim_release, 32, 0, 0); end; - + AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0); AddAction(BestActions, aia_attack, aim_push, 1, 0, 0); AddAction(BestActions, aia_attack, aim_release, 1, 0, 0); @@ -243,21 +234,21 @@ if (Me^.State and gstAttacked) = 0 then TestAmmos(Actions, Me, false); - + BestRate:= RatePlace(Me); BaseRate:= Max(BestRate, 0); -// switch to 'skip' if we can't move because of mouse cursor being shown +// switch to 'skip' if we cannot move because of mouse cursor being shown if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0); - -if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) + +if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) and (GameFlags and gfArtillery = 0) then begin tmp:= random(2) + 1; Push(0, Actions, Me^, tmp); Push(0, Actions, Me^, tmp xor 3); - + while (Stack.Count > 0) and (not StopThinking) do begin Pop(ticks, Actions, Me^); @@ -267,7 +258,7 @@ AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0) else AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0); - + steps:= 0; while (not StopThinking) do @@ -280,8 +271,8 @@ if ticks > maxticks then break; - if (BotLevel < 5) - and (GoInfo.JumpType = jmpHJump) + if (BotLevel < 5) + and (GoInfo.JumpType = jmpHJump) and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markHJumped)) then // hjump support begin @@ -295,7 +286,7 @@ AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0) else AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0); - + AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0); AddAction(MadeActions, aia_HJump, 0, 350, 0, 0); end; @@ -303,8 +294,8 @@ Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message) end; end; - if (BotLevel < 3) - and (GoInfo.JumpType = jmpLJump) + if (BotLevel < 3) + and (GoInfo.JumpType = jmpLJump) and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markLJumped)) then // ljump support begin @@ -323,7 +314,7 @@ // push current position so we proceed from it after checking jump+forward walk opportunities if CanGo then Push(ticks, Actions, Me^, Me^.Message); - + // first check where we go after jump walking forward if Push(ticks, Actions, AltMe, Me^.Message) then with Stack.States[Pred(Stack.Count)] do @@ -331,10 +322,10 @@ break end; - // 'not CanGO' means we can't go straight, possible jumps are checked above + // 'not CanGO' means we cannot go straight, possible jumps are checked above if not CanGo then break; - + inc(steps); Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X); Rate:= RatePlace(Me); @@ -347,17 +338,17 @@ end else if Rate < BestRate then break; - + if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then begin if (steps > 4) and checkMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere) then - break; + break; addMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere); TestAmmos(Actions, Me, ticks shr 12 = oldticks shr 12); - + end; - + if GoInfo.FallPix >= FallPixForBranching then Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right end {while}; @@ -368,25 +359,26 @@ end {if} end; -function Think(Me: Pointer): ptrint; +function Think(Me: PGear): LongInt; cdecl; export; var BackMe, WalkMe: TGear; switchCount: LongInt; StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword; switchImmediatelyAvailable: boolean; Actions: TActions; begin -InterlockedIncrement(hasThread); +AddFileLog('Think thread started'); +dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; StartTicks:= GameTicks; currHedgehogIndex:= CurrentTeam^.CurrHedgehog; itHedgehog:= currHedgehogIndex; switchesNum:= 0; switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher); -if PGear(Me)^.Hedgehog^.BotLevel <> 5 then +if Me^.Hedgehog^.BotLevel <> 5 then switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch) else switchCount:= 0; -if (PGear(Me)^.State and gstAttacked) = 0 then +if (Me^.State and gstAttacked) = 0 then if Targets.Count > 0 then begin // iterate over current team hedgehogs @@ -402,7 +394,7 @@ begin // when AI has to use switcher, make it cost smth unless they have a lot of switches if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000; - AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0); + AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0); AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0); AddAction(Actions, aia_attack, aim_release, 1, 0, 0); end; @@ -416,10 +408,9 @@ itHedgehog:= Succ(itHedgehog) mod CurrentTeam^.HedgehogsNumber; until (itHedgehog = currHedgehogIndex) or ((CurrentTeam^.Hedgehogs[itHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[itHedgehog].Effects[heFrozen]=0)); - inc(switchesNum); until (not (switchImmediatelyAvailable or (switchCount > 0))) - or StopThinking + or StopThinking or (itHedgehog = currHedgehogIndex) or BestActions.isWalkingToABetterPlace; @@ -435,7 +426,7 @@ end else SDL_Delay(100) else begin - BackMe:= PGear(Me)^; + BackMe:= Me^; while (not StopThinking) and (BestActions.Count = 0) do begin (* @@ -454,9 +445,11 @@ end end; -PGear(Me)^.State:= PGear(Me)^.State and (not gstHHThinking); +Me^.State:= Me^.State and (not gstHHThinking); +SDL_LockMutex(ThreadLock); +ThinkThread:= nil; +SDL_UnlockMutex(ThreadLock); Think:= 0; -InterlockedDecrement(hasThread) end; procedure StartThink(Me: PGear); @@ -486,13 +479,10 @@ end; FillBonuses((Me^.State and gstAttacked) <> 0); -AddFileLog('Enter Think Thread'); -{$IFDEF USE_SDLTHREADS} -ThinkThread := SDL_CreateThread(@Think{$IFDEF SDL13}, nil{$ENDIF}, Me); -{$ELSE} -BeginThread(@Think, Me, ThinkThread); -{$ENDIF} -AddFileLog('Thread started'); + +SDL_LockMutex(ThreadLock); +ThinkThread:= SDL_CreateThread(@Think{$IFDEF SDL13}, 'think'{$ENDIF}, Me); +SDL_UnlockMutex(ThreadLock); end; //var scoreShown: boolean = false; @@ -513,14 +503,14 @@ StopMessages(Gear^.Message); TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true); end; - + if Gear^.Message <> 0 then exit; - - //scoreShown:= false; + + //scoreShown:= false; StartThink(Gear); StartTicks:= GameTicks - + end else begin {if not scoreShown then @@ -537,14 +527,15 @@ procedure initModule; begin - hasThread:= 0; StartTicks:= 0; - ThinkThread:= ThinkThread; + ThinkThread:= nil; + ThreadLock:= SDL_CreateMutex(); end; procedure freeModule; begin FreeActionsList(); + SDL_DestroyMutex(ThreadLock); end; end. diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uAIAmmoTests.pas Sat Apr 20 02:20:15 2013 +0200 @@ -21,7 +21,7 @@ unit uAIAmmoTests; interface uses SDLh, uConsts, uFloat, uTypes; -const +const amtest_Rare = $00000001; // check only several positions amtest_NoTarget = $00000002; // each pos, but no targetting @@ -163,9 +163,9 @@ dX:= dX + windSpeed; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0); - + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0); + EX:= trunc(x); EY:= trunc(y); if Level = 1 then @@ -184,7 +184,7 @@ end; end //until (value > 204800) or (rTime > 4250); not so useful since adding score to the drowning -until rTime > 4250; +until rTime > 5050 - Level * 800; TestBazooka:= valueResult end; @@ -226,10 +226,10 @@ dX:= dX + windSpeed; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (y > cWaterLine); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (y > cWaterLine); - if TestCollWithLand(trunc(x), trunc(y), 5) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then + if TestCollExcludingObjects(trunc(x), trunc(y), 5) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then begin timer := 500; t2 := 0.5 / sqrt(sqr(dX) + sqr(dY)); @@ -244,11 +244,13 @@ or (y < 0) or (trunc(x) > LAND_WIDTH) or (trunc(y) > LAND_HEIGHT) - or not TestCollWithLand(trunc(x), trunc(y), 5) + or not TestCollExcludingObjects(trunc(x), trunc(y), 5) or (timer = 0) end; EX:= trunc(x); EY:= trunc(y); + // Try to prevent AI from thinking firing into water will cause a drowning + if (EY < cWaterLine-5) and (Timer > 0) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then exit(BadTurn); if Level = 1 then value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else value:= RateExplosion(Me, EX, EY, 101); @@ -262,7 +264,7 @@ valueResult:= value-2500 // trying to make it slightly less attractive than a bazooka, to prevent waste. AI could use awareness of weapon count end; end - until rTime > 4250; + until rTime > 5050 - Level * 800; TestDrillRocket:= valueResult end; @@ -301,8 +303,8 @@ dX:= dX + windSpeed; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0); EX:= trunc(x); EY:= trunc(y); @@ -321,7 +323,7 @@ valueResult:= value end; end -until (rTime > 4250); +until (rTime > 5050 - Level * 800); TestSnowball:= valueResult end; @@ -353,15 +355,15 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0); EX:= trunc(x); EY:= trunc(y); if t < 50 then Score:= RateExplosion(Me, EX, EY, 97) // average of 17 attempts, most good, but some failing spectacularly else Score:= BadTurn; - + if valueResult < Score then begin ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); @@ -372,7 +374,7 @@ valueResult:= Score end; end -until (TestTime > 4250); +until (TestTime > 5050 - Level * 800); TestMolotov:= valueResult end; @@ -397,7 +399,7 @@ if not (r > 1) then begin x:= meX; - y:= meY; + y:= meY; dY:= -Vy; t:= TestTime; repeat @@ -405,21 +407,21 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0); EX:= trunc(x); EY:= trunc(y); - if t < 50 then + if t < 50 then if Level = 1 then Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else Score:= RateExplosion(Me, EX, EY, 101) - else + else Score:= BadTurn; if (valueResult < Score) and (Score > 0) then begin - ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); - ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15); + ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 3)); + ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 20); ap.Time:= TestTime; ap.ExplR:= 100; ap.ExplX:= EX; @@ -428,7 +430,7 @@ end; end //until (Score > 204800) or (TestTime > 4000); -until TestTime > 4000; +until TestTime > 4500 - Level * 512; TestGrenade:= valueResult end; @@ -465,18 +467,18 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0); EX:= trunc(x); EY:= trunc(y); - if t < 50 then + if t < 50 then Score:= RateExplosion(Me, EX, EY, 41) - else + else Score:= BadTurn; if valueResult < Score then begin - ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); + ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 2)); ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15); ap.Time:= TestTime div 1000 * 1000; ap.ExplR:= 90; @@ -518,16 +520,16 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0); - + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0); + EX:= trunc(x); EY:= trunc(y); - if t < 50 then + if t < 50 then Score:= RateExplosion(Me, EX, EY, 200) + RateExplosion(Me, EX, EY + 120, 200) - else + else Score:= BadTurn; - + if valueResult < Score then begin ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); @@ -564,7 +566,7 @@ else Solve:= 0 end; - + function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; //const tDelta = 24; var Vx, Vy: real; @@ -599,8 +601,8 @@ dY:= dY + cGravityf; EX:= trunc(x); EY:= trunc(y); - until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, EX, EY, 4))) or (EY > cWaterLine); + until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine); if (EY < cWaterLine) and (dY >= 0) then begin @@ -653,16 +655,16 @@ y:= y + vY; rx:= trunc(x); ry:= trunc(y); - if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, rx, ry, 2)) then + if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, rx, ry, 2)) then begin x:= x + vX * 8; y:= y + vY * 8; valueResult:= RateShotgun(Me, vX, vY, rx, ry); - - if valueResult = 0 then + + if valueResult = 0 then valueResult:= 1024 - Metric(Targ.X, Targ.Y, rx, ry) div 64 - else + else dec(valueResult, Level * 4000); // 27/20 is reuse bonus exit(valueResult * 27 div 20) @@ -768,7 +770,7 @@ fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg); if fallDmg < 0 then TestSniperRifle:= BadTurn - else + else TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024) end else @@ -807,13 +809,13 @@ , 32, 30, 115 , dx, -dy, trackFall); if (v1 > valueResult) or (v2 > valueResult) then - if (v2 > v1) + if (v2 > v1) or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then begin ap.Angle:= a; valueResult:= v2 end - else + else begin ap.Angle:= -a; valueResult:= v1 @@ -821,7 +823,7 @@ a:= a - 15 - random(cMaxAngle div 16) end; - + if valueResult <= 0 then valueResult:= BadTurn; @@ -867,18 +869,18 @@ , 19, 30, 40 , 0.45, -0.9, trackFall); - if (v2 > v1) + if (v2 > v1) or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then begin ap.Angle:= 1; valueResult:= v2 end - else + else begin ap.Angle:= -1; valueResult:= v1 end; - + if valueResult <= 0 then valueResult:= BadTurn; @@ -902,8 +904,8 @@ y:= hwRound(Me^.Y); // check left direction - {first RateShove checks farthermost of two whip's AmmoShove attacks - to encourage distant attacks (damaged hog is excluded from view of second + {first RateShove checks farthermost of two whip's AmmoShove attacks + to encourage distant attacks (damaged hog is excluded from view of second RateShove call)} v1:= RateShove(x - 13, y , 30, 30, 25 @@ -921,18 +923,18 @@ , 30, 30, 25 , 1, -0.8, trackFall); - if (v2 > v1) + if (v2 > v1) or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then begin ap.Angle:= 1; valueResult:= v2 end - else + else begin ap.Angle:= -1; valueResult:= v1 end; - + if valueResult <= 0 then valueResult:= BadTurn else @@ -951,13 +953,13 @@ ap.Time:= 0; ap.Power:= 1; - if Level = 1 then + if Level = 1 then trackFall:= afTrackFall else if Level = 2 then trackFall:= 0 else exit(BadTurn); - + valueResult:= 0; v:= 0; @@ -978,16 +980,16 @@ ap.Angle:= DxDy2AttackAnglef(dx, -dy) end; - + if dx >= 0 then cx:= 0.45 else cx:= -0.45; for i:= 0 to 512 div step - 2 do begin - valueResult:= valueResult + + valueResult:= valueResult + RateShove(trunc(x), trunc(y) , 30, 30, 25 , cx, -0.9, trackFall or afSetSkip); - + x:= x + dx; y:= y + dy; end; @@ -1002,7 +1004,7 @@ for i:= 1 to 512 div step - 2 do begin y:= y + dy; - v:= v + + v:= v + RateShove(tx, trunc(y) , 30, 30, 25 , -cx, -0.9, trackFall or afSetSkip); @@ -1035,7 +1037,7 @@ ap.Time:= 0; ap.Power:= 1; ap.Angle:= 0; - + rate:= RateHammer(Me); if rate = 0 then rate:= BadTurn; @@ -1126,7 +1128,7 @@ if Me^.Health <= 100 then begin maxTop := Targ.Y - cHHRadius * 2; - + while not TestColl(Targ.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do dec(maxTop, cHHRadius*2); if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then @@ -1145,7 +1147,7 @@ inc(failNum); until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius) or (failNum = bonuses.Count*2); - + if failNum < bonuses.Count*2 then begin ap.AttackPutX := bonuses.ar[i].X; @@ -1167,7 +1169,7 @@ begin cakeStep(Gear); v:= RateExplosion(Me, hwRound(Gear^.X), hwRound(Gear^.Y), cakeDmg * 2, afTrackFall); - if v > ap.Power then + if v > ap.Power then begin ap.ExplX:= hwRound(Gear^.X); ap.ExplY:= hwRound(Gear^.Y); diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uAIMisc.pas Sat Apr 20 02:20:15 2013 +0200 @@ -64,7 +64,6 @@ function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; function TraceShoveFall(x, y, dX, dY: Real): LongInt; -function TestCollWithLand(x, y, r: LongInt): boolean; inline; function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; @@ -90,11 +89,12 @@ const KillScore = 200; var friendlyfactor: LongInt = 300; +var dmgMod: real = 1.0; implementation uses uCollisions, uVariables, uUtils, uLandTexture, uGearsUtils; -var +var KnownExplosion: record X, Y, Radius: LongInt end = (X: 0; Y: 0; Radius: 0); @@ -113,14 +113,14 @@ for i:= 0 to cMaxHHIndex do if (Hedgehogs[i].Gear <> nil) and (Hedgehogs[i].Gear <> ThinkingHH) - and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) + and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) then begin with Targets.ar[Targets.Count], Hedgehogs[i] do begin skip:= false; matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0; - + Point.X:= hwRound(Gear^.X); Point.Y:= hwRound(Gear^.Y); if Clan <> CurrentTeam^.Clan then @@ -181,24 +181,24 @@ gtFlame: if (Gear^.State and gsttmpFlag) <> 0 then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50); -// avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow +// avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow gtMine: if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) and (Gear^.Health <> 0)) or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50) else if (Gear^.State and gstAttacking) <> 0 then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on - + gtExplosives: if isAfterAttack then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60 + Gear^.Health); - + gtSMine: AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30); - + gtDynamite: AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75); - + gtHedgehog: begin if Gear^.Damage >= Gear^.Health then @@ -270,8 +270,8 @@ if not CheckBounds(x, y, r) then exit(false); - if (Land[y-r, x-r] <> 0) or - (Land[y+r, x-r] <> 0) or + if (Land[y-r, x-r] <> 0) or + (Land[y+r, x-r] <> 0) or (Land[y-r, x+r] <> 0) or (Land[y+r, x+r] <> 0) then exit(true); @@ -285,7 +285,7 @@ exit(false); if (Land[y-r, x-r] > lfAllObjMask) or - (Land[y+r, x-r] > lfAllObjMask) or + (Land[y+r, x-r] > lfAllObjMask) or (Land[y-r, x+r] > lfAllObjMask) or (Land[y+r, x+r] > lfAllObjMask) then exit(true); @@ -299,28 +299,14 @@ exit(false); if (Land[y-r, x-r] and lfNotCurrentMask <> 0) or - (Land[y+r, x-r] and lfNotCurrentMask <> 0) or + (Land[y+r, x-r] and lfNotCurrentMask <> 0) or (Land[y-r, x+r] and lfNotCurrentMask <> 0) or (Land[y+r, x+r] and lfNotCurrentMask <> 0) then exit(true); - + TestColl:= false; end; -function TestCollWithLand(x, y, r: LongInt): boolean; inline; -begin - if not CheckBounds(x, y, r) then - exit(false); - - if (Land[y-r, x-r] > lfAllObjMask) or - (Land[y+r, x-r] > lfAllObjMask) or - (Land[y-r, x+r] > lfAllObjMask) or - (Land[y+r, x+r] > lfAllObjMask) then - exit(true); - - TestCollWithLand:= false; -end; - // Wrapper to test various approaches. If it works reasonably, will just replace. // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with... @@ -356,7 +342,7 @@ y:= y + dY; dY:= dY + cGravityf; skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); - if not skipLandCheck and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then + if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then begin if 0.4 < dY then begin @@ -381,7 +367,7 @@ y:= y + dY; dY:= dY + cGravityf; -{ if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then +{ if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then begin LandPixels[trunc(y), trunc(x)]:= v; UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); @@ -412,11 +398,10 @@ function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; var i, fallDmg, dmg, dmgBase, rate, erasure: LongInt; - dX, dY, dmgMod: real; + dX, dY: real; hadSkips: boolean; begin fallDmg:= 0; -dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; rate:= 0; // add our virtual position with Targets.ar[Targets.Count] do @@ -450,7 +435,7 @@ begin dX:= 0.005 * dmg + 0.01; dY:= dX; - if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and + if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod) @@ -480,16 +465,15 @@ function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; var i, fallDmg, dmg, rate: LongInt; - dX, dY, dmgMod: real; + dX, dY: real; begin fallDmg:= 0; dX:= gdX * 0.01 * kick; dY:= gdY * 0.01 * kick; -dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; rate:= 0; for i:= 0 to Pred(Targets.Count) do with Targets.ar[i] do - if skip then + if skip then if (Flags and afSetSkip = 0) then skip:= false else {still skip} else if matters then begin @@ -500,7 +484,7 @@ if dmg > 0 then begin if (Flags and afSetSkip <> 0) then skip:= true; - if (Flags and afTrackFall <> 0) and (Score > 0) then + if (Flags and afTrackFall <> 0) and (Score > 0) then fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod); if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI if Score > 0 then @@ -524,10 +508,9 @@ function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt; - dX, dY, dmgMod: real; + dX, dY: real; hadSkips: boolean; begin -dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; rate:= 0; gdX:= gdX * 0.01; gdY:= gdX * 0.01; @@ -565,7 +548,7 @@ dY:= gdY * dmg; if dX < 0 then dX:= dX - 0.01 else dX:= dX + 0.01; - if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and + if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod); @@ -610,7 +593,7 @@ r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); if r <= 18 then - if Score > 0 then + if Score > 0 then inc(rate, Score div 3) else inc(rate, Score div 3 * friendlyfactor div 100) @@ -628,7 +611,7 @@ bY:= hwRound(Gear^.Y); case JumpType of jmpNone: exit(false); - + jmpHJump: if TestCollisionYwithGear(Gear, -1) = 0 then begin @@ -638,7 +621,7 @@ end else exit(false); - + jmpLJump: begin if TestCollisionYwithGear(Gear, -1) <> 0 then @@ -660,12 +643,12 @@ end; repeat - {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then + {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then begin LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= Gear^.Hedgehog^.Team^.Clan^.Color; UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true); end;} - + if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then exit(false); if (Gear^.State and gstMoving) <> 0 then @@ -723,7 +706,7 @@ GoInfo.JumpType:= jmpNone; tY:= hwRound(Gear^.Y); repeat - {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then + {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then begin LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= random($FFFFFFFF);//Gear^.Hedgehog^.Team^.Clan^.Color; UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true); @@ -737,8 +720,8 @@ AddWalkBonus(pX, tY, 250, -40); exit(false) end; - - // hog is falling + + // hog is falling if (Gear^.State and gstMoving) <> 0 then begin inc(GoInfo.Ticks); @@ -747,7 +730,7 @@ begin GoInfo.FallPix:= 0; // try ljump instead of fall with damage - HHJump(AltGear, jmpLJump, GoInfo); + HHJump(AltGear, jmpLJump, GoInfo); if AltGear^.Hedgehog^.BotLevel < 4 then AddWalkBonus(pX, tY, 175, -20); exit(false) diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uCommandHandlers.pas Sat Apr 20 02:20:15 2013 +0200 @@ -36,7 +36,7 @@ procedure chGenCmd(var s: shortstring); begin case s[1] of - 'R': if ReadyTimeLeft > 1 then + 'R': if ReadyTimeLeft > 1 then begin ReadyTimeLeft:= 1; if not isExternalSource then @@ -480,7 +480,7 @@ with CurrentHedgehog^.Gear^ do begin Message:= Message or (gmSlot and InputMask); - MsgParam:= slot; + MsgParam:= slot; ScriptCall('onSlot', MsgParam); end end; @@ -517,7 +517,7 @@ with CurrentHedgehog^.Gear^ do begin Message:= Message or (gmAnimate and InputMask); - MsgParam:= byte(s[1]) ; + MsgParam:= byte(s[1]) ; ScriptCall('onTaunt', MsgParam); end end; @@ -573,7 +573,7 @@ begin if isDeveloperMode then begin - SetRandomSeed(s); + SetRandomSeed(s, true); cSeed:= s; InitStepsFlags:= InitStepsFlags or cifRandomize end diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uFloat.pas --- a/hedgewars/uFloat.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uFloat.pas Sat Apr 20 02:20:15 2013 +0200 @@ -84,7 +84,8 @@ function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign. function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t. function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value -function hwSqrt(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t. +function hwSqrt1(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t. +function hwSqrt(const x: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t. function Distance(const dx, dy: hwFloat): hwFloat; // Returns the distance between two points in 2-dimensional space, of which the parameters are the horizontal and vertical distance. function DistanceI(const dx, dy: LongInt): hwFloat; // Same as above for integer parameters. function AngleSin(const Angle: Longword): hwFloat; @@ -264,7 +265,7 @@ end end; -function isZero(const z: hwFloat): boolean; inline; +function isZero(const z: hwFloat): boolean; inline; begin isZero := z.QWordValue = 0; end; @@ -277,7 +278,7 @@ if z1.QWordValue = z2.QWordValue then b:= false else - b:= not((z1.QWordValue = z2.QWordValue) or ((z2.QWordValue < z1.QWordValue) <> z1.isNegative)) + b:= (z2.QWordValue < z1.QWordValue) = z1.isNegative end; operator > (const z1, z2: hwFloat) b : boolean; inline; @@ -312,24 +313,23 @@ end; operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline; -var t: hwFloat; +var t: QWord; begin z.isNegative:= z1.isNegative xor z2.isNegative; z.Round:= z1.QWordValue div z2.QWordValue; -t:= z1 - z2 * z.Round; -if t.QWordValue = 0 then - z.Frac:= 0 -else +t:= z1.QWordValue - z2.QWordValue * z.Round; +z.Frac:= 0; + +if t <> 0 then begin - while ((t.QWordValue and $8000000000000000) = 0) and ((z2.QWordValue and $8000000000000000) = 0) do + while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do begin - t.QWordValue:= t.QWordValue shl 1; - z2.QWordValue:= z2.QWordValue shl 1 + t:= t shl 8; + z2.QWordValue:= z2.QWordValue shl 8 end; + if z2.Round > 0 then - z.Frac:= (t.QWordValue) div (z2.Round) - else - z.Frac:= 0 + inc(z.QWordValue, t div z2.Round); end end; @@ -385,14 +385,14 @@ end end; -function hwSqrt(const t: hwFloat): hwFloat; +function hwSqrt1(const t: hwFloat): hwFloat; const pwr = 8; // even value, feel free to adjust rThreshold = 1 shl (pwr + 32); lThreshold = 1 shl (pwr div 2 + 32); var l, r: QWord; c: hwFloat; begin -hwSqrt.isNegative:= false; +hwSqrt1.isNegative:= false; if t.Round = 0 then begin @@ -425,12 +425,47 @@ l:= c.QWordValue until r - l <= 1; -hwSqrt.QWordValue:= l +hwSqrt1.QWordValue:= l end; -function Distance(const dx, dy: hwFloat): hwFloat; +function hwSqrt(const x: hwFloat): hwFloat; +var r, t, s, q: QWord; + i: integer; begin -Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy)) +hwSqrt.isNegative:= false; + +t:= $4000000000000000; +r:= 0; +q:= x.QWordValue; + +for i:= 0 to 31 do + begin + s:= r + t; + r:= r shr 1; + if s <= q then + begin + dec(q, s); + inc(r, t); + end; + t:= t shr 2; + end; + +hwSqrt.QWordValue:= r shl 16 +end; + + + +function Distance(const dx, dy: hwFloat): hwFloat; +var r: QWord; +begin +r:= dx.QWordValue or dy.QWordValue; + +if r < $10000 then + begin + Distance.QWordValue:= r; + Distance.isNegative:= false + end else + Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy)) end; function DistanceI(const dx, dy: LongInt): hwFloat; diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uMisc.pas --- a/hedgewars/uMisc.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uMisc.pas Sat Apr 20 02:20:15 2013 +0200 @@ -38,8 +38,7 @@ implementation uses SysUtils, uVariables, uUtils - {$IFDEF PNG_SCREENSHOTS}, PNGh, png {$ENDIF} - {$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}; + {$IFDEF PNG_SCREENSHOTS}, PNGh, png {$ENDIF}; type PScreenshot = ^TScreenshot; TScreenshot = record @@ -64,7 +63,7 @@ {$IFDEF PNG_SCREENSHOTS} // this funtion will be executed in separate thread -function SaveScreenshot(screenshot: pointer): PtrInt; +function SaveScreenshot(screenshot: pointer): LongInt; cdecl; export; var i: LongInt; png_ptr: ^png_struct; info_ptr: ^png_info; @@ -119,7 +118,7 @@ {$ELSE} // no PNG_SCREENSHOTS // this funtion will be executed in separate thread -function SaveScreenshot(screenshot: pointer): PtrInt; +function SaveScreenshot(screenshot: pointer): LongInt; cdecl; export; var f: file; // Windows Bitmap Header head: array[0..53] of Byte = ( @@ -262,11 +261,7 @@ image^.size:= size; image^.buffer:= p; -{$IFDEF USE_SDLTHREADS} -SDL_CreateThread(@SaveScreenshot{$IFDEF SDL13}, nil{$ENDIF}, image); -{$ELSE} -BeginThread(@SaveScreenshot, image); -{$ENDIF} +SDL_CreateThread(@SaveScreenshot{$IFDEF SDL13}, 'snapshot'{$ENDIF}, image); MakeScreenshot:= true; // possibly it is not true but we will not wait for thread to terminate end; diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uRandom.pas --- a/hedgewars/uRandom.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uRandom.pas Sat Apr 20 02:20:15 2013 +0200 @@ -30,7 +30,7 @@ interface uses uFloat; -procedure SetRandomSeed(Seed: shortstring); // Sets the seed that should be used for generating pseudo-random values. +procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean); // Sets the seed that should be used for generating pseudo-random values. function GetRandomf: hwFloat; overload; // Returns a pseudo-random hwFloat. function GetRandom(m: LongWord): LongWord; overload; inline; // Returns a positive pseudo-random integer smaller than m. procedure AddRandomness(r: LongWord); inline; @@ -59,18 +59,24 @@ GetNext:= cirbuf[n] end; -procedure SetRandomSeed(Seed: shortstring); -var i: Longword; +procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean); +var i, t, l: Longword; begin n:= 54; if Length(Seed) > 54 then Seed:= copy(Seed, 1, 54); // not 55 to ensure we have odd numbers in cirbuf -for i:= 0 to Pred(Length(Seed)) do - cirbuf[i]:= byte(Seed[i + 1]); +t:= 0; +l:= Length(Seed); -for i:= Length(Seed) to 54 do +while (t < l) and ((not dropAdditionalPart) or (Seed[t + 1] <> '|')) do + begin + cirbuf[t]:= byte(Seed[t + 1]); + inc(t) + end; + +for i:= t to 54 do cirbuf[i]:= $A98765 + 68; // odd number for i:= 0 to 1023 do diff -r 6ea838b8dcd5 -r 13ac59499066 project_files/hedgewars.pro --- a/project_files/hedgewars.pro Sat Apr 20 02:17:53 2013 +0200 +++ b/project_files/hedgewars.pro Sat Apr 20 02:20:15 2013 +0200 @@ -250,7 +250,7 @@ RESOURCES += ../QTfrontend/hedgewars.qrc -LIBS += -L../bin -lphysfs +LIBS += -L../bin -lhw_physfs -lphyslayer macx { QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/Graphics/hedgehog.svg --- a/share/hedgewars/Data/Graphics/hedgehog.svg Sat Apr 20 02:17:53 2013 +0200 +++ b/share/hedgewars/Data/Graphics/hedgehog.svg Sat Apr 20 02:20:15 2013 +0200 @@ -9,11 +9,11 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="800" + width="1600" height="800" id="svg2902" version="1.1" - inkscape:version="0.47 r22583" + inkscape:version="0.48.3.1 r9886" sodipodi:docname="hedgehog.svg"> Hedgehog @@ -76,17 +76,17 @@ borderopacity="1.0" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:zoom="0.49497475" - inkscape:cx="523.00419" - inkscape:cy="282.86638" + inkscape:zoom="0.45185547" + inkscape:cx="842.9141" + inkscape:cy="306.27016" inkscape:document-units="px" - inkscape:current-layer="g3598" + inkscape:current-layer="layer3" showgrid="false" - inkscape:window-width="1280" - inkscape:window-height="946" - inkscape:window-x="-4" - inkscape:window-y="-3" - inkscape:window-maximized="1" /> + inkscape:window-width="1250" + inkscape:window-height="852" + inkscape:window-x="170" + inkscape:window-y="184" + inkscape:window-maximized="0" /> @@ -112,17 +112,20 @@ style="color:#000000;fill:#2c78d2;fill-opacity:1;stroke:none;stroke-width:22;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" d="M 539.75014,184.97991 289.94272,20.934533 c -10.12171,-6.646795 -18.53237,-1.405552 -18.77514,8.934515 l -6.50762,277.176512" id="path3847" - sodipodi:nodetypes="cccc" /> + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" /> + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" /> + style="color:#000000;fill:none;stroke:#9f086e;stroke-width:22;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + inkscape:connector-curvature="0" /> + style="color:#000000;fill:#54a2fa;fill-opacity:1;stroke:none;stroke-width:22;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + inkscape:connector-curvature="0" /> + id="path3849" + inkscape:connector-curvature="0" /> + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" /> @@ -148,16 +154,19 @@ style="color:#000000;fill:#54a2fa;fill-opacity:1;stroke:none;stroke-width:22;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" d="M 305.99695,247.38296 28.159159,357.4774 c -11.257429,4.46082 -11.804016,14.3558 -3.482965,20.49879 L 247.73076,542.64501" id="path3827" - sodipodi:nodetypes="cccc" /> + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" /> + id="path3854" + inkscape:connector-curvature="0" /> + style="color:#000000;fill:none;stroke:#9f086e;stroke-width:22;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + inkscape:connector-curvature="0" /> @@ -165,16 +174,19 @@ sodipodi:nodetypes="cccc" id="path3829" d="M 228.84636,338.65556 53.568239,580.71384 c -7.101908,9.80772 -2.250103,18.44887 8.068116,19.16343 l 276.590465,19.15401" - style="color:#000000;fill:#54a2fa;fill-opacity:1;stroke:none;stroke-width:22;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="color:#000000;fill:#54a2fa;fill-opacity:1;stroke:none;stroke-width:22;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + inkscape:connector-curvature="0" /> + id="path3859" + inkscape:connector-curvature="0" /> + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" /> + id="path3783" + inkscape:connector-curvature="0" /> + id="path3762" + inkscape:connector-curvature="0" /> + id="path3749" + inkscape:connector-curvature="0" /> + transform="translate(-5.6478893,85.928699)" + inkscape:connector-curvature="0" /> + id="path3736" + inkscape:connector-curvature="0" /> + sodipodi:nodetypes="csssss" + inkscape:connector-curvature="0" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/Locale/missions_tr.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/missions_tr.txt Sat Apr 20 02:20:15 2013 +0200 @@ -0,0 +1,50 @@ +Basic_Training_-_Bazooka.name=Temel Roketatar Eğitimi +Basic_Training_-_Bazooka.desc="Rüzgarı yararına kullanmak bir anahtar!" + +Basic_Training_-_Grenade.name=Temel Bomba Eğitimi +Basic_Training_-_Grenade.desc="Unutma, pimi çek VE at!" + +Basic_Training_-_Cluster_Bomb.name=Temel Parça Tesirli Bomba Eğitimi +Basic_Training_-_Cluster_Bomb.desc="Birinin sıcak duşa ihtiyacı var!" + +Basic_Training_-_Shotgun.name=Temel Tüfek Eğitimi +Basic_Training_-_Shotgun.desc="Önce atış yap, soruları sonra sor!" + +Basic_Training_-_Sniper_Rifle.name=Temel Keskin Nişancı Tüfeği Eğitimi +Basic_Training_-_Sniper_Rifle.desc="Bum, kafadan!" + +Basic_Training_-_Rope.name=Temel Halat Eğitimi +Basic_Training_-_Rope.desc="Ordan çık ve sallan!" + +User_Mission_-_Dangerous_Ducklings.name=Görev: Tehlikeli Ördek Yavruları +User_Mission_-_Dangerous_Ducklings.desc="Peki acemi! Şimdi Temel Eğitimde öğrendiklerini uygulamanın zamanı!" + +User_Mission_-_Diver.name=Görev: Dalıcı +User_Mission_-_Diver.desc="Bu 'iki yönlü saldırı' göründüğünden daha zor..." + +User_Mission_-_Teamwork.name=Görev: Takım Çalışması +User_Mission_-_Teamwork.desc="Bazen, aşk acıtır." + +User_Mission_-_Spooky_Tree.name=Görev: Korkak Ağaç +User_Mission_-_Spooky_Tree.desc="Burada çok fazla kasa var. Eminim bu kuş aç değildir." + +User_Mission_-_Bamboo_Thicket.name=Görev: Bambu Ormanı +User_Mission_-_Bamboo_Thicket.desc="Ölüm yukardan gelir." + +User_Mission_-_That_Sinking_Feeling.name=Görev: Batıyormuş Hissi +User_Mission_-_That_Sinking_Feeling.desc="Su hızlıca yükseliyor ve zaman kısıtlı. Çoğu denedi ve kaybetti. Hepsini kurtarabilecek misin?" + +User_Mission_-_Newton_and_the_Hammock.name=Görev: Newton ve Hamak +User_Mission_-_Newton_and_the_Hammock.desc="Kirpişleri unutma: Bir vücudun hızı harici bir kuvvetle itilmedikçe sabit kalır!" + +User_Mission_-_The_Great_Escape.name=Görev: Büyük Kaçış +User_Mission_-_The_Great_Escape.desc="Beni hapsedebileceğini mi sanıyorsun!?" + +User_Mission_-_Rope_Knock_Challenge.name=Mücadele: Halat Vuruşu +User_Mission_-_Rope_Knock_Challenge.desc="Arkana bak!" + +User_Mission_-_RCPlane_Challenge.name=Mücadele: RC Uçağı +User_Mission_-_RCPlane_Challenge.desc="Çok emin görünüyorsun değil mi, uçan çocuk?" + +portal.name= Görev: Portal eğitim görevi +portal.desc="Hızlı ve uzak yerlere hareket için portalı kullan, öldürmek için kullan, dikkatli kullan!" diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/Locale/tr.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tr.lua Sat Apr 20 02:20:15 2013 +0200 @@ -0,0 +1,989 @@ +locale = { +-- [":("] = "", +-- ["!!!"] = "", +-- ["..."] = "", +-- ["011101000"] = "", -- A_Classic_Fairytale:dragon +-- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united + ["30 minutes later..."] = "30 dakika sonra...", -- A_Classic_Fairytale:shadow +-- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy + ["Accuracy Bonus!"] = "Güzel Nişan Bonusu!", +-- ["Ace"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge +-- ["Achievement Unlocked"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_That_Sinking_Feeling, Tumbler +-- ["A Classic Fairytale"] = "", -- A_Classic_Fairytale:first_blood +-- ["???"] = "", -- A_Classic_Fairytale:backstab +-- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow +-- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["Africa"] = "", -- Continental_supplies +-- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood +-- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow +-- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge + ["a Hedgewars mini-game"] = "Hedgewars mini oyunu", -- Space_Invasion, The_Specialists + ["Aiming Practice"] = "Atış Eğitimi", --Bazooka, Shotgun, SniperRifle +-- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood +-- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow +-- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey +-- ["All walls touched!"] = "", -- WxW + ["Ammo Depleted!"] = "Munition erschöpft!", + ["ammo extended!"] = "Munition aufgestockt!", + ["Ammo is reset at the end of your turn."] = "Munition wird am Ende des Spielzuges zurückgesetzt.", + ["Ammo Maniac!"] = "Munitionsverrückter!", + ["Ammo"] = "Mermi", +-- ["And how am I alive?!"] = "", -- A_Classic_Fairytale:enemy +-- ["And so happenned that Leaks A Lot failed to complete the challenge! He landed, pressured by shame..."] = "", -- A_Classic_Fairytale:first_blood +-- ["And so it began..."] = "", -- A_Classic_Fairytale:first_blood +-- ["...and so the cyborgs took over the world..."] = "", -- A_Classic_Fairytale:shadow +-- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey +-- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon +-- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey +-- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Antarctica"] = "", -- Continental_supplies +-- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow +-- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab +-- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy +-- ["Artur Detour"] = "", -- A_Classic_Fairytale:queen +-- ["As a reward for your performance, here's some new technology!"] = "", -- A_Classic_Fairytale:dragon +-- ["a shoppa minigame"] = "", -- WxW +-- ["Asia"] = "", -- Continental_supplies +-- ["Assault Team"] = "", -- A_Classic_Fairytale:backstab +-- ["As the ammo is sparse, you might want to reuse ropes while mid-air.|"] = "", -- A_Classic_Fairytale:dragon +-- ["As the challenge was completed, Leaks A Lot set foot on the ground..."] = "", -- A_Classic_Fairytale:first_blood +-- ["As you can see, there is no way to get on the other side!"] = "", -- A_Classic_Fairytale:dragon +-- ["Attack From Rope"] = "", -- WxW +-- ["Australia"] = "", -- Continental_supplies + ["Available points remaining: "] = "Verfügbare Punkte verbleibend:", +-- ["Back Breaker"] = "", -- A_Classic_Fairytale:backstab +-- ["Back in the village, after telling the villagers about the threat..."] = "", -- A_Classic_Fairytale:united +-- ["[Backspace]"] = "", +-- ["Backstab"] = "", -- A_Classic_Fairytale:backstab +-- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Bamboo Thicket"] = "", + ["Barrel Eater!"] = "Fassfresser!", + ["Barrel Launcher"] = "Fasswerfer", +-- ["Baseballbat"] = "", -- Continental_supplies + ["Bat balls at your enemies and|push them into the sea!"] = "Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!", + ["Bat your opponents through the|baskets and out of the map!"] = "Schlage deine Widersacher durch|die Körbe und aus der Karte hinaus!", + ["Bazooka Training"] = "Bazooka-Training", +-- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen + ["Best laps per team: "] = "Beste Rundenzeiten pro Team: ", + ["Best Team Times: "] = "Beste Team-Zeiten: ", +-- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Blender"] = "", -- A_Classic_Fairytale:family +-- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab +-- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow +-- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow + ["Bloody Rookies"] = "Blutige Anfänger", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab +-- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["Boom!"] = "Bumm!", + ["BOOM!"] = "KABUMM!", + ["Boss defeated!"] = "Boss wurde besiegt!", + ["Boss Slayer!"] = "Boss-Töter!", +-- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey +-- ["Brainiac"] = "", -- A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:shadow +-- ["Brainila"] = "", -- A_Classic_Fairytale:united +-- ["Brain Stu"] = "", -- A_Classic_Fairytale:united +-- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab +-- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil +-- ["Brutus"] = "", -- A_Classic_Fairytale:backstab + ["Build a track and race."] = "Konstruiere eine Strecke und mach ein Wettrennen.", +-- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon +-- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon +-- ["But that's impossible!"] = "", -- A_Classic_Fairytale:backstab +-- ["But the ones alive are stronger in their heart!"] = "", -- A_Classic_Fairytale:enemy +-- ["But...we died!"] = "", -- A_Classic_Fairytale:backstab +-- ["But where can we go?"] = "", -- A_Classic_Fairytale:united +-- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab +-- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy +-- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family +-- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood +-- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey +-- ["Cannibals?! You're the cannibals!"] = "", -- A_Classic_Fairytale:enemy + ["CAPTURE THE FLAG"] = "EROBERE DIE FAHNE", + ["Careless"] = "Achtlos", +-- ["Carol"] = "", -- A_Classic_Fairytale:family +-- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge + ["Change Weapon"] = "Waffenwechsel", +-- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow + ["Clumsy"] = "Hoppla", +-- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb +-- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb + ["Codename: Teamwork"] = "Code-Name: Teamwork", +-- ["Collateral Damage"] = "", -- A_Classic_Fairytale:journey +-- ["Collateral Damage II"] = "", -- A_Classic_Fairytale:journey +-- ["Collect all the crates, but remember, our time in this life is limited!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Collect or destroy all the health crates."] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Collect the crate on the right.|Hint: Select the rope, [Up] or [Down] to aim, [Space] to fire, directional keys to move.|Ropes can be fired again in the air!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Collect the crates within the time limit!|If you fail, you'll have to try again."] = "", -- A_Classic_Fairytale:first_blood +-- ["Come closer, so that your training may continue!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Compete to use as few planes as possible!"] = "", -- User_Mission_-_RCPlane_Challenge + ["Complete the track as fast as you can!"] = "Durchlaufe die Strecke so schnell du kannst!", +-- ["COMPLETION TIME"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Configuration accepted."] = "", -- WxW +-- ["Congratulations"] = "", -- Basic_Training_-_Rope + ["Congratulations!"] = "Gratulation!", +-- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb +-- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope + ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.", --Bazooka, Shotgun, SniperRifle +-- ["Continental supplies"] = "", -- Continental_supplies + ["Control pillars to score points."] = "Kontrolliere die Säulen um Punkte zu erhalten.", +-- ["Corporationals"] = "", -- A_Classic_Fairytale:queen +-- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow +-- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge + ["Cybernetic Empire"] = "Kybernetisches Imperium", +-- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy +-- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab + ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "VERDAMMT, REKRUT! RUNTER VON MEINEM KOPF!", + ["DAMMIT, ROOKIE!"] = "VERDAMMT, REKRUT!", +-- ["Dangerous Ducklings"] = "", + ["Deadweight"] = "Gravitus", +-- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab +-- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united +-- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow +-- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow + ["Demolition is fun!"] = "Zerstörung macht Spaß!", +-- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow + ["Depleted Kamikaze!"] = "Munitionsloses Kamikaze!", +-- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood + ["Destroy invaders to score points."] = "Zerstöre die Angreifer um Punkte zu erhalten.", +-- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood +-- ["Destroy the targets!|Hint: [Up], [Down] to aim, [Space] to shoot"] = "", -- A_Classic_Fairytale:first_blood +-- ["Did anyone follow you?"] = "", -- A_Classic_Fairytale:united +-- ["Did you see him coming?"] = "", -- A_Classic_Fairytale:shadow +-- ["Did you warn the village?"] = "", -- A_Classic_Fairytale:shadow +-- ["Die, die, die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Disguise as a Rockhopper Penguin: [Swap place with a random enemy hog in the circle]"] = "", -- Continental_supplies +-- ["Dist: "] = "", -- Space_Invasion +-- ["Do not laugh, inexperienced one, for he speaks the truth!"] = "", -- A_Classic_Fairytale:backstab +-- ["Do not let his words fool you, young one! He will stab you in the back as soon as you turn away!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Do the deed"] = "", -- A_Classic_Fairytale:first_blood +-- ["Double Kill!"] = "", +-- ["DOUBLE KILL"] = "", -- Mutant +-- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy +-- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy +-- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drone Hunter!"] = "", +-- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Absäufer", +-- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family +-- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey +-- ["Dude, that's so cool!"] = "", -- A_Classic_Fairytale:backstab +-- ["Dude, we really need a new shaman..."] = "", -- A_Classic_Fairytale:shadow +-- ["Dude, what's this place?!"] = "", -- A_Classic_Fairytale:dragon +-- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab +-- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab +-- ["Duration"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies + ["Each turn you get 1-3 random weapons"] = "Du bekommst jede Runde 1-3 zufällig gewählte Waffen", + ["Each turn you get one random weapon"] = "Du bekommst jede Runde eine zufällig gewählte Waffe.", +-- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab +-- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil +-- ["Elderbot"] = "", -- A_Classic_Fairytale:family +-- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape + ["Eliminate all enemies"] = "Vernichte alle Gegner", + ["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Eliminiere alle Ziele bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.", --Bazooka, Shotgun, SniperRifle +-- ["Eliminate enemy hogs and take their weapons."] = "", -- Highlander + ["Eliminate Poison before the time runs out"] = "Neutralisiere das Gift bevor die Zeit abgelaufen ist", + ["Eliminate the Blue Team"] = "Lösche das Blaue Team aus", + ["Eliminate the enemy before the time runs out"] = "Vernichte den Feind bevor die Zeit abgelaufen ist", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock + ["Eliminate the enemy hogs to win."] = "Vernichte alle gegnerischen Igel um zu gewinnen", + ["Eliminate the enemy specialists."] = "Vernichte die gegnerischen Spezialisten", + ["- Eliminate Unit 3378 |- Feeble Resistance must survive"] = "- Vernichte Einheit 3378 | Kraftloser Widerstand muss überleben", +-- ["Elmo"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["Energetic Engineer"] = "", + ["Enjoy the swim..."] = "Viel Spaß beim Schwimmen...", +-- ["[Enter]"] = "", +-- ["Europe"] = "", -- Continental_supplies +-- [" ever done to you?!"] = "", -- A_Classic_Fairytale:backstab +-- ["Everyone knows this."] = "", -- A_Classic_Fairytale:enemy +-- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon +-- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy +-- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey +-- ["INSANITY"] = "", -- Mutant +-- ["Family Reunion"] = "", -- A_Classic_Fairytale:family + ["Fastest lap: "] = "Schnellste Runde: ", + ["Feeble Resistance"] = "Kraftloser Widerstand", +-- ["Fell From Grace"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["Fell From Heaven"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen +-- ["Fell From Heaven is the best! Fell From Heaven is the greatest!"] = "", -- A_Classic_Fairytale:family +-- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow +-- ["Fierce Competition!"] = "", -- Space_Invasion +-- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon +-- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood +-- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Feuer", +-- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united +-- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood +-- ["FIRST BLOOD MUTATES"] = "", -- Mutant +-- ["First Steps"] = "", -- A_Classic_Fairytale:first_blood + ["Flag captured!"] = "Fahne erobert!", + ["Flag respawned!"] = "Fahne wieder erschienen!", + ["Flag returned!"] = "Fahne zurückgebracht!", + ["Flags, and their home base will be placed where each team ends their first turn."] = "Fahnen und deren Heimatstandort werden dort plaziert wo jedes Team deren ersten Zug beendet.", +-- ["Flamer"] = "", +-- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab +-- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies +-- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["For improved features/stability, play 0.9.18+"] = "", -- WxW +-- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Friendly Fire!"] = "", + ["fuel extended!"] = "Treibstoff aus!", + ["GAME BEGUN!!!"] = "SPIEL GESTARTET!!!", +-- ["Game Modifiers: "] = "", -- The_Specialists + ["GAME OVER!"] = "SPIEL ZU ENDE!", + ["Game Started!"] = "Spiel Gestartet!]", +-- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy +-- ["GasBomb"] = "", -- Continental_supplies +-- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey + ["Get on over there and take him out!"] = "Mach, dass du hinüber kommst und schalte ihn aus!", +-- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood +-- ["Get out of there!"] = "", -- User_Mission_-_The_Great_Escape +-- ["Get that crate!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Get the crate on the other side of the island!|"] = "", -- A_Classic_Fairytale:journey +-- ["Get to the target using your rope! |Controls: Left & Right to swing the rope - Up & Down to Contract and Expand!"] = "", -- Basic_Training_-_Rope +-- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family +-- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Glark"] = "", -- A_Classic_Fairytale:shadow + ["Goal"] = "Ziel", + ["GO! GO! GO!"] = "Bewegung, Bewegung, Bewegung!", + ["Good birdy......"] = "Braver Vogel......", +-- ["Good Dude"] = "", -- User_Mission_-_The_Great_Escape +-- ["Good idea, they'll never find us there!"] = "", -- A_Classic_Fairytale:united +-- ["Good luck...or else!"] = "", -- A_Classic_Fairytale:journey + ["Good luck out there!"] = "Viel Glück da draußen!", + ["Good so far!"] = "Gut soweit!", + ["Good to go!"] = "Startklar!", +-- ["Go on top of the flower"] = "", -- A_Classic_Fairytale:first_blood +-- ["Go, quick!"] = "", -- A_Classic_Fairytale:backstab +-- ["Gorkij"] = "", -- A_Classic_Fairytale:journey +-- ["Go surf!"] = "", -- WxW + ["GOTCHA!"] = "ERWISCHT!", + ["Grab Mines/Explosives"] = "Sammle Minen/Fässer", +-- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow +-- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope +-- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow +-- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies +-- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon +-- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade Training"] = "", -- Basic_Training_-_Grenade +-- ["Grenadiers"] = "", -- Basic_Training_-_Grenade +-- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab +-- ["HAHA!"] = "", -- A_Classic_Fairytale:enemy +-- ["Haha!"] = "", -- A_Classic_Fairytale:united +-- ["Hahahaha!"] = "", + ["Haha, now THAT would be something!"] = "Haha, na DAS wär ja was!", +-- ["Hannibal"] = "", -- A_Classic_Fairytale:epil + ["Hapless Hogs"] = "Glücklose Igel", + [" Hapless Hogs left!"] = " Glücklose Igel verbleibend!", + +-- [" HAS MUTATED"] = "", -- Mutant +-- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen +-- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow +-- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy + ["Health crates extend your time."] = "Medipacks verlängern deine Zeit.", +-- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united + ["Heavy"] = "Schwierig", +-- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy +-- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basketball", + ["Hedgewars-Knockball"] = "Hedgewars-Knockball", +-- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab + ["Heh, it's not that bad."] = "Hehe, so schlimm ist es nicht.", +-- ["Hello again, "] = "", -- A_Classic_Fairytale:family +-- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey +-- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey +-- ["Help me, please!"] = "", -- A_Classic_Fairytale:journey +-- ["He moves like an eagle in the sky."] = "", -- A_Classic_Fairytale:first_blood +-- ["He must be in the village already."] = "", -- A_Classic_Fairytale:journey +-- ["Here, let me help you!"] = "", -- A_Classic_Fairytale:backstab +-- ["Here, let me help you save her!"] = "", -- A_Classic_Fairytale:family +-- ["Here...pick your weapon!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Hero Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["He's so brave..."] = "", -- A_Classic_Fairytale:first_blood +-- ["He won't be selling us out anymore!"] = "", -- A_Classic_Fairytale:backstab +-- ["Hey, guys!"] = "", -- A_Classic_Fairytale:backstab +-- ["Hey guys!"] = "", -- A_Classic_Fairytale:united +-- ["Hey! This is cheating!"] = "", -- A_Classic_Fairytale:journey +-- ["HIGHLANDER"] = "", -- Highlander +-- ["Hightime"] = "", -- A_Classic_Fairytale:first_blood +-- ["Hint: Double Jump - Press [Backspace] twice"] = "", -- A_Classic_Fairytale:first_blood +-- ["Hint: Select the BlowTorch, aim and press [Fire]. Press [Fire] again to stop.|Don't blow up the crate."] = "", -- A_Classic_Fairytale:journey +-- ["Hint: Select the LowGravity and press [Fire]."] = "", -- A_Classic_Fairytale:journey +-- ["Hint: you might want to stay out of sight and take all the crates...|"] = "", -- A_Classic_Fairytale:journey +-- ["His arms are so strong!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Hit Combo!"] = "", +-- ["Hmmm..."] = "", +-- ["Hmmm...actually...I didn't either."] = "", -- A_Classic_Fairytale:enemy +-- ["Hmmm, I'll have to find some way of moving him off this anti-portal surface..."] = "", -- portal +-- ["Hmmm...it's a draw. How unfortunate!"] = "", -- A_Classic_Fairytale:enemy +-- ["Hmmm...perhaps a little more time will help."] = "", -- A_Classic_Fairytale:first_blood +-- ["Hogminator"] = "", -- A_Classic_Fairytale:family +-- ["Hogs in sight!"] = "", -- Continental_supplies +-- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy + ["Hooray!"] = "Hurra!", +-- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family +-- ["How can I ever repay you for saving my life?"] = "", -- A_Classic_Fairytale:journey +-- ["How come in a village full of warriors, it's up to me to save it?"] = "", -- A_Classic_Fairytale:dragon +-- ["How difficult would you like it to be?"] = "", -- A_Classic_Fairytale:first_blood +-- ["HOW DO THEY KNOW WHERE WE ARE???"] = "", -- A_Classic_Fairytale:united +-- ["However, if you fail to do so, she dies a most violent death, just like your friend! Muahahaha!"] = "", -- A_Classic_Fairytale:journey +-- ["However, if you fail to do so, she dies a most violent death! Muahahaha!"] = "", -- A_Classic_Fairytale:journey +-- ["However, my mates don't agree with me on letting you go..."] = "", -- A_Classic_Fairytale:dragon +-- [" HP"] = "", -- Mutant + ["Hunter"] = "Jäger", --Bazooka, Shotgun, SniperRifle +-- ["I believe there's more of them."] = "", -- A_Classic_Fairytale:backstab +-- ["I can see you have been training diligently."] = "", -- A_Classic_Fairytale:first_blood +-- ["I can't believe it worked!"] = "", -- A_Classic_Fairytale:shadow +-- ["I can't believe this!"] = "", -- A_Classic_Fairytale:enemy +-- ["I can't believe what I'm hearing!"] = "", -- A_Classic_Fairytale:backstab +-- ["I can't wait any more, I have to save myself!"] = "", -- A_Classic_Fairytale:shadow +-- ["I could just teleport myself there..."] = "", -- A_Classic_Fairytale:family +-- ["I'd better get going myself."] = "", -- A_Classic_Fairytale:journey +-- ["I didn't until about a month ago."] = "", -- A_Classic_Fairytale:enemy +-- ["I don't know how you did that.. But good work! |The next one should be easy as cake for you!"] = "", -- Basic_Training_-_Rope +-- ["I feel something...a place! They will arrive near the circles!"] = "", -- A_Classic_Fairytale:backstab +-- ["If only I had a way..."] = "", -- A_Classic_Fairytale:backstab +-- ["If only I were given a chance to explain my being here..."] = "", -- A_Classic_Fairytale:first_blood +-- ["I forgot that she's the daughter of the chief, too..."] = "", -- A_Classic_Fairytale:backstab +-- ["If they try coming here, they can have a taste of my delicious knuckles!"] = "", -- A_Classic_Fairytale:united +-- ["If you agree to provide the information we need, you will be spared!"] = "", -- A_Classic_Fairytale:shadow +-- ["If you can get that crate fast enough, your beloved \"princess\" may go free."] = "", -- A_Classic_Fairytale:journey +-- ["If you decide to help us, though, we will no longer need to find a new governor for the island."] = "", -- A_Classic_Fairytale:shadow +-- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey +-- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow +-- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow + +-- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon +-- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow +-- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow +-- ["I have to follow that alien."] = "", -- A_Classic_Fairytale:backstab +-- ["I have to get back to the village!"] = "", -- A_Classic_Fairytale:shadow +-- ["I hope you are prepared for a small challenge, young one."] = "", -- A_Classic_Fairytale:first_blood +-- ["I just don't want to sink to your level."] = "", -- A_Classic_Fairytale:backstab +-- ["I just found out that they have captured your princess!"] = "", -- A_Classic_Fairytale:family +-- ["I just wonder where Ramon and Spiky disappeared..."] = "", -- A_Classic_Fairytale:journey +-- ["I'll hold them off while you return to the village!"] = "", -- A_Classic_Fairytale:shadow +-- ["Imagine those targets are the wolves that killed your parents! Take your anger out on them!"] = "", -- A_Classic_Fairytale:first_blood +-- ["I'm...alive? How? Why?"] = "", -- A_Classic_Fairytale:backstab +-- ["I'm a ninja."] = "", -- A_Classic_Fairytale:dragon +-- ["I marked the place of their arrival. You're welcome!"] = "", -- A_Classic_Fairytale:backstab +-- ["I'm certain that this is a misunderstanding, fellow hedgehogs!"] = "", -- A_Classic_Fairytale:first_blood +-- ["I mean, none of you ceased to live."] = "", -- A_Classic_Fairytale:enemy +-- ["I'm getting old for this!"] = "", -- A_Classic_Fairytale:family +-- ["I'm getting thirsty..."] = "", -- A_Classic_Fairytale:family +-- ["I'm here to help you rescue her."] = "", -- A_Classic_Fairytale:family +-- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united +-- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood +-- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow +-- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab +-- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey +-- ["I need to move the tribe!"] = "", -- A_Classic_Fairytale:united +-- ["I need to prevent their arrival!"] = "", -- A_Classic_Fairytale:backstab +-- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab +-- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab +-- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon + ["Instructor"] = "Ausbilder", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings +-- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy +-- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab +-- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow + ["invaders destroyed"] = "Angreifer zerstört", +-- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow +-- ["I see..."] = "", -- A_Classic_Fairytale:shadow +-- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood +-- ["I see you would like his punishment to be more...personal..."] = "", -- A_Classic_Fairytale:first_blood +-- ["I sense another wave of cannibals heading my way!"] = "", -- A_Classic_Fairytale:backstab +-- ["I sense another wave of cannibals heading our way!"] = "", -- A_Classic_Fairytale:backstab +-- ["I shouldn't have drunk that last pint."] = "", -- A_Classic_Fairytale:dragon +-- ["Is this place in my head?"] = "", -- A_Classic_Fairytale:dragon +-- ["It doesn't matter. I won't let that alien hurt my daughter!"] = "", -- A_Classic_Fairytale:dragon +-- ["I think we are safe here."] = "", -- A_Classic_Fairytale:backstab +-- ["I thought their shaman died when he tried our medicine!"] = "", -- A_Classic_Fairytale:shadow +-- ["It is called 'Hogs of Steel'."] = "", -- A_Classic_Fairytale:enemy +-- ["It is time to practice your fighting skills."] = "", -- A_Classic_Fairytale:first_blood +-- ["It must be a childhood trauma..."] = "", -- A_Classic_Fairytale:family +-- ["It must be the aliens!"] = "", -- A_Classic_Fairytale:backstab +-- ["It must be the aliens' deed."] = "", -- A_Classic_Fairytale:backstab +-- ["It must be the cyborgs again!"] = "", -- A_Classic_Fairytale:enemy +-- ["I told you, I just found them."] = "", -- A_Classic_Fairytale:backstab + ["It's a good thing SUDDEN DEATH is 99 turns away..."] = "Gut, dass SUDDEN DEATH noch 99 Runden entfernt ist...", +-- ["It's always up to women to clear up the mess men created!"] = "", -- A_Classic_Fairytale:dragon +-- ["It's a shame, I forgot how to do that!"] = "", -- A_Classic_Fairytale:family +-- ["It's impossible to communicate with the spirits without a shaman."] = "", -- A_Classic_Fairytale:shadow +-- ["It's over..."] = "", -- A_Classic_Fairytale:shadow +-- ["It's time you learned that your actions have consequences!"] = "", -- A_Classic_Fairytale:journey +-- ["It's worth more than wood!"] = "", -- A_Classic_Fairytale:enemy +-- ["It wants our brains!"] = "", -- A_Classic_Fairytale:shadow +-- ["It was not a dream, unwise one!"] = "", -- A_Classic_Fairytale:backstab +-- ["I've seen this before. They just appear out of thin air."] = "", -- A_Classic_Fairytale:united +-- ["I want to play a game..."] = "", -- A_Classic_Fairytale:journey +-- ["I want to see how it handles this!"] = "", -- A_Classic_Fairytale:backstab +-- ["I wish to help you, "] = "", -- A_Classic_Fairytale:dragon +-- ["I wonder where Dense Cloud is..."] = "", -- A_Classic_Fairytale:journey, A_Classic_Fairytale:shadow +-- ["I wonder why I'm so angry all the time..."] = "", -- A_Classic_Fairytale:family +-- ["I won't let you kill her!"] = "", -- A_Classic_Fairytale:journey +-- ["Jack"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["Jeremiah"] = "", -- A_Classic_Fairytale:dragon +-- ["John"] = "", -- A_Classic_Fairytale:journey +-- ["Judas"] = "", -- A_Classic_Fairytale:backstab + ["Jumping is disabled"] = "Sprünge sind deaktiviert!", +-- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy +-- ["Just on a walk."] = "", -- A_Classic_Fairytale:united +-- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family + ["Kamikaze Expert!"] = "Kamikazeexperte!", + ["Keep it up!"] = "Weiter so!", +-- ["Kerguelen"] = "", -- Continental_supplies + ["Killing spree!"] = "Blutrausch!", +-- ["KILL IT!"] = "", -- A_Classic_Fairytale:first_blood +-- ["KILLS"] = "", +-- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon +-- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab + ["Last Target!"] = "Letzte Zielscheibe!", +-- ["Leader"] = "", -- A_Classic_Fairytale:enemy +-- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen +-- ["Leaks A Lot"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Leaks A Lot, depressed for killing his loved one, failed to save the village..."] = "", -- A_Classic_Fairytale:journey +-- ["Leaks A Lot gave his life for his tribe! He should have survived!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey +-- ["Led Heart"] = "", -- A_Classic_Fairytale:queen +-- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["[Left Shift]"] = "", +-- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies +-- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey +-- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey +-- ["Let's head back to the village!"] = "", -- A_Classic_Fairytale:shadow +-- ["Let's see what your comrade does now!"] = "", -- A_Classic_Fairytale:journey +-- ["Let's show those cannibals what we're made of!"] = "", -- A_Classic_Fairytale:backstab +-- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab +-- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab +-- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united + ["Listen up, maggot!!"] = "Aufgepasst, du Made!!", +-- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow +-- ["Lively Lifeguard"] = "", +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies +-- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab +-- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab +-- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy +-- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united +-- ["LUDICROUS KILL"] = "", -- Mutant +-- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab +-- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies +-- ["MEGA KILL"] = "", -- Mutant +-- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab +-- ["Mindy"] = "", -- A_Classic_Fairytale:united + ["Mine Deployer"] = "Minenleger", + ["Mine Eater!"] = "Minenfresser!", + ["|- Mines Time:"] = "| - Minenzündzeit: ", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["MISSION FAILED"] = "MISSION GESCHEITERT", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["MISSION SUCCESSFUL"] = "MISSION ERFOLGREICH", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["MISSION SUCCESS"] = "MISSIONSERFOLG", +-- ["Molotov"] = "", -- Continental_supplies +-- ["MONSTER KILL"] = "", -- Mutant +-- ["More Natives"] = "", -- A_Classic_Fairytale:epil + ["Movement: [Up], [Down], [Left], [Right]"] = "Bewegung: [Hoch], [Runter], [Links], [Rechts]", +-- ["Multi-shot!"] = "", + ["Munition!"] = "Munition erschöpft!", +-- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow +-- ["-------"] = "", -- Mutant +-- ["Nade Boy"] = "", -- Basic_Training_-_Grenade +-- ["Name"] = "", -- A_Classic_Fairytale:queen + ["Nameless Heroes"] = "Namenlose Helden", +-- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies +-- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united + ["New Barrels Per Turn"] = "Neue Fässer jede Runde", + ["NEW CLAN RECORD: "] = "NEUER KLAN-REKORD", + ["NEW fastest lap: "] = "NEUE schnellste Runde: ", + ["New Mines Per Turn"] = "Neue Minen jede Runde", + ["NEW RACE RECORD: "] = "NEUER RENNREKORD: ", +-- ["Newton's Hammock"] = "", +-- ["Nicely done, meatbags!"] = "", -- A_Classic_Fairytale:enemy +-- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon +-- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy +-- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow +-- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey +-- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey +-- ["NomNom"] = "", -- A_Classic_Fairytale:united +-- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow +-- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey +-- ["NORMAL"] = "", -- Continental_supplies +-- ["North America"] = "", -- Continental_supplies +-- ["Not all hogs are born equal."] = "", -- Highlander + ["NOT ENOUGH WAYPOINTS"] = "NICHT GENUG WEGPUNKTE", +-- ["Not now, Fiery Water!"] = "", -- A_Classic_Fairytale:backstab + ["Not So Friendly Match"] = "Kein-so-Freundschaftsspiel", -- Basketball, Knockball +-- ["Not you again! My head still hurts from last time!"] = "", -- A_Classic_Fairytale:shadow +-- ["No, we made sure of that!"] = "", -- A_Classic_Fairytale:united +-- ["Now find the next target! |Tip: Normally you lose health by falling down, so be careful!"] = "", -- Basic_Training_-_Rope +-- ["No! What have I done?! What have YOU done?!"] = "", -- A_Classic_Fairytale:journey +-- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow +-- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon +-- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow +-- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon +-- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family +-- ["OH, COME ON!"] = "", -- A_Classic_Fairytale:journey +-- ["Oh, my!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Oh, my! This is even more entertaining than I've expected!"] = "", -- A_Classic_Fairytale:backstab + ["Oh no! Just try again!"] = "Oh nein! Versuch's nochmal!", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Oh no, not "] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united + ["Oh no! Time's up! Just try again."] = "Oh nein! Die Zeit ist um! Versuche es nochmal.", --Bazooka, Shotgun, SniperRifle +-- ["Oh no! You failed! Just try again."] = "", -- Basic_Training_-_Cluster_Bomb +-- ["Oh, silly me! I forgot that I'm the shaman."] = "", -- A_Classic_Fairytale:backstab +-- ["Olive"] = "", -- A_Classic_Fairytale:united +-- ["Omnivore"] = "", -- A_Classic_Fairytale:first_blood +-- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood +-- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant +-- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united +-- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Operation Diver"] = "", + ["Opposing Team: "] = "Gegnerisches Team: ", +-- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy +-- ["Parachute"] = "", -- Continental_supplies + ["Pathetic Hog #%d"] = "Erbärmlicher Igel #%d", + ["Pathetic Resistance"] = "Erbärmlicher Widerstand", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood + ["Per-Hog Ammo"] = "Munition pro Igel", +-- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies + +-- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow +-- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Pings left:"] = "", -- Space_Invasion + + ["Place more waypoints using the 'Air Attack' weapon."] = "Platziere mehr Wegpunkte durch Verwenden der 'Luftangriff'-Waffe", +-- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Play with me!"] = "", -- A_Classic_Fairytale:shadow +-- ["Please place the way-point further from the waterline."] = "", -- Racer +-- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer +-- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow +-- ["Point Blank Combo!"] = "", -- Space_Invasion + ["points"] = "Punkte", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle + ["Poison"] = "Gift", +-- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon +-- ["Portal mission"] = "", -- portal + ["Power Remaining"] = "Verbleibende Energie", + ["Prepare yourself"] = "Mach dich bereit", +-- ["Press [Enter] to accept this configuration."] = "", -- WxW +-- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood +-- ["Press [Precise] to skip intro"] = "", +-- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb +-- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow + ["PUNKTESTAND"] = "", + ["Race complexity limit reached."] = "Rennkomplexitätslimit erreicht.", +-- ["RACER"] = "", +-- ["Rachel"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["Radar Ping"] = "", -- Space_Invasion +-- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab +-- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab +-- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope +-- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow + [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Bringe die gegnerische Flagge zu deiner Heimatbasis um zu punkten. | - Das Team das zuerst 3 Flaggen erobert gewinnt. | - Du kannst nur punkten wenn deine eigene Flagge in deiner Basis ist | - Igel lassen die Flagge fallen wenn sie sterben oder ertrinken | - Fallen gelassene Flaggen können zurückgebracht oder wieder gestohlen werden | - Igel tauchen nach ihrem Tod wieder auf", +-- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow +-- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope Training"] = "", -- Basic_Training_-_Rope +-- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow +-- ["Round Limit:"] = "", + ["Round Limit"] = "Rundenbegrenzung", +-- ["Rounds Complete: "] = "", + ["Rounds Complete"] = "Runden Gespielt", + ["RULES OF THE GAME [Press ESC to view]"] = "SPIEL REGELN (Drücke ESC zum Anzeigen)", +-- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen +-- ["s|"] = "", +-- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united +-- ["Salvation"] = "", -- A_Classic_Fairytale:family +-- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon + ["Save as many hapless hogs as possible!"] = "Rette so viele glücklose Igel als möglich!", +-- ["Save Fell From Heaven!"] = "", -- A_Classic_Fairytale:journey +-- ["Save Leaks A Lot!|Hint: The Switch utility might be of help to you."] = "", -- A_Classic_Fairytale:shadow +-- ["Save the princess! All your hogs must survive!|Hint: Kill the cyborgs first! Use the ammo very carefully!|Hint: You might want to spare a girder for cover!"] = "", -- A_Classic_Fairytale:family +-- ["Save the princess by collecting the crate in under 12 turns!"] = "", -- A_Classic_Fairytale:journey +-- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab +-- ["Score"] = "", -- Mutant +-- ["SCORE"] = "", -- Space_Invasion +-- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies +-- ["sec"] = "", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag +-- ["Seduction"] = "", -- Continental_supplies +-- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab +-- ["See that crate farther on the right?"] = "", -- A_Classic_Fairytale:first_blood + ["See ya!"] = "Mach's gut!", +-- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon +-- ["Select continent!"] = "", -- Continental_supplies +-- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood + ["selected!"] = "ausgewählt!", +-- ["s"] = "", -- GaudyRacer, Space_Invasion +-- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey +-- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family + ["Shield boosted! +30 power"] = "Schild verstärkt! +30 Energie", + ["Shield Depleted"] = "Schild aufgebraucht!", + ["Shield is fully recharged!"] = "Schild vollständig aufgeladen!", + ["Shield Master!"] = "Schildmeister!", + ["Shield Miser!"] = "Schildgieriger", + ["Shield OFF:"] = "Schild AUS:", + ["Shield ON:"] = "Schild AN:", + ["Shield Seeker!"] = "Schildsucher!", +-- ["Shotgun"] = "", -- Continental_supplies + ["Shotgun Team"] = "Schrotflinten-Team", + ["Shotgun Training"] = "Schrotflinten-Training", + ["shots remaining."] = "Schüsse übrig", + ["Silly"] = "Doofi", + ["Sinky"] = "Blubb", +-- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy + ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s ist draußen und Team %d|erhält eine Strafe!| |Punktestand:", -- Basketball, Knockball + ["%s is out and Team %d|scored a point!| |Score:"] = "%s ist draußen und Team %d|erhält einen Punkt!| |Punktestand:", -- Basketball, Knockball +-- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy +-- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy +-- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy +-- ["Smith 0.99b"] = "", -- A_Classic_Fairytale:enemy +-- ["Smith 0.99f"] = "", -- A_Classic_Fairytale:enemy +-- ["Smith 1.0"] = "", -- A_Classic_Fairytale:enemy +-- ["Sniper Rifle"] = "", -- Continental_supplies +-- ["Sniper!"] = "", -- Space_Invasion + ["Sniper Training"] = "Scharfschützen-Training", + ["Sniperz"] = "Heckenschützen", +-- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["South America"] = "", -- Continental_supplies +-- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow +-- ["Spawn the crate, and attack!"] = "", -- WxW +-- ["Special Weapons:"] = "", -- Continental_supplies + ["Spielmodifikatoren: "] = "", +-- ["Spiky Cheese"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["Spleenlover"] = "", -- A_Classic_Fairytale:united + ["Sponge"] = "Schwamm", +-- ["Spooky Tree"] = "", +-- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion +-- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen +-- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood +-- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow +-- ["Structure"] = "", -- Continental_supplies +-- ["Super Weapons"] = "", -- WxW +-- ["Surf Before Crate"] = "", -- WxW +-- ["Surfer! +15 points!"] = "", -- Space_Invasion +-- ["Surfer!"] = "", -- WxW +-- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow +-- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood + ["Switched to "] = "Gewechselt zu ", +-- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Team %d: "] = "", + ["Team Scores"] = "Teampunktestand", -- Control, Space_Invasion +-- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Thanks!"] = "", -- A_Classic_Fairytale:family +-- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family +-- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey +-- ["Thank you, oh, thank you, my heroes!"] = "", -- A_Classic_Fairytale:journey +-- ["That is, indeed, very weird..."] = "", -- A_Classic_Fairytale:united +-- ["That makes it almost invaluable!"] = "", -- A_Classic_Fairytale:enemy +-- ["That ought to show them!"] = "", -- A_Classic_Fairytale:backstab +-- ["That's for my father!"] = "", -- A_Classic_Fairytale:backstab +-- ["That shaman sure knows what he's doing!"] = "", -- A_Classic_Fairytale:shadow +-- ["That Sinking Feeling"] = "", +-- ["That's not our problem!"] = "", -- A_Classic_Fairytale:enemy +-- ["That's typical of you!"] = "", -- A_Classic_Fairytale:family +-- ["That was just mean!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united + ["That was pointless."] = "Das war sinnlos.", +-- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab +-- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood +-- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united +-- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood +-- ["The Dilemma"] = "", -- A_Classic_Fairytale:shadow +-- ["The enemy can't move but it might be a good idea to stay out of sight!|"] = "", -- A_Classic_Fairytale:dragon + ["The enemy is hiding out on yonder ducky!"] = "Der Feind versteckt sich auf dem Entlein dort drüben!", +-- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy +-- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood +-- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow + ["The flag will respawn next round."] = "Die Fahne wird nächste Runde wieder auftauchen.", +-- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab +-- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood +-- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The guardian"] = "", -- A_Classic_Fairytale:shadow +-- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow +-- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united +-- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey +-- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood +-- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey + ["The Nameless One"] = "Der Namenlose", +-- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope +-- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow +-- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab +-- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united +-- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey +-- ["There's nothing more satisfying to us than seeing you share your beauty..."] = "", -- A_Classic_Fairytale:journey +-- ["There's nothing more satisfying to us than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey +-- ["The Rising"] = "", -- A_Classic_Fairytale:first_blood +-- ["The Savior"] = "", -- A_Classic_Fairytale:journey +-- ["These primitive people are so funny!"] = "", -- A_Classic_Fairytale:backstab +-- ["The Shadow Falls"] = "", -- A_Classic_Fairytale:shadow +-- ["The Showdown"] = "", -- A_Classic_Fairytale:shadow +-- ["The Slaughter"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:first_blood + ["THE SPECIALISTS"] = "DIE SPEZIALISTEN", +-- ["The spirits of the ancerstors are surely pleased, Leaks A Lot."] = "", -- A_Classic_Fairytale:first_blood +-- ["The Torment"] = "", -- A_Classic_Fairytale:first_blood +-- ["The Tunnel Maker"] = "", -- A_Classic_Fairytale:journey +-- ["The Ultimate Weapon"] = "", -- A_Classic_Fairytale:first_blood +-- ["The Union"] = "", -- A_Classic_Fairytale:enemy +-- ["The village, unprepared, was destroyed by the cyborgs..."] = "", -- A_Classic_Fairytale:journey +-- ["The walk of Fame"] = "", -- A_Classic_Fairytale:shadow +-- ["The wasted youth"] = "", -- A_Classic_Fairytale:first_blood +-- ["The weapon in that last crate was bestowed upon us by the ancients!"] = "", -- A_Classic_Fairytale:first_blood +-- ["The what?!"] = "", -- A_Classic_Fairytale:dragon +-- ["The wind whispers that you are ready to become familiar with tools, now..."] = "", -- A_Classic_Fairytale:first_blood +-- ["They are all waiting back in the village, haha."] = "", -- A_Classic_Fairytale:enemy +-- ["They Call Me Bullseye!"] = "", -- Space_Invasion +-- ["They have weapons we've never seen before!"] = "", -- A_Classic_Fairytale:united +-- ["They keep appearing like this. It's weird!"] = "", -- A_Classic_Fairytale:united +-- ["They killed "] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united +-- ["They must be trying to weaken us!"] = "", -- A_Classic_Fairytale:enemy +-- ["They never learn"] = "", -- A_Classic_Fairytale:journey +-- ["They told us to wear these clothes. They said that this is the newest trend."] = "", -- A_Classic_Fairytale:enemy +-- ["They've been manipulating us all this time!"] = "", -- A_Classic_Fairytale:enemy +-- ["Thighlicker"] = "", -- A_Classic_Fairytale:united +-- ["This is it! It's time to make Fell From Heaven fall for me..."] = "", -- A_Classic_Fairytale:first_blood +-- ["This island is the only place left on Earth with grass on it!"] = "", -- A_Classic_Fairytale:enemy +-- ["This is typical!"] = "", -- A_Classic_Fairytale:dragon +-- ["This must be some kind of sorcery!"] = "", -- A_Classic_Fairytale:shadow +-- ["This must be the caves!"] = "", -- A_Classic_Fairytale:backstab + ["This one's tricky."] = "Der hier ist knifflig.", + ["This rain is really something..."] = "Das nenne ich mal einen Regenschauer...", +-- ["This will be fun!"] = "", -- A_Classic_Fairytale:enemy +-- ["Those aliens are destroying the island!"] = "", -- A_Classic_Fairytale:family + ["Timed Kamikaze!"] = "Pünktliches Kamikaze!", + ["Time Extended!"] = "Zeit verlängert!", + ["Time Extension"] = "Zeitverlängerung", + ["Time Left: "] = "Verbleibende Zeit", + ["TIME: "] = "ZEIT: ", +-- ["Tip: The rope physics are different than in the real world, |use it to your advantage!"] = "", -- Basic_Training_-_Rope + ["Toggle Shield"] = "Schild ein/aus", +-- ["To help you, of course!"] = "", -- A_Classic_Fairytale:journey +-- ["To place a girder, select it, use [Left] and [Right] to select angle and length, place with [Left Click]"] = "", -- A_Classic_Fairytale:shadow +-- ["Torn Muscle"] = "", -- A_Classic_Fairytale:journey +-- [" to save the village."] = "", -- A_Classic_Fairytale:dragon +-- ["To the caves..."] = "", -- A_Classic_Fairytale:united + ["Toxic Team"] = "Giftige Gegner", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["TRACK COMPLETED"] = "STRECKENLAUF BEENDET", + ["TRACK FAILED!"] = "STRECKENLAUF GESCHEITERT", +-- ["training"] = "", -- portal +-- ["Traitors"] = "", -- A_Classic_Fairytale:epil +-- ["Tribe"] = "", -- A_Classic_Fairytale:backstab +-- ["TrophyRace"] = "", +-- ["Try to protect the chief! You won't lose if he dies, but it is advised that he survives."] = "", -- A_Classic_Fairytale:united +-- ["T_T"] = "", + ["Tumbling Time Extended!"] = "Purzelzeit verlängert!", +-- ["Turns until Sudden Death: "] = "", -- A_Classic_Fairytale:dragon +-- [" turns until Sudden Death! Better hurry!"] = "", -- A_Classic_Fairytale:dragon + ["Turn Time"] = "Zeit pro Zug", +-- ["Two little hogs cooperating, getting past obstacles..."] = "", -- A_Classic_Fairytale:journey +-- ["Uhm...I met one of them and took his weapons."] = "", -- A_Classic_Fairytale:shadow +-- ["Uhmm...ok no."] = "", -- A_Classic_Fairytale:enemy +-- ["ULTRA KILL"] = "", -- Mutant +-- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow +-- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family +-- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united + ["Unit 3378"] = "Einheit 3378", + ["Unit 835"] = "Einheit 3378", +-- ["United We Stand"] = "", -- A_Classic_Fairytale:united + ["Unit"] = "Einheit", + ["Unlimited Attacks"] = "Unbegrenzte Angriffe", +-- ["Unlucky Sods"] = "", -- User_Mission_-_Rope_Knock_Challenge + ["Unstoppable!"] = "Unaufhaltbar!", +-- ["Unsuspecting Louts"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["[Up], [Down] to aim, [Space] to shoot!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon +-- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood +-- ["User Challenge"] = "", + +-- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon +-- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge + ["Use your rope to get from start to finish as fast as you can!"] = "Nutze das Seil um von Start zu Ziel zu gelangen - so schnell du kannst!", +-- ["Vedgies"] = "", -- A_Classic_Fairytale:journey +-- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy +-- ["Victory!"] = "", -- Basic_Training_-_Rope + ["Victory for the "] = "Sieg für ", -- CTF_Blizzard, Capture_the_Flag +-- ["Violence is not the answer to your problems!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Walls Left"] = "", -- WxW +-- ["Walls Required"] = "", -- WxW +-- ["WALL TO WALL"] = "", -- WxW +-- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood + ["Waypoint placed."] = "Wegpunkt gesetzt", + ["Way-Points Remaining"] = "Wegpunkte verbleibend", +-- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow +-- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapons reset."] = "", -- Highlander + ["Weapons Reset"] = "Waffenzurücksetzung", +-- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab +-- ["We can't defeat them!"] = "", -- A_Classic_Fairytale:shadow +-- ["We can't hold them up much longer!"] = "", -- A_Classic_Fairytale:united +-- ["We can't let them take over our little island!"] = "", -- A_Classic_Fairytale:enemy +-- ["We have no time to waste..."] = "", -- A_Classic_Fairytale:journey +-- ["We have nowhere else to live!"] = "", -- A_Classic_Fairytale:enemy +-- ["We have to protect the village!"] = "", -- A_Classic_Fairytale:united +-- ["We have to unite and defeat those cylergs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Welcome, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey + ["Well done."] = "Gut gemacht.", +-- ["We'll give you a problem then!"] = "", -- A_Classic_Fairytale:enemy +-- ["We'll spare your life for now!"] = "", -- A_Classic_Fairytale:backstab +-- ["Well, that was a waste of time."] = "", -- A_Classic_Fairytale:dragon +-- ["Well, well! Isn't that the cutest thing you've ever seen?"] = "", -- A_Classic_Fairytale:journey +-- ["Well, yes. This was a cyborg television show."] = "", -- A_Classic_Fairytale:enemy +-- ["We made sure noone followed us!"] = "", -- A_Classic_Fairytale:backstab +-- ["We need to move!"] = "", -- A_Classic_Fairytale:united +-- ["We need to prevent their arrival!"] = "", -- A_Classic_Fairytale:backstab +-- ["We need to warn the village."] = "", -- A_Classic_Fairytale:shadow +-- ["We should head back to the village now."] = "", -- A_Classic_Fairytale:shadow +-- ["We were trying to save her and we got lost."] = "", -- A_Classic_Fairytale:family +-- ["We won't let you hurt her!"] = "", -- A_Classic_Fairytale:journey +-- ["What?! A cannibal? Here? There is no time to waste! Come, you are prepared."] = "", -- A_Classic_Fairytale:first_blood +-- ["What a douche!"] = "", -- A_Classic_Fairytale:enemy +-- ["What am I gonna...eat, yo?"] = "", -- A_Classic_Fairytale:family +-- ["What are you doing at a distance so great, young one?"] = "", -- A_Classic_Fairytale:first_blood +-- ["What are you doing? Let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["What a ride!"] = "", -- A_Classic_Fairytale:shadow +-- ["What a strange cave!"] = "", -- A_Classic_Fairytale:dragon +-- ["What a strange feeling!"] = "", -- A_Classic_Fairytale:backstab +-- ["What do my faulty eyes observe? A spy!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Whatever floats your boat..."] = "", -- A_Classic_Fairytale:shadow +-- [" What !! For all of this struggle i just win some ... TIME o0"] = "", -- portal +-- ["What has "] = "", -- A_Classic_Fairytale:backstab +-- ["What? Here? How did they find us?!"] = "", -- A_Classic_Fairytale:backstab +-- ["What is this place?"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy +-- ["What shall we do with the traitor?"] = "", -- A_Classic_Fairytale:backstab +-- ["WHAT?! You're the ones attacking us!"] = "", -- A_Classic_Fairytale:enemy +-- ["When?"] = "", -- A_Classic_Fairytale:enemy +-- ["When I find it..."] = "", -- A_Classic_Fairytale:dragon +-- ["Where are all these crates coming from?!"] = "", -- A_Classic_Fairytale:shadow +-- ["Where are they?!"] = "", -- A_Classic_Fairytale:backstab +-- ["Where did that alien run?"] = "", -- A_Classic_Fairytale:dragon +-- ["Where did you get the exploding apples?"] = "", -- A_Classic_Fairytale:shadow +-- ["Where did you get the exploding apples and the magic bow that shoots many arrows?"] = "", -- A_Classic_Fairytale:shadow +-- ["Where did you get the magic bow that shoots many arrows?"] = "", -- A_Classic_Fairytale:shadow +-- ["Where did you get the weapons in the forest, Dense Cloud?"] = "", -- A_Classic_Fairytale:backstab +-- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy +-- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab +-- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["? Why?"] = "", -- A_Classic_Fairytale:backstab +-- ["Why "] = "", -- A_Classic_Fairytale:backstab +-- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united +-- ["Why are you doing this?"] = "", -- A_Classic_Fairytale:journey +-- ["Why are you helping us, uhm...?"] = "", -- A_Classic_Fairytale:family +-- ["Why can't he just let her go?!"] = "", -- A_Classic_Fairytale:family +-- ["Why do men keep hurting me?"] = "", -- A_Classic_Fairytale:first_blood +-- ["Why do you not like me?"] = "", -- A_Classic_Fairytale:shadow +-- ["Why do you want to take over our island?"] = "", -- A_Classic_Fairytale:enemy +-- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab +-- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab +-- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies +-- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies +-- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies + ["Will this ever end?"] = "Bu sona erecek mi?", +-- ["WINNER IS "] = "", -- Mutant + ["WINNING TIME: "] = "KAZANMA SÜRESİ: ", +-- ["Wise Oak"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["With Dense Cloud on the land of shadows, I'm the village's only hope..."] = "", -- A_Classic_Fairytale:journey +-- ["With the rest of the tribe gone, it was up to "] = "", -- A_Classic_Fairytale:dragon +-- ["Worry not, for it is a peaceful animal! There is no reason to be afraid..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Wow, what a dream!"] = "", -- A_Classic_Fairytale:backstab +-- ["Y3K1337"] = "", -- A_Classic_Fairytale:journey, A_Classic_Fairytale:shadow +-- ["Yay, we won!"] = "", -- A_Classic_Fairytale:enemy +-- ["Y Chwiliad"] = "", -- A_Classic_Fairytale:dragon +-- ["Yeah...I think it's a 'he', lol."] = "", -- A_Classic_Fairytale:shadow +-- ["Yeah, sure! I died. Hillarious!"] = "", -- A_Classic_Fairytale:backstab +-- ["Yeah, take that!"] = "", -- A_Classic_Fairytale:dragon +-- ["Yeah? Watcha gonna do? Cry?"] = "", -- A_Classic_Fairytale:journey +-- ["Yes!"] = "", -- A_Classic_Fairytale:enemy +-- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow +-- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy +-- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united +-- ["You bear impressive skills, "] = "", -- A_Classic_Fairytale:dragon +-- ["You can't fire a portal on the blue surface"] = "", -- portal +-- ["You couldn't possibly believe that after refusing my offer I'd just let you go!"] = "", -- A_Classic_Fairytale:journey + ["You'd almost swear the water was rising!"] = "Suyun yükseldiğine yemin edebilirdin!", +-- ["You'd better watch your steps..."] = "", -- A_Classic_Fairytale:journey +-- ["You did not make it in time, try again!"] = "", -- Basic_Training_-_Rope +-- ["You have 7 turns until the next wave arrives.|Make sure the arriving cannibals are greeted appropriately!|If the hog dies, the cause is lost.|Hint: you might want to use some mines..."] = "", -- A_Classic_Fairytale:backstab +-- ["You have "] = "", -- A_Classic_Fairytale:dragon +-- ["You have been giving us out to the enemy, haven't you!"] = "", -- A_Classic_Fairytale:backstab +-- ["You have been respawned, at your last checkpoint!"] = "", -- Basic_Training_-_Rope +-- ["You have been respawned, be more carefull next time!"] = "", -- Basic_Training_-_Rope +-- ["You have chosen the perfect moment to leave."] = "", -- A_Classic_Fairytale:united +-- ["You have failed to complete your task, young one!"] = "", -- A_Classic_Fairytale:journey +-- ["You have failed to save the tribe!"] = "", -- A_Classic_Fairytale:backstab +-- ["You have finally figured it out!"] = "", -- A_Classic_Fairytale:enemy +-- ["You have kidnapped our whole tribe!"] = "", -- A_Classic_Fairytale:enemy +-- ["You have killed an innocent hedgehog!"] = "", -- A_Classic_Fairytale:backstab +-- ["You have proven yourself worthy to see our most ancient secret!"] = "", -- A_Classic_Fairytale:first_blood +-- ["You have proven yourselves worthy!"] = "", -- A_Classic_Fairytale:enemy + ["You have SCORED!!"] = "VURDUN!", +-- ["You have to destroy 12 targets in 180 seconds"] = "", -- Basic_Training_-_Cluster_Bomb +-- ["You have won the game by proving true cooperative skills!"] = "", -- A_Classic_Fairytale:enemy +-- ["You just appeared out of thin air!"] = "", -- A_Classic_Fairytale:backstab +-- ["You just committed suicide..."] = "", -- A_Classic_Fairytale:shadow +-- ["You killed my father, you monster!"] = "", -- A_Classic_Fairytale:backstab +-- ["You know...taking a stroll."] = "", -- A_Classic_Fairytale:backstab +-- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab +-- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy +-- ["You may only attack from a rope!"] = "", -- WxW +-- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy +-- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab +-- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united +-- ["You probably know what to do next..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Your deaths will be avenged, cannibals!"] = "", -- A_Classic_Fairytale:enemy +-- ["Your death will not be in vain, Dense Cloud!"] = "", -- A_Classic_Fairytale:shadow +-- ["You're...alive!? But we saw you die!"] = "", -- A_Classic_Fairytale:backstab +-- ["You're a pathetic liar!"] = "", -- A_Classic_Fairytale:backstab +-- ["You're funny!"] = "", -- A_Classic_Fairytale:journey +-- ["You're getting pretty good! |Tip: When you shorten you rope you move faster! |and when you lengthen it you move slower"] = "", -- Basic_Training_-_Rope +-- ["You're pathetic! You are not worthy of my attention..."] = "", -- A_Classic_Fairytale:shadow +-- ["You're probably wondering why I bought you back..."] = "", -- A_Classic_Fairytale:backstab +-- ["You're terrorizing the forest...We won't catch anything like this!"] = "", -- A_Classic_Fairytale:shadow +-- ["Your hogs must survive!"] = "", -- A_Classic_Fairytale:journey +-- ["Your movement skills will be evaluated now."] = "", -- A_Classic_Fairytale:first_blood + ["You saved"] = "Kurtarılan: ", +-- ["You've been assaulting us, we have been just defending ourselves!"] = "", -- A_Classic_Fairytale:enemy + ["You've failed. Try again."] = "Başaramadın. Yeniden dene!", + ["You've reached the goal!| |Time: "] = "Hedefe ulaştın!| |Süre: ", +-- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab +-- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family +-- ["Zealandia"] = "", -- Continental_supplies + ["'Zooka Team"] = "Roketatar Takımı", +-- ["Zork"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen + } diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/Locale/tr.txt --- a/share/hedgewars/Data/Locale/tr.txt Sat Apr 20 02:17:53 2013 +0200 +++ b/share/hedgewars/Data/Locale/tr.txt Sat Apr 20 02:20:15 2013 +0200 @@ -2,7 +2,7 @@ 00:00=El Bombası 00:01=Parça Tesirli Bomba -00:02=Bazuka +00:02=Roketatar 00:03=UFO 00:04=Pompalı Tüfek 00:05=Kompresör @@ -12,7 +12,7 @@ 00:09=Çöl Kartalı 00:10=Dinamit 00:11=Beyzbol Sopası -00:12=Shoryuken +00:12=Yükselen Ejderha 00:13=san 00:14=Paraşüt 00:15=Hava Saldırısı @@ -37,34 +37,501 @@ 00:34=Ölümsüzlük 00:35=Arttırılmış Zaman 00:36=Lazer Görüşü -00:37=Vampirism -00:38=Sniper Rifle -00:39=Flying Saucer -00:40=Molotov Cocktail +00:37=Vampirleşme +00:38=Keskin Nişansı Tüfeği +00:39=Uçan Daire +00:40=Molotof Kokteyli +00:41=Kuşçuk +00:42=Taşınabilir Portal Aygıtı +00:43=Piano Vuruşu +00:44=Eski Limburger +00:45=Sinüs Tabancası (beta) +00:46=Alev Püskürtücü +00:47=Yapışkan Mayın +00:48=Çekiç +00:49=Yeniden Doğuş +00:50=Matkap Vuruşu +00:51=Çamur Topu +00:52=Silah Seçilmedi +00:53=Zaman Kutusu +; 00:54=Yapı +00:54=Zemin Spreyi +00:55=Dondurucu +00:56=Satır 01:00=Savaş başlasın! 01:01=Beraberlik 01:02=%1 kazandı! -01:03=Bölüm %1% +01:03=Bölüm %%1 01:04=Duraklatıldı 01:05=Çıkılsın mı (Y/Esc)? 01:06=Ani ölüm! -01:07=%1 Remaining -01:08=Fuel +01:07=%1 Kaldı +01:08=Yakıt +01:09=Eşzamanlanıyor... +01:10=Bu yardımcıyı kullanmak sıranı bitirmeyecek! +01:11=Bu silah veya yardımcı henüz kullanılamıyor! +01:12=Ani Ölüm için son tur! +01:13=Ani Ölüme %1 tur kaldı! +01:14=Hazırlan, %1! +01:15=Az +01:16=Düşük +01:17=Normal +01:18=Yüksek +01:19=En Yüksek +01:20=%1 Sekmesi +01:21=Ses Kapalı + ; Event messages ; Hog (%1) died -02:00=%1 has kicked the bucket! -02:00=%1 has seen the light! -02:00=%1 never saw that comming! +02:00=%1 sepeti boyladı! +02:00=%1 ışığı gördü! +02:00=%1 bunun geldiğini farketmemişti! +02:00=%1 baş baş yapıyor! +02:00=%1 daha iyi bir yere gitti! +02:00=%1 yapan ile buluşuyor! +02:00=%1 daha fazla dayanamıyor! +02:00=%1 görevini yaptı! +02:00=%1 mükemmel fedakarlık yapıyor! +02:00=%1 havan sarımını ateşliyor! +02:00=%1 ağaç olup ayrılıyor! +02:00=%1 zaman aşımına uğradı! +02:00=%1 dünya barışı istiyor! +02:00=%1 sevgiyle hatırlanacak! +02:00=%1 damar genişlemesi başladı! +02:00=%1 arkasında gözü yaşlı eş ve çocuk bırakıyor +02:00=%1 son roketatarını fırlattı +02:00=%1 son el bombasını fırlattı +02:00=%1 son pastasını pişirdi +02:00=%1 son halatında sallandı +02:00=%1 son hava saldırısını çağırdı +02:00=%1 son tüfeğini ateşledi +02:00=%1 son karpuzunu attı +02:00=%1 son çizimini yaptı +02:00=%1 bir atışı çok kez aldı +02:00=%1 gerçekten bir sağlık sandığı kullanabilirdi +02:00=%1 daha iyi bir oyun oynamak için gitti +02:00=%1 hayata kaçtı +02:00=%1 başarısız oldu +02:00=Zavallı %1... +02:00=%1 wormux'u tercih ediyor +02:00=%1 yüzüyle vuruşları engelliyordu +02:00=%1 bana göre bir kahraman...hımmm...kirpi +02:00=%1 kendi yerini Valhalla'da buldu +02:00=%1 binayı terketti +02:00=%1 dinazorların yanına gidiyor +02:00=%1 kirpileri nesillerini tüketmeye bir adım daha yaklaştırdı +02:00=%1 gözlerimi yaşarttı +02:00=%1 eskiden bir kirpiydi +02:00=%1 papatya ekiyor +02:00=%1 artık yok +02:00=%1 için bir veda yapalım +02:00=%1 ümidi kesildi +02:00=%1 son perdeyi kapattı +02:00=Varsa iç bir tane %1 +02:00=%1 Anlık Yoğun Varlık Sorunu çekiyor +02:00=%1 hayata veda etti +02:00=%1 kaya gibi öldü +02:00=%1 artık yok +02:00=%1 son kullanma tarihi doldu +02:00=Yaşamdan yoksun, %1 huzur içinde yatsın +02:00=%1 görünmezler korosuna katıldı +02:00=Hoşça kal %1, seni iyi bilirdik! +02:00=%1 vurulmaya çok az dayanabildi +02:00=%1 ek bir can kullanabilirdi +02:00=Evde bir doktor var mı? + ; Hog (%1) drowned -02:01=%1 plays submarine! -02:01=%1 mimics the Titanic! -02:01=%1 swims like a stone! -; Match starts -02:02=Let's fight! -02:02=Armed and ready! +02:01=%1 deniz altı oynuyor! +02:01=%1 Titanik'i taklit ediyor! +02:01=%1 kaya gibi yüzüyor! +02:01=%1 tuğla gibi havada kaldı! +02:01=%1 derin dibi kontrol ediyor +02:01=%1 bir şey diyor: "gulu gulu gulu" +02:01=%1 atlama yapıyor +02:01=%1 kolluklarını unuttu +02:01=%1 gerçekten yüzme dersi almalıydı +02:01=%1 sörf tahtasını evde bırakmış +02:01=%1 yıkanıyor +02:01=%1 ıslak bir kirpi +02:01=%1 can yeleğini getirmeyi unuttu +02:01=%1 bıcı bıcıya gidiyor +02:01=%1 balıklarla yüzüyor +02:01=%1 oyundaki su fiziğinin berbat olduğunu düşünüyor +02:01=%1 susamış görünüyor +02:01=Deniz seni istiyor %1 +02:01=%1 denizde kayboldu +02:01=%1 dalış takımını getirmeliydi +02:01=%1 denizde gömülüyor +02:01=%1 batıyor gibi hissediyor +02:01=%1 sırtüstü yüzme denemesi yapıyor +02:01=%1 Titanik'i aramaya gidiyor +02:01=%1 bu sefer güldürmedi +02:01=%1 Nemo'yu arıyor +02:01=%1 su alıyor +02:01=Aşağıda kaç kirpi var bir bilsen +02:01=%1 okyanus seviyesini yükseltiyor +02:01=%1 orduya katılmamıştı +02:01=%1 ölü balık taklidi yapıyor +02:01=En azından tuvalette boğulmadın, %1 +02:01=Sonic yüzemezdi %1 de öyle +02:01=%1 Ecco the dolphin oyunu oynamak istiyor +02:01=%1 Akvaryum ziyaretine gitti +02:01=%1 kayıp şehir Atlantis'i buldu +02:01=%1 Bioshock 3'te baş rolü oynamaya gidiyor +02:01=Patilerin biraz çalışabilirdi, %1 +02:01=%1 bir jet ski getirmeliydi +02:01=%1 su sporlarını sevmiyor +02:01=%1 sonsuza kadar baloncuk çıkarıyor +02:01=%1 bir sala ihtiyaç duyuyor +02:01=%1 tuzlu suyun cilt için iyi geldiğini düşünüyor +02:01=%1 yarasına tuz basıyor +02:01=%1 tahtada yürüdü +02:01=%1 bir banyoya sahip +02:01=%1 artık ıslak ıslak ıslak +02:01=%1 tüylerini ıslattı +02:01=O, %1 için bir Davy Jones dolabı + +; Round starts +02:02=Savaş başlasın! +02:02=Hazır ve nazır! +02:02=Haykırmaya hazır ol! +02:02=Hadi başlayalım! +02:02=Artık parti başlasın +02:02=Son kalan kirpi kazansın +02:02=Hadi gidelim! +02:02=Başlayalım! +02:02=Bastır! +02:02=Başlıyor... +02:02=Bu büyük şeyin bir başlangıcı +02:02=Hedgewars'a Hoş Geldin +02:02=Sınır hattına hoş geldin +02:02=Düşmanını ez! +02:02=En iyi kirpi kazansın +02:02=Zafer ya da ölüm +02:02=Zafer ganimettir +02:02=Kaybetmek bir seçenek değil +02:02=Ağla tahribat! Kirpi savaşı başlasın! +02:02=Hedgewars, Hedgewars.org tarafından sağlandı +02:02=GL HF +02:02=Şansın varmış Tiyuri'ye karşı oynamıyorsun +02:02=Şansın varmış C0Rr'e karşı oynamıyorsunun +02:02=Şansın varmış Nemo'ya karşı oynamıyorsun +02:02=Şansın varmış Smaxx'e karşı oynamıyorsun +02:02=Şansın varmış Jessor'e karşı oynamıyorsun +02:02=Her şeyi ortaya koy! +02:02=Kaybeden bulaşıkları yıkar! +02:02=Binyıl dövüşü başlasın +02:02=Yüzyıl dövüşü başlasın +02:02=Onyıl dövüşü başlasın +02:02=Yılın dövüşü başlasın +02:02=Ayın dövüşü başlasın +02:02=Haftanın dövüşü başlasın +02:02=Günün dövüşü başlasın +02:02=Saatin dövüşü başlasın +02:02=Elinden geleni yap! +02:02=Düşmanı yok et! +02:02=İyi şanslar +02:02=İyi eğlenceler +02:02=İyi dövüş +02:02=Pis dövüş +02:02=Onura dövüş +02:02=Pes etme +02:02=Asla teslim olma +02:02=Yen ve parçala! +02:02=Parçalama festivali başlasın! +02:02=Umarım mücadeleye hazırsın! +02:02=Hadi Hadi Hadi! +02:02=Hedgehogs devam! +02:02=Göster onlara! +02:02=Asla korkma! +02:02=Cesur ol ve fethet + +; Round ends (win; unused atm) +02:03=... + +; Round ends (draw; unused atm) +02:04=... + +; New health crate +02:05=Yardım geliyor! +02:05=İlkyardım! +02:05=Göklerden ilkyardım! +02:05=Size bir sağlık paketi +02:05=İyi sağlık... kutu biçiminde! +02:05=Doktor çağırıyor +02:05=Taze yara bantları! +02:05=Bu daha iyi hissetmeni sağlayacak +02:05=Büyük iksir! Aaa, yanlış oyun +02:05=Bir beni-al! +02:05=Yakala +02:05=Sağlıklı bir atıştırmalık +02:05=Acıya tedavi +02:05=Kullanım dozu: bulabildiğin kadar çok! +02:05=Acele posta +02:05=Emanetler! + +; New ammo crate +02:06=Daha çok silah! +02:06=Destek geliyor! +02:06=Kilitlen ve bırak! +02:06=Acaba içinde hangi silah var? +02:06=Tedarikler! +02:06=İçinde ne olabilir? +02:06=Hedgewars'ta yılbaşı erken geliyor +02:06=Bir hediye! +02:06=Özel posta! +02:06=Bunu gümrükten geçirmek bir kabustu +02:06=Cennetten yok edici oyuncaklar +02:06=Uyarı! Uçucu İçerik +02:06=Kaldır veya havaya uçur, seçim senin +02:06=Eşyalar! +02:06=Hım hım Cephane +02:06=Yok edici güç kutusu +02:06=Uçak postası! +02:06=Bu kutuda ne varsa pizza olmadığı kesin +02:06=Al şunu! +02:06=Silah bırakılıyor +02:06=Düşmanın bunu almasın! +02:06=Yeni parlak oyuncaklar! +02:06=Gizemli bir kutu! + +; New utility crate +02:07=Araç zamanı! +02:07=Bu işe yarayabilir... +02:07=Araçlar! +02:07=Bu kutudan yararlan +02:07=Dikkat et +02:07=Daha fazla alet! +02:07=Senin için alet! +02:07=Bu güzel olmalı! +02:07=Zekice kullan +02:07=Off bu kutu da ağırmış +02:07=Buna ihtiyacın olabilir + +; Hog (%1) skips his turn +02:08=%1 çoook sıkıcı... +02:08=%1 rahatsız olamazdı +02:08=%1 tembel bir kirpi +02:08=%1 düşüncesiz +02:08=%1 pes etti +02:08=Ertelersen kaybedersin, %1 +02:08=%1 utanmaksızın geçiyor +02:08=%1 gerçekten tembel +02:08=%1 daha fazla motivasyona ihtiyacın var +02:08=%1 bir barışcı +02:08=%1 bir mola alıyor +02:08=%1 dinleniyor +02:08=%1 moral bozmuyor +02:08=%1 yeteneklerine inanmıyor +02:08=%1 hiçbir şey yapmamaya karar veriyor +02:08=%1 düşmanın kendisini yok etmesine izin veriyor +02:08=%1 partilerde berbat olur +02:08=%1 saklanıyor +02:08=%1 bu fırsatı değerlendirmek istemedi +02:08=%1 yapabileceği en iyi şeyin...hiçbir şey olduğuna karar verdi +02:08=%1 koca bir korkak +02:08=Gıt gıt gıdak, %1 bir tavuk +02:08=%1 küçük bir sarı arıyor +02:08=%1 bir ürkek! +02:08=%1 ani ölümü bekliyor +02:08=%1 dövüş istemiyor +02:08=%1 hayattaki amacını tekrar düşünüyor +02:08=%1 hiçbir zaman iyi bir atış yapamadı zaten +02:08=%1 orduya da isteyerek katılmamıştı +02:08=Zamanımızı boşa harcamayı kes, %1 +02:08=Beni hayal kırıklığına uğrattın, %1 +02:08=Hadi ama, bundan daha iyisini yapabilirsin %1 +02:08=%1 kalbi kırıldı +02:08=Görünüyor ki %1 daha iyi yapacak şeylere sahip +02:08=%1 korkak bir ölü +02:08=%1 uyuya kaldı + +; Hog (%1) hurts himself only +02:09=%1 atış çalışmalı! +02:09=%1 kendinden nefret ediyor gibi görünüyor +02:09=%1 yanlış tarafta duruyor! +02:09=%1 emo gibi yapıyor +02:09=%1 silahını yanlış yönde tutuyordu +02:09=%1 sanki biraz sadist +02:09=%1 bir mazoşist +02:09=%1 kendini koruma iç güdüsüne sahip değil +02:09=%1 batırdı +02:09=%1 mahvetti +02:09=Kötü bir atıştı, %1 +02:09=%1 tehlikeli silahlarla çok dikkatsiz +02:09=%1 kariyerini değiştirmeyi düşünmeli +02:09=Dünyadaki. En berbat. Atıştı! +02:09=Yo yo yo %1, DÜŞMANA ateş etmelisin! +02:09=%1 sadece düşmanı yok etmeli +02:09=%1 intihara bir adım daha yaklaşıyor +02:09=%1 düşmana yardım ediyor +02:09=Bu aptalcaydı %1 +02:09=%1 "acı yok, kazanmak yok" deyimiyle yaşıyor +02:09=%1, sanki kafan karışık +02:09=%1 yanlışlıkla kendine zarar veriyor +02:09=%1, kendini utandırmakta üstüne yok +02:09=%1 bir saloz! +02:09=Sakarsın %1 +02:09=%1 düşmana yeteneklerini gösteriyor +02:09=%1 her zaman mükemmel olması beklenemez +02:09=Sorun değil %1, hiç kimse mükemmel değildir +02:09=%1 bunu kesinlikle bilerek yaptı +02:09=Yapmazsan kimseye söylemem, %1 +02:09=Ne utanç verici ama! +02:09=Eminim kimse bunu görmedi %1 +02:09=%1 kendi alan kılavuzunu gözden geçirmeli +02:09=%1 silahında sorun vardı + ; Hog shot an home run (using the bat and another hog) -02:10=Home Run! -02:10=A bird, a plane, ... -02:10=That one is out! +02:10=Tur Vuruşu! +02:10=Bu bir kuş. Hayır uçak, ... +02:10=Bu çıkar! + +; Hog (%1) has to leave (team is gone) +02:11=%1 uyumaya gitmeli! +02:11=%1 oynamak için çok meşgul görünüyor +02:11=Ateşle onu, Scotty! +02:11=%1 gitmeli + +; Weapon Categories +03:00=Zamanlı El Bombası +03:01=Zamanlı El Bombası +03:02=Balistik Silah +03:03=Kılavuzlu Silah +03:04=Tabanca (çok atışlı) +03:05=Kazma Aracı +03:06=Eylem +03:07=Taşıma Yardımcısı +03:08=Yakınlık Bombası +03:09=Tabanca (çok atışlı) +03:10=BUM! +03:11=Bum! +03:12=Dövüş Sanatları +03:13=KULLANILMIYOR +03:14=Taşıma Yardımcısı +03:15=Hava Saldırısı +03:16=Hava Saldırısı +03:17=Kazma Aracı +03:18=Yardımcı +03:19=Taşıma Yardımcısı +03:20=Eylem +03:21=Balistik Silah +03:22=Bana Indiana de! +03:23=(Gerçekten) Dövüş Sanatları +03:24=Pasta yalan DEĞİL! +03:25=Kostüm Seti +03:26=Meyveli El Bombası +03:27=Ateşli El Bombası +03:28=Balistik Silah +03:29=Balistik Silah +03:30=Hava Saldırısı +03:31=Uzaktan Kumandalı Bomba +03:32=Geçici Etki +03:33=Geçici Etki +03:34=Geçici Etki +03:35=Geçici Etki +03:36=Geçici Etki +03:37=Geçici Etki +03:38=Tabanca (çok atışlı) +03:39=Taşıma Yardımcısı +03:40=Yakıcı El Bombası +03:41=Cıvıldamaların büyük fanı +03:42=Burada bir şey demek istiyorum... +; the misspelled "Beethoven" is intentional (-> to beat) +03:43=Beathoven'ın ölümcül sonatasını gösteriyor +03:44=Son kullanma tarihi: 1923 +03:45=Bilimin gücü +03:46=Sıcak Sıcak Sıcak! +03:47=Bunları kullanışlı bir yere yapıştır! +03:48=Çekiç zamanı! +03:49=Tahmin ettiğin şeyi yapıyor +03:50=Köstebek fanı +03:51=Zeminde bulunan +03:52=KULLANILMIYOR +03:53=Tür 40 +03:54=Bir şey inşa et +03:55=Yardımcı + +; Weapon Descriptions (use | as line breaks) +04:00=Düşmanlarına basit el bombası ile saldır.|Zamanlayıcı sıfır olduğunda patlayacak.|1-5: Bomba süresini ayarla|Saldır: Daha fazla güçte atmak için basılı tut +04:01=Düğmanlarına parça tesirli bomba ile saldır.|Zamanlayıcı sıfır olduğunda daha küçük|bombalara dönüşür.|1-5: Bomba süresini ayarla|Saldır: Daha fazla güçte atmak için basılı tut +04:02=Düşmanlarına rüzgardan etkilenebilecek|balistik mermi kullanarak saldır.|Saldır: Daha fazla güçle atış için basılı tut +04:03=Seçili hedefe kilitlenecek patlayıcı bir arı|fırlat. Kesinliğini arttırmak için tam güçle|fırlatma.|İmleç: Hedef seç|Saldır: Daha fazla güçle atış için basılı tut +04:04=Düşmanına iki atışla tüfek kullanarak saldır.|Yayılması sayesinde rakibine zarar vermen için|keskin vuruş yapman gerekmiyor.|Saldır: Ateş (çok kez) +04:05=Yer altına hareket et! Çekici kullanarak|zemine bir delik kaz ve diğer yerlere ulaş.|Saldır: Kazmayı başlat ve durdur +04:06=Sıkıldın mı? Saldıracak yer mi yok? Cephane mi |kurtarmak istiyorsun? Problem yok!|Pas geç korkak!|Saldır: Dövüşmeden turu atla +04:07=İp kullanarak zamanlı atışlarla uzun mesafelere|bağlan. Diğer kirpilere doğru kaymak için|momentumunu kullan veya üzerlerine el bombası|ve diğer silahları at.|Saldır: At ve ipi bırak|Uzun Atlama: El bombası veya benzer silahları|bırak +04:08=Küçük geçişlere veya ayaklarının yanına mayın|bırakarak düşmanı uzaklaştır. Kendin için|tetiklemediğinden emin ol!|Saldır: Ayağının yanına mayın bırak +04:09=Hedefinden emin değil misin? Tabanca|kullanarak dört atışa kadar düşmanı vur.|Saldır: Ateş (çok kez) +04:10=Zor kullanım her zaman bir seçenek. Bu klasik|patlayıcıyı düşmanının yanına koy ve çekil.|Saldır: Ayağının yanına dinamit bırak +04:11=Düşman kirpilerden üzerlerine sopa ile vurarak|uzaklara veya suya düşür. Veya|arkadaşlarına birkaç mayın fırlatmak nasıl olurdu?|Saldır: Önündeki herşeye vurarak fırlat +04:12=Yakınlaş ve neredeyse bu ölümcül dövüş sanatı|teknik gücünü ortaya çıkar.|Saldır: Muhteşem Yükselen Ejderha yap. +04:13=KULLANILMIYOR +04:14=Yükseklikten mi korkuyorsun? O zaman bir paraşüt|kullan.|Uzağa düşerken açılacak ve kirpinin düşme zararı|almasını engelleyecek|Saldır: Paraşütü aç|Uzun Atlama: El bombası veya benzeri silahlar bırak +04:15=Bombalayıcı kulanarak uçakla düşmanlarına saldır.|Sol/Sağ: Saldırı yönünü belirle|İmleç: Hedef bölgeyi seç +04:16=Hedef alana çeşitli mayın atacak bir uçak çağır.|Sol/Sağ: Saldırı yönünü belirle|İmleç: Hedef bölgeyi seç +04:17=Korunak mı gerekiyor? Seni kaplayabilecek bir|tünel için kaynak makinesi kullan|Saldır: Kazmayı başlat/durdur +04:18=Ek koruma mı gerekiyor? Yoksa geçilemez|zemini mi geçmek istiyorsun? İstediğin kadar|merdiven koy|Sol/Sağ: Yerleştilecek merdiveni seç|İmleç: Geçerli yere merdiven yerleştir +04:19=Doğru yerde kullanıldığında ışınlanma tüm|silahlardan daha güçlü olabilir. Kirpileri|saniyeler içerisinde tehlikeli durumlardan|kurtarır.|İmleç: Hedef bölgeyi seç +04:20=Geçerli turu başka bir kirpiyle oynamanı|sağlar.|Saldır: Kirpi değiştirmeyi etkinleştir +04:21=El bombasına benzer bir füze fırlatır ve|çarpma sonrası çok sayıda bombaya dönüşür.|Saldır: Tam güçte fırlat +04:22=Sadece Indiana Jones için değil! Kamçı|çoğu durumda çok kullanışlı bir silahtır.|Özellikle birini yamaçtan uçurmak için.|Saldır: Önündeki her şeye vur +04:23=Eğer kaybedecek hiçbir şeyin yoksa, bu|kullanışlı olabilir. Kirpini özel bir yönde|başlatarak feda et ve önündeki her şeye|zarar verip sonunda patlamasını sağla.|Saldır: Şiddetli ve ölümcül bir saldırı başlat +04:24=Mutlu Yıllar! Bu keki çalıştır, düşmanının yanına|yürümesine izin ver ve patlayan bir parti yapmalarını|sağla. Kek neredeyse tüm zeminlerden geçebilir|fakat yolun ortasında patlayabilir.|Saldır: Keki başlat ve durdurup patlat +04:25=Bu kiti kullanarak düşmanlarının kirpine doğru zıplamasını|sağla (ve bir boşluk veya deliğe).|Saldır: Kiti kullan ve diğer kirpiyi etkile +04:26=Bu sulu karpuzu düşmanına at. Zaman dolduğunda|çok sayıda patlayıcı parçaya ayrılacaktır.|1-5: Karpuz zaanlayıcısını ayarla.|Saldır: Daha fazla güçle atış için basılı tut +04:27=Bu zalim patlayıcıyı kullanarak rakibini cehennem|ateş yağmuruna tut. Küçük ateşler daha|uzun süreceğinden yakın olmamaya dikkat et.|Saldır: Daha fazla güçle atış için basılı tut +04:28=Bu roketi fırlattıktan kısa süre sonra katı zemini|kazmaya başlayacak ve tekrar yüzeye çıktığında|veya süresi dolduğunda patlayacak.|Saldır: Daha fazla güçle atış için basılı tut +04:29=Bu küçük çocuklar için değil! Top tabancası patlayıcı|dolu tonlarca küçük renkli top fırlatır.|Saldır: Tam güçte atış yap|Yukarı/Aşağı: Nişan al +04:30=Muhteşem napalm atışı için bir uçak çağır.|Doğru nişan ile bu saldırı zeminin büyük bölümünü|yok edebilir ve tabii ki şansız kirpileri de.|Sol/Sağ: Saldırı yönünü belirle|İmleç: Hedef bölgeyi seç +04:31=RC uçağı sandıkları toplamak veya uzaktaki kirpilere|saldırmak için kullanışlı bir silahtır.|Doğrudan düşmanlara çarp veya ilk olarak bomba bırak.|Saldır: Uçağı başlat veya bomba bırak|Uzun Zıplama: Valkrie'lerin savaşa gelmelerini sağla|Sol/Sağ: Uçağı kontrol et +04:32=Düşük yer çekimi diğer tüm diyetlerden daha etkilidir!|Daha yukarı ve büyük uzaklıklara zıpla|veya düşmanının daha uzağa uçmasını sağla|Saldır: Etkinleştir +04:33=Bazen daha fazla zarar vermek için bu küçük ek güce|ihtiyacın olabilir.|Saldır: Etkinleştir +04:34=Bana dokunamazsın!|Saldır: Etkinleştir +04:35=Bazen zaman su gibi akıp geçiyor. Saldırını bitirmek|için ek saniye al.|Saldır: Etkinleştir +04:36=Aslında bazen hedef tutturmada çok kötüsün. Modern|teknoloji kullanarak biraz yardım al.|Saldır: Etkinleştir +04:37=Gün ışığından korkma. Sadece bir tur sürecek fakat|Diğer kirpilere verdiğin zararı emmeni sağlayacak.|Saldır: Etkinleştir +04:38=Keskin nişancı tüfeği birliğindeki en zarar verici silah|olabilir ancak yakın mesafede etkisi azdır.|Hasar, hedef uzak oldukça daha çok artar.|Saldır: Ateş et (iki kez) +04:39=Haritanın diğer yerlerine uçan daire ile uç.|Bu uzmanlaşmak için zaman gerektirir ve|alışana kadar savaş alanında her yere|götürebilir.|Saldır: Etkinleştir|Yukarı/Sol/Sağ: Bir yöne güç uygula|Uzun Atlama: El bombası veya|benzer silahlar bırak +04:40=Set some ground on fire using this bottle filled|with (soon to be) burning liquid.|Saldır: Daha fazla güçle atış için basılı tut +04:41=Doğa uçan dairenin üzerinde de olabilir|Kuşçuk kirpini taşıyabilir ve|düşmanlarına yumurta bırakabilir!|Hızlı ol, çünkü Kuşçuğu kullanmak |zamanını tüketir!|Saldır: Etkinleştir ve yumurta bırak|Yukarı/Sol/Sağ: Bir yöne kanat çırp +04:42=Bu taşınabilir portal aygıtı seni, düşmanlarını|veya bir silahını zemindeki iki nokta arasında|hemen taşıma yeteneğine|sahip.|Zekice kullan ve maceran bir... BAŞARIYA|DÖNÜŞSÜN!|Saldır: Bir portal ateş et|Değiştir: Portal renkleri arasında geçiş yap +04:43=Müzikal kariyerine başarılı bir patlamayla başla!|Cennetten bir piyano düşür, fakat dikkat et...|birinin çalması gerekiyor ve|bu senin hayatın olmasın.|İmleç: Hedef bölgeyi seç|F1-F9: Piyanoyu çal +04:44=Bu sadece bir peynir değil, bir biyolojik silah!|Zamanlayıcı sıfır olduğunda koca bir hasar|vermenin yanında, kokuya dokunan şanssız|herkesi de zehirleyecek!|1-5: Bombanın zamanını ayarla|Saldır: Daha fazla güç ile fırlatmak için tut +04:45=Sonunda fizik dersleri işe yaradı.|Düşmanlarına kocaman bir sinüs dalgası at.|Dikkatli ol, bu silah oldukça büyük bir vuruşa sahip|(Bu silah bitmedi)|Saldır: Ateş et +04:46=Düşmanlarını sızan akışkan alevle kapla|Kalp ısıtıcı!|Saldır: Etkinleştir|Yukarı/Aşağı: Hedef almaya devam et|Sol/Sağ: Fışkırtma gücünü değiştir +04:47=Dikenli, sinsi, yapışkan mayınlarla çifte zevk!|Zincirleme reaksiyon ayarla veya kendini koru (veya ikisi de!)|Saldır: Daha fazla güçle atış için basılı tut (iki kez) +04:48=Niçin köstebeklere kötü davranılsın?|Bir kirpi de zevk için dövülebilir! Bu|çekicin iyi bir yanı kirpinin canının |üçte birini alması ve yer altına sokması.|Saldır: Etkinleştir +04:49=Arkadaşlarını yeniden canlandır!|Fakat dikkatli ol, bu ayrıca düşmanlarını da|canlandırır.|Saldır: Yavaşça canlandırmak için saldırma|düğmesini basılı tut|Yukarı: Canlandırmayı hızlandır +04:50=Biri altta mı saklanıyor?|Matkap saldırısı ile kaz!|Zamanlayıcı ne kadar kazılacağını denetler. +04:51=Bir çamur topu fırlatarak ücretsiz bir atış kap.|Biraz kokar ancak kirpileri geri sektirir. +04:52=KULLANILMIYOR +04:53=Arkadaşlarını savaşta yalnız bırakarak|zaman ve uzaya seyahat et.|Herhangi bir an, Ani Ölüm veya tümü|ölmüşse geri gelmeye hazır ol.|Yadsıma: Ani Ölüm kipinde, tek isen veya|Kralsan çalışmaz. +04:54=TAM DEĞİL +04:55=Yapışkan tanecikler püskürt.|Köprü yap, düşmanı göm, tünelleri kapat.|Dikkatli ol sana gelmesin! + +; Game goal strings +05:00=Oyun Kipleri +05:01=Aşağıdaki kurallar uygulanır +05:02=Kaleler: Kaleni savun; düşmanlarını alt et! +05:03=Düşük Yer Çekimi: Adımına dikkat et +05:04=Dayanıklılık: Kirpiler (neredeyse) zarar görmezler +05:05=Vampirleşme: Verilen hasar kirpileri iyileştirir +05:06=Karma: Verilen hasar kirpilere zarar verir +05:07=Kralı Koru: Kralın ölmesine izin verme!|Kralı Yerleştir: Kralın için korunaklı bir başlangıç noktası seç +05:08=Kirpileri Yerleştir: Kirpilerini oyun başlamadan önce yerleştir +05:09=Ağır Sınıf: Kirpiler hareket etmek için yer değiştiremezler +05:10=Yıkılmaz Zemin: Çoğu silah zemine zarar veremez +05:11=Paylaşılan Cephane: Aynı renkteki tüm takımlar cephaneyi paylaşır +05:12=Mayın Zamanlayıcı: Mayınlar %1 saniye sonra patlayacak +05:13=Mayın Zamanlayıcı: Mayınlar hemen patlayacak +05:14=Mayın Zamanlayıcı: Mayınlar 0 - 5 saniye içinde patlayacak +05:15=Hasar Değiştirici: Tüm silahlar %%1 hasar verecek +05:16=Tur sonunda tüm kirpilerin sağlığı sıfırlanacak +05:17=Yapay zeka kirpileri öldükten sonra yeniden doğar +05:18=Sınırsız Saldırı +05:19=Silahlar her tur sonunda sıfırlanır +05:20=Silahlar kirpiler arasında paylaşılmaz +05:21=Takımları Etiketle: Klandaki takımlar başarılı turlar alır|Paylaşılan Zaman: Klandaki takımlar tur zamanını paylaşırlar diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/Themes/Fruit/Orange1.png Binary file share/hedgewars/Data/Themes/Fruit/Orange1.png has changed diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/Themes/Fruit/Orange2.png Binary file share/hedgewars/Data/Themes/Fruit/Orange2.png has changed diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/Themes/Fruit/theme.cfg --- a/share/hedgewars/Data/Themes/Fruit/theme.cfg Sat Apr 20 02:17:53 2013 +0200 +++ b/share/hedgewars/Data/Themes/Fruit/theme.cfg Sat Apr 20 02:20:15 2013 +0200 @@ -2,7 +2,7 @@ border = 0, 128, 0 water-top = 255, 98, 0 water-bottom = 255, 68, 0 -water-opacity = 255 +water-opacity = 125 music = oriental.ogg clouds = 20 object = Orange1, 1, 50, 84, 15, 3, 1, 8, 2, 90, 73 @@ -10,4 +10,4 @@ object = Watermelon, 1, 87, 272, 77, 10, 1, 21, 2, 242, 219 object = Banana1, 1, 152, 191, 37, 24, 1, 2, 1, 163, 174 object = Banana2, 1, 1, 190, 37, 24, 1, 22, 0, 163, 174 -flakes = 40, 3, 999999999, 100, 260 +flakes = 20, 3, 999999999, 100, 260 diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/misc/hedgewars-mimeinfo.xml --- a/share/hedgewars/Data/misc/hedgewars-mimeinfo.xml Sat Apr 20 02:17:53 2013 +0200 +++ b/share/hedgewars/Data/misc/hedgewars-mimeinfo.xml Sat Apr 20 02:20:15 2013 +0200 @@ -18,6 +18,7 @@ Ukázka hry Hedgewars Demo för Hedgewars Hedgewars-demo + Hedgewars Dösteri @@ -39,6 +40,7 @@ Uložená hra Hedgewars Sparfil för Hedgewars Gemt Hedgewars-spil + Hedgewars kayıtlı oyun diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/misc/hedgewars.desktop --- a/share/hedgewars/Data/misc/hedgewars.desktop Sat Apr 20 02:17:53 2013 +0200 +++ b/share/hedgewars/Data/misc/hedgewars.desktop Sat Apr 20 02:20:15 2013 +0200 @@ -16,6 +16,7 @@ GenericName[sk]=Bojujúci ježkovia GenericName[cs]=Bojující ježci GenericName[sv]=Stridande igelkottar +GenericName[tr]=Dövüşen Kirpiler Icon=hedgewars.png Exec=hedgewars %U Terminal=false diff -r 6ea838b8dcd5 -r 13ac59499066 share/hedgewars/Data/misc/hwengine.desktop.in --- a/share/hedgewars/Data/misc/hwengine.desktop.in Sat Apr 20 02:17:53 2013 +0200 +++ b/share/hedgewars/Data/misc/hwengine.desktop.in Sat Apr 20 02:20:15 2013 +0200 @@ -13,6 +13,7 @@ GenericName[pt]=Motor de jogo Hedgewars, para reprodução de jogos guardados e demos GenericName[ru]=Движок Hedgewars для проигрывания сохранённых игр и демок GenericName[sk]=Engine hry Hedgewars, pre prehrávanie uložených hier a demo súborov +GenericName[tr]=Kayıtların ve gösterilerin oynatılması için Hedgewars motoru GenericName[cs]=Engine hry Hedgewars pro přehrávání uložených her a ukázkových souborů GenericName[sv]=Hedgewarsmotorn, för att öppna demo- och sparfiler GenericName[da]=Kæmpende Pindsvin