# HG changeset patch # User koda # Date 1382965624 -3600 # Node ID 3a3defce1b28f666825976c3aeb447e6727ff45a # Parent 37a6d807c1408aacf4b46ec35e1dedab86451251# Parent 7588daa8d28f8e5d2708b10f8ac39931f7c3aebf merge spacecampaign diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/CMakeLists.txt --- a/QTfrontend/CMakeLists.txt Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/CMakeLists.txt Mon Oct 28 14:07:04 2013 +0100 @@ -13,6 +13,12 @@ find_package(Qt4 REQUIRED) include(${QT_USE_FILE}) +if(APPLE AND + ${QTVERSION} VERSION_GREATER "4.7.0" AND + ${QTVERSION} VERSION_LESS "4.7.4") + message(FATAL_ERROR "This version of QT is known *not* to work, please update or use a lower version") +endif() + find_package(SDL REQUIRED) #video in SDLInteraction find_package(SDL_mixer REQUIRED) #audio in SDLInteraction diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/drawmapscene.cpp --- a/QTfrontend/drawmapscene.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/drawmapscene.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "drawmapscene.h" @@ -44,6 +46,8 @@ setBackgroundBrush(m_eraser); m_isErasing = false; + m_pathType = Polyline; + m_pen.setWidth(76); m_pen.setJoinStyle(Qt::RoundJoin); m_pen.setCapStyle(Qt::RoundCap); @@ -60,19 +64,45 @@ if(m_currPath && (mouseEvent->buttons() & Qt::LeftButton)) { QPainterPath path = m_currPath->path(); + QPointF currentPos = mouseEvent->scenePos(); if(mouseEvent->modifiers() & Qt::ControlModifier) + currentPos = putSomeConstraints(paths.first().initialPoint, currentPos); + + switch (m_pathType) { - int c = path.elementCount(); - QPointF pos = mouseEvent->scenePos(); - path.setElementPositionAt(c - 1, pos.x(), pos.y()); + case Polyline: + if(mouseEvent->modifiers() & Qt::ControlModifier) + { + int c = path.elementCount(); + path.setElementPositionAt(c - 1, currentPos.x(), currentPos.y()); + } + else + { + path.lineTo(currentPos); + paths.first().points.append(mouseEvent->scenePos().toPoint()); + } + break; + case Rectangle: { + path = QPainterPath(); + QPointF p1 = paths.first().initialPoint; + QPointF p2 = currentPos; + path.moveTo(p1); + path.lineTo(p1.x(), p2.y()); + path.lineTo(p2); + path.lineTo(p2.x(), p1.y()); + path.lineTo(p1); + break; + } + case Ellipse: { + path = QPainterPath(); + QList points = makeEllipse(paths.first().initialPoint, currentPos); + path.addPolygon(QPolygonF(QVector::fromList(points))); + break; } - else - { - path.lineTo(mouseEvent->scenePos()); - paths.first().points.append(mouseEvent->scenePos().toPoint()); } + m_currPath->setPath(path); emit pathChanged(); @@ -96,7 +126,8 @@ PathParams params; params.width = serializePenWidth(m_pen.width()); params.erasing = m_isErasing; - params.points = QList() << mouseEvent->scenePos().toPoint(); + params.initialPoint = mouseEvent->scenePos().toPoint(); + params.points = QList() << params.initialPoint; paths.prepend(params); m_currPath->setPath(path); @@ -107,14 +138,43 @@ { if (m_currPath) { - QPainterPath path = m_currPath->path(); - path.lineTo(mouseEvent->scenePos()); - paths.first().points.append(mouseEvent->scenePos().toPoint()); - m_currPath->setPath(path); + QPointF currentPos = mouseEvent->scenePos(); + + if(mouseEvent->modifiers() & Qt::ControlModifier) + currentPos = putSomeConstraints(paths.first().initialPoint, currentPos); - simplifyLast(); + switch (m_pathType) + { + case Polyline: { + QPainterPath path = m_currPath->path(); + path.lineTo(mouseEvent->scenePos()); + paths.first().points.append(currentPos.toPoint()); + m_currPath->setPath(path); + simplifyLast(); + break; + } + case Rectangle: { + QPoint p1 = paths.first().initialPoint; + QPoint p2 = currentPos.toPoint(); + QList rpoints; + rpoints << p1 << QPoint(p1.x(), p2.y()) << p2 << QPoint(p2.x(), p1.y()) << p1; + paths.first().points = rpoints; + break; + } + case Ellipse: + QPoint p1 = paths.first().initialPoint; + QPoint p2 = currentPos.toPoint(); + QList points = makeEllipse(p1, p2); + QList epoints; + foreach(const QPointF & p, points) + epoints.append(p.toPoint()); + paths.first().points = epoints; + break; + } m_currPath = 0; + + emit pathChanged(); } } @@ -156,7 +216,7 @@ if(m_isCursorShown) return; - if(items().size()) + if(paths.size()) { removeItem(items().first()); paths.removeFirst(); @@ -183,15 +243,18 @@ if(!items().size()) return; + m_specialPoints.clear(); oldItems.clear(); // do this since clear() would _destroy_ all items - while(items().size()) + for(int i = paths.size() - 1; i >= 0; --i) { oldItems.push_front(items().first()); removeItem(items().first()); } + items().clear(); + oldPaths = paths; paths.clear(); @@ -211,7 +274,7 @@ QByteArray DrawMapScene::encode() { - QByteArray b; + QByteArray b(m_specialPoints); for(int i = paths.size() - 1; i >= 0; --i) { @@ -247,9 +310,12 @@ oldPaths.clear(); clear(); paths.clear(); + m_specialPoints.clear(); PathParams params; + bool isSpecial = true; + while(data.size() >= 5) { qint16 px = qFromBigEndian(*(qint16 *)data.data()); @@ -258,9 +324,11 @@ data.remove(0, 2); quint8 flags = *(quint8 *)data.data(); data.remove(0, 1); - + qDebug() << px << py; if(flags & 0x80) { + isSpecial = false; + if(params.points.size()) { addPath(pointsToPath(params.points), m_pen); @@ -278,9 +346,23 @@ else m_pen.setBrush(m_brush); params.width = penWidth; - } + } else + if(isSpecial) + { + QPainterPath path; + path.addEllipse(QPointF(px, py), 10, 10); + + addPath(path); - params.points.append(QPoint(px, py)); + qint16 x = qToBigEndian(px); + qint16 y = qToBigEndian(py); + m_specialPoints.append((const char *)&x, 2); + m_specialPoints.append((const char *)&y, 2); + m_specialPoints.append((const char *)&flags, 1); + } + + if(!isSpecial) + params.points.append(QPoint(px, py)); } if(params.points.size()) @@ -323,8 +405,6 @@ QGraphicsPathItem * pathItem = static_cast(items()[m_isCursorShown ? 1 : 0]); pathItem->setPath(pointsToPath(paths[0].points)); } - - emit pathChanged(); } int DrawMapScene::pointsCount() @@ -361,3 +441,47 @@ { return width * 10 + 6; } + +void DrawMapScene::setPathType(PathType pathType) +{ + m_pathType = pathType; +} + +QList DrawMapScene::makeEllipse(const QPointF ¢er, const QPointF &corner) +{ + QList l; + qreal rx = qAbs(center.x() - corner.x()); + qreal ry = qAbs(center.y() - corner.y()); + qreal r = qMax(rx, ry); + + if(r < 4) + { + l.append(center); + } else + { + qreal angleDelta = qMax(0.1, qMin(0.7, 120 / r)); + for(qreal angle = 0.0; angle < 2*M_PI; angle += angleDelta) + l.append(center + QPointF(rx * cos(angle), ry * sin(angle))); + l.append(l.first()); + } + + return l; +} + +QPointF DrawMapScene::putSomeConstraints(const QPointF &initialPoint, const QPointF &point) +{ + QPointF vector = point - initialPoint; + + for(int angle = 0; angle < 180; angle += 15) + { + QTransform transform; + transform.rotate(angle); + + QPointF rotated = transform.map(vector); + + if(rotated.x() == 0) return point; + if(qAbs(rotated.y() / rotated.x()) < 0.05) return initialPoint + transform.inverted().map(QPointF(rotated.x(), 0)); + } + + return point; +} diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/drawmapscene.h --- a/QTfrontend/drawmapscene.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/drawmapscene.h Mon Oct 28 14:07:04 2013 +0100 @@ -29,6 +29,7 @@ { quint8 width; bool erasing; + QPoint initialPoint; QList points; }; @@ -38,6 +39,12 @@ { Q_OBJECT public: + enum PathType { + Polyline = 0, + Rectangle = 1, + Ellipse = 2 + }; + explicit DrawMapScene(QObject *parent = 0); QByteArray encode(); @@ -54,6 +61,7 @@ void setErasing(bool erasing); void showCursor(); void hideCursor(); + void setPathType(PathType pathType); private: QPen m_pen; @@ -66,6 +74,8 @@ QList oldItems; QGraphicsEllipseItem * m_cursor; bool m_isCursorShown; + QByteArray m_specialPoints; + PathType m_pathType; virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent); virtual void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent); @@ -76,6 +86,8 @@ quint8 serializePenWidth(int width); int deserializePenWidth(quint8 width); + QList makeEllipse(const QPointF & center, const QPointF & corner); + QPointF putSomeConstraints(const QPointF & initialPoint, const QPointF & point); }; #endif // DRAWMAPSCENE_H diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/game.cpp --- a/QTfrontend/game.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/game.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -89,18 +89,6 @@ SetGameState(gsStopped); } -void HWGame::addKeyBindings(QByteArray * buf) -{ - for(int i = 0; i < BINDS_NUMBER; i++) - { - QString value = config->value(QString("Binds/%1").arg(cbinds[i].action), cbinds[i].strbind).toString(); - if (value.isEmpty() || value == "default") continue; - - QString bind = QString("edbind " + value + " " + cbinds[i].action); - HWProto::addStringToBuffer(*buf, bind); - } -} - void HWGame::commonConfig() { QByteArray buf; @@ -118,8 +106,6 @@ } HWProto::addStringToBuffer(buf, gt); - addKeyBindings(&buf); - buf += gamecfg->getFullConfig(); if (m_pTeamSelWidget) @@ -132,7 +118,7 @@ HWProto::addStringToBuffer(buf, QString("eammreinf %1").arg(ammostr.mid(3 * cAmmoNumber, cAmmoNumber))); if(gamecfg->schemeData(15).toBool() || !gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore")); HWProto::addStringListToBuffer(buf, - team.teamGameConfig(gamecfg->getInitHealth(), config)); + team.teamGameConfig(gamecfg->getInitHealth())); ; } } @@ -150,8 +136,6 @@ QByteArray teamscfg; ThemeModel * themeModel = DataManager::instance().themeModel(); - addKeyBindings(&teamscfg); - HWProto::addStringToBuffer(teamscfg, "TL"); HWProto::addStringToBuffer(teamscfg, QString("etheme %1") .arg((themeModel->rowCount() > 0) ? themeModel->index(rand() % themeModel->rowCount()).data(ThemeModel::ActualNameRole).toString() : "steel")); @@ -165,7 +149,7 @@ team1.setNumHedgehogs(4); HWNamegen::teamRandomNames(team1,true); HWProto::addStringListToBuffer(teamscfg, - team1.teamGameConfig(100, config)); + team1.teamGameConfig(100)); HWTeam team2; team2.setDifficulty(4); @@ -175,7 +159,7 @@ HWNamegen::teamRandomNames(team2,true); while(!team2.name().compare(team1.name()) || !team2.hedgehog(0).Hat.compare(team1.hedgehog(0).Hat)); HWProto::addStringListToBuffer(teamscfg, - team2.teamGameConfig(100, config)); + team2.teamGameConfig(100)); HWProto::addStringToBuffer(teamscfg, QString("eammloadt %1").arg(cDefaultAmmoStore->mid(0, cAmmoNumber))); HWProto::addStringToBuffer(teamscfg, QString("eammprob %1").arg(cDefaultAmmoStore->mid(cAmmoNumber, cAmmoNumber))); @@ -194,8 +178,6 @@ HWProto::addStringToBuffer(traincfg, "eseed " + QUuid::createUuid().toString()); HWProto::addStringToBuffer(traincfg, "escript " + training); - addKeyBindings(&traincfg); - RawSendIPC(traincfg); } @@ -207,8 +189,6 @@ HWProto::addStringToBuffer(campaigncfg, "escript " + campaignScript); - addKeyBindings(&campaigncfg); - RawSendIPC(campaigncfg); } diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/game.h --- a/QTfrontend/game.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/game.h Mon Oct 28 14:07:04 2013 +0100 @@ -113,7 +113,6 @@ GameType gameType; QByteArray m_netSendBuffer; - void addKeyBindings(QByteArray * buf); void commonConfig(); void SendConfig(); void SendQuickConfig(); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/gameuiconfig.cpp --- a/QTfrontend/gameuiconfig.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/gameuiconfig.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -159,6 +159,8 @@ Form->ui.pageOptions->leProxyLogin->setText(value("proxy/login", "").toString()); Form->ui.pageOptions->leProxyPassword->setText(value("proxy/password", "").toString()); + applyProxySettings(); + { // load colors QStandardItemModel * model = DataManager::instance().colorsModel(); for(int i = model->rowCount() - 1; i >= 0; --i) @@ -310,22 +312,7 @@ setValue("proxy/password", Form->ui.pageOptions->leProxyPassword->text()); } - QNetworkProxy proxy; - - if(proxyType == PageOptions::SystemProxy) - { - // use system proxy settings - proxy = QNetworkProxyFactory::systemProxyForQuery().at(0); - } else - { - proxy.setType(proxyTypesMap[proxyType]); - proxy.setHostName(Form->ui.pageOptions->leProxy->text()); - proxy.setPort(Form->ui.pageOptions->sbProxyPort->value()); - proxy.setUser(Form->ui.pageOptions->leProxyLogin->text()); - proxy.setPassword(Form->ui.pageOptions->leProxyPassword->text()); - } - - QNetworkProxy::setApplicationProxy(proxy); + applyProxySettings(); } { // save colors @@ -665,3 +652,25 @@ m_binds[bindID].strbind = strbind; setValue(QString("Binds/%1").arg(m_binds[bindID].action), strbind); } + +void GameUIConfig::applyProxySettings() +{ + QNetworkProxy proxy; + + int proxyType = Form->ui.pageOptions->cbProxyType->currentIndex(); + + if(proxyType == PageOptions::SystemProxy) + { + // use system proxy settings + proxy = QNetworkProxyFactory::systemProxyForQuery().at(0); + } else + { + proxy.setType(proxyTypesMap[proxyType]); + proxy.setHostName(Form->ui.pageOptions->leProxy->text()); + proxy.setPort(Form->ui.pageOptions->sbProxyPort->value()); + proxy.setUser(Form->ui.pageOptions->leProxyLogin->text()); + proxy.setPassword(Form->ui.pageOptions->leProxyPassword->text()); + } + + QNetworkProxy::setApplicationProxy(proxy); +} diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/gameuiconfig.h --- a/QTfrontend/gameuiconfig.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/gameuiconfig.h Mon Oct 28 14:07:04 2013 +0100 @@ -99,6 +99,8 @@ bool eventFilter(QObject *object, QEvent *event); QString temphash; QList m_binds; + + void applyProxySettings(); }; #endif diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/hedgewars.qrc --- a/QTfrontend/hedgewars.qrc Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/hedgewars.qrc Mon Oct 28 14:07:04 2013 +0100 @@ -128,6 +128,7 @@ res/iconMine.png res/iconDud.png res/iconRope.png + res/iconEarth.png res/dice.png res/Star.png res/inverse-corner-bl.png @@ -179,5 +180,9 @@ res/splash.png res/html/about.html res/xml/tips.xml + res/chat/hedgehogcontributor.png + res/chat/hedgehogcontributor_gray.png + res/chat/roomadmincontributor.png + res/chat/roomadmincontributor_gray.png diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/hwform.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -1130,7 +1130,7 @@ //ForcedDisconnect(tr("No nickname supplied.")); bool retry = RetryDialog(tr("Hedgewars - Empty nickname"), tr("No nickname supplied.")); GoBack(); - if (retry) { + if (retry && hwnet) { if (hwnet->m_private_game) { QStringList list = hwnet->getHost().split(":"); NetConnectServer(list.at(0), list.at(1).toShort()); @@ -1140,7 +1140,8 @@ return; } - hwnet->NewNick(newNick); + if(hwnet) + hwnet->NewNick(newNick); config->setValue("net/nick", newNick); config->updNetNick(); @@ -1164,6 +1165,13 @@ } } +void HWForm::askRoomPassword() +{ + QString password = QInputDialog::getText(this, tr("Room password"), tr("The room is protected with password.\nPlease, enter the password:")); + if(hwnet && !password.isEmpty()) + hwnet->roomPasswordEntered(password); +} + bool HWForm::RetryDialog(const QString & title, const QString & label) { QMessageBox retryMsg(this); @@ -1243,6 +1251,7 @@ connect(hwnet, SIGNAL(NickTaken(const QString&)), this, SLOT(NetNickTaken(const QString&)), Qt::QueuedConnection); connect(hwnet, SIGNAL(AuthFailed()), this, SLOT(NetAuthFailed()), Qt::QueuedConnection); //connect(ui.pageNetGame->BtnBack, SIGNAL(clicked()), hwnet, SLOT(partRoom())); + connect(hwnet, SIGNAL(askForRoomPassword()), this, SLOT(askRoomPassword()), Qt::QueuedConnection); ui.pageRoomsList->chatWidget->setUsersModel(hwnet->lobbyPlayersModel()); ui.pageNetGame->chatWidget->setUsersModel(hwnet->roomPlayersModel()); @@ -1257,10 +1266,10 @@ connect(hwnet, SIGNAL(serverMessage(const QString&)), ui.pageRoomsList->chatWidget, SLOT(onServerMessage(const QString&)), Qt::QueuedConnection); - connect(ui.pageRoomsList, SIGNAL(askForCreateRoom(const QString &)), - hwnet, SLOT(CreateRoom(const QString&))); - connect(ui.pageRoomsList, SIGNAL(askForJoinRoom(const QString &)), - hwnet, SLOT(JoinRoom(const QString&))); + connect(ui.pageRoomsList, SIGNAL(askForCreateRoom(const QString &, const QString &)), + hwnet, SLOT(CreateRoom(const QString&, const QString &))); + connect(ui.pageRoomsList, SIGNAL(askForJoinRoom(const QString &, const QString &)), + hwnet, SLOT(JoinRoom(const QString&, const QString &))); // connect(ui.pageRoomsList, SIGNAL(askForCreateRoom(const QString &)), // this, SLOT(NetGameMaster())); // connect(ui.pageRoomsList, SIGNAL(askForJoinRoom(const QString &)), diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/hwform.h --- a/QTfrontend/hwform.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/hwform.h Mon Oct 28 14:07:04 2013 +0100 @@ -112,6 +112,7 @@ void NetNickNotRegistered(const QString & nick); void NetNickTaken(const QString & nick); void NetAuthFailed(); + void askRoomPassword(); bool RetryDialog(const QString & title, const QString & label); void NetTeamAccepted(const QString& team); void AddNetTeam(const HWTeam& team); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/model/ammoSchemeModel.cpp --- a/QTfrontend/model/ammoSchemeModel.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/model/ammoSchemeModel.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -64,6 +64,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; AmmoSchemeModel::AmmoSchemeModel(QObject* parent, const QString & fileName) : @@ -128,6 +129,7 @@ << "healthdecrease" // 38 << "ropepct" // 39 << "getawaytime" // 40 + << "worldedge" // 41 ; QList proMode; @@ -173,6 +175,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList shoppa; @@ -218,6 +221,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList cleanslate; @@ -263,6 +267,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList minefield; @@ -308,6 +313,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList barrelmayhem; @@ -353,6 +359,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList tunnelhogs; @@ -398,6 +405,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList forts; @@ -443,6 +451,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList timeless; @@ -488,6 +497,7 @@ << QVariant(0) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList thinkingportals; @@ -533,6 +543,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; QList kingmode; @@ -578,6 +589,7 @@ << QVariant(5) // health dec amt 38 << QVariant(100) // rope modfier 39 << QVariant(100) // get away time 40 + << QVariant(0) // world edge 41 ; diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/model/playerslistmodel.cpp --- a/QTfrontend/model/playerslistmodel.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/model/playerslistmodel.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -11,7 +11,8 @@ PlayersListModel::PlayersListModel(QObject *parent) : QAbstractListModel(parent) { - + m_fontInRoom = QFont(); + m_fontInRoom.setItalic(true); } @@ -223,6 +224,7 @@ << index.data(Ignore).toBool() << index.data(InGame).toBool() << index.data(RoomFilterRole).toBool() + << index.data(InRoom).toBool() ; for(int i = flags.size() - 1; i >= 0; --i) @@ -253,16 +255,26 @@ else painter.drawPixmap(0, 0, 16, 16, QPixmap(":/res/chat/lamp_off.png")); } + } else + { // we're in lobby + if(!index.data(InRoom).toBool()) + painter.drawPixmap(0, 0, 16, 16, QPixmap(":/res/Flake.png")); } QString mainIconName(":/res/chat/"); - if(index.data(RoomAdmin).toBool()) - mainIconName += "roomadmin"; - else if(index.data(ServerAdmin).toBool()) + if(index.data(ServerAdmin).toBool()) mainIconName += "serveradmin"; else - mainIconName += "hedgehog"; + { + if(index.data(RoomAdmin).toBool()) + mainIconName += "roomadmin"; + else + mainIconName += "hedgehog"; + + if(index.data(Contributor).toBool()) + mainIconName += "contributor"; + } if(!index.data(Registered).toBool()) mainIconName += "_gray"; diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/model/playerslistmodel.h --- a/QTfrontend/model/playerslistmodel.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/model/playerslistmodel.h Mon Oct 28 14:07:04 2013 +0100 @@ -6,6 +6,7 @@ #include #include #include +#include class PlayersListModel : public QAbstractListModel { @@ -19,7 +20,9 @@ Registered = Qt::UserRole + 3, Friend = Qt::UserRole + 4, Ignore = Qt::UserRole + 5, - InGame = Qt::UserRole + 6 + InGame = Qt::UserRole + 6, + InRoom = Qt::UserRole + 7, + Contributor = Qt::UserRole + 8 }; enum SpecialRoles { @@ -61,6 +64,7 @@ QList m_data; QSet m_friendsSet, m_ignoredSet; QString m_nickname; + QFont m_fontInRoom; void updateIcon(const QModelIndex & index); void updateSortData(const QModelIndex & index); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/net/newnetclient.cpp --- a/QTfrontend/net/newnetclient.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/net/newnetclient.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -94,7 +94,7 @@ NetSocket.disconnectFromHost(); } -void HWNewNet::CreateRoom(const QString & room) +void HWNewNet::CreateRoom(const QString & room, const QString & password) { if(netClientState != InLobby) { @@ -104,11 +104,15 @@ myroom = room; - RawSendNet(QString("CREATE_ROOM%1%2").arg(delimeter).arg(room)); + if(password.isEmpty()) + RawSendNet(QString("CREATE_ROOM%1%2").arg(delimeter).arg(room)); + else + RawSendNet(QString("CREATE_ROOM%1%2%1%3").arg(delimeter).arg(room).arg(password)); + isChief = true; } -void HWNewNet::JoinRoom(const QString & room) +void HWNewNet::JoinRoom(const QString & room, const QString &password) { if(netClientState != InLobby) { @@ -118,7 +122,11 @@ myroom = room; - RawSendNet(QString("JOIN_ROOM%1%2").arg(delimeter).arg(room)); + if(password.isEmpty()) + RawSendNet(QString("JOIN_ROOM%1%2").arg(delimeter).arg(room)); + else + RawSendNet(QString("JOIN_ROOM%1%2%1%3").arg(delimeter).arg(room).arg(password)); + isChief = false; } @@ -436,6 +444,16 @@ foreach(const QString & nick, nicks) m_playersModel->setFlag(nick, PlayersListModel::Registered, setFlag); break; + // flag indicating if a player is in room + case 'i': + foreach(const QString & nick, nicks) + m_playersModel->setFlag(nick, PlayersListModel::InRoom, setFlag); + break; + // flag indicating if a player is contributor + case 'c': + foreach(const QString & nick, nicks) + m_playersModel->setFlag(nick, PlayersListModel::InRoom, setFlag); + break; // flag indicating if a player has engine running case 'g': if(inRoom) @@ -1055,10 +1073,11 @@ switch(n) { case 0: - { emit NickTaken(mynick); break; - } + case 2: + emit askForRoomPassword(); + break; } } @@ -1076,3 +1095,9 @@ { return m_roomPlayersModel; } + +void HWNewNet::roomPasswordEntered(const QString &password) +{ + if(!myroom.isEmpty()) + JoinRoom(myroom, password); +} diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/net/newnetclient.h --- a/QTfrontend/net/newnetclient.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/net/newnetclient.h Mon Oct 28 14:07:04 2013 +0100 @@ -76,6 +76,7 @@ PlayersListModel * m_playersModel; QSortFilterProxyModel * m_lobbyPlayersModel; QSortFilterProxyModel * m_roomPlayersModel; + QString m_lastRoom; QStringList cmdbuf; @@ -103,6 +104,7 @@ void adminAccess(bool); void roomMaster(bool); void roomNameUpdated(const QString & name); + void askForRoomPassword(); void netSchemeConfig(QStringList &); void paramChanged(const QString & param, const QStringList & value); @@ -153,8 +155,8 @@ void setLatestProtocolVar(int proto); void askServerVars(); - void JoinRoom(const QString & room); - void CreateRoom(const QString & room); + void JoinRoom(const QString & room, const QString & password); + void CreateRoom(const QString & room, const QString &password); void updateRoomName(const QString &); void askRoomsList(); void gameFinished(bool correcly); @@ -173,6 +175,7 @@ void removeBan(const QString &); void banIP(const QString & ip, const QString & reason, int seconds); void banNick(const QString & nick, const QString & reason, int seconds); + void roomPasswordEntered(const QString & password); private slots: void ClientRead(); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/res/chat/hedgehogcontributor.png Binary file QTfrontend/res/chat/hedgehogcontributor.png has changed diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/res/chat/hedgehogcontributor_gray.png Binary file QTfrontend/res/chat/hedgehogcontributor_gray.png has changed diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/res/chat/roomadmincontributor.png Binary file QTfrontend/res/chat/roomadmincontributor.png has changed diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/res/chat/roomadmincontributor_gray.png Binary file QTfrontend/res/chat/roomadmincontributor_gray.png has changed diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/res/iconEarth.png Binary file QTfrontend/res/iconEarth.png has changed diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/team.cpp --- a/QTfrontend/team.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/team.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -261,7 +261,7 @@ return true; } -QStringList HWTeam::teamGameConfig(quint32 InitHealth, GameUIConfig * config) const +QStringList HWTeam::teamGameConfig(quint32 InitHealth) const { QStringList sl; if (m_isNetTeam) diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/team.h --- a/QTfrontend/team.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/team.h Mon Oct 28 14:07:04 2013 +0100 @@ -93,7 +93,7 @@ void incWins(); // convert team info into strings for further computation - QStringList teamGameConfig(quint32 InitHealth, GameUIConfig * config) const; + QStringList teamGameConfig(quint32 InitHealth) const; // comparison operators bool operator == (const HWTeam& t1) const; diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/mouseoverfilter.cpp --- a/QTfrontend/ui/mouseoverfilter.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/mouseoverfilter.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -49,8 +49,6 @@ { SDLInteraction::instance().playSoundFile("/Sounds/steps.ogg"); } - - return true; } else if (event->type() == QEvent::Leave) { @@ -63,7 +61,6 @@ else abstractpage->setButtonDescription(""); } - return false; } diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pagedrawmap.cpp --- a/QTfrontend/ui/page/pagedrawmap.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pagedrawmap.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -20,6 +20,7 @@ #include #include #include +#include #include "pagedrawmap.h" #include "drawmapwidget.h" @@ -32,12 +33,22 @@ cbEraser = new QCheckBox(tr("Eraser"), this); pageLayout->addWidget(cbEraser, 0, 0); pbUndo = addButton(tr("Undo"), pageLayout, 1, 0); - pbClear = addButton(tr("Clear"), pageLayout, 2, 0); - pbLoad = addButton(tr("Load"), pageLayout, 3, 0); - pbSave = addButton(tr("Save"), pageLayout, 4, 0); + + rbPolyline = new QRadioButton(tr("Polyline"), this); + pageLayout->addWidget(rbPolyline, 2, 0); + rbRectangle = new QRadioButton(tr("Rectangle"), this); + pageLayout->addWidget(rbRectangle, 3, 0); + rbEllipse = new QRadioButton(tr("Ellipse"), this); + pageLayout->addWidget(rbEllipse, 4, 0); + + rbPolyline->setChecked(true); + + pbClear = addButton(tr("Clear"), pageLayout, 5, 0); + pbLoad = addButton(tr("Load"), pageLayout, 6, 0); + pbSave = addButton(tr("Save"), pageLayout, 7, 0); drawMapWidget = new DrawMapWidget(this); - pageLayout->addWidget(drawMapWidget, 0, 1, 6, 1); + pageLayout->addWidget(drawMapWidget, 0, 1, 9, 1); return pageLayout; } @@ -49,6 +60,10 @@ connect(pbClear, SIGNAL(clicked()), drawMapWidget, SLOT(clear())); connect(pbLoad, SIGNAL(clicked()), this, SLOT(load())); connect(pbSave, SIGNAL(clicked()), this, SLOT(save())); + + connect(rbPolyline, SIGNAL(toggled(bool)), this, SLOT(pathTypeSwitched(bool))); + connect(rbRectangle, SIGNAL(toggled(bool)), this, SLOT(pathTypeSwitched(bool))); + connect(rbEllipse, SIGNAL(toggled(bool)), this, SLOT(pathTypeSwitched(bool))); } PageDrawMap::PageDrawMap(QWidget* parent) : AbstractPage(parent) @@ -71,3 +86,13 @@ if(!fileName.isEmpty()) drawMapWidget->save(fileName); } + +void PageDrawMap::pathTypeSwitched(bool b) +{ + if(b) + { + if(rbPolyline->isChecked()) drawMapWidget->setPathType(DrawMapScene::Polyline); + else if(rbRectangle->isChecked()) drawMapWidget->setPathType(DrawMapScene::Rectangle); + else if(rbEllipse->isChecked()) drawMapWidget->setPathType(DrawMapScene::Ellipse); + } +} diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pagedrawmap.h --- a/QTfrontend/ui/page/pagedrawmap.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pagedrawmap.h Mon Oct 28 14:07:04 2013 +0100 @@ -22,6 +22,7 @@ #include "AbstractPage.h" class DrawMapWidget; +class QRadioButton; class PageDrawMap : public AbstractPage { @@ -42,10 +43,14 @@ QPushButton * pbLoad; QPushButton * pbSave; QCheckBox * cbEraser; + QRadioButton * rbPolyline; + QRadioButton * rbRectangle; + QRadioButton * rbEllipse; private slots: void load(); void save(); + void pathTypeSwitched(bool b); }; #endif diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pageeditteam.cpp --- a/QTfrontend/ui/page/pageeditteam.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pageeditteam.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -203,12 +203,18 @@ { initPage(); - QRegExp pngSuffix("\\.png$"); + m_playerHash = "0000000000000000000000000000000000000000"; + m_loaded = false; +} - m_playerHash = "0000000000000000000000000000000000000000"; +void PageEditTeam::lazyLoad() +{ + if(m_loaded) return; + m_loaded = true; + qDebug("[LAZYNESS] PageEditTeam::lazyLoad()"); + QRegExp pngSuffix("\\.png$"); DataManager & dataMgr = DataManager::instance(); - QStringList list; @@ -236,7 +242,7 @@ pix = pix.copy(0, 0, 32, 32); QIcon icon(pix); - QString grave = QString(file).remove(pngSuffix); + QString grave = file.remove(pngSuffix); CBGrave->addItem(icon, grave); } @@ -327,6 +333,8 @@ void PageEditTeam::createTeam(const QString & name, const QString & playerHash) { m_playerHash = playerHash; + lazyLoad(); + HWTeam newTeam(name); loadTeam(newTeam); } @@ -334,6 +342,8 @@ void PageEditTeam::editTeam(const QString & name, const QString & playerHash) { m_playerHash = playerHash; + lazyLoad(); + HWTeam team(name); team.loadFromFile(); loadTeam(team); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pageeditteam.h --- a/QTfrontend/ui/page/pageeditteam.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pageeditteam.h Mon Oct 28 14:07:04 2013 +0100 @@ -66,6 +66,7 @@ HWTeam data(); QString m_playerHash; KeyBinder * binder; + bool m_loaded; QLayout * bodyLayoutDefinition(); QLayout * footerLayoutDefinition(); @@ -78,6 +79,8 @@ QPushButton * btnRandomTeam; QPushButton * btnTestSound; + void lazyLoad(); + private slots: void saveTeam(); void setRandomNames(); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pageroomslist.cpp --- a/QTfrontend/ui/page/pageroomslist.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pageroomslist.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -531,17 +531,17 @@ void PageRoomsList::onCreateClick() { - RoomNamePrompt prompt(parentWidget()->parentWidget(), m_gameSettings->value("frontend/lastroomname", QString()).toString()); - connect(&prompt, SIGNAL(roomNameChosen(const QString &)), this, SLOT(onRoomNameChosen(const QString &))); - prompt.exec(); + RoomNamePrompt prompt(this, m_gameSettings->value("frontend/lastroomname", QString()).toString()); + if(prompt.exec()) + onRoomNameChosen(prompt.getRoomName(), prompt.getPassword()); } -void PageRoomsList::onRoomNameChosen(const QString & roomName) +void PageRoomsList::onRoomNameChosen(const QString & roomName, const QString & password) { if (!roomName.trimmed().isEmpty()) { m_gameSettings->setValue("frontend/lastroomname", roomName); - emit askForCreateRoom(roomName); + emit askForCreateRoom(roomName, password); } else { @@ -570,7 +570,7 @@ if (!gameInLobby) emit askJoinConfirmation(roomName); else - emit askForJoinRoom(roomName); + emit askForJoinRoom(roomName, QString()); } void PageRoomsList::onRefreshClick() @@ -600,7 +600,7 @@ if (reallyJoinMsg.exec() == QMessageBox::Ok) { - emit askForJoinRoom(room); + emit askForJoinRoom(room, QString()); } } diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pageroomslist.h --- a/QTfrontend/ui/page/pageroomslist.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pageroomslist.h Mon Oct 28 14:07:04 2013 +0100 @@ -70,8 +70,8 @@ void updateNickCounter(int cnt); signals: - void askForCreateRoom(const QString &); - void askForJoinRoom(const QString &); + void askForCreateRoom(const QString &, const QString &); + void askForJoinRoom(const QString &, const QString &); void askForRoomList(); void askJoinConfirmation(const QString &); @@ -89,7 +89,7 @@ void onSortIndicatorChanged(int logicalIndex, Qt::SortOrder order); void onFilterChanged(); void saveHeaderState(); - void onRoomNameChosen(const QString &); + void onRoomNameChosen(const QString &, const QString &password); void roomSelectionChanged(const QModelIndex &, const QModelIndex &); void moveSelectionUp(); void moveSelectionDown(); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pagescheme.cpp --- a/QTfrontend/ui/page/pagescheme.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pagescheme.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -383,6 +383,23 @@ glBSLayout->addWidget(SB_GetAwayTime,14,2,1,1); l = new QLabel(gbBasicSettings); + l->setText(QLabel::tr("World Edge")); + l->setWordWrap(true); + glBSLayout->addWidget(l,15,0,1,1); + l = new QLabel(gbBasicSettings); + l->setFixedSize(32,32); + l->setPixmap(QPixmap(":/res/iconEarth.png")); + glBSLayout->addWidget(l,15,1,1,1); + CB_WorldEdge = new QComboBox(gbBasicSettings); + CB_WorldEdge->insertItem(0, tr("None (Default)")); + CB_WorldEdge->insertItem(1, tr("Wrap (World wraps)")); + CB_WorldEdge->insertItem(2, tr("Bounce (Edges reflect)")); + CB_WorldEdge->insertItem(3, tr("Sea (Edges connect to sea)")); + /* CB_WorldEdge->insertItem(4, tr("Skybox")); */ + glBSLayout->addWidget(CB_WorldEdge,15,2,1,1); + + + l = new QLabel(gbBasicSettings); l->setText(QLabel::tr("Scheme Name:")); LE_name = new QLineEdit(this); @@ -471,6 +488,7 @@ mapper->addMapping(SB_HealthDecrease, 38); mapper->addMapping(SB_RopeModifier, 39); mapper->addMapping(SB_GetAwayTime, 40); + mapper->addMapping(CB_WorldEdge, 41, "currentIndex"); mapper->toFirst(); } diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/page/pagescheme.h --- a/QTfrontend/ui/page/pagescheme.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/page/pagescheme.h Mon Oct 28 14:07:04 2013 +0100 @@ -91,6 +91,7 @@ QSpinBox * SB_Explosives; QSpinBox * SB_RopeModifier; QSpinBox * SB_GetAwayTime; + QComboBox * CB_WorldEdge; QLineEdit * LE_name; QGroupBox * gbGameModes; diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/chatwidget.cpp --- a/QTfrontend/ui/widget/chatwidget.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/chatwidget.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -930,3 +930,17 @@ chatText->verticalScrollBar()->setValue(m_scrollBarPos); } } + +void HWChatWidget::resizeEvent(QResizeEvent * event) +{ + Q_UNUSED(event); + + afterContentAdd(); +} + +void HWChatWidget::showEvent(QShowEvent * event) +{ + Q_UNUSED(event); + + afterContentAdd(); +} diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/chatwidget.h --- a/QTfrontend/ui/widget/chatwidget.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/chatwidget.h Mon Oct 28 14:07:04 2013 +0100 @@ -68,6 +68,8 @@ protected: virtual void dragEnterEvent(QDragEnterEvent * event); virtual void dropEvent(QDropEvent * event); + virtual void resizeEvent(QResizeEvent * event); + virtual void showEvent(QShowEvent * event); private: static QString * s_styleSheet; diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/drawmapwidget.cpp --- a/QTfrontend/ui/widget/drawmapwidget.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/drawmapwidget.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -123,6 +123,11 @@ if(m_scene) m_scene->setErasing(erasing); } +void DrawMapWidget::setPathType(DrawMapScene::PathType pathType) +{ + if(m_scene) m_scene->setPathType(pathType); +} + void DrawMapWidget::save(const QString & fileName) { if(m_scene) @@ -160,6 +165,7 @@ } else m_scene->decode(qUncompress(QByteArray::fromBase64(f.readAll()))); + //m_scene->decode(f.readAll()); } } @@ -191,7 +197,7 @@ QGraphicsView::setScene(scene); } -// Why don't I ever recieve this event? +// Why don't I ever receive this event? void DrawMapView::enterEvent(QEvent *event) { if(m_scene) diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/drawmapwidget.h --- a/QTfrontend/ui/widget/drawmapwidget.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/drawmapwidget.h Mon Oct 28 14:07:04 2013 +0100 @@ -100,6 +100,7 @@ void setErasing(bool erasing); void save(const QString & fileName); void load(const QString & fileName); + void setPathType(DrawMapScene::PathType pathType); protected: void changeEvent(QEvent *e); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/gamecfgwidget.cpp --- a/QTfrontend/ui/widget/gamecfgwidget.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/gamecfgwidget.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -321,6 +321,7 @@ bcfg << QString("e$healthdec %1").arg(schemeData(38).toInt()).toUtf8(); bcfg << QString("e$ropepct %1").arg(schemeData(39).toInt()).toUtf8(); bcfg << QString("e$getawaytime %1").arg(schemeData(40).toInt()).toUtf8(); + bcfg << QString("e$worldedge %1").arg(schemeData(41).toInt()).toUtf8(); bcfg << QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()).toUtf8(); bcfg << QString("e$mapgen %1").arg(mapgen).toUtf8(); diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/roomnameprompt.cpp --- a/QTfrontend/ui/widget/roomnameprompt.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/roomnameprompt.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -23,6 +23,7 @@ #include #include #include +#include #include "roomnameprompt.h" @@ -32,24 +33,34 @@ setWindowFlags(Qt::Sheet); setWindowModality(Qt::WindowModal); setMinimumSize(360, 130); - resize(360, 130); + resize(360, 180); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); // Layout QVBoxLayout * dialogLayout = new QVBoxLayout(this); // Label - label = new QLabel(tr("Enter a name for your room.")); + label = new QLabel(tr("Enter a name for your room."), this); label->setWordWrap(true); - dialogLayout->addWidget(label, 0); + dialogLayout->addWidget(label); // Input box - editBox = new QLineEdit(); - editBox->setText(roomName); - editBox->setMaxLength(59); // It didn't like 60 :( - editBox->setStyleSheet("QLineEdit { padding: 3px; }"); - editBox->selectAll(); - dialogLayout->addWidget(editBox, 1); + leRoomName = new QLineEdit(this); + leRoomName->setText(roomName); + leRoomName->setMaxLength(59); // It didn't like 60 :( + leRoomName->setStyleSheet("QLineEdit { padding: 3px; }"); + leRoomName->selectAll(); + dialogLayout->addWidget(leRoomName); + + cbSetPassword = new QCheckBox(this); + cbSetPassword->setText(tr("set password")); + dialogLayout->addWidget(cbSetPassword); + + lePassword = new QLineEdit(this); + lePassword->setMaxLength(30); + lePassword->setStyleSheet("QLineEdit { padding: 3px; }"); + lePassword->setEnabled(false); + dialogLayout->addWidget(lePassword); dialogLayout->addStretch(1); @@ -73,10 +84,20 @@ setStyleSheet("QPushButton { padding: 5px; }"); - connect(btnOkay, SIGNAL(clicked()), this, SLOT(setRoomName())); + connect(cbSetPassword, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled())); +} + +QString RoomNamePrompt::getRoomName() +{ + return leRoomName->text(); } -void RoomNamePrompt::setRoomName() +QString RoomNamePrompt::getPassword() { - emit roomNameChosen(editBox->text()); + return lePassword->text(); } + +void RoomNamePrompt::checkBoxToggled() +{ + lePassword->setEnabled(cbSetPassword->isChecked()); +} diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/roomnameprompt.h --- a/QTfrontend/ui/widget/roomnameprompt.h Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/roomnameprompt.h Mon Oct 28 14:07:04 2013 +0100 @@ -23,6 +23,7 @@ class QLineEdit; class QLabel; +class QCheckBox; class RoomNamePrompt : public QDialog { @@ -30,16 +31,17 @@ public: RoomNamePrompt(QWidget* parent, const QString & roomName); + QString getRoomName(); + QString getPassword(); - signals: - void roomNameChosen(const QString & roomName); + private: + QLineEdit * leRoomName; + QLabel * label; + QCheckBox * cbSetPassword; + QLineEdit * lePassword; private slots: - void setRoomName(); - - private: - QLineEdit * editBox; - QLabel * label; + void checkBoxToggled(); }; #endif // ROOMNAMEPROMPT_H diff -r 7588daa8d28f -r 3a3defce1b28 QTfrontend/ui/widget/teamselhelper.cpp --- a/QTfrontend/ui/widget/teamselhelper.cpp Wed Sep 25 05:42:16 2013 +0300 +++ b/QTfrontend/ui/widget/teamselhelper.cpp Mon Oct 28 14:07:04 2013 +0100 @@ -55,7 +55,7 @@ butt = new QPushButton(difficultyIcon, team.name().replace("&","&&"), this); butt->setFlat(true); - butt->setWhatsThis(tr("%1's team").arg(team.owner())); + butt->setToolTip(team.owner()); mainLayout.addWidget(butt); butt->setStyleSheet("QPushButton{" "icon-size: 48px;" diff -r 7588daa8d28f -r 3a3defce1b28 cmake_modules/CMakeDeterminePascalCompiler.cmake --- a/cmake_modules/CMakeDeterminePascalCompiler.cmake Wed Sep 25 05:42:16 2013 +0300 +++ b/cmake_modules/CMakeDeterminePascalCompiler.cmake Mon Oct 28 14:07:04 2013 +0100 @@ -5,6 +5,9 @@ # the cmake variable CMAKE_GENERATOR_PASCAL which can be defined by a generator # as a default compiler +# NOTE: on Darwin cmake >= 2.8.11 until cmake <= 2.8.12.1 will add an incompatible +# -F flag to so you won't be able to use those versions with this script + if(NOT CMAKE_Pascal_COMPILER) # prefer the environment variable FPC if($ENV{FPC} MATCHES ".+") diff -r 7588daa8d28f -r 3a3defce1b28 cmake_modules/CMakePascalInformation.cmake --- a/cmake_modules/CMakePascalInformation.cmake Wed Sep 25 05:42:16 2013 +0300 +++ b/cmake_modules/CMakePascalInformation.cmake Mon Oct 28 14:07:04 2013 +0100 @@ -2,6 +2,7 @@ # It also loads the available platform file for the system-compiler # if it exists. +# in case fpc ever becomes included in cmake get_filename_component(CMAKE_BASE_NAME ${CMAKE_Pascal_COMPILER} NAME_WE) set(CMAKE_SYSTEM_AND_Pascal_COMPILER_INFO_FILE ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) @@ -33,17 +34,18 @@ # No flags supported during linking as a shell script takes care of it # however to avoid interferences we escape -Wl flags to the Pascal -k -if(NOT CMAKE_SHARED_LIBRARY_CREATE_Pascal_FLAGS) -#-shared - string(REGEX REPLACE "-Wl," "-k" CMAKE_SHARED_LIBRARY_CREATE_Pascal_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS}) -endif(NOT CMAKE_SHARED_LIBRARY_CREATE_Pascal_FLAGS) +#if(NOT CMAKE_SHARED_LIBRARY_CREATE_Pascal_FLAGS) +#-shared (linux) / -dynamiclib -Wl,-headerpad_max_install_names (darwin) +# string(REGEX REPLACE "-Wl," "-k" CMAKE_SHARED_LIBRARY_CREATE_Pascal_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS}) +#endif(NOT CMAKE_SHARED_LIBRARY_CREATE_Pascal_FLAGS) if(NOT CMAKE_SHARED_LIBRARY_Pascal_FLAGS AND CMAKE_SHARED_LIBRARY_C_FLAGS) +#-fPIC string(REGEX REPLACE "-Wl," "-k" CMAKE_SHARED_LIBRARY_Pascal_FLAGS ${CMAKE_SHARED_LIBRARY_C_FLAGS}) endif() if(NOT CMAKE_SHARED_LIBRARY_LINK_Pascal_FLAGS AND CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) -#-rdynamic +#-rdynamic (linux) / (empty on darwin) string(REGEX REPLACE "-Wl," "-k" CMAKE_SHARED_LIBRARY_LINK_Pascal_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS}) endif() @@ -70,9 +72,10 @@ endif(NOT CMAKE_MODULE_EXISTS) # repeat for modules -if(NOT CMAKE_SHARED_MODULE_CREATE_Pascal_FLAGS) +if(NOT CMAKE_SHARED_MODULE_CREATE_Pascal_FLAGS AND CMAKE_SHARED_MODULE_CREATE_C_FLAGS) +# ? (linux) / -bundle -Wl,-headerpad_max_install_names (darwin) string(REGEX REPLACE "-Wl," "-k" CMAKE_SHARED_MODULE_CREATE_Pascal_FLAGS ${CMAKE_SHARED_MODULE_CREATE_C_FLAGS}) -endif(NOT CMAKE_SHARED_MODULE_CREATE_Pascal_FLAGS) +endif() if(NOT CMAKE_SHARED_MODULE_Pascal_FLAGS AND CMAKE_SHARED_MODULE_C_FLAGS) string(REGEX REPLACE "-Wl," "-k" CMAKE_SHARED_MODULE_Pascal_FLAGS ${CMAKE_SHARED_MODULE_C_FLAGS}) @@ -86,6 +89,7 @@ set(CMAKE_SHARED_MODULE_RUNTIME_Pascal_FLAG_SEP ${CMAKE_SHARED_MODULE_RUNTIME_C_FLAG_SEP}) endif(NOT CMAKE_SHARED_MODULE_RUNTIME_Pascal_FLAG_SEP) +# now other system things if(NOT CMAKE_INCLUDE_FLAG_Pascal) #amazing, fpc: -I Add to include path set(CMAKE_INCLUDE_FLAG_Pascal ${CMAKE_INCLUDE_FLAG_C}) @@ -95,8 +99,14 @@ set(CMAKE_INCLUDE_FLAG_SEP_Pascal ${CMAKE_INCLUDE_FLAG_SEP_C}) endif(NOT CMAKE_INCLUDE_FLAG_SEP_Pascal) +if(NOT CMAKE_Pascal_FRAMEWORK_SEARCH_FLAG) + #however -F won't work, -Ff is Pascal equivalent + set(CMAKE_Pascal_FRAMEWORK_SEARCH_FLAG "-Ff") +endif(NOT CMAKE_Pascal_FRAMEWORK_SEARCH_FLAG) + # Copy C version of this flag which is normally determined in platform file. if(NOT CMAKE_SHARED_LIBRARY_SONAME_Pascal_FLAG) +#-soname (linux) / -install-name (dawin) set(CMAKE_SHARED_LIBRARY_SONAME_Pascal_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_C_FLAG}) endif(NOT CMAKE_SHARED_LIBRARY_SONAME_Pascal_FLAG) diff -r 7588daa8d28f -r 3a3defce1b28 cmake_modules/platform.cmake --- a/cmake_modules/platform.cmake Wed Sep 25 05:42:16 2013 +0300 +++ b/cmake_modules/platform.cmake Mon Oct 28 14:07:04 2013 +0100 @@ -1,5 +1,10 @@ if(APPLE) + if(${CMAKE_VERSION} VERSION_GREATER "2.8.10.2" AND + ${CMAKE_VERSION} VERSION_LESS "2.8.12.1") + message(FATAL_ERROR "This version of CMake is known *not* to work, please update or use a lower version") + endif() + set(CMAKE_FIND_FRAMEWORK "FIRST") #what system are we building for diff -r 7588daa8d28f -r 3a3defce1b28 gameServer/Actions.hs --- a/gameServer/Actions.hs Wed Sep 25 05:42:16 2013 +0300 +++ b/gameServer/Actions.hs Mon Oct 28 14:07:04 2013 +0100 @@ -456,6 +456,7 @@ processAction JoinLobby = do chan <- client's sendChan + rnc <- gets roomsClients clientNick <- client's nick isAuthenticated <- liftM (not . B.null) $ client's webPassword isAdmin <- client's isAdministrator @@ -465,6 +466,10 @@ let authenticatedNicks = L.map nick . L.filter (not . B.null . webPassword) $ loggedInClients let adminsNicks = L.map nick . L.filter isAdministrator $ loggedInClients let contrNicks = L.map nick . L.filter isContributor $ loggedInClients + inRoomNicks <- io $ + allClientsM rnc + >>= filterM (liftM ((/=) lobbyId) . clientRoomM rnc) + >>= mapM (client'sM rnc nick) let clFlags = B.concat . L.concat $ [["u" | isAuthenticated], ["a" | isAdmin], ["c" | isContr]] mapM_ processAction . concat $ [ [AnswerClients clientsChans ["LOBBY:JOINED", clientNick]] @@ -472,6 +477,7 @@ , [AnswerClients [chan] ("CLIENT_FLAGS" : "+u" : authenticatedNicks) | not $ null authenticatedNicks] , [AnswerClients [chan] ("CLIENT_FLAGS" : "+a" : adminsNicks) | not $ null adminsNicks] , [AnswerClients [chan] ("CLIENT_FLAGS" : "+c" : contrNicks) | not $ null contrNicks] + , [AnswerClients [chan] ("CLIENT_FLAGS" : "+i" : inRoomNicks) | not $ null inRoomNicks] , [AnswerClients (chan : clientsChans) ["CLIENT_FLAGS", B.concat["+" , clFlags], clientNick] | not $ B.null clFlags] , [ModifyClient (\cl -> cl{logonPassed = True, isVisible = True})] , [SendServerMessage] diff -r 7588daa8d28f -r 3a3defce1b28 gameServer/CoreTypes.hs --- a/gameServer/CoreTypes.hs Wed Sep 25 05:42:16 2013 +0300 +++ b/gameServer/CoreTypes.hs Mon Oct 28 14:07:04 2013 +0100 @@ -101,7 +101,6 @@ logonPassed :: Bool, isVisible :: Bool, clientProto :: !Word16, - roomID :: RoomIndex, pingsQueue :: !Word, isMaster :: Bool, isReady :: !Bool, diff -r 7588daa8d28f -r 3a3defce1b28 gameServer/NetRoutines.hs --- a/gameServer/NetRoutines.hs Wed Sep 25 05:42:16 2013 +0300 +++ b/gameServer/NetRoutines.hs Mon Oct 28 14:07:04 2013 +0100 @@ -36,7 +36,6 @@ False False 0 - lobbyId 0 False False diff -r 7588daa8d28f -r 3a3defce1b28 gameServer/OfficialServer/checker.hs --- a/gameServer/OfficialServer/checker.hs Wed Sep 25 05:42:16 2013 +0300 +++ b/gameServer/OfficialServer/checker.hs Mon Oct 28 14:07:04 2013 +0100 @@ -171,7 +171,7 @@ Right (login, password) <- runErrorT $ do d <- liftIO $ getHomeDirectory - conf <- join . liftIO . CF.readfile CF.emptyCP $ d ++ "/.hedgewars/hedgewars.ini" + conf <- join . liftIO . CF.readfile CF.emptyCP $ d ++ "/.hedgewars/settings.ini" l <- CF.get conf "net" "nick" p <- CF.get conf "net" "passwordhash" return (B.pack l, B.pack p) diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/hwengine.pas Mon Oct 28 14:07:04 2013 +0100 @@ -32,7 +32,7 @@ uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler , uSound, uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uAILandMarks, uLandTexture, uCollisions , SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted - , uPhysFSLayer, uCursor, uRandom, ArgParsers, uVisualGearsHandlers + , uPhysFSLayer, uCursor, uRandom, ArgParsers, uVisualGearsHandlers, uTextures {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}, uTouch {$ENDIF} {$IFDEF ANDROID}, GLUnit{$ENDIF} @@ -441,9 +441,10 @@ if complete then begin uPhysFSLayer.initModule; + uTextures.initModule; {$IFDEF ANDROID}GLUnit.initModule;{$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}uTouch.initModule;{$ENDIF} -{$IFDEF USE_VIDEO_RECORDING}uVideoRec.initModule;{$ENDIF} //stub +{$IFDEF USE_VIDEO_RECORDING}uVideoRec.initModule;{$ENDIF} uAI.initModule; uAIMisc.initModule; uAILandMarks.initModule; //stub @@ -453,7 +454,7 @@ uChat.initModule; uCollisions.initModule; uGears.initModule; - uInputHandler.initModule; //stub + uInputHandler.initModule; uMisc.initModule; uLandTexture.initModule; //stub uScript.initModule; @@ -493,6 +494,7 @@ {$IFDEF USE_VIDEO_RECORDING}uVideoRec.freeModule;{$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}uTouch.freeModule;{$ENDIF} //stub {$IFDEF ANDROID}GLUnit.freeModule;{$ENDIF} + uTextures.freeModule; uPhysFSLayer.freeModule; end; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uAI.pas --- a/hedgewars/uAI.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uAI.pas Mon Oct 28 14:07:04 2013 +0100 @@ -106,7 +106,7 @@ procedure TestAmmos(var Actions: TActions; Me: PGear; rareChecks: boolean); var BotLevel: Byte; ap: TAttackParams; - Score, i, dAngle: LongInt; + Score, i, t, n, dAngle: LongInt; a, aa: TAmmoType; begin BotLevel:= Me^.Hedgehog^.BotLevel; @@ -182,7 +182,15 @@ end else if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then begin + if (AmmoTests[a].flags and amtest_MultipleAttacks) = 0 then + n:= 1 else n:= ap.AttacksNum; + AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0); + for t:= 2 to n do + begin + AddAction(BestActions, aia_attack, aim_push, 150, 0, 0); + AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0); + end; AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0); end; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uAIAmmoTests.pas Mon Oct 28 14:07:04 2013 +0100 @@ -22,13 +22,14 @@ interface uses uConsts, uFloat, uTypes, uAIMisc; const - amtest_Rare = $00000001; // check only several positions - amtest_NoTarget = $00000002; // each pos, but no targetting + amtest_Rare = $00000001; // check only several positions + amtest_NoTarget = $00000002; // each pos, but no targetting + amtest_MultipleAttacks = $00000004; // test could result in multiple attacks, set AttacksNum var windSpeed: real; type TAttackParams = record - Time: Longword; + Time, AttacksNum: Longword; Angle, Power: LongInt; ExplX, ExplY, ExplR: LongInt; AttackPutX, AttackPutY: LongInt; @@ -72,7 +73,7 @@ (proc: nil; flags: 0), // amSkip (proc: nil; flags: 0), // amRope (proc: nil; flags: 0), // amMine - (proc: @TestDesertEagle; flags: 0), // amDEagle + (proc: @TestDesertEagle; flags: amtest_MultipleAttacks), // amDEagle (proc: nil; flags: 0), // amDynamite (proc: @TestFirePunch; flags: amtest_NoTarget), // amFirePunch (proc: @TestWhip; flags: amtest_NoTarget), // amWhip @@ -715,8 +716,13 @@ or (d > 48); if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5 then - valueResult:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, 7, 20, vX*0.125, vY*0.125, afTrackFall) -else valueResult:= BadTurn; + begin + ap.AttacksNum:= 1 + (d + 8) div 12; + valueResult:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, 7, 20, vX*0.125, vY*0.125, afTrackFall) - ap.AttacksNum + end +else + valueResult:= BadTurn; + TestDesertEagle:= valueResult end; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uChat.pas --- a/hedgewars/uChat.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uChat.pas Mon Oct 28 14:07:04 2013 +0100 @@ -41,7 +41,7 @@ Width: LongInt; s: shortstring; end; - TChatCmd = (quit, pause, finish, fullscreen); + TChatCmd = (quit, pause, finish, showhistory, fullscreen); var Strs: array[0 .. MaxStrIndex] of TChatLine; MStrs: array[0 .. MaxStrIndex] of shortstring; @@ -73,6 +73,7 @@ (ChatCmd: '/quit'; ProcedureCallChatCmd: 'halt'), (ChatCmd: '/pause'; ProcedureCallChatCmd: 'pause'), (ChatCmd: '/finish'; ProcedureCallChatCmd: 'finish'), + (ChatCmd: '/history'; ProcedureCallChatCmd: 'history'), (ChatCmd: '/fullscreen'; ProcedureCallChatCmd: 'fullscr') ); diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uCommandHandlers.pas Mon Oct 28 14:07:04 2013 +0100 @@ -797,6 +797,11 @@ CampaignVariable := s; end; +procedure chWorldEdge(var s: shortstring); +begin +WorldEdge:= TWorldEdge(StrToInt(s)) +end; + procedure initModule; begin //////// Begin top sorted by freq analysis not including chatmsg @@ -882,6 +887,7 @@ RegisterVariable('-cur_r' , @chCurR_m , true ); RegisterVariable('campvar' , @chCampVar , true ); RegisterVariable('record' , @chRecord , true ); + RegisterVariable('worldedge',@chWorldEdge , false); end; procedure freeModule; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uConsts.pas Mon Oct 28 14:07:04 2013 +0100 @@ -250,6 +250,8 @@ ammoprop_NeedTarget = $00000004; ammoprop_ForwMsgs = $00000008; ammoprop_AttackInMove = $00000010; + ammoprop_DoesntStopTimerWhileAttacking + = $00000020; ammoprop_NoCrosshair = $00000040; ammoprop_AttackingPut = $00000080; ammoprop_DontHold = $00000100; @@ -263,6 +265,8 @@ ammoprop_OscAim = $00010000; ammoprop_NoMoveAfter = $00020000; ammoprop_Track = $00040000; + ammoprop_DoesntStopTimerInMultiShoot + = $00080000; ammoprop_NoRoundEnd = $10000000; AMMO_INFINITE = 100; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uGears.pas --- a/hedgewars/uGears.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uGears.pas Mon Oct 28 14:07:04 2013 +0100 @@ -401,7 +401,8 @@ if (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.State and gstAttacked = 0) and (CurAmmoGear = nil) then SweepDirty; - CheckNoDamage; + if (CurrentHedgehog^.Gear = nil) or (CurrentHedgehog^.Gear^.State and gstHHDriven = 0) or (CurrentHedgehog^.Gear^.Damage = 0) then + CheckNoDamage; AliveCount:= 0; // shorter version of check for win to allow typical step activity to proceed for i:= 0 to Pred(ClansCount) do if ClansArray[i]^.ClanHealth > 0 then @@ -419,8 +420,10 @@ if TurnTimeLeft > 0 then if CurrentHedgehog^.Gear <> nil then - if ((CurrentHedgehog^.Gear^.State and gstAttacking) = 0) and - not(isInMultiShoot and (CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle])) then + if (((CurrentHedgehog^.Gear^.State and gstAttacking) = 0) + or (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerWhileAttacking <> 0)) + and not(isInMultiShoot and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerInMultiShoot) <> 0)) then + //(CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle]) begin if (TurnTimeLeft = 5000) and (cHedgehogTurnTime >= 10000) diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uGearsHandlersMess.pas --- a/hedgewars/uGearsHandlersMess.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uGearsHandlersMess.pas Mon Oct 28 14:07:04 2013 +0100 @@ -280,10 +280,18 @@ var isFalling: boolean; //tmp: QWord; - tdX, tdY: hwFloat; + tX, tdX, tdY: hwFloat; collV, collH: LongInt; land: word; begin + tX:= Gear^.X; + if (Gear^.Kind <> gtGenericFaller) and WorldWrap(Gear) and (WorldEdge = weWrap) and (Gear^.AdvBounce <> 0) and + (TestCollisionXwithGear(Gear, 1) or TestCollisionXwithGear(Gear, -1)) then + begin + Gear^.X:= tX; + Gear^.dX.isNegative:= (hwRound(tX) > leftX+Gear^.Radius*2) + end; + // clip velocity at 2 - over 1 per pixel, but really shouldn't cause many actual problems. if Gear^.dX.Round > 2 then Gear^.dX.QWordValue:= 8589934592; @@ -302,8 +310,6 @@ tdX := Gear^.dX; tdY := Gear^.dY; - - // might need some testing/adjustments - just to avoid projectiles to fly forever (accelerated by wind/skips) if (hwRound(Gear^.X) < min(LAND_WIDTH div -2, -2048)) or (hwRound(Gear^.X) > max(LAND_WIDTH * 3 div 2, 6144)) then @@ -384,8 +390,7 @@ Gear^.X := Gear^.X + Gear^.dX; Gear^.Y := Gear^.Y + Gear^.dY; - if Gear^.Kind <> gtBee then - CheckGearDrowning(Gear); + CheckGearDrowning(Gear); //if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _0_0002) and if (not isFalling) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_02.QWordValue) then Gear^.State := Gear^.State and (not gstMoving) @@ -695,6 +700,13 @@ draw:= true; xx:= hwRound(Gear^.X); yy:= hwRound(Gear^.Y); + if draw and (WorldEdge = weWrap) and ((xx < leftX+3) or (xx > rightX-3)) then + begin + if xx < leftX+3 then + xx:= rightX-3 + else xx:= leftX+3; + Gear^.X:= int2hwFloat(xx) + end end else if GameTicks and $7 = 0 then begin @@ -889,6 +901,7 @@ flower: PVisualGear; begin + WorldWrap(Gear); AllInactive := false; gX := hwRound(Gear^.X); gY := hwRound(Gear^.Y); @@ -968,6 +981,7 @@ dec(Gear^.Timer) else begin + Gear^.State:= Gear^.State and not gstSubmersible; if nuw then begin StopSoundChan(Gear^.SoundChannel); @@ -1055,6 +1069,7 @@ repeat Gear^.X := Gear^.X + Gear^.dX; Gear^.Y := Gear^.Y + Gear^.dY; + WorldWrap(Gear); CheckCollision(Gear); if (Gear^.State and gstCollision) <> 0 then begin @@ -1120,7 +1135,7 @@ procedure doStepBulletWork(Gear: PGear); var i, x, y: LongWord; - oX, oY: hwFloat; + oX, oY, tX, tY, cX, cY: hwFloat; VGear: PVisualGear; begin AllInactive := false; @@ -1131,6 +1146,22 @@ repeat Gear^.X := Gear^.X + Gear^.dX; Gear^.Y := Gear^.Y + Gear^.dY; + tX:= Gear^.X; + tY:= Gear^.Y; + if (Gear^.PortalCounter < 30) and WorldWrap(Gear) then + begin + cX:= Gear^.X; + cY:= Gear^.Y; + Gear^.X:= tX; + Gear^.Y:= tY; + SpawnBulletTrail(Gear); + Gear^.X:= cX; + Gear^.Y:= cY; + inc(Gear^.PortalCounter); + Gear^.Elasticity:= Gear^.X; + Gear^.Friction:= Gear^.Y; + SpawnBulletTrail(Gear); + end; x := hwRound(Gear^.X); y := hwRound(Gear^.Y); @@ -1305,6 +1336,7 @@ HHGear: PGear; begin AllInactive := false; + WorldWrap(Gear); HHGear := Gear^.Hedgehog^.Gear; dec(Gear^.Timer); if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then @@ -1428,6 +1460,7 @@ prevX: LongInt; begin AllInactive := false; + WorldWrap(Gear); dec(Gear^.Timer); if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then dec(TurnTimeLeft); @@ -2013,6 +2046,7 @@ tdX,tdY: HWFloat; landPixel: Word; begin + WorldWrap(Gear); sticky:= (Gear^.State and gsttmpFlag) <> 0; if not sticky then AllInactive := false; @@ -2378,6 +2412,7 @@ var HHGear: PGear; x, y, tx, ty: hwFloat; + rx: LongInt; begin AllInactive := false; @@ -2386,8 +2421,13 @@ ty := int2hwFloat(Gear^.Target.Y); x := HHGear^.X; y := HHGear^.Y; - - if (Distance(tx - x, ty - y) > _256) + rx:= hwRound(x); + + if ((Distance(tx - x, ty - y) > _256) and ((WorldEdge <> weWrap) or + ( + (Distance(tx - int2hwFloat(rightX+(rx-leftX)), ty - y) > _256) and + (Distance(tx - int2hwFloat(leftX-(rightX-rx)), ty - y) > _256) + ))) or (not TryPlaceOnLand(Gear^.Target.X - SpritesData[sprAmGirder].Width div 2, Gear^.Target.Y - SpritesData[sprAmGirder].Height div 2, sprAmGirder, Gear^.State, true, false)) then begin PlaySound(sndDenied); @@ -3187,11 +3227,26 @@ var HHGear: PGear; i: LongInt; - dX, dY: hwFloat; + dX, dY, X, Y : hwFloat; fChanged: boolean; trueAngle: Longword; t: PGear; begin + if WorldWrap(Gear) and (WorldEdge <> weWrap) then + begin + Y.isNegative:= false; + Y.QWordValue:= 4294967296 * 112; + X.isNegative:= false; + X.QWordValue:= 4294967296 * 35; + dX.isNegative:= false; + dX.QWordValue:= 4294967296 * 1152; + + dY:=hwAbs(Gear^.dX*4); + dY:= dY + hwPow(dY,3)/_6 + _3 * hwPow(dY,5) / _40 + _5 * hwPow(dY,7) / Y + X * hwPow(dY,9) / dX; + Gear^.Angle:= hwRound(dY*_2048 / _PI); + if not Gear^.dY.isNegative then Gear^.Angle:= 2048-Gear^.Angle; + if Gear^.dX.isNegative then Gear^.Angle:= 4096-Gear^.Angle; + end; AllInactive := false; HHGear := Gear^.Hedgehog^.Gear; @@ -3201,7 +3256,7 @@ dec(Gear^.Timer); fChanged := false; - if ((HHGear^.State and gstHHDriven) = 0) or (Gear^.Timer = 0) then + if (HHGear = nil) or ((HHGear^.State and gstHHDriven) = 0) or (Gear^.Timer = 0) then begin fChanged := true; if Gear^.Angle > 2048 then @@ -3246,7 +3301,7 @@ else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); - if ((HHGear^.Message and gmAttack) <> 0) and (Gear^.Health <> 0) then + if (HHGear <> nil) and ((HHGear^.Message and gmAttack) <> 0) and (Gear^.Health <> 0) then begin HHGear^.Message := HHGear^.Message and (not gmAttack); AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY * @@ -3254,7 +3309,7 @@ dec(Gear^.Health) end; - if ((HHGear^.Message and gmLJump) <> 0) and ((Gear^.State and gsttmpFlag) = 0) then + if (HHGear <> nil) and ((HHGear^.Message and gmLJump) <> 0) and ((Gear^.State and gsttmpFlag) = 0) then begin Gear^.State := Gear^.State or gsttmpFlag; PauseMusic; @@ -4044,7 +4099,8 @@ if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) - and (CurAmmoGear^.Kind =gtRope) then + and (CurAmmoGear^.Kind = gtRope) + and (CurAmmoGear^.Elasticity <> _0) then CurAmmoGear^.PortalCounter:= 1; if not isbullet and (iterator^.State and gstInvisible = 0) @@ -4097,6 +4153,7 @@ x, y, tx, ty: LongInt; s: hwFloat; begin + WorldWrap(Gear); x := hwRound(Gear^.X); y := hwRound(Gear^.Y); tx := 0; @@ -4637,6 +4694,7 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepPoisonCloud(Gear: PGear); begin + WorldWrap(Gear); if Gear^.Timer = 0 then begin DeleteGear(Gear); @@ -5117,11 +5175,12 @@ begin cnt:= 0; for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do - for i:= 0 to Pred(HH^.Team^.Clan^.Teams[j]^.HedgehogsNumber) do - if (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear <> nil) - and ((HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.State and gstDrowning) = 0) - and (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Health > HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Damage) then - inc(cnt); + with HH^.Team^.Clan^.Teams[j]^ do + for i:= 0 to Pred(HedgehogsNumber) do + if (Hedgehogs[i].Gear <> nil) + and ((Hedgehogs[i].Gear^.State and gstDrowning) = 0) + and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) then + inc(cnt); if (cnt = 0) or SuddenDeathDmg or (Gear^.Timer = 0) then begin if HH^.GearHidden <> nil then diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uGearsHandlersRope.pas --- a/hedgewars/uGearsHandlersRope.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uGearsHandlersRope.pas Mon Oct 28 14:07:04 2013 +0100 @@ -31,8 +31,17 @@ procedure doStepRopeAfterAttack(Gear: PGear); var HHGear: PGear; + tX: hwFloat; begin HHGear := Gear^.Hedgehog^.Gear; + tX:= HHGear^.X; + if WorldWrap(HHGear) and (WorldEdge = weWrap) and + (TestCollisionXwithGear(HHGear, 1) or TestCollisionXwithGear(HHGear, -1)) then + begin + HHGear^.X:= tX; + HHGear^.dX.isNegative:= (hwRound(tX) > leftX+HHGear^.Radius*2) + end; + if (HHGear^.Hedgehog^.CurAmmoType = amParachute) and (HHGear^.dY > _0_39) then begin DeleteGear(Gear); @@ -116,8 +125,20 @@ HHGear := Gear^.Hedgehog^.Gear; - if ((HHGear^.State and gstHHDriven) = 0) - or (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then + tX:= HHGear^.X; + if WorldWrap(HHGear) and (WorldEdge = weWrap) and + (TestCollisionXwithGear(HHGear, 1) or TestCollisionXwithGear(HHGear, -1)) then + begin + PlaySound(sndRopeRelease); + RopeDeleteMe(Gear, HHGear); + HHGear^.X:= tX; + HHGear^.dX.isNegative:= (hwRound(tX) > leftX+HHGear^.Radius*2); + exit + end; + + tX:= HHGear^.X; + if ((HHGear^.State and gstHHDriven) = 0) or + (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then begin PlaySound(sndRopeRelease); RopeDeleteMe(Gear, HHGear); diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uGearsHedgehog.pas Mon Oct 28 14:07:04 2013 +0100 @@ -116,7 +116,7 @@ // Try again in the next slot if CurAmmoType = prevAmmo then begin - if slot >= cMaxSlotIndex then slot:= 0 else inc(slot); + if slot < cMaxSlotIndex then inc(slot); HHGear^.MsgParam:= slot; ChangeAmmo(HHGear) end @@ -848,10 +848,12 @@ if (Gear^.dY.isNegative) and TestCollisionYKick(Gear, -1) then Gear^.dY:= _0; Gear^.State:= Gear^.State or gstMoving; - if (CurrentHedgehog^.Gear = Gear) - and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then + if (CurrentHedgehog^.Gear = Gear) and (CurrentHedgehog^.Gear^.State and gstHHDriven <> 0) and + (not CurrentTeam^.ExtDriven) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then begin // TODO: why so aggressive at setting FollowGear when falling? + // because hog was being yanked out of frame by other stuff when doing a complicated jump/chute/saucer/roping. + // added a couple more conditions to make it a bit less aggressive, at cost of possibly spectator failing to follow a maneuver FollowGear:= Gear; end; if isUnderwater then @@ -1273,7 +1275,21 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepHedgehog(Gear: PGear); +var tX: hwFloat; begin +tX:= Gear^.X; +if WorldWrap(Gear) then + begin + if (WorldEdge <> weBounce) and (Gear = CurrentHedgehog^.Gear) and + (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) and (CurAmmoGear^.Elasticity <> _0) then + CurAmmoGear^.PortalCounter:= 1; + if (WorldEdge = weWrap) and (TestCollisionXwithGear(Gear, 1) or TestCollisionXwithGear(Gear, -1)) then + begin + Gear^.X:= tX; + Gear^.dX.isNegative:= (hwRound(tX) > leftX+Gear^.Radius*2) + end + end; + CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel; if (Gear^.Message and gmDestroy) <> 0 then begin diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uGearsList.pas --- a/hedgewars/uGearsList.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uGearsList.pas Mon Oct 28 14:07:04 2013 +0100 @@ -281,6 +281,7 @@ gear^.RenderTimer:= true; gear^.Elasticity:= _0_9; gear^.Tag:= 0; + gear^.State:= Gear^.State or gstSubmersible end; gtSeduction: begin gear^.Radius:= 250; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uGearsRender.pas Mon Oct 28 14:07:04 2013 +0100 @@ -671,6 +671,25 @@ end; amGirder: begin DrawSpriteRotated(sprHandConstruction, hx, hy, sign, aangle); + if WorldEdge = weWrap then + begin + if hwRound(Gear^.X) < leftX+256 then + DrawSpriteClipped(sprGirder, + rightX+(ox-leftX)-256, + oy-256, + LongInt(topY)+WorldDy, + LongInt(rightX)+WorldDx, + cWaterLine+WorldDy, + LongInt(leftX)+WorldDx); + if hwRound(Gear^.X) > rightX-256 then + DrawSpriteClipped(sprGirder, + leftX-(rightX-ox)-256, + oy-256, + LongInt(topY)+WorldDy, + LongInt(rightX)+WorldDx, + cWaterLine+WorldDy, + LongInt(leftX)+WorldDx) + end; DrawSpriteClipped(sprGirder, ox-256, oy-256, diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uGearsUtils.pas Mon Oct 28 14:07:04 2013 +0100 @@ -53,13 +53,14 @@ function GetAmmo(Hedgehog: PHedgehog): TAmmoType; function GetUtility(Hedgehog: PHedgehog): TAmmoType; +function WorldWrap(var Gear: PGear): boolean; + function MakeHedgehogsStep(Gear: PGear) : boolean; var doStepHandlers: array[TGearType] of TGearStepProcedure; - implementation uses uSound, uCollisions, uUtils, uConsts, uVisualGears, uAIMisc, uVariables, uLandGraphics, uScript, uStats, uCaptions, uTeams, uStore, @@ -486,7 +487,10 @@ CurAmmoGear^.Pos := 1000 end else - CheckGearDrowning := false; + begin + if not (Gear^.Kind in [gtJetpack, gtBee]) then Gear^.State:= Gear^.State and not gstSubmersible; // making it temporary for most gears is more attractive I think + CheckGearDrowning := false + end end; @@ -589,6 +593,11 @@ ignoreNearObjects:= false; // try not skipping proximity at first ignoreOverlap:= false; // this not only skips proximity, but allows overlapping objects (barrels, mines, hogs, crates). Saving it for a 3rd pass. With this active, winning AI Survival goes back to virtual impossibility tryAgain:= true; +if WorldEdge <> weNone then + begin + Left:= max(Left,leftX+Gear^.Radius); + Right:= min(Right,rightX-Gear^.Radius) + end; while tryAgain do begin delta:= LAND_WIDTH div 16; @@ -1198,5 +1207,79 @@ GetUtility:= i end; +(* +Intended to check Gear X/Y against the map left/right edges and apply one of the world modes +* Normal - infinite world, do nothing +* Wrap (entering left edge exits at same height on right edge) +* Bounce (striking edge is treated as a 100% elasticity bounce) +* From the depths (same as from sky, but from sea, with submersible flag set) + +Trying to make the checks a little broader than on first pass to catch things that don't move normally. +*) +function WorldWrap(var Gear: PGear): boolean; +var tdx: hwFloat; +begin +WorldWrap:= false; +if WorldEdge = weNone then exit(false); +if (hwRound(Gear^.X)-Gear^.Radius < leftX) or + (hwRound(Gear^.X)+Gear^.Radius > rightX) then + begin + if WorldEdge = weWrap then + begin + if (hwRound(Gear^.X)-Gear^.Radius < leftX) then + Gear^.X:= int2hwfloat(rightX-Gear^.Radius) + else Gear^.X:= int2hwfloat(leftX+Gear^.Radius); + LeftImpactTimer:= 150; + RightImpactTimer:= 150 + end + else if WorldEdge = weBounce then + begin + if (hwRound(Gear^.X)-Gear^.Radius < leftX) then + begin + LeftImpactTimer:= 333; + Gear^.dX.isNegative:= false; + Gear^.X:= int2hwfloat(leftX+Gear^.Radius) + end + else + begin + RightImpactTimer:= 333; + Gear^.dX.isNegative:= true; + Gear^.X:= int2hwfloat(rightX-Gear^.Radius) + end; + if (Gear^.Radius > 2) and (Gear^.dX.QWordValue > _0_001.QWordValue) then + PlaySound(sndMelonImpact) + end + else if WorldEdge = weSea then + begin + if (hwRound(Gear^.Y) > cWaterLine) and (Gear^.State and gstSubmersible <> 0) then + Gear^.State:= Gear^.State and not gstSubmersible + else + begin + Gear^.State:= Gear^.State or gstSubmersible; + Gear^.X:= int2hwFloat(PlayWidth)*int2hwFloat(min(max(0,hwRound(Gear^.Y)),PlayHeight))/PlayHeight; + Gear^.Y:= int2hwFloat(cWaterLine+cVisibleWater+Gear^.Radius*2); + tdx:= Gear^.dX; + Gear^.dX:= -Gear^.dY; + Gear^.dY:= tdx; + Gear^.dY.isNegative:= true + end + end; +(* +* Window in the sky (Gear moved high into the sky, Y is used to determine X) [unfortunately, not a safe thing to do. shame, I thought aerial bombardment would be kinda neat +This one would be really easy to freeze game unless it was flagged unfortunately. + + else + begin + Gear^.X:= int2hwFloat(PlayWidth)*int2hwFloat(min(max(0,hwRound(Gear^.Y)),PlayHeight))/PlayHeight; + Gear^.Y:= -_2048-_256-_256; + tdx:= Gear^.dX; + Gear^.dX:= Gear^.dY; + Gear^.dY:= tdx; + Gear^.dY.isNegative:= false + end +*) + WorldWrap:= true + end; +end; end. diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uInputHandler.pas --- a/hedgewars/uInputHandler.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uInputHandler.pas Mon Oct 28 14:07:04 2013 +0100 @@ -40,6 +40,8 @@ procedure SetBinds(var binds: TBinds); procedure SetDefaultBinds; procedure chDefaultBind(var id: shortstring); +procedure loadBinds(cmd, s: shortstring); +procedure addBind(var binds: TBinds; var id: shortstring); procedure ControllerInit; procedure ControllerAxisEvent(joy, axis: Byte; value: Integer); @@ -47,7 +49,7 @@ procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean); implementation -uses uConsole, uCommands, uMisc, uVariables, uConsts, uUtils, uDebug; +uses uConsole, uCommands, uMisc, uVariables, uConsts, uUtils, uDebug, uPhysFSLayer; const LSHIFT = $0200; @@ -70,7 +72,6 @@ //ControllerBalls: array[0..5] of array[0..19] of array[0..1] of Integer; //ControllerHats: array[0..5] of array[0..19] of Byte; //ControllerButtons: array[0..5] of array[0..19] of Byte; - usingDBinds: boolean; function KeyNameToCode(name: shortstring): LongInt; inline; begin @@ -314,6 +315,8 @@ DefaultBinds[KeyNameToCode('j0a1d')]:= '+down'; for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+IntToStr(i); for i:= 1 to 5 do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i); + +loadBinds('dbind', cPathz[ptData] + '/settings.ini'); end; procedure SetBinds(var binds: TBinds); @@ -447,22 +450,68 @@ ProcessKey(k + ControllerNumAxes[joy]*2 + ControllerNumHats[joy]*4 + button, pressed); end; -// Bind that isn't a team bind, but overrides defaultbinds. -// When first called, DefaultBinds is cleared, because we assume we are getting a full list of dbinds. -procedure chDefaultBind(var id: shortstring); +procedure loadBinds(cmd, s: shortstring); +var i: LongInt; + f: PFSFile; + p, l: shortstring; + b: byte; +begin + AddFileLog('[BINDS] Loading binds from: ' + s); + + l:= ''; + if pfsExists(s) then + begin + f:= pfsOpenRead(s); + while (not pfsEOF(f)) and (l <> '[Binds]') do + pfsReadLn(f, l); + + while (not pfsEOF(f)) and (l <> '') do + begin + pfsReadLn(f, l); + + p:= ''; + i:= 1; + while (i <= length(l)) and (l[i] <> '=') do + begin + if l[i] <> '%' then + begin + p:= p + l[i]; + inc(i) + end else + begin + l[i]:= '$'; + val(copy(l, i, 3), b); + p:= p + char(b); + inc(i, 3) + end; + end; + + if i < length(l) then + begin + l:= copy(l, i + 1, length(l) - i); + if l <> 'default' then + begin + p:= cmd + ' ' + l + ' ' + p; + ParseCommand(p, true) + end + end + end; + + pfsClose(f) + end + else + AddFileLog('[BINDS] file not found'); +end; + + +procedure addBind(var binds: TBinds; var id: shortstring); var KeyName, Modifier, tmp: shortstring; - b: LongInt; + i, b: LongInt; begin KeyName:= ''; Modifier:= ''; -if (not usingDBinds) then - begin - usingDBinds:= true; - FillByte(DefaultBinds, SizeOf(DefaultBinds), 0); - end; - -if (Pos('mod:', id) <> 0) then +if(Pos('mod:', id) <> 0)then begin tmp:= ''; SplitBySpace(id, tmp); @@ -479,12 +528,27 @@ if b = 0 then OutError(errmsgUnknownVariable + ' "' + id + '"', false) else - DefaultBinds[b]:= KeyName; + begin + // add bind: first check if this cmd is already bound, and remove old bind + i:= cKbdMaxIndex; + repeat + dec(i) + until (i < 0) or (binds[i] = KeyName); + if (i >= 0) then + binds[i]:= ''; + + binds[b]:= KeyName; + end +end; + +// Bind that isn't a team bind, but overrides defaultbinds. +procedure chDefaultBind(var id: shortstring); +begin + addBind(DefaultBinds, id) end; procedure initModule; begin - usingDBinds:= false; RegisterVariable('dbind', @chDefaultBind, true ); end; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uLand.pas --- a/hedgewars/uLand.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uLand.pas Mon Oct 28 14:07:04 2013 +0100 @@ -729,26 +729,27 @@ // also try basing cave dimensions on map/template dimensions, if they exist for w:= 0 to 5 do // width of 3 allowed hogs to be knocked through with grenade begin - for y:= topY to LAND_HEIGHT - 1 do - begin - Land[y, leftX + w]:= lfIndestructible; - Land[y, rightX - w]:= lfIndestructible; - if (y + w) mod 32 < 16 then - c:= AMask - else - c:= AMask or RMask or GMask; // FF00FFFF + if (WorldEdge <> weBounce) and (WorldEdge <> weWrap) then + for y:= topY to LAND_HEIGHT - 1 do + begin + Land[y, leftX + w]:= lfIndestructible; + Land[y, rightX - w]:= lfIndestructible; + if (y + w) mod 32 < 16 then + c:= AMask + else + c:= AMask or RMask or GMask; // FF00FFFF - if (cReducedQuality and rqBlurryLand) = 0 then - begin - LandPixels[y, leftX + w]:= c; - LandPixels[y, rightX - w]:= c; - end - else - begin - LandPixels[y div 2, (leftX + w) div 2]:= c; - LandPixels[y div 2, (rightX - w) div 2]:= c; + if (cReducedQuality and rqBlurryLand) = 0 then + begin + LandPixels[y, leftX + w]:= c; + LandPixels[y, rightX - w]:= c; + end + else + begin + LandPixels[y div 2, (leftX + w) div 2]:= c; + LandPixels[y div 2, (rightX - w) div 2]:= c; + end; end; - end; for x:= leftX to rightX do begin diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uLandPainted.pas --- a/hedgewars/uLandPainted.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uLandPainted.pas Mon Oct 28 14:07:04 2013 +0100 @@ -27,7 +27,7 @@ procedure freeModule; implementation -uses uLandGraphics, uConsts, uVariables, uUtils, SDLh, uCommands, uDebug; +uses uLandGraphics, uConsts, uVariables, uUtils, SDLh, uCommands, uDebug, uScript; type PointRec = packed record X, Y: SmallInt; @@ -88,7 +88,11 @@ radius:= 0; pe:= pointsListHead; - TryDo((pe = nil) or (pe^.point.flags and $80 <> 0), 'Corrupted draw data', true); + while (pe <> nil) and (pe^.point.flags and $80 = 0) do + begin + ScriptCall('onSpecialPoint', pe^.point.X, pe^.point.Y, pe^.point.flags); + pe:= pe^.next; + end; while(pe <> nil) do begin @@ -110,7 +114,7 @@ end; prevPoint:= pe^.point; - pe:= pe^.next; + pe:= pe^.next; end; end; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uPhysFSLayer.pas --- a/hedgewars/uPhysFSLayer.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uPhysFSLayer.pas Mon Oct 28 14:07:04 2013 +0100 @@ -145,10 +145,12 @@ AddFileLog('[PhysFS] mount ' + PathPrefix + ': ' + inttostr(i)); i:= PHYSFS_mount(Str2PChar(UserPathPrefix + '/Data'), nil, false); AddFileLog('[PhysFS] mount ' + UserPathPrefix + '/Data: ' + inttostr(i)); - i:= PHYSFS_mount(Str2PChar(UserPathPrefix + '/Teams'), '/Teams', false); - AddFileLog('[PhysFS] mount ' + UserPathPrefix + '/Teams: ' + inttostr(i)); hedgewarsMountPackages; + + i:= PHYSFS_mount(Str2PChar(UserPathPrefix), nil, false); + // need access to teams and frontend configs (for bindings) + AddFileLog('[PhysFS] mount ' + UserPathPrefix + ': ' + inttostr(i)); end; procedure freeModule; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uRender.pas --- a/hedgewars/uRender.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uRender.pas Mon Oct 28 14:07:04 2013 +0100 @@ -44,6 +44,7 @@ procedure DrawCircle (X, Y, Radius, Width: LongInt); procedure DrawCircle (X, Y, Radius, Width: LongInt; r, g, b, a: Byte); +procedure DrawLine (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline; procedure DrawLine (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte); procedure DrawFillRect (r: TSDL_Rect); procedure DrawHedgehog (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real); @@ -348,6 +349,11 @@ DrawTexture(X - round(Source^.w * scale) div 2, Top, Source, scale) end; +procedure DrawLine(X0, Y0, X1, Y1, Width: Single; color: LongWord); inline; +begin +DrawLine(X0, Y0, X1, Y1, Width, (color shr 24) and $FF, (color shr 16) and $FF, (color shr 8) and $FF, color and $FF) +end; + procedure DrawLine(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte); var VertexBuffer: array [0..1] of TVertex2f; begin @@ -533,7 +539,7 @@ procedure Tint(r, g, b, a: Byte); inline; var nc, tw: Longword; begin - nc:= (a shl 24) or (b shl 16) or (g shl 8) or r; + nc:= (r shl 24) or (g shl 16) or (b shl 8) or a; if nc = lastTint then exit; @@ -554,6 +560,7 @@ procedure Tint(c: Longword); inline; begin + if c = lastTint then exit; Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF)) end; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uScript.pas --- a/hedgewars/uScript.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uScript.pas Mon Oct 28 14:07:04 2013 +0100 @@ -95,6 +95,7 @@ ScriptAmmoDelay : shortstring; ScriptAmmoReinforcement : shortstring; ScriptLoaded : boolean; + mapDims : boolean; procedure ScriptPrepareAmmoStore; forward; procedure ScriptApplyAmmoStore; forward; @@ -2065,7 +2066,8 @@ end; ScriptSetInteger('ClansCount', ClansCount); -ScriptSetInteger('TeamsCount', TeamsCount) +ScriptSetInteger('TeamsCount', TeamsCount); +mapDims:= false end; @@ -2088,7 +2090,10 @@ begin s:= cPathz[ptData] + name; if not pfsExists(s) then + begin + AddFileLog('[LUA] Script not found: ' + name); exit; + end; f:= pfsOpenRead(s); if f = nil then @@ -2119,8 +2124,9 @@ ScriptSetInteger('GameTime', GameTicks); ScriptSetInteger('TotalRounds', TotalRounds); ScriptSetInteger('WaterLine', cWaterLine); -if GameTicks = 0 then +if not mapDims then begin + mapDims:= true; ScriptSetInteger('LAND_WIDTH', LAND_WIDTH); ScriptSetInteger('LAND_HEIGHT', LAND_HEIGHT); ScriptSetInteger('LeftX', leftX); @@ -2622,6 +2628,7 @@ procedure initModule; begin +mapDims:= false; end; procedure freeModule; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uStore.pas --- a/hedgewars/uStore.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uStore.pas Mon Oct 28 14:07:04 2013 +0100 @@ -704,20 +704,20 @@ end; procedure SetupOpenGL; -var name: array[byte] of char; +var buf: array[byte] of char; AuxBufNum: LongInt = 0; tmpstr: AnsiString; tmpint: LongInt; tmpn: LongInt; begin {$IFDEF SDL2} - name:= SDL_GetCurrentVideoDriver(); + AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_GetCurrentVideoDriver()) + ')'); {$ELSE} - name:= SDL_VideoDriverName(name, sizeof(name)); + buf[0]:= char(0); // avoid compiler hint + AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_VideoDriverName(buf, sizeof(buf))) + ')'); {$ENDIF} AuxBufNum:= AuxBufNum; - AddFileLog('Setting up OpenGL (using driver: ' + shortstring(name) + ')'); {$IFDEF MOBILE} // TODO: this function creates an opengles1.1 context diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uTeams.pas --- a/hedgewars/uTeams.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uTeams.pas Mon Oct 28 14:07:04 2013 +0100 @@ -43,7 +43,7 @@ implementation uses uLocale, uAmmos, uChat, uVariables, uUtils, uIO, uCaptions, uCommands, uDebug, - uGearsUtils, uGearsList, uVisualGearsList, uPhysFSLayer + uGearsUtils, uGearsList, uVisualGearsList, uTextures {$IFDEF USE_TOUCH_INTERFACE}, uTouch{$ENDIF}; var MaxTeamHealth: LongInt; @@ -570,57 +570,13 @@ procedure loadTeamBinds(s: shortstring); var i: LongInt; - f: PFSFile; - p, l: shortstring; - b: byte; begin - l:= ''; - for i:= 1 to length(s) do if s[i] in ['\', '/', ':'] then s[i]:= '_'; - - s:= cPathz[ptTeams] + '/' + s + '.hwt'; - if pfsExists(s) then - begin - AddFileLog('Loading binds from: ' + s); - f:= pfsOpenRead(s); - while (not pfsEOF(f)) and (l <> '[Binds]') do - pfsReadLn(f, l); - - while (not pfsEOF(f)) and (l <> '') do - begin - pfsReadLn(f, l); - p:= ''; - i:= 1; - while (i <= length(l)) and (l[i] <> '=') do - begin - if l[i] <> '%' then - begin - p:= p + l[i]; - inc(i) - end else - begin - l[i]:= '$'; - val(copy(l, i, 3), b); - p:= p + char(b); - inc(i, 3) - end; - end; + s:= cPathz[ptTeams] + '/' + s + '.hwt'; - if i < length(l) then - begin - l:= copy(l, i + 1, length(l) - i); - if l <> 'default' then - begin - p:= 'bind ' + l + ' ' + p; - ParseCommand(p, true) - end - end - end; - - pfsClose(f) - end + loadBinds('bind', s); end; procedure chAddTeam(var s: shortstring); @@ -665,43 +621,11 @@ end; procedure chBind(var id: shortstring); -var KeyName, Modifier, tmp: shortstring; - i, b: LongInt; begin -KeyName:= ''; -Modifier:= ''; - -if CurrentTeam = nil then - exit; - -if(Pos('mod:', id) <> 0)then - begin - tmp:= ''; - SplitBySpace(id, tmp); - Modifier:= id; - id:= tmp; - end; + if CurrentTeam = nil then + exit; -SplitBySpace(id, KeyName); -if KeyName[1]='"' then - Delete(KeyName, 1, 1); -if KeyName[byte(KeyName[0])]='"' then - Delete(KeyName, byte(KeyName[0]), 1); -b:= KeyNameToCode(id, Modifier); -if b = 0 then - OutError(errmsgUnknownVariable + ' "' + id + '"', false) -else - begin - // add bind: first check if this cmd is already bound, and remove old bind - i:= cKbdMaxIndex; - repeat - dec(i) - until (i < 0) or (CurrentTeam^.Binds[i] = KeyName); - if (i >= 0) then - CurrentTeam^.Binds[i]:= ''; - - CurrentTeam^.Binds[b]:= KeyName; - end + addBind(CurrentTeam^.Binds, id) end; procedure chTeamGone(var s:shortstring); @@ -790,8 +714,26 @@ for i:= 0 to Pred(TeamsCount) do begin for h:= 0 to cMaxHHIndex do - if TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil then - Dispose(TeamsArray[i]^.Hedgehogs[h].GearHidden); + with TeamsArray[i]^.Hedgehogs[h] do + begin + if GearHidden <> nil then + Dispose(GearHidden); + + FreeTexture(NameTagTex); + FreeTexture(HealthTagTex); + FreeTexture(HatTex); + end; + + with TeamsArray[i]^ do + begin + FreeTexture(NameTagTex); + FreeTexture(CrosshairTex); + FreeTexture(GraveTex); + FreeTexture(HealthTex); + FreeTexture(AIKillsTex); + FreeTexture(FlagTex); + end; + Dispose(TeamsArray[i]); end; for i:= 0 to Pred(ClansCount) do diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uTypes.pas Mon Oct 28 14:07:04 2013 +0100 @@ -173,6 +173,8 @@ TRenderMode = (rmDefault, rmLeftEye, rmRightEye); TStereoMode = (smNone, smRedCyan, smCyanRed, smRedBlue, smBlueRed, smRedGreen, smGreenRed, smHorizontal, smVertical); + TWorldEdge = (weNone, weWrap, weBounce, weSea, weSky); + THHFont = record Handle: PTTF_Font; Height: LongInt; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uVariables.pas Mon Oct 28 14:07:04 2013 +0100 @@ -82,6 +82,9 @@ GameType : TGameType; InputMask : LongWord; GameFlags : Longword; + WorldEdge : TWorldEdge; + LeftImpactTimer : LongWord; + RightImpactTimer: LongWord; TurnTimeLeft : Longword; TagTurnTimeLeft : Longword; ReadyTimeLeft : Longword; @@ -841,7 +844,8 @@ Probability: 0; NumberInCase: 1; Ammo: (Propz: ammoprop_ForwMsgs or - ammoprop_NeedUpDown; + ammoprop_NeedUpDown or + ammoprop_DoesntStopTimerInMultiShoot; Count: AMMO_INFINITE; NumPerTurn: 1; Timer: 0; @@ -922,7 +926,8 @@ ammoprop_AttackInMove or ammoprop_Utility or ammoprop_AltAttack or - ammoprop_NeedUpDown; + ammoprop_NeedUpDown or + ammoprop_DoesntStopTimerWhileAttacking; Count: 5; NumPerTurn: 0; Timer: 0; @@ -974,7 +979,7 @@ NameTex: nil; Probability: 20; NumberInCase: 2; - Ammo: (Propz: ammoprop_NeedUpDown; + Ammo: (Propz: ammoprop_NeedUpDown or ammoprop_DoesntStopTimerInMultiShoot; Count: 3; NumPerTurn: 3; Timer: 0; @@ -1736,9 +1741,10 @@ NameTex: nil; Probability: 20; NumberInCase: 2; - Ammo: (Propz: ammoprop_NeedUpDown or + Ammo: (Propz: ammoprop_NeedUpDown or ammoprop_OscAim or - ammoprop_NoMoveAfter; + ammoprop_NoMoveAfter or + ammoprop_DoesntStopTimerInMultiShoot; Count: 2; NumPerTurn: 1; Timer: 0; @@ -2446,6 +2452,9 @@ InputMask := $FFFFFFFF; GameFlags := 0; + WorldEdge := weNone; + LeftImpactTimer := 0; + RightImpactTimer := 0; TurnTimeLeft := 0; TagTurnTimeLeft := 0; cSuddenDTurns := 15; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uVideoRec.pas --- a/hedgewars/uVideoRec.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uVideoRec.pas Mon Oct 28 14:07:04 2013 +0100 @@ -367,6 +367,10 @@ procedure initModule; begin + // we need to make sure these variables are initialized before the main loop + // or the wrapper will keep the default values of preinit + cScreenWidth:= max(cWindowedWidth, 640); + cScreenHeight:= max(cWindowedHeight, 480); end; procedure freeModule; diff -r 7588daa8d28f -r 3a3defce1b28 hedgewars/uWorld.pas --- a/hedgewars/uWorld.pas Wed Sep 25 05:42:16 2013 +0300 +++ b/hedgewars/uWorld.pas Mon Oct 28 14:07:04 2013 +0100 @@ -85,6 +85,7 @@ AmmoMenuTex : PTexture; HorizontOffset: LongInt; cOffsetY: LongInt; + WorldEnd, WorldFade : array[0..3] of HwColor4f; const cStereo_Sky = 0.0500; cStereo_Horizon = 0.0250; @@ -1129,6 +1130,8 @@ highlight: Boolean; smallScreenOffset, offsetX, offsetY, screenBottom: LongInt; VertexBuffer: array [0..3] of TVertex2f; + lw, lh: GLfloat; + c1, c2: LongWord; // couple of colours for edges begin if (cReducedQuality and rqNoBackground) = 0 then begin @@ -1235,6 +1238,106 @@ end; {$WARNINGS ON} +if WorldEdge <> weNone then + begin +(* I think for a bounded world, will fill the left and right areas with black or something. Also will probably want various border effects/animations based on border type. Prob also, say, trigger a border animation timer on an impact. *) + + glDisable(GL_TEXTURE_2D); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glPushMatrix; + glTranslatef(WorldDx, WorldDy, 0); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, @WorldFade[0]); + + VertexBuffer[0].X:= leftX-20; + VertexBuffer[0].Y:= -3000; + VertexBuffer[1].X:= leftX-20; + VertexBuffer[1].Y:= cWaterLine+cVisibleWater; + VertexBuffer[2].X:= leftX+30; + VertexBuffer[2].Y:= cWaterLine+cVisibleWater; + VertexBuffer[3].X:= leftX+30; + VertexBuffer[3].Y:= -3000; + + glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); + glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); + + VertexBuffer[0].X:= rightX+20; + VertexBuffer[1].X:= rightX+20; + VertexBuffer[2].X:= rightX-30; + VertexBuffer[3].X:= rightX-30; + + glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); + glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); + + glColorPointer(4, GL_UNSIGNED_BYTE, 0, @WorldEnd[0]); + + VertexBuffer[0].X:= -5000; + VertexBuffer[1].X:= -5000; + VertexBuffer[2].X:= leftX-20; + VertexBuffer[3].X:= leftX-20; + + glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); + glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); + + VertexBuffer[0].X:= rightX+5000; + VertexBuffer[1].X:= rightX+5000; + VertexBuffer[2].X:= rightX+20; + VertexBuffer[3].X:= rightX+20; + + glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); + glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); + + glPopMatrix; + glDisableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glColor4ub($FF, $FF, $FF, $FF); // must not be Tint() as color array seems to stay active and color reset is required + glEnable(GL_TEXTURE_2D); + + // I'd still like to have things happen to the border when a wrap or bounce just occurred, based on a timer + if WorldEdge = weBounce then + begin + // could maybe alternate order of these on a bounce, or maybe drop the outer ones. + if LeftImpactTimer mod 2 = 0 then + begin + c1:= $5454FFFF; c2:= $FFFFFFFF; + end + else begin + c1:= $FFFFFFFF; c2:= $5454FFFF; + end; + DrawLine(leftX, -3000, leftX, cWaterLine+cVisibleWater, 7.0, c1); + DrawLine(leftX, -3000, leftX, cWaterLine+cVisibleWater, 5.0, c2); + DrawLine(leftX, -3000, leftX, cWaterLine+cVisibleWater, 3.0, c1); + DrawLine(leftX, -3000, leftX, cWaterLine+cVisibleWater, 1.0, c2); + if RightImpactTimer mod 2 = 0 then + begin + c1:= $5454FFFF; c2:= $FFFFFFFF; + end + else begin + c1:= $FFFFFFFF; c2:= $5454FFFF; + end; + DrawLine(rightX, -3000, rightX, cWaterLine+cVisibleWater, 7.0, c1); + DrawLine(rightX, -3000, rightX, cWaterLine+cVisibleWater, 5.0, c2); + DrawLine(rightX, -3000, rightX, cWaterLine+cVisibleWater, 3.0, c1); + DrawLine(rightX, -3000, rightX, cWaterLine+cVisibleWater, 1.0, c2) + end + else if WorldEdge = weWrap then + begin + DrawLine(leftX, -3000, leftX, cWaterLine+cVisibleWater, 5.0, $A0, $30, $60, max(50,255-LeftImpactTimer)); + DrawLine(leftX, -3000, leftX, cWaterLine+cVisibleWater, 2.0, $FF0000FF); + DrawLine(rightX, -3000, rightX, cWaterLine+cVisibleWater, 5.0, $A0, $30, $60, max(50,255-RightImpactTimer)); + DrawLine(rightX, -3000, rightX, cWaterLine+cVisibleWater, 2.0, $FF0000FF); + end + else + begin + DrawLine(leftX, -3000, leftX, cWaterLine+cVisibleWater, 5.0, $2E8B5780); + DrawLine(rightX, -3000, rightX, cWaterLine+cVisibleWater, 5.0, $2E8B5780) + end; + if LeftImpactTimer > Lag then dec(LeftImpactTimer,Lag) else LeftImpactTimer:= 0; + if RightImpactTimer > Lag then dec(RightImpactTimer,Lag) else RightImpactTimer:= 0 + end; + // this scale is used to keep the various widgets at the same dimension at all zoom levels SetScale(cDefaultZoomLevel); @@ -1631,7 +1734,7 @@ DrawSprite(sprArrow, TargetCursorPoint.X, cScreenHeight - TargetCursorPoint.Y, (RealTicks shr 6) mod 8) end end; -isFirstFrame:= false +isFirstFrame:= false; end; var PrevSentPointTime: LongWord = 0; @@ -1899,6 +2002,16 @@ AMState:= AMHidden; isFirstFrame:= true; stereoDepth:= stereoDepth; // avoid hint + + FillChar(WorldFade, sizeof(WorldFade), 0); + WorldFade[0].a:= 255; + WorldFade[1].a:= 255; + FillChar(WorldEnd, sizeof(WorldEnd), 0); + WorldEnd[0].a:= 255; + WorldEnd[1].a:= 255; + WorldEnd[2].a:= 255; + WorldEnd[3].a:= 255; + end; procedure freeModule; diff -r 7588daa8d28f -r 3a3defce1b28 project_files/hedgewars.pro --- a/project_files/hedgewars.pro Wed Sep 25 05:42:16 2013 +0300 +++ b/project_files/hedgewars.pro Mon Oct 28 14:07:04 2013 +0100 @@ -87,7 +87,6 @@ ../QTfrontend/achievements.h \ ../QTfrontend/binds.h \ ../QTfrontend/ui_hwform.h \ - ../QTfrontend/KB.h \ ../QTfrontend/hwconsts.h \ ../QTfrontend/sdlkeys.h \ ../QTfrontend/ui/mouseoverfilter.h \ diff -r 7588daa8d28f -r 3a3defce1b28 share/hedgewars/Data/Scripts/Multiplayer/Racer.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Racer.lua Wed Sep 25 05:42:16 2013 +0300 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Racer.lua Mon Oct 28 14:07:04 2013 +0100 @@ -92,6 +92,10 @@ local currY = {} local currCount = 0 +local specialPointsX = {} +local specialPointsY = {} +local specialPointsCount = 0 + -------------------------- -- hog and team tracking variales -------------------------- @@ -489,6 +493,10 @@ lastRound = TotalRounds RoundHasChanged = false -- true + for i = 0, (specialPointsCount-1) do + PlaceWayPoint(specialPointsX[i], specialPointsY[i]) + end + RebuildTeamInfo() ShowMission ( @@ -501,7 +509,7 @@ "", 4, 4000 ) - TryRepositionHogs() + TryRepositionHogs() end @@ -524,10 +532,16 @@ end +function onSpecialPoint(x,y,flag) + specialPointsX[specialPointsCount] = x + specialPointsY[specialPointsCount] = y + specialPointsCount = specialPointsCount + 1 +end + function onNewTurn() CheckForNewRound() - TryRepositionHogs() + TryRepositionHogs() racerActive = false