# HG changeset patch # User Medo <smaxein@googlemail.com> # Date 1345243689 -7200 # Node ID 3c4b4cb40f402780ffe4122b750ef12b586d81aa # Parent 763d3961400b294e5d6f231f3a5bafbaba2b377a# Parent c7a21fc530de3f2a3fee55f3b22f55033e4c603d Merge diff -r 763d3961400b -r 3c4b4cb40f40 QTfrontend/gameuiconfig.cpp --- a/QTfrontend/gameuiconfig.cpp Sat Aug 18 00:47:51 2012 +0200 +++ b/QTfrontend/gameuiconfig.cpp Sat Aug 18 00:48:09 2012 +0200 @@ -22,6 +22,7 @@ #include <QDesktopWidget> #include <QInputDialog> #include <QCryptographicHash> +#include <QStandardItemModel> #include "gameuiconfig.h" #include "hwform.h" @@ -30,6 +31,7 @@ #include "hwconsts.h" #include "fpsedit.h" #include "HWApplication.h" +#include "DataManager.h" GameUIConfig::GameUIConfig(HWForm * FormWidgets, const QString & fileName) : QSettings(fileName, QSettings::IniFormat) @@ -108,6 +110,12 @@ depth = HWApplication::desktop()->depth(); if (depth < 16) depth = 16; else if (depth > 16) depth = 32; + + { // load colors + QStandardItemModel * model = DataManager::instance().colorsModel(); + for(int i = model->rowCount() - 1; i >= 0; --i) + model->item(i)->setData(QColor(value(QString("colors/color%1").arg(i), model->item(i)->data().value<QColor>()).value<QColor>())); + } } QStringList GameUIConfig::GetTeamsList() @@ -182,6 +190,13 @@ #ifdef SPARKLE_ENABLED setValue("misc/autoUpdate", isAutoUpdateEnabled()); #endif + + { // 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()); + } + Form->gameSettings->sync(); } diff -r 763d3961400b -r 3c4b4cb40f40 QTfrontend/net/newnetclient.cpp --- a/QTfrontend/net/newnetclient.cpp Sat Aug 18 00:47:51 2012 +0200 +++ b/QTfrontend/net/newnetclient.cpp Sat Aug 18 00:48:09 2012 +0200 @@ -384,38 +384,6 @@ return; } - if (lst[0] == "ADD_TEAM") - { - if(lst.size() != 24) - { - qWarning("Net: Bad ADDTEAM message"); - return; - } - QStringList tmp = lst; - tmp.removeFirst(); - emit AddNetTeam(tmp); - return; - } - - if (lst[0] == "REMOVE_TEAM") - { - if(lst.size() != 2) - { - qWarning("Net: Bad REMOVETEAM message"); - return; - } - emit RemoveNetTeam(HWTeam(lst[1])); - return; - } - - if(lst[0] == "ROOMABANDONED") - { - netClientState = InLobby; - askRoomsList(); - emit LeftRoom(tr("Room destroyed")); - return; - } - if(lst[0] == "KICKED") { netClientState = InLobby; @@ -424,31 +392,6 @@ return; } - if(lst[0] == "JOINED") - { - if(lst.size() < 2) - { - qWarning("Net: Bad JOINED message"); - return; - } - - for(int i = 1; i < lst.size(); ++i) - { - if (lst[i] == mynick) - { - netClientState = InRoom; - emit EnteredGame(); - emit roomMaster(isChief); - if (isChief) - emit configAsked(); - } - - emit nickAdded(lst[i], isChief && (lst[i] != mynick)); - emit chatStringFromNet(tr("%1 *** %2 has joined the room").arg('\x03').arg(lst[i])); - } - return; - } - if(lst[0] == "LOBBY:JOINED") { if(lst.size() < 2) @@ -472,21 +415,6 @@ return; } - if(lst[0] == "LEFT") - { - if(lst.size() < 2) - { - 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 - emit chatStringFromNet(tr("%1 *** %2 has left (%3)").arg('\x03').arg(lst[1], lst[2])); - return; - } - if(lst[0] == "ROOM" && lst.size() == 10 && lst[1] == "ADD") { QStringList tmp = lst; @@ -529,13 +457,6 @@ return; } - if (lst[0] == "RUN_GAME") - { - netClientState = InGame; - emit AskForRunGame(); - return; - } - if (lst[0] == "ASKPASSWORD") { emit AskForPassword(mynick); @@ -563,76 +484,6 @@ return; } - if (lst[0] == "TEAM_ACCEPTED") - { - if (lst.size() != 2) - { - qWarning("Net: Bad TEAM_ACCEPTED message"); - return; - } - emit TeamAccepted(lst[1]); - return; - } - - - if (lst[0] == "CFG") - { - if(lst.size() < 3) - { - qWarning("Net: Bad CFG message"); - return; - } - QStringList tmp = lst; - tmp.removeFirst(); - tmp.removeFirst(); - if (lst[1] == "SCHEME") - emit netSchemeConfig(tmp); - else - emit paramChanged(lst[1], tmp); - return; - } - - if (lst[0] == "HH_NUM") - { - if (lst.size() != 3) - { - qWarning("Net: Bad TEAM_ACCEPTED message"); - return; - } - HWTeam tmptm(lst[1]); - tmptm.setNumHedgehogs(lst[2].toUInt()); - emit hhnumChanged(tmptm); - return; - } - - if (lst[0] == "TEAM_COLOR") - { - if (lst.size() != 3) - { - qWarning("Net: Bad TEAM_COLOR message"); - return; - } - HWTeam tmptm(lst[1]); - tmptm.setColor(lst[2].toInt()); - emit teamColorChanged(tmptm); - return; - } - - if (lst[0] == "EM") - { - if(lst.size() < 2) - { - qWarning("Net: Bad EM message"); - return; - } - for(int i = 1; i < lst.size(); ++i) - { - QByteArray em = QByteArray::fromBase64(lst[i].toAscii()); - emit FromNet(em); - } - return; - } - if (lst[0] == "BYE") { if (lst.size() < 2) @@ -650,26 +501,192 @@ return; } - if (lst[0] == "ADMIN_ACCESS") { emit adminAccess(true); return; } - if (lst[0] == "ROOM_CONTROL_ACCESS") + if(netClientState == InLobby && lst[0] == "JOINED") { - if (lst.size() < 2) + if(lst.size() < 2 || lst[1] != mynick) { - qWarning("Net: Bad ROOM_CONTROL_ACCESS message"); + qWarning("Net: Bad JOINED message"); return; } - isChief = (lst[1] != "0"); - emit roomMaster(isChief); + + for(int i = 1; i < lst.size(); ++i) + { + if (lst[i] == mynick) + { + netClientState = InRoom; + emit EnteredGame(); + emit roomMaster(isChief); + if (isChief) + emit configAsked(); + } + + emit nickAdded(lst[i], isChief && (lst[i] != mynick)); + emit chatStringFromNet(tr("%1 *** %2 has joined the room").arg('\x03').arg(lst[i])); + } return; } - qWarning() << "Net: Unknown message:" << lst; + if(netClientState == InRoom || netClientState == InGame) + { + if (lst[0] == "EM") + { + if(lst.size() < 2) + { + qWarning("Net: Bad EM message"); + return; + } + for(int i = 1; i < lst.size(); ++i) + { + QByteArray em = QByteArray::fromBase64(lst[i].toAscii()); + emit FromNet(em); + } + return; + } + + if (lst[0] == "ADD_TEAM") + { + if(lst.size() != 24) + { + qWarning("Net: Bad ADDTEAM message"); + return; + } + QStringList tmp = lst; + tmp.removeFirst(); + emit AddNetTeam(tmp); + return; + } + + if (lst[0] == "REMOVE_TEAM") + { + if(lst.size() != 2) + { + qWarning("Net: Bad REMOVETEAM message"); + return; + } + emit RemoveNetTeam(HWTeam(lst[1])); + return; + } + + if(lst[0] == "ROOMABANDONED") + { + netClientState = InLobby; + askRoomsList(); + emit LeftRoom(tr("Room destroyed")); + return; + } + + if (lst[0] == "RUN_GAME") + { + netClientState = InGame; + emit AskForRunGame(); + return; + } + + if (lst[0] == "TEAM_ACCEPTED") + { + if (lst.size() != 2) + { + qWarning("Net: Bad TEAM_ACCEPTED message"); + return; + } + emit TeamAccepted(lst[1]); + return; + } + + if (lst[0] == "CFG") + { + if(lst.size() < 3) + { + qWarning("Net: Bad CFG message"); + return; + } + QStringList tmp = lst; + tmp.removeFirst(); + tmp.removeFirst(); + if (lst[1] == "SCHEME") + emit netSchemeConfig(tmp); + else + emit paramChanged(lst[1], tmp); + return; + } + + if (lst[0] == "HH_NUM") + { + if (lst.size() != 3) + { + qWarning("Net: Bad TEAM_ACCEPTED message"); + return; + } + HWTeam tmptm(lst[1]); + tmptm.setNumHedgehogs(lst[2].toUInt()); + emit hhnumChanged(tmptm); + return; + } + + if (lst[0] == "TEAM_COLOR") + { + if (lst.size() != 3) + { + qWarning("Net: Bad TEAM_COLOR message"); + return; + } + HWTeam tmptm(lst[1]); + tmptm.setColor(lst[2].toInt()); + emit teamColorChanged(tmptm); + return; + } + + if(lst[0] == "JOINED") + { + if(lst.size() < 2) + { + qWarning("Net: Bad JOINED message"); + return; + } + + 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])); + } + return; + } + + if(lst[0] == "LEFT") + { + if(lst.size() < 2) + { + 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 + emit chatStringFromNet(tr("%1 *** %2 has left (%3)").arg('\x03').arg(lst[1], lst[2])); + return; + } + + if (lst[0] == "ROOM_CONTROL_ACCESS") + { + if (lst.size() < 2) + { + qWarning("Net: Bad ROOM_CONTROL_ACCESS message"); + return; + } + isChief = (lst[1] != "0"); + emit roomMaster(isChief); + return; + } + } + + qWarning() << "Net: Unknown message or wrong state:" << lst; } void HWNewNet::onHedgehogsNumChanged(const HWTeam& team) diff -r 763d3961400b -r 3c4b4cb40f40 QTfrontend/ui/page/pageeditteam.cpp --- a/QTfrontend/ui/page/pageeditteam.cpp Sat Aug 18 00:47:51 2012 +0200 +++ b/QTfrontend/ui/page/pageeditteam.cpp Sat Aug 18 00:48:09 2012 +0200 @@ -289,6 +289,9 @@ int idx = list.indexOf("cpu.png"); if (idx >= 0) list.removeAt(idx); + idx = list.indexOf("cpu_plain.png"); + if (idx >= 0) + list.removeAt(idx); idx = list.indexOf("hedgewars.png"); if (idx >= 0) list.removeAt(idx); diff -r 763d3961400b -r 3c4b4cb40f40 QTfrontend/ui/page/pageoptions.cpp --- a/QTfrontend/ui/page/pageoptions.cpp Sat Aug 18 00:47:51 2012 +0200 +++ b/QTfrontend/ui/page/pageoptions.cpp Sat Aug 18 00:48:09 2012 +0200 @@ -28,368 +28,397 @@ #include <QTextBrowser> #include <QTableWidget> #include <QSlider> +#include <QSignalMapper> +#include <QColorDialog> +#include <QStandardItemModel> #include "pageoptions.h" #include "hwconsts.h" #include "fpsedit.h" #include "igbox.h" +#include "DataManager.h" // TODO cleanup QLayout * PageOptions::bodyLayoutDefinition() { - QGridLayout * pageLayout = new QGridLayout(); - pageLayout->setColumnStretch(0, 100); - pageLayout->setColumnStretch(1, 100); - pageLayout->setColumnStretch(2, 100); - pageLayout->setRowStretch(0, 0); - //pageLayout->setRowStretch(1, 100); - pageLayout->setRowStretch(2, 0); - pageLayout->setContentsMargins(7, 7, 7, 0); - pageLayout->setSpacing(0); + QVBoxLayout * pageLayout = new QVBoxLayout(); + QTabWidget * tabs = new QTabWidget(this); + pageLayout->addWidget(tabs); + QWidget * page1 = new QWidget(this); + QWidget * page2 = new QWidget(this); + tabs->addTab(page1, tr("General")); + tabs->addTab(page2, tr("Advanced")); + + { // page 1 + QGridLayout * page1Layout = new QGridLayout(page1); + //gbTBLayout->setMargin(0); + page1Layout->setSpacing(0); + page1Layout->setAlignment(Qt::AlignTop | Qt::AlignLeft); - QGroupBox * gbTwoBoxes = new QGroupBox(this); - pageLayout->addWidget(gbTwoBoxes, 0, 0, 1, 3); - QGridLayout * gbTBLayout = new QGridLayout(gbTwoBoxes); - gbTBLayout->setMargin(0); - gbTBLayout->setSpacing(0); - gbTBLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); - - QPixmap pmNew(":/res/new.png"); - QPixmap pmEdit(":/res/edit.png"); - QPixmap pmDelete(":/res/delete.png"); + QPixmap pmNew(":/res/new.png"); + QPixmap pmEdit(":/res/edit.png"); + QPixmap pmDelete(":/res/delete.png"); - { - teamsBox = new IconedGroupBox(this); - //teamsBox->setContentTopPadding(0); - //teamsBox->setAttribute(Qt::WA_PaintOnScreen, true); - teamsBox->setIcon(QIcon(":/res/teamicon.png")); - teamsBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - teamsBox->setTitle(QGroupBox::tr("Teams")); + { + teamsBox = new IconedGroupBox(this); + //teamsBox->setContentTopPadding(0); + //teamsBox->setAttribute(Qt::WA_PaintOnScreen, true); + teamsBox->setIcon(QIcon(":/res/teamicon.png")); + teamsBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + teamsBox->setTitle(QGroupBox::tr("Teams")); - QGridLayout * GBTlayout = new QGridLayout(teamsBox); + QGridLayout * GBTlayout = new QGridLayout(teamsBox); - CBTeamName = new QComboBox(teamsBox); - GBTlayout->addWidget(CBTeamName, 0, 0); + CBTeamName = new QComboBox(teamsBox); + GBTlayout->addWidget(CBTeamName, 0, 0); - BtnNewTeam = new QPushButton(teamsBox); - BtnNewTeam->setToolTip(tr("New team")); - BtnNewTeam->setIconSize(pmNew.size()); - BtnNewTeam->setIcon(pmNew); - BtnNewTeam->setMaximumWidth(pmNew.width() + 6); - connect(BtnNewTeam, SIGNAL(clicked()), this, SIGNAL(newTeamRequested())); - GBTlayout->addWidget(BtnNewTeam, 0, 1); + BtnNewTeam = new QPushButton(teamsBox); + BtnNewTeam->setToolTip(tr("New team")); + BtnNewTeam->setIconSize(pmNew.size()); + BtnNewTeam->setIcon(pmNew); + BtnNewTeam->setMaximumWidth(pmNew.width() + 6); + connect(BtnNewTeam, SIGNAL(clicked()), this, SIGNAL(newTeamRequested())); + GBTlayout->addWidget(BtnNewTeam, 0, 1); - BtnEditTeam = new QPushButton(teamsBox); - BtnEditTeam->setToolTip(tr("Edit team")); - BtnEditTeam->setIconSize(pmEdit.size()); - BtnEditTeam->setIcon(pmEdit); - BtnEditTeam->setMaximumWidth(pmEdit.width() + 6); - connect(BtnEditTeam, SIGNAL(clicked()), this, SLOT(requestEditSelectedTeam())); - GBTlayout->addWidget(BtnEditTeam, 0, 2); + BtnEditTeam = new QPushButton(teamsBox); + BtnEditTeam->setToolTip(tr("Edit team")); + BtnEditTeam->setIconSize(pmEdit.size()); + BtnEditTeam->setIcon(pmEdit); + BtnEditTeam->setMaximumWidth(pmEdit.width() + 6); + connect(BtnEditTeam, SIGNAL(clicked()), this, SLOT(requestEditSelectedTeam())); + GBTlayout->addWidget(BtnEditTeam, 0, 2); - BtnDeleteTeam = new QPushButton(teamsBox); - BtnDeleteTeam->setToolTip(tr("Delete team")); - BtnDeleteTeam->setIconSize(pmDelete.size()); - BtnDeleteTeam->setIcon(pmDelete); - BtnDeleteTeam->setMaximumWidth(pmDelete.width() + 6); - connect(BtnDeleteTeam, SIGNAL(clicked()), this, SLOT(requestDeleteSelectedTeam())); - GBTlayout->addWidget(BtnDeleteTeam, 0, 3); - - LblNoEditTeam = new QLabel(teamsBox); - LblNoEditTeam->setText(tr("You can't edit teams from team selection. Go back to main menu to add, edit or delete teams.")); - LblNoEditTeam->setWordWrap(true); - LblNoEditTeam->setVisible(false); - GBTlayout->addWidget(LblNoEditTeam, 0, 0); + BtnDeleteTeam = new QPushButton(teamsBox); + BtnDeleteTeam->setToolTip(tr("Delete team")); + BtnDeleteTeam->setIconSize(pmDelete.size()); + BtnDeleteTeam->setIcon(pmDelete); + BtnDeleteTeam->setMaximumWidth(pmDelete.width() + 6); + connect(BtnDeleteTeam, SIGNAL(clicked()), this, SLOT(requestDeleteSelectedTeam())); + GBTlayout->addWidget(BtnDeleteTeam, 0, 3); - gbTBLayout->addWidget(teamsBox, 0, 0); - } - - { - IconedGroupBox* groupWeapons = new IconedGroupBox(this); + LblNoEditTeam = new QLabel(teamsBox); + LblNoEditTeam->setText(tr("You can't edit teams from team selection. Go back to main menu to add, edit or delete teams.")); + LblNoEditTeam->setWordWrap(true); + LblNoEditTeam->setVisible(false); + GBTlayout->addWidget(LblNoEditTeam, 0, 0); - //groupWeapons->setContentTopPadding(0); - //groupWeapons->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - groupWeapons->setIcon(QIcon(":/res/weaponsicon.png")); - groupWeapons->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - groupWeapons->setTitle(QGroupBox::tr("Schemes and Weapons")); - QGridLayout * WeaponsLayout = new QGridLayout(groupWeapons); + page1Layout->addWidget(teamsBox, 0, 0); + } - QLabel* SchemeLabel = new QLabel(groupWeapons); - SchemeLabel->setText(QLabel::tr("Game scheme")); - WeaponsLayout->addWidget(SchemeLabel, 1, 0); + { + IconedGroupBox* groupWeapons = new IconedGroupBox(this); - SchemesName = new QComboBox(groupWeapons); - WeaponsLayout->addWidget(SchemesName, 1, 1); + //groupWeapons->setContentTopPadding(0); + //groupWeapons->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + groupWeapons->setIcon(QIcon(":/res/weaponsicon.png")); + groupWeapons->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + groupWeapons->setTitle(QGroupBox::tr("Schemes and Weapons")); + QGridLayout * WeaponsLayout = new QGridLayout(groupWeapons); - SchemeNew = new QPushButton(groupWeapons); - SchemeNew->setWhatsThis(tr("New scheme")); - SchemeNew->setIconSize(pmNew.size()); - SchemeNew->setIcon(pmNew); - SchemeNew->setMaximumWidth(pmNew.width() + 6); - WeaponsLayout->addWidget(SchemeNew, 1, 2); + QLabel* SchemeLabel = new QLabel(groupWeapons); + SchemeLabel->setText(QLabel::tr("Game scheme")); + WeaponsLayout->addWidget(SchemeLabel, 1, 0); - SchemeEdit = new QPushButton(groupWeapons); - SchemeEdit->setWhatsThis(tr("Edit scheme")); - SchemeEdit->setIconSize(pmEdit.size()); - SchemeEdit->setIcon(pmEdit); - SchemeEdit->setMaximumWidth(pmEdit.width() + 6); - WeaponsLayout->addWidget(SchemeEdit, 1, 3); + SchemesName = new QComboBox(groupWeapons); + WeaponsLayout->addWidget(SchemesName, 1, 1); - SchemeDelete = new QPushButton(groupWeapons); - SchemeDelete->setWhatsThis(tr("Delete scheme")); - SchemeDelete->setIconSize(pmDelete.size()); - SchemeDelete->setIcon(pmDelete); - SchemeDelete->setMaximumWidth(pmDelete.width() + 6); - WeaponsLayout->addWidget(SchemeDelete, 1, 4); + SchemeNew = new QPushButton(groupWeapons); + SchemeNew->setWhatsThis(tr("New scheme")); + SchemeNew->setIconSize(pmNew.size()); + SchemeNew->setIcon(pmNew); + SchemeNew->setMaximumWidth(pmNew.width() + 6); + WeaponsLayout->addWidget(SchemeNew, 1, 2); - QLabel* WeaponLabel = new QLabel(groupWeapons); - WeaponLabel->setText(QLabel::tr("Weapons")); - WeaponsLayout->addWidget(WeaponLabel, 2, 0); - - WeaponsName = new QComboBox(groupWeapons); - WeaponsLayout->addWidget(WeaponsName, 2, 1); - - WeaponNew = new QPushButton(groupWeapons); - WeaponNew->setWhatsThis(tr("New weapon set")); - WeaponNew->setIconSize(pmNew.size()); - WeaponNew->setIcon(pmNew); - WeaponNew->setMaximumWidth(pmNew.width() + 6); - WeaponsLayout->addWidget(WeaponNew, 2, 2); + SchemeEdit = new QPushButton(groupWeapons); + SchemeEdit->setWhatsThis(tr("Edit scheme")); + SchemeEdit->setIconSize(pmEdit.size()); + SchemeEdit->setIcon(pmEdit); + SchemeEdit->setMaximumWidth(pmEdit.width() + 6); + WeaponsLayout->addWidget(SchemeEdit, 1, 3); - WeaponEdit = new QPushButton(groupWeapons); - WeaponEdit->setWhatsThis(tr("Edit weapon set")); - WeaponEdit->setIconSize(pmEdit.size()); - WeaponEdit->setIcon(pmEdit); - WeaponEdit->setMaximumWidth(pmEdit.width() + 6); - WeaponsLayout->addWidget(WeaponEdit, 2, 3); + SchemeDelete = new QPushButton(groupWeapons); + SchemeDelete->setWhatsThis(tr("Delete scheme")); + SchemeDelete->setIconSize(pmDelete.size()); + SchemeDelete->setIcon(pmDelete); + SchemeDelete->setMaximumWidth(pmDelete.width() + 6); + WeaponsLayout->addWidget(SchemeDelete, 1, 4); - WeaponDelete = new QPushButton(groupWeapons); - WeaponDelete->setWhatsThis(tr("Delete weapon set")); - WeaponDelete->setIconSize(pmDelete.size()); - WeaponDelete->setIcon(pmDelete); - WeaponDelete->setMaximumWidth(pmDelete.width() + 6); - WeaponsLayout->addWidget(WeaponDelete, 2, 4); + QLabel* WeaponLabel = new QLabel(groupWeapons); + WeaponLabel->setText(QLabel::tr("Weapons")); + WeaponsLayout->addWidget(WeaponLabel, 2, 0); - WeaponTooltip = new QCheckBox(this); - WeaponTooltip->setText(QCheckBox::tr("Show ammo menu tooltips")); - WeaponsLayout->addWidget(WeaponTooltip, 3, 0, 1, 4); - - gbTBLayout->addWidget(groupWeapons, 1, 0); - } + WeaponsName = new QComboBox(groupWeapons); + WeaponsLayout->addWidget(WeaponsName, 2, 1); - { - IconedGroupBox* groupMisc = new IconedGroupBox(this); - //groupMisc->setContentTopPadding(0); - groupMisc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding); - groupMisc->setIcon(QIcon(":/res/miscicon.png")); - //groupMisc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - groupMisc->setTitle(QGroupBox::tr("Misc")); - QGridLayout * MiscLayout = new QGridLayout(groupMisc); + WeaponNew = new QPushButton(groupWeapons); + WeaponNew->setWhatsThis(tr("New weapon set")); + WeaponNew->setIconSize(pmNew.size()); + WeaponNew->setIcon(pmNew); + WeaponNew->setMaximumWidth(pmNew.width() + 6); + WeaponsLayout->addWidget(WeaponNew, 2, 2); - // Label for "Language" - QLabel *labelLanguage = new QLabel(groupMisc); - labelLanguage->setText(QLabel::tr("Locale") + " *"); - MiscLayout->addWidget(labelLanguage, 0, 0); + WeaponEdit = new QPushButton(groupWeapons); + WeaponEdit->setWhatsThis(tr("Edit weapon set")); + WeaponEdit->setIconSize(pmEdit.size()); + WeaponEdit->setIcon(pmEdit); + WeaponEdit->setMaximumWidth(pmEdit.width() + 6); + WeaponsLayout->addWidget(WeaponEdit, 2, 3); - // List of installed languages - CBLanguage = new QComboBox(groupMisc); - QDir tmpdir; - tmpdir.cd(cfgdir->absolutePath()); - tmpdir.cd("Data/Locale"); - tmpdir.setFilter(QDir::Files); - QStringList locs = tmpdir.entryList(QStringList("hedgewars_*.qm")); - CBLanguage->addItem(QComboBox::tr("(System default)"), QString("")); - for(int i = 0; i < locs.count(); i++) - { - QLocale loc(locs[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1")); - CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name()); + WeaponDelete = new QPushButton(groupWeapons); + WeaponDelete->setWhatsThis(tr("Delete weapon set")); + WeaponDelete->setIconSize(pmDelete.size()); + WeaponDelete->setIcon(pmDelete); + WeaponDelete->setMaximumWidth(pmDelete.width() + 6); + WeaponsLayout->addWidget(WeaponDelete, 2, 4); + + WeaponTooltip = new QCheckBox(this); + WeaponTooltip->setText(QCheckBox::tr("Show ammo menu tooltips")); + WeaponsLayout->addWidget(WeaponTooltip, 3, 0, 1, 4); + + page1Layout->addWidget(groupWeapons, 1, 0); } - tmpdir.cd(datadir->absolutePath()); - tmpdir.cd("Locale"); - tmpdir.setFilter(QDir::Files); - QStringList tmplist = tmpdir.entryList(QStringList("hedgewars_*.qm")); - for(int i = 0; i < tmplist.count(); i++) { - if (locs.contains(tmplist[i])) continue; - QLocale loc(tmplist[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1")); - CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name()); + IconedGroupBox* groupMisc = new IconedGroupBox(this); + //groupMisc->setContentTopPadding(0); + groupMisc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding); + groupMisc->setIcon(QIcon(":/res/miscicon.png")); + //groupMisc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + groupMisc->setTitle(QGroupBox::tr("Misc")); + QGridLayout * MiscLayout = new QGridLayout(groupMisc); + + // Label for "Language" + QLabel *labelLanguage = new QLabel(groupMisc); + labelLanguage->setText(QLabel::tr("Locale") + " *"); + MiscLayout->addWidget(labelLanguage, 0, 0); + + // List of installed languages + CBLanguage = new QComboBox(groupMisc); + QDir tmpdir; + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Locale"); + tmpdir.setFilter(QDir::Files); + QStringList locs = tmpdir.entryList(QStringList("hedgewars_*.qm")); + CBLanguage->addItem(QComboBox::tr("(System default)"), QString("")); + for(int i = 0; i < locs.count(); i++) + { + QLocale loc(locs[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1")); + CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name()); + } + + tmpdir.cd(datadir->absolutePath()); + tmpdir.cd("Locale"); + tmpdir.setFilter(QDir::Files); + QStringList tmplist = tmpdir.entryList(QStringList("hedgewars_*.qm")); + for(int i = 0; i < tmplist.count(); i++) + { + if (locs.contains(tmplist[i])) continue; + QLocale loc(tmplist[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1")); + CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name()); + } + + MiscLayout->addWidget(CBLanguage, 0, 1); + + // Label and field for net nick + labelNN = new QLabel(groupMisc); + labelNN->setText(QLabel::tr("Nickname")); + MiscLayout->addWidget(labelNN, 1, 0); + + editNetNick = new QLineEdit(groupMisc); + editNetNick->setMaxLength(20); + editNetNick->setText(QLineEdit::tr("anonymous")); + MiscLayout->addWidget(editNetNick, 1, 1); + + // checkbox and field for password + CBSavePassword = new QCheckBox(groupMisc); + CBSavePassword->setText(QCheckBox::tr("Save password")); + MiscLayout->addWidget(CBSavePassword, 2, 0); + + editNetPassword = new QLineEdit(groupMisc); + editNetPassword->setEchoMode(QLineEdit::Password); + MiscLayout->addWidget(editNetPassword, 2, 1); + + CBNameWithDate = new QCheckBox(groupMisc); + CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name")); + MiscLayout->addWidget(CBNameWithDate, 5, 0, 1, 2); + + BtnAssociateFiles = new QPushButton(groupMisc); + BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions")); + BtnAssociateFiles->setVisible(!custom_data && !custom_config); + MiscLayout->addWidget(BtnAssociateFiles, 6, 0, 1, 2); + + #ifdef __APPLE__ + #ifdef SPARKLE_ENABLED + CBAutoUpdate = new QCheckBox(groupMisc); + CBAutoUpdate->setText(QCheckBox::tr("Check for updates at startup")); + MiscLayout->addWidget(CBAutoUpdate, 7, 0, 1, 3); + #endif + #endif + page1Layout->addWidget(groupMisc, 2, 0); } - MiscLayout->addWidget(CBLanguage, 0, 1); + { + AGGroupBox = new IconedGroupBox(this); + //AGGroupBox->setContentTopPadding(0); + AGGroupBox->setIcon(QIcon(":/res/graphicsicon.png")); + //AGGroupBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + AGGroupBox->setTitle(QGroupBox::tr("Audio/Graphic options")); + + QVBoxLayout * GBAlayout = new QVBoxLayout(AGGroupBox); + QHBoxLayout * GBAreslayout = new QHBoxLayout(0); + QHBoxLayout * GBAstereolayout = new QHBoxLayout(0); + QHBoxLayout * GBAqualayout = new QHBoxLayout(0); - // Label and field for net nick - labelNN = new QLabel(groupMisc); - labelNN->setText(QLabel::tr("Nickname")); - MiscLayout->addWidget(labelNN, 1, 0); + CBFrontendFullscreen = new QCheckBox(AGGroupBox); + CBFrontendFullscreen->setText(QCheckBox::tr("Frontend fullscreen")); + GBAlayout->addWidget(CBFrontendFullscreen); + + CBFrontendEffects = new QCheckBox(AGGroupBox); + CBFrontendEffects->setText(QCheckBox::tr("Frontend effects")); + GBAlayout->addWidget(CBFrontendEffects); + + CBEnableFrontendSound = new QCheckBox(AGGroupBox); + CBEnableFrontendSound->setText(QCheckBox::tr("Enable frontend sounds")); + GBAlayout->addWidget(CBEnableFrontendSound); + + CBEnableFrontendMusic = new QCheckBox(AGGroupBox); + CBEnableFrontendMusic->setText(QCheckBox::tr("Enable frontend music")); + GBAlayout->addWidget(CBEnableFrontendMusic); - editNetNick = new QLineEdit(groupMisc); - editNetNick->setMaxLength(20); - editNetNick->setText(QLineEdit::tr("anonymous")); - MiscLayout->addWidget(editNetNick, 1, 1); + QFrame * hr = new QFrame(AGGroupBox); + hr->setFrameStyle(QFrame::HLine); + hr->setLineWidth(3); + hr->setFixedHeight(10); + GBAlayout->addWidget(hr); + + QLabel * resolution = new QLabel(AGGroupBox); + resolution->setText(QLabel::tr("Resolution")); + GBAreslayout->addWidget(resolution); + + CBResolution = new QComboBox(AGGroupBox); + GBAreslayout->addWidget(CBResolution); + GBAlayout->addLayout(GBAreslayout); - // checkbox and field for password - CBSavePassword = new QCheckBox(groupMisc); - CBSavePassword->setText(QCheckBox::tr("Save password")); - MiscLayout->addWidget(CBSavePassword, 2, 0); + CBFullscreen = new QCheckBox(AGGroupBox); + CBFullscreen->setText(QCheckBox::tr("Fullscreen")); + GBAreslayout->addWidget(CBFullscreen); + + QLabel * quality = new QLabel(AGGroupBox); + quality->setText(QLabel::tr("Quality")); + quality->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + GBAqualayout->addWidget(quality); + + SLQuality = new QSlider(Qt::Horizontal, AGGroupBox); + SLQuality->setTickPosition(QSlider::TicksBelow); + SLQuality->setMaximum(5); + SLQuality->setMinimum(0); + SLQuality->setFixedWidth(150); + GBAqualayout->addWidget(SLQuality); + GBAlayout->addLayout(GBAqualayout); + + QLabel * stereo = new QLabel(AGGroupBox); + stereo->setText(QLabel::tr("Stereo rendering")); + GBAstereolayout->addWidget(stereo); - editNetPassword = new QLineEdit(groupMisc); - editNetPassword->setEchoMode(QLineEdit::Password); - MiscLayout->addWidget(editNetPassword, 2, 1); + CBStereoMode = new QComboBox(AGGroupBox); + CBStereoMode->addItem(QComboBox::tr("Disabled")); + CBStereoMode->addItem(QComboBox::tr("Red/Cyan")); + CBStereoMode->addItem(QComboBox::tr("Cyan/Red")); + CBStereoMode->addItem(QComboBox::tr("Red/Blue")); + CBStereoMode->addItem(QComboBox::tr("Blue/Red")); + CBStereoMode->addItem(QComboBox::tr("Red/Green")); + CBStereoMode->addItem(QComboBox::tr("Green/Red")); + CBStereoMode->addItem(QComboBox::tr("Side-by-side")); + CBStereoMode->addItem(QComboBox::tr("Top-Bottom")); + CBStereoMode->addItem(QComboBox::tr("Wiggle")); + CBStereoMode->addItem(QComboBox::tr("Red/Cyan grayscale")); + CBStereoMode->addItem(QComboBox::tr("Cyan/Red grayscale")); + CBStereoMode->addItem(QComboBox::tr("Red/Blue grayscale")); + CBStereoMode->addItem(QComboBox::tr("Blue/Red grayscale")); + CBStereoMode->addItem(QComboBox::tr("Red/Green grayscale")); + CBStereoMode->addItem(QComboBox::tr("Green/Red grayscale")); - CBNameWithDate = new QCheckBox(groupMisc); - CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name")); - MiscLayout->addWidget(CBNameWithDate, 5, 0, 1, 2); + GBAstereolayout->addWidget(CBStereoMode); + GBAlayout->addLayout(GBAstereolayout); + + QHBoxLayout * GBAfpslayout = new QHBoxLayout(0); + QLabel * maxfps = new QLabel(AGGroupBox); + maxfps->setText(QLabel::tr("FPS limit")); + GBAfpslayout->addWidget(maxfps); + GBAlayout->addLayout(GBAfpslayout); + fpsedit = new FPSEdit(AGGroupBox); + GBAfpslayout->addWidget(fpsedit); + + CBShowFPS = new QCheckBox(AGGroupBox); + CBShowFPS->setText(QCheckBox::tr("Show FPS")); + GBAfpslayout->addWidget(CBShowFPS); - BtnAssociateFiles = new QPushButton(groupMisc); - BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions")); - BtnAssociateFiles->setVisible(!custom_data && !custom_config); - MiscLayout->addWidget(BtnAssociateFiles, 6, 0, 1, 2); + hr = new QFrame(AGGroupBox); + hr->setFrameStyle(QFrame::HLine); + hr->setLineWidth(3); + hr->setFixedHeight(10); + GBAlayout->addWidget(hr); + + QGridLayout * GBAvollayout = new QGridLayout(); + QLabel * vol = new QLabel(AGGroupBox); + vol->setText(QLabel::tr("Initial sound volume")); + GBAvollayout->addWidget(vol, 0, 0, 1, 2); + GBAlayout->addLayout(GBAvollayout); + volumeBox = new QSpinBox(AGGroupBox); + volumeBox->setRange(0, 100); + volumeBox->setSingleStep(5); + GBAvollayout->addWidget(volumeBox, 0, 2); -#ifdef __APPLE__ -#ifdef SPARKLE_ENABLED - CBAutoUpdate = new QCheckBox(groupMisc); - CBAutoUpdate->setText(QCheckBox::tr("Check for updates at startup")); - MiscLayout->addWidget(CBAutoUpdate, 7, 0, 1, 3); -#endif -#endif - gbTBLayout->addWidget(groupMisc, 2, 0); + CBEnableSound = new QCheckBox(AGGroupBox); + CBEnableSound->setText(QCheckBox::tr("Enable sound")); + GBAvollayout->addWidget(CBEnableSound, 1, 0, 1, 1); + + CBEnableMusic = new QCheckBox(AGGroupBox); + CBEnableMusic->setText(QCheckBox::tr("Enable music")); + GBAvollayout->addWidget(CBEnableMusic, 1, 1, 1, 2); + + GBAvollayout->setSizeConstraint(QLayout::SetMinimumSize); + + hr = new QFrame(AGGroupBox); + hr->setFrameStyle(QFrame::HLine); + hr->setLineWidth(3); + hr->setFixedHeight(10); + GBAlayout->addWidget(hr); + + CBAltDamage = new QCheckBox(AGGroupBox); + CBAltDamage->setText(QCheckBox::tr("Alternative damage show")); + GBAlayout->addWidget(CBAltDamage); + + page1Layout->addWidget(AGGroupBox, 0, 1, 3, 1); + } } - { - AGGroupBox = new IconedGroupBox(this); - //AGGroupBox->setContentTopPadding(0); - AGGroupBox->setIcon(QIcon(":/res/graphicsicon.png")); - //AGGroupBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - AGGroupBox->setTitle(QGroupBox::tr("Audio/Graphic options")); - - QVBoxLayout * GBAlayout = new QVBoxLayout(AGGroupBox); - QHBoxLayout * GBAreslayout = new QHBoxLayout(0); - QHBoxLayout * GBAstereolayout = new QHBoxLayout(0); - QHBoxLayout * GBAqualayout = new QHBoxLayout(0); - - CBFrontendFullscreen = new QCheckBox(AGGroupBox); - CBFrontendFullscreen->setText(QCheckBox::tr("Frontend fullscreen")); - GBAlayout->addWidget(CBFrontendFullscreen); - - CBFrontendEffects = new QCheckBox(AGGroupBox); - CBFrontendEffects->setText(QCheckBox::tr("Frontend effects")); - GBAlayout->addWidget(CBFrontendEffects); - - CBEnableFrontendSound = new QCheckBox(AGGroupBox); - CBEnableFrontendSound->setText(QCheckBox::tr("Enable frontend sounds")); - GBAlayout->addWidget(CBEnableFrontendSound); - - CBEnableFrontendMusic = new QCheckBox(AGGroupBox); - CBEnableFrontendMusic->setText(QCheckBox::tr("Enable frontend music")); - GBAlayout->addWidget(CBEnableFrontendMusic); + { // page 2 + QGridLayout * page2Layout = new QGridLayout(page2); - QFrame * hr = new QFrame(AGGroupBox); - hr->setFrameStyle(QFrame::HLine); - hr->setLineWidth(3); - hr->setFixedHeight(10); - GBAlayout->addWidget(hr); - - QLabel * resolution = new QLabel(AGGroupBox); - resolution->setText(QLabel::tr("Resolution")); - GBAreslayout->addWidget(resolution); - - CBResolution = new QComboBox(AGGroupBox); - GBAreslayout->addWidget(CBResolution); - GBAlayout->addLayout(GBAreslayout); + IconedGroupBox * gbColors = new IconedGroupBox(this); + //gbColors->setIcon(QIcon(":/res/teamicon.png")); + gbColors->setTitle(QGroupBox::tr("Custom colors")); + page2Layout->addWidget(gbColors, 0, 0, 1, 3); + QVBoxLayout * gbCLayout = new QVBoxLayout(gbColors); - CBFullscreen = new QCheckBox(AGGroupBox); - CBFullscreen->setText(QCheckBox::tr("Fullscreen")); - GBAreslayout->addWidget(CBFullscreen); - - QLabel * quality = new QLabel(AGGroupBox); - quality->setText(QLabel::tr("Quality")); - quality->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - GBAqualayout->addWidget(quality); + QSignalMapper * mapper = new QSignalMapper(this); - SLQuality = new QSlider(Qt::Horizontal, AGGroupBox); - SLQuality->setTickPosition(QSlider::TicksBelow); - SLQuality->setMaximum(5); - SLQuality->setMinimum(0); - SLQuality->setFixedWidth(150); - GBAqualayout->addWidget(SLQuality); - GBAlayout->addLayout(GBAqualayout); - - QLabel * stereo = new QLabel(AGGroupBox); - stereo->setText(QLabel::tr("Stereo rendering")); - GBAstereolayout->addWidget(stereo); + QStandardItemModel * model = DataManager::instance().colorsModel(); - CBStereoMode = new QComboBox(AGGroupBox); - CBStereoMode->addItem(QComboBox::tr("Disabled")); - CBStereoMode->addItem(QComboBox::tr("Red/Cyan")); - CBStereoMode->addItem(QComboBox::tr("Cyan/Red")); - CBStereoMode->addItem(QComboBox::tr("Red/Blue")); - CBStereoMode->addItem(QComboBox::tr("Blue/Red")); - CBStereoMode->addItem(QComboBox::tr("Red/Green")); - CBStereoMode->addItem(QComboBox::tr("Green/Red")); - CBStereoMode->addItem(QComboBox::tr("Side-by-side")); - CBStereoMode->addItem(QComboBox::tr("Top-Bottom")); - CBStereoMode->addItem(QComboBox::tr("Wiggle")); - CBStereoMode->addItem(QComboBox::tr("Red/Cyan grayscale")); - CBStereoMode->addItem(QComboBox::tr("Cyan/Red grayscale")); - CBStereoMode->addItem(QComboBox::tr("Red/Blue grayscale")); - CBStereoMode->addItem(QComboBox::tr("Blue/Red grayscale")); - CBStereoMode->addItem(QComboBox::tr("Red/Green grayscale")); - CBStereoMode->addItem(QComboBox::tr("Green/Red grayscale")); - - GBAstereolayout->addWidget(CBStereoMode); - GBAlayout->addLayout(GBAstereolayout); - - QHBoxLayout * GBAfpslayout = new QHBoxLayout(0); - QLabel * maxfps = new QLabel(AGGroupBox); - maxfps->setText(QLabel::tr("FPS limit")); - GBAfpslayout->addWidget(maxfps); - GBAlayout->addLayout(GBAfpslayout); - fpsedit = new FPSEdit(AGGroupBox); - GBAfpslayout->addWidget(fpsedit); - - CBShowFPS = new QCheckBox(AGGroupBox); - CBShowFPS->setText(QCheckBox::tr("Show FPS")); - GBAfpslayout->addWidget(CBShowFPS); + connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(onColorModelDataChanged(QModelIndex,QModelIndex))); + for(int i = 0; i < model->rowCount(); ++i) + { + QPushButton * btn = new QPushButton(this); + gbCLayout->addWidget(btn); + btn->setStyleSheet(QString("background: %1").arg(model->item(i)->data().value<QColor>().name())); + m_colorButtons.append(btn); + connect(btn, SIGNAL(clicked()), mapper, SLOT(map())); + mapper->setMapping(btn, i); + } - hr = new QFrame(AGGroupBox); - hr->setFrameStyle(QFrame::HLine); - hr->setLineWidth(3); - hr->setFixedHeight(10); - GBAlayout->addWidget(hr); - - QGridLayout * GBAvollayout = new QGridLayout(); - QLabel * vol = new QLabel(AGGroupBox); - vol->setText(QLabel::tr("Initial sound volume")); - GBAvollayout->addWidget(vol, 0, 0, 1, 2); - GBAlayout->addLayout(GBAvollayout); - volumeBox = new QSpinBox(AGGroupBox); - volumeBox->setRange(0, 100); - volumeBox->setSingleStep(5); - GBAvollayout->addWidget(volumeBox, 0, 2); - - CBEnableSound = new QCheckBox(AGGroupBox); - CBEnableSound->setText(QCheckBox::tr("Enable sound")); - GBAvollayout->addWidget(CBEnableSound, 1, 0, 1, 1); - - CBEnableMusic = new QCheckBox(AGGroupBox); - CBEnableMusic->setText(QCheckBox::tr("Enable music")); - GBAvollayout->addWidget(CBEnableMusic, 1, 1, 1, 2); - - GBAvollayout->setSizeConstraint(QLayout::SetMinimumSize); - - hr = new QFrame(AGGroupBox); - hr->setFrameStyle(QFrame::HLine); - hr->setLineWidth(3); - hr->setFixedHeight(10); - GBAlayout->addWidget(hr); - - CBAltDamage = new QCheckBox(AGGroupBox); - CBAltDamage->setText(QCheckBox::tr("Alternative damage show")); - GBAlayout->addWidget(CBAltDamage); - - gbTBLayout->addWidget(AGGroupBox, 0, 1, 3, 1); + connect(mapper, SIGNAL(mapped(int)), this, SLOT(colorButtonClicked(int))); } previousQuality = this->SLQuality->value(); @@ -499,3 +528,25 @@ CBTeamName->setVisible(enabled); LblNoEditTeam->setVisible(!enabled); } + +void PageOptions::colorButtonClicked(int i) +{ + if(i < 0 || i >= m_colorButtons.size()) + return; + + QPalette p = m_colorButtons[i]->palette(); + QColor c = QColorDialog::getColor(p.color(QPalette::Button)); + + if(c.isValid()) + { + DataManager::instance().colorsModel()->item(i)->setData(c); + m_colorButtons[i]->setStyleSheet(QString("background: %1").arg(c.name())); + } +} + +void PageOptions::onColorModelDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight) +{ + QStandardItemModel * model = DataManager::instance().colorsModel(); + + m_colorButtons[topLeft.row()]->setStyleSheet(QString("background: %1").arg(model->item(topLeft.row())->data().value<QColor>().name())); +} diff -r 763d3961400b -r 3c4b4cb40f40 QTfrontend/ui/page/pageoptions.h --- a/QTfrontend/ui/page/pageoptions.h Sat Aug 18 00:47:51 2012 +0200 +++ b/QTfrontend/ui/page/pageoptions.h Sat Aug 18 00:48:09 2012 +0200 @@ -23,6 +23,7 @@ class FPSEdit; class IconedGroupBox; +class QSignalMapper; class PageOptions : public AbstractPage { @@ -91,6 +92,7 @@ QPushButton *BtnNewTeam; QPushButton *BtnEditTeam; QPushButton *BtnDeleteTeam; + QList<QPushButton *> m_colorButtons; private slots: void forceFullscreen(int index); @@ -101,6 +103,8 @@ void requestEditSelectedTeam(); void requestDeleteSelectedTeam(); void savePwdChanged(int state); + void colorButtonClicked(int i); + void onColorModelDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight); }; #endif diff -r 763d3961400b -r 3c4b4cb40f40 QTfrontend/ui/widget/chatwidget.cpp --- a/QTfrontend/ui/widget/chatwidget.cpp Sat Aug 18 00:47:51 2012 +0200 +++ b/QTfrontend/ui/widget/chatwidget.cpp Sat Aug 18 00:48:09 2012 +0200 @@ -922,7 +922,7 @@ if(b) { chatNicks->insertAction(0, acKick); -// chatNicks->insertAction(0, acBan); + chatNicks->insertAction(0, acBan); } } diff -r 763d3961400b -r 3c4b4cb40f40 QTfrontend/ui/widget/teamselect.cpp --- a/QTfrontend/ui/widget/teamselect.cpp Sat Aug 18 00:47:51 2012 +0200 +++ b/QTfrontend/ui/widget/teamselect.cpp Sat Aug 18 00:48:09 2012 +0200 @@ -135,6 +135,11 @@ curPlayingTeams.erase(itPlay); break; } + else + { + qWarning() << QString("removeNetTeam: team '%1' was actually a local team!").arg(team.name()); + break; + } } emit setEnabledGameStart(curPlayingTeams.size()>1); } diff -r 763d3961400b -r 3c4b4cb40f40 gameServer/Actions.hs --- a/gameServer/Actions.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/gameServer/Actions.hs Sat Aug 18 00:48:09 2012 +0200 @@ -146,9 +146,14 @@ io $ infoM "Clients" (show ci ++ " quits: " ++ B.unpack msg) - processAction $ AnswerClients [chan] ["BYE", msg] when loggedIn $ processAction $ AnswerClients clientsChans ["LOBBY:LEFT", clNick, msg] + mapM processAction + [ + AnswerClients [chan] ["BYE", msg] + , ModifyClient (\c -> c{logonPassed = False}) -- this will effectively hide client from others while he isn't deleted from list + ] + s <- get put $! s{removedClients = ci `Set.insert` removedClients s} @@ -216,7 +221,7 @@ chans <- othersChans if master then - if gameProgress && playersNum > 1 then + if playersNum > 1 then mapM_ processAction [ChangeMaster, NoticeMessage AdminLeft, RemoveClientTeams ci, AnswerClients chans ["LEFT", clNick, msg]] else processAction RemoveRoom @@ -225,7 +230,7 @@ -- when not removing room ready <- client's isReady - when (not master || (gameProgress && playersNum > 1)) . io $ do + when (not master || playersNum > 1) . io $ do modifyRoom rnc (\r -> r{ playersIn = playersIn r - 1, readyPlayers = if ready then readyPlayers r - 1 else readyPlayers r @@ -418,11 +423,22 @@ processAction JoinLobby = do chan <- client's sendChan clientNick <- client's nick - (lobbyNicks, clientsChans) <- liftM (unzip . Prelude.map (nick &&& sendChan) . Prelude.filter logonPassed) $! allClientsS - mapM_ processAction $ - AnswerClients clientsChans ["LOBBY:JOINED", clientNick] - : AnswerClients [chan] ("LOBBY:JOINED" : clientNick : lobbyNicks) - : [ModifyClient (\cl -> cl{logonPassed = True}), SendServerMessage] + isAuthenticated <- liftM (not . B.null) $ client's webPassword + isAdmin <- client's isAdministrator + loggedInClients <- liftM (Prelude.filter logonPassed) $! allClientsS + let (lobbyNicks, clientsChans) = unzip . L.map (nick &&& sendChan) $ loggedInClients + let authenticatedNicks = L.map nick . L.filter (not . B.null . webPassword) $ loggedInClients + let adminsNicks = L.map nick . L.filter isAdministrator $ loggedInClients + let clFlags = B.concat . L.concat $ [["u" | isAuthenticated], ["a" | isAdmin]] + mapM_ processAction . concat $ [ + [AnswerClients clientsChans ["LOBBY:JOINED", clientNick]] + , [AnswerClients [chan] ("LOBBY:JOINED" : clientNick : lobbyNicks)] + , [AnswerClients [chan] ("CLIENT_FLAGS" : "+u" : authenticatedNicks) | not $ null authenticatedNicks] + , [AnswerClients [chan] ("CLIENT_FLAGS" : "+a" : adminsNicks) | not $ null adminsNicks] + , [AnswerClients (chan : clientsChans) ["CLIENT_FLAGS", B.concat["+" , clFlags], clientNick] | not $ B.null clFlags] + , [ModifyClient (\cl -> cl{logonPassed = True})] + , [SendServerMessage] + ] processAction (KickClient kickId) = do @@ -453,9 +469,9 @@ processAction BanList = do ch <- client's sendChan - bans <- gets (bans . serverInfo) + bans <- gets (B.pack . unlines . map show . bans . serverInfo) processAction $ - AnswerClients [ch] ["BANLIST", B.pack $ show bans] + AnswerClients [ch] ["BANLIST", bans] @@ -522,9 +538,11 @@ where kickTimeouted rnc ci = do pq <- io $ client'sM rnc pingsQueue ci - when (pq > 0) $ + when (pq > 0) $ do withStateT (\as -> as{clientIndex = Just ci}) $ processAction (ByeClient "Ping timeout") + when (pq > 1) $ + processAction $ DeleteClient ci -- smth went wrong with client io threads, issue DeleteClient here processAction StatsAction = do diff -r 763d3961400b -r 3c4b4cb40f40 gameServer/CoreTypes.hs --- a/gameServer/CoreTypes.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/gameServer/CoreTypes.hs Sat Aug 18 00:48:09 2012 +0200 @@ -94,6 +94,7 @@ readyPlayers :: !Int, isRestrictedJoins :: Bool, isRestrictedTeams :: Bool, + roomBansList :: [B.ByteString], mapParams :: Map.Map B.ByteString B.ByteString, params :: Map.Map B.ByteString [B.ByteString] } @@ -111,6 +112,7 @@ 0 False False + [] ( Map.fromList $ Prelude.zipWith (,) ["MAP", "MAPGEN", "MAZE_SIZE", "SEED", "TEMPLATE"] diff -r 763d3961400b -r 3c4b4cb40f40 gameServer/HWProtoInRoomState.hs --- a/gameServer/HWProtoInRoomState.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/gameServer/HWProtoInRoomState.hs Sat Aug 18 00:48:09 2012 +0200 @@ -278,6 +278,14 @@ where engineMsg cl = toEngineMsg $ B.concat ["b", nick cl, "(team): ", msg, "\x20\x20"] +handleCmd_inRoom ["BAN", banNick] = do + (_, rnc) <- ask + maybeClientId <- clientByNick banNick + let banId = fromJust maybeClientId + master <- liftM isMaster thisClient + return [ModifyRoom (\r -> r{roomBansList = (host $ rnc `client` banId) : roomBansList r}) | master && isJust maybeClientId] + + handleCmd_inRoom ["LIST"] = return [] -- for old clients (<= 0.9.17) handleCmd_inRoom (s:_) = return [ProtocolError $ "Incorrect command '" `B.append` s `B.append` "' (state: in room)"] diff -r 763d3961400b -r 3c4b4cb40f40 gameServer/HWProtoLobbyState.hs --- a/gameServer/HWProtoLobbyState.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/gameServer/HWProtoLobbyState.hs Sat Aug 18 00:48:09 2012 +0200 @@ -70,11 +70,14 @@ let jRoomClients = map (client irnc) $ roomClients irnc jRI let nicks = map nick jRoomClients let chans = map sendChan (cl : jRoomClients) + let isBanned = host cl `elem` roomBansList jRoom return $ if isNothing maybeRI || not sameProto then [Warning "No such room"] else if isRestrictedJoins jRoom then [Warning "Joining restricted"] + else if isBanned then + [Warning "You are banned in this room"] else if roomPassword /= password jRoom then [NoticeMessage WrongPassword] else @@ -183,7 +186,7 @@ handleCmd_lobby ["RESTART_SERVER"] = do cl <- thisClient - return [RestartServer] + return [RestartServer | isAdministrator cl] handleCmd_lobby _ = return [ProtocolError "Incorrect command (state: in lobby)"] diff -r 763d3961400b -r 3c4b4cb40f40 gameServer/ServerCore.hs --- a/gameServer/ServerCore.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/gameServer/ServerCore.hs Sat Aug 18 00:48:09 2012 +0200 @@ -43,7 +43,7 @@ ClientMessage (ci, cmd) -> do liftIO $ debugM "Clients" $ show ci ++ ": " ++ show cmd - + removed <- gets removedClients unless (ci `Set.member` removed) $ do modify (\s -> s{clientIndex = Just ci}) @@ -75,8 +75,6 @@ (fromJust $ serverSocket si) (coreChan si) - return () - _ <- forkIO $ timerLoop 0 $ coreChan si startDBConnection si diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/GSHandlers.inc Sat Aug 18 00:48:09 2012 +0200 @@ -610,11 +610,10 @@ // move back to cloud layer if yy > cWaterLine then move:= true - else if ((yy and LAND_HEIGHT_MASK) <> 0) - or (xx > LAND_WIDTH + 512) or (xx < -512) then + else if (xx > snowRight) or (xx < snowLeft) then move:=true // Solid pixel encountered - else if ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then + else if ((yy and LAND_HEIGHT_MASK) = 0) and ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then begin lf:= Land[yy, xx] and (lfObject or lfBasic or lfIndestructible); // If there's room below keep falling @@ -724,8 +723,8 @@ exit end; Gear^.Pos:= 0; - Gear^.X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512); - Gear^.Y:= int2hwFloat(750+(GetRandom(50)-25)); + Gear^.X:= int2hwFloat(GetRandom(snowRight-snowLeft)+snowLeft); + Gear^.Y:= int2hwFloat(LAND_HEIGHT-1300+(GetRandom(50)-25)); Gear^.State:= Gear^.State or gstInvisible; end end; @@ -1817,7 +1816,7 @@ Message := Message and (not gmAttack) end; DeleteGear(Gear); - exit; + exit; end; if CheckGearDrowning(HHGear) then DeleteGear(Gear) end; @@ -3685,10 +3684,6 @@ Gear^.X := HHGear^.X; Gear^.Y := HHGear^.Y; - // For some reason I need to reapply followgear here, something else grabs it otherwise. - // This is probably not needed anymore - if not CurrentTeam^.ExtDriven then - FollowGear := HHGear; if not isUnderWater and hasBorder and ((HHGear^.X < _0) or (hwRound(HHGear^.X) > LAND_WIDTH)) then @@ -4788,7 +4783,7 @@ Gear^.Timer:= Gear^.Tag end; - if (Gear^.Health = 0) or (HHGear^.Damage <> 0) then + if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) then begin DeleteGear(Gear); AfterAttack @@ -4864,7 +4859,7 @@ Gear^.Timer:= Gear^.Tag end; - if (Gear^.Health = 0) or (HHGear^.Damage <> 0) or ((HHGear^.Message and gmAttack) <> 0) then + if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) or ((HHGear^.Message and gmAttack) <> 0) then begin HHGear^.Message:= HHGear^.Message and (not gmAttack); DeleteGear(Gear); diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/SDLh.pas --- a/hedgewars/SDLh.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/SDLh.pas Sat Aug 18 00:48:09 2012 +0200 @@ -410,12 +410,10 @@ PSDL_Color = ^TSDL_Color; TSDL_Color = record - case Byte of - 0: ( r: Byte; - g: Byte; - b: Byte; - unused: Byte; ); - 1: ( value: LongWord; ); + r: Byte; + g: Byte; + b: Byte; + unused: Byte; end; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/hwengine.pas Sat Aug 18 00:48:09 2012 +0200 @@ -57,6 +57,9 @@ gsLandGen: begin GenMap; + uLandTexture.initModule; + UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false); + uAILandMarks.initModule; ParseCommand('sendlanddigest', true); GameState:= gsStart; end; @@ -401,7 +404,6 @@ uAI.initModule; //uAIActions does not need initialization //uAIAmmoTests does not need initialization - uAILandMarks.initModule; uAIMisc.initModule; uAmmos.initModule; uChat.initModule; @@ -413,7 +415,6 @@ //uLandGraphics does not need initialization //uLandObjects does not need initialization //uLandTemplates does not need initialization - uLandTexture.initModule; //uLocale does not need initialization uRandom.initModule; uScript.initModule; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uAI.pas --- a/hedgewars/uAI.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uAI.pas Sat Aug 18 00:48:09 2012 +0200 @@ -178,9 +178,12 @@ begin AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0); AddAction(BestActions, aia_attack, aim_release, 1, 0, 0); - - AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0); - AddAction(BestActions, aia_Down, aim_release, 32, 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); @@ -274,7 +277,8 @@ break; if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support - if Push(ticks, Actions, AltMe, Me^.Message) then + // check if we could go backwards and maybe ljump over a gap after this hjump + if Push(ticks, Actions, AltMe, Me^.Message xor 3) then begin with Stack.States[Pred(Stack.Count)] do begin @@ -291,9 +295,8 @@ else AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0); end; - - // check if we could go backwards and maybe ljump over a gap after this hjump - Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message xor 3) + // but first check walking forward + Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message) end; if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support begin diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uAIAmmoTests.pas Sat Aug 18 00:48:09 2012 +0200 @@ -47,6 +47,7 @@ function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; @@ -84,7 +85,7 @@ //(proc: @TestTeleport; flags: amtest_OnTurn), // amTeleport (proc: nil; flags: 0), // amSwitch (proc: @TestMortar; flags: 0), // amMortar - (proc: nil; flags: 0), // amKamikaze + (proc: @TestKamikaze; flags: 0), // amKamikaze (proc: @TestCake; flags: amtest_OnTurn or amtest_NoTarget), // amCake (proc: nil; flags: 0), // amSeduction (proc: @TestWatermelon; flags: 0), // amWatermelon @@ -167,7 +168,7 @@ EX:= trunc(x); EY:= trunc(y); - if Me^.Hedgehog^.BotLevel = 1 then + if Level = 1 then value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else value:= RateExplosion(Me, EX, EY, 101); if value = 0 then @@ -330,7 +331,7 @@ EX:= trunc(x); EY:= trunc(y); if t < 50 then - if Me^.Hedgehog^.BotLevel = 1 then + if Level = 1 then Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else Score:= RateExplosion(Me, EX, EY, 101) else @@ -361,12 +362,12 @@ t: LongInt; begin valueResult:= BadTurn; -TestTime:= 0; +TestTime:= 500; ap.ExplR:= 0; meX:= hwFloat2Float(Me^.X); meY:= hwFloat2Float(Me^.Y); repeat - inc(TestTime, 1000); + inc(TestTime, 900); // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster if meX<Targ.X then Vx:= ((Targ.X+10) - meX) / (TestTime + tDelta) @@ -398,14 +399,14 @@ begin ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15); - ap.Time:= TestTime; + ap.Time:= TestTime div 1000 * 1000; ap.ExplR:= 90; ap.ExplX:= EX; ap.ExplY:= EY; valueResult:= Score end; end -until (TestTime = 4000); +until (TestTime = 4100); TestClusterBomb:= valueResult end; @@ -418,12 +419,12 @@ t: LongInt; begin valueResult:= BadTurn; -TestTime:= 0; +TestTime:= 500; ap.ExplR:= 0; meX:= hwFloat2Float(Me^.X); meY:= hwFloat2Float(Me^.Y); repeat - inc(TestTime, 1000); + inc(TestTime, 900); Vx:= (Targ.X - meX) / (TestTime + tDelta); Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Y-50) - meY) / (TestTime + tDelta); r:= sqr(Vx)+sqr(Vy); @@ -452,14 +453,14 @@ begin ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15); - ap.Time:= TestTime; + ap.Time:= TestTime div 1000 * 1000; ap.ExplR:= 300; ap.ExplX:= EX; ap.ExplY:= EY; valueResult:= Score end; end -until (TestTime = 4000); +until (TestTime = 4100); TestWatermelon:= valueResult end; @@ -600,19 +601,22 @@ d: Longword; fallDmg, valueResult: LongInt; begin -if Me^.Hedgehog^.BotLevel > 3 then exit(BadTurn); +if Level > 3 then exit(BadTurn); dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; Level:= Level; // avoid compiler hint ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; + x:= hwFloat2Float(Me^.X); y:= hwFloat2Float(Me^.Y); + if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then begin TestDesertEagle:= BadTurn; exit(BadTurn); end; + t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y)); Vx:= (Targ.X - x) * t; Vy:= (Targ.Y - y) * t; @@ -650,7 +654,7 @@ d: Longword; fallDmg, valueResult: LongInt; begin -if Me^.Hedgehog^.BotLevel > 3 then exit(BadTurn); +if Level > 3 then exit(BadTurn); dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; Level:= Level; // avoid compiler hint ap.ExplR:= 0; @@ -700,9 +704,9 @@ x, y, trackFall: LongInt; dx, dy: real; begin - if Me^.Hedgehog^.BotLevel < 3 then trackFall:= afTrackFall + if Level < 3 then trackFall:= afTrackFall else trackFall:= 0; - Level:= Level; // avoid compiler hint + ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; @@ -749,9 +753,9 @@ var valueResult, v1, v2, i: LongInt; x, y, trackFall: LongInt; begin - if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall + if Level = 1 then trackFall:= afTrackFall else trackFall:= 0; - Level:= Level; // avoid compiler hint + ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; @@ -805,9 +809,9 @@ var valueResult, v1, v2: LongInt; x, y, trackFall: LongInt; begin - if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall + if Level = 1 then trackFall:= afTrackFall else trackFall:= 0; - Level:= Level; // avoid compiler hint + ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; @@ -822,7 +826,7 @@ , 30, 30, 25 , -1, -0.8, trackFall or afSetSkip); v1:= v1 + - RateShove(Me, x, y + RateShove(Me, x - 2, y , 30, 30, 25 , -1, -0.8, trackFall); // now try opposite direction @@ -830,7 +834,7 @@ , 30, 30, 25 , 1, -0.8, trackFall or afSetSkip); v2:= v2 + - RateShove(Me, x, y + RateShove(Me, x + 2, y , 30, 30, 25 , 1, -0.8, trackFall); @@ -854,6 +858,90 @@ TestWhip:= valueResult; end; +function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +const step = 8; +var valueResult, i, v, tx: LongInt; + trackFall: LongInt; + t, d, x, y, dx, dy, cx: real; +begin + ap.ExplR:= 0; + ap.Time:= 0; + ap.Power:= 1; + + if Level = 1 then + trackFall:= afTrackFall + else if Level = 2 then + trackFall:= 0 + else + exit(BadTurn); + + valueResult:= 0; + v:= 0; + + x:= hwFloat2Float(Me^.X); + y:= hwFloat2Float(Me^.Y); + d:= sqrt(sqr(Targ.X - x) + sqr(Targ.Y - y)); + if d < 10 then + begin + dx:= 0; + dy:= 8; + ap.Angle:= 2048 + end + else + begin + t:= step / d; + dx:= (Targ.X - x) * t; + dy:= (Targ.Y - y) * t; + + 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 + + RateShove(Me, trunc(x), trunc(y) + , 30, 30, 25 + , cx, -0.9, trackFall or afSetSkip); + + x:= x + dx; + y:= y + dy; + end; + if dx = 0 then + begin + x:= hwFloat2Float(Me^.X); + y:= hwFloat2Float(Me^.Y); + tx:= trunc(x); + v:= RateShove(Me, tx, trunc(y) + , 30, 30, 25 + , -cx, -0.9, trackFall); + for i:= 1 to 512 div step - 2 do + begin + y:= y + dy; + v:= v + + RateShove(Me, tx, trunc(y) + , 30, 30, 25 + , -cx, -0.9, trackFall or afSetSkip); + end + end; + if v > valueResult then + begin + ap.Angle:= -2048; + valueResult:= v + end; + + v:= RateShove(Me, trunc(x), trunc(y) + , 30, 30, 25 + , cx, -0.9, trackFall); + valueResult:= valueResult + v - KillScore * friendlyfactor div 100 * 1024; + + if v < 65536 then + inc(valueResult, RateExplosion(Me, trunc(x), trunc(y), 30)); + + TestKamikaze:= valueResult; +end; + function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var rate: LongInt; begin @@ -1008,7 +1096,8 @@ x, y, trackFall: LongInt; cake: TGear; begin - Level:= Level; // avoid compiler hint + if (Level > 2) then + exit(BadTurn); ap.ExplR:= 0; ap.Time:= 0; ap.Power:= BadTurn; // use it as max score value in checkCakeWalk diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uAILandMarks.pas --- a/hedgewars/uAILandMarks.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uAILandMarks.pas Sat Aug 18 00:48:09 2012 +0200 @@ -1,71 +1,71 @@ -unit uAILandMarks; - -interface -const markWasHere = $01; - -procedure addMark(X, Y: LongInt; mark: byte); -function checkMark(X, Y: LongInt; mark: byte) : boolean; -procedure clearAllMarks; -procedure clearMarks(mark: byte); - -procedure initModule; -procedure freeModule; - -implementation -uses uVariables; - -const gr = 2; - -var marks: array of array of byte; - WIDTH, HEIGHT: Longword; - -procedure addMark(X, Y: LongInt; mark: byte); -begin - if((X and LAND_WIDTH_MASK) = 0) and ((Y and LAND_HEIGHT_MASK) = 0) then - begin - X:= X shr gr; - Y:= Y shr gr; - marks[Y, X]:= marks[Y, X] or mark - end -end; - -function checkMark(X, Y: LongInt; mark: byte) : boolean; -begin - checkMark:= ((X and LAND_WIDTH_MASK) = 0) - and ((Y and LAND_HEIGHT_MASK) = 0) - and ((marks[Y shr gr, X shr gr] and mark) <> 0) -end; - -procedure clearAllMarks; -var - Y, X: Longword; -begin - for Y:= 0 to Pred(HEIGHT) do - for X:= 0 to Pred(WIDTH) do - marks[Y, X]:= 0 -end; - -procedure clearMarks(mark: byte); -var - Y, X: Longword; -begin - for Y:= 0 to Pred(HEIGHT) do - for X:= 0 to Pred(WIDTH) do - marks[Y, X]:= marks[Y, X] and (not mark) -end; - - -procedure initModule; -begin - WIDTH:= LAND_WIDTH shr gr; - HEIGHT:= LAND_HEIGHT shr gr; - - SetLength(marks, HEIGHT, WIDTH); -end; - -procedure freeModule; -begin - SetLength(marks, 0, 0); -end; - -end. +unit uAILandMarks; + +interface +const markWasHere = $01; + +procedure addMark(X, Y: LongInt; mark: byte); +function checkMark(X, Y: LongInt; mark: byte) : boolean; +procedure clearAllMarks; +procedure clearMarks(mark: byte); + +procedure initModule; +procedure freeModule; + +implementation +uses uVariables; + +const gr = 2; + +var marks: array of array of byte; + WIDTH, HEIGHT: Longword; + +procedure addMark(X, Y: LongInt; mark: byte); +begin + if((X and LAND_WIDTH_MASK) = 0) and ((Y and LAND_HEIGHT_MASK) = 0) then + begin + X:= X shr gr; + Y:= Y shr gr; + marks[Y, X]:= marks[Y, X] or mark + end +end; + +function checkMark(X, Y: LongInt; mark: byte) : boolean; +begin + checkMark:= ((X and LAND_WIDTH_MASK) = 0) + and ((Y and LAND_HEIGHT_MASK) = 0) + and ((marks[Y shr gr, X shr gr] and mark) <> 0) +end; + +procedure clearAllMarks; +var + Y, X: Longword; +begin + for Y:= 0 to Pred(HEIGHT) do + for X:= 0 to Pred(WIDTH) do + marks[Y, X]:= 0 +end; + +procedure clearMarks(mark: byte); +var + Y, X: Longword; +begin + for Y:= 0 to Pred(HEIGHT) do + for X:= 0 to Pred(WIDTH) do + marks[Y, X]:= marks[Y, X] and (not mark) +end; + + +procedure initModule; +begin + WIDTH:= LAND_WIDTH shr gr; + HEIGHT:= LAND_HEIGHT shr gr; + + SetLength(marks, HEIGHT, WIDTH); +end; + +procedure freeModule; +begin + SetLength(marks, 0, 0); +end; + +end. diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uAIMisc.pas Sat Aug 18 00:48:09 2012 +0200 @@ -86,12 +86,13 @@ ar: array[0..Pred(MAXBONUS div 8)] of TBonus; // don't use too many end; +const KillScore = 200; +var friendlyfactor: LongInt = 300; + implementation uses uCollisions, uVariables, uUtils, uDebug, uLandTexture; -const KillScore = 200; - -var friendlyfactor: LongInt = 300; +var KnownExplosion: record X, Y, Radius: LongInt end = (X: 0; Y: 0; Radius: 0); diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uCollisions.pas --- a/hedgewars/uCollisions.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uCollisions.pas Sat Aug 18 00:48:09 2012 +0200 @@ -82,7 +82,7 @@ X:= hwRound(Gear^.X); Y:= hwRound(Gear^.Y); Radius:= Gear^.Radius; - ChangeRoundInLand(X, Y, Radius - 1, true, Gear = CurrentHedgehog^.Gear); + ChangeRoundInLand(X, Y, Radius - 1, true, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase)); cGear:= Gear end; Gear^.CollisionIndex:= Count; @@ -103,7 +103,7 @@ if Gear^.CollisionIndex >= 0 then begin with cinfos[Gear^.CollisionIndex] do - ChangeRoundInLand(X, Y, Radius - 1, false, Gear = CurrentHedgehog^.Gear); + ChangeRoundInLand(X, Y, Radius - 1, false, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase)); cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)]; cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex; Gear^.CollisionIndex:= -1; @@ -138,7 +138,7 @@ var x, y, i: LongInt; begin // Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap -if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and +if (Gear^.CollisionMask = $FF7F) and (Gear^.Kind <> gtHedgehog) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and ((hwRound(Gear^.Hedgehog^.Gear^.X) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.X) - Gear^.Radius) or (hwRound(Gear^.Hedgehog^.Gear^.X) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.X) + Gear^.Radius)) then Gear^.CollisionMask:= $FFFF; @@ -168,7 +168,7 @@ var x, y, i: LongInt; begin // Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap -if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and +if (Gear^.CollisionMask = $FF7F) and (Gear^.Kind <> gtHedgehog) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and ((hwRound(Gear^.Hedgehog^.Gear^.Y) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.Y) - Gear^.Radius) or (hwRound(Gear^.Hedgehog^.Gear^.Y) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.Y) + Gear^.Radius)) then Gear^.CollisionMask:= $FFFF; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uCommandHandlers.pas Sat Aug 18 00:48:09 2012 +0200 @@ -614,13 +614,14 @@ if CheckNoTeamOrHH or isPaused then exit; -if FollowGear <> nil then +if autoCameraOn then begin + FollowGear:= nil; AddCaption('Auto Camera Off', $CCCCCC, capgrpVolume); autoCameraOn:= false end - else - begin +else + begin AddCaption('Auto Camera On', $CCCCCC, capgrpVolume); bShowFinger:= true; if not CurrentHedgehog^.Unplaced then diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uConsts.pas Sat Aug 18 00:48:09 2012 +0200 @@ -245,6 +245,7 @@ gmRemoveFromList = $00004000; gmAddToList = $00008000; + gmDelete = $00010000; gmAllStoppable = gmLeft or gmRight or gmUp or gmDown or gmAttack or gmPrecise; cMaxSlotIndex = 9; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uFloat.pas --- a/hedgewars/uFloat.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uFloat.pas Sat Aug 18 00:48:09 2012 +0200 @@ -369,7 +369,7 @@ function hwPow(const t: hwFloat;p: LongWord): hwFloat; begin hwPow:= t; -if p mod 2 = 0 then hwPow.isNegative:= t.isNegative; +if p mod 2 = 0 then hwPow.isNegative:= false; while p > 0 do begin diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uGears.pas --- a/hedgewars/uGears.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uGears.pas Sat Aug 18 00:48:09 2012 +0200 @@ -77,6 +77,7 @@ stAfterDelay, stChWin, stWater, stChWin2, stHealth, stSpawn, stNTurn); upd: Longword; + snowLeft,snowRight: LongInt; //SDMusic: shortstring; // For better maintainability the step handlers of gears are stored in @@ -206,23 +207,28 @@ curHandledGear:= t; t:= curHandledGear^.NextGear; - if curHandledGear^.Message and gmRemoveFromList <> 0 then - begin - RemoveGearFromList(curHandledGear); - // since I can't think of any good reason this would ever be separate from a remove from list, going to keep it inside this block - if curHandledGear^.Message and gmAddToList <> 0 then InsertGearToList(curHandledGear); - curHandledGear^.Message:= curHandledGear^.Message and (not (gmRemoveFromList or gmAddToList)) - end; - if curHandledGear^.Active then + if curHandledGear^.Message and gmDelete <> 0 then + DeleteGear(curHandledGear) + else begin - if curHandledGear^.RenderTimer and (curHandledGear^.Timer > 500) and ((curHandledGear^.Timer mod 1000) = 0) then + if curHandledGear^.Message and gmRemoveFromList <> 0 then + begin + RemoveGearFromList(curHandledGear); + // since I can't think of any good reason this would ever be separate from a remove from list, going to keep it inside this block + if curHandledGear^.Message and gmAddToList <> 0 then InsertGearToList(curHandledGear); + curHandledGear^.Message:= curHandledGear^.Message and (not (gmRemoveFromList or gmAddToList)) + end; + if curHandledGear^.Active then begin - FreeTexture(curHandledGear^.Tex); - curHandledGear^.Tex:= RenderStringTex(inttostr(curHandledGear^.Timer div 1000), cWhiteColor, fntSmall); - end; - curHandledGear^.doStep(curHandledGear); - // might be useful later - //ScriptCall('onGearStep', Gear^.uid); + if curHandledGear^.RenderTimer and (curHandledGear^.Timer > 500) and ((curHandledGear^.Timer mod 1000) = 0) then + begin + FreeTexture(curHandledGear^.Tex); + curHandledGear^.Tex:= RenderStringTex(inttostr(curHandledGear^.Timer div 1000), cWhiteColor, fntSmall); + end; + curHandledGear^.doStep(curHandledGear); + // might be useful later + //ScriptCall('onGearStep', Gear^.uid); + end end end; curHandledGear:= nil; @@ -642,9 +648,12 @@ AddGear(rx, ry, gtGenericFaller, gstInvisible, rdx, rdy, $FFFFFFFF); end; +snowRight:= max(LAND_WIDTH,4096)+512; +snowLeft:= -(snowRight-LAND_WIDTH); + if not hasBorder and ((Theme = 'Snow') or (Theme = 'Christmas')) then - for i:= 0 to Pred(vobCount*2) do - AddGear(GetRandom(LAND_WIDTH+1024)-512, LAND_HEIGHT - GetRandom(LAND_HEIGHT div 2), gtFlake, 0, _0, _0, 0); + for i:= vobCount * max(LAND_WIDTH,4096) div 2048 downto 1 do + AddGear(GetRandom(snowRight-snowLeft)+snowLeft, LAND_HEIGHT-1300+GetRandom(750), gtFlake, 0, _0, _0, 0); end; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uGearsHedgehog.pas Sat Aug 18 00:48:09 2012 +0200 @@ -455,11 +455,13 @@ procedure AfterAttack; var s: shortstring; a: TAmmoType; + HHGear: PGear; begin -with CurrentHedgehog^.Gear^, CurrentHedgehog^ do +with CurrentHedgehog^ do begin + HHGear:= Gear; a:= CurAmmoType; - State:= State and (not gstAttacking); + if HHGear <> nil then HHGear^.State:= HHGear^.State and (not gstAttacking); if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then begin Inc(MultiShootAttacks); @@ -484,8 +486,8 @@ TagTurnTimeLeft:= TurnTimeLeft; TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100; end; - if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) then - State:= State or gstAttacked; + if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (HHGear <> nil) then + HHGear^.State:= HHGear^.State or gstAttacked; if (Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0 then ApplyAmmoChanges(CurrentHedgehog^) end; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uGearsRender.pas Sat Aug 18 00:48:09 2012 +0200 @@ -376,26 +376,26 @@ hAngle:= 0; i:= -1 end; - if ((Gear^.State and gstWinner) = 0) then - begin - DrawHedgehog(ox, oy, - i, - 1, - 0, - DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + dAngle); - with HH^ do - if (HatTex <> nil) then - begin - DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32, - i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle); - if HatTex^.w > 64 then + if ((Gear^.State and gstWinner) = 0) then + begin + DrawHedgehog(ox, oy, + i, + 1, + 0, + DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + dAngle); + with HH^ do + if (HatTex <> nil) then begin - Tint(HH^.Team^.Clan^.Color shl 8 or $FF); - DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32, + DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32, i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle); - Tint($FF, $FF, $FF, $FF) + if HatTex^.w > 64 then + begin + Tint(HH^.Team^.Clan^.Color shl 8 or $FF); + DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32, + i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle); + Tint($FF, $FF, $FF, $FF) + end end - end end; DrawAltWeapon(Gear, ox, oy); defaultPos:= false diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uGearsUtils.pas diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uLand.pas --- a/hedgewars/uLand.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uLand.pas Sat Aug 18 00:48:09 2012 +0200 @@ -20,7 +20,7 @@ unit uLand; interface -uses SDLh, uLandTemplates, uFloat, uConsts, GLunit, uTypes; +uses SDLh, uLandTemplates, uFloat, uConsts, GLunit, uTypes, uAILandMarks; procedure initModule; procedure freeModule; @@ -35,6 +35,28 @@ var digest: shortstring; +procedure ResizeLand(width, height: LongWord); +var potW, potH: LongWord; +begin +potW:= toPowerOf2(width); +potH:= toPowerOf2(height); +if (potW <> LAND_WIDTH) or (potH <> LAND_HEIGHT) then + begin + LAND_WIDTH:= potW; + LAND_HEIGHT:= potH; + LAND_WIDTH_MASK:= not(LAND_WIDTH-1); + LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); + cWaterLine:= LAND_HEIGHT; + if (cReducedQuality and rqBlurryLand) = 0 then + SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH) + else + SetLength(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2); + + SetLength(Land, LAND_HEIGHT, LAND_WIDTH); + SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); + end; +end; + procedure ColorizeLand(Surface: PSDL_Surface); var tmpsurf: PSDL_Surface; r, rr: TSDL_Rect; @@ -181,6 +203,7 @@ i: Longword; y, x: Longword; begin + ResizeLand(Template.TemplateWidth, Template.TemplateHeight); for y:= 0 to LAND_HEIGHT - 1 do for x:= 0 to LAND_WIDTH - 1 do Land[y, x]:= lfBasic; @@ -237,6 +260,7 @@ procedure GenDrawnMap; begin + ResizeLand(4096, 2048); uLandPainted.Draw; MaxHedgehogs:= 48; @@ -299,7 +323,7 @@ WriteLnToConsole('Generating land...'); case cMapGen of 0: GenBlank(EdgeTemplates[SelectTemplate]); - 1: GenMaze; + 1: begin ResizeLand(4096,2048); GenMaze; end; 2: GenDrawnMap; else OutError('Unknown mapgen', true); @@ -489,7 +513,10 @@ if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptMissionMaps] + '/' + mapName + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); end; -TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true); +// (bare) Sanity check. Considering possible LongInt comparisons as well as just how much system memoery it would take +TryDo((tmpsurf^.w < $40000000) and (tmpsurf^.h < $40000000) and (tmpsurf^.w * tmpsurf^.h < 6*1024*1024*1024), 'Map dimensions too big!', true); + +ResizeLand(tmpsurf^.w, tmpsurf^.h); // unC0Rr - should this be passed from the GUI? I am not sure which layer does what s:= UserPathz[ptMapCurrent] + '/map.cfg'; @@ -676,12 +703,10 @@ LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask) end end; - -UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false); end; procedure GenPreview(out Preview: TPreview); -var x, y, xx, yy, t, bit, cbit, lh, lw: LongInt; +var rh, rw, ox, oy, x, y, xx, yy, t, bit, cbit, lh, lw: LongInt; begin WriteLnToConsole('Generating preview...'); case cMapGen of @@ -692,8 +717,21 @@ OutError('Unknown mapgen', true); end; - lh:= LAND_HEIGHT div 128; - lw:= LAND_WIDTH div 32; + // strict scaling needed here since preview assumes a rectangle + rh:= max(LAND_HEIGHT,2048); + rw:= max(LAND_WIDTH,4096); + ox:= 0; + if rw < rh*2 then + begin + rw:= rh*2; + end; + if rh < rw div 2 then rh:= rw * 2; + + ox:= (rw-LAND_WIDTH) div 2; + oy:= rh-LAND_HEIGHT; + + lh:= rh div 128; + lw:= rw div 32; for y:= 0 to 127 do for x:= 0 to 31 do begin @@ -704,7 +742,8 @@ cbit:= bit * 8; for yy:= y * lh to y * lh + 7 do for xx:= x * lw + cbit to x * lw + cbit + 7 do - if Land[yy, xx] <> 0 then + if ((yy-oy) and LAND_HEIGHT_MASK = 0) and ((xx-ox) and LAND_WIDTH_MASK = 0) + and (Land[yy-oy, xx-ox] <> 0) then inc(t); if t > 8 then Preview[y, x]:= Preview[y, x] or ($80 shr bit); diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uLandGraphics.pas Sat Aug 18 00:48:09 2012 +0200 @@ -59,7 +59,7 @@ begin addBgColor:= NewColor; exit - end; + end; // Get colors oRed := (OldColor shr RShift); oGreen := (OldColor shr GShift); @@ -72,7 +72,7 @@ // Mix colors nRed := min(255,((nRed*nAlpha) div 255) + ((oRed*oAlpha*byte(255-nAlpha)) div 65025)); nGreen := min(255,((nGreen*nAlpha) div 255) + ((oGreen*oAlpha*byte(255-nAlpha)) div 65025)); - nBlue := min(255,((nBlue*nAlpha) div 255) + ((oBlue*oAlpha*byte(255-nAlpha)) div 65025)); + nBlue := min(255,((nBlue*nAlpha) div 255) + ((oBlue*oAlpha*byte(255-nAlpha)) div 65025)); nAlpha := min(255, oAlpha + nAlpha); addBgColor := (nAlpha shl AShift) or (nRed shl RShift) or (nGreen shl GShift) or (nBlue shl BShift); @@ -106,25 +106,25 @@ begin if ((y + dy) and LAND_HEIGHT_MASK) = 0 then for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then + if isCurrent then Land[y + dy, i]:= Land[y + dy, i] and $FF7F else if Land[y + dy, i] and $007F > 0 then Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) - 1); if ((y - dy) and LAND_HEIGHT_MASK) = 0 then for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then + if isCurrent then Land[y - dy, i]:= Land[y - dy, i] and $FF7F else if Land[y - dy, i] and $007F > 0 then Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) - 1); if ((y + dx) and LAND_HEIGHT_MASK) = 0 then for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then + if isCurrent then Land[y + dx, i]:= Land[y + dx, i] and $FF7F else if Land[y + dx, i] and $007F > 0 then Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) - 1); if ((y - dx) and LAND_HEIGHT_MASK) = 0 then for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then + if isCurrent then Land[y - dx, i]:= Land[y - dx, i] and $FF7F else if Land[y - dx, i] and $007F > 0 then Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) - 1) @@ -133,27 +133,27 @@ begin if ((y + dy) and LAND_HEIGHT_MASK) = 0 then for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then + if isCurrent then Land[y + dy, i]:= Land[y + dy, i] or $80 else if Land[y + dy, i] and $007F < 127 then Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) + 1); - if ((y - dy) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then - Land[y - dy, i]:= Land[y - dy, i] or $80 - else if Land[y - dy, i] and $007F < 127 then + if ((y - dy) and LAND_HEIGHT_MASK) = 0 then + for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + if isCurrent then + Land[y - dy, i]:= Land[y - dy, i] or $80 + else if Land[y - dy, i] and $007F < 127 then Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) + 1); - if ((y + dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then - Land[y + dx, i]:= Land[y + dx, i] or $80 - else if Land[y + dx, i] and $007F < 127 then + if ((y + dx) and LAND_HEIGHT_MASK) = 0 then + for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + if isCurrent then + Land[y + dx, i]:= Land[y + dx, i] or $80 + else if Land[y + dx, i] and $007F < 127 then Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) + 1); - if ((y - dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then - Land[y - dx, i]:= Land[y - dx, i] or $80 - else if Land[y - dx, i] and $007F < 127 then + if ((y - dx) and LAND_HEIGHT_MASK) = 0 then + for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + if isCurrent then + Land[y - dx, i]:= Land[y - dx, i] or $80 + else if Land[y - dx, i] and $007F < 127 then Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) + 1) end end; @@ -266,7 +266,7 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; @@ -288,7 +288,7 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; @@ -310,7 +310,7 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; t:= y - dx; @@ -331,7 +331,7 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; FillLandCircleLinesBG:= cnt; @@ -504,7 +504,7 @@ end; if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then LandPixels[by, bx]:= LandBackPixel(tx, ty) - else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end end; @@ -567,7 +567,7 @@ and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - if despeckle then + if despeckle then begin Land[ty, tx]:= Land[ty, tx] or lfDamaged; LandDirty[ty div 32, tx div 32]:= 1 @@ -837,7 +837,7 @@ procedure Smooth(X, Y: LongInt); begin // a bit of AA for explosions -if (Land[Y, X] = 0) and (Y > LongInt(topY) + 1) and +if (Land[Y, X] = 0) and (Y > LongInt(topY) + 1) and (Y < LAND_HEIGHT-2) and (X > LongInt(leftX) + 1) and (X < LongInt(rightX) - 1) then begin if ((((Land[y, x-1] and lfDamaged) <> 0) and (((Land[y+1,x] and lfDamaged) <> 0)) or ((Land[y-1,x] and lfDamaged) <> 0)) diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uLandObjects.pas --- a/hedgewars/uLandObjects.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uLandObjects.pas Sat Aug 18 00:48:09 2012 +0200 @@ -501,7 +501,7 @@ c2.g:= t; c2.b:= t end; - ExplosionBorderColor:= c2.value or AMask; + ExplosionBorderColor:= c2.r shl 24 or c2.g shl 16 or c2.b shl 8 or $FF; end else if key = 'water-top' then begin @@ -554,7 +554,7 @@ SetMusicName(Trim(s)) else if key = 'clouds' then begin - cCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div LAND_WIDTH; + cCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096; cSDCloudsNumber:= cCloudsNumber end else if key = 'object' then @@ -700,7 +700,7 @@ else if key = 'sd-water-opacity' then SDWaterOpacity:= StrToInt(Trim(s)) else if key = 'sd-clouds' then - cSDCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div LAND_WIDTH + cSDCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096 else if key = 'sd-flakes' then begin i:= Pos(',', s); diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uLandTemplates.pas --- a/hedgewars/uLandTemplates.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uLandTemplates.pas Sat Aug 18 00:48:09 2012 +0200 @@ -1571,9 +1571,191 @@ ( (X: 512; Y: 0) ); +// Many islands +const Template43Points: array[0..173] of TSDL_Rect = + ( + (x: 95; y: 500; w: 1; h: 1), + (x: 100; y: 275; w: 25; h: 100), + (x: 325; y: 275; w: 25; h: 100), + (x: 330; y: 500; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 725; y: 125; w: 1; h: 1), + (x: 725; y: 25; w: 5; h: 25), + (x: 825; y: 35; w: 5; h: 10), + (x: 825; y: 135; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1150; y: 550; w: 25; h: 50), + (x: 1250; y: 300; w: 25; h: 50), + (x: 1350; y: 300; w: 25; h: 50), + (x: 1400; y: 575; w: 25; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 525; y:1050; w: 50; h: 50), + (x: 700; y: 800; w: 100; h: 150), + (x: 950; y: 900; w: 100; h: 150), + (x: 1100; y:1100; w: 50; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 175; y:1500; w: 1; h: 1), + (x: 210; y:1400; w: 5; h: 25), + (x: 240; y:1400; w: 5; h: 25), + (x: 275; y:1510; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 450; y:1800; w: 100; h: 100), + (x: 600; y:1750; w: 100; h: 100), + (x: 750; y:1750; w: 100; h: 100), + (x: 950; y:1850; w: 100; h: 100), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1075; y:1450; w: 1; h: 1), + (x: 1110; y:1300; w: 5; h: 25), + (x: 1140; y:1300; w: 5; h: 25), + (x: 1175; y:1430; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1600; y:1250; w: 25; h: 100), + (x: 1700; y:1150; w: 25; h: 100), + (x: 1850; y: 500; w: 50; h: 100), + (x: 1950; y: 550; w: 50; h: 150), + (x: 2250; y:1150; w: 25; h: 100), + (x: 2350; y:1250; w: 25; h: 100), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1750; y:2010; w: 1; h: 1), + (x: 1900; y:1870; w: 50; h: 50), + (x: 2050; y:1870; w: 50; h: 50), + (x: 2175; y:2010; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2500; y:1700; w: 1; h: 1), + (x: 2575; y:1500; w: 10; h: 50), + (x: 2650; y:1500; w: 10; h: 50), + (x: 2700; y:1690; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2000; y: 125; w: 1; h: 1), + (x: 2050; y: 50; w: 25; h: 25), + (x: 2100; y: 50; w: 25; h: 25), + (x: 2150; y: 150; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2600; y: 250; w: 25; h: 100), + (x: 2750; y: 400; w: 50; h: 50), + (x: 2900; y: 525; w: 50; h: 50), + (x: 3150; y: 550; w: 50; h: 100), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2800; y:1150; w: 1; h: 1), + (x: 2840; y: 950; w: 25; h: 25), + (x: 2880; y: 950; w: 25; h: 25), + (x: 2900; y:1150; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3075; y:1985; w: 1; h: 1), + (x: 3325; y:1700; w: 50; h: 100), + (x: 3475; y:1700; w: 50; h: 100), + (x: 3625; y:1985; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3200; y:1450; w: 1; h: 1), + (x: 3240; y:1350; w: 25; h: 25), + (x: 3280; y:1350; w: 25; h: 25), + (x: 3300; y:1450; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3500; y:1050; w: 25; h: 50), + (x: 3650; y: 600; w: 50; h: 100), + (x: 3800; y: 600; w: 50; h: 100), + (x: 3900; y:1000; w: 25; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3800; y: 200; w: 25; h: 50), + (x: 3875; y: 100; w: 50; h: 50), + (x: 3925; y: 50; w: 50; h: 25), + (x: 4050; y: 125; w: 25; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 95; y:2548; w: 1; h: 1), + (x: 100; y:2323; w: 25; h: 100), + (x: 325; y:2323; w: 25; h: 100), + (x: 330; y:2548; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 725; y:2173; w: 1; h: 1), + (x: 725; y:2073; w: 5; h: 25), + (x: 825; y:2083; w: 5; h: 10), + (x: 825; y:2183; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1150; y:2598; w: 25; h: 50), + (x: 1250; y:2348; w: 25; h: 50), + (x: 1350; y:2348; w: 25; h: 50), + (x: 1400; y:2623; w: 25; h: 50), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 525; y:3098; w: 50; h: 50), + (x: 700; y:2848; w: 100; h: 150), + (x: 950; y:2948; w: 100; h: 150), + (x: 1100; y:3148; w: 50; h: 50), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 175; y:3548; w: 1; h: 1), + (x: 210; y:3448; w: 5; h: 25), + (x: 240; y:3448; w: 5; h: 25), + (x: 275; y:3558; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 450; y:3848; w: 100; h: 100), + (x: 600; y:3798; w: 100; h: 100), + (x: 750; y:3798; w: 100; h: 100), + (x: 950; y:3898; w: 100; h: 100), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1075; y:3498; w: 1; h: 1), + (x: 1110; y:3348; w: 5; h: 25), + (x: 1140; y:3348; w: 5; h: 25), + (x: 1175; y:3478; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1600; y:3298; w: 25; h: 100), + (x: 1700; y:3198; w: 25; h: 100), + (x: 1850; y:2548; w: 50; h: 100), + (x: 1950; y:2598; w: 50; h: 150), + (x: 2250; y:3198; w: 25; h: 100), + (x: 2350; y:3298; w: 25; h: 100), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1750; y:4058; w: 1; h: 1), + (x: 1900; y:3918; w: 50; h: 50), + (x: 2050; y:3918; w: 50; h: 50), + (x: 2175; y:4058; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2500; y:3748; w: 1; h: 1), + (x: 2575; y:3548; w: 10; h: 50), + (x: 2650; y:3548; w: 10; h: 50), + (x: 2700; y:3738; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2000; y:2173; w: 1; h: 1), + (x: 2050; y:2098; w: 25; h: 25), + (x: 2100; y:2098; w: 25; h: 25), + (x: 2150; y:2198; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2600; y:2298; w: 25; h: 100), + (x: 2750; y:2448; w: 50; h: 50), + (x: 2900; y:2573; w: 50; h: 50), + (x: 3150; y:2598; w: 50; h: 100), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2800; y:3198; w: 1; h: 1), + (x: 2840; y:2998; w: 25; h: 25), + (x: 2880; y:2998; w: 25; h: 25), + (x: 2900; y:3198; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3075; y:4033; w: 1; h: 1), + (x: 3325; y:3748; w: 50; h: 100), + (x: 3475; y:3748; w: 50; h: 100), + (x: 3625; y:4033; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3200; y:3498; w: 1; h: 1), + (x: 3240; y:3398; w: 25; h: 25), + (x: 3280; y:3398; w: 25; h: 25), + (x: 3300; y:3498; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3500; y:3098; w: 25; h: 50), + (x: 3650; y:2648; w: 50; h: 100), + (x: 3800; y:2648; w: 50; h: 100), + (x: 3900; y:3048; w: 25; h: 50), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3800; y:2248; w: 25; h: 50), + (x: 3875; y:2148; w: 50; h: 50), + (x: 3925; y:2098; w: 50; h: 25), + (x: 4050; y:2173; w: 25; h: 50), + (x: NTPX; y:2048; w: 1; h: 1) + ); + Template43FPoints: array[0..0] of TPoint = + ( + (X: 4095; Y: 0) + ); //////////////////////////////////////////////////////////////////////// -var EdgeTemplates: array[0..42] of TEdgeTemplate = +var EdgeTemplates: array[0..43] of TEdgeTemplate = ( (BasePoints: @Template0Points; BasePointsCount: Succ(High(Template0Points)); @@ -2047,19 +2229,30 @@ canMirror: true; canFlip: false; isNegative: false; canInvert: false; hasGirders: false; MaxHedgeHogs: 8; + ), + (BasePoints: @Template43Points; + BasePointsCount: Succ(High(Template43Points)); + FillPoints: @Template43FPoints; + FillPointsCount: Succ(High(Template43FPoints)); + BezierizeCount: 3; + RandPassesCount: 5; + TemplateHeight: 4096; TemplateWidth: 4096; + canMirror: true; canFlip: true; isNegative: false; canInvert: false; + hasGirders: true; + MaxHedgeHogs: 48; ) ); const SmallTemplates: array[0..2] of Longword = ( 39, 40, 42 ); const MediumTemplates: array[0..17] of Longword = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ); -const LargeTemplates: array[0..19] of Longword = +const LargeTemplates: array[0..20] of Longword = ( 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 37, 38 + 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 43 ); const CavernTemplates: array[0..4] of Longword = (36, 2, 3, 21, 29); //const WackyTemplates: array[0..4] of Longword = (37, 38, 39, 40, 41); -const WackyTemplates: array[0..2] of Longword = (37, 38, 41); +const WackyTemplates: array[0..3] of Longword = (37, 38, 41, 43); implementation diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uRenderUtils.pas --- a/hedgewars/uRenderUtils.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uRenderUtils.pas Sat Aug 18 00:48:09 2012 +0200 @@ -92,7 +92,7 @@ textRect.y:= Y; textRect.w:= w; textRect.h:= h; - DrawRoundRect(@finalRect, cWhiteColor, endian(cNearBlackColorChannels.value), Surface, true); + DrawRoundRect(@finalRect, cWhiteColor, cNearBlackColor, Surface, true); clr.r:= (Color shr 16) and $FF; clr.g:= (Color shr 8) and $FF; clr.b:= Color and $FF; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uScript.pas --- a/hedgewars/uScript.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uScript.pas Sat Aug 18 00:48:09 2012 +0200 @@ -412,7 +412,7 @@ begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then - DeleteGear(gear); + gear^.Message:= gear^.Message or gmDelete; end; lc_deletegear:= 0 end; @@ -744,7 +744,7 @@ TryDo(texsurf <> nil, errmsgCreateSurface, true); TryDo(SDL_SetColorKey(texsurf, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true); - DrawRoundRect(@r, cWhiteColor, cNearBlackColorChannels.value, texsurf, true); + DrawRoundRect(@r, cWhiteColor, cNearBlackColor, texsurf, true); rr:= r; inc(rr.x, 2); dec(rr.w, 4); inc(rr.y, 2); dec(rr.h, 4); DrawRoundRect(@rr, clan^.Color, clan^.Color, texsurf, false); diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uStore.pas --- a/hedgewars/uStore.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uStore.pas Sat Aug 18 00:48:09 2012 +0200 @@ -131,10 +131,11 @@ procedure WriteNames(Font: THWFont); var t: LongInt; - i: LongInt; + i, maxLevel: LongInt; r, rr: TSDL_Rect; drY: LongInt; texsurf, flagsurf, iconsurf: PSDL_Surface; + foundBot: boolean; begin r.x:= 0; r.y:= 0; @@ -151,7 +152,7 @@ TryDo(texsurf <> nil, errmsgCreateSurface, true); TryDo(SDL_SetColorKey(texsurf, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true); - DrawRoundRect(@r, cWhiteColor, cNearBlackColorChannels.value, texsurf, true); + DrawRoundRect(@r, cWhiteColor, cNearBlackColor, texsurf, true); rr:= r; inc(rr.x, 2); dec(rr.w, 4); inc(rr.y, 2); dec(rr.h, 4); DrawRoundRect(@rr, Clan^.Color, Clan^.Color, texsurf, false); @@ -172,11 +173,28 @@ DrawRoundRect(@r, cWhiteColor, cNearBlackColor, texsurf, true); // overwrite flag for cpu teams and keep players from using it - if (Hedgehogs[0].Gear <> nil) and (Hedgehogs[0].BotLevel > 0) then - if Flag = 'hedgewars' then - Flag:= 'cpu' - else if Flag = 'cpu' then - Flag:= 'hedgewars'; + foundBot:= false; + maxLevel:= -1; + for i:= 0 to cMaxHHIndex do + with Hedgehogs[i] do + if (Gear <> nil) and (BotLevel > 0) then + begin + foundBot:= true; + // initially was going to do the highest botlevel of the team, but for now, just apply if entire team has same bot level + if maxLevel = -1 then maxLevel:= BotLevel + else if (maxLevel > 0) and (maxLevel <> BotLevel) then maxLevel:= 0; + //if (maxLevel > 0) and (BotLevel < maxLevel) then maxLevel:= BotLevel + end + else if Gear <> nil then maxLevel:= 0; + + if foundBot then + begin + // disabled the plain flag - I think it looks ok even w/ full bars obscuring CPU + //if (maxLevel > 0) and (maxLevel < 3) then Flag:= 'cpu_plain' else + Flag:= 'cpu' + end + else if (Flag = 'cpu') or (Flag = 'cpu_plain') then + Flag:= 'hedgewars'; flagsurf:= LoadImage(UserPathz[ptFlags] + '/' + Flag, ifNone); if flagsurf = nil then @@ -186,16 +204,27 @@ if flagsurf = nil then flagsurf:= LoadImage(Pathz[ptFlags] + '/hedgewars', ifNone); TryDo(flagsurf <> nil, 'Failed to load flag "' + Flag + '" as well as the default flag', true); + + case maxLevel of + 1: copyToXY(SpritesData[sprBotlevels].Surface, flagsurf, 0, 0); + 2: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 5, 2, 17, 13, 5, 2); + 3: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 9, 5, 13, 10, 9, 5); + 4: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 13, 9, 9, 6, 13, 9); + 5: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 17, 11, 5, 4, 17, 11) + end; + copyToXY(flagsurf, texsurf, 2, 2); SDL_FreeSurface(flagsurf); flagsurf:= nil; + // restore black border pixels inside the flag PLongwordArray(texsurf^.pixels)^[32 * 2 + 2]:= cNearBlackColor; PLongwordArray(texsurf^.pixels)^[32 * 2 + 23]:= cNearBlackColor; PLongwordArray(texsurf^.pixels)^[32 * 16 + 2]:= cNearBlackColor; PLongwordArray(texsurf^.pixels)^[32 * 16 + 23]:= cNearBlackColor; + FlagTex:= Surface2Tex(texsurf, false); SDL_FreeSurface(texsurf); texsurf:= nil; @@ -204,7 +233,7 @@ dec(drY, r.h + 2); DrawHealthY:= drY; - for i:= 0 to 7 do + for i:= 0 to cMaxHHIndex do with Hedgehogs[i] do if Gear <> nil then begin @@ -294,7 +323,6 @@ WriteLnToConsole(msgOK) end; -WriteNames(fnt16); MakeCrossHairs; LoadGraves; if not reload then @@ -391,6 +419,8 @@ Surface:= nil end; +WriteNames(fnt16); + if not reload then AddProgress; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uTypes.pas Sat Aug 18 00:48:09 2012 +0200 @@ -86,7 +86,7 @@ sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb, sprBulletHit, sprSnowball, sprHandSnowball, sprSnow, sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis, - sprSlider + sprSlider, sprBotlevels ); // Gears that interact with other Gears and/or Land diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uUtils.pas --- a/hedgewars/uUtils.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uUtils.pas Sat Aug 18 00:48:09 2012 +0200 @@ -43,7 +43,7 @@ function StrToInt(s: shortstring): LongInt; function FloatToStr(n: hwFloat): shortstring; -function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; +function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; inline; function DxDy2Angle32(const _dY, _dX: hwFloat): LongInt; function DxDy2AttackAngle(const _dY, _dX: hwFloat): LongInt; function DxDy2AttackAnglef(const _dY, _dX: extended): LongInt; @@ -182,15 +182,11 @@ end; -function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; +function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; inline; var dY, dX: Extended; begin -dY:= _dY.QWordValue / $100000000; -if _dY.isNegative then - dY:= - dY; -dX:= _dX.QWordValue / $100000000; -if _dX.isNegative then - dX:= - dX; +dY:= hwFloat2Float(_dY); +dX:= hwFloat2Float(_dX); DxDy2Angle:= arctan2(dY, dX) * 180 / pi end; @@ -198,12 +194,8 @@ const _16divPI: Extended = 16/pi; var dY, dX: Extended; begin -dY:= _dY.QWordValue / $100000000; -if _dY.isNegative then - dY:= - dY; -dX:= _dX.QWordValue / $100000000; -if _dX.isNegative then - dX:= - dX; +dY:= hwFloat2Float(_dY); +dX:= hwFloat2Float(_dX); DxDy2Angle32:= trunc(arctan2(dY, dX) * _16divPI) and $1f end; @@ -211,12 +203,8 @@ const MaxAngleDivPI: Extended = cMaxAngle/pi; var dY, dX: Extended; begin -dY:= _dY.QWordValue / $100000000; -if _dY.isNegative then - dY:= - dY; -dX:= _dX.QWordValue / $100000000; -if _dX.isNegative then - dX:= - dX; +dY:= hwFloat2Float(_dY); +dX:= hwFloat2Float(_dX); DxDy2AttackAngle:= trunc(arctan2(dY, dX) * MaxAngleDivPI) end; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uVariables.pas Sat Aug 18 00:48:09 2012 +0200 @@ -644,7 +644,9 @@ (FileName: 'TARDIS'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; Width: 48; Height: 79; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis (FileName: 'slider'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; - Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprSlider + Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider + (FileName: 'botlevels'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 22; Height: 15; imageWidth: 22; imageHeight: 15; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprBotlevels ); const diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uVisualGears.pas --- a/hedgewars/uVisualGears.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uVisualGears.pas Sat Aug 18 00:48:09 2012 +0200 @@ -958,10 +958,10 @@ exit; if hasBorder or ((Theme <> 'Snow') and (Theme <> 'Christmas')) then - for i:= 0 to Pred(vobCount * cScreenSpace div LAND_WIDTH) do + for i:= 0 to Pred(vobCount * cScreenSpace div 4096) do AddVisualGear(cLeftScreenBorder + random(cScreenSpace), random(1024+200) - 100 + LAND_HEIGHT, vgtFlake) else - for i:= 0 to Pred((vobCount * cScreenSpace div LAND_WIDTH) div 3) do + for i:= 0 to Pred((vobCount * cScreenSpace div 4096) div 3) do AddVisualGear(cLeftScreenBorder + random(cScreenSpace), random(1024+200) - 100 + LAND_HEIGHT, vgtFlake); end; diff -r 763d3961400b -r 3c4b4cb40f40 hedgewars/uWorld.pas --- a/hedgewars/uWorld.pas Sat Aug 18 00:47:51 2012 +0200 +++ b/hedgewars/uWorld.pas Sat Aug 18 00:48:09 2012 +0200 @@ -1614,10 +1614,7 @@ uCursor.updatePosition(); {$ENDIF} z:= round(200/zoom); -if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) then - if (not autoCameraOn) then - FollowGear:= nil - else +if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) and autoCameraOn then if ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then begin FollowGear:= nil; diff -r 763d3961400b -r 3c4b4cb40f40 share/hedgewars/Data/Graphics/Flags/cpu_plain.png Binary file share/hedgewars/Data/Graphics/Flags/cpu_plain.png has changed diff -r 763d3961400b -r 3c4b4cb40f40 share/hedgewars/Data/Graphics/botlevels.png Binary file share/hedgewars/Data/Graphics/botlevels.png has changed diff -r 763d3961400b -r 3c4b4cb40f40 share/hedgewars/Data/Locale/en.txt --- a/share/hedgewars/Data/Locale/en.txt Sat Aug 18 00:47:51 2012 +0200 +++ b/share/hedgewars/Data/Locale/en.txt Sat Aug 18 00:48:09 2012 +0200 @@ -492,7 +492,7 @@ 04:36=Well, sometimes you're just too bad in aiming. Get|some assistance using modern day technology.|Attack: Activate 04:37=Don't fear the daylight. It will just last one turn|but will enable you to absorb the damage you do to|other hogs.|Attack: Activate 04:38=The sniper rifle can be the most devastating weapon|in your whole arsenal, however it's very ineffective|at close quarters. The damage dealt increases with|the distance to its target.|Attack: Shoot (twice) -04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility is able to|take you to almost any position on the battlefield.|Attack: Activate|Up/Left/Right: Apply force in one direction|Long Jump: Drop grenades or similar weapons +04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility can|take you to almost any position on the battlefield.|Attack: Activate|Up/Left/Right: Apply force in one direction|Long Jump: Drop grenades or similar weapons 04:40=Set some ground on fire using this bottle filled|with (soon to be) burning liquid.|Attack: Hold to shoot with more power 04:41=The evidence nature might even top the flying|saucer. Birdy can carry your hog around and|drop eggs on your enemies!|Be quick, as using Birdy eats into your turn|time!|Attack: Activate and drop eggs|Up/Left/Right: Flap in one direction 04:42=This portable portal device is capable|of instantly transporting you, your enemies,|or your weaponry between two points on the|terrain.|Use it wisely and your campaign will be a...|HUGE SUCCESS!|Attack: Shoot a portal|Switch: Cycle portal colours @@ -506,7 +506,7 @@ 04:50=Is someone hiding underground?|Dig them out with a drill strike!|Timer controls how far it will dig. 04:51=Get in a free shot by hurling a ball of mud.|Stings a bit, and knocks hogs back. 04:52=UNUSED -04:53=Go on an adventure through time and space,|while leaving your comrades to fight on alone.|Be prepared to return at any time,|or for Sudden Death or if they are all defeated.|Disclaimer. Does not function in Sudden Death,|if you are alone, or if you are a King. +04:53=Take a trip through time and space,|while leaving your comrades to fight on alone.|Be prepared to return at any time,|or for Sudden Death or if they are all defeated.|Disclaimer. Does not function in Sudden Death,|if you are alone, or if you are a King. 04:54=INCOMPLETE 04:55=Spray a stream of sticky flakes.|Build bridges, bury enemies, seal off tunnels.|Be careful you don't get any on you! diff -r 763d3961400b -r 3c4b4cb40f40 share/hedgewars/Data/Locale/hedgewars_zh_CN.ts --- a/share/hedgewars/Data/Locale/hedgewars_zh_CN.ts Sat Aug 18 00:47:51 2012 +0200 +++ b/share/hedgewars/Data/Locale/hedgewars_zh_CN.ts Sat Aug 18 00:48:09 2012 +0200 @@ -2,325 +2,240 @@ <!DOCTYPE TS> <TS version="2.0" language="zh_CN"> <context> - <name>AmmoSchemeModel</name> - <message> - <source>new</source> - <translation>新建</translation> - </message> - <message> - <source>copy of</source> - <translation>副本</translation> - </message> -</context> -<context> - <name>DrawMapWidget</name> - <message> - <source>File error</source> - <translation>文件错误</translation> - </message> - <message> - <source>Cannot open file '%1' for writing</source> - <translatorcomment>无法打开文件 '%1' 写入</translatorcomment> - <translation>无法打开要写入的文件 '%1'</translation> - </message> - <message> - <source>Cannot read file '%1'</source> - <translation>无法读取文件 '%1'</translation> - </message> -</context> -<context> <name>FreqSpinBox</name> <message> + <location filename="../../../../QTfrontend/misc.h" line="38"/> <source>Never</source> <translation>从不</translation> </message> <message numerus="yes"> + <location filename="../../../../QTfrontend/misc.h" line="40"/> <source>Every %1 turn</source> <translation> - <numerusform>每 %1 个回合</numerusform> + <numerusform>每隔 %1 回合</numerusform> </translation> </message> </context> <context> <name>GameCFGWidget</name> <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="129"/> <source>Error</source> <translation>错误</translation> </message> <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="129"/> <source>Illegal ammo scheme</source> <translation>无法使用此弹药设置</translation> </message> <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="57"/> <source>Edit schemes</source> <translation>修改游戏设置</translation> </message> - <message> - <source>Edit weapons</source> - <translation>修改武器</translation> - </message> - <message> - <source>When this option is enabled selecting a game scheme will auto-select a weapon</source> - <translation>使用此项则游戏框架自动选择武器配备</translation> - </message> - <message> - <source>Game Options</source> - <translation>游戏选项</translation> - </message> </context> <context> - <name>HWChatWidget</name> - <message> - <source>%1 *** %2 has been removed from your ignore list</source> - <translation type="obsolete">%1 *** %2 已经从您的忽略列表中移除</translation> - </message> - <message> - <source>%1 *** %2 has been added to your ignore list</source> - <translation type="obsolete">%1 *** %2 已经添加到您的忽略列表中</translation> - </message> - <message> - <source>%1 *** %2 has been removed from your friends list</source> - <translation type="obsolete">%1 *** %2 已经从您的朋友列表中移除</translation> - </message> + <name>GameUIConfig</name> <message> - <source>%1 *** %2 has been added to your friends list</source> - <translation type="obsolete">%1 *** %2 已经添加到您的朋友列表中</translation> - </message> - <message> - <source>%1 has been removed from your ignore list</source> - <translation>%1 已从您的忽略列表中移除</translation> - </message> - <message> - <source>%1 has been added to your ignore list</source> - <translation>%1 已被添加到您的忽略列表中</translation> - </message> - <message> - <source>%1 has been removed from your friends list</source> - <translation>%1 已从您的好友列表中移除</translation> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="0"/> + <source>Error</source> + <translation type="obsolete">错误</translation> </message> <message> - <source>%1 has been added to your friends list</source> - <translation>%1 已加入您的好友列表</translation> - </message> - <message> - <source>Stylesheet imported from %1</source> - <translation>已从 %1 导入样式表</translation> - </message> - <message> - <source>Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset!</source> - <translation>键入 %1 以使用当前的样式表,键入 %2 以重置!</translation> - </message> - <message> - <source>Couldn't read %1</source> - <translation>无法读取 %1</translation> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="0"/> + <source>Cannot create directory %1</source> + <translation type="obsolete">不能创建路径</translation> </message> <message> - <source>StyleSheet discarded</source> - <translation>已丢弃样式表</translation> - </message> - <message> - <source>StyleSheet saved to %1</source> - <translation>样式表已保存到 %1</translation> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="0"/> + <source>Quit</source> + <translation type="obsolete">退出</translation> </message> <message> - <source>Failed to save StyleSheet to %1</source> - <translation>保存样式表到 %1 失败</translation> - </message> - <message> - <source>%1 is not a valid command!</source> - <translation>%1 不是一个有效的命令!</translation> - </message> - <message> - <source>Kicking %1 ...</source> - <translation>正在踢出 %1 ...</translation> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="0"/> + <source>Cannot save options to file %1</source> + <translation type="obsolete">不能把选项保存到 %1</translation> </message> </context> <context> <name>HWForm</name> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="639"/> <source>Error</source> <translation>错误</translation> </message> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="0"/> + <source>Please, select demo from the list above</source> + <translation type="obsolete">请选择一个DEMO</translation> + </message> + <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="484"/> <source>OK</source> <translation>确认</translation> </message> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="0"/> + <source>Please, select server from the list above</source> + <translation type="obsolete">请选择一个服务器</translation> + </message> + <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="483"/> + <source>Please, select record from the list above</source> + <translation>请选择一个记录</translation> + </message> + <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="794"/> <source>Cannot save record to file %1</source> <translation>无法录入文件 %1</translation> </message> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="640"/> <source>Unable to start the server</source> <translation>开启服务端出现错误</translation> </message> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="256"/> <source>new</source> - <translation type="obsolete">新</translation> - </message> - <message> - <source>Please select record from the list above</source> - <translation>请选择一个记录</translation> - </message> - <message> - <source>DefaultTeam</source> - <translation>默认队伍</translation> - </message> - <message> - <source>Hedgewars Demo File</source> - <comment>File Types</comment> - <translation>刺猬大作战回放文件</translation> - </message> - <message> - <source>Hedgewars Save File</source> - <comment>File Types</comment> - <translation>刺猬大作战存档文件</translation> - </message> - <message> - <source>Demo name</source> - <translation>回放录像名称</translation> - </message> - <message> - <source>Demo name:</source> - <translation>回放录像名称:</translation> - </message> - <message> - <source>Game aborted</source> - <translation>游戏被中断</translation> - </message> - <message> - <source>Password</source> - <translation>密码</translation> - </message> - <message> - <source>Your nickname %1 is -registered on Hedgewars.org -Please provide your password below -or pick another nickname in game config:</source> - <translation>您的昵称%1 -在Hedgewars.org已注册 -请输入您的密码 -或从游戏配置中选择另一个昵称:</translation> - </message> - <message> - <source>No password supplied.</source> - <translation>没有填写密码.</translation> - </message> - <message> - <source>Nickname</source> - <translation>昵称</translation> - </message> - <message> - <source>Some one already uses - your nickname %1 -on the server. -Please pick another nickname:</source> - <translation>您的昵称 %1 -以被其他人 -在服务器上使用 -请选择另一个昵称:</translation> - </message> - <message> - <source>No nickname supplied.</source> - <translation>没有填写昵称。</translation> + <translation>新</translation> </message> </context> <context> <name>HWGame</name> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="0"/> + <source>Error</source> + <translation type="obsolete">错误</translation> + </message> + <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="0"/> + <source>Unable to start the server: %1.</source> + <translation type="obsolete">开启服务端出现错误: %1.</translation> + </message> + <message> + <location filename="../../../../QTfrontend/game.cpp" line="280"/> <source>en.txt</source> <translation>zh_CN.txt</translation> </message> <message> + <location filename="../../../../QTfrontend/game.cpp" line="0"/> + <source>Cannot save demo to file %1</source> + <translation type="obsolete">不能把demo保存为 %1</translation> + </message> + <message> + <location filename="../../../../QTfrontend/game.cpp" line="0"/> + <source>Quit</source> + <translation type="obsolete">退出</translation> + </message> + <message> + <location filename="../../../../QTfrontend/game.cpp" line="305"/> <source>Cannot open demofile %1</source> <translation>DEMO %1 打不开</translation> </message> + <message> + <location filename="../../../../QTfrontend/game.cpp" line="0"/> + <source>Unable to run engine: %1 (</source> + <translation type="obsolete">引擎无法启动: %1 (</translation> + </message> + <message> + <location filename="../../../../QTfrontend/game.cpp" line="147"/> + <source>Error reading training config file</source> + <translation>训练设置文件无法读取</translation> + </message> </context> <context> <name>HWMapContainer</name> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="90"/> <source>Map</source> <translation>地图</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="110"/> <source>Themes</source> <translation>主题</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="93"/> <source>Filter</source> <translation>过滤</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="97"/> <source>All</source> <translation>全部</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="98"/> <source>Small</source> <translation>小型</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="99"/> <source>Medium</source> <translation>中型</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="100"/> <source>Large</source> <translation>大型</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="101"/> <source>Cavern</source> <translation>洞穴</translation> </message> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="102"/> <source>Wacky</source> - <translation>险峻</translation> - </message> - <message> - <source>Type</source> - <translation>类型</translation> + <translation>曲折</translation> </message> +</context> +<context> + <name>HWNet</name> <message> - <source>Small tunnels</source> - <translation>小型隧道</translation> - </message> - <message> - <source>Medium tunnels</source> - <translation>中型隧道</translation> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="0"/> + <source>Error</source> + <translation type="obsolete">错误</translation> </message> <message> - <source>Large tunnels</source> - <translation>大型隧道</translation> - </message> - <message> - <source>Small floating islands</source> - <translation>小型漂浮岛屿</translation> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="0"/> + <source>The host was not found. Please check the host name and port settings.</source> + <translation type="obsolete">未发现主机。请检查主机名和端口设置。</translation> </message> <message> - <source>Medium floating islands</source> - <translation>中型漂浮岛屿</translation> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="0"/> + <source>Connection refused</source> + <translation type="obsolete">连接被拒绝</translation> + </message> +</context> +<context> + <name>HWNetServer</name> + <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="0"/> + <source>Error</source> + <translation type="obsolete">错误</translation> </message> <message> - <source>Large floating islands</source> - <translation>大型漂浮岛屿</translation> - </message> - <message> - <source>Seed</source> - <translation>作种</translation> - </message> - <message> - <source>Set</source> - <translation>设定</translation> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="0"/> + <source>Unable to start the server: %1.</source> + <translation type="obsolete">无法启动服务端: %1.</translation> </message> </context> <context> <name>HWNetServersModel</name> <message> + <location filename="../../../../QTfrontend/netserverslist.cpp" line="45"/> <source>Title</source> - <translation>名称</translation> + <translation>标题</translation> </message> <message> + <location filename="../../../../QTfrontend/netserverslist.cpp" line="46"/> <source>IP</source> <translation>IP</translation> </message> <message> + <location filename="../../../../QTfrontend/netserverslist.cpp" line="47"/> <source>Port</source> <translation>端口</translation> </message> @@ -328,177 +243,109 @@ <context> <name>HWNewNet</name> <message> - <source>The host was not found. Please check the host name and port settings.</source> - <translation>没找到主机。请检查主机名和端口设置。</translation> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="187"/> + <source>Error</source> + <translation type="obsolete">错误</translation> </message> <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="192"/> + <source>The host was not found. Please check the host name and port settings.</source> + <translation>错误没找到这个主机。请检查主机名和端口设置。</translation> + </message> + <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="195"/> <source>Connection refused</source> <translation>连接被拒绝</translation> </message> <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="402"/> + <source>*** %1 joined</source> + <translation>*** %1 加入</translation> + </message> + <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="439"/> + <source>*** %1 left</source> + <translation>*** %1 离开</translation> + </message> + <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="441"/> + <source>*** %1 left (%2)</source> + <translation>*** %1 离开 (%2)</translation> + </message> + <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="531"/> <source>Quit reason: </source> <translation>退出原因:</translation> </message> <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="350"/> <source>Room destroyed</source> <translation>房间损坏</translation> </message> <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="357"/> <source>You got kicked</source> <translation>被踢出</translation> </message> <message> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="452"/> <source>Password</source> - <translation type="obsolete">密码</translation> - </message> - <message> - <source>Your nickname %1 is -registered on Hedgewars.org -Please provide your password -or pick another nickname:</source> - <translation type="obsolete">您的昵称%1 -在Hedgewars.org已注册 -请输入您的密码 -或选择另一个昵称:</translation> - </message> - <message> - <source>%1 *** %2 has joined the room</source> - <translation>%1 *** %2 进入这个房间了</translation> - </message> - <message> - <source>%1 *** %2 has joined</source> - <translation>%1 *** %2 加入了</translation> + <translation>密码</translation> </message> <message> - <source>%1 *** %2 has left (%3)</source> - <translation>%1 *** %2 离开了(%3)</translation> - </message> - <message> - <source>%1 *** %2 has left</source> - <translation>%1 *** %2 离开了</translation> - </message> - <message> - <source>Your nickname %1 is -registered on Hedgewars.org -Please provide your password below -or pick another nickname in game config:</source> - <translation type="obsolete">您的昵称%1 -在Hedgewars.org已注册 -请输入您的密码 -或从游戏配置中选择另一个昵称:</translation> - </message> - <message> - <source>Nickname</source> - <translation type="obsolete">昵称</translation> - </message> - <message> - <source>User quit</source> - <translation>用户退出</translation> + <location filename="../../../../QTfrontend/newnetclient.cpp" line="452"/> + <source>Enter your password:</source> + <translation>输入你的密码:</translation> </message> </context> <context> <name>KB</name> <message> + <location filename="../../../../QTfrontend/KB.h" line="32"/> <source>SDL_ttf returned error while rendering text, most propably it is related to the bug in freetype2. It's recommended to update your freetype lib.</source> - <translation>渲染文字时SDL_ttf 返回错误,可能有关freetype2的bug。建议升级 freetype。</translation> + <translation>SDL_ttf 返回错误-渲染文字失败,可能有关freetype2的bug。建议升级 freetype。</translation> </message> </context> <context> <name>PageAdmin</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="1063"/> <source>Server message:</source> - <translation type="obsolete">服务器信息:</translation> - </message> - <message> - <source>Set message</source> - <translation type="obsolete">设定信息</translation> - </message> - <message> - <source>Clear Accounts Cache</source> - <translation>清空账户缓存</translation> - </message> - <message> - <source>Fetch data</source> - <translation>获取数据</translation> + <translation>服务器信息:</translation> </message> <message> - <source>Server message for latest version:</source> - <translation>最新版本的服务器信息:</translation> - </message> - <message> - <source>Server message for previous versions:</source> - <translation>之前版本的服务器信息:</translation> - </message> - <message> - <source>Latest version protocol number:</source> - <translation>最新版本的通讯协议号码:</translation> - </message> - <message> - <source>MOTD preview:</source> - <translation>MOTD预览:</translation> - </message> - <message> - <source>Set data</source> - <translation>设定数据</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="1069"/> + <source>Set message</source> + <translation>设定信息</translation> </message> </context> <context> <name>PageConnecting</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="848"/> <source>Connecting...</source> <translation>连接中...</translation> </message> - <message> - <source>Cancel</source> - <translation type="obsolete">取消</translation> - </message> -</context> -<context> - <name>PageDrawMap</name> - <message> - <source>Undo</source> - <translation>取消</translation> - </message> - <message> - <source>Clear</source> - <translation>清除</translation> - </message> - <message> - <source>Load</source> - <translation>读取</translation> - </message> - <message> - <source>Save</source> - <translation>保存</translation> - </message> - <message> - <source>Load drawn map</source> - <translation>读取已经绘制的地图</translation> - </message> - <message> - <source>Drawn Maps (*.hwmap);;All files (*.*)</source> - <translation type="obsolete">绘制的地图 (*.hwmap);;全部文件 (*.*)</translation> - </message> - <message> - <source>Save drawn map</source> - <translation>保存绘制的地图</translation> - </message> - <message> - <source>Drawn Maps</source> - <translation>绘制的地图</translation> - </message> - <message> - <source>All files</source> - <translation>全部文件</translation> - </message> </context> <context> <name>PageEditTeam</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Discard</source> + <translation type="obsolete">中止</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Save</source> + <translation type="obsolete">保存</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="106"/> <source>General</source> <translation>常规</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="107"/> <source>Advanced</source> <translation>进阶</translation> </message> @@ -506,393 +353,87 @@ <context> <name>PageGameStats</name> <message> + <location filename="../../../../QTfrontend/statsPage.cpp" line="101"/> <source><p>The best shot award was won by <b>%1</b> with <b>%2</b> pts.</p></source> - <translation type="obsolete"><p>最佳射手奖给与 <b>%1</b>:伤害 <b>%2</b>点。</p></translation> - </message> - <message numerus="yes"> - <source><p>The best killer is <b>%1</b> with <b>%2</b> kills in a turn.</p></source> - <translation type="obsolete"> - <numerusform><p>最佳杀手是 <b>%1</b>单回合击杀刺猬数:<b>%2</b></p></numerusform> - </translation> + <translation><p>最佳射手是<b>%1</b>。伤害 <b>%2</b>点。</p></translation> </message> <message numerus="yes"> - <source><p>A total of <b>%1</b> hedgehog(s) were killed during this round.</p></source> - <translation type="obsolete"> - <numerusform><p>本轮总共有<b>%1</b>只刺猬被击杀</p></numerusform> - </translation> - </message> - <message> - <source>Details</source> - <translation>细节</translation> - </message> - <message> - <source>Health graph</source> - <translation>健康值图形</translation> - </message> - <message> - <source>Ranking</source> - <translation>排名</translation> - </message> - <message> - <source>The best shot award was won by <b>%1</b> with <b>%2</b> pts.</source> - <translation>最佳射手<b>%1</b>制造了<b>%2</b>点伤害。</translation> - </message> - <message numerus="yes"> - <source>The best killer is <b>%1</b> with <b>%2</b> kills in a turn.</source> + <location filename="../../../../QTfrontend/statsPage.cpp" line="108"/> + <source><p>The best killer is <b>%1</b> with <b>%2</b> kills in a turn.</p></source> <translation> - <numerusform>最佳杀手 <b>%1</b> 完成了单回合<b>%2</b>次击杀。</numerusform> + <numerusform><p>最佳杀手<b>%1</b>:却敌<b>%2</b></p></numerusform> </translation> </message> <message numerus="yes"> - <source>A total of <b>%1</b> hedgehog(s) were killed during this round.</source> - <translation> - <numerusform>总共 <b>%1</b> 只刺猬在本轮失去生命。</numerusform> - </translation> - </message> - <message numerus="yes"> - <source>(%1 kill)</source> + <location filename="../../../../QTfrontend/statsPage.cpp" line="115"/> + <source><p>A total of <b>%1</b> hedgehog(s) were killed during this round.</p></source> <translation> - <numerusform>(%1 击杀)</numerusform> - </translation> - </message> - <message> - <source>(%1 kills)</source> - <translation type="obsolete">(%1 击杀)</translation> - </message> - <message numerus="yes"> - <source><b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts.</source> - <translation> - <numerusform><b>%1</b>以为给自己的刺猬造成 <b>%2</b> 点创伤是小意思。</numerusform> + <numerusform><p>有<b>%1</b>个刺猬在此局失去生命。</p></numerusform> </translation> </message> - <message numerus="yes"> - <source><b>%1</b> killed <b>%2</b> of his own hedgehogs.</source> - <translation> - <numerusform><b>%1</b> 整垮了 <b>%2</b> 只自己的刺猬。</numerusform> - </translation> - </message> - <message numerus="yes"> - <source><b>%1</b> was scared and skipped turn <b>%2</b> times.</source> - <translation> - <numerusform><b>%1</b> 受惊了,共计 <b>%2</b> 次放弃。</numerusform> - </translation> - </message> -</context> -<context> - <name>PageInGame</name> - <message> - <source>In game...</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>PageMain</name> <message> - <source>Local Game (Play a game on a single computer)</source> - <translation>单机游戏(在一台电脑上)</translation> - </message> - <message> - <source>Network Game (Play a game across a network)</source> - <translation>网络游戏(通过网络)</translation> - </message> - <message> - <source>Simply pick the same color as a friend to play together as a team. Each of you will still control his or her own hedgehogs but they'll win or lose together.</source> - <comment>Tips</comment> - <translation>点击同色作为同一组的友军。控制权不分享,但是共同胜利/失败。</translation> - </message> - <message> - <source>Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water.</source> - <comment>Tips</comment> - <translation>有些武器可能威力低下但是有毁灭性的效果。比如沙漠之鹰能把多个刺猬打入水中。</translation> - </message> - <message> - <source>If you're unsure what to do and don't want to waste ammo, skip one round. But don't let too much time pass as there will be Sudden Death!</source> - <comment>Tips</comment> - <translation>加入不确定怎么做,不要浪费弹药,跳过此回合。但是注意突然时间!</translation> - </message> - <message> - <source>Want to save ropse? Release the rope in mid air and then shoot again. As long as you don't touch the ground you'll reuse your rope without wasting ammo!</source> - <comment>Tips</comment> - <translation type="obsolete">保存绳子?在半空释放然后再次射出。只要不接触地面停止就可以继续使用同一根不会浪费!</translation> - </message> - <message> - <source>If you'd like to keep others from using your preferred nickname on the official server, register an account at http://www.hedgewars.org/.</source> - <comment>Tips</comment> - <translation>如果您确定好了一个昵称不想让别人使用,那么在 http://www.hedgewars.org/. 注册一个帐号吧。</translation> - </message> - <message> - <source>You're bored of default gameplay? Try one of the missions - they'll offer different gameplay depending on the one you picked.</source> - <comment>Tips</comment> - <translation>厌倦了默认的玩法?试试任务吧——每个任务都有不同的玩法。</translation> - </message> - <message> - <source>By default the game will always record the last game played as a demo. Select 'Local Game' and pick the 'Demos' button on the lower right corner to play or manage them.</source> - <comment>Tips</comment> - <translation>默认情况下游戏记录最后的游戏作为Demo,选择单机游戏——然后Demo——然后点击右下角开始回放或者整理。</translation> - </message> - <message> - <source>Hedgewars is Open Source and Freeware we create in our spare time. If you've got problems, ask on our forums but please don't expect 24/7 support!</source> - <comment>Tips</comment> - <translation>刺猬大作战是一个开放源代码的免费软件,它充分利用了我们的业余时间。如果您有问题,到论坛来吧,不过7×24小时支持不可能!</translation> - </message> - <message> - <source>Hedgewars is Open Source and Freeware we create in our spare time. If you like it, help us with a small donation or contribute your own work!</source> - <comment>Tips</comment> - <translation>刺猬大作战是一个开放源代码的免费软件,它充分利用了我们的业余时间。如果您喜欢它,我们接受您的捐赠/感谢!</translation> - </message> - <message> - <source>Hedgewars is Open Source and Freeware we create in our spare time. Share it with your family and friends as you like!</source> - <comment>Tips</comment> - <translation>刺猬大作战是一个开放源代码的免费软件,它充分利用了我们的业余时间。与他人分享它吧!</translation> - </message> - <message> - <source>From time to time there will be official tournaments. Upcoming events will be announced at http://www.hedgewars.org/ some days in advance.</source> - <comment>Tips</comment> - <translation>官方的竞赛一直存在。临近时去 http://www.hedgewars.org/ 即可看到。</translation> - </message> - <message> - <source>Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us!</source> - <comment>Tips</comment> - <translation>Hedgewars 被翻译成多种语言,中文是刺猬大作战——同样为翻译名。如果您的语言翻译有什么缺失/过时/遗漏或任何问题,来联系我们吧!</translation> - </message> - <message> - <source>Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and Linux.</source> - <comment>Tips</comment> - <translation>刺猬大作战可以运行的操作系统包括:GNU/Linux、Mac OS X、MicroSoft Windows。</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>Multiplayer</source> + <translation type="obsolete">多人游戏</translation> </message> <message> - <source>Always remember you're able to set up your own games in local and network/online play. You're not restricted to the 'Simple Game' option.</source> - <comment>Tips</comment> - <translation>您可以建立自己的网络游戏/局域网游戏。不仅限于 "简单游戏" 选项。</translation> - </message> - <message> - <source>Create an account on http://www.hedgewars.org/ to keep others from using your most favourite nickname while playing on the official server.</source> - <comment>Tips</comment> - <translation type="obsolete">在官方服务器 http://www.hedgewars.org/ 建立自己的帐号——就能一直使用最喜欢的昵称</translation> - </message> - <message> - <source>While playing you should give yourself a short break at least once an hour.</source> - <comment>Tips</comment> - <translation>最好玩一个小时就休息一下,如果你要继续用电脑。</translation> - </message> - <message> - <source>If your graphics card isn't able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance.</source> - <comment>Tips</comment> - <translation>假如你的显卡不能提供OpenGL硬件加速,试着用降低效果的方式运行。</translation> - </message> - <message> - <source>We're open to suggestions and constructive feedback. If you don't like something or got a great idea, let us know!</source> - <comment>Tips</comment> - <translation>我们接受意见和建设性反馈。假如您有好电子或者不喜欢的东西,告诉我们!</translation> - </message> - <message> - <source>Especially while playing online be polite and always remember there might be some minors playing with or against you as well!</source> - <comment>Tips</comment> - <translation>特别是网络游戏,请有礼貌记住对方也和您一样是人!</translation> - </message> - <message> - <source>Special game modes such as 'Vampirism' or 'Karma' allow you to develop completely new tactics. Try them in a custom game!</source> - <comment>Tips</comment> - <translation>特别游戏模式“吸血“、”因果报应“需要全新的战术。现在自定义游戏里试试!</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>Single Player</source> + <translation type="obsolete">单人游戏</translation> </message> <message> - <source>The Windows version of Hedgewars supports Xfire. Make sure to add Hedgwars to its game list so your friends can see you playing.</source> - <comment>Tips</comment> - <translation type="obsolete">Windows版本的刺猬大作战支持Xfire。添加它到游戏列表里让您的朋友看到。</translation> - </message> - <message> - <source>You should never install Hedgewars on computers you don't own (school, university, work, etc.). Please ask the responsible person instead!</source> - <comment>Tips</comment> - <translation>您不应该在不属于您的计算机上安装刺猬大作战——比如学校/工作场所等。您应当向计算机的负责人咨询!</translation> - </message> - <message> - <source>Hedgewars can be perfect for short games during breaks. Just ensure you don't add too many hedgehogs or use an huge map. Reducing time and health might help as well.</source> - <comment>Tips</comment> - <translation>刺猬大作战适合短时间休息,不需要太多刺猬挤在大地图上。</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>Net game</source> + <translation type="obsolete">网络游戏</translation> </message> <message> - <source>No hedgehogs were harmed in making this game.</source> - <comment>Tips</comment> - <translation>在制作这款游戏时没有任何刺猬受到伤害。</translation> - </message> - <message> - <source>Connect one or more gamepads before launching the game to be able to assign their controls to your teams.</source> - <comment>Tips</comment> - <translation type="obsolete">在运行游戏前连接游戏板</translation> - </message> - <message> - <source>Hedgewars is Open Source and Freeware we create in our spare time. If someone sold you the game, you should try get a refund!</source> - <comment>Tips</comment> - <translation>刺猬大作战是开放源代码的免费软件,用我们的闲暇时间创造。如果有人卖给你,那么应该把钱拿回来!</translation> - </message> - <message> - <source>Create an account on %1 to keep others from using your most favourite nickname while playing on the official server.</source> - <comment>Tips</comment> - <translation>在 %1 建立一个帐号阻止其他人使用你喜欢的名称在官方服务器游戏。</translation> - </message> - <message> - <source>There are three different jumps available. Tap [high jump] twice to do a very high/backwards jump.</source> - <comment>Tips</comment> - <translation>三种跳跃方式。点击[高跳]两次做出跳跃高度极限的后空翻。</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>Saved games</source> + <translation type="obsolete">存档</translation> </message> <message> - <source>Afraid of falling off a cliff? Hold down [precise] to turn [left] or [right] without actually moving.</source> - <comment>Tips</comment> - <translation>害怕掉下悬崖?按住[精确]后再点击[左][右]就会只转身,不移动位置。</translation> - </message> - <message> - <source>Some weapons require special strategies or just lots of training, so don't give up on a particular tool if you miss an enemy once.</source> - <comment>Tips</comment> - <translation>有些武器需要特殊策略或者仅仅是大量的练习,假如你一次失去准星,也不要放弃。</translation> - </message> - <message> - <source>Most weapons won't work once they touch the water. The Homing Bee as well as the Cake are exceptions to this.</source> - <comment>Tips</comment> - <translation>多数武器不会在接触水之后生效。归巢的蜜蜂和蛋糕是例外。</translation> - </message> - <message> - <source>The Old Limbuger only causes a small explosion. However the wind affected smelly cloud can poison lots of hogs at once.</source> - <comment>Tips</comment> - <translation>老干酪发射器造成小规模爆炸,然后产生随风移动的有毒云雾——能一次毒害多个刺猬。</translation> - </message> - <message> - <source>The Piano Strike is the most damaging air strike. You'll lose the hedgehog performing it, so there's a huge downside as well.</source> - <comment>Tips</comment> - <translation>钢琴攻击是最大威力的空袭。弹奏钢琴的刺猬会跟着钢琴返回天堂。</translation> - </message> - <message> - <source>The Homing Bee can be tricky to use. It's turn radius depends on it's velocity, so try to not use full power.</source> - <comment>Tips</comment> - <translation type="obsolete">归巢的蜜蜂有些技巧。它的回转半径和初速有关,最好不用全力发射。</translation> - </message> - <message> - <source>Sticky Mines are a perfect tool to create small chain reactions knocking enemy hedgehogs into dire situations ... or water.</source> - <comment>Tips</comment> - <translation>黏着地雷是创造小范围连锁反应的绝佳武器。</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>Demos</source> + <translation type="obsolete">Demo</translation> </message> <message> - <source>The Hammer is most effective when used on bridges or girders. Hit hogs will just break through the ground.</source> - <comment>Tips</comment> - <translation>锤是桥梁上/分界处最佳武器之一,只是刚刚好把刺猬打陷——如果没底就没办法了。</translation> - </message> - <message> - <source>If you're stuck behind an enemy hedgehog, use the Hammer to free yourself without getting damaged by an explosion.</source> - <comment>Tips</comment> - <translation>假如对方刺猬把你堵住了,一锤打下去让自己轻松些。</translation> - </message> - <message> - <source>The Cake's maximum walking distance depends on the ground it has to pass. Use [attack] to detonate it early.</source> - <comment>Tips</comment> - <translation>蛋糕的最大行走距离取决于地表。也可按下[攻击键]激活起爆。</translation> - </message> - <message> - <source>The Flame Thrower is a weapon but it can be used for tunnel digging as well.</source> - <comment>Tips</comment> - <translation>火焰喷射器是一种武器,也是一种开路机器。</translation> - </message> - <message> - <source>Use the Incinerating Grenade to temporary keep hedgehogs from passing terrain such as tunnels or platforms.</source> - <comment>Tips</comment> - <translation type="obsolete">燃烧瓶可以短时阻止刺猬通过特定区域(比如通道或平台)</translation> - </message> - <message> - <source>Want to know who's behind the game? Click on the Hedgewars logo in the main menu to see the credits.</source> - <comment>Tips</comment> - <translation>想要知道谁是此游戏的幕后人员?点击主菜单的Hedgewars Logo就可以看到贡献者名单。</translation> - </message> - <message> - <source>Like hedgewars? Become a fan on %1 or join our group at %2. You could follow us on %3 as well!</source> - <comment>Tips</comment> - <translation type="obsolete">喜欢刺猬大作战(hedgewars)?那么加入我们 %1 或者 %2.。你可以在 %3 跟随我们!</translation> - </message> - <message> - <source>You can find your Hedgewars configuration files under "My Documents\Hedgewars". Create backups or take the files with you, but don't edit them by hand.</source> - <comment>Tips</comment> - <translation>你可以在( 我的文档\Hedgewars)里找到设置文件。可以创建备份,但不要手动修改。</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>Setup</source> + <translation type="obsolete">设置</translation> </message> <message> - <source>You can find your Hedgewars configuration files under "Hedgewars" in your home directory. Create backups or take the files with you, but don't edit them by hand.</source> - <comment>Tips</comment> - <translation type="obsolete">你可以在家目录找到 .hedgewars。可以创建备份,但不要手动修改。</translation> - </message> - <message> - <source>Connect one or more gamepads before starting the game to be able to assign their controls to your teams.</source> - <comment>Tips</comment> - <translation>在游戏开始前连接游戏手柄才能用它们操控你的队伍。</translation> - </message> - <message> - <source>If your graphics card isn't able to provide hardware accelerated OpenGL, try to update the associated drivers.</source> - <comment>Tips</comment> - <translation>加入你的显卡不能使用OpenGL硬件加速,请升级相应驱动。</translation> - </message> - <message> - <source>Like Hedgewars? Become a fan on %1 or join our group at %2. You could follow us on %3 as well!</source> - <comment>Tips</comment> - <translation type="obsolete">喜欢刺猬大作战(Hedgewars)吗?加入 %2 ,成为 %1 粉丝,也可以在 %3 跟随我们!</translation> - </message> - <message> - <source>Feel free to draw your own graves, hats, flags or even maps and themes! But note that you'll have to share them somewhere to use them online.</source> - <comment>Tips</comment> - <translation>欢迎你自己绘制墓碑,帽子(头饰),旗帜或者地图,主题!但是记住,如果要在网上使用,你的必须把它们分享出来。</translation> - </message> - <message> - <source>Really want to wear a specific hat? Donate to us and receive an exclusive hat of your choice!</source> - <comment>Tips</comment> - <translation>非常想要一个帽子?捐赠的话就给你!</translation> - </message> - <message> - <source>Keep your video card drivers up to date to avoid issues playing the game.</source> - <comment>Tips</comment> - <translation>保持显卡驱动最新避免可能的麻烦。</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>About</source> + <translation type="obsolete">关于</translation> </message> <message> - <source>You're able to associate Hedgewars related files (savegames and demo recordings) with the game to launch them right from your favorite file or internet browser.</source> - <comment>Tips</comment> - <translation>你可以关联刺猬大作战的相关文件(比如存档和回放)到本游戏以便在网络或文件浏览器中直接打开这些文件。</translation> - </message> - <message> - <source>Want to save ropes? Release the rope in mid air and then shoot again. As long as you don't touch the ground you'll reuse your rope without wasting ammo!</source> - <comment>Tips</comment> - <translation>想要节省绳子?放开绳子之后再次发射,只要你不曾脱离绳子接触接触地面就可以继续使用同一根!</translation> - </message> - <message> - <source>Like Hedgewars? Become a fan on %1 or follow us on %2!</source> - <comment>Tips</comment> - <translation>喜欢刺猬大作战Hedgewars吗?来 %1 或者 %2 追随我们吧!</translation> - </message> - <message> - <source>You can find your Hedgewars configuration files under "Library/Application Support/Hedgewars" in your home directory. Create backups or take the files with you, but don't edit them by hand.</source> - <comment>Tips</comment> - <translation>在家目录的"Library/Application Support/Hedgewars"找到刺猬的配置文件。备份随你,但是不要手动编辑。</translation> + <location filename="../../../../QTfrontend/statsPage.cpp" line="0"/> + <source>Exit</source> + <translation type="obsolete">退出</translation> </message> <message> - <source>You can find your Hedgewars configuration files under ".hedgewars" in your home directory. Create backups or take the files with you, but don't edit them by hand.</source> - <comment>Tips</comment> - <translation>在家目录的".hedgewars"找到刺猬的配置文件。备份随你,但是不要手动编辑。</translation> - </message> - <message> - <source>The Windows version of Hedgewars supports Xfire. Make sure to add Hedgewars to its game list so your friends can see you playing.</source> - <comment>Tips</comment> - <translation>Windows版本的刺猬大作战支持Xfire。您可以添加刺猬大作战到它的游戏列表里让您的朋友看到。</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="81"/> + <source>Local Game (Play a game on a single computer)</source> + <translation>本地游戏(在一台电脑上)</translation> </message> <message> - <source>Use the Molotov or Flame Thrower to temporary keep hedgehogs from passing terrain such as tunnels or platforms.</source> - <comment>Tips</comment> - <translation>使用燃烧瓶或火焰喷射器可以短时阻止刺猬通过特定区域(比如隧道或平台).</translation> - </message> - <message> - <source>The Homing Bee can be tricky to use. Its turn radius depends on its velocity, so try to not use full power.</source> - <comment>Tips</comment> - <translation>使用归巢的蜜蜂有些技巧,它的回转半径和发射速度有关,所以最好不要全力发射。</translation> - </message> - <message> - <source>Downloadable Content</source> - <translation>可下载内容</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="85"/> + <source>Network Game (Play a game across a network)</source> + <translation>网络游戏(通过网络)</translation> </message> </context> <context> <name>PageMultiplayer</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Back</source> + <translation type="obsolete">返回</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="309"/> <source>Start</source> <translation>开始</translation> </message> @@ -900,40 +441,43 @@ <context> <name>PageNet</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Local</source> + <translation type="obsolete">本地</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Internet</source> + <translation type="obsolete">Internet</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="520"/> <source>Error</source> <translation>错误</translation> </message> <message> - <source>Please select server from the list above</source> + <location filename="../../../../QTfrontend/pages.cpp" line="520"/> + <source>Please, select server from the list above</source> <translation>请选择一个服务器</translation> </message> </context> <context> <name>PageNetGame</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="626"/> <source>Control</source> - <translation>房间管理</translation> - </message> - <message> - <source>Error</source> - <translation>错误</translation> - </message> - <message> - <source>Please enter room name</source> - <translation>请键入房间名</translation> - </message> - <message> - <source>OK</source> - <translation>确定</translation> + <translation>Ctrl</translation> </message> </context> <context> <name>PageNetType</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="1097"/> <source>LAN game</source> <translation>局域网游戏</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="1098"/> <source>Official server</source> <translation>官方服务器</translation> </message> @@ -941,925 +485,681 @@ <context> <name>PageOptions</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="344"/> <source>New team</source> <translation>新队伍</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="345"/> <source>Edit team</source> <translation>修改队伍设定</translation> </message> <message> - <source>Delete team</source> - <translation>删除队伍</translation> - </message> - <message> - <source>New weapon scheme</source> - <translation type="obsolete">新武器配置</translation> - </message> - <message> - <source>Edit weapon scheme</source> - <translation type="obsolete">修改武器配置</translation> - </message> - <message> - <source>Delete weapon scheme</source> - <translation type="obsolete">删除武器配置</translation> - </message> - <message> - <source>You can't edit teams from team selection. Go back to main menu to add, edit or delete teams.</source> - <translation>您不能在队伍选择界面修改队伍。请返回主页面进行添加、修改、删除队伍等操作。</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Save</source> + <translation type="obsolete">保存</translation> </message> <message> - <source>New scheme</source> - <translation>新框架</translation> - </message> - <message> - <source>Edit scheme</source> - <translation>修改框架</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Back</source> + <translation type="obsolete">返回</translation> </message> <message> - <source>Delete scheme</source> - <translation>删除框架</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="373"/> + <source>Weapons set</source> + <translation>新武器设定</translation> </message> <message> - <source>New weapon set</source> - <translation>新武器配置</translation> - </message> - <message> - <source>Edit weapon set</source> - <translation>修改武器配置</translation> - </message> - <message> - <source>Delete weapon set</source> - <translation>删除武器配置</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="376"/> + <source>Edit</source> + <translation>修改当前武器设定</translation> </message> </context> <context> <name>PagePlayDemo</name> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="149"/> <source>Error</source> <translation>错误</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="137"/> + <source>Please, select record from the list</source> + <translation>请从列表选择记录</translation> + </message> + <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="138"/> <source>OK</source> <translation>确认</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="113"/> <source>Rename dialog</source> <translation>重命名对话框</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="113"/> <source>Enter new file name:</source> <translation>输入新的文件名:</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="124"/> <source>Cannot rename to</source> <translation>不能改变名字</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="149"/> <source>Cannot delete file</source> <translation>不能删除文件</translation> </message> - <message> - <source>Please select record from the list</source> - <translation>请从列表选择记录</translation> - </message> </context> <context> <name>PageRoomsList</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="764"/> <source>Create</source> <translation>建立</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="765"/> <source>Join</source> <translation>加入</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="766"/> <source>Refresh</source> <translation>刷新</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="828"/> <source>Error</source> <translation>错误</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="818"/> + <source>Please, enter room name</source> + <translation>请键入房间名</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="830"/> <source>OK</source> <translation>确认</translation> </message> <message> - <source>Admin features</source> - <translation>管理员功能</translation> - </message> - <message> - <source>Room Name:</source> - <translation>房间名:</translation> - </message> - <message> - <source>This game is in lobby. -You may join and start playing once the game starts.</source> - <translation>游戏正在大厅中。 -您可以加入等待游戏开始。</translation> - </message> - <message> - <source>This game is in progress. -You may join and spectate now but you'll have to wait for the game to end to start playing.</source> - <translation>游戏正在进行中。 -您可以加入观战但必须等游戏结束才能参与游戏。</translation> - </message> - <message> - <source>%1 is the host. He may adjust settings and start the game.</source> - <translation>%1 是房主,他可以调整设置、开始游戏。</translation> - </message> - <message> - <source>Random Map</source> - <translation>随机地图</translation> - </message> - <message> - <source>Games may be played on precreated or randomized maps.</source> - <translation>游戏可以在预先创建或者随机产生的地图上进行。</translation> - </message> - <message> - <source>The Game Scheme defines general options and preferences like Round Time, Sudden Death or Vampirism.</source> - <translation>游戏设置包括一般选项例如回合时间,突然死亡或吸血模式。</translation> - </message> - <message> - <source>The Weapon Scheme defines available weapons and their ammunition count.</source> - <translation>武器配置包括可以选用的武器和弹药数量。</translation> - </message> - <message numerus="yes"> - <source>There are %1 clients connected to this room.</source> - <translation> - <numerusform>有 %1 个客户端连接到这个房间。</numerusform> - </translation> - </message> - <message numerus="yes"> - <source>There are %1 teams participating in this room.</source> - <translation> - <numerusform>有 %1 个队伍加入这个房间。</numerusform> - </translation> - </message> - <message> - <source>Please enter room name</source> - <translation>请键入房间名</translation> - </message> - <message> - <source>Please select room from the list</source> + <location filename="../../../../QTfrontend/pages.cpp" line="829"/> + <source>Please, select room from the list</source> <translation>请从列表选中房间</translation> </message> <message> - <source>Random Maze</source> - <translation>随机迷宫</translation> - </message> - <message> - <source>State:</source> - <translation type="obsolete">游戏状态</translation> - </message> - <message> - <source>Rules:</source> - <translation>规则</translation> - </message> - <message> - <source>Weapons:</source> - <translation>武器</translation> - </message> - <message> - <source>Search:</source> - <translation>搜索</translation> - </message> - <message> - <source>Clear</source> - <translation>清除</translation> - </message> - <message> - <source>Warning</source> - <translation>警告</translation> - </message> - <message> - <source>The game you are trying to join has started. -Do you still want to join the room?</source> - <translation>你要加入的游戏已经开始了。 -还要进入房间吗?</translation> - </message> - <message numerus="yes"> - <source>%1 players online</source> - <translation> - <numerusform>%1 个玩家在线</numerusform> - </translation> + <location filename="../../../../QTfrontend/pages.cpp" line="769"/> + <source>Admin features</source> + <translation>管理员功能</translation> </message> </context> <context> <name>PageScheme</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="1008"/> <source>New</source> - <translation>新模式</translation> - </message> - <message> - <source>Delete</source> - <translation>删除</translation> - </message> - <message> - <source>Defend your fort and destroy the opponents, two team colours max!</source> - <translation>保卫你的城堡,破坏对手的,努力吧!</translation> - </message> - <message> - <source>Teams will start on opposite sides of the terrain, two team colours max!</source> - <translation>队伍开始在对手的地盘,努力!</translation> - </message> - <message> - <source>Land can not be destroyed!</source> - <translation>地面无法破坏!</translation> - </message> - <message> - <source>Add an indestructable border around the terrain</source> - <translation type="obsolete">添加不可毁坏地边界</translation> - </message> - <message> - <source>Lower gravity</source> - <translation>低重力</translation> - </message> - <message> - <source>Assisted aiming with laser sight</source> - <translation>激光瞄准辅助</translation> - </message> - <message> - <source>All hogs have a personal forcefield</source> - <translation>每个刺猬都有一个力场</translation> - </message> - <message> - <source>Enable random mines</source> - <translation type="obsolete">开启随机地雷</translation> - </message> - <message> - <source>Gain 80% of the damage you do back in health</source> - <translation>伤害的80%变成自身力量</translation> - </message> - <message> - <source>Share your opponents pain, share their damage</source> - <translation>分担你的对手的疼痛</translation> - </message> - <message> - <source>Your hogs are unable to move, put your artillery skills to the test</source> - <translation>你的刺猬不能移动,检验你射击技巧的时候到了</translation> - </message> - <message> - <source>Random</source> - <translation>随机</translation> - </message> - <message> - <source>Seconds</source> - <translation>秒钟</translation> + <translation>新游戏</translation> </message> <message> - <source>Order of play is random instead of in room order.</source> - <translation>出场顺序是随机的而不是按照房间顺序。</translation> - </message> - <message> - <source>Play with a King. If he dies, your side dies.</source> - <translation>国王不能死。</translation> - </message> - <message> - <source>Take turns placing your hedgehogs before the start of play.</source> - <translation>在开局前轮流手动放置刺猬。</translation> - </message> - <message> - <source>Ammo is shared between all teams that share a colour.</source> - <translation>同色队伍共享所有弹药。</translation> - </message> - <message> - <source>Disable girders when generating random maps.</source> - <translation>禁止随机生成地图时使用梁。</translation> - </message> - <message> - <source>Disable land objects when generating random maps.</source> - <translation type="unfinished">禁止随机生成地图时使用地面物体。</translation> - </message> - <message> - <source>AI respawns on death.</source> - <translation>AI 死亡再生。</translation> - </message> - <message> - <source>Attacking does not end your turn.</source> - <translation>攻击不会结束当前回合。</translation> - </message> - <message> - <source>Weapons are reset to starting values each turn.</source> - <translation>在每回合武器将自动重置到开始设定。</translation> - </message> - <message> - <source>Each hedgehog has its own ammo. It does not share with the team.</source> - <translation>每个刺猬都有独立的弹药,而非团队分享。</translation> - </message> - <message> - <source>All (living) hedgehogs are fully restored at the end of turn</source> - <translation>所有活着的刺猬在回合结束时完全恢复健康</translation> - </message> - <message> - <source>You will not have to worry about wind anymore.</source> - <translation>不用担心风的影响了。</translation> - </message> - <message> - <source>Wind will affect almost everything.</source> - <translation>风无所不在。</translation> - </message> - <message> - <source>Copy</source> - <translation>备份</translation> - </message> - <message> - <source>Teams in each clan take successive turns sharing their turn time.</source> - <translation>在同一集团中的队伍在共用的回合时间里使用连续的回合。</translation> - </message> - <message> - <source>Add an indestructible border around the terrain</source> - <translation>添加不可毁坏地边界</translation> - </message> - <message> - <source>Add an indestructible border along the bottom</source> - <translation>在底部添加一个不可毁坏的边界</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="1009"/> + <source>Delete</source> + <translation>删除</translation> </message> </context> <context> <name>PageSelectWeapon</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Back</source> + <translation type="obsolete">返回</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="729"/> <source>Default</source> <translation>默认</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="730"/> <source>Delete</source> <translation>删除</translation> </message> <message> - <source>New</source> - <translation>新模式</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Save</source> + <translation type="obsolete">保存</translation> + </message> +</context> +<context> + <name>PageSimpleGame</name> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Back</source> + <translation type="obsolete">返回</translation> </message> <message> - <source>Copy</source> - <translation>备份</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Simple Game</source> + <translation type="obsolete">简单游戏</translation> </message> </context> <context> <name>PageSinglePlayer</name> <message> - <source>Simple Game (a quick game against the computer, settings are chosen for you)</source> - <translation>快速游戏 (使用预设对抗电脑)</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Simple Game</source> + <translation type="obsolete">简单游戏</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Training</source> + <translation type="obsolete">训练</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Multiplayer</source> + <translation type="obsolete">多人游戏</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Saved games</source> + <translation type="obsolete">游戏存档</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Demos</source> + <translation type="obsolete">Demo</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="685"/> + <source>Simple Game (a quick game against the computer, settings are chosen for you)</source> + <translation>快速游戏 (对抗电脑,固定设置)</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="688"/> <source>Multiplayer (play a hotseat game against your friends, or AI teams)</source> <translation>多人游戏 (热坐对抗朋友或AI)</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="693"/> <source>Training Mode (Practice your skills in a range of training missions). IN DEVELOPMENT</source> - <translation type="obsolete">训练模式 (一系列训练任务)。开发中</translation> + <translation>训练模式 (一系列训练任务)。开发中</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="699"/> <source>Demos (Watch recorded demos)</source> <translation>Demo (观看记录的Demo)</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="702"/> <source>Load (Load a previously saved game)</source> <translation>读取 (读取之前保存的游戏)</translation> </message> - <message> - <source>Campaign Mode (...). IN DEVELOPMENT</source> - <translation type="obsolete">战役模式 ——开发中</translation> - </message> - <message> - <source>Campaign Mode (...)</source> - <translation>战役模式 (...)</translation> - </message> - <message> - <source>Training Mode (Practice your skills in a range of training missions)</source> - <translation>训练模式(在一系列训练任务中练习你的技能)</translation> - </message> -</context> -<context> - <name>PageTraining</name> - <message> - <source>No description available</source> - <translation>没有可用描述</translation> - </message> - <message> - <source>Select a mission!</source> - <translation>选择一个任务!</translation> - </message> </context> <context> <name>QAction</name> <message> + <location filename="../../../../QTfrontend/chatwidget.cpp" line="62"/> <source>Kick</source> - <translation>踢出</translation> + <translation>踢</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="638"/> <source>Start</source> <translation>开始</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="628"/> <source>Restrict Joins</source> <translation>限制参与</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="630"/> <source>Restrict Team Additions</source> - <translation>限制增加团队</translation> + <translation>限制团队插件</translation> </message> <message> + <location filename="../../../../QTfrontend/chatwidget.cpp" line="60"/> <source>Info</source> <translation>信息</translation> </message> <message> + <location filename="../../../../QTfrontend/chatwidget.cpp" line="64"/> <source>Ban</source> <translation>屏蔽</translation> </message> - <message> - <source>Follow</source> - <translation>跟随</translation> - </message> - <message> - <source>Ignore</source> - <translation>忽略</translation> - </message> - <message> - <source>Add friend</source> - <translation>添加朋友</translation> - </message> - <message> - <source>Unignore</source> - <translation>取消忽略</translation> - </message> - <message> - <source>Remove friend</source> - <translation>移除朋友</translation> - </message> - <message> - <source>Update</source> - <translation>更新</translation> - </message> </context> <context> <name>QCheckBox</name> <message> - <source>Check for updates at startup</source> - <translation>启动时检查程序升级</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="415"/> + <source>Enable sound</source> + <translation>开启音效</translation> </message> <message> - <source>Enable sound</source> - <translation>开启游戏音效</translation> - </message> - <message> + <location filename="../../../../QTfrontend/pages.cpp" line="407"/> <source>Fullscreen</source> <translation>游戏全屏幕</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="861"/> + <source>Forts mode</source> + <translation type="obsolete">城堡模式</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="434"/> <source>Show FPS</source> <translation>显示帧率 (FPS)</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="438"/> <source>Alternative damage show</source> <translation>另一种伤害显示方式</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="419"/> <source>Enable music</source> - <translation>开启游戏音乐</translation> + <translation>开启音乐</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="411"/> <source>Frontend fullscreen</source> - <translation>前端界面全屏幕</translation> - </message> - <message> - <source>Append date and time to record file name</source> - <translation>记录名称中包含具体时间和日期</translation> + <translation>界面全屏幕</translation> </message> <message> - <source>Reduced quality</source> - <translation type="obsolete">降低显示效果</translation> - </message> - <message> - <source>Show ammo menu tooltips</source> - <translation>显示武器菜单提示</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="865"/> + <source>Divide teams</source> + <translation type="obsolete">分组</translation> </message> <message> - <source>Enable frontend sounds</source> - <translation>开启前端界面音效</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="442"/> + <source>Append date and time to record file name</source> + <translation>记录名称中包含具体时间日期</translation> </message> <message> - <source>Enable frontend music</source> - <translation>开启前端界面音乐</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="869"/> + <source>Solid land</source> + <translation type="obsolete">固实地面</translation> </message> <message> - <source>Frontend effects</source> - <translation>前端界面效果</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="403"/> + <source>Reduce Quality</source> + <translation>降低质量</translation> </message> </context> <context> <name>QComboBox</name> <message> + <location filename="../../../../QTfrontend/mapContainer.cpp" line="62"/> <source>generated map...</source> <translation>生成地图...</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="171"/> <source>Human</source> <translation>玩家</translation> </message> <message> - <source>Level</source> - <translation>Lv 级别</translation> - </message> - <message> - <source>(System default)</source> - <translation>(系统默认)</translation> - </message> - <message> - <source>generated maze...</source> - <translation>生成迷宫...</translation> - </message> - <message> - <source>Mission</source> - <translation>任务</translation> - </message> - <message> - <source>Community</source> - <translation>社区</translation> - </message> - <message> - <source>Any</source> - <translation>任意</translation> - </message> - <message> - <source>In lobby</source> - <translation>大厅中</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Level 5</source> + <translation type="obsolete">Lv 5</translation> </message> <message> - <source>In progress</source> - <translation>进行中</translation> - </message> - <message> - <source>Default</source> - <translation type="obsolete">默认</translation> - </message> - <message> - <source>Pro mode</source> - <translation type="obsolete">高手模式</translation> - </message> - <message> - <source>Shoppa</source> - <translation type="obsolete">绳子党</translation> - </message> - <message> - <source>Basketball</source> - <translation type="obsolete">篮球</translation> - </message> - <message> - <source>Minefield</source> - <translation type="obsolete">雷区</translation> - </message> - <message> - <source>Barrel mayhem</source> - <translation type="obsolete">炼狱场</translation> - </message> - <message> - <source>Tunnel hogs</source> - <translation type="obsolete">刺猬洞</translation> - </message> - <message> - <source>Crazy</source> - <translation type="obsolete">疯狂刺猬</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Level 4</source> + <translation type="obsolete">Lv 4</translation> </message> <message> - <source>hand drawn map...</source> - <translation>手绘地图...</translation> - </message> - <message> - <source>Disabled</source> - <translation>禁用</translation> - </message> - <message> - <source>Red/Cyan</source> - <translation>红/青</translation> - </message> - <message> - <source>Cyan/Red</source> - <translation>青/红</translation> - </message> - <message> - <source>Red/Blue</source> - <translation>红/蓝</translation> - </message> - <message> - <source>Blue/Red</source> - <translation>蓝/红</translation> - </message> - <message> - <source>Red/Green</source> - <translation>红/绿</translation> - </message> - <message> - <source>Green/Red</source> - <translation>绿/红</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Level 3</source> + <translation type="obsolete">Lv 3</translation> </message> <message> - <source>Side-by-side</source> - <translation>横向排列</translation> - </message> - <message> - <source>Top-Bottom</source> - <translation>自顶向下</translation> - </message> - <message> - <source>Wiggle</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Red/Cyan grayscale</source> - <translation type="unfinished">红/青 灰度</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Level 2</source> + <translation type="obsolete">Lv 2</translation> </message> <message> - <source>Cyan/Red grayscale</source> - <translation type="unfinished">青/红 灰度</translation> - </message> - <message> - <source>Red/Blue grayscale</source> - <translation type="unfinished">红/蓝 灰度</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Level 1</source> + <translation type="obsolete">Lv 1</translation> </message> <message> - <source>Blue/Red grayscale</source> - <translation type="unfinished">蓝/红 灰度</translation> - </message> - <message> - <source>Red/Green grayscale</source> - <translation type="unfinished">红/绿 灰度</translation> - </message> - <message> - <source>Green/Red grayscale</source> - <translation type="unfinished">绿/红 灰度</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="175"/> + <source>Level</source> + <translation>Lv 级别</translation> </message> </context> <context> <name>QGroupBox</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="126"/> <source>Team Members</source> <translation>成员</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="161"/> + <source>Team</source> + <translation>队伍</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="202"/> <source>Fort</source> <translation>城堡模式</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="236"/> <source>Key binds</source> <translation>键位绑定</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="335"/> <source>Teams</source> <translation>队伍</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="384"/> <source>Audio/Graphic options</source> <translation>音频/视频选项</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Net nick</source> + <translation type="obsolete">昵称</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Net options</source> + <translation type="obsolete">网络选项</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Landscape</source> + <translation type="obsolete">地形</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Game scheme</source> + <translation type="obsolete">游戏设置</translation> + </message> + <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="228"/> <source>Playing teams</source> <translation>玩家队伍</translation> </message> <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="0"/> + <source>Team level</source> + <translation type="obsolete">队伍级别</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="473"/> <source>Net game</source> - <translation>局域网络游戏</translation> + <translation>网络游戏</translation> </message> <message> - <source>Weapons</source> - <translation type="obsolete">武器</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Servers list</source> + <translation type="obsolete">服务器列表</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="370"/> + <source>Weapons</source> + <translation>武器</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="862"/> + <source>Scheme options</source> + <translation type="obsolete">游戏设定</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="866"/> <source>Game Modifiers</source> <translation>游戏修改</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="867"/> <source>Basic Settings</source> <translation>基本设置</translation> </message> - <message> - <source>Team Settings</source> - <translation>队伍设定</translation> - </message> - <message> - <source>Misc</source> - <translation>杂项</translation> - </message> - <message> - <source>Schemes and Weapons</source> - <translation>游戏框架和武器配置</translation> - </message> </context> <context> <name>QLabel</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="353"/> <source>Net nick</source> <translation>网络游戏昵称</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Server address</source> + <translation type="obsolete">服务器地址</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source><div align="center"><h1>Hedgewars</h1><h3>Version 0.8</h3><p><a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a></p><br>This program is distributed under the GNU General Public License</div></source> + <translation type="obsolete"><div align="center"><h1>刺猬大作战</h1><h3>0.8</h3><p><a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a></p><br>This program is distributed under the GNU General Public License</div></translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source><h2>Developers:</h2><p>Andrey Korotaev &lt;<a href="mailto:unC0Rr@gmail.com">unC0Rr@gmail.com</a>&gt;<br>Igor Ulyanov &lt;<a href="mailto:iulyanov@gmail.com">iulyanov@gmail.com</a>&gt;</p><h2>Translations:</h2>english: Andrey Korotaev &lt;<a href="mailto:unC0Rr@gmail.com">unC0Rr@gmail.com</a>&gt;<br>russian: Andrey Korotaev &lt;<a href="mailto:unC0Rr@gmail.com">unC0Rr@gmail.com</a>&gt;</source> + <translation type="obsolete"><h2>Developers:</h2><p>Andrey Korotaev &lt;<a href="mailto:unC0Rr@gmail.com">unC0Rr@gmail.com</a>&gt;<br>Igor Ulyanov &lt;<a href="mailto:iulyanov@gmail.com">iulyanov@gmail.com</a>&gt;</p><h2>Translations:</h2>english: Andrey Korotaev &lt;<a href="mailto:unC0Rr@gmail.com">unC0Rr@gmail.com</a>&gt;<br>russian: Andrey Korotaev &lt;<a href="mailto:unC0Rr@gmail.com">unC0Rr@gmail.com</a>&gt;</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>difficulty:</source> + <translation type="obsolete">难度:</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source><h3>Version 0.8</h3></source> + <translation type="obsolete"><h3>版本 0.8</h3></translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="46"/> <source>This program is distributed under the GNU General Public License</source> - <translation type="obsolete">This program is distributed under the GNU General Public License</translation> + <translation>This program is distributed under the GNU General Public License</translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="0"/> + <source><h2>Translations:</h2></source> + <translation type="obsolete"><h2>翻译:</h2></translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="0"/> + <source><h2>Developers:</h2></source> + <translation type="obsolete"><h2>开发者:</h2></translation> </message> <message> + <location filename="../../../../QTfrontend/about.cpp" line="0"/> + <source><h2>Translations:</h2><p></source> + <translation type="obsolete"><h2>翻译:</h2><p></translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="0"/> + <source><h2>Special thanks:</h2><p></source> + <translation type="obsolete"><h2>特别感谢:</h2><p></translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="0"/> + <source><h3>Version 0.8.1</h3></source> + <translation type="obsolete"><h3>版本 0.8.1</h3></translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="0"/> + <source><h2></h2><p></p></source> + <translation type="obsolete"><h2></h2><p></p></translation> + </message> + <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="62"/> + <source>Turn time</source> + <translation type="obsolete">回合时间</translation> + </message> + <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="63"/> + <source>Initial health</source> + <translation type="obsolete">初始生命值</translation> + </message> + <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="687"/> + <source><p>The best shot award was won by <b>%1</b> with <b>%2</b> pts.</p></source> + <translation type="obsolete"><p>射击冠军<b>%1</b> with <b>%2</b> .</p></translation> + </message> + <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="699"/> + <source><p>A total of <b>%1</b> Hedgehog(s) were killed during this round.</p></source> + <translation type="obsolete"><p>阵亡<b>%1</b> </p></translation> + </message> + <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="0"/> + <source><h3>Version 0.9</h3></source> + <translation type="obsolete"><h3>版本0.9</h3></translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="389"/> <source>Resolution</source> <translation>分辨率</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="398"/> <source>FPS limit</source> <translation>FPS 上限</translation> </message> <message> + <location filename="../../../../QTfrontend/about.cpp" line="61"/> <source>Developers:</source> <translation>开发者:</translation> </message> <message> + <location filename="../../../../QTfrontend/about.cpp" line="71"/> <source>Art:</source> <translation>艺术:</translation> </message> <message> + <location filename="../../../../QTfrontend/about.cpp" line="91"/> <source>Translations:</source> <translation>翻译:</translation> </message> <message> + <location filename="../../../../QTfrontend/about.cpp" line="111"/> <source>Special thanks:</source> <translation>特别感谢:</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="564"/> <source>Server name:</source> <translation>服务器名:</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="571"/> <source>Server port:</source> <translation>服务器端口:</translation> </message> <message> + <location filename="../../../../QTfrontend/input_ip.cpp" line="32"/> <source>Host:</source> <translation>主机:</translation> </message> <message> + <location filename="../../../../QTfrontend/input_ip.cpp" line="36"/> <source>Port:</source> <translation>端口:</translation> </message> <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="61"/> <source>Weapons</source> <translation>武器</translation> </message> <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="0"/> + <source><h3>Version 0.9.2</h3></source> + <translation type="obsolete"><h3>版本0.9.2</h3></translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="43"/> <source>Version</source> <translation>版本</translation> </message> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="694"/> + <source><p>The best shot award was won by <b>%1</b> with <b>%2</b> kills.</p></source> + <translation type="obsolete"><p>最佳射手<b>%1</b>取得的战果 <b>%2</b></p></translation> + </message> + <message> + <location filename="../../../../QTfrontend/about.cpp" line="83"/> <source>Sounds:</source> <translation>声音:</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="424"/> <source>Initial sound volume</source> <translation>初始音量</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="923"/> <source>Damage Modifier</source> - <translation>伤害修正值</translation> + <translation>伤害修改</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="938"/> <source>Turn Time</source> <translation>回合时间</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="953"/> <source>Initial Health</source> <translation>初始生命值</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="968"/> <source>Sudden Death Timeout</source> <translation>死亡模式倒计时</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="980"/> + <source>Case Probability</source> + <translation type="obsolete">箱子掉落几率</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="998"/> <source>Scheme Name:</source> <translation>设置名称:</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="983"/> <source>Crate Drops</source> <translation>箱子降落</translation> </message> <message> + <location filename="../../../../QTfrontend/gamecfgwidget.cpp" line="53"/> <source>Game scheme</source> <translation>游戏设置</translation> </message> - <message> - <source>Mines Time</source> - <translation>布雷时间</translation> - </message> - <message> - <source>Mines</source> - <translation>地雷</translation> - </message> - <message> - <source>% Dud Mines</source> - <translation>% 地雷故障</translation> - </message> - <message> - <source>Name</source> - <translation>名称</translation> - </message> - <message> - <source>Type</source> - <translation>类型</translation> - </message> - <message> - <source>Grave</source> - <translation>墓碑</translation> - </message> - <message> - <source>Flag</source> - <translation>旗帜</translation> - </message> - <message> - <source>Voice</source> - <translation>声音</translation> - </message> - <message> - <source>Locale</source> - <translation>Locale</translation> - </message> - <message> - <source>Restart game to apply</source> - <translation>需要重新启动游戏方可应用</translation> - </message> - <message> - <source>Explosives</source> - <translation>爆炸物</translation> - </message> - <message> - <source>Tip: </source> - <translation>提示:</translation> - </message> - <message> - <source>This development build is 'work in progress' and may not be compatible with other versions of the game. Some features might be broken or incomplete. Use at your own risk!</source> - <translation>当前运行的为开发版本,不同其他版本兼容。功能或许损坏、不完整。请自行承担风险!</translation> - </message> - <message> - <source>Quality</source> - <translation>图像质量</translation> - </message> - <message> - <source>Sudden Death Water Rise</source> - <translation>死亡模式水位上涨</translation> - </message> - <message> - <source>Sudden Death Health Decrease</source> - <translation>死亡模式健康降低</translation> - </message> - <message> - <source>% Rope Length</source> - <translation>% 绳长</translation> - </message> - <message> - <source>% Health Crates</source> - <translation>% 生命箱</translation> - </message> - <message> - <source>Health in Crates</source> - <translation>生命箱的值数</translation> - </message> - <message> - <source>Gameplay</source> - <translation type="obsolete">游戏</translation> - </message> - <message> - <source>Stereo rendering</source> - <translation>立体渲染</translation> - </message> - <message> - <source>Style</source> - <translation type="unfinished">样式</translation> - </message> - <message> - <source>Scheme</source> - <translation type="unfinished">模式</translation> - </message> - <message> - <source>Password</source> - <translation>密码</translation> - </message> - <message> - <source>% Get Away Time</source> - <translation>% 脱身时间</translation> - </message> - <message> - <source>This program is distributed under the GNU General Public License v2</source> - <translation>本程序在GNU通用许可证协议第二版(GNU GPLv2)下发布</translation> - </message> </context> <context> <name>QLineEdit</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="358"/> <source>unnamed</source> <translation>无名</translation> </message> - <message> - <source>hedgehog %1</source> - <translation>刺猬 %1</translation> - </message> </context> <context> <name>QMainWindow</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>-= by unC0Rr =-</source> + <translation type="obsolete">-= by unC0Rr =-</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Hedgewars</source> + <translation type="obsolete">刺猬大作战</translation> + </message> + <message> + <location filename="../../../../QTfrontend/ui_hwform.cpp" line="37"/> <source>Hedgewars %1</source> <translation>刺猬大作战 %1</translation> </message> @@ -1867,10 +1167,12 @@ <context> <name>QMessageBox</name> <message> + <location filename="../../../../QTfrontend/main.cpp" line="272"/> <source>Error</source> <translation>错误</translation> </message> <message> + <location filename="../../../../QTfrontend/main.cpp" line="275"/> <source>Failed to open data directory: %1 Please check your installation</source> @@ -1879,233 +1181,292 @@ 请检查</translation> </message> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="685"/> <source>Network</source> <translation>网络</translation> </message> <message> + <location filename="../../../../QTfrontend/hwform.cpp" line="686"/> <source>Connection to server is lost</source> - <translation>与服务器的连接丢失</translation> + <translation>服务器连接丢失</translation> </message> <message> + <location filename="../../../../QTfrontend/selectWeapon.cpp" line="170"/> <source>Weapons</source> <translation>武器</translation> </message> <message> + <location filename="../../../../QTfrontend/selectWeapon.cpp" line="165"/> <source>Can not delete default weapon set</source> - <translation type="obsolete">不能删除默认武器设定</translation> + <translation>不能删除默认武器设定</translation> </message> <message> + <location filename="../../../../QTfrontend/selectWeapon.cpp" line="170"/> <source>Really delete this weapon set?</source> <translation>真的删除这个武器设定吗?</translation> </message> <message> + <location filename="../../../../QTfrontend/selectWeapon.cpp" line="127"/> <source>Can not edit default weapon set</source> - <translation type="obsolete">不能更改默认的武器设定</translation> - </message> - <message> - <source>Can not overwrite default weapon set '%1'!</source> - <translation>不能覆盖默认的武器配置 '%1'!</translation> - </message> - <message> - <source>All file associations have been set.</source> - <translation>所有相关文件已经设定。</translation> - </message> - <message> - <source>Teams</source> - <translation>队伍</translation> - </message> - <message> - <source>Really delete this team?</source> - <translation>真的要删除队伍?</translation> - </message> - <message> - <source>Schemes</source> - <translation>游戏框架</translation> - </message> - <message> - <source>Can not delete default scheme '%1'!</source> - <translation>无法删除默认游戏框架 '%1'!</translation> - </message> - <message> - <source>File association failed.</source> - <translation>文件关联失败。</translation> - </message> - <message> - <source>Really delete this game scheme?</source> - <translation>真的删除此游戏框架?</translation> - </message> - <message> - <source>Can not delete default weapon set '%1'!</source> - <translation>无法删除武器配置%1'!</translation> + <translation>不能更改默认的武器设定</translation> </message> </context> <context> <name>QObject</name> <message> + <location filename="../../../../QTfrontend/main.cpp" line="35"/> <source>Error</source> <translation>错误</translation> </message> <message> + <location filename="../../../../QTfrontend/main.cpp" line="36"/> <source>Cannot create directory %1</source> <translation>无法创建路径 %1</translation> </message> <message> - <source>OK</source> - <translation>确认</translation> + <location filename="../../../../QTfrontend/main.cpp" line="0"/> + <source>Quit</source> + <translation type="obsolete">退出</translation> </message> <message> - <source>Nickname</source> - <translation>昵称</translation> - </message> - <message> - <source>Please enter your nickname</source> - <translation>请输入您的昵称</translation> + <location filename="../../../../QTfrontend/main.cpp" line="37"/> + <source>OK</source> + <translation>确认</translation> </message> </context> <context> <name>QPushButton</name> <message> + <location filename="../../../../QTfrontend/main.cpp" line="0"/> + <source>Single Player</source> + <translation type="obsolete">单人游戏</translation> + </message> + <message> + <location filename="../../../../QTfrontend/main.cpp" line="0"/> + <source>Multiplayer</source> + <translation type="obsolete">多人游戏</translation> + </message> + <message> + <location filename="../../../../QTfrontend/main.cpp" line="0"/> + <source>Net game</source> + <translation type="obsolete">网络游戏</translation> + </message> + <message> + <location filename="../../../../QTfrontend/main.cpp" line="0"/> + <source>Demos</source> + <translation type="obsolete">Demo</translation> + </message> + <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="237"/> <source>Setup</source> <translation>设置</translation> </message> <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="0"/> + <source>Exit</source> + <translation type="obsolete">退出</translation> + </message> + <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="0"/> + <source>Back</source> + <translation type="obsolete">返回</translation> + </message> + <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="0"/> + <source>Simple Game</source> + <translation type="obsolete">简单游戏</translation> + </message> + <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="0"/> + <source>Discard</source> + <translation type="obsolete">中止</translation> + </message> + <message> + <location filename="../../../../QTfrontend/teamselect.cpp" line="0"/> + <source>Save</source> + <translation type="obsolete">保存</translation> + </message> + <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="75"/> <source>Play demo</source> <translation>播放 demo</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="0"/> + <source>New team</source> + <translation type="obsolete">新队伍</translation> + </message> + <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="0"/> + <source>Edit team</source> + <translation type="obsolete">编辑队伍</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="482"/> <source>Connect</source> <translation>连接</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Disconnect</source> + <translation type="obsolete">失去连接</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Join</source> + <translation type="obsolete">加入</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Create</source> + <translation type="obsolete">创建</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Add Team</source> + <translation type="obsolete">添加队伍</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="714"/> <source>Go!</source> <translation>上场!</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="544"/> <source>Start</source> <translation>开始</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>About</source> + <translation type="obsolete">关于</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="466"/> <source>Start server</source> <translation>开始服务端</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="491"/> <source>Update</source> <translation>更新</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="0"/> + <source>Waiting</source> + <translation type="obsolete">等待中</translation> + </message> + <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="80"/> <source>Load</source> <translation>读取</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="0"/> + <source>Weapons scheme</source> + <translation type="obsolete">武器设定</translation> + </message> + <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="0"/> + <source>Training</source> + <translation type="obsolete">训练</translation> + </message> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="496"/> <source>Specify</source> <translation>指定</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="580"/> <source>default</source> <translation>默认</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="48"/> <source>Rename</source> <translation>重命名</translation> </message> <message> + <location filename="../../../../QTfrontend/input_ip.cpp" line="52"/> <source>OK</source> <translation>确定</translation> </message> <message> + <location filename="../../../../QTfrontend/input_ip.cpp" line="57"/> <source>Cancel</source> <translation>取消</translation> </message> <message> + <location filename="../../../../QTfrontend/playrecordpage.cpp" line="52"/> <source>Delete</source> <translation>删除</translation> </message> <message> - <source>Ready</source> - <translation>准备好了</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="501"/> + <source>Join official server</source> + <translation type="obsolete">加入官方服务器</translation> </message> <message> - <source>Random Team</source> - <translation>随机分配队伍</translation> - </message> - <message> - <source>Associate file extensions</source> - <translation>相关文件扩展</translation> - </message> - <message> - <source>more</source> - <translation>更多</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="618"/> + <source>Ready</source> + <translation>准备好了</translation> </message> </context> <context> <name>QTableWidget</name> <message> - <source>Room Name</source> - <translation>房间名</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="787"/> + <source>Room name</source> + <translation>房间名称</translation> </message> <message> - <source>C</source> - <translation>人数限制</translation> - </message> - <message> - <source>T</source> - <translation>时间限制</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="788"/> + <source>Players number</source> + <translation>玩家数量</translation> </message> <message> - <source>Owner</source> - <translation>创建者</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="790"/> + <source>Round in progress</source> + <translation>回合数</translation> + </message> +</context> +<context> + <name>QToolBox</name> + <message> + <location filename="../../../../QTfrontend/pages.cpp" line="242"/> + <source>Actions</source> + <translation>行动</translation> </message> <message> - <source>Map</source> - <translation>地图</translation> - </message> - <message> - <source>Rules</source> - <translation>规则</translation> - </message> - <message> + <location filename="../../../../QTfrontend/pages.cpp" line="244"/> <source>Weapons</source> <translation>武器</translation> </message> -</context> -<context> - <name>SelWeaponWidget</name> <message> - <source>Weapon set</source> - <translation>武器设置</translation> - </message> - <message> - <source>Probabilities</source> - <translation>空中支援几率</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="246"/> + <source>Weapon properties</source> + <translation>武器选项</translation> </message> <message> - <source>Ammo in boxes</source> - <translation>弹药箱</translation> - </message> - <message> - <source>Delays</source> - <translation>延迟回合数</translation> - </message> - <message> - <source>new</source> - <translation>新</translation> - </message> - <message> - <source>copy of</source> - <translation>副本</translation> + <location filename="../../../../QTfrontend/pages.cpp" line="248"/> + <source>Other</source> + <translation>其他</translation> </message> </context> <context> <name>TCPBase</name> <message> + <location filename="../../../../QTfrontend/tcpBase.cpp" line="99"/> <source>Error</source> <translation>错误</translation> </message> <message> + <location filename="../../../../QTfrontend/tcpBase.cpp" line="45"/> <source>Unable to start the server: %1.</source> <translation>无法开始服务端: %1.</translation> </message> <message> + <location filename="../../../../QTfrontend/tcpBase.cpp" line="101"/> <source>Unable to run engine: %1 (</source> <translation>无法运行引擎: %1 (</translation> </message> @@ -2113,678 +1474,362 @@ <context> <name>ToggleButtonWidget</name> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="888"/> <source>Fort Mode</source> <translation>城堡模式</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="892"/> <source>Divide Teams</source> <translation>团体行动</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="896"/> <source>Solid Land</source> <translation>固实地面</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="900"/> <source>Add Border</source> <translation>添加边界</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="904"/> <source>Low Gravity</source> <translation>低重力</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="908"/> <source>Laser Sight</source> <translation>激光瞄准</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="912"/> <source>Invulnerable</source> <translation>刀枪不入</translation> </message> <message> + <location filename="../../../../QTfrontend/pages.cpp" line="916"/> <source>Add Mines</source> - <translation type="obsolete">布置地雷</translation> - </message> - <message> - <source>Vampirism</source> - <translation>吸血鬼</translation> - </message> - <message> - <source>Karma</source> - <translation>因果报应</translation> - </message> - <message> - <source>Artillery</source> - <translation>射术</translation> - </message> - <message> - <source>Random Order</source> - <translation>随机顺序</translation> - </message> - <message> - <source>King</source> - <translation>国王模式</translation> - </message> - <message> - <source>Place Hedgehogs</source> - <translation>手动放置刺猬</translation> - </message> - <message> - <source>Clan Shares Ammo</source> - <translation>团队共享弹药</translation> - </message> - <message> - <source>Disable Girders</source> - <translation>禁止梁</translation> - </message> - <message> - <source>Disable Land Objects</source> - <translation>禁止地面物件</translation> - </message> - <message> - <source>AI Survival Mode</source> - <translation>AI生存模式</translation> - </message> - <message> - <source>Unlimited Attacks</source> - <translation>无限攻击</translation> - </message> - <message> - <source>Reset Weapons</source> - <translation>重置武器</translation> - </message> - <message> - <source>Per Hedgehog Ammo</source> - <translation>每个刺猬的弹药</translation> - </message> - <message> - <source>Reset Health</source> - <translation>重置生命值</translation> - </message> - <message> - <source>Disable Wind</source> - <translation>禁止风力作用</translation> - </message> - <message> - <source>More Wind</source> - <translation>让风来地更猛烈吧</translation> - </message> - <message> - <source>Tag Team</source> - <translation>为队伍添加标签</translation> - </message> - <message> - <source>Add Bottom Border</source> - <translation>添加底部边界</translation> + <translation>布置地雷</translation> </message> </context> <context> <name>binds</name> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="23"/> <source>up</source> <translation>上</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="24"/> <source>left</source> <translation>左</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="25"/> <source>right</source> <translation>右</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="26"/> <source>down</source> <translation>下</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="28"/> + <source>jump</source> + <translation>跳</translation> + </message> + <message> + <location filename="../../../../QTfrontend/binds.cpp" line="29"/> <source>attack</source> <translation>攻击</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="31"/> <source>put</source> <translation>放</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="32"/> <source>switch</source> <translation>切换</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="35"/> <source>slot 1</source> <translation>slot 1</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="36"/> <source>slot 2</source> <translation>slot 2</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="37"/> <source>slot 3</source> <translation>slot 3</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="38"/> <source>slot 4</source> <translation>slot 4</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="39"/> <source>slot 5</source> <translation>slot 5</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="40"/> <source>slot 6</source> <translation>slot 6</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="41"/> <source>slot 7</source> <translation>slot 7</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="42"/> <source>slot 8</source> <translation>slot 8</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="44"/> <source>timer 1 sec</source> <translation>定时1秒</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="45"/> <source>timer 2 sec</source> <translation>定时2秒</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="46"/> <source>timer 3 sec</source> <translation>定时3秒</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="47"/> <source>timer 4 sec</source> <translation>定时4秒</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="48"/> <source>timer 5 sec</source> <translation>定时5秒</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="56"/> <source>capture</source> - <translation>截取</translation> + <translation>夺取</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="58"/> <source>quit</source> <translation>退出</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="33"/> <source>find hedgehog</source> - <translation>寻找刺猬</translation> + <translation>找到 刺猬</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="34"/> <source>ammo menu</source> <translation>弹药菜单</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="53"/> <source>volume down</source> <translation>降低音量</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="54"/> <source>volume up</source> <translation>提高音量</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="55"/> <source>change mode</source> <translation>改变模式</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="51"/> <source>pause</source> <translation>暂停</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="43"/> <source>slot 9</source> <translation>slot 9</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="57"/> <source>hedgehogs info</source> <translation>刺猬大作战 信息</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="49"/> <source>chat</source> <translation>聊天</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="50"/> <source>chat history</source> <translation>聊天记录</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="52"/> <source>confirmation</source> <translation>确认</translation> </message> <message> + <location filename="../../../../QTfrontend/binds.cpp" line="30"/> <source>precise aim</source> <translation>练习瞄准</translation> </message> - <message> - <source>zoom in</source> - <translation>放大</translation> - </message> - <message> - <source>zoom out</source> - <translation>缩小</translation> - </message> - <message> - <source>reset zoom</source> - <translation>重置</translation> - </message> - <message> - <source>long jump</source> - <translation>远跳</translation> - </message> - <message> - <source>high jump</source> - <translation>高跳</translation> - </message> - <message> - <source>slot 10</source> - <translation>slot 10</translation> - </message> -</context> -<context> - <name>binds (categories)</name> - <message> - <source>Basic controls</source> - <translation>基本控制</translation> - </message> - <message> - <source>Weapon controls</source> - <translation>武器控制</translation> - </message> - <message> - <source>Camera and cursor controls</source> - <translation>镜头和光标控制</translation> - </message> - <message> - <source>Other</source> - <translation>其他</translation> - </message> -</context> -<context> - <name>binds (descriptions)</name> - <message> - <source>Move your hogs and aim:</source> - <translation>移动您的刺猬同时瞄准:</translation> - </message> - <message> - <source>Traverse gaps and obstacles by jumping:</source> - <translation>使用跳跃越过沟渠、障碍:</translation> - </message> - <message> - <source>Fire your selected weapon or trigger an utility item:</source> - <translation>使用选择的武器开火、使用物品:</translation> - </message> - <message> - <source>Pick a weapon or a target location under the cursor:</source> - <translation>选取一个武器或者瞄准光标下的地点:</translation> - </message> - <message> - <source>Switch your currently active hog (if possible):</source> - <translation>切换到您当前活动的刺猬(如果可用):</translation> - </message> - <message> - <source>Pick a weapon or utility item:</source> - <translation>选择一个武器或物品:</translation> - </message> - <message> - <source>Set the timer on bombs and timed weapons:</source> - <translation>设置定时炸弹等武器起爆时间:</translation> - </message> - <message> - <source>Move the camera to the active hog:</source> - <translation>移动镜头到选中的刺猬:</translation> - </message> - <message> - <source>Move the cursor or camera without using the mouse:</source> - <translation>不用鼠标移动光标或镜头:</translation> - </message> - <message> - <source>Modify the camera's zoom level:</source> - <translation>调整镜头放大倍数:</translation> - </message> - <message> - <source>Talk to your team or all participants:</source> - <translation>同队友或全部参与者对话:</translation> - </message> - <message> - <source>Pause, continue or leave your game:</source> - <translation>暂停、继续或离开游戏:</translation> - </message> - <message> - <source>Modify the game's volume while playing:</source> - <translation>调整游戏时音量:</translation> - </message> - <message> - <source>Toggle fullscreen mode:</source> - <translation>全屏模式:</translation> - </message> - <message> - <source>Take a screenshot:</source> - <translation>截图:</translation> - </message> - <message> - <source>Toggle labels above hedgehogs:</source> - <translation>切换刺猬头顶标签的显示方式:</translation> - </message> </context> <context> - <name>binds (keys)</name> - <message> - <source>Axis</source> - <translation>Axis轴</translation> - </message> + <name>teams</name> <message> - <source>(Up)</source> - <translation>(上)</translation> - </message> - <message> - <source>(Down)</source> - <translation>(下)</translation> - </message> - <message> - <source>Hat</source> - <translation>帽子</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="53"/> + <source>Hedgehogs</source> + <translation>刺猬 </translation> </message> <message> - <source>(Left)</source> - <translation>(左)</translation> - </message> - <message> - <source>(Right)</source> - <translation>(右)</translation> - </message> - <message> - <source>Button</source> - <translation>按键</translation> - </message> - <message> - <source>Keyboard</source> - <translation>键盘</translation> - </message> - <message> - <source>Mouse: Left button</source> - <translation>鼠标:左键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="54"/> + <source>hedgehog 1</source> + <translation>刺猬 1号</translation> </message> <message> - <source>Mouse: Middle button</source> - <translation>鼠标:中键</translation> - </message> - <message> - <source>Mouse: Right button</source> - <translation>鼠标:右键</translation> - </message> - <message> - <source>Mouse: Wheel up</source> - <translation>鼠标滚轮:向上</translation> - </message> - <message> - <source>Mouse: Wheel down</source> - <translation>鼠标滚轮:向下</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="55"/> + <source>hedgehog 2</source> + <translation>刺猬 2号</translation> </message> <message> - <source>Backspace</source> - <translation>退格键</translation> - </message> - <message> - <source>Tab</source> - <translation>Tab</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="56"/> + <source>hedgehog 3</source> + <translation>刺猬 3号</translation> </message> <message> - <source>Clear</source> - <translation>Num Lock / Clear</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="57"/> + <source>hedgehog 4</source> + <translation>刺猬 4号</translation> </message> <message> - <source>Return</source> - <translation>回车</translation> - </message> - <message> - <source>Pause</source> - <translation>暂停键</translation> - </message> - <message> - <source>Escape</source> - <translation>ESC键(退出键)</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="58"/> + <source>hedgehog 5</source> + <translation>刺猬 5号</translation> </message> <message> - <source>Space</source> - <translation>空格键</translation> - </message> - <message> - <source>Delete</source> - <translation>Del(删除键)</translation> - </message> - <message> - <source>Numpad 0</source> - <translation>小键盘0</translation> - </message> - <message> - <source>Numpad 1</source> - <translation>小键盘1</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="59"/> + <source>hedgehog 6</source> + <translation>刺猬 6号</translation> </message> <message> - <source>Numpad 2</source> - <translation>小键盘2</translation> - </message> - <message> - <source>Numpad 3</source> - <translation>小键盘3</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="60"/> + <source>hedgehog 7</source> + <translation>刺猬 7号</translation> </message> <message> - <source>Numpad 4</source> - <translation>小键盘4</translation> - </message> - <message> - <source>Numpad 5</source> - <translation>小键盘5</translation> - </message> - <message> - <source>Numpad 6</source> - <translation>小键盘6</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="61"/> + <source>hedgehog 8</source> + <translation>刺猬 8号</translation> </message> <message> - <source>Numpad 7</source> - <translation>小键盘7</translation> - </message> - <message> - <source>Numpad 8</source> - <translation>小键盘8</translation> - </message> - <message> - <source>Numpad 9</source> - <translation>小键盘9</translation> - </message> - <message> - <source>Numpad .</source> - <translation>小键盘.</translation> - </message> - <message> - <source>Numpad /</source> - <translation>小键盘/</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="73"/> + <source>Goddess</source> + <translation>女神</translation> </message> <message> - <source>Numpad *</source> - <translation>小键盘*</translation> - </message> - <message> - <source>Numpad -</source> - <translation>小键盘-</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="74"/> + <source>Isis</source> + <translation>艾希丝</translation> </message> <message> - <source>Numpad +</source> - <translation>小键盘+</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="75"/> + <source>Astarte</source> + <translation>阿斯德尔特</translation> </message> <message> - <source>Enter</source> - <translation>回车键</translation> - </message> - <message> - <source>Equals</source> - <translation>等于</translation> - </message> - <message> - <source>Up</source> - <translation>上</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="76"/> + <source>Diana</source> + <translation>黛安娜</translation> </message> <message> - <source>Down</source> - <translation>下</translation> - </message> - <message> - <source>Right</source> - <translation>右</translation> - </message> - <message> - <source>Left</source> - <translation>左</translation> - </message> - <message> - <source>Insert</source> - <translation>插入键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="77"/> + <source>Aphrodite</source> + <translation>阿弗罗狄特</translation> </message> <message> - <source>Home</source> - <translation>Home键</translation> - </message> - <message> - <source>End</source> - <translation>End键</translation> - </message> - <message> - <source>Page up</source> - <translation>向上翻页键</translation> - </message> - <message> - <source>Page down</source> - <translation>向下翻页键</translation> - </message> - <message> - <source>Num lock</source> - <translation>小键盘数字锁</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="78"/> + <source>Hecate</source> + <translation>赫卡特</translation> </message> <message> - <source>Caps lock</source> - <translation>大小写切换键</translation> - </message> - <message> - <source>Scroll lock</source> - <translation>Scroll Lock键</translation> - </message> - <message> - <source>Right shift</source> - <translation>右Shift键</translation> - </message> - <message> - <source>Left shift</source> - <translation>左Shift键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="79"/> + <source>Demeter</source> + <translation>得墨忒耳</translation> </message> <message> - <source>Right ctrl</source> - <translation>右Ctrl键</translation> - </message> - <message> - <source>Left ctrl</source> - <translation>左Ctrl键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="80"/> + <source>Kali</source> + <translation>迦梨</translation> </message> <message> - <source>Right alt</source> - <translation>右Alt键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="81"/> + <source>Inanna</source> + <translation>維納斯</translation> </message> <message> - <source>Left alt</source> - <translation>左Alt键</translation> - </message> - <message> - <source>Right meta</source> - <translation>右meta键</translation> - </message> - <message> - <source>Left meta</source> - <translation>左meta键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="93"/> + <source>Fruits</source> + <translation>水果</translation> </message> <message> - <source>A button</source> - <translation>A 键</translation> - </message> - <message> - <source>B button</source> - <translation>B 键</translation> - </message> - <message> - <source>X button</source> - <translation>X 键</translation> - </message> - <message> - <source>Y button</source> - <translation>Y 键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="94"/> + <source>Banana</source> + <translation>香蕉</translation> </message> <message> - <source>LB button</source> - <translation>LB 键</translation> - </message> - <message> - <source>RB button</source> - <translation>RB 键</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="95"/> + <source>Apple</source> + <translation>苹果</translation> </message> <message> - <source>Back button</source> - <translation>返回键</translation> - </message> - <message> - <source>Start button</source> - <translation>开始键</translation> - </message> - <message> - <source>Left stick</source> - <translation>左摇杆</translation> - </message> - <message> - <source>Right stick</source> - <translation>右摇杆</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="96"/> + <source>Orange</source> + <translation>橙子</translation> </message> <message> - <source>Left stick (Right)</source> - <translation>右(左摇杆)</translation> - </message> - <message> - <source>Left stick (Left)</source> - <translation>左(左摇杆)</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="97"/> + <source>Lemon</source> + <translation>柠檬</translation> </message> <message> - <source>Left stick (Down)</source> - <translation>下(左摇杆)</translation> - </message> - <message> - <source>Left stick (Up)</source> - <translation>上(左摇杆)</translation> - </message> - <message> - <source>Left trigger</source> - <translation>左制动</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="98"/> + <source>Pineapple</source> + <translation>菠萝</translation> </message> <message> - <source>Right trigger</source> - <translation>右制动</translation> - </message> - <message> - <source>Right stick (Down)</source> - <translation>下(右摇杆)</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="99"/> + <source>Mango</source> + <translation>芒果</translation> </message> <message> - <source>Right stick (Up)</source> - <translation>上(右摇杆)</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="100"/> + <source>Peach</source> + <translation>桃子</translation> </message> <message> - <source>Right stick (Right)</source> - <translation>右(右摇杆)</translation> - </message> - <message> - <source>Right stick (Left)</source> - <translation>左(右摇杆)</translation> - </message> - <message> - <source>DPad</source> - <translation>DPad板</translation> + <location filename="../../../../QTfrontend/predefteams.h" line="101"/> + <source>Plum</source> + <translation>梅子</translation> </message> </context> </TS> diff -r 763d3961400b -r 3c4b4cb40f40 share/hedgewars/Data/Locale/zh_CN.txt --- a/share/hedgewars/Data/Locale/zh_CN.txt Sat Aug 18 00:47:51 2012 +0200 +++ b/share/hedgewars/Data/Locale/zh_CN.txt Sat Aug 18 00:48:09 2012 +0200 @@ -1,825 +1,47 @@ ; Simplified Chinese locale 00:00=手榴弹 -00:01=集束炸弹 -00:02=火箭筒 -00:03=归巢的蜜蜂 -00:04=霰弹枪 -00:05=大锤 -00:06=跳过回合 +00:01=子母炸弹 +00:02=火箭炮 +00:03=UFO +00:04=散弹枪 +00:05=气锤 +00:06=掠过 00:07=绳索 00:08=地雷 00:09=沙漠之鹰 00:10=炸药 00:11=球棒 -00:12=Shoryuken +00:12=升龙拳 00:13=秒 00:14=降落伞 00:15=空袭 -00:16=地雷空袭 +00:16=地雷袭击 00:17=喷灯 -00:18=钢梁 +00:18=钢板 00:19=传送 -00:20=切换刺猬 +00:20=切换 00:21=迫击炮 00:22=鞭子 00:23=神风特工队 00:24=蛋糕 -00:25=引诱 +00:25=吸引 00:26=西瓜炸弹 00:27=地狱礼花 -00:28=钻头火箭 +00:28=钻地火箭 00:29=弹珠炮 -00:30=汽油弹空袭 -00:31=遥控轰炸机 +00:30=燃烧弹 +00:31=轰炸机 00:32=低重力 -00:33=增强伤害 -00:34=无敌 +00:33=附加伤害 +00:34=刀枪不入 00:35=加时 00:36=激光瞄准 -00:37=吸血 -00:38=狙击枪 -00:39=UFO -00:40=燃烧瓶 -00:41=鸟儿 -00:42=传送器 -00:43=飞来的钢琴 -00:44=毒奶酪 -00:45=正弦能量炮 -00:46=火焰喷射器 -00:47=固定地雷 -00:48=大锤 -00:49=复苏 -00:50=电钻空袭 -00:51=土块 -01:00=开战! -01:01=平局 -01:02= %1 胜利! +01:00=战斗啦! +01:01=平手 +01:02= %1 胜! 01:03=音量 %1% 01:04=暂停 -01:05=确定要退出? (是Y/否Esc) -01:06=死亡模式! -01:07=%1 剩余 -01:08=燃料 -01:09=同步中... -01:10=使用本工具不会结束回合! -01:11=您还不能用它! -01:12=死亡模式前最后一回合! -01:13=%1 回合倒计时! -01:14=预备上, %1! - -; Event messages -; Hog (%1) died -; 02:00=%1 has kicked the bucket! -02:00=%1 翘辫子了! -; 02:00=%1 has seen the light! -02:00=%1 目睹圣光降临! -; 02:00=%1 never saw that coming! -02:00=%1 无法瞑目! -; 02:00=%1 waves goodbye! -02:00=%1 向大家挥手道别。 -; 02:00=%1 has gone to a better place! -02:00=%1 去了极乐世界! -; 02:00=%1 meets his maker! -02:00=%1 去见造物主了! -; 02:00=%1 can hang on no longer! -02:00=%1 再也受不了了! -; 02:00=%1 has done his duty! -02:00=%1 完成了他的使命! -; 02:00=%1 makes the ultimate sacrifice! -02:00=%1 做了最大的牺牲! -; 02:00=%1 departs this mortal coil! -02:00=%1 摆脱了躯壳的束缚! -; 02:00=%1 makes like a tree and leaves! -02:00=%1 叶落归根。 -; 02:00=%1 has timed out! -02:00=%1 大限已至。 -; 02:00=%1 says peace out! -02:00=%1 悄然离场了。 -; 02:00=%1 will be fondly remembered! -02:00=%1 永远活在我们心中! -; 02:00=%1 has an aneurysm! -02:00=%1 不治而亡。 -; 02:00=%1 leaves behind a wife and child -02:00=%1 留下一家孤儿寡母 -; 02:00=%1 has launched his last bazooka -02:00=%1 发射了最后一发火箭弹 -; 02:00=%1 has tossed his last grenade -02:00=%1 扔出了最后一枚手榴弹 -; 02:00=%1 has baked his last cake -02:00=%1 烘烤了最后一块蛋糕 -; 02:00=%1 has swung on his last rope -02:00=%1 最后一次甩出了绳索 -; 02:00=%1 has called his last airstrike -02:00=%1 最后一次呼叫空袭 -; 02:00=%1 has pumped his last shotgun -02:00=%1 最后一次抽出了霰弹枪 -; 02:00=%1 has thrown his last melon -02:00=%1 最后一次扔出了西瓜炸弹 -; 02:00=%1 has drawn his last deagle -02:00=%1 最后一次拔出了沙漠之鹰 -; 02:00=%1 took one shot too many -02:00=%1 挨了太多枪子了 -; 02:00=%1 could really have used a health crate -02:00=%1 真该用下医疗包的 -; 02:00=%1 has gone to play a better game -02:00=%1 去玩更有意思的游戏去了 -; 02:00=%1 has ragequit life -02:00=%1 拔网线了! -; 02:00=%1 fails -02:00=%1 失败了 -; 02:00=Poor poor %1... -02:00=可怜的 %1... -; 02:00=%1 prefers wormux -02:00=%1 更喜欢 Warmux -; 02:00=%1 has been blocking shots with his face -02:00=%1 勇于面对子弹,结果相当惨烈 -; 02:00=%1 is a hero amongst me...err..hogs -02:00=%1 是位英雄……额……在刺猬当中 -; 02:00=%1 finds his place in Valhalla -02:00=%1 在勇者纪念碑上找到了自己的位置 -; 02:00=%1 has left the building -02:00=%1 离开了这间屋子 -; 02:00=%1 goes the way of the dinosaurs -02:00=%1 步上了恐龙的道路 -; 02:00=%1 brings hedgehogs one step closer to extinction -02:00=%1 让刺猬向物种灭绝更近了一步 -; 02:00=%1 brings a tear to my eye -02:00=%1 带走了我一滴眼泪 -; 02:00=%1 is an ex-hog -02:00=%1 生前是一只刺猬 -; 02:00=%1 is pushing up the daisies -02:00=%1 被菊花簇拥 -; 02:00=%1 has ceased to be -02:00=%1 被删除了 -; 02:00=Say goodbye to %1 -02:00=对 %1 说再见 -; 02:00=No hope left for %1 -02:00=%1 没有希望了 -; 02:00=%1 faces the final curtain -02:00=%1 面容被落下的帷幕遮住了 -; 02:00=Smoke 'em if you got 'em, %1 -02:00=%1 抓紧时间实现你最后的愿望吧 -; 02:00=%1 suffers a Spontaneous Massive Existence Failure -02:00=%1 遭遇了自发性大规模故障 -; 02:00=%1 has passed on -02:00=%1 走了 -; 02:00=%1 is stone dead -02:00=%1 永垂不朽 -; 02:00=%1 is no more -02:00=%1 不在了 -; 02:00=%1 has expired -02:00=%1 已故 -; 02:00=Bereft of life, %1 rests in peace -02:00=%1 安详地躺着 -; 02:00=%1 joins the choir invisible -02:00=%1 加入了隐形唱诗班 -; 02:00=Farewell %1, we hardly knew ye! -02:00=%1, 永别了,我们还没熟悉你呢! -; 02:00=%1 had a low tolerance for being shot -02:00=%1 抗打击能力不足 -; 02:00=%1 could have used an extra life -02:00=%1 本该有第二条命的 -; 02:00=Is there a doctor in the house? -02:00=这里有医生吗? - -; Hog (%1) drowned -; 02:01=%1 plays submarine! -02:01=%1 去玩潜水艇了! -; 02:01=%1 mimics the Titanic! -02:01=%1 学泰坦尼克去了! -; 02:01=%1 swims like a stone! -02:01=%1 石沉大海! -;02:01=%1 checks out the deep end -02:01=%1 说要去检查深水区 -;02:01=%1 goes glug glug glug -02:01=%1 :“咕噜咕噜咕噜……” -;02:01=%1 goes splash -02:01=%1 栽入水花里 -;02:01=%1 forgot his armbands -02:01=%1 忘记了戴臂章 -;02:01=%1 really should have taken swimming lessons -02:01=%1 真的该去学游泳的 -;02:01=%1 left his surfboard at home -02:01=%1 把救生圈忘家了 -;02:01=%1 is washed up -02:01=%1 被冲走了 -;02:01=%1 is one soggy hog -02:01=%1 脑子进水了 -;02:01=%1 forgot to bring his life jacket -02:01=%1 忘记带救生衣了 -;02:01=%1 goes splish splash splish -02:01=%1 实现了水上飘,身后一片水花荡漾 -;02:01=%1 is sleeping with the fishes -02:01=%1 将会和鱼睡在一起 -;02:01=%1 thinks the water physics suck in this game -02:01=%1 认为这游戏关于落水的设定糟糕透了 -;02:01=%1 looks thirsty -02:01=%1 看样子很渴 -;02:01=the sea claims %1 -02:01=大海吞没了 %1 -;02:01=%1 is lost at sea -02:01=%1 在海上迷失了 -;02:01=%1 should have brought his scuba gear -02:01=%1 应该要带潜水工具的 -;02:01=%1 gets a burial at sea -02:01=%1 享受到了海葬待遇 -;02:01=%1 has that sinking feeling -02:01=%1 觉得自己在下沉 -;02:01=%1 is practicing his backstroke -02:01=%1 终于能实践自己的游泳理论了 -;02:01=%1 goes in search of the Titanic -02:01=%1 去泰坦尼克号寻宝了 -;02:01=%1 is not Jesus -02:01=很遗憾 %1 不是耶稣 -;02:01=%1 is finding Nemo -02:01=%1 正在寻找Nemo -;02:01=%1 springs a leak -02:01=%1 钻入了一个水洼 -;02:01=You've gotta wonder how many hogs are down there -02:01=你会知道海底还会有多少同伴的 -;02:01=%1 makes the ocean slightly higher -02:01=%1 让海平面高了那么一点, 就一点 -;02:01=%1 didn't enlist in the Navy -02:01=很明显 %1 没在海军服役过 -;02:01=%1 is doing his impersonation of a dead fish -02:01=%1 其实是在模仿死鱼啦 -;02:01=At least you didn't go down the toilet, %1 -02:01=还好 %1 你不是掉进了厕所 -;02:01=Sonic couldn't swim and neither can %1 -02:01=索尼克不能游泳, %1 也一样 -;02:01=%1 wants to play Ecco the dolphin -02:01=%1 想玩海底漫步 -;02:01=%1 has gone to visit Aquaria -02:01=%1 去水族馆报到了 -;02:01=%1 has found the lost city of Atlantis -02:01=%1 找到了传说中的亚特兰蒂斯城 -;02:01=%1 aims for the lead role in Bioshock 3 -02:01=%1 立志在生化奇兵3中担任头号角色 -;02:01=Your doggy paddle could use a little work, %1 -02:01=你的狗刨式会有点用的, %1 -;02:01=%1 should have brought a jet ski -02:01=%1 竟然没带摩托艇 -;02:01=%1 doesn't like watersports -02:01=%1 不喜欢水上运动 -;02:01=%1 is forever blowing bubbles -02:01=%1 学会了绝技: 神风吹泡泡 -;02:01=%1 is short of a raft -02:01=%1 需要一个救生艇 -;02:01=%1 thinks salt water is good for the skin -02:01=%1 认为盐水对皮肤有好处 -;02:01=%1 gets salt water in his wounds -02:01=%1 的伤口沾上了盐水 -;02:01=%1 has walked the plank -02:01=%1 错过了那块木板 -;02:01=%1 has a bath -02:01=%1 洗澡去了 -;02:01=%1 is wet wet wet -02:01=%1 全身都是水,水,水…… -;02:01=%1 gets his quills wet -02:01=%1 把刺全弄湿了 -;02:01=It's Davy Jones' locker for %1 -02:01=深海阎王正在等待 %1 - -; Round starts -; 02:02=Let's fight! -02:02=开战吧! -; 02:02=Armed and ready! -02:02=武装准备! -;02:02=Let's get ready to rumble! -02:02=准备对轰! -;02:02=Let's get it on! -02:02=为胜利而战吧! -;02:02=Let's get this party started -02:02=让我们开始这个派对吧 -;02:02=Last hog standing wins -02:02=胜利属于最后一个生还者 -;02:02=Let's go! -02:02=出发吧! -;02:02=Let's rock! -02:02=一起摇滚吧! -;02:02=Let's jam! -;02:02=It's beginning... -02:02=开始了... -;02:02=This is the start of something big -02:02=这是一个伟大的开始 -;02:02=Welcome to Hedgewars -02:02=欢迎来到刺猬大作战 -;02:02=Welcome to the front lines -02:02=欢迎来到前线 -;02:02=Crush your enemies! -02:02=目标:粉碎你的敌人! -;02:02=May the best hog win -02:02=祝愿胜利属于最厉害的刺猬! -;02:02=Victory or death -02:02=胜利或死亡 -;02:02=To the victor goes the spoils -02:02=战利品只属于胜利者 -;02:02=Losing is not an option -02:02=字典里面应该没有"输"这个字的 -;02:02=Cry havoc! Let loose the hogs of war! -02:02=放声喊吧! 这是刺猬的战争! -;02:02=Hedgewars, brought to you by Hedgewars.org -02:02=欢迎来到刺猬大作战, Hedgewars.org 为你呈现 -02:02=GL HF -;02:02=Just count yourself lucky you're not up against Tiyuri -02:02=你看你多幸运不是在对战 Tiyuri -;02:02=Just count yourself lucky you're not up against unC0Rr -02:02=你看你多幸运不是在对战 unC0Rr -;02:02=Just count yourself lucky you're not up against Nemo -02:02=你看你多幸运不是在对战 Nemo -;02:02=Just count yourself lucky you're not up against Smaxx -02:02=你看你多幸运不是在对战 Smaxx -;02:02=Just count yourself lucky you're not up against Jessor -02:02=你看你多幸运不是在对战 Jessor -;02:02=Give it your all! -02:02=展现你的一切吧! -;02:02=The losers do the cleaning up! -02:02=输的要罚扫厕所! -;02:02=Let the fight of the millenium begin -02:02=宇宙之战开始了 -;02:02=Let the fight of the century begin -02:02=世纪之战开始了 -;02:02=Let the fight of the decade begin -02:02=正义之战开始了 -;02:02=Let the fight of the year begin -02:02=年度争霸战开始了 -;02:02=Let the fight of the month begin -02:02=本月之星争霸战开始了 -;02:02=Let the fight of the week begin -02:02=每周擂主争霸战开始了 -;02:02=Let the fight of the day begin -02:02=本日最强入围赛开始了 -;02:02=Let the fight of the hour begin -02:02=我们能战一小时! -;02:02=Do your best! -02:02=诸君努力! -;02:02=Destroy the enemy! -02:02=目标: 摧毁敌人 -;02:02=Good luck -02:02=祝你好运 -;02:02=Have fun~ -02:02=开心玩~ -;02:02=Fight the good fight -02:02=漂亮的战斗 -;02:02=Fight dirty -02:02=不择手段 -;02:02=Fight with honour -02:02=满载荣誉而战 -;02:02=Don't give up -02:02=教练告诉你: 别放弃 -;02:02=Never surrender -02:02=永不屈服! -;02:02=Rock 'em and sock 'em! -02:02=蹂虐对手 -;02:02=Let the fragfest begin! -02:02=积分赛开始! -;02:02=I hope you're ready for a tussle! -02:02=你准备好恶战了么? -;02:02=Go Go Go! -02:02=冲冲冲! -;02:02=Hedgehogs advance! -02:02=刺猬向前冲! -;02:02=Bring it to them! -02:02=炸飞他们! -;02:02=Have no fear! -02:02=无所畏惧! -;02:02=Be brave and conquer -02:02=敢于征服! - -; Round ends (win; unused atm) -02:03=回合结束(胜利) - -; Round ends (draw; unused atm) -02:04=回合结束(平局) - -; New health crate -;02:05=Incoming aid! -02:05=医疗包! -;02:05=Medic! -02:05=急救包! -;02:05=First aid from the skies! -02:05=救援物资空运来了! -;02:05=A health pack for you -02:05=你的医疗包到了 -;02:05=Good health.. in box form! -02:05=生命就在那箱子里! -;02:05=The doctor calls -02:05=医生的紧急呼叫 -;02:05=Fresh band-aids! -02:05=新鲜创可贴! -;02:05=This will make you feel better -02:05=吃了这个感觉会好些的... -;02:05=A Hi-Potion! Whoops wrong game -02:05=兴奋剂!呃。。。走错地方了 -;02:05=A pick-me-up! -02:05=万金油! -;02:05=Grab it -02:05=捉住它 -;02:05=A healthy snack -02:05=健康食品 -;02:05=A remedy to pain -02:05=止痛饼来了 -;02:05=Correct Dosage: as many as you can find! -02:05=使用方法: 吃得越多越好 -;02:05=Urgent delivery -02:05=紧急物资 -;02:05=Supplies! -02:05=补给! - -; New ammo crate -; 02:06=More weapons! -02:06=武器! -;02:06=Reinforcements! -02:06=增援! -;02:06=Lock and load! -02:06=准备! -;02:06=I wonder what weapon is in there? -02:06=我要的那个会在的吧... -;02:06=Supplies! -02:06=补给! -;02:06=What could be inside? -02:06=里面会有啥呢? -;02:06=Christmas comes early in Hedgewars -02:06=刺猬大作战每天都是圣诞节 -;02:06=A present! -02:06=礼物送到! -;02:06=Special delivery! -02:06=特快专递! -;02:06=It was a nightmare getting this through customs -02:06=本局的噩梦来了 -;02:06=Destructive toys from the heavens -02:06=玩具从天堂掉下来了 -;02:06=Warning! Contents Volatile -02:06=警告! 内含危险物品 -;02:06=Pick it up or blow it up, choice is yours -02:06=拿走或打爆, 随你 -;02:06=Goodies! -02:06=好玩意儿! -;02:06=Mmmmm Ammo -02:06=弹药!!!! -;02:06=A box of destructive power -02:06=潘朵拉之盒 -;02:06=Airmail! -02:06=天降之物! -;02:06=Whatever's in that box, it ain't pizza -02:06=无论里面是啥, 那肯定不会是软妹子 -;02:06=Get it! -02:06=拿走它! -;02:06=Weapon drop incoming -02:06=武器掉下来了! -;02:06=Don't let the enemy grab that! -02:06=别让敌人拿了! -;02:06=Shiny new toys! -02:06=新玩具! -;02:06=A mysterious box! -02:06=神秘的箱子! - -; New utility crate -; 02:07=Tooltime! -02:07=工具箱! -;02:07=This could come in handy... -02:07=这可能派上用场 -;02:07=Utilities! -02:07=工具! -;02:07=Utilise this box -02:07=工具在这里! -;02:07=Watch out below -02:07=快看这里! -;02:07=More utilities! -02:07=更多选择更多欢笑, 尽在工具包 -;02:07=Tools for you! -02:07=一堆工具, 送给你! -;02:07=This should be good! -02:07=这看见起来蛮好... -;02:07=Use this wisely -02:07=使用这个才是明智的选择 -;02:07=Ooo this box is heavy -02:07=好重...好重... -;02:07=You might need this -02:07=会有用的 - -; Hog (%1) skips his turn -; 02:08=%1 is sooo boring... -02:08=%1 太无聊了... -;02:08=%1 couldn't be bothered -02:08=%1 不想被打扰! -;02:08=%1 is one lazy hog -02:08=%1 太懒了 -;02:08=%1 is thoughtless -02:08=%1 太轻率了 -;02:08=%1 gave up -02:08=%1 放弃了 -;02:08=You snooze you lose, %1 -02:08=不认真你就输了, %1 -;02:08=%1 shamelessly skips -02:08=%1 无耻的跳过了本回合 -;02:08=%1 is really lazy -02:08=%1 真的太懒了 -;02:08=%1 needs a little more motivation -02:08=%1 没有动力了 -;02:08=%1 is a pacifist -02:08=%1 是和平主义者 -;02:08=%1 has a breather -02:08=%1 需要喘息一下 -;02:08=%1 has a rest -02:08=%1 需要休息 -;02:08=%1 chills out -02:08=%1 发冷了 -;02:08=%1 has no faith in his own abilities -02:08=%1 做啥都没信心了 -;02:08=%1 decides to do nothing at all -02:08=%1 决定啥都不做 -;02:08=%1 lets the enemy destroy itself -02:08=%1 认为敌人会自杀的 -;02:08=%1 would be terrible at parties -02:08=%1 将会陷入可怕的事件中 -;02:08=%1 hides out -02:08=%1 说:“你看不到我,你看不到我……” -;02:08=%1 has decided to pass on this opportunity -02:08=%1 已经决定放弃这个机会 -;02:08=%1 decides the best thing he can do is...nothing -02:08=%1 决定他现在最应该做的是......坐着不动 -;02:08=%1 is a big wuss -02:08=%1 大笨蛋! -;02:08=Buck Buck Buck, %1 is a chicken -02:08=%1 是小鸡鸡 -;02:08=%1 is looking a little yellow -02:08=%1 看来有点印堂发黑 -;02:08=%1 is a coward! -02:08=%1 是懦夫! -;02:08=%1 is waiting for sudden death -02:08=%1 在等待突然死亡模式 -;02:08=%1 is not the fighting type -02:08=%1 不是战斗系的 -;02:08=%1 is reconsidering his purpose in life -02:08=%1 正在重新寻找他的人生 -;02:08=%1 was never much of a good shot anyway -02:08=%1 从来没一次打准的 -;02:08=%1 didn't want to join the army in the first place -02:08=%1 不想参军 -;02:08=Stop wasting our time, %1 -02:08=别浪费时间了! %1 -;02:08=I'm dissapointed in you, %1 -02:08=我对你失望了, %1 -;02:08=Come on, you can do better than that %1 -02:08=%1 明明就能做的更好的 -;02:08=%1's will has broken -02:08=%1 会被打飞的 -;02:08=%1 apparently has better things to do -02:08=%1 显然有更好的事情等着做 -;02:08=%1 is scared stiff -02:08=%1 怕刺激 -;02:08=%1 has fallen asleep -02:08=%1 睡着了 - -; Hog (%1) hurts himself only -; 02:09=%1 should practice aiming! -02:09=%1 该练练瞄准了! -; 02:09=%1 seems to hate himself. -02:09=%1 似乎看自己很不爽。 -; 02:09=%1 is standing on the wrong side! -02:09=%1 在表演乌龙! -; 02:09=%1 makes like an emo -02:09=%1 以为自己无敌 -; 02:09=%1 was holding his weapon the wrong way around -02:09=%1 好像把武器拿错方向了 -;02:09=%1 is a little sadistic -02:09=%1 有点施虐狂 -;02:09=%1 is a masochist -02:09=%1 是受虐狂 -;02:09=%1 has no instinct of self-preservation -02:09=%1 根本不会自我保护 -;02:09=%1 messed up -02:09=%1 乱套了 -;02:09=%1 screwed up -02:09=%1 搞砸了 -;02:09=That was a poor shot, %1 -02:09=%1 这一发真渣 -;02:09=%1 is a little too careless with dangerous weapons -02:09=%1 太不小心用那些危险的玩意了 -;02:09=%1 should consider a change of career -02:09=%1 正在考虑转职 -;02:09=Worst. Shot. Ever! -02:09=更差! 最差! 非常差! -;02:09=No no no %1, you shoot at the ENEMY! -02:09=No no no %1, 你要打敌人! -;02:09=%1 should only be destroying the enemy -02:09=%1 应该消灭敌人才对 -;02:09=%1 moves one step closer to suicide -02:09=%1 正在走向自杀 -;02:09=%1 aids the enemy -02:09=%1 帮助敌人 -;02:09=That was stupid %1 -02:09= %1 是笨蛋 -;02:09=%1 lives by the mantra of "no pain, no gain" -02:09=%1 贯彻“不付出,何收获“的原则 -;02:09=%1 is confused -02:09=%1 思维混乱了 -;02:09=%1 hurt itself in its confusion -02:09=%1 在混乱中攻击自己 -;02:09=%1 has a knack for embarrassing himself -02:09=%1 正在为自己尴尬 -;02:09=%1 is a klutz! -02:09=%1 就是一个笨蛋! -;02:09=%1 is clumsy -02:09=%1 笨手笨脚的 -;02:09=%1 shows the enemy what he's capable of -02:09=%1 展示了自己的能力 -;02:09=%1 can't be expected to be perfect all the time -02:09=%1 不能每次都完美 -;02:09=Don't worry %1, pobody's nerfect -02:09=不用担心 %1 , 人都不是完美的 -;02:09=%1 totally did that on purpose -02:09=%1 这么做真的是有目的 -;02:09=I won't tell anyone if you don't, %1 -02:09=我不会把 %1 的事情到处说的 -;02:09=How embarrassing! -02:09=何等的失态! -;02:09=I'm sure nobody saw that %1 -02:09=保证,决没人看到 %1 做什么 -;02:09=%1 needs to review his field manual -02:09=%1 需要复习说明书 -;02:09=%1's weapon clearly malfunctioned -02:09=%1 的武器很明显坏了 - -; Hog shot an home run (using the bat and another hog) -; 02:10=Home Run! -02:10=全垒打! -; 02:10=A bird, a plane, ... -02:10=一只鸟,一架飞机,... -; 02:10=That one is out! -02:10=那一位出界了! - -; Hog (%1) has to leave (team is gone) -02:11=%1 必须上床了 -02:11=%1 玩的过火了,休息一下 -02:11=发射!这位已经被送出去 -02:11=%1 必须走了 - -; Weapon Categories -03:00=定时手雷 -03:01=定时手雷 -03:02=弹道武器 -03:03=制导武器 -03:04=枪 (多发子弹) -03:05=钻孔工具 -03:06=动作 -03:07=移动工具 -03:08=接近式炸弹 -03:09=枪 (多发子弹) -03:10=BOOM! -03:11=咚! -03:12=武术 -03:13=未使用 -03:14=移动工具 -03:15=空投打击 -03:16=空投打击 -03:17=打洞工具 -03:18=工具 -03:19=移动工具 -03:20=动作 -03:21=弹道武器 -03:22=叫我主人! -03:23=武术 (真的!) -03:24=蛋糕不是谎言! -03:25=化妆的诱惑 -03:26=果汁手雷 -03:27=烫手手雷 -03:28=弹道武器 -03:29=弹道武器 -03:30=空投打击 -03:31=遥控飞机(不是玩具!) -03:32=临时效果 -03:33=临时效果 -03:34=临时效果 -03:35=临时效果 -03:36=临时效果 -03:37=临时效果 -03:38=枪 (多发子弹) -03:39=移动工具 -03:40=燃烧弹 -;03:41=Huge fan of Squawks -03:41=粉丝的呼喊 -;03:42=I'm making a note here... -03:42=我将在此做一记录... -; the misspelled "Beethoven" is intentional (-> to beat) -;03:43=Performing Beathoven's deadly sonata -03:43=正在演奏贝揍芬的死亡奏鸣曲 -;03:44=Best before: 1923 -03:44=此日期前最佳:1923 -;03:45=The power of science -03:45=科学的力量 -;03:46=Hot Hot Hot! -03:46=烫烫烫! -;03:47=Stick these somewhere useful! -03:47= 呆在有利的地方! -;03:48=It's Hammer time! -03:48=大锤威武! -;03:49=Does what you guess -03:49=尽情猜想 -;03:50=Moles fan -03:50=地道战 - -; Weapon Descriptions (use | as line breaks) -04:00=使用简单的手榴弹攻击敌人.|定时器倒数到0就会爆炸.|1-5: 设定定时器|攻击键: 按住蓄力. -04:01=使用集束手雷攻击敌人.|定时器倒数到0就会爆炸并裂开成几块.|1-5: 设定定时器|攻击键: 按住蓄力. -04:02=使用弹道导弹攻击敌人.|受风力影响.|攻击键: 按住蓄力. -04:03=发射一个制导导弹攻击所选目标.|如果要精确打击就不要使用全力发射.|光标: 选定目标|攻击键: 按住蓄力. -04:04=霰弹枪有两排子弹.|因为是霰弹枪所以不一定要对准敌人.|攻击键: 开枪 (两发) -04:05=向地底出发! 使用他就能在地面|打个洞, 就能去其他地方.|攻击键: 开始/停止打洞 -04:06=闷了? 没法打? 保存体力? 没问题!|跳过这回合就可以了, 懦夫!|攻击键: 跳过回合 -04:07=用绳索就可以去很远的地方.|还能空降到别的刺猬身上丢手榴弹呢.|攻击键: 发射/收回绳索|长跳键: 发射手榴弹或其他武器 -04:08=你能用地雷阻止敌人靠近.|还能静悄悄的放在敌人脚下.|一定要在爆炸前逃离到安全的地方!|攻击键: 把地雷放在你的脚下 -04:09=自我感觉准头不行? |沙漠之鹰有4颗子弹呢.|攻击键: 开枪 (四发) -04:10=使用强力炸药就是一个明智的选择.|这是最经典的轰炸方式.|攻击键: 把炸药放在你的脚下 -04:11=把敌人打飞, 飞出地图或者飞进水里.|或者把地雷打过去?|攻击键: 敲打你面前的所有东西 -04:12=这就是武术的威力!|致命的气功!|攻击键: 使用升龙拳 -04:13=UNUSED -04:14=有恐高症? 拿降落伞吧.|他能慢慢的安全的把你带到地面.|攻击键: 展开降落伞 -04:15=呼叫一架飞机轰炸你的敌人.|左/右方向键: 决定攻击方向|光标: 选定目标 -04:16=呼叫一架飞机投下大量地雷.|左/右方向键: 决定攻击方向|光标: 选定目标 -04:17=需要个安全的地方? 使用喷灯为你挖掘一条安全的隧道!|攻击键: 开始/停止挖掘 -04:18=喷灯还不够?还要个更安全的地方?|建造若干条大梁挡住吧.|左/右方向键: 选择梁的方向|光标: 建造 -04:19=适当的时候撤退是比所有的攻击|更安全的选择|光标: 选择传送目标 -04:20=可以让你更换当前使用的刺猬.|攻击键: 启动切换功能 -04:21=用炮弹发射器发射一个手榴弹样|的东西. 在爆炸之后会裂开成小块|攻击键: 全力发射 -04:22=这不只是女王才用的东西!|这鞭子能解决很多问题, 比如说那些|喜欢站在悬崖边上的小屁孩.|攻击键: 鞭打你面前的一切东西 -04:23=自杀式炸弹袭击向来好用!|用你的一条命攻击直线上的一切东西并爆炸.|攻击键: 启动自杀性攻击 -04:24=生日快乐! 嗱, 放下这个蛋糕, 他|就会走到敌人身边然后爆炸.| 而且能贴着地形走.|攻击键: 让蛋糕开始/结束走路 -04:25=使用美人计让敌人向着你这个方向跳|(比如跳进海里).|攻击键: 使用本工具诱惑敌人 -04:26=把这个多汁的西瓜扔向敌人!| 一旦定时器倒数完, 就会|炸成几块更强力的炸弹.|攻击键: 按住蓄力. -04:27=让地狱的礼花在敌人头上绽放!|这真的是危险品, 使用时候记得原理|爆炸之后还会燃烧好一阵子|攻击键: 按住蓄力. -04:28=本火箭在发射后将会钻到地里|一旦燃料用完或者打穿地面就会爆炸.|攻击键: 按住蓄力. -04:29=还记得小时候玩的玻璃球么?|不过这个是炸弹版. 发射大量的小玻|璃球然后爆炸|攻击键: 全力发射|上/下方向键: 发射过程中更换方向 -04:30=呼叫一架飞机空投燃烧弹.|用得好的话会造成巨大伤害.|左/右方向键: 决定攻击方向|光标: 选定目标 -04:31=啊哈, 遥控飞机除了能帮你|收集物品之外. 还能空投炸弹.|攻击键: 飞机起飞/投放炸弹|长跳键: 战场之神|上/下方向键: 控制方向 -04:32=低重力装置能影响更多东西!| 除了跳得更远之外还能让|敌人飞得更远.|攻击键: 激活 -04:33=有时候致命打击还是不够过瘾.|攻击键: 激活 -04:34=你打不到我!|攻击键: 激活 -04:35=时间流逝得很快, 你也知道|刺猬腿短.|攻击键: 激活 -04:36=好吧, 你最后还是承认自己眼神不好.|高科技还是能帮你不少的.|攻击键: 激活 -04:37=不用害怕白天.|这只能本回合有效, 可以把造成的伤害变|成自己的血量 .|攻击键: 激活 -04:38=你也知道狙击枪的威力,|能打比较远的地方.|攻击键: 射击 (2发子弹) -04:39=驾驶飞碟可以飞到地图上的任何角落.|不过这个东西连发明者都认为很难用.|攻击键: 激活|上/左/右方向键: 向某方向飞|前跳:攻击敌人 -04:40=把地面填满汽油然后....|攻击键: 按住蓄力. -;04:41=The evidence nature might even top the flying|saucer. Birdy can carry your hog around and|drop eggs on your enemies!|Be quick, as using Birdy eats into your turn|time!|Attack: Activate and drop eggs|Up/Left/Right: Flap in one direction -04:41=自然的力量胜过飞盘的证据。|鸟儿可以携带刺猬并在敌人头上下蛋!|要快!使用鸟儿会消耗回合时间!|攻击键: 激活鸟儿和下蛋|上/左/右方向键: 向某方向飞 -;04:42=This portable portal device is capable|of instantly transporting you, your enemies,|or your weaponry between two points on the|terrain.|Use it wisely and your campaign will be a...|HUGE SUCCESS!|Attack: Shoot a portal|Switch: Cycle portal colours -04:42=移动传送装置|迅速传输自己或者敌人或者|你的武器,直接连接|地表的两个不同位置。|如果用的聪明那你的战斗将是一场……|巨大的胜利!|攻击键: 发射一个传送点|切换键: 改变颜色 -;04:43=Make your musical debut an explosive success!|Drop a piano from the heavens, but beware...|someone needs to play it, and that may cost you|your life!|Cursor: Select target region|F1-F9: Play the piano -04:43=音乐细胞的迸发!|钢琴从天堂降落,带|着演奏者最终回归天堂|光标: 选择目标区域|F1-F9:演奏钢琴 -04:44=这不是奶酪!而是生化武器!|爆炸只有一次,带来的毒害是深远的!|1-5: 设定定时器|攻击键: 按住蓄力 -;04:45=All those physics classes have finally |paid off, launch a devastating Sine |wave at your foes. |Watch out, this weapon packs quite a kick. (This weapon is incomplete)|Attack: Shoot -04:45=全部物理阶级最终|转化为正弦波动|留心,力是相对的|攻击键: 发射 -;04:46=Cover your foes with sizzling liquid flame.|Heartwarming!|Attack: Activate|Up/Down: Continue aiming|Left/Right: Modify spitting power -04:46= 用满腔的火焰虐待你的对手吧。|攻击键: 激活|上/下方向键: 改变攻击方向|左/右方向键: 调整喷射距离 -;04:47=Double the fun with two spiky, sneaky, sticky mines.|Set up a chain reaction or defend yourself (or both!)|Attack: Hold to shoot with more power (twice) -04:47=两次机会双重乐趣,隐蔽且黏着的地雷。|利用脑力造成连锁反应!|攻击键: 按住蓄力(两发) -;04:48=Why should the moles get all the abuse?|Wacking a hog can be just as fun! A good|blow from this hammer will shave off one|third of a hog's health and plunge them|underground.|Attack: Activate -04:48=痛扁刺猬:用力一锤|将使中者镶入地表,削减它健康的1/3.|攻击键: 打 -;04:49=Resurrect your friends!|But beware that this also resurrects your foes.|Attack: Keep attack pressed to resurrect slowly|Up: Accelerate resurrection -04:49=复苏|注意,一视同仁|使用: 按住使用键|上: 提高速率 - -; Game goal strings -;05:01=The following rules apply -05:01= 将应用以下规则 -;05:02=Forts: Defend your fortress; vanquish your enemies! -05:02= 城堡: 守住你的城堡; 削平你的敌人! -;05:03=Low Gravity: Watch your step -05:03= 低重力: 注意脚步 -;05:04=Invulnerability: Hogs are (almost) invulnerable -05:04=无敌: 刺猬不受伤害 -;05:05=Vampirism: Hogs will be healed for the damage dealt -05:05=吸血: 敌人失去的就是我的 -;05:06=Karma: Hogs will be damaged for the damage dealt -05:06=因果效应: 伤害有多少,自己都知道 -;05:07=Protect the King: Don't let your king die!|Place the King: Pick a protected starting point for your King -05:07=保护国王: 国王不能死!|放置国王: 为国王选择安全的起始地点 -;05:08=Place Hedgehogs: Place your hogs before the game starts -05:08=选择起始点: 游戏开始前手动放置刺猬 -;05:09=Artillery: Hogs can't walk to change position -05:09=远程打击: 不许动! -;05:10=Indestructible Terrain: Most weapons won't destroy terrain -05:10=无损地表: 多数武器无法改变地形 -;05:11=Shared Ammo: All teams of the same color share their ammunition -05:11=共享装备: 同色的刺猬共享它们的装备 -;05:12=Mine Timers: Mines will detonate after %1 second(s) -05:12=地雷定时器: %1 秒起爆 -;05:13=Mine Timers: Mines will detonate instantly -05:13=地雷定时器: 立即起爆 -;05:14=Mine Timers: Mines will detonate after 0 - 3 seconds -05:14=地雷定时器: 0-3 秒起爆 -;05:15=Damage Modifier: All weapons will do %1% damage -05:15=伤害修正: 武器伤害使用 %1% 修正值 -;05:16=Health of all hogs is reset on end of turn -05:16=所有活着的刺猬回合结尾时彻底恢复健康 -;05:17=AI hogs respawn on death -05:17=AI刺猬即时复活 -;05:18=Unlimited Attacks -05:18=无限攻击法则 -;05:19=Weapons are reset on end of turn -05:19=武器在回合结束时重置 -;05:20=Weapons are not shared between hogs -05:20=刺猬的武器无法分享 +01:05=退出 (Y/Esc)? +01:06=出现紧急情况! diff -r 763d3961400b -r 3c4b4cb40f40 tools/PascalParser.hs --- a/tools/PascalParser.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/tools/PascalParser.hs Sat Aug 18 00:48:09 2012 +0200 @@ -270,12 +270,12 @@ char ';' comments forward <- liftM isJust $ optionMaybe (try (string "forward;") >> comments) - many functionDecorator + inline <- liftM (any (== "inline;")) $ many functionDecorator b <- if isImpl && (not forward) then liftM Just functionBody else return Nothing - return $ [OperatorDeclaration i rid ret vs b] + return $ [OperatorDeclaration i rid inline ret vs b] funcDecl = do @@ -295,21 +295,24 @@ char ';' comments forward <- liftM isJust $ optionMaybe (try (string "forward;") >> comments) - many functionDecorator + inline <- liftM (any (== "inline;")) $ many functionDecorator b <- if isImpl && (not forward) then liftM Just functionBody else return Nothing - return $ [FunctionDeclaration i ret vs b] + return $ [FunctionDeclaration i inline ret vs b] - functionDecorator = choice [ - try $ string "inline;" - , try $ caseInsensitiveString "cdecl;" - , try $ string "overload;" - , try $ string "export;" - , try $ string "varargs;" - , try (string "external") >> comments >> iD >> optional (string "name" >> comments >> stringLiteral pas)>> string ";" - ] >> comments + functionDecorator = do + d <- choice [ + try $ string "inline;" + , try $ caseInsensitiveString "cdecl;" + , try $ string "overload;" + , try $ string "export;" + , try $ string "varargs;" + , try (string "external") >> comments >> iD >> optional (string "name" >> comments >> stringLiteral pas)>> string ";" + ] + comments + return d program = do diff -r 763d3961400b -r 3c4b4cb40f40 tools/PascalUnitSyntaxTree.hs --- a/tools/PascalUnitSyntaxTree.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/tools/PascalUnitSyntaxTree.hs Sat Aug 18 00:48:09 2012 +0200 @@ -19,8 +19,8 @@ deriving Show data TypeVarDeclaration = TypeDeclaration Identifier TypeDecl | VarDeclaration Bool Bool ([Identifier], TypeDecl) (Maybe InitExpression) - | FunctionDeclaration Identifier TypeDecl [TypeVarDeclaration] (Maybe (TypesAndVars, Phrase)) - | OperatorDeclaration String Identifier TypeDecl [TypeVarDeclaration] (Maybe (TypesAndVars, Phrase)) + | FunctionDeclaration Identifier Bool TypeDecl [TypeVarDeclaration] (Maybe (TypesAndVars, Phrase)) + | OperatorDeclaration String Identifier Bool TypeDecl [TypeVarDeclaration] (Maybe (TypesAndVars, Phrase)) deriving Show data TypeDecl = SimpleType Identifier | RangeType Range diff -r 763d3961400b -r 3c4b4cb40f40 tools/pas2c.hs --- a/tools/pas2c.hs Sat Aug 18 00:47:51 2012 +0200 +++ b/tools/pas2c.hs Sat Aug 18 00:48:09 2012 +0200 @@ -17,24 +17,32 @@ import Data.List (find) import Numeric -import PascalParser +import PascalParser(pascalUnit) import PascalUnitSyntaxTree data InsertOption = IOInsert + | IOInsertWithType Doc | IOLookup | IOLookupLast | IOLookupFunction Int | IODeferred -type Record = (String, BaseType) +data Record = Record + { + lcaseId :: String, + baseType :: BaseType, + typeDecl :: Doc + } + deriving Show type Records = Map.Map String [Record] data RenderState = RenderState { currentScope :: Records, lastIdentifier :: String, lastType :: BaseType, + lastIdTypeDecl :: Doc, stringConsts :: [(String, String)], uniqCounter :: Int, toMangle :: Set.Set String, @@ -43,7 +51,9 @@ namespaces :: Map.Map String Records } -emptyState = RenderState Map.empty "" BTUnknown [] 0 Set.empty "" "" +rec2Records = map (\(a, b) -> Record a b empty) + +emptyState = RenderState Map.empty "" BTUnknown empty [] 0 Set.empty "" "" getUniq :: State RenderState Int getUniq = do @@ -161,12 +171,12 @@ nss <- gets namespaces withState' (\st -> st{currentScope = fromMaybe Map.empty $ Map.lookup li (namespaces st)}) f -withRecordNamespace :: String -> [(String, BaseType)] -> State RenderState Doc -> State RenderState Doc +withRecordNamespace :: String -> [Record] -> State RenderState Doc -> State RenderState Doc withRecordNamespace _ [] = error "withRecordNamespace: empty record" withRecordNamespace prefix recs = withState' f where f st = st{currentScope = Map.unionWith un records (currentScope st), currentUnit = ""} - records = Map.fromList $ map (\(a, b) -> (map toLower a, [(prefix ++ a, b)])) recs + records = Map.fromList $ map (\(Record a b d) -> (map toLower a, [Record (prefix ++ a) b d])) recs un [a] b = a : b toCFiles :: Map.Map String Records -> (String, PascalUnit) -> IO () @@ -200,7 +210,7 @@ pascal2C (Program _ implementation mainFunction) = do impl <- implementation2C implementation - [main] <- tvar2C True False True True (FunctionDeclaration (Identifier "main" BTInt) (SimpleType $ Identifier "int" BTInt) [VarDeclaration False False ([Identifier "argc" BTInt], SimpleType (Identifier "Integer" BTInt)) Nothing, VarDeclaration False False ([Identifier "argv" BTUnknown], SimpleType (Identifier "PPChar" BTUnknown)) Nothing] (Just (TypesAndVars [], mainFunction))) + [main] <- tvar2C True False True True (FunctionDeclaration (Identifier "main" BTInt) False (SimpleType $ Identifier "int" BTInt) [VarDeclaration False False ([Identifier "argc" BTInt], SimpleType (Identifier "Integer" BTInt)) Nothing, VarDeclaration False False ([Identifier "argv" BTUnknown], SimpleType (Identifier "PPChar" BTUnknown)) Nothing] (Just (TypesAndVars [], mainFunction))) return $ impl $+$ main @@ -231,7 +241,7 @@ where initMap = Map.empty --initMap = Map.fromList [("reset", 2)] - ins (FunctionDeclaration (Identifier i _) _ _ _) m = Map.insertWith (+) (map toLower i) 1 m + ins (FunctionDeclaration (Identifier i _) _ _ _ _) m = Map.insertWith (+) (map toLower i) 1 m ins _ m = m -- the second bool indicates whether declare variable as extern or not @@ -261,8 +271,11 @@ uses2List (Uses ids) = map (\(Identifier i _) -> i) ids +setLastIdValues vv = (\s -> s{lastType = baseType vv, lastIdentifier = lcaseId vv, lastIdTypeDecl = typeDecl vv}) + id2C :: InsertOption -> Identifier -> State RenderState Doc -id2C IOInsert (Identifier i t) = do +id2C IOInsert i = id2C (IOInsertWithType empty) i +id2C (IOInsertWithType d) (Identifier i t) = do ns <- gets currentScope tom <- gets (Set.member n . toMangle) cu <- gets currentUnit @@ -271,7 +284,7 @@ (BTFunction _ _ _, _) -> (cu ++ i, t) (BTVarParam t', _) -> ('(' : '*' : i ++ ")" , t') _ -> (i, t) - modify (\s -> s{currentScope = Map.insertWith (++) n [(i', t')] (currentScope s), lastIdentifier = n}) + modify (\s -> s{currentScope = Map.insertWith (++) n [Record i' t' d] (currentScope s), lastIdentifier = n}) return $ text i' where n = map toLower i @@ -286,9 +299,9 @@ error $ "Not defined: '" ++ i' ++ "'\n" ++ show lt ++ "\nwith num of params = " ++ show params ++ "\n" ++ show v else let vv = fromMaybe (head $ fromJust v) . find checkParam $ fromJust v in - modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv) + modify (setLastIdValues vv) >> (return . text . lcaseId $ vv) where - checkParam (_, BTFunction _ p _) = p == params + checkParam (Record _ (BTFunction _ p _) _) = p == params checkParam _ = False id2C IODeferred (Identifier i t) = do let i' = map toLower i @@ -296,7 +309,7 @@ if (isNothing v) then modify (\s -> s{lastType = BTUnknown, lastIdentifier = i}) >> return (text i) else - let vv = head $ fromJust v in modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv) + let vv = head $ fromJust v in modify (setLastIdValues vv) >> (return . text . lcaseId $ vv) id2CLookup :: ([Record] -> Record) -> Identifier -> State RenderState Doc id2CLookup f (Identifier i t) = do @@ -306,30 +319,34 @@ if isNothing v then error $ "Not defined: '" ++ i' ++ "'\n" ++ show lt else - let vv = f $ fromJust v in modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv) + let vv = f $ fromJust v in modify (setLastIdValues vv) >> (return . text . lcaseId $ vv) id2CTyped :: TypeDecl -> Identifier -> State RenderState Doc -id2CTyped t (Identifier i _) = do +id2CTyped = id2CTyped2 Nothing + +id2CTyped2 :: Maybe Doc -> TypeDecl -> Identifier -> State RenderState Doc +id2CTyped2 md t (Identifier i _) = do tb <- resolveType t case (t, tb) of (_, BTUnknown) -> do error $ "id2CTyped: type BTUnknown for " ++ show i ++ "\ntype: " ++ show t (SimpleType {}, BTRecord _ r) -> do ts <- type2C t - id2C IOInsert (Identifier i (BTRecord (render $ ts empty) r)) + id2C (IOInsertWithType $ ts empty) (Identifier i (BTRecord (render $ ts empty) r)) (_, BTRecord _ r) -> do ts <- type2C t - id2C IOInsert (Identifier i (BTRecord i r)) - _ -> id2C IOInsert (Identifier i tb) - + id2C (IOInsertWithType $ ts empty) (Identifier i (BTRecord i r)) + _ -> case md of + Nothing -> id2C IOInsert (Identifier i tb) + Just ts -> id2C (IOInsertWithType ts) (Identifier i tb) resolveType :: TypeDecl -> State RenderState BaseType resolveType st@(SimpleType (Identifier i _)) = do let i' = map toLower i v <- gets $ Map.lookup i' . currentScope - if isJust v then return . snd . head $ fromJust v else return $ f i' + if isJust v then return . baseType . head $ fromJust v else return $ f i' where f "integer" = BTInt f "pointer" = BTPointerTo BTVoid @@ -372,7 +389,7 @@ resolve s (BTUnresolved t) = do v <- gets $ Map.lookup t . currentScope if isJust v then - resolve s . snd . head . fromJust $ v + resolve s . baseType . head . fromJust $ v else error $ "Unknown type " ++ show t ++ "\n" ++ s resolve _ t = return t @@ -412,20 +429,21 @@ ps = zip ['a'..] (toIsVarList params) fun2C :: Bool -> String -> TypeVarDeclaration -> State RenderState [Doc] -fun2C _ _ (FunctionDeclaration name returnType params Nothing) = do +fun2C _ _ (FunctionDeclaration name inline returnType params Nothing) = do t <- type2C returnType t'<- gets lastType p <- withState' id $ functionParams2C params n <- liftM render . id2C IOInsert $ setBaseType (BTFunction hasVars (numberOfDeclarations params) t') name + let decor = if inline then text "inline" else empty if hasVars then - return [funWithVarsToDefine n params $+$ t empty <+> text (n ++ "__vars") <> parens p] + return [funWithVarsToDefine n params $+$ decor <+> t empty <+> text (n ++ "__vars") <> parens p] else - return [t empty <+> text n <> parens p] + return [decor <+> t empty <+> text n <> parens p] where hasVars = hasPassByReference params -fun2C True rv (FunctionDeclaration name@(Identifier i _) returnType params (Just (tvars, phrase))) = do +fun2C True rv (FunctionDeclaration name@(Identifier i _) inline returnType params (Just (tvars, phrase))) = do let res = docToLower $ text rv <> text "_result" t <- type2C returnType t'<- gets lastType @@ -438,7 +456,7 @@ VoidType -> True _ -> False - (p, ph) <- withState' (\st -> st{currentScope = Map.insertWith un (map toLower rv) [(render res, t')] $ currentScope st + (p, ph) <- withState' (\st -> st{currentScope = Map.insertWith un (map toLower rv) [Record (render res) t' empty] $ currentScope st , currentFunctionResult = if isVoid then [] else render res}) $ do p <- functionParams2C params ph <- liftM2 ($+$) (typesAndVars2C False False True tvars) (phrase2C' phrase) @@ -446,11 +464,12 @@ let phrasesBlock = if isVoid then ph else t empty <+> res <> semi $+$ ph $+$ text "return" <+> res <> semi let define = if hasVars then text "#ifndef" <+> text n $+$ funWithVarsToDefine n params $+$ text "#endif" else empty + let decor = if inline then text "inline" else empty return [ define $+$ --(if notDeclared && hasVars then funWithVarsToDefine n params else empty) $+$ - t empty <+> text (if hasVars then n ++ "__vars" else n) <> parens p + decor <+> t empty <+> text (if hasVars then n ++ "__vars" else n) <> parens p $+$ text "{" $+$ @@ -463,14 +482,14 @@ un [a] b = a : b hasVars = hasPassByReference params -fun2C False _ (FunctionDeclaration (Identifier name _) _ _ _) = error $ "nested functions not allowed: " ++ name +fun2C False _ (FunctionDeclaration (Identifier name _) _ _ _ _) = error $ "nested functions not allowed: " ++ name fun2C _ tv _ = error $ "fun2C: I don't render " ++ show tv -- the second bool indicates whether declare variable as extern or not -- the third bool indicates whether include types or not -- the fourth bool indicates whether ignore initialization or not (basically for dynamic arrays since we cannot do initialization in function params) tvar2C :: Bool -> Bool -> Bool -> Bool -> TypeVarDeclaration -> State RenderState [Doc] -tvar2C b _ includeType _ f@(FunctionDeclaration (Identifier name _) _ _ _) = do +tvar2C b _ includeType _ f@(FunctionDeclaration (Identifier name _) _ _ _ _) = do t <- fun2C b name f if includeType then return t else return [] tvar2C _ _ includeType _ td@(TypeDeclaration i' t) = do @@ -480,7 +499,7 @@ tvar2C _ _ _ _ (VarDeclaration True _ (ids, t) Nothing) = do t' <- liftM ((empty <+>) . ) $ type2C t - liftM (map(\i -> t' i)) $ mapM (id2CTyped (VarParamType t)) ids + liftM (map(\i -> t' i)) $ mapM (id2CTyped2 (Just $ t' empty) (VarParamType t)) ids tvar2C _ externVar includeType ignoreInit (VarDeclaration _ isConst (ids, t) mInitExpr) = do t' <- liftM (((if isConst then text "static const" else if externVar @@ -515,7 +534,7 @@ (_, _) -> return result - _ -> liftM (map(\i -> varDeclDecision isConst includeType (t' i) ie)) $ mapM (id2CTyped t) ids + _ -> liftM (map(\i -> varDeclDecision isConst includeType (t' i) ie)) $ mapM (id2CTyped2 (Just $ t' empty) t) ids where initExpr Nothing = return $ empty initExpr (Just e) = liftM (text "=" <+>) (initExpr2C e) @@ -528,9 +547,9 @@ ArrayDecl _ _ -> error "Mixed dynamic array and static array are not supported." _ -> 0 -tvar2C f _ _ _ (OperatorDeclaration op (Identifier i _) ret params body) = do +tvar2C f _ _ _ (OperatorDeclaration op (Identifier i _) inline ret params body) = do r <- op2CTyped op (extractTypes params) - fun2C f i (FunctionDeclaration r ret params body) + fun2C f i (FunctionDeclaration r inline ret params body) op2CTyped :: String -> [TypeDecl] -> State RenderState Identifier @@ -780,20 +799,27 @@ r <- ref2C ref t <- gets lastType case t of - (BTRecord _ rs) -> withRecordNamespace (render r ++ ".") rs $ phrase2C $ wrapPhrase p + (BTRecord _ rs) -> withRecordNamespace (render r ++ ".") (rec2Records rs) $ phrase2C $ wrapPhrase p a -> do error $ "'with' block referencing non-record type " ++ show a ++ "\n" ++ show wb phrase2C (ForCycle i' e1' e2' p up) = do i <- id2C IOLookup i' + iType <- gets lastIdTypeDecl e1 <- expr2C e1' e2 <- expr2C e2' - ph <- phrase2C (wrapPhrase p) - cmp <- return $ if up == True then "<=" else ">=" - inc <- return $ if up == True then "++" else "--" - return $ - text "for" <> (parens . hsep . punctuate (char ';') $ [i <+> text "=" <+> parens e1, i <+> text cmp <+> parens e2, text inc <> i]) + let inc = if up then "inc" else "dec" + let add = if up then "+ 1" else "- 1" + let iEnd = i <> text "__end__" + ph <- phrase2C . appendPhrase (BuiltInFunctionCall [Reference $ SimpleReference i'] (SimpleReference (Identifier inc BTUnknown))) $ wrapPhrase p + return . braces $ + i <+> text "=" <+> e1 <> semi $$ - ph + iType <+> iEnd <+> text "=" <+> e2 <> semi + $$ + text "if" <+> (parens $ i <+> text "<=" <+> iEnd) <+> text "do" <+> ph <+> + text "while" <> parens (i <+> text "!=" <+> iEnd <+> text add) <> semi + where + appendPhrase p (Phrases ps) = Phrases $ ps ++ [p] phrase2C (RepeatCycle e' p') = do e <- expr2C e' p <- phrase2C (Phrases p') @@ -992,7 +1018,7 @@ r1 <- ref2C ref1 t <- fromPointer (show ref1) =<< gets lastType r2 <- case t of - BTRecord _ rs -> withRecordNamespace "" rs $ ref2C ref2 + BTRecord _ rs -> withRecordNamespace "" (rec2Records rs) $ ref2C ref2 BTUnit -> error "What??" a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf return $ @@ -1002,7 +1028,7 @@ t <- gets lastType case t of BTRecord _ rs -> do - r2 <- withRecordNamespace "" rs $ ref2C ref2 + r2 <- withRecordNamespace "" (rec2Records rs) $ ref2C ref2 return $ r1 <> text "." <> r2 BTUnit -> withLastIdNamespace $ ref2C ref2 a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf