# HG changeset patch
# User koda
# Date 1294142026 -3600
# Node ID f924be23ffb4bdf5c8368c968b9a3459d55e0ddc
# Parent 0ddb100fea6164a5444030929e5c925f4e306119# Parent 3edc0cdcfe03abf1143ddbdabf92d37258a2605f
merge with HEAD after 0.9.15 release, move consts and vars in their proper files
diff -r 0ddb100fea61 -r f924be23ffb4 .hgtags
--- a/.hgtags Mon Dec 27 23:57:44 2010 +0100
+++ b/.hgtags Tue Jan 04 12:53:46 2011 +0100
@@ -22,3 +22,6 @@
0000000000000000000000000000000000000000 Hedgewars-iOS-1.0.1
3620607258cdc1213dce20cb6ad7872f6b8085e0 Hedgewars-iOS-1.0.1
adffb668f06e265b45d1e4aedc283e6f4e5ba7e8 Hedgewars-iOS-1.1
+ede569bb76f389bd5dfbb7ebf68af3087e3e881c Hedgewars-iOS-1.2
+a5735e877aae61cd705265e2f8c0c7ad08d45f0e Hedgewars-iOS-1.2.1
+5ea3d182415e4327e7584b1aa68197931d232ac3 Hedgewars-iOS-1.2.2
diff -r 0ddb100fea61 -r f924be23ffb4 CMakeLists.txt
--- a/CMakeLists.txt Mon Dec 27 23:57:44 2010 +0100
+++ b/CMakeLists.txt Tue Jan 04 12:53:46 2011 +0100
@@ -18,13 +18,9 @@
ARGS identify -in ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE version_suffix
)
- STRING(REGEX REPLACE "(.*) +(.*)" "\\2:\\1" version_suffix ${version_suffix})
+ STRING(REGEX REPLACE "([0-9a-zA-Z]+)(.*) ([0-9]+)(.*)" "\\3:\\1" version_suffix ${version_suffix})
MESSAGE(STATUS "Building revision ${version_suffix}")
- set(version_suffix ".${version_suffix}")
-# #truncate to numbers only - trying to fix a problem described in http://www.hedgewars.org/node/2019
-# STRING(REGEX REPLACE "^\\.(\\d+)" ".\\1" version_suffix ${version_suffix})
-# # screw whole suffix if there's no number
-# STRING(REGEX REPLACE "^\\.([a-z]+.*)" "-dev" version_suffix ${version_suffix})
+ set(version_suffix "-${version_suffix}")
ENDIF()
ENDIF()
ELSE()
@@ -243,13 +239,14 @@
"release$"
"Debug$"
"Release$"
- "proto.inc$"
- "hwconsts.cpp$"
- "playlist.inc$"
+ "proto\\\\.inc$"
+ "hwconsts\\\\.cpp$"
+ "playlist\\\\.inc$"
"CPack"
- "cmake_install.cmake$"
- "config.inc$"
- "hwengine.desktop$"
+ "cmake_install\\\\.cmake$"
+ "config\\\\.inc$"
+ "hwengine\\\\.desktop$"
+ "CMakeCache\\\\.txt$"
# "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libopenalbridge"
"^${CMAKE_CURRENT_SOURCE_DIR}/project_files/HedgewarsMobile/"
"^${CMAKE_CURRENT_SOURCE_DIR}/bin/[a-z]"
diff -r 0ddb100fea61 -r f924be23ffb4 ChangeLog.txt
--- a/ChangeLog.txt Mon Dec 27 23:57:44 2010 +0100
+++ b/ChangeLog.txt Tue Jan 04 12:53:46 2011 +0100
@@ -1,6 +1,33 @@
+ features
* bugfixes
+0.9.14 -> 0.9.15:
+ + Ability to create, save and load hand drawn maps
+ + New maps: Capture the Flag (Blizzard) Map
+ + New themes: Christmas
+ + Snowflakes on Christmas/Snow themes accumulates on the ground
+ + New game modifiers: No wind, More wind
+ + New missions: Dangerous ducklings, Diver, Spooky tree, Teamwork
+ + New weapons: Mudball, Drill strike
+ + Many more Lua hooks
+ + Readytimer
+ + Ability to edit seed
+ + Ability to select gameplay scripts
+ + New gameplay scripts: Capture the Flag, No jumping, Random weapon
+ + New Lua unified translation framework
+ + Code refactoring
+ + Max teams upped to 8
+ + Cosmetic enhancements to Napalm strike
+ + Selecting a game scheme selects the corresponding weapon set
+ + Dust when drills dig
+ + New hats: beaver, porkey, sheep
+ + Add density property to Gears
+ + Reworked management of schemes and weapon sets
+ + Will ask before deleting teams, schemes and weapon sets
+ + Explosions detach rope from land
+ + Variable rope length in scheme
+ + Allow hog speech when not your turn
+
0.9.13 -> 0.9.14:
+ New audio tracks
+ New forts: EvilChicken, Tank
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/CMakeLists.txt
--- a/QTfrontend/CMakeLists.txt Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/CMakeLists.txt Tue Jan 04 12:53:46 2011 +0100
@@ -23,137 +23,142 @@
include_directories(${SDL_INCLUDE_DIR})
include_directories(${SDLMIXER_INCLUDE_DIR})
if(UNIX)
- # HACK: in freebsd cannot find iconv.h included via SDL.h
- include_directories("/usr/local/include")
+ # HACK: in freebsd cannot find iconv.h included via SDL.h
+ include_directories("/usr/local/include")
endif(UNIX)
if(WIN32 AND NOT UNIX)
- set(HEDGEWARS_BINDIR ".")
- set(HEDGEWARS_DATADIR "../share/")
+ set(HEDGEWARS_BINDIR ".")
+ set(HEDGEWARS_DATADIR "../share/")
add_definitions(-DUSE_XFIRE)
else()
- set(HEDGEWARS_BINDIR ${CMAKE_INSTALL_PREFIX})
- if(DEFINED DATA_INSTALL_DIR)
- set(HEDGEWARS_DATADIR ${DATA_INSTALL_DIR})
- else()
- set(HEDGEWARS_DATADIR ${CMAKE_INSTALL_PREFIX}/share/)
- endif()
+ set(HEDGEWARS_BINDIR ${CMAKE_INSTALL_PREFIX})
+ if(DEFINED DATA_INSTALL_DIR)
+ set(HEDGEWARS_DATADIR ${DATA_INSTALL_DIR})
+ else()
+ set(HEDGEWARS_DATADIR ${CMAKE_INSTALL_PREFIX}/share/)
+ endif()
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hwconsts.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp)
-set( hwfr_src
- game.cpp
- main.cpp
- hwform.cpp
- team.cpp
- namegen.cpp
- teamselect.cpp
- teamselhelper.cpp
- frameTeam.cpp
- vertScrollArea.cpp
- gameuiconfig.cpp
- ui_hwform.cpp
- gamecfgwidget.cpp
- pages.cpp
- SquareLabel.cpp
- hats.cpp
- hedgehogerWidget.cpp
- hwmap.cpp
- mapContainer.cpp
- tcpBase.cpp
- about.cpp
- proto.cpp
- fpsedit.cpp
- netserver.cpp
- newnetclient.cpp
- netudpserver.cpp
- netudpwidget.cpp
- netregister.cpp
- netserverslist.cpp
- chatwidget.cpp
- binds.cpp
- SDLs.cpp
- playrecordpage.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp
- selectWeapon.cpp
- itemNum.cpp
- input_ip.cpp
- igbox.cpp
- weaponItem.cpp
- statsPage.cpp
- misc.cpp
- ammoSchemeModel.cpp
- togglebutton.cpp
- bgwidget.cpp
- achievements.cpp
- )
+set(hwfr_src
+ game.cpp
+ main.cpp
+ hwform.cpp
+ team.cpp
+ namegen.cpp
+ teamselect.cpp
+ teamselhelper.cpp
+ frameTeam.cpp
+ vertScrollArea.cpp
+ gameuiconfig.cpp
+ ui_hwform.cpp
+ gamecfgwidget.cpp
+ pages.cpp
+ SquareLabel.cpp
+ hats.cpp
+ hedgehogerWidget.cpp
+ hwmap.cpp
+ mapContainer.cpp
+ tcpBase.cpp
+ about.cpp
+ proto.cpp
+ fpsedit.cpp
+ netserver.cpp
+ newnetclient.cpp
+ netudpserver.cpp
+ netudpwidget.cpp
+ netregister.cpp
+ netserverslist.cpp
+ chatwidget.cpp
+ binds.cpp
+ SDLs.cpp
+ playrecordpage.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp
+ selectWeapon.cpp
+ itemNum.cpp
+ input_ip.cpp
+ igbox.cpp
+ weaponItem.cpp
+ statsPage.cpp
+ misc.cpp
+ ammoSchemeModel.cpp
+ togglebutton.cpp
+ bgwidget.cpp
+ achievements.cpp
+ qaspectratiolayout.cpp
+ drawmapwidget.cpp
+ drawmapscene.cpp
+ )
#xfire integration
if(WIN32)
- set(hwfr_src ${hwfr_src} xfire.cpp ../misc/xfire/xfiregameclient.cpp)
+ set(hwfr_src ${hwfr_src} xfire.cpp ../misc/xfire/xfiregameclient.cpp)
endif(WIN32)
if(MINGW)
- # resource compilation for mingw
- add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o
- COMMAND windres -I ${CMAKE_CURRENT_SOURCE_DIR}
- -i ${CMAKE_CURRENT_SOURCE_DIR}/hedgewars.rc
- -o ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o)
- set(hwfr_src ${hwfr_src} ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o)
+ # resource compilation for mingw
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o
+ COMMAND windres -I ${CMAKE_CURRENT_SOURCE_DIR}
+ -i ${CMAKE_CURRENT_SOURCE_DIR}/hedgewars.rc
+ -o ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o)
+ set(hwfr_src ${hwfr_src} ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o)
else(MINGW)
- set(hwfr_src ${hwfr_src} hedgewars.rc)
+ set(hwfr_src ${hwfr_src} hedgewars.rc)
endif(MINGW)
-set( hwfr_moc_hdrs
- game.h
- hats.h
- hwform.h
- teamselect.h
- teamselhelper.h
- frameTeam.h
- vertScrollArea.h
- gameuiconfig.h
- gamecfgwidget.h
- pages.h
- SquareLabel.h
- hedgehogerWidget.h
- hwmap.h
- mapContainer.h
- tcpBase.h
- about.h
- proto.h
- fpsedit.h
- netserver.h
- newnetclient.h
- netudpserver.h
- netudpwidget.h
- netregister.h
- netserverslist.h
- chatwidget.h
- SDLs.h
- playrecordpage.h
- selectWeapon.h
- itemNum.h
- input_ip.h
- igbox.h
- weaponItem.h
- statsPage.h
- misc.h
- ammoSchemeModel.h
- togglebutton.h
- bgwidget.h
- )
+set(hwfr_moc_hdrs
+ game.h
+ hats.h
+ hwform.h
+ teamselect.h
+ teamselhelper.h
+ frameTeam.h
+ vertScrollArea.h
+ gameuiconfig.h
+ gamecfgwidget.h
+ pages.h
+ SquareLabel.h
+ hedgehogerWidget.h
+ hwmap.h
+ mapContainer.h
+ tcpBase.h
+ about.h
+ proto.h
+ fpsedit.h
+ netserver.h
+ newnetclient.h
+ netudpserver.h
+ netudpwidget.h
+ netregister.h
+ netserverslist.h
+ chatwidget.h
+ SDLs.h
+ playrecordpage.h
+ selectWeapon.h
+ itemNum.h
+ input_ip.h
+ igbox.h
+ weaponItem.h
+ statsPage.h
+ misc.h
+ ammoSchemeModel.h
+ togglebutton.h
+ bgwidget.h
+ qaspectratiolayout.h
+ drawmapwidget.h
+ drawmapscene.h
+ )
-set( hwfr_hdrs
- binds.h
- ui_hwform.h
- predefteams.h
- KB.h
- hwconsts.h
- )
+set(hwfr_hdrs
+ binds.h
+ ui_hwform.h
+ KB.h
+ hwconsts.h
+ )
set(hwfr_rez hedgewars.qrc)
@@ -163,45 +168,45 @@
if(APPLE)
- set(hwfr_src ${hwfr_src} InstallController.cpp CocoaInitializer.mm M3Panel.mm M3InstallController.m NSWorkspace_RBAdditions.m)
- set(HW_LINK_LIBS IOKit)
+ set(hwfr_src ${hwfr_src} InstallController.cpp CocoaInitializer.mm M3Panel.mm M3InstallController.m NSWorkspace_RBAdditions.m)
+ set(HW_LINK_LIBS IOKit)
- find_package(Sparkle)
- if(SPARKLE_FOUND)
+ find_package(Sparkle)
+ if(SPARKLE_FOUND)
add_definitions(-DSPARKLE_ENABLED)
- set(hwfr_src ${hwfr_src} AutoUpdater.cpp SparkleAutoUpdater.mm)
+ set(hwfr_src ${hwfr_src} AutoUpdater.cpp SparkleAutoUpdater.mm)
set(HW_LINK_LIBS ${SPARKLE_LIBRARY} ${HW_LINK_LIBS})
- endif()
+ endif()
endif()
add_executable(hedgewars WIN32
- ${hwfr_src}
- ${hwfr_moc_srcs}
- ${hwfr_hdrs}
- ${hwfr_rez_src}
- )
+ ${hwfr_src}
+ ${hwfr_moc_srcs}
+ ${hwfr_hdrs}
+ ${hwfr_rez_src}
+ )
-set( HW_LINK_LIBS
- ${QT_LIBRARIES}
- ${SDL_LIBRARY}
- ${SDLMIXER_LIBRARY}
- ${HW_LINK_LIBS}
- )
+set(HW_LINK_LIBS
+ ${QT_LIBRARIES}
+ ${SDL_LIBRARY}
+ ${SDLMIXER_LIBRARY}
+ ${HW_LINK_LIBS}
+ )
if(WIN32 AND NOT UNIX)
- if(NOT SDL_LIBRARY)
- set(HW_LINK_LIBS ${HW_LINK_LIBS} SDL)
- endif()
+ if(NOT SDL_LIBRARY)
+ set(HW_LINK_LIBS ${HW_LINK_LIBS} SDL)
+ endif()
- set( HW_LINK_LIBS
- ${HW_LINK_LIBS}
- ole32
- oleaut32
- winspool
- uuid
- )
+ set( HW_LINK_LIBS
+ ${HW_LINK_LIBS}
+ ole32
+ oleaut32
+ winspool
+ uuid
+ )
endif()
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/SDLs.cpp
--- a/QTfrontend/SDLs.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/SDLs.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -166,7 +166,7 @@
SDLMusicInit();
if (music == NULL) {
- music = Mix_LoadMUS((datadir->absolutePath() + "/Music/main theme.ogg").toLocal8Bit().constData());
+ music = Mix_LoadMUS((datadir->absolutePath() + "/Music/main_theme.ogg").toLocal8Bit().constData());
}
Mix_VolumeMusic(MIX_MAX_VOLUME - 28);
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/SquareLabel.cpp
--- a/QTfrontend/SquareLabel.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/SquareLabel.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -29,6 +29,8 @@
void SquareLabel::paintEvent(QPaintEvent * event)
{
+ Q_UNUSED(event);
+
QPainter painter(this);
int pixsize;
if (width() > height()) {
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/about.cpp
--- a/QTfrontend/about.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/about.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -119,13 +119,14 @@
"German: Peter Hüwe <PeterHuewe@gmx.de>, Mario Liebisch <mario.liebisch@gmail.com>
"
"Italian: Luca Bonora <bonora.luca@gmail.com>
"
"Japanese: ADAM Etienne <etienne.adam@gmail.com>
"
+ "Korean: Anthony Bellew <webmaster@anthonybellew.com>
"
"Polish: Maciej Mroziński <mynick2@o2.pl>, Wojciech Latkowski <magik17l@gmail.com>, Piotr Mitana, Maciej Górny
"
"Portuguese: Fábio Canário <inufabie@gmail.com>
"
"Russian: Andrey Korotaev <unC0Rr@gmail.com>
"
"Slovak: Jose Riha
"
"Spanish: Carlos Vives <mail@carlosvives.es>
"
"Swedish: Niklas Grahn <raewolusjoon@yaoo.com>, Henrik Rostedt <henrik.rostedt@gmail.com>
"
- "Ukrainian: Eugene V. Lyubimkin <jackyf.devel@gmail.com>"
+ "Ukrainian: Eugene V. Lyubimkin <jackyf.devel@gmail.com>, Igor Paliychuk <igor-hkr@mail.ru>, Yevhen Sakara <eresid@gmail.com>"
"
") +
QLabel::tr("Special thanks:") + "
"
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/ammoSchemeModel.cpp
--- a/QTfrontend/ammoSchemeModel.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/ammoSchemeModel.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -60,6 +60,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
AmmoSchemeModel::AmmoSchemeModel(QObject* parent, const QString & fileName) :
@@ -120,6 +121,7 @@
<< "healthcaseamount" // 34
<< "waterrise" // 35
<< "healthdecrease" // 36
+ << "ropepct" // 37
;
QList proMode;
@@ -161,6 +163,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList shoppa;
@@ -202,6 +205,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList cleanslate;
@@ -243,6 +247,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList minefield;
@@ -284,6 +289,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList barrelmayhem;
@@ -325,6 +331,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList tunnelhogs;
@@ -366,6 +373,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList forts;
@@ -407,6 +415,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList timeless;
@@ -448,6 +457,7 @@
<< QVariant(30) // health case amt 34
<< QVariant(0) // water rise amt 35
<< QVariant(0) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList thinkingportals;
@@ -489,6 +499,7 @@
<< QVariant(25) // health case amt 34
<< QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
QList kingmode;
@@ -507,8 +518,8 @@
<< QVariant(false) // artillery 11
<< QVariant(true) // random order 12
<< QVariant(true) // king 13
- << QVariant(true) // place hog 14
- << QVariant(true) // shared ammo 15
+ << QVariant(false) // place hog 14
+ << QVariant(false) // shared ammo 15
<< QVariant(false) // disable girders 16
<< QVariant(false) // disable land objects 17
<< QVariant(false) // AI survival 18
@@ -523,13 +534,14 @@
<< QVariant(15) // sudden death 27
<< QVariant(5) // case prob 28
<< QVariant(3) // mines time 29
- << QVariant(3) // mines number 30
- << QVariant(20) // mine dud pct 31
- << QVariant(3) // explosives 32
+ << QVariant(4) // mines number 30
+ << QVariant(0) // mine dud pct 31
+ << QVariant(2) // explosives 32
<< QVariant(35) // health case pct 33
- << QVariant(30) // health case amt 34
- << QVariant(30) // water rise amt 35
+ << QVariant(25) // health case amt 34
+ << QVariant(47) // water rise amt 35
<< QVariant(5) // health dec amt 36
+ << QVariant(100) // rope modfier 37
;
@@ -565,6 +577,10 @@
QVariant AmmoSchemeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
+ Q_UNUSED(section);
+ Q_UNUSED(orientation);
+ Q_UNUSED(role);
+
return QVariant();
}
@@ -586,6 +602,8 @@
Qt::ItemFlags AmmoSchemeModel::flags(const QModelIndex & index) const
{
+ Q_UNUSED(index);
+
return
Qt::ItemIsEnabled
| Qt::ItemIsSelectable
@@ -608,12 +626,22 @@
bool AmmoSchemeModel::insertRows(int row, int count, const QModelIndex & parent)
{
- beginInsertRows(parent, row, row);
+ Q_UNUSED(count);
+
+ beginInsertRows(parent, schemes.size(), schemes.size());
- QList newScheme = defaultScheme;
- newScheme[0] = QVariant(tr("new"));
-
- schemes.insert(row, newScheme);
+ if (row == -1)
+ {
+ QList newScheme = defaultScheme;
+ newScheme[0] = QVariant(tr("new"));
+ schemes.insert(schemes.size(), newScheme);
+ }
+ else
+ {
+ QList newScheme = schemes[row];
+ newScheme[0] = QVariant(tr("copy of") + " " + newScheme[0].toString());
+ schemes.insert(schemes.size(), newScheme);
+ }
endInsertRows();
@@ -672,6 +700,10 @@
QVariant NetAmmoSchemeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
+ Q_UNUSED(section);
+ Q_UNUSED(orientation);
+ Q_UNUSED(role);
+
return QVariant();
}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/ammoSchemeModel.h
--- a/QTfrontend/ammoSchemeModel.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/ammoSchemeModel.h Tue Jan 04 12:53:46 2011 +0100
@@ -42,6 +42,7 @@
int numberOfDefaultSchemes;
QStringList predefSchemesNames;
+ QStringList spNames;
public slots:
void Save();
@@ -54,8 +55,6 @@
private:
QSettings fileConfig;
-
- QStringList spNames;
};
class NetAmmoSchemeModel : public QAbstractTableModel
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/bgwidget.cpp
--- a/QTfrontend/bgwidget.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/bgwidget.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -103,6 +103,8 @@
void BGWidget::paintEvent(QPaintEvent *event)
{
+ Q_UNUSED(event);
+
QPainter p;
p.begin(this);
//p.setRenderHint(QPainter::Antialiasing);
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/chatwidget.cpp
--- a/QTfrontend/chatwidget.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/chatwidget.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -341,6 +341,8 @@
void HWChatWidget::chatNickSelected(int index)
{
+ Q_UNUSED(index);
+
QListWidgetItem* item = chatNicks->currentItem();
if (!item)
return;
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/drawmapscene.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/drawmapscene.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,195 @@
+#include
+#include
+#include
+
+#include "drawmapscene.h"
+
+template T sqr(const T & x)
+{
+ return x*x;
+}
+
+DrawMapScene::DrawMapScene(QObject *parent) :
+ QGraphicsScene(parent),
+ m_pen(Qt::yellow),
+ m_brush(Qt::yellow)
+{
+ setSceneRect(0, 0, 4096, 2048);
+
+ QLinearGradient gradient(0, 0, 0, 2048);
+ gradient.setColorAt(0, QColor(60, 60, 155));
+ gradient.setColorAt(1, QColor(155, 155, 60));
+ setBackgroundBrush(QBrush(gradient));
+
+ m_pen.setWidth(67);
+ m_pen.setJoinStyle(Qt::RoundJoin);
+ m_pen.setCapStyle(Qt::RoundCap);
+ m_currPath = 0;
+}
+
+void DrawMapScene::mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent)
+{
+ if(m_currPath && (mouseEvent->buttons() & Qt::LeftButton))
+ {
+ QPainterPath path = m_currPath->path();
+ path.lineTo(mouseEvent->scenePos());
+ paths.first().append(mouseEvent->scenePos().toPoint());
+ m_currPath->setPath(path);
+
+ emit pathChanged();
+ }
+}
+
+void DrawMapScene::mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent)
+{
+ m_currPath = addPath(QPainterPath(), m_pen);
+
+ QPainterPath path = m_currPath->path();
+ QPointF p = mouseEvent->scenePos();
+ p += QPointF(0.01, 0.01);
+ path.moveTo(p);
+ path.lineTo(mouseEvent->scenePos());
+ paths.prepend(QList() << mouseEvent->scenePos().toPoint());
+ m_currPath->setPath(path);
+
+ emit pathChanged();
+}
+
+void DrawMapScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * mouseEvent)
+{
+ Q_UNUSED(mouseEvent);
+
+ simplifyLast();
+
+ m_currPath = 0;
+}
+
+void DrawMapScene::undo()
+{
+ if(items().size())
+ {
+ removeItem(items().first());
+ paths.removeFirst();
+
+ emit pathChanged();
+ }
+}
+
+void DrawMapScene::clearMap()
+{
+ clear();
+ paths.clear();
+
+ emit pathChanged();
+}
+
+QByteArray DrawMapScene::encode()
+{
+ QByteArray b;
+
+ for(int i = paths.size() - 1; i >= 0; --i)
+ {
+ int cnt = 0;
+ QList points = paths.at(i);
+ foreach(QPoint point, points)
+ {
+ qint16 px = qToBigEndian((qint16)point.x());
+ qint16 py = qToBigEndian((qint16)point.y());
+ quint8 flags = 2;
+ if(!cnt) flags |= 0x80;
+ b.append((const char *)&px, 2);
+ b.append((const char *)&py, 2);
+ b.append((const char *)&flags, 1);
+
+ ++cnt;
+ }
+
+ }
+
+ return b;
+}
+
+void DrawMapScene::decode(QByteArray data)
+{
+ clear();
+ paths.clear();
+
+ QList points;
+
+ while(data.size() >= 5)
+ {
+ qint16 px = qFromBigEndian(*(qint16 *)data.data());
+ data.remove(0, 2);
+ qint16 py = qFromBigEndian(*(qint16 *)data.data());
+ data.remove(0, 2);
+ quint8 flags = *(quint8 *)data.data();
+ data.remove(0, 1);
+
+ if((flags & 0x80) && points.size())
+ {
+ addPath(pointsToPath(points), m_pen);
+ paths.prepend(points);
+
+ points.clear();
+ }
+
+ points.append(QPoint(px, py));
+ }
+
+ if(points.size())
+ {
+ addPath(pointsToPath(points), m_pen);
+ paths.prepend(points);
+ }
+
+ emit pathChanged();
+}
+
+void DrawMapScene::simplifyLast()
+{
+ if(!paths.size()) return;
+
+ QList points = paths.at(0);
+
+ QPoint prevPoint = points.first();
+ int i = 1;
+ while(i < points.size())
+ {
+ if( (i != points.size() - 1)
+ && (sqr(prevPoint.x() - points[i].x()) + sqr(prevPoint.y() - points[i].y()) < 1000)
+ )
+ points.removeAt(i);
+ else
+ {
+ prevPoint = points[i];
+ ++i;
+ }
+ }
+
+ paths[0] = points;
+
+
+ // redraw path
+ {
+ QGraphicsPathItem * pathItem = static_cast(items()[0]);
+ pathItem->setPath(pointsToPath(paths[0]));
+ }
+
+ emit pathChanged();
+}
+
+QPainterPath DrawMapScene::pointsToPath(const QList points)
+{
+ QPainterPath path;
+
+ if(points.size())
+ {
+ QPointF p = points[0] + QPointF(0.01, 0.01);
+ path.moveTo(p);
+
+ foreach(QPoint p, points)
+ path.lineTo(p);
+ }
+
+ return path;
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/drawmapscene.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/drawmapscene.h Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,41 @@
+#ifndef DRAWMAPSCENE_H
+#define DRAWMAPSCENE_H
+
+#include
+#include
+
+class QGraphicsPathItem;
+
+typedef QList > Paths;
+
+class DrawMapScene : public QGraphicsScene
+{
+Q_OBJECT
+public:
+ explicit DrawMapScene(QObject *parent = 0);
+
+ QByteArray encode();
+ void decode(QByteArray data);
+
+signals:
+ void pathChanged();
+
+public slots:
+ void undo();
+ void clearMap();
+ void simplifyLast();
+
+private:
+ QPen m_pen;
+ QBrush m_brush;
+ QGraphicsPathItem * m_currPath;
+ Paths paths;
+
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * mouseEvent);
+
+ QPainterPath pointsToPath(const QList points);
+};
+
+#endif // DRAWMAPSCENE_H
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/drawmapwidget.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/drawmapwidget.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,87 @@
+#include
+#include
+
+#include "drawmapwidget.h"
+
+DrawMapWidget::DrawMapWidget(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::DrawMapWidget)
+{
+ ui->setupUi(this);
+
+ m_scene = 0;
+}
+
+DrawMapWidget::~DrawMapWidget()
+{
+ delete ui;
+}
+
+void DrawMapWidget::changeEvent(QEvent *e)
+{
+ QWidget::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void DrawMapWidget::setScene(DrawMapScene * scene)
+{
+ ui->graphicsView->setScene(scene);
+ m_scene = scene;
+}
+
+void DrawMapWidget::resizeEvent(QResizeEvent * event)
+{
+ Q_UNUSED(event);
+
+ if(ui->graphicsView && ui->graphicsView->scene())
+ ui->graphicsView->fitInView(ui->graphicsView->scene()->sceneRect(), Qt::KeepAspectRatio);
+}
+
+void DrawMapWidget::showEvent(QShowEvent * event)
+{
+ Q_UNUSED(event);
+
+ resizeEvent(0);
+}
+
+void DrawMapWidget::undo()
+{
+ if(m_scene) m_scene->undo();
+}
+
+void DrawMapWidget::clear()
+{
+ if(m_scene) m_scene->clearMap();
+}
+
+void DrawMapWidget::save(const QString & fileName)
+{
+ if(m_scene)
+ {
+ QFile file(fileName);
+
+ if(!file.open(QIODevice::WriteOnly))
+ QMessageBox::warning(this, tr("File error"), tr("Cannot open file '%1' for writing").arg(fileName));
+ else
+ file.write(qCompress(m_scene->encode()).toBase64());
+ }
+}
+
+void DrawMapWidget::load(const QString & fileName)
+{
+ if(m_scene)
+ {
+ QFile f(fileName);
+
+ if(!f.open(QIODevice::ReadOnly))
+ QMessageBox::warning(this, tr("File error"), tr("Cannot read file '%1'").arg(fileName));
+ else
+ m_scene->decode(qUncompress(QByteArray::fromBase64(f.readAll())));
+ }
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/drawmapwidget.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/drawmapwidget.h Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,69 @@
+#ifndef DRAWMAPWIDGET_H
+#define DRAWMAPWIDGET_H
+
+#include
+#include
+#include
+#include
+#include
+
+#include "qaspectratiolayout.h"
+#include "drawmapscene.h"
+
+namespace Ui {
+ class Ui_DrawMapWidget
+ {
+ public:
+ QGraphicsView *graphicsView;
+
+ void setupUi(QWidget *drawMapWidget)
+ {
+ QAspectRatioLayout * arLayout = new QAspectRatioLayout(drawMapWidget);
+ arLayout->setMargin(0);
+
+ graphicsView = new QGraphicsView(drawMapWidget);
+ arLayout->addWidget(graphicsView);
+
+ retranslateUi(drawMapWidget);
+
+ QMetaObject::connectSlotsByName(drawMapWidget);
+ } // setupUi
+
+ void retranslateUi(QWidget *drawMapWidget)
+ {
+ Q_UNUSED(drawMapWidget);
+ } // retranslateUi
+
+ };
+
+ class DrawMapWidget: public Ui_DrawMapWidget {};
+}
+
+class DrawMapWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit DrawMapWidget(QWidget *parent = 0);
+ ~DrawMapWidget();
+
+ void setScene(DrawMapScene * scene);
+
+public slots:
+ void undo();
+ void clear();
+ void save(const QString & fileName);
+ void load(const QString & fileName);
+
+protected:
+ void changeEvent(QEvent *e);
+ virtual void resizeEvent(QResizeEvent * event);
+ virtual void showEvent(QShowEvent * event);
+
+private:
+ Ui::DrawMapWidget *ui;
+
+ DrawMapScene * m_scene;
+};
+
+#endif // DRAWMAPWIDGET_H
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/game.cpp
--- a/QTfrontend/game.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/game.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -40,6 +40,7 @@
this->config = config;
this->gamecfg = gamecfg;
TeamCount = 0;
+ netSuspend = false;
}
HWGame::~HWGame()
@@ -77,7 +78,7 @@
}
HWProto::addStringToBuffer(buf, gt);
- HWProto::addStringListToBuffer(buf, gamecfg->getFullConfig());
+ buf += gamecfg->getFullConfig();
if (m_pTeamSelWidget)
{
@@ -88,7 +89,7 @@
HWProto::addStringToBuffer(buf, QString("eammprob %1").arg(ammostr.mid(cAmmoNumber, cAmmoNumber)));
HWProto::addStringToBuffer(buf, QString("eammdelay %1").arg(ammostr.mid(2 * cAmmoNumber, cAmmoNumber)));
HWProto::addStringToBuffer(buf, QString("eammreinf %1").arg(ammostr.mid(3 * cAmmoNumber, cAmmoNumber)));
- HWProto::addStringToBuffer(buf, QString("eammstore"));
+ if(!gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore"));
HWProto::addStringListToBuffer(buf,
(*it).TeamGameConfig(gamecfg->getInitHealth()));
}
@@ -245,7 +246,7 @@
break;
}
default: {
- if (gameType == gtNet)
+ if (gameType == gtNet && !netSuspend)
{
emit SendNet(msg);
}
@@ -378,3 +379,15 @@
gameState = state;
emit GameStateChanged(state);
}
+
+void HWGame::KillAllTeams()
+{
+ if (m_pTeamSelWidget)
+ {
+ QByteArray buf;
+ QList teams = m_pTeamSelWidget->getPlayingTeams();
+ for(QList::iterator it = teams.begin(); it != teams.end(); ++it)
+ HWProto::addStringToBuffer(buf, QString("eteamgone %1").arg((*it).TeamName));
+ RawSendIPC(buf);
+ }
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/game.h
--- a/QTfrontend/game.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/game.h Tue Jan 04 12:53:46 2011 +0100
@@ -53,6 +53,9 @@
void StartNet();
void StartTraining(const QString & file);
void StartCampaign(const QString & file);
+ void KillAllTeams();
+ GameState gameState;
+ bool netSuspend;
protected:
virtual QStringList setArguments();
@@ -89,7 +92,6 @@
GameCFGWidget * gamecfg;
TeamSelWidget* m_pTeamSelWidget;
GameType gameType;
- GameState gameState;
void commonConfig();
void SendConfig();
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/gamecfgwidget.cpp
--- a/QTfrontend/gamecfgwidget.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/gamecfgwidget.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -30,8 +30,9 @@
#include "igbox.h"
#include "hwconsts.h"
#include "ammoSchemeModel.h"
+#include "proto.h"
-GameCFGWidget::GameCFGWidget(QWidget* parent, bool externalControl) :
+GameCFGWidget::GameCFGWidget(QWidget* parent) :
QGroupBox(parent), mainLayout(this)
{
mainLayout.setMargin(0);
@@ -42,48 +43,96 @@
IconedGroupBox *GBoxOptions = new IconedGroupBox(this);
GBoxOptions->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- mainLayout.addWidget(GBoxOptions);
+ mainLayout.addWidget(GBoxOptions, 1, 0);
QGridLayout *GBoxOptionsLayout = new QGridLayout(GBoxOptions);
- GameSchemes = new QComboBox(GBoxOptions);
- GBoxOptionsLayout->addWidget(GameSchemes, 0, 1);
+ GBoxOptionsLayout->addWidget(new QLabel(QLabel::tr("Gameplay"), GBoxOptions), 0, 0);
+
+ Scripts = new QComboBox(GBoxOptions);
+ GBoxOptionsLayout->addWidget(Scripts, 0, 1);
+
+ Scripts->addItem("Normal");
+ Scripts->insertSeparator(1);
+
+ for (int i = 0; i < scriptList->size(); ++i) {
+ QString script = (*scriptList)[i].remove(".lua", Qt::CaseInsensitive);
+ QList scriptInfo;
+ scriptInfo.push_back(script);
+ QFile scriptCfgFile(QString("%1/Scripts/Multiplayer/%2.cfg").arg(datadir->absolutePath()).arg(script));
+ if (scriptCfgFile.exists() && scriptCfgFile.open(QFile::ReadOnly)) {
+ QString scheme;
+ QString weapons;
+ QTextStream input(&scriptCfgFile);
+ input >> scheme;
+ input >> weapons;
+ if (scheme.isEmpty())
+ scheme = "locked";
+ scheme.replace("_", " ");
+ if (weapons.isEmpty())
+ weapons = "locked";
+ weapons.replace("_", " ");
+ scriptInfo.push_back(scheme);
+ scriptInfo.push_back(weapons);
+ scriptCfgFile.close();
+ }
+ else
+ {
+ scriptInfo.push_back("locked");
+ scriptInfo.push_back("locked");
+ }
+ Scripts->addItem(script.replace("_", " "), scriptInfo);
+ }
+
+ connect(Scripts, SIGNAL(currentIndexChanged(int)), this, SLOT(scriptChanged(int)));
+
+ QWidget *SchemeWidget = new QWidget(GBoxOptions);
+ GBoxOptionsLayout->addWidget(SchemeWidget, 1, 0, 1, 2);
+
+ QGridLayout *SchemeWidgetLayout = new QGridLayout(SchemeWidget);
+ SchemeWidgetLayout->setMargin(0);
+
+ GameSchemes = new QComboBox(SchemeWidget);
+ SchemeWidgetLayout->addWidget(GameSchemes, 0, 2);
connect(GameSchemes, SIGNAL(currentIndexChanged(int)), this, SLOT(schemeChanged(int)));
- GBoxOptionsLayout->addWidget(new QLabel(QLabel::tr("Game scheme"), GBoxOptions), 0, 0);
+ SchemeWidgetLayout->addWidget(new QLabel(QLabel::tr("Game scheme"), SchemeWidget), 0, 0);
QPixmap pmEdit(":/res/edit.png");
- QPushButton * goToSchemePage = new QPushButton(GBoxOptions);
+ QPushButton * goToSchemePage = new QPushButton(SchemeWidget);
goToSchemePage->setToolTip(tr("Edit schemes"));
goToSchemePage->setIconSize(pmEdit.size());
goToSchemePage->setIcon(pmEdit);
goToSchemePage->setMaximumWidth(pmEdit.width() + 6);
- GBoxOptionsLayout->addWidget(goToSchemePage, 0, 2);
- connect(goToSchemePage, SIGNAL(clicked()), this, SIGNAL(goToSchemes()));
+ SchemeWidgetLayout->addWidget(goToSchemePage, 0, 3);
+ connect(goToSchemePage, SIGNAL(clicked()), this, SLOT(jumpToSchemes()));
- GBoxOptionsLayout->addWidget(new QLabel(QLabel::tr("Weapons"), GBoxOptions), 1, 0);
+ SchemeWidgetLayout->addWidget(new QLabel(QLabel::tr("Weapons"), SchemeWidget), 1, 0);
- WeaponsName = new QComboBox(GBoxOptions);
- GBoxOptionsLayout->addWidget(WeaponsName, 1, 1);
+ WeaponsName = new QComboBox(SchemeWidget);
+ SchemeWidgetLayout->addWidget(WeaponsName, 1, 2);
connect(WeaponsName, SIGNAL(currentIndexChanged(int)), this, SLOT(ammoChanged(int)));
- QPushButton * goToWeaponPage = new QPushButton(GBoxOptions);
+ QPushButton * goToWeaponPage = new QPushButton(SchemeWidget);
goToWeaponPage->setToolTip(tr("Edit weapons"));
goToWeaponPage->setIconSize(pmEdit.size());
goToWeaponPage->setIcon(pmEdit);
goToWeaponPage->setMaximumWidth(pmEdit.width() + 6);
- GBoxOptionsLayout->addWidget(goToWeaponPage, 1, 2);
-
+ SchemeWidgetLayout->addWidget(goToWeaponPage, 1, 3);
connect(goToWeaponPage, SIGNAL(clicked()), this, SLOT(jumpToWeapons()));
- GBoxOptionsLayout->addWidget(new QLabel(QLabel::tr("Bind schemes and weapons"), GBoxOptions), 2, 0);
+ //GBoxOptionsLayout->addWidget(new QLabel(QLabel::tr("Bind schemes with weapons"), GBoxOptions), 2, 0);
- bindEntries = new QCheckBox(GBoxOptions);
- bindEntries->setToolTip(tr("When this option is enabled selecting a game scheme will auto-select a weapon (and viceversa)"));
+ bindEntries = new QCheckBox(SchemeWidget);
+ bindEntries->setToolTip(tr("When this option is enabled selecting a game scheme will auto-select a weapon"));
bindEntries->setChecked(true);
- GBoxOptionsLayout->addWidget(bindEntries, 2, 2);
+ bindEntries->setMaximumWidth(42);
+ bindEntries->setStyleSheet( "QCheckBox::indicator:checked { image: url(\":/res/lock.png\"); }"
+ "QCheckBox::indicator:unchecked { image: url(\":/res/unlock.png\"); }" );
+ SchemeWidgetLayout->addWidget(bindEntries, 0, 1, 0, 1, Qt::AlignVCenter);
+ //GBoxOptionsLayout->addWidget(bindEntries, 2, 2);
connect(pMapContainer, SIGNAL(seedChanged(const QString &)), this, SLOT(seedChanged(const QString &)));
connect(pMapContainer, SIGNAL(mapChanged(const QString &)), this, SLOT(mapChanged(const QString &)));
@@ -91,11 +140,18 @@
connect(pMapContainer, SIGNAL(maze_sizeChanged(int)), this, SLOT(maze_sizeChanged(int)));
connect(pMapContainer, SIGNAL(themeChanged(const QString &)), this, SLOT(themeChanged(const QString &)));
connect(pMapContainer, SIGNAL(newTemplateFilter(int)), this, SLOT(templateFilterChanged(int)));
+ connect(pMapContainer, SIGNAL(drawMapRequested()), this, SIGNAL(goToDrawMap()));
+ connect(pMapContainer, SIGNAL(drawnMapChanged(const QByteArray &)), this, SLOT(onDrawnMapChanged(const QByteArray &)));
+}
+
+void GameCFGWidget::jumpToSchemes()
+{
+ emit goToSchemes(GameSchemes->currentIndex());
}
void GameCFGWidget::jumpToWeapons()
{
- emit goToWeapons(WeaponsName->currentText());
+ emit goToWeapons(WeaponsName->currentIndex());
}
QVariant GameCFGWidget::schemeData(int column) const
@@ -162,37 +218,71 @@
return schemeData(26).toInt();
}
-QStringList GameCFGWidget::getFullConfig() const
+QByteArray GameCFGWidget::getFullConfig() const
{
- QStringList sl;
- sl.append("eseed " + pMapContainer->getCurrentSeed());
- sl.append(QString("e$gmflags %1").arg(getGameFlags()));
- sl.append(QString("e$damagepct %1").arg(schemeData(24).toInt()));
- sl.append(QString("e$turntime %1").arg(schemeData(25).toInt() * 1000));
- sl.append(QString("e$sd_turns %1").arg(schemeData(27).toInt()));
- sl.append(QString("e$casefreq %1").arg(schemeData(28).toInt()));
- sl.append(QString("e$minestime %1").arg(schemeData(29).toInt()));
- sl.append(QString("e$minesnum %1").arg(schemeData(30).toInt()));
- sl.append(QString("e$minedudpct %1").arg(schemeData(31).toInt()));
- sl.append(QString("e$explosives %1").arg(schemeData(32).toInt()));
- sl.append(QString("e$healthprob %1").arg(schemeData(33).toInt()));
- sl.append(QString("e$hcaseamount %1").arg(schemeData(34).toInt()));
- sl.append(QString("e$waterrise %1").arg(schemeData(35).toInt()));
- sl.append(QString("e$healthdec %1").arg(schemeData(36).toInt()));
- sl.append(QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()));
- sl.append(QString("e$mapgen %1").arg(pMapContainer->get_mapgen()));
- sl.append(QString("e$maze_size %1").arg(pMapContainer->get_maze_size()));
+ QList bcfg;
+ int mapgen = pMapContainer->get_mapgen();
+
+ bcfg << QString("eseed " + pMapContainer->getCurrentSeed()).toUtf8();
+ bcfg << QString("e$gmflags %1").arg(getGameFlags()).toUtf8();
+ bcfg << QString("e$damagepct %1").arg(schemeData(24).toInt()).toUtf8();
+ bcfg << QString("e$turntime %1").arg(schemeData(25).toInt() * 1000).toUtf8();
+ bcfg << QString("e$sd_turns %1").arg(schemeData(27).toInt()).toUtf8();
+ bcfg << QString("e$casefreq %1").arg(schemeData(28).toInt()).toUtf8();
+ bcfg << QString("e$minestime %1").arg(schemeData(29).toInt() * 1000).toUtf8();
+ bcfg << QString("e$minesnum %1").arg(schemeData(30).toInt()).toUtf8();
+ bcfg << QString("e$minedudpct %1").arg(schemeData(31).toInt()).toUtf8();
+ bcfg << QString("e$explosives %1").arg(schemeData(32).toInt()).toUtf8();
+ bcfg << QString("e$healthprob %1").arg(schemeData(33).toInt()).toUtf8();
+ bcfg << QString("e$hcaseamount %1").arg(schemeData(34).toInt()).toUtf8();
+ bcfg << QString("e$waterrise %1").arg(schemeData(35).toInt()).toUtf8();
+ bcfg << QString("e$healthdec %1").arg(schemeData(36).toInt()).toUtf8();
+ bcfg << QString("e$ropepct %1").arg(schemeData(37).toInt()).toUtf8();
+ bcfg << QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()).toUtf8();
+ bcfg << QString("e$mapgen %1").arg(mapgen).toUtf8();
+
+ switch (mapgen)
+ {
+ case MAPGEN_MAZE:
+ bcfg << QString("e$maze_size %1").arg(pMapContainer->get_maze_size()).toUtf8();
+ break;
+
+ case MAPGEN_DRAWN:
+ {
+ QByteArray data = pMapContainer->getDrawnMapData();
+ while(data.size() > 0)
+ {
+ QByteArray tmp = data;
+ tmp.truncate(200);
+ tmp.prepend("edraw ");
+ bcfg << tmp;
+ data.remove(0, 200);
+ }
+ break;
+ }
+ default: ;
+ }
QString currentMap = pMapContainer->getCurrentMap();
if (currentMap.size() > 0)
{
- sl.append("emap " + currentMap);
+ bcfg << QString("emap " + currentMap).toUtf8();
if(pMapContainer->getCurrentIsMission())
- sl.append(QString("escript Maps/%1/map.lua")
- .arg(currentMap));
+ bcfg << QString("escript Maps/%1/map.lua").arg(currentMap).toUtf8();
+ }
+ bcfg << QString("etheme " + pMapContainer->getCurrentTheme()).toUtf8();
+
+ if (Scripts->currentIndex() > 0)
+ {
+ bcfg << QString("escript Scripts/Multiplayer/%1.lua").arg(Scripts->itemData(Scripts->currentIndex()).toList()[0].toString()).toUtf8();
}
- sl.append("etheme " + pMapContainer->getCurrentTheme());
- return sl;
+
+ QByteArray result;
+
+ foreach(QByteArray ba, bcfg)
+ HWProto::addByteArrayToBuffer(result, ba);
+
+ return result;
}
void GameCFGWidget::setNetAmmo(const QString& name, const QString& ammo)
@@ -220,6 +310,7 @@
themeChanged(pMapContainer->getCurrentTheme());
schemeChanged(GameSchemes->currentIndex());
+ scriptChanged(Scripts->currentIndex());
mapgenChanged(pMapContainer->get_mapgen());
maze_sizeChanged(pMapContainer->get_maze_size());
@@ -241,6 +332,9 @@
}
if (param == "SEED") {
pMapContainer->setSeed(value);
+ if (!QRegExp("\\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\}").exactMatch(value)) {
+ pMapContainer->seedEdit->setVisible(true);
+ }
return;
}
if (param == "THEME") {
@@ -259,6 +353,14 @@
pMapContainer->setMaze_size(value.toUInt());
return;
}
+ if (param == "SCRIPT") {
+ Scripts->setCurrentIndex(Scripts->findText(value));
+ return;
+ }
+ if (param == "DRAWNMAP") {
+ pMapContainer->setDrawnMapData(qUncompress(QByteArray::fromBase64(slValue[0].toLatin1())));
+ return;
+ }
}
if (slValue.size() == 2)
@@ -279,32 +381,54 @@
"AMMO",
QStringList() << WeaponsName->itemText(index) << WeaponsName->itemData(index).toString()
);
- if (bindEntries->isChecked() == true) {
- QString weapName = WeaponsName->itemText(index);
- for (int i = 0; i < GameSchemes->count(); i++) {
- QString schemeName = GameSchemes->itemText(i);
- int res = QString::compare(weapName, schemeName, Qt::CaseSensitive);
- if (0 == res) {
- GameSchemes->setCurrentIndex(i);
- break;
- }
- }
- }
}
}
void GameCFGWidget::mapChanged(const QString & value)
{
- if(pMapContainer->getCurrentIsMission())
+ if(isEnabled() && pMapContainer->getCurrentIsMission())
{
- GameSchemes->setEnabled(false);
- WeaponsName->setEnabled(false);
- bindEntries->setEnabled(false);
- GameSchemes->setCurrentIndex(GameSchemes->findText("Default"));
- WeaponsName->setCurrentIndex(WeaponsName->findText("Default"));
+ Scripts->setEnabled(false);
+ Scripts->setCurrentIndex(0);
+
+ if (pMapContainer->getCurrentScheme() == "locked")
+ {
+ GameSchemes->setEnabled(false);
+ GameSchemes->setCurrentIndex(GameSchemes->findText("Default"));
+ }
+ else
+ {
+ GameSchemes->setEnabled(true);
+ int num = GameSchemes->findText(pMapContainer->getCurrentScheme());
+ if (num != -1)
+ GameSchemes->setCurrentIndex(num);
+ else
+ GameSchemes->setCurrentIndex(GameSchemes->findText("Default"));
+ }
+
+ if (pMapContainer->getCurrentWeapons() == "locked")
+ {
+ WeaponsName->setEnabled(false);
+ WeaponsName->setCurrentIndex(WeaponsName->findText("Default"));
+ }
+ else
+ {
+ WeaponsName->setEnabled(true);
+ int num = WeaponsName->findText(pMapContainer->getCurrentWeapons());
+ if (num != -1)
+ WeaponsName->setCurrentIndex(num);
+ else
+ WeaponsName->setCurrentIndex(WeaponsName->findText("Default"));
+ }
+
+ if (pMapContainer->getCurrentScheme() != "locked" && pMapContainer->getCurrentWeapons() != "locked")
+ bindEntries->setEnabled(true);
+ else
+ bindEntries->setEnabled(false);
}
else
{
+ Scripts->setEnabled(true);
GameSchemes->setEnabled(true);
WeaponsName->setEnabled(true);
bindEntries->setEnabled(true);
@@ -337,19 +461,71 @@
emit paramChanged("SCHEME", sl);
- if (bindEntries->isChecked() == true) {
+ if (isEnabled() && bindEntries->isEnabled() && bindEntries->isChecked()) {
QString schemeName = GameSchemes->itemText(index);
for (int i = 0; i < WeaponsName->count(); i++) {
QString weapName = WeaponsName->itemText(i);
int res = QString::compare(weapName, schemeName, Qt::CaseSensitive);
if (0 == res) {
WeaponsName->setCurrentIndex(i);
+ emit ammoChanged(i);
break;
}
}
}
}
+void GameCFGWidget::scriptChanged(int index)
+{
+ if(isEnabled() && index > 0)
+ {
+ QString scheme = Scripts->itemData(Scripts->currentIndex()).toList()[1].toString();
+ QString weapons = Scripts->itemData(Scripts->currentIndex()).toList()[2].toString();
+
+ if (scheme == "locked")
+ {
+ GameSchemes->setEnabled(false);
+ GameSchemes->setCurrentIndex(GameSchemes->findText("Default"));
+ }
+ else
+ {
+ GameSchemes->setEnabled(true);
+ int num = GameSchemes->findText(scheme);
+ if (num != -1)
+ GameSchemes->setCurrentIndex(num);
+ else
+ GameSchemes->setCurrentIndex(GameSchemes->findText("Default"));
+ }
+
+ if (weapons == "locked")
+ {
+ WeaponsName->setEnabled(false);
+ WeaponsName->setCurrentIndex(WeaponsName->findText("Default"));
+ }
+ else
+ {
+ WeaponsName->setEnabled(true);
+ int num = WeaponsName->findText(weapons);
+ if (num != -1)
+ WeaponsName->setCurrentIndex(num);
+ else
+ WeaponsName->setCurrentIndex(WeaponsName->findText("Default"));
+ }
+
+ if (scheme != "locked" && weapons != "locked")
+ bindEntries->setEnabled(true);
+ else
+ bindEntries->setEnabled(false);
+ }
+ else
+ {
+ GameSchemes->setEnabled(true);
+ WeaponsName->setEnabled(true);
+ bindEntries->setEnabled(true);
+ }
+ emit paramChanged("SCRIPT", QStringList(Scripts->itemText(index)));
+}
+
void GameCFGWidget::mapgenChanged(MapGenerator m)
{
emit paramChanged("MAPGEN", QStringList(QString::number(m)));
@@ -364,3 +540,8 @@
{
schemeChanged(GameSchemes->currentIndex());
}
+
+void GameCFGWidget::onDrawnMapChanged(const QByteArray & data)
+{
+ emit paramChanged("DRAWNMAP", QStringList(qCompress(data, 9).toBase64()));
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/gamecfgwidget.h
--- a/QTfrontend/gamecfgwidget.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/gamecfgwidget.h Tue Jan 04 12:53:46 2011 +0100
@@ -36,14 +36,16 @@
Q_OBJECT
public:
- GameCFGWidget(QWidget* parent, bool externalControl=false);
+ GameCFGWidget(QWidget* parent);
quint32 getGameFlags() const;
quint32 getInitHealth() const;
- QStringList getFullConfig() const;
+ QByteArray getFullConfig() const;
+ QComboBox * Scripts;
QComboBox * GameSchemes;
QComboBox * WeaponsName;
HWMapContainer* pMapContainer;
QTableView * tv;
+ QVariant schemeData(int column) const;
public slots:
void setParam(const QString & param, const QStringList & value);
@@ -52,8 +54,9 @@
signals:
void paramChanged(const QString & param, const QStringList & value);
- void goToSchemes();
- void goToWeapons(const QString & name);
+ void goToSchemes(int);
+ void goToWeapons(int);
+ void goToDrawMap();
private slots:
void ammoChanged(int index);
@@ -62,9 +65,12 @@
void seedChanged(const QString &);
void themeChanged(const QString &);
void schemeChanged(int);
+ void scriptChanged(int);
+ void jumpToSchemes();
void jumpToWeapons();
void mapgenChanged(MapGenerator m);
void maze_sizeChanged(int s);
+ void onDrawnMapChanged(const QByteArray & data);
private:
QGridLayout mainLayout;
@@ -74,7 +80,6 @@
void setNetAmmo(const QString& name, const QString& ammo);
- QVariant schemeData(int column) const;
};
#endif // GAMECONFIGWIDGET_H
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/gameuiconfig.cpp
--- a/QTfrontend/gameuiconfig.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/gameuiconfig.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -185,7 +185,7 @@
quint32 rqNoBackground = 0x00000004; // don't draw background
quint32 rqSimpleRope = 0x00000008; // avoid drawing rope
quint32 rq2DWater = 0x00000010; // disabe 3D water effect
- quint32 rqFancyBoom = 0x00000020; // no fancy explosion effects
+ quint32 rqAntiBoom = 0x00000020; // no fancy explosion effects
quint32 rqKillFlakes = 0x00000040; // no flakes
quint32 rqSlowMenu = 0x00000080; // ammomenu appears with no animation
quint32 rqPlainSplash = 0x00000100; // no droplets
@@ -206,15 +206,15 @@
break;
case 2:
result |= rqBlurryLand | rqKillFlakes | rqPlainSplash | rq2DWater |
- rqFancyBoom | rqSlowMenu;
+ rqAntiBoom | rqSlowMenu;
break;
case 1:
result |= rqBlurryLand | rqKillFlakes | rqPlainSplash | rq2DWater |
- rqFancyBoom | rqSlowMenu | rqSimpleRope | rqDesyncVBlank;
+ rqAntiBoom | rqSlowMenu | rqSimpleRope | rqDesyncVBlank;
break;
case 0:
result |= rqBlurryLand | rqKillFlakes | rqPlainSplash | rq2DWater |
- rqFancyBoom | rqSlowMenu | rqSimpleRope | rqDesyncVBlank |
+ rqAntiBoom | rqSlowMenu | rqSimpleRope | rqDesyncVBlank |
rqNoBackground | rqClampLess;
break;
default:
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hats.cpp
--- a/QTfrontend/hats.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hats.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -77,6 +77,10 @@
QVariant HatsModel::headerData(int section,
Qt::Orientation orientation, int role) const
{
+ Q_UNUSED(section);
+ Q_UNUSED(orientation);
+ Q_UNUSED(role);
+
return QVariant();
}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hedgehogerWidget.cpp
--- a/QTfrontend/hedgehogerWidget.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hedgehogerWidget.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -20,8 +20,8 @@
#include "frameTeam.h"
-CHedgehogerWidget::CHedgehogerWidget(const QImage& im, QWidget * parent) :
- ItemNum(im, parent, 1)
+CHedgehogerWidget::CHedgehogerWidget(const QImage& im, const QImage& img, QWidget * parent) :
+ ItemNum(im, img, parent, 1)
{
// TODO: maxHedgehogsPerGame doesn't reset properly and won't match map limits for now
/*if(parent) {
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hedgehogerWidget.h
--- a/QTfrontend/hedgehogerWidget.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hedgehogerWidget.h Tue Jan 04 12:53:46 2011 +0100
@@ -28,7 +28,7 @@
Q_OBJECT
public:
- CHedgehogerWidget(const QImage& im, QWidget * parent);
+ CHedgehogerWidget(const QImage& im, const QImage& img, QWidget * parent);
virtual ~CHedgehogerWidget();
unsigned char getHedgehogsNum() const;
void setHHNum (unsigned int num);
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hedgewars.qrc
--- a/QTfrontend/hedgewars.qrc Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hedgewars.qrc Tue Jan 04 12:53:46 2011 +0100
@@ -2,8 +2,15 @@
../share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png
res/hh25x25.png
+ res/hh25x25grey.png
res/ammopic.png
+ res/ammopicgrey.png
+ res/ammopicbox.png
+ res/ammopicboxgrey.png
+ res/ammopicdelay.png
+ res/ammopicdelaygrey.png
res/infinity.png
+ res/infinitygrey.png
res/botlevels/0.png
res/botlevels/1.png
res/botlevels/2.png
@@ -80,6 +87,7 @@
res/iconTime.png
res/iconMine.png
res/iconDud.png
+ res/iconRope.png
res/dice.png
res/Star.png
res/file_save.png
@@ -93,8 +101,6 @@
res/chat_default_off.png
res/chat_ignore_off.png
res/chat_friend_off.png
- res/ammopicbox.png
- res/ammopicdelay.png
res/addfriend.png
res/remfriend.png
res/ignore.png
@@ -102,6 +108,8 @@
res/follow.png
res/info.png
res/kick.png
+ res/lock.png
+ res/unlock.png
res/StatsMedal1.png
res/StatsMedal2.png
res/StatsMedal3.png
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hwconsts.cpp.in
--- a/QTfrontend/hwconsts.cpp.in Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hwconsts.cpp.in Tue Jan 04 12:53:46 2011 +0100
@@ -29,6 +29,7 @@
QStringList * Themes;
QStringList * mapList;
+QStringList * scriptList;
bool custom_config = false;
bool custom_data = false;
@@ -36,10 +37,10 @@
int cMaxTeams = 6;
QString * cDefaultAmmoStore = new QString(
- "93919294221991210322351110012010000002111101010111"
- "04050405416006555465544647765766666661555101011154"
- "00000000000002055000000400070040000000002000000006"
- "13111103121111111231141111111111111112111111011111"
+ "939192942219912103223511100120100000021111010101112"
+ "040504054160065554655446477657666666615551010111541"
+ "000000000000020550000004000700400000000020000000060"
+ "131111031211111112311411111111111111121111110111112"
);
int cAmmoNumber = cDefaultAmmoStore->size() / 4;
@@ -48,40 +49,40 @@
<< qMakePair(QString("Default"), *cDefaultAmmoStore)
<< qMakePair(QString("Crazy"), QString(
// TODO: Remove Piano's unlimited uses!
- "99999999999999999929999999999999992999999999099999"
- "11111101111111111111111111111111111111111111011111"
- "00000000000000000000000000000000000000000000000000"
- "13111103121111111231141111111111111112111101011111"
+ "999999999999999999299999999999999929999999990999999"
+ "111111011111111111111111111111111111111111110111111"
+ "000000000000000000000000000000000000000000000000000"
+ "131111031211111112311411111111111111121111010111111"
))
<< qMakePair(QString("Pro Mode"), QString(
- "90900090000000000000090000000000000000000000000000"
- "00000000000000000000000000000000000000000000000000"
- "00000000000002055000000400070040000000002000000000"
- "11111111111111111111111111111111111111111001011111"
+ "909000900000000000000900000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000"
+ "000000000000020550000004000700400000000020000000000"
+ "111111111111111111111111111111111111111110010111111"
))
<< qMakePair(QString("Shoppa"), QString(
- "00000099000000000000000000000000000000000000000000"
- "44444100442444022101121212224220000000020004000100"
- "00000000000000000000000000000000000000000000000000"
- "11111111111111111111111111111111111111111011011111"
+ "000000990000000000000000000000000000000000000000000"
+ "444441004424440221011212122242200000000200040001001"
+ "000000000000000000000000000000000000000000000000000"
+ "111111111111111111111111111111111111111110110111111"
))
<< qMakePair(QString("Clean Slate"),QString(
- "10100090000100000110000000000000000000000000000010"
- "04050405416006555465544647765766666661555101011154"
- "00000000000000000000000000000000000000000000000000"
- "13111103121111111231141111111111111112111111011111"
+ "101000900001000001100000000000000000000000000000100"
+ "040504054160065554655446477657666666615551010111541"
+ "000000000000000000000000000000000000000000000000000"
+ "131111031211111112311411111111111111121111110111111"
))
<< qMakePair(QString("Minefield"), QString(
- "00000099000900000003000000000000000000000000000000"
- "00000000000000000000000000000000000000000000000000"
- "00000000000002055000000400070040000000002000000006"
- "11111111111111111111111111111111111111111111011111"
+ "000000990009000000030000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000"
+ "000000000000020550000004000700400000000020000000060"
+ "111111111111111111111111111111111111111111110111111"
))
<< qMakePair(QString("Thinking with Portals"), QString(
- "90000090020000000021000000000000001100000900000000"
- "04050405416006555465544647765766666661555101011154"
- "00000000000002055000000400070040000000002000000006"
- "13111103121111111231141111111111111112111111011111"
+ "900000900200000000210000000000000011000009000000000"
+ "040504054160065554655446477657666666615551010111541"
+ "000000000000020550000004000700400000000020000000060"
+ "131111031211111112311411111111111111121111110111111"
));
QColor *colors[] = {
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hwconsts.h
--- a/QTfrontend/hwconsts.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hwconsts.h Tue Jan 04 12:53:46 2011 +0100
@@ -38,6 +38,7 @@
extern QStringList * Themes;
extern QStringList * mapList;
+extern QStringList * scriptList;
extern QString * cDefaultAmmoStore;
extern int cAmmoNumber;
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hwform.cpp
--- a/QTfrontend/hwform.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hwform.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include "hwform.h"
#include "game.h"
@@ -56,6 +57,7 @@
#include "ammoSchemeModel.h"
#include "bgwidget.h"
#include "xfire.h"
+#include "drawmapwidget.h"
#ifdef __APPLE__
#include "CocoaInitializer.h"
@@ -77,13 +79,14 @@
#ifdef USE_XFIRE
xfire_init();
#endif
+ game = NULL;
gameSettings = new QSettings(cfgdir->absolutePath() + "/hedgewars.ini", QSettings::IniFormat);
frontendEffects = gameSettings->value("frontend/effects", true).toBool();
playerHash = QString(QCryptographicHash::hash(gameSettings->value("net/nick","").toString().toLatin1(), QCryptographicHash::Md5).toHex());
ui.setupUi(this);
setMinimumSize(760, 580);
- setFocusPolicy(Qt::StrongFocus);
+ //setFocusPolicy(Qt::StrongFocus);
CustomizePalettes();
ui.pageOptions->CBResolution->addItems(sdli.getResolutions());
@@ -107,13 +110,23 @@
UpdateCampaignPage(0);
UpdateWeapons();
+ pageSwitchMapper = new QSignalMapper(this);
+ connect(pageSwitchMapper, SIGNAL(mapped(int)), this, SLOT(GoToPage(int)));
+
connect(config, SIGNAL(frontendFullscreen(bool)), this, SLOT(onFrontendFullscreen(bool)));
onFrontendFullscreen(config->isFrontendFullscreen());
- connect(ui.pageMain->BtnSinglePlayer, SIGNAL(clicked()), this, SLOT(GoToSinglePlayer()));
- connect(ui.pageMain->BtnSetup, SIGNAL(clicked()), this, SLOT(GoToSetup()));
- connect(ui.pageMain->BtnNet, SIGNAL(clicked()), this, SLOT(GoToNetType()));
- connect(ui.pageMain->BtnInfo, SIGNAL(clicked()), this, SLOT(GoToInfo()));
+ connect(ui.pageMain->BtnSinglePlayer, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageMain->BtnSinglePlayer, ID_PAGE_SINGLEPLAYER);
+
+ connect(ui.pageMain->BtnSetup, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageMain->BtnSetup, ID_PAGE_SETUP);
+
+ connect(ui.pageMain->BtnNet, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageMain->BtnNet, ID_PAGE_NETTYPE);
+ connect(ui.pageMain->BtnInfo, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageMain->BtnInfo, ID_PAGE_INFO);
+
connect(ui.pageMain->BtnExit, SIGNAL(pressed()), this, SLOT(btnExitPressed()));
connect(ui.pageMain->BtnExit, SIGNAL(clicked()), this, SLOT(btnExitClicked()));
@@ -127,9 +140,12 @@
connect(ui.pageMultiplayer->BtnStartMPGame, SIGNAL(clicked()), this, SLOT(StartMPGame()));
connect(ui.pageMultiplayer->teamsSelect, SIGNAL(setEnabledGameStart(bool)),
ui.pageMultiplayer->BtnStartMPGame, SLOT(setEnabled(bool)));
- connect(ui.pageMultiplayer->teamsSelect, SIGNAL(SetupClicked()), this, SLOT(IntermediateSetup()));
- connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToSchemes()), this, SLOT(GoToSchemes()));
- connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToWeapons(const QString &)), this, SLOT(GoToSelectWeaponSet(const QString &)));
+ connect(ui.pageMultiplayer, SIGNAL(SetupClicked()), this, SLOT(IntermediateSetup()));
+ connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToSchemes(int)), this, SLOT(GoToScheme(int)));
+ connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToWeapons(int)), this, SLOT(GoToSelectWeaponSet(int)));
+ connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToDrawMap()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageMultiplayer->gameCFG, ID_PAGE_DRAWMAP);
+
connect(ui.pagePlayDemo->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
connect(ui.pagePlayDemo->BtnPlayDemo, SIGNAL(clicked()), this, SLOT(PlayDemo()));
@@ -146,12 +162,18 @@
#endif
connect(ui.pageOptions->WeaponEdit, SIGNAL(clicked()), this, SLOT(GoToSelectWeapon()));
- connect(ui.pageOptions->WeaponsButt, SIGNAL(clicked()), this, SLOT(GoToSelectNewWeapon()));
+ connect(ui.pageOptions->WeaponNew, SIGNAL(clicked()), this, SLOT(GoToSelectNewWeapon()));
+ connect(ui.pageOptions->WeaponDelete, SIGNAL(clicked()), this, SLOT(DeleteWeaponSet()));
+ connect(ui.pageOptions->SchemeEdit, SIGNAL(clicked()), this, SLOT(GoToEditScheme()));
+ connect(ui.pageOptions->SchemeNew, SIGNAL(clicked()), this, SLOT(GoToNewScheme()));
+ connect(ui.pageOptions->SchemeDelete, SIGNAL(clicked()), this, SLOT(DeleteScheme()));
connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsChanged()), this, SLOT(UpdateWeapons()));
connect(ui.pageNet->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
connect(ui.pageNet->BtnSpecifyServer, SIGNAL(clicked()), this, SLOT(NetConnect()));
- connect(ui.pageNet->BtnNetSvrStart, SIGNAL(clicked()), this, SLOT(GoToNetServer()));
+ connect(ui.pageNet->BtnNetSvrStart, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageNet->BtnNetSvrStart, ID_PAGE_NETSERVER);
+
connect(ui.pageNet, SIGNAL(connectClicked(const QString &, quint16)), this, SLOT(NetConnectServer(const QString &, quint16)));
connect(ui.pageNetServer->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
@@ -162,21 +184,30 @@
ui.pageNetGame->BtnGo, SLOT(setEnabled(bool)));
connect(ui.pageNetGame->pNetTeamsWidget, SIGNAL(setEnabledGameStart(bool)),
ui.pageNetGame->BtnStart, SLOT(setEnabled(bool)));
- connect(ui.pageNetGame->pNetTeamsWidget, SIGNAL(SetupClicked()), this, SLOT(IntermediateSetup()));
- connect(ui.pageNetGame->pGameCFG, SIGNAL(goToSchemes()), this, SLOT(GoToSchemes()));
- connect(ui.pageNetGame->pGameCFG, SIGNAL(goToWeapons(const QString &)), this, SLOT(GoToSelectWeaponSet(const QString &)));
+ connect(ui.pageNetGame, SIGNAL(SetupClicked()), this, SLOT(IntermediateSetup()));
+ connect(ui.pageNetGame->pGameCFG, SIGNAL(goToSchemes(int)), this, SLOT(GoToScheme(int)));
+ connect(ui.pageNetGame->pGameCFG, SIGNAL(goToWeapons(int)), this, SLOT(GoToSelectWeaponSet(int)));
+ connect(ui.pageNetGame->pGameCFG, SIGNAL(goToDrawMap()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageNetGame->pGameCFG, ID_PAGE_DRAWMAP);
connect(ui.pageRoomsList->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
- connect(ui.pageRoomsList->BtnAdmin, SIGNAL(clicked()), this, SLOT(GoToAdmin()));
+ connect(ui.pageRoomsList->BtnAdmin, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageRoomsList->BtnAdmin, ID_PAGE_ADMIN);
connect(ui.pageInfo->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
connect(ui.pageGameStats->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
connect(ui.pageSinglePlayer->BtnSimpleGamePage, SIGNAL(clicked()), this, SLOT(SimpleGame()));
- connect(ui.pageSinglePlayer->BtnTrainPage, SIGNAL(clicked()), this, SLOT(GoToTraining()));
- connect(ui.pageSinglePlayer->BtnCampaignPage, SIGNAL(clicked()), this, SLOT(GoToCampaign()));
- connect(ui.pageSinglePlayer->BtnMultiplayer, SIGNAL(clicked()), this, SLOT(GoToMultiplayer()));
+ connect(ui.pageSinglePlayer->BtnTrainPage, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageSinglePlayer->BtnTrainPage, ID_PAGE_TRAINING);
+
+ connect(ui.pageSinglePlayer->BtnCampaignPage, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageSinglePlayer->BtnCampaignPage, ID_PAGE_CAMPAIGN);
+
+ connect(ui.pageSinglePlayer->BtnMultiplayer, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+ pageSwitchMapper->setMapping(ui.pageSinglePlayer->BtnMultiplayer, ID_PAGE_MULTIPLAYER);
+
connect(ui.pageSinglePlayer->BtnLoad, SIGNAL(clicked()), this, SLOT(GoToSaves()));
connect(ui.pageSinglePlayer->BtnDemos, SIGNAL(clicked()), this, SLOT(GoToDemos()));
connect(ui.pageSinglePlayer->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
@@ -194,8 +225,8 @@
ui.pageSelectWeapon->pWeapons, SLOT(deleteWeaponsName())); // executed first
connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsDeleted()),
this, SLOT(UpdateWeapons())); // executed second
- connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsDeleted()),
- this, SLOT(GoBack())); // executed third
+ //connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsDeleted()),
+ // this, SLOT(GoBack())); // executed third
connect(ui.pageScheme->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
@@ -205,10 +236,13 @@
connect(ui.pageNetType->BtnLAN, SIGNAL(clicked()), this, SLOT(GoToNet()));
connect(ui.pageNetType->BtnOfficialServer, SIGNAL(clicked()), this, SLOT(NetConnectOfficialServer()));
+ connect(ui.pageDrawMap->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
+
ammoSchemeModel = new AmmoSchemeModel(this, cfgdir->absolutePath() + "/schemes.ini");
ui.pageScheme->setModel(ammoSchemeModel);
ui.pageMultiplayer->gameCFG->GameSchemes->setModel(ammoSchemeModel);
+ ui.pageOptions->SchemesName->setModel(ammoSchemeModel);
wBackground = NULL;
if (config->isFrontendEffects()) {
@@ -274,11 +308,13 @@
}
}
+/*
void HWForm::keyReleaseEvent(QKeyEvent *event)
{
- if (event->key() == Qt::Key_Escape /*|| event->key() == Qt::Key_Backspace*/ )
+ if (event->key() == Qt::Key_Escape)
this->GoBack();
}
+*/
void HWForm::CustomizePalettes()
{
@@ -299,6 +335,7 @@
combos.push_back(ui.pageOptions->WeaponsName);
combos.push_back(ui.pageMultiplayer->gameCFG->WeaponsName);
combos.push_back(ui.pageNetGame->pGameCFG->WeaponsName);
+ combos.push_back(ui.pageSelectWeapon->selectWeaponSet);
QStringList names = ui.pageSelectWeapon->pWeapons->getWeaponNames();
@@ -336,59 +373,24 @@
ui.pageCampaign->CBTeam->addItems(teamslist);
}
-void HWForm::GoToMain()
-{
- GoToPage(ID_PAGE_MAIN);
-}
-
-void HWForm::GoToSinglePlayer()
-{
- GoToPage(ID_PAGE_SINGLEPLAYER);
-}
-
-void HWForm::GoToTraining()
-{
- GoToPage(ID_PAGE_TRAINING);
-}
-
-void HWForm::GoToCampaign()
-{
- GoToPage(ID_PAGE_CAMPAIGN);
-}
-
-void HWForm::GoToSetup()
-{
- GoToPage(ID_PAGE_SETUP);
-}
-
void HWForm::GoToSelectNewWeapon()
{
- ui.pageSelectWeapon->pWeapons->setWeaponsName(tr("new"));
+ ui.pageSelectWeapon->pWeapons->newWeaponsName();
GoToPage(ID_PAGE_SELECTWEAPON);
}
void HWForm::GoToSelectWeapon()
{
- ui.pageSelectWeapon->pWeapons->setWeaponsName(ui.pageOptions->WeaponsName->currentText());
+ ui.pageSelectWeapon->selectWeaponSet->setCurrentIndex(ui.pageOptions->WeaponsName->currentIndex());
GoToPage(ID_PAGE_SELECTWEAPON);
}
-void HWForm::GoToSelectWeaponSet(const QString & name)
+void HWForm::GoToSelectWeaponSet(int index)
{
- ui.pageSelectWeapon->pWeapons->setWeaponsName(name);
+ ui.pageSelectWeapon->selectWeaponSet->setCurrentIndex(index);
GoToPage(ID_PAGE_SELECTWEAPON);
}
-void HWForm::GoToInfo()
-{
- GoToPage(ID_PAGE_INFO);
-}
-
-void HWForm::GoToMultiplayer()
-{
- GoToPage(ID_PAGE_MULTIPLAYER);
-}
-
void HWForm::GoToSaves()
{
ui.pagePlayDemo->FillFromDir(PagePlayDemo::RT_Save);
@@ -410,24 +412,22 @@
GoToPage(ID_PAGE_NET);
}
-void HWForm::GoToNetType()
+void HWForm::GoToScheme(int index)
{
- GoToPage(ID_PAGE_NETTYPE);
-}
-
-void HWForm::GoToNetServer()
-{
- GoToPage(ID_PAGE_NETSERVER);
-}
-
-void HWForm::GoToSchemes()
-{
+ ui.pageScheme->selectScheme->setCurrentIndex(index);
GoToPage(ID_PAGE_SCHEME);
}
-void HWForm::GoToAdmin()
+void HWForm::GoToNewScheme()
{
- GoToPage(ID_PAGE_ADMIN);
+ ui.pageScheme->newRow();
+ GoToPage(ID_PAGE_SCHEME);
+}
+
+void HWForm::GoToEditScheme()
+{
+ ui.pageScheme->selectScheme->setCurrentIndex(ui.pageOptions->SchemesName->currentIndex());
+ GoToPage(ID_PAGE_SCHEME);
}
void HWForm::OnPageShown(quint8 id, quint8 lastid)
@@ -435,6 +435,24 @@
#ifdef USE_XFIRE
updateXfire();
#endif
+ if(id == ID_PAGE_DRAWMAP)
+ {
+ DrawMapScene * scene;
+ if(lastid == ID_PAGE_MULTIPLAYER)
+ scene = ui.pageMultiplayer->gameCFG->pMapContainer->getDrawMapScene();
+ else
+ scene = ui.pageNetGame->pGameCFG->pMapContainer->getDrawMapScene();
+
+ ui.pageDrawMap->drawMapWidget->setScene(scene);
+ }
+ if(lastid == ID_PAGE_DRAWMAP)
+ {
+ if(id == ID_PAGE_MULTIPLAYER)
+ ui.pageMultiplayer->gameCFG->pMapContainer->mapDrawingFinished();
+ else
+ ui.pageNetGame->pGameCFG->pMapContainer->mapDrawingFinished();
+ }
+
if (id == ID_PAGE_MULTIPLAYER || id == ID_PAGE_NETGAME) {
QStringList tmNames = config->GetTeamsList();
TeamSelWidget* curTeamSelWidget;
@@ -457,7 +475,7 @@
teamsList.push_back(team);
}
- if(lastid == ID_PAGE_SETUP) { // _TEAM
+ if(lastid == ID_PAGE_SETUP || lastid == ID_PAGE_DRAWMAP) { // _TEAM
if (editedTeam) {
curTeamSelWidget->addTeam(*editedTeam);
}
@@ -490,13 +508,19 @@
if(id == ID_PAGE_NETGAME) // joining a room
ui.pageNetGame->pChatWidget->loadLists(ui.pageOptions->editNetNick->text());
- else if(id == ID_PAGE_ROOMSLIST) // joining the lobby
+// joining the lobby
+ else if(id == ID_PAGE_ROOMSLIST) {
+ if ( hwnet && game && game->gameState == gsStarted) { // abnormal exit - kick or room destruction - send kills.
+ game->netSuspend = true;
+ game->KillAllTeams();
+ }
ui.pageRoomsList->chatWidget->loadLists(ui.pageOptions->editNetNick->text());
+ }
}
-void HWForm::GoToPage(quint8 id)
+void HWForm::GoToPage(int id)
{
- quint8 lastid = ui.Pages->currentIndex();
+ int lastid = ui.Pages->currentIndex();
PagesStack.push(ui.Pages->currentIndex());
OnPageShown(id, lastid);
ui.Pages->setCurrentIndex(id);
@@ -504,8 +528,8 @@
void HWForm::GoBack()
{
- quint8 id = PagesStack.isEmpty() ? ID_PAGE_MAIN : PagesStack.pop();
- quint8 curid = ui.Pages->currentIndex();
+ int id = PagesStack.isEmpty() ? ID_PAGE_MAIN : PagesStack.pop();
+ int curid = ui.Pages->currentIndex();
ui.Pages->setCurrentIndex(id);
OnPageShown(id, curid);
@@ -521,6 +545,9 @@
GoBack();
if (curid == ID_PAGE_ROOMSLIST) NetDisconnect();
+ if (curid == ID_PAGE_NETGAME) hwnet->partRoom();
+ // need to work on this, can cause invalid state for admin quit trying to prevent bad state message on kick
+ //if (curid == ID_PAGE_NETGAME && (!game || game->gameState != gsStarted)) hwnet->partRoom();
if (curid == ID_PAGE_SCHEME)
ammoSchemeModel->Save();
@@ -588,11 +615,15 @@
void HWForm::DeleteTeam()
{
- editedTeam = new HWTeam(ui.pageOptions->CBTeamName->currentText());
- editedTeam->DeleteFile();
+ QMessageBox reallyDelete(QMessageBox::Question, QMessageBox::tr("Teams"), QMessageBox::tr("Really delete this team?"), QMessageBox::Ok | QMessageBox::Cancel);
- // Remove from lists
- ui.pageOptions->CBTeamName->removeItem(ui.pageOptions->CBTeamName->currentIndex());
+ if (reallyDelete.exec() == QMessageBox::Ok) {
+ editedTeam = new HWTeam(ui.pageOptions->CBTeamName->currentText());
+ editedTeam->DeleteFile();
+
+ // Remove from lists
+ ui.pageOptions->CBTeamName->removeItem(ui.pageOptions->CBTeamName->currentIndex());
+ }
}
void HWForm::RandomNames()
@@ -626,6 +657,23 @@
GoBack();
}
+void HWForm::DeleteScheme()
+{
+ ui.pageScheme->selectScheme->setCurrentIndex(ui.pageOptions->SchemesName->currentIndex());
+ if (ui.pageOptions->SchemesName->currentIndex() < ammoSchemeModel->numberOfDefaultSchemes) {
+ QMessageBox::warning(0, QMessageBox::tr("Schemes"), QMessageBox::tr("Can not delete default scheme '%1'!").arg(ui.pageOptions->SchemesName->currentText()));
+ } else {
+ ui.pageScheme->deleteRow();
+ ammoSchemeModel->Save();
+ }
+}
+
+void HWForm::DeleteWeaponSet()
+{
+ ui.pageSelectWeapon->selectWeaponSet->setCurrentIndex(ui.pageOptions->WeaponsName->currentIndex());
+ ui.pageSelectWeapon->pWeapons->deleteWeaponsName();
+}
+
void HWForm::SimpleGame()
{
CreateGame(0, 0, *cDefaultAmmoStore);
@@ -678,7 +726,7 @@
connect(hwnet, SIGNAL(EnteredGame()), this, SLOT(NetGameEnter()));
connect(hwnet, SIGNAL(LeftRoom()), this, SLOT(NetLeftRoom()));
connect(hwnet, SIGNAL(AddNetTeam(const HWTeam&)), this, SLOT(AddNetTeam(const HWTeam&)));
- connect(ui.pageNetGame->BtnBack, SIGNAL(clicked()), hwnet, SLOT(partRoom()));
+ //connect(ui.pageNetGame->BtnBack, SIGNAL(clicked()), hwnet, SLOT(partRoom()));
// rooms list page stuff
connect(hwnet, SIGNAL(roomsList(const QStringList&)),
@@ -830,7 +878,6 @@
void HWForm::NetDisconnect()
{
- //qDebug("NetDisconnect");
if(hwnet) {
hwnet->Disconnect();
delete hwnet;
@@ -853,8 +900,9 @@
{
if(pnetserver) return; // we have server - let it care of all things
if (hwnet) {
- hwnet->deleteLater();
+ HWNewNet * tmp = hwnet;
hwnet = 0;
+ tmp->deleteLater();
QMessageBox::warning(this, QMessageBox::tr("Network"),
QMessageBox::tr("Connection to server is lost"));
@@ -892,11 +940,12 @@
void HWForm::GameStateChanged(GameState gameState)
{
+ quint8 id = ui.Pages->currentIndex();
switch(gameState) {
case gsStarted: {
Music(false);
if (wBackground) wBackground->stopAnimation();
- GoToPage(ID_PAGE_INGAME);
+ if (!hwnet || (!hwnet->isRoomChief() || !hwnet->isInRoom())) GoToPage(ID_PAGE_INGAME);
ui.pageGameStats->clear();
if (pRegisterServer)
{
@@ -910,19 +959,23 @@
case gsFinished: {
//setVisible(true);
setFocusPolicy(Qt::StrongFocus);
- GoBack();
+ if (id == ID_PAGE_INGAME) GoBack();
Music(ui.pageOptions->CBEnableFrontendMusic->isChecked());
if (wBackground) wBackground->startAnimation();
GoToPage(ID_PAGE_GAMESTATS);
- if (hwnet) hwnet->gameFinished();
+ if (hwnet && (!game || !game->netSuspend)) hwnet->gameFinished();
+ if (game) game->netSuspend = false;
break;
}
default: {
//setVisible(true);
setFocusPolicy(Qt::StrongFocus);
quint8 id = ui.Pages->currentIndex();
- if (id == ID_PAGE_INGAME) {
- GoBack();
+ if (id == ID_PAGE_INGAME ||
+// was room chief and the game was aborted
+ (hwnet && hwnet->isRoomChief() && hwnet->isInRoom() &&
+ (gameState == gsInterrupted || gameState == gsStopped || gameState == gsDestroyed))) {
+ if (id == ID_PAGE_INGAME) GoBack();
Music(ui.pageOptions->CBEnableFrontendMusic->isChecked());
if (wBackground) wBackground->startAnimation();
if (hwnet) hwnet->gameFinished();
@@ -1089,7 +1142,7 @@
void HWForm::NetLeftRoom()
{
- if (ui.Pages->currentIndex() == ID_PAGE_NETGAME)
+ if (ui.Pages->currentIndex() == ID_PAGE_NETGAME || ui.Pages->currentIndex() == ID_PAGE_INGAME)
GoBack();
else
qWarning("Left room while not in room");
@@ -1107,6 +1160,8 @@
void HWForm::UpdateCampaignPage(int index)
{
+ Q_UNUSED(index);
+
HWTeam team(ui.pageCampaign->CBTeam->currentText());
ui.pageCampaign->CBSelect->clear();
@@ -1117,7 +1172,7 @@
QStringList entries = tmpdir.entryList(QStringList("*#*.lua"));
//entries.sort();
for(int i = 0; (i < entries.count()) && (i <= team.CampaignProgress); i++)
- ui.pageCampaign->CBSelect->addItem(QString(entries[i]).replace(QRegExp("^(\\d+)#(.+)\\.lua"), QComboBox::tr("Mission") + " \\1: \\2"), QString(entries[i]).replace(QRegExp("^(.*)\\.lua"), "\\1"));
+ ui.pageCampaign->CBSelect->addItem(QString(entries[i]).replace(QRegExp("^(\\d+)#(.+)\\.lua"), QComboBox::tr("Mission") + " \\1: \\2").replace("_", " "), QString(entries[i]).replace(QRegExp("^(.*)\\.lua"), "\\1"));
}
void HWForm::AssociateFiles()
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hwform.h
--- a/QTfrontend/hwform.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hwform.h Tue Jan 04 12:53:46 2011 +0100
@@ -42,6 +42,7 @@
class QCloseEvent;
class AmmoSchemeModel;
class QSettings;
+class QSignalMapper;
extern bool frontendEffects;
extern QString playerHash;
@@ -59,24 +60,16 @@
void updateXfire();
private slots:
- void GoToMain();
- void GoToSinglePlayer();
- void GoToSetup();
- void GoToMultiplayer();
void GoToSaves();
void GoToDemos();
void GoToNet();
- void GoToNetType();
- void GoToInfo();
- void GoToTraining();
- void GoToCampaign();
void GoToSelectWeapon();
- void GoToSelectWeaponSet(const QString & name);
+ void GoToSelectWeaponSet(int index);
void GoToSelectNewWeapon();
- void GoToNetServer();
- void GoToSchemes();
- void GoToAdmin();
- void GoToPage(quint8 id);
+ void GoToScheme(int index);
+ void GoToEditScheme();
+ void GoToNewScheme();
+ void GoToPage(int id);
void GoBack();
void AssociateFiles();
void btnExitPressed();
@@ -89,6 +82,8 @@
void RandomName(const int &i);
void TeamSave();
void TeamDiscard();
+ void DeleteScheme();
+ void DeleteWeaponSet();
void SimpleGame();
void PlayDemo();
void StartTraining();
@@ -127,7 +122,7 @@
void closeEvent(QCloseEvent *event);
void CustomizePalettes();
void resizeEvent(QResizeEvent * event);
- void keyReleaseEvent(QKeyEvent *event);
+ //void keyReleaseEvent(QKeyEvent *event);
enum PageIDs {
ID_PAGE_SETUP_TEAM = 0,
@@ -149,7 +144,8 @@
ID_PAGE_SCHEME = 16,
ID_PAGE_ADMIN = 17,
ID_PAGE_NETTYPE = 18,
- ID_PAGE_CAMPAIGN = 19
+ ID_PAGE_CAMPAIGN = 19,
+ ID_PAGE_DRAWMAP = 20
};
HWGame * game;
HWNetServer* pnetserver;
@@ -158,9 +154,10 @@
HWNewNet * hwnet;
HWNamegen * namegen;
AmmoSchemeModel * ammoSchemeModel;
- QStack PagesStack;
+ QStack PagesStack;
QTime eggTimer;
BGWidget * wBackground;
+ QSignalMapper * pageSwitchMapper;
#ifdef __APPLE__
InstallController * panel;
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hwmap.cpp
--- a/QTfrontend/hwmap.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hwmap.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -27,12 +27,13 @@
{
}
-void HWMap::getImage(std::string seed, int filter, MapGenerator mapgen, int maze_size)
+void HWMap::getImage(const QString & seed, int filter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData)
{
m_seed = seed;
templateFilter = filter;
m_mapgen = mapgen;
m_maze_size = maze_size;
+ if(mapgen == MAPGEN_DRAWN) m_drawMapData = drawMapData;
Start();
}
@@ -59,9 +60,30 @@
void HWMap::SendToClientFirst()
{
- SendIPC(QString("eseed %1").arg(m_seed.c_str()).toLatin1());
- SendIPC(QString("e$template_filter %1").arg(templateFilter).toLatin1());
- SendIPC(QString("e$mapgen %1").arg(m_mapgen).toLatin1());
- SendIPC(QString("e$maze_size %1").arg(m_maze_size).toLatin1());
+ SendIPC(QString("eseed %1").arg(m_seed).toUtf8());
+ SendIPC(QString("e$template_filter %1").arg(templateFilter).toUtf8());
+ SendIPC(QString("e$mapgen %1").arg(m_mapgen).toUtf8());
+
+ switch (m_mapgen)
+ {
+ case MAPGEN_MAZE:
+ SendIPC(QString("e$maze_size %1").arg(m_maze_size).toUtf8());
+ break;
+
+ case MAPGEN_DRAWN:
+ {
+ QByteArray data = m_drawMapData;
+ while(data.size() > 0)
+ {
+ QByteArray tmp = data;
+ tmp.truncate(200);
+ SendIPC("edraw " + tmp);
+ data.remove(0, 200);
+ }
+ break;
+ }
+ default: ;
+ }
+
SendIPC("!");
}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/hwmap.h
--- a/QTfrontend/hwmap.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/hwmap.h Tue Jan 04 12:53:46 2011 +0100
@@ -25,12 +25,12 @@
#include "tcpBase.h"
-#include
-
enum MapGenerator
{
MAPGEN_REGULAR,
MAPGEN_MAZE,
+ MAPGEN_DRAWN,
+ MAPGEN_MAP
};
class HWMap : public TCPBase
@@ -40,7 +40,7 @@
public:
HWMap();
virtual ~HWMap();
- void getImage(std::string seed, int templateFilter, MapGenerator mapgen, int maze_size);
+ void getImage(const QString & seed, int templateFilter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData);
protected:
virtual QStringList setArguments();
@@ -52,10 +52,11 @@
void HHLimitReceived(int hhLimit);
private:
- std::string m_seed;
+ QString m_seed;
int templateFilter;
MapGenerator m_mapgen;
int m_maze_size;
+ QByteArray m_drawMapData;
private slots:
};
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/igbox.cpp
--- a/QTfrontend/igbox.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/igbox.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -24,6 +24,7 @@
#include "igbox.h"
IconedGroupBox::IconedGroupBox(QWidget * parent)
+ : QGroupBox(parent)
{
// Has issues with border-radius on children
// setAttribute(Qt::WA_PaintOnScreen, true);
@@ -56,6 +57,8 @@
void IconedGroupBox::paintEvent(QPaintEvent * event)
{
+ Q_UNUSED(event);
+
QStylePainter painter(this);
QStyleOptionGroupBox option;
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/itemNum.cpp
--- a/QTfrontend/itemNum.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/itemNum.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -22,10 +22,11 @@
#include
#include
-ItemNum::ItemNum(const QImage& im, QWidget * parent, unsigned char min, unsigned char max) :
- QFrame(parent), m_im(im), infinityState(false), nonInteractive(false), minItems(min), maxItems(max),
+ItemNum::ItemNum(const QImage& im, const QImage& img, QWidget * parent, unsigned char min, unsigned char max) :
+ QFrame(parent), m_im(im), m_img(img), infinityState(false), nonInteractive(false), minItems(min), maxItems(max),
numItems(min+2 >= max ? min : min+2)
{
+ enabled = true;
if(frontendEffects) setAttribute(Qt::WA_PaintOnScreen, true);
}
@@ -36,7 +37,7 @@
void ItemNum::mousePressEvent ( QMouseEvent * event )
{
if(nonInteractive) return;
- if(event->button()==Qt::LeftButton) {
+ if(event->button()==Qt::LeftButton && enabled) {
event->accept();
if((infinityState && numItems <= maxItems) || (!infinityState && numItems < maxItems)) {
incItems();
@@ -45,7 +46,7 @@
// appears there's an emit in there
decItems();
}
- } else if (event->button()==Qt::RightButton) {
+ } else if (event->button()==Qt::RightButton && enabled) {
event->accept();
if(numItems > minItems) {
decItems();
@@ -67,15 +68,25 @@
void ItemNum::paintEvent(QPaintEvent* event)
{
+ Q_UNUSED(event);
+
QPainter painter(this);
if (numItems==maxItems+1) {
QRect target(0, 0, 100, 32);
- painter.drawImage(target, QImage(":/res/infinity.png"));
+ if (enabled) {
+ painter.drawImage(target, QImage(":/res/infinity.png"));
+ } else {
+ painter.drawImage(target, QImage(":/res/infinitygrey.png"));
+ }
} else {
for(int i=0; iabsolutePath());
+ tmpdir.cd("Scripts/Multiplayer");
+ tmpdir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
+ scriptList = new QStringList(tmpdir.entryList(QStringList("*.lua")));
+
QTranslator Translator;
{
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/mapContainer.cpp
--- a/QTfrontend/mapContainer.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/mapContainer.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -29,6 +29,8 @@
#include
#include
#include
+#include
+#include
#include "hwconsts.h"
#include "mapContainer.h"
@@ -38,8 +40,7 @@
QWidget(parent),
mainLayout(this),
pMap(0),
- mapgen(MAPGEN_REGULAR),
- maze_size(0)
+ mapgen(MAPGEN_REGULAR)
{
hhSmall.load(":/res/hh_small.png");
hhLimit = 18;
@@ -50,17 +51,23 @@
QApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
QApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
- imageButt = new QPushButton(this);
+ QWidget* mapWidget = new QWidget(this);
+ mainLayout.addWidget(mapWidget, 0, 0, Qt::AlignHCenter);
+
+ QGridLayout* mapLayout = new QGridLayout(mapWidget);
+ mapLayout->setMargin(0);
+
+ imageButt = new QPushButton(mapWidget);
imageButt->setObjectName("imageButt");
imageButt->setFixedSize(256 + 6, 128 + 6);
imageButt->setFlat(true);
imageButt->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);//QSizePolicy::Minimum, QSizePolicy::Minimum);
- mainLayout.addWidget(imageButt, 0, 0, 1, 2);
+ mapLayout->addWidget(imageButt, 0, 0, 1, 2);
//connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomSeed()));
//connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomTheme()));
connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomMap()));
- chooseMap = new QComboBox(this);
+ chooseMap = new QComboBox(mapWidget);
chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
chooseMap->addItem(
// FIXME - need real icons. Disabling until then
@@ -70,6 +77,10 @@
// FIXME - need real icons. Disabling until then
//QIcon(":/res/mapMaze.png"),
QComboBox::tr("generated maze..."));
+
+ chooseMap->addItem(QComboBox::tr("hand drawn map..."));
+ chooseMap->insertSeparator(chooseMap->count()); // separator between generators and missions
+
chooseMap->insertSeparator(chooseMap->count()); // separator between generators and missions
int missionindex = chooseMap->count();
@@ -88,10 +99,14 @@
if (mapCfgFile.open(QFile::ReadOnly)) {
QString theme;
quint32 limit = 0;
+ QString scheme;
+ QString weapons;
QList mapInfo;
QTextStream input(&mapCfgFile);
input >> theme;
input >> limit;
+ input >> scheme;
+ input >> weapons;
mapInfo.push_back(map);
mapInfo.push_back(theme);
if (limit)
@@ -99,6 +114,14 @@
else
mapInfo.push_back(18);
mapInfo.push_back(mapLuaFile.exists());
+ if (scheme.isEmpty())
+ scheme = "locked";
+ scheme.replace("_", " ");
+ if (weapons.isEmpty())
+ weapons = "locked";
+ weapons.replace("_", " ");
+ mapInfo.push_back(scheme);
+ mapInfo.push_back(weapons);
if(mapLuaFile.exists())
{
chooseMap->insertItem(missionindex++,
@@ -118,29 +141,29 @@
chooseMap->insertSeparator(missionindex); // separator between missions and maps
connect(chooseMap, SIGNAL(currentIndexChanged(int)), this, SLOT(mapChanged(int)));
- mainLayout.addWidget(chooseMap, 1, 1);
+ mapLayout->addWidget(chooseMap, 1, 1);
- QLabel * lblMap = new QLabel(tr("Map"), this);
- mainLayout.addWidget(lblMap, 1, 0);
+ QLabel * lblMap = new QLabel(tr("Map"), mapWidget);
+ mapLayout->addWidget(lblMap, 1, 0);
- lblFilter = new QLabel(tr("Filter"), this);
- mainLayout.addWidget(lblFilter, 2, 0);
+ lblFilter = new QLabel(tr("Filter"), mapWidget);
+ mapLayout->addWidget(lblFilter, 2, 0);
- CB_TemplateFilter = new QComboBox(this);
+ CB_TemplateFilter = new QComboBox(mapWidget);
CB_TemplateFilter->addItem(tr("All"), 0);
CB_TemplateFilter->addItem(tr("Small"), 1);
CB_TemplateFilter->addItem(tr("Medium"), 2);
CB_TemplateFilter->addItem(tr("Large"), 3);
CB_TemplateFilter->addItem(tr("Cavern"), 4);
CB_TemplateFilter->addItem(tr("Wacky"), 5);
- mainLayout.addWidget(CB_TemplateFilter, 2, 1);
+ mapLayout->addWidget(CB_TemplateFilter, 2, 1);
connect(CB_TemplateFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(templateFilterChanged(int)));
- maze_size_label = new QLabel(tr("Type"), this);
+ maze_size_label = new QLabel(tr("Type"), mapWidget);
mainLayout.addWidget(maze_size_label, 2, 0);
maze_size_label->hide();
- maze_size_selection = new QComboBox(this);
+ maze_size_selection = new QComboBox(mapWidget);
maze_size_selection->addItem(tr("Small tunnels"), 0);
maze_size_selection->addItem(tr("Medium tunnels"), 1);
maze_size_selection->addItem(tr("Large tunnels"), 2);
@@ -148,23 +171,23 @@
maze_size_selection->addItem(tr("Medium floating islands"), 4);
maze_size_selection->addItem(tr("Large floating islands"), 5);
maze_size_selection->setCurrentIndex(1);
- maze_size = 1;
- mainLayout.addWidget(maze_size_selection, 2, 1);
+
+ mapLayout->addWidget(maze_size_selection, 2, 1);
maze_size_selection->hide();
connect(maze_size_selection, SIGNAL(currentIndexChanged(int)), this, SLOT(setMaze_size(int)));
- gbThemes = new IconedGroupBox(this);
- gbThemes->setTitleTextPadding(60);
- gbThemes->setContentTopPadding(6);
+ gbThemes = new IconedGroupBox(mapWidget);
+ gbThemes->setTitleTextPadding(80);
+ gbThemes->setContentTopPadding(15);
gbThemes->setTitle(tr("Themes"));
//gbThemes->setStyleSheet("padding: 0px"); // doesn't work - stylesheet is set with icon
- mainLayout.addWidget(gbThemes, 0, 2, 3, 1);
+ mapLayout->addWidget(gbThemes, 0, 2, 3, 1);
QVBoxLayout * gbTLayout = new QVBoxLayout(gbThemes);
gbTLayout->setContentsMargins(0, 0, 0 ,0);
gbTLayout->setSpacing(0);
- lwThemes = new QListWidget(this);
+ lwThemes = new QListWidget(mapWidget);
lwThemes->setMinimumHeight(30);
lwThemes->setFixedWidth(140);
for (int i = 0; i < Themes->size(); ++i) {
@@ -193,7 +216,29 @@
gbTLayout->addWidget(lwThemes);
lwThemes->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
- mainLayout.setSizeConstraint(QLayout::SetFixedSize);//SetMinimumSize
+ mapLayout->setSizeConstraint(QLayout::SetFixedSize);
+
+ QWidget* seedWidget = new QWidget(this);
+ mainLayout.addWidget(seedWidget, 1, 0);
+
+ QGridLayout* seedLayout = new QGridLayout(seedWidget);
+ seedLayout->setMargin(0);
+
+ seedLabel = new QLabel(tr("Seed"), seedWidget);
+ seedLayout->addWidget(seedLabel, 3, 0);
+ seedEdit = new QLineEdit(seedWidget);
+ seedEdit->setMaxLength(54);
+ connect(seedEdit, SIGNAL(returnPressed()), this, SLOT(seedEdited()));
+ seedLayout->addWidget(seedEdit, 3, 1);
+ seedLayout->setColumnStretch(1, 5);
+ seedSet = new QPushButton(seedWidget);
+ seedSet->setText(QPushButton::tr("more"));
+ connect(seedSet, SIGNAL(clicked()), this, SLOT(seedEdited()));
+ seedLayout->setColumnStretch(2, 1);
+ seedLayout->addWidget(seedSet, 3, 2);
+
+ seedLabel->setVisible(false);
+ seedEdit->setVisible(false);
setRandomSeed();
setRandomTheme();
@@ -216,7 +261,7 @@
p.drawPixmap(QPoint(0, 0), px);
addInfoToPreview(pxres);
- chooseMap->setCurrentIndex(mapgen);
+ //chooseMap->setCurrentIndex(mapgen);
pMap = 0;
}
@@ -230,7 +275,7 @@
switch(index) {
case MAPGEN_REGULAR:
mapgen = MAPGEN_REGULAR;
- changeImage();
+ updatePreview();
gbThemes->show();
lblFilter->show();
CB_TemplateFilter->show();
@@ -242,7 +287,7 @@
break;
case MAPGEN_MAZE:
mapgen = MAPGEN_MAZE;
- changeImage();
+ updatePreview();
gbThemes->show();
lblFilter->hide();
CB_TemplateFilter->hide();
@@ -252,8 +297,20 @@
emit mapgenChanged(mapgen);
emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
break;
+ case MAPGEN_DRAWN:
+ mapgen = MAPGEN_DRAWN;
+ updatePreview();
+ gbThemes->show();
+ lblFilter->hide();
+ CB_TemplateFilter->hide();
+ maze_size_label->hide();
+ maze_size_selection->hide();
+ emit mapChanged("+drawn+");
+ emit mapgenChanged(mapgen);
+ emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
+ break;
default:
- loadMap(index);
+ updatePreview();
gbThemes->hide();
lblFilter->hide();
CB_TemplateFilter->hide();
@@ -263,19 +320,6 @@
}
}
-void HWMapContainer::loadMap(int index)
-{
- QPixmap mapImage;
- if(!mapImage.load(datadir->absolutePath() + "/Maps/" + chooseMap->itemData(index).toList()[0].toString() + "/preview.png")) {
- changeImage();
- chooseMap->setCurrentIndex(0);
- return;
- }
-
- hhLimit = chooseMap->itemData(index).toList()[2].toInt();
- addInfoToPreview(mapImage);
-}
-
// Should this add text to identify map size?
void HWMapContainer::addInfoToPreview(QPixmap image)
{
@@ -296,7 +340,7 @@
imageButt->setIconSize(image.size());
}
-void HWMapContainer::changeImage()
+void HWMapContainer::askForGeneratedPreview()
{
if (pMap)
{
@@ -308,25 +352,28 @@
pMap = new HWMap();
connect(pMap, SIGNAL(ImageReceived(const QImage)), this, SLOT(setImage(const QImage)));
connect(pMap, SIGNAL(HHLimitReceived(int)), this, SLOT(setHHLimit(int)));
- pMap->getImage(m_seed.toStdString(), getTemplateFilter(), mapgen, maze_size);
+ pMap->getImage(m_seed,
+ getTemplateFilter(),
+ get_mapgen(),
+ get_maze_size(),
+ getDrawnMapData()
+ );
}
void HWMapContainer::themeSelected(int currentRow)
{
QString theme = Themes->at(currentRow);
- QList mapInfoRegular;
- mapInfoRegular.push_back(QString("+rnd+"));
- mapInfoRegular.push_back(theme);
- mapInfoRegular.push_back(18);
- mapInfoRegular.push_back(false);
- chooseMap->setItemData(0, mapInfoRegular);
- QList mapInfoMaze;
- mapInfoMaze.push_back(QString("+maze+"));
- mapInfoMaze.push_back(theme);
- mapInfoMaze.push_back(18);
- mapInfoMaze.push_back(false);
- chooseMap->setItemData(1, mapInfoMaze);
- gbThemes->setIcon(QIcon(QString("%1/Themes/%2/icon.png").arg(datadir->absolutePath()).arg(theme)));
+ QList mapInfo;
+ mapInfo.push_back(QString("+rnd+"));
+ mapInfo.push_back(theme);
+ mapInfo.push_back(18);
+ mapInfo.push_back(false);
+ chooseMap->setItemData(0, mapInfo);
+ mapInfo[0] = QString("+maze+");
+ chooseMap->setItemData(1, mapInfo);
+ mapInfo[0] = QString("+drawn+");
+ chooseMap->setItemData(2, mapInfo);
+ gbThemes->setIcon(QIcon(QString("%1/Themes/%2/icon@2x.png").arg(datadir->absolutePath()).arg(theme)));
emit themeChanged(theme);
}
@@ -337,7 +384,7 @@
QString HWMapContainer::getCurrentMap() const
{
- if(chooseMap->currentIndex() <= 1) return QString();
+ if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
return chooseMap->itemData(chooseMap->currentIndex()).toList()[0].toString();
}
@@ -357,6 +404,16 @@
return hhLimit;
}
+QString HWMapContainer::getCurrentScheme() const
+{
+ return chooseMap->itemData(chooseMap->currentIndex()).toList()[4].toString();
+}
+
+QString HWMapContainer::getCurrentWeapons() const
+{
+ return chooseMap->itemData(chooseMap->currentIndex()).toList()[5].toString();
+}
+
quint32 HWMapContainer::getTemplateFilter() const
{
return CB_TemplateFilter->itemData(CB_TemplateFilter->currentIndex()).toInt();
@@ -364,23 +421,21 @@
void HWMapContainer::resizeEvent ( QResizeEvent * event )
{
+ Q_UNUSED(event);
//imageButt->setIconSize(imageButt->size());
}
void HWMapContainer::setSeed(const QString & seed)
{
m_seed = seed;
- changeImage();
+ if (seed != seedEdit->text())
+ seedEdit->setText(seed);
+ if (chooseMap->currentIndex() < MAPGEN_MAP)
+ updatePreview();
}
void HWMapContainer::setMap(const QString & map)
{
- if(map == "+rnd+" || map == "+maze+")
- {
- changeImage();
- return;
- }
-
int id = 0;
for(int i = 0; i < chooseMap->count(); i++)
if(!chooseMap->itemData(i).isNull() && chooseMap->itemData(i).toList()[0].toString() == map)
@@ -397,7 +452,7 @@
pMap = 0;
}
chooseMap->setCurrentIndex(id);
- loadMap(id);
+ updatePreview();
}
}
@@ -407,18 +462,21 @@
if(items.size())
lwThemes->setCurrentItem(items.at(0));
}
-#include
+
void HWMapContainer::setRandomMap()
{
+ setRandomSeed();
switch(chooseMap->currentIndex())
{
case MAPGEN_REGULAR:
case MAPGEN_MAZE:
- setRandomSeed();
setRandomTheme();
break;
+ case MAPGEN_DRAWN:
+ emit drawMapRequested();
+ break;
default:
- if(chooseMap->currentIndex() < numMissions + 3)
+ if(chooseMap->currentIndex() <= numMissions + MAPGEN_MAP + 1)
setRandomMission();
else
setRandomStatic();
@@ -428,21 +486,26 @@
void HWMapContainer::setRandomStatic()
{
- chooseMap->setCurrentIndex(4 + numMissions + rand() % (chooseMap->count() - 4 - numMissions));
- m_seed = QUuid::createUuid().toString();
+ int i = MAPGEN_MAP + 3 + numMissions + rand() % (chooseMap->count() - MAPGEN_MAP - 3 - numMissions);
+ chooseMap->setCurrentIndex(i);
+ setRandomSeed();
}
void HWMapContainer::setRandomMission()
{
- chooseMap->setCurrentIndex(3 + rand() % numMissions);
- m_seed = QUuid::createUuid().toString();
+ int i = MAPGEN_MAP + 2 + rand() % numMissions;
+ qDebug() << i << MAPGEN_MAP << numMissions;
+ chooseMap->setCurrentIndex(i);
+ setRandomSeed();
}
void HWMapContainer::setRandomSeed()
{
m_seed = QUuid::createUuid().toString();
+ seedEdit->setText(m_seed);
emit seedChanged(m_seed);
- changeImage();
+ if (chooseMap->currentIndex() < MAPGEN_MAP)
+ updatePreview();
}
void HWMapContainer::setRandomTheme()
@@ -460,7 +523,7 @@
void HWMapContainer::templateFilterChanged(int filter)
{
emit newTemplateFilter(filter);
- changeImage();
+ updatePreview();
}
MapGenerator HWMapContainer::get_mapgen(void) const
@@ -470,20 +533,90 @@
int HWMapContainer::get_maze_size(void) const
{
- return maze_size;
+ return maze_size_selection->currentIndex();
}
void HWMapContainer::setMaze_size(int size)
{
- maze_size = size;
maze_size_selection->setCurrentIndex(size);
emit maze_sizeChanged(size);
- changeImage();
+ updatePreview();
}
void HWMapContainer::setMapgen(MapGenerator m)
{
mapgen = m;
+ chooseMap->setCurrentIndex(m);
emit mapgenChanged(m);
- changeImage();
+ updatePreview();
+}
+
+void HWMapContainer::setDrawnMapData(const QByteArray & ar)
+{
+ drawMapScene.decode(ar);
+ updatePreview();
+}
+
+QByteArray HWMapContainer::getDrawnMapData()
+{
+ return drawMapScene.encode();
+}
+
+void HWMapContainer::seedEdited()
+{
+ if (seedLabel->isVisible() == false )
+ {
+ seedLabel->setVisible(true);
+ seedEdit->setVisible(true);
+ seedSet->setText(tr("Set"));
+ return;
+ }
+
+ if (seedEdit->text().isEmpty())
+ seedEdit->setText(m_seed);
+ else
+ {
+ setSeed(seedEdit->text());
+ emit seedChanged(seedEdit->text());
+ }
}
+
+DrawMapScene * HWMapContainer::getDrawMapScene()
+{
+ return &drawMapScene;
+}
+
+void HWMapContainer::mapDrawingFinished()
+{
+ emit drawnMapChanged(getDrawnMapData());
+
+ updatePreview();
+}
+
+void HWMapContainer::updatePreview()
+{
+ int curIndex = chooseMap->currentIndex();
+
+ switch(curIndex)
+ {
+ case MAPGEN_REGULAR:
+ askForGeneratedPreview();
+ break;
+ case MAPGEN_MAZE:
+ askForGeneratedPreview();
+ break;
+ case MAPGEN_DRAWN:
+ askForGeneratedPreview();
+ break;
+ default:
+ QPixmap mapImage;
+ qDebug() << "Map data" << curIndex << chooseMap->currentText() << chooseMap->itemData(curIndex);
+ if(!mapImage.load(datadir->absolutePath() + "/Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png")) {
+ imageButt->setIcon(QIcon());
+ return;
+ }
+
+ hhLimit = chooseMap->itemData(curIndex).toList()[2].toInt();
+ addInfoToPreview(mapImage);
+ }
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/mapContainer.h
--- a/QTfrontend/mapContainer.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/mapContainer.h Tue Jan 04 12:53:46 2011 +0100
@@ -23,8 +23,11 @@
#include
#include
#include
+#include
+#include
#include "hwmap.h"
+#include "drawmapscene.h"
class QPushButton;
class IconedGroupBox;
@@ -44,19 +47,26 @@
QString getCurrentMap() const;
QString getCurrentTheme() const;
int getCurrentHHLimit() const;
+ QString getCurrentScheme() const;
+ QString getCurrentWeapons() const;
quint32 getTemplateFilter() const;
MapGenerator get_mapgen(void) const;
int get_maze_size(void) const;
bool getCurrentIsMission() const;
+ QByteArray getDrawnMapData();
+ DrawMapScene * getDrawMapScene();
+ void mapDrawingFinished();
+ QLineEdit* seedEdit;
public slots:
- void changeImage();
+ void askForGeneratedPreview();
void setSeed(const QString & seed);
void setMap(const QString & map);
void setTheme(const QString & theme);
void setTemplateFilter(int);
void setMapgen(MapGenerator m);
void setMaze_size(int size);
+ void setDrawnMapData(const QByteArray & ar);
signals:
void seedChanged(const QString & seed);
@@ -65,6 +75,8 @@
void newTemplateFilter(int filter);
void mapgenChanged(MapGenerator m);
void maze_sizeChanged(int s);
+ void drawMapRequested();
+ void drawnMapChanged(const QByteArray & data);
private slots:
void setImage(const QImage newImage);
@@ -78,6 +90,7 @@
void themeSelected(int currentRow);
void addInfoToPreview(QPixmap image);
void templateFilterChanged(int filter);
+ void seedEdited();
protected:
virtual void resizeEvent ( QResizeEvent * event );
@@ -90,6 +103,8 @@
QListWidget* lwThemes;
HWMap* pMap;
QString m_seed;
+ QPushButton* seedSet;
+ QLabel* seedLabel;
int hhLimit;
int templateFilter;
QPixmap hhSmall;
@@ -99,9 +114,9 @@
QComboBox *maze_size_selection;
MapGenerator mapgen;
int numMissions;
- int maze_size;
+ DrawMapScene drawMapScene;
- void loadMap(int index);
+ void updatePreview();
};
#endif // _HWMAP_CONTAINER_INCLUDED
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/netregister.cpp
--- a/QTfrontend/netregister.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/netregister.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -21,7 +21,8 @@
HWNetRegisterServer::HWNetRegisterServer(QObject *parent, const QString & descr, quint16 port) :
QObject(parent)
{
-
+ Q_UNUSED(descr);
+ Q_UNUSED(port);
}
void HWNetRegisterServer::unregister()
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/newnetclient.cpp
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/pages.cpp
--- a/QTfrontend/pages.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/pages.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
#include "ammoSchemeModel.h"
#include "pages.h"
@@ -63,6 +64,7 @@
#include "togglebutton.h"
#include "hwform.h"
#include "SDLs.h"
+#include "drawmapwidget.h"
PageMain::PageMain(QWidget* parent) :
AbstractPage(parent)
@@ -440,17 +442,22 @@
{
QGridLayout * pageLayout = new QGridLayout(this);
- BtnBack = addButton(":/res/Exit.png", pageLayout, 2, 0, true);
+ BtnBack = addButton(":/res/Exit.png", pageLayout, 3, 0, true);
gameCFG = new GameCFGWidget(this);
pageLayout->addWidget(gameCFG, 0, 0, 1, 2);
- pageLayout->setRowStretch(1, 1);
+ QPushButton * btnSetup = new QPushButton(this);
+ btnSetup->setText(QPushButton::tr("Setup"));
+ connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
+ pageLayout->addWidget(btnSetup, 1, 0, 1, 2);
+
+ pageLayout->setRowStretch(2, 1);
teamsSelect = new TeamSelWidget(this);
- pageLayout->addWidget(teamsSelect, 0, 2, 2, 2);
+ pageLayout->addWidget(teamsSelect, 0, 2, 3, 2);
- BtnStartMPGame = addButton(tr("Start"), pageLayout, 2, 3);
+ BtnStartMPGame = addButton(tr("Start"), pageLayout, 3, 3);
}
PageOptions::PageOptions(QWidget* parent) :
@@ -522,45 +529,74 @@
}
{
- // TODO: This box should contain controls for all schemes: game modes and weapons
-
IconedGroupBox* groupWeapons = new IconedGroupBox(this);
+
//groupWeapons->setContentTopPadding(0);
//groupWeapons->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
groupWeapons->setIcon(QIcon(":/res/weaponsicon.png"));
groupWeapons->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- groupWeapons->setTitle(QGroupBox::tr("Weapons"));
+ groupWeapons->setTitle(QGroupBox::tr("Schemes and Weapons"));
QGridLayout * WeaponsLayout = new QGridLayout(groupWeapons);
+ QLabel* SchemeLabel = new QLabel(groupWeapons);
+ SchemeLabel->setText(QLabel::tr("Game scheme"));
+ WeaponsLayout->addWidget(SchemeLabel, 1, 0);
+
+ SchemesName = new QComboBox(groupWeapons);
+ WeaponsLayout->addWidget(SchemesName, 1, 1);
+
+ SchemeNew = new QPushButton(groupWeapons);
+ SchemeNew->setToolTip(tr("New scheme"));
+ SchemeNew->setIconSize(pmNew.size());
+ SchemeNew->setIcon(pmNew);
+ SchemeNew->setMaximumWidth(pmNew.width() + 6);
+ WeaponsLayout->addWidget(SchemeNew, 1, 2);
+
+ SchemeEdit = new QPushButton(groupWeapons);
+ SchemeEdit->setToolTip(tr("Edit scheme"));
+ SchemeEdit->setIconSize(pmEdit.size());
+ SchemeEdit->setIcon(pmEdit);
+ SchemeEdit->setMaximumWidth(pmEdit.width() + 6);
+ WeaponsLayout->addWidget(SchemeEdit, 1, 3);
+
+ SchemeDelete = new QPushButton(groupWeapons);
+ SchemeDelete->setToolTip(tr("Delete scheme"));
+ SchemeDelete->setIconSize(pmDelete.size());
+ SchemeDelete->setIcon(pmDelete);
+ SchemeDelete->setMaximumWidth(pmDelete.width() + 6);
+ WeaponsLayout->addWidget(SchemeDelete, 1, 4);
+
+ QLabel* WeaponLabel = new QLabel(groupWeapons);
+ WeaponLabel->setText(QLabel::tr("Weapons"));
+ WeaponsLayout->addWidget(WeaponLabel, 2, 0);
+
WeaponsName = new QComboBox(groupWeapons);
- WeaponsLayout->addWidget(WeaponsName, 0, 0);
+ WeaponsLayout->addWidget(WeaponsName, 2, 1);
- WeaponsButt = new QPushButton(groupWeapons);
- WeaponsButt->setToolTip(tr("New weapon scheme"));
- WeaponsButt->setIconSize(pmNew.size());
- WeaponsButt->setIcon(pmNew);
- WeaponsButt->setMaximumWidth(pmNew.width() + 6);
- WeaponsLayout->addWidget(WeaponsButt, 0, 1);
+ WeaponNew = new QPushButton(groupWeapons);
+ WeaponNew->setToolTip(tr("New weapon set"));
+ WeaponNew->setIconSize(pmNew.size());
+ WeaponNew->setIcon(pmNew);
+ WeaponNew->setMaximumWidth(pmNew.width() + 6);
+ WeaponsLayout->addWidget(WeaponNew, 2, 2);
WeaponEdit = new QPushButton(groupWeapons);
- WeaponEdit->setToolTip(tr("Edit weapon scheme"));
+ WeaponEdit->setToolTip(tr("Edit weapon set"));
WeaponEdit->setIconSize(pmEdit.size());
WeaponEdit->setIcon(pmEdit);
WeaponEdit->setMaximumWidth(pmEdit.width() + 6);
- WeaponsLayout->addWidget(WeaponEdit, 0, 2);
+ WeaponsLayout->addWidget(WeaponEdit, 2, 3);
WeaponDelete = new QPushButton(groupWeapons);
- WeaponDelete->setToolTip(tr("Delete weapon scheme"));
+ WeaponDelete->setToolTip(tr("Delete weapon set"));
WeaponDelete->setIconSize(pmDelete.size());
WeaponDelete->setIcon(pmDelete);
WeaponDelete->setMaximumWidth(pmDelete.width() + 6);
- WeaponDelete->setEnabled(false);
- WeaponDelete->setVisible(false); // hide for now
- WeaponsLayout->addWidget(WeaponDelete, 0, 3);
+ WeaponsLayout->addWidget(WeaponDelete, 2, 4);
WeaponTooltip = new QCheckBox(this);
WeaponTooltip->setText(QCheckBox::tr("Show ammo menu tooltips"));
- WeaponsLayout->addWidget(WeaponTooltip, 1, 0, 1, 3);
+ WeaponsLayout->addWidget(WeaponTooltip, 3, 0, 1, 4);
gbTBLayout->addWidget(groupWeapons, 1, 0);
}
@@ -942,19 +978,24 @@
// chatwidget
pChatWidget = new HWChatWidget(this, gameSettings, sdli, true);
pChatWidget->setShowReady(true); // show status bulbs by default
- pageLayout->addWidget(pChatWidget, 1, 0, 1, 2);
+ pageLayout->addWidget(pChatWidget, 2, 0, 1, 2);
pageLayout->setRowStretch(1, 100);
pGameCFG = new GameCFGWidget(this);
pageLayout->addWidget(pGameCFG, 0, 0);
+ QPushButton * btnSetup = new QPushButton(this);
+ btnSetup->setText(QPushButton::tr("Setup"));
+ connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
+ pageLayout->addWidget(btnSetup, 1, 0);
+
pNetTeamsWidget = new TeamSelWidget(this);
pNetTeamsWidget->setAcceptOuter(true);
- pageLayout->addWidget(pNetTeamsWidget, 0, 1);
+ pageLayout->addWidget(pNetTeamsWidget, 0, 1, 2, 1);
QHBoxLayout * bottomLayout = new QHBoxLayout;
- pageLayout->addLayout(bottomLayout, 3, 0, 1, 2);
+ pageLayout->addLayout(bottomLayout, 4, 0, 1, 2);
BtnBack = addButton(":/res/Exit.png", bottomLayout, 0, true);
@@ -1035,7 +1076,7 @@
BtnCampaignPage = addButton(":/res/Campaign.png", middleLine, 0, true);
BtnCampaignPage->setToolTip(tr("Campaign Mode (...). IN DEVELOPMENT"));
- BtnCampaignPage->setVisible(false);
+ //BtnCampaignPage->setVisible(false);
BtnTrainPage = addButton(":/res/Trainings.png", middleLine, 1, true);
BtnTrainPage->setToolTip(tr("Training Mode (Practice your skills in a range of training missions). IN DEVELOPMENT"));
@@ -1069,7 +1110,10 @@
tmpdir.setFilter(QDir::Files);
CBSelect->addItems(tmpdir.entryList(QStringList("*.lua")).replaceInStrings(QRegExp("^(.*)\\.lua"), "\\1"));
for(int i = 0; i < CBSelect->count(); i++)
+ {
CBSelect->setItemData(i, CBSelect->itemText(i));
+ CBSelect->setItemText(i, CBSelect->itemText(i).replace("_", " "));
+ }
pageLayout->addWidget(CBSelect, 1, 1);
@@ -1110,18 +1154,26 @@
QGridLayout * pageLayout = new QGridLayout(this);
pWeapons = new SelWeaponWidget(cAmmoNumber, this);
- pageLayout->addWidget(pWeapons, 0, 0, 1, 4);
+ pageLayout->addWidget(pWeapons, 0, 0, 1, 5);
- BtnBack = addButton(":/res/Exit.png", pageLayout, 1, 0, true);
- BtnDefault = addButton(tr("Default"), pageLayout, 1, 1);
- BtnDelete = addButton(tr("Delete"), pageLayout, 1, 2);
- BtnSave = addButton(":/res/Save.png", pageLayout, 1, 3, true);
+ BtnBack = addButton(":/res/Exit.png", pageLayout, 1, 0, 2, 1, true);
+ BtnDefault = addButton(tr("Default"), pageLayout, 1, 3);
+ BtnNew = addButton(tr("New"), pageLayout, 1, 2);
+ BtnCopy = addButton(tr("Copy"), pageLayout, 2, 2);
+ BtnDelete = addButton(tr("Delete"), pageLayout, 2, 3);
+ BtnSave = addButton(":/res/Save.png", pageLayout, 1, 4, 2, 1, true);
BtnSave->setStyleSheet("QPushButton{margin: 24px 0px 0px 0px;}");
BtnBack->setFixedHeight(BtnSave->height());
BtnBack->setStyleSheet("QPushButton{margin-top: 31px;}");
+ selectWeaponSet = new QComboBox(this);
+ pageLayout->addWidget(selectWeaponSet, 1, 1, 2, 1);
+
connect(BtnDefault, SIGNAL(clicked()), pWeapons, SLOT(setDefault()));
connect(BtnSave, SIGNAL(clicked()), pWeapons, SLOT(save()));
+ connect(BtnNew, SIGNAL(clicked()), pWeapons, SLOT(newWeaponsName()));
+ connect(BtnCopy, SIGNAL(clicked()), pWeapons, SLOT(copy()));
+ connect(selectWeaponSet, SIGNAL(currentIndexChanged(const QString&)), pWeapons, SLOT(setWeaponsName(const QString&)));
}
PageInGame::PageInGame(QWidget* parent) :
@@ -1502,7 +1554,7 @@
sp.setVerticalPolicy(QSizePolicy::MinimumExpanding);
sp.setHorizontalPolicy(QSizePolicy::Expanding);
- pageLayout->addWidget(gb, 1,0,13,4);
+ pageLayout->addWidget(gb, 1,0,13,5);
gbGameModes = new QGroupBox(QGroupBox::tr("Game Modifiers"), gb);
gbBasicSettings = new QGroupBox(QGroupBox::tr("Basic Settings"), gb);
@@ -1705,105 +1757,118 @@
glBSLayout->addWidget(SB_HealthDecrease,5,2,1,1);
l = new QLabel(gbBasicSettings);
- l->setText(QLabel::tr("Crate Drops"));
+ l->setText(QLabel::tr("% Rope Length"));
l->setWordWrap(true);
glBSLayout->addWidget(l,6,0,1,1);
l = new QLabel(gbBasicSettings);
l->setFixedSize(32,32);
- l->setPixmap(QPixmap(":/res/iconBox.png"));
+ l->setPixmap(QPixmap(":/res/iconRope.png"));
glBSLayout->addWidget(l,6,1,1,1);
- SB_CaseProb = new FreqSpinBox(gbBasicSettings);
- SB_CaseProb->setRange(0, 9);
- SB_CaseProb->setValue(5);
- glBSLayout->addWidget(SB_CaseProb,6,2,1,1);
+ SB_RopeModifier = new QSpinBox(gbBasicSettings);
+ SB_RopeModifier->setRange(25, 999);
+ SB_RopeModifier->setValue(100);
+ SB_RopeModifier->setSingleStep(25);
+ glBSLayout->addWidget(SB_RopeModifier,6,2,1,1);
l = new QLabel(gbBasicSettings);
- l->setText(QLabel::tr("% Health Crates"));
+ l->setText(QLabel::tr("Crate Drops"));
l->setWordWrap(true);
glBSLayout->addWidget(l,7,0,1,1);
l = new QLabel(gbBasicSettings);
l->setFixedSize(32,32);
- l->setPixmap(QPixmap(":/res/iconHealth.png")); // TODO: icon
+ l->setPixmap(QPixmap(":/res/iconBox.png"));
glBSLayout->addWidget(l,7,1,1,1);
- SB_HealthCrates = new QSpinBox(gbBasicSettings);
- SB_HealthCrates->setRange(0, 100);
- SB_HealthCrates->setValue(35);
- SB_HealthCrates->setSingleStep(5);
- glBSLayout->addWidget(SB_HealthCrates,7,2,1,1);
+ SB_CaseProb = new FreqSpinBox(gbBasicSettings);
+ SB_CaseProb->setRange(0, 9);
+ SB_CaseProb->setValue(5);
+ glBSLayout->addWidget(SB_CaseProb,7,2,1,1);
l = new QLabel(gbBasicSettings);
- l->setText(QLabel::tr("Health in Crates"));
+ l->setText(QLabel::tr("% Health Crates"));
l->setWordWrap(true);
glBSLayout->addWidget(l,8,0,1,1);
l = new QLabel(gbBasicSettings);
l->setFixedSize(32,32);
l->setPixmap(QPixmap(":/res/iconHealth.png")); // TODO: icon
glBSLayout->addWidget(l,8,1,1,1);
+ SB_HealthCrates = new QSpinBox(gbBasicSettings);
+ SB_HealthCrates->setRange(0, 100);
+ SB_HealthCrates->setValue(35);
+ SB_HealthCrates->setSingleStep(5);
+ glBSLayout->addWidget(SB_HealthCrates,8,2,1,1);
+
+ l = new QLabel(gbBasicSettings);
+ l->setText(QLabel::tr("Health in Crates"));
+ l->setWordWrap(true);
+ glBSLayout->addWidget(l,9,0,1,1);
+ l = new QLabel(gbBasicSettings);
+ l->setFixedSize(32,32);
+ l->setPixmap(QPixmap(":/res/iconHealth.png")); // TODO: icon
+ glBSLayout->addWidget(l,9,1,1,1);
SB_CrateHealth = new QSpinBox(gbBasicSettings);
SB_CrateHealth->setRange(0, 200);
SB_CrateHealth->setValue(25);
SB_CrateHealth->setSingleStep(5);
- glBSLayout->addWidget(SB_CrateHealth,8,2,1,1);
+ glBSLayout->addWidget(SB_CrateHealth,9,2,1,1);
l = new QLabel(gbBasicSettings);
l->setText(QLabel::tr("Mines Time"));
l->setWordWrap(true);
- glBSLayout->addWidget(l,9,0,1,1);
+ glBSLayout->addWidget(l,10,0,1,1);
l = new QLabel(gbBasicSettings);
l->setFixedSize(32,32);
l->setPixmap(QPixmap(":/res/iconTime.png")); // TODO: icon
- glBSLayout->addWidget(l,9,1,1,1);
+ glBSLayout->addWidget(l,10,1,1,1);
SB_MinesTime = new QSpinBox(gbBasicSettings);
SB_MinesTime->setRange(-1, 5);
SB_MinesTime->setValue(3);
SB_MinesTime->setSingleStep(1);
SB_MinesTime->setSpecialValueText(tr("Random"));
SB_MinesTime->setSuffix(" "+ tr("Seconds"));
- glBSLayout->addWidget(SB_MinesTime,9,2,1,1);
+ glBSLayout->addWidget(SB_MinesTime,10,2,1,1);
l = new QLabel(gbBasicSettings);
l->setText(QLabel::tr("Mines"));
l->setWordWrap(true);
- glBSLayout->addWidget(l,10,0,1,1);
+ glBSLayout->addWidget(l,11,0,1,1);
l = new QLabel(gbBasicSettings);
l->setFixedSize(32,32);
l->setPixmap(QPixmap(":/res/iconMine.png")); // TODO: icon
- glBSLayout->addWidget(l,10,1,1,1);
+ glBSLayout->addWidget(l,11,1,1,1);
SB_Mines = new QSpinBox(gbBasicSettings);
SB_Mines->setRange(0, 80);
SB_Mines->setValue(0);
SB_Mines->setSingleStep(5);
- glBSLayout->addWidget(SB_Mines,10,2,1,1);
+ glBSLayout->addWidget(SB_Mines,11,2,1,1);
l = new QLabel(gbBasicSettings);
l->setText(QLabel::tr("% Dud Mines"));
l->setWordWrap(true);
- glBSLayout->addWidget(l,11,0,1,1);
+ glBSLayout->addWidget(l,12,0,1,1);
l = new QLabel(gbBasicSettings);
l->setFixedSize(32,32);
l->setPixmap(QPixmap(":/res/iconDud.png"));
- glBSLayout->addWidget(l,11,1,1,1);
+ glBSLayout->addWidget(l,12,1,1,1);
SB_MineDuds = new QSpinBox(gbBasicSettings);
SB_MineDuds->setRange(0, 100);
SB_MineDuds->setValue(0);
SB_MineDuds->setSingleStep(5);
- glBSLayout->addWidget(SB_MineDuds,11,2,1,1);
+ glBSLayout->addWidget(SB_MineDuds,12,2,1,1);
l = new QLabel(gbBasicSettings);
l->setText(QLabel::tr("Explosives"));
l->setWordWrap(true);
- glBSLayout->addWidget(l,12,0,1,1);
+ glBSLayout->addWidget(l,13,0,1,1);
l = new QLabel(gbBasicSettings);
l->setFixedSize(32,32);
l->setPixmap(QPixmap(":/res/iconDamage.png"));
- glBSLayout->addWidget(l,12,1,1,1);
+ glBSLayout->addWidget(l,13,1,1,1);
SB_Explosives = new QSpinBox(gbBasicSettings);
SB_Explosives->setRange(0, 40);
SB_Explosives->setValue(0);
SB_Explosives->setSingleStep(1);
- glBSLayout->addWidget(SB_Explosives,12,2,1,1);
-
+ glBSLayout->addWidget(SB_Explosives,13,2,1,1);
l = new QLabel(gbBasicSettings);
l->setText(QLabel::tr("Scheme Name:"));
@@ -1816,12 +1881,14 @@
mapper = new QDataWidgetMapper(this);
BtnBack = addButton(":/res/Exit.png", pageLayout, 15, 0, true);
- BtnNew = addButton(tr("New"), pageLayout, 15, 2);
- BtnDelete = addButton(tr("Delete"), pageLayout, 15, 3);
+ BtnCopy = addButton(tr("Copy"), pageLayout, 15, 2);
+ BtnNew = addButton(tr("New"), pageLayout, 15, 3);
+ BtnDelete = addButton(tr("Delete"), pageLayout, 15, 4);
selectScheme = new QComboBox(this);
pageLayout->addWidget(selectScheme, 15, 1);
+ connect(BtnCopy, SIGNAL(clicked()), this, SLOT(copyRow()));
connect(BtnNew, SIGNAL(clicked()), this, SLOT(newRow()));
connect(BtnDelete, SIGNAL(clicked()), this, SLOT(deleteRow()));
connect(selectScheme, SIGNAL(currentIndexChanged(int)), mapper, SLOT(setCurrentIndex(int)));
@@ -1870,6 +1937,7 @@
mapper->addMapping(SB_CrateHealth, 34);
mapper->addMapping(SB_WaterRise, 35);
mapper->addMapping(SB_HealthDecrease, 36);
+ mapper->addMapping(SB_RopeModifier, 37);
mapper->toFirst();
}
@@ -1877,14 +1945,25 @@
void PageScheme::newRow()
{
QAbstractItemModel * model = mapper->model();
- model->insertRow(model->rowCount());
+ model->insertRow(-1);
+ selectScheme->setCurrentIndex(model->rowCount() - 1);
+}
+
+void PageScheme::copyRow()
+{
+ QAbstractItemModel * model = mapper->model();
+ model->insertRow(selectScheme->currentIndex());
selectScheme->setCurrentIndex(model->rowCount() - 1);
}
void PageScheme::deleteRow()
{
- QAbstractItemModel * model = mapper->model();
- model->removeRow(selectScheme->currentIndex());
+ QMessageBox reallyDelete(QMessageBox::Question, QMessageBox::tr("Schemes"), QMessageBox::tr("Really delete this game scheme?"), QMessageBox::Ok | QMessageBox::Cancel);
+
+ if (reallyDelete.exec() == QMessageBox::Ok) {
+ QAbstractItemModel * model = mapper->model();
+ model->removeRow(selectScheme->currentIndex());
+ }
}
void PageScheme::schemeSelected(int n)
@@ -1993,3 +2072,41 @@
BtnBack = addButton(":/res/Exit.png", pageLayout, 4, 0, true);
}
+
+/////////////////////////////////////////////////
+
+PageDrawMap::PageDrawMap(QWidget* parent) : AbstractPage(parent)
+{
+ QGridLayout * pageLayout = new QGridLayout(this);
+
+ QPushButton * pbUndo = addButton(tr("Undo"), pageLayout, 0, 0);
+ QPushButton * pbClear = addButton(tr("Clear"), pageLayout, 1, 0);
+ QPushButton * pbLoad = addButton(tr("Load"), pageLayout, 2, 0);
+ QPushButton * pbSave = addButton(tr("Save"), pageLayout, 3, 0);
+
+ BtnBack = addButton(":/res/Exit.png", pageLayout, 5, 0, true);
+
+ drawMapWidget = new DrawMapWidget(this);
+ pageLayout->addWidget(drawMapWidget, 0, 1, 5, 1);
+
+ connect(pbUndo, SIGNAL(clicked()), drawMapWidget, SLOT(undo()));
+ connect(pbClear, SIGNAL(clicked()), drawMapWidget, SLOT(clear()));
+ connect(pbLoad, SIGNAL(clicked()), this, SLOT(load()));
+ connect(pbSave, SIGNAL(clicked()), this, SLOT(save()));
+}
+
+void PageDrawMap::load()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Load drawn map"), ".", tr("Drawn Maps (*.hwmap);;All files (*.*)"));
+
+ if(!fileName.isEmpty())
+ drawMapWidget->load(fileName);
+}
+
+void PageDrawMap::save()
+{
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save drawn map"), ".", tr("Drawn Maps (*.hwmap);;All files (*.*)"));
+
+ if(!fileName.isEmpty())
+ drawMapWidget->save(fileName);
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/pages.h
--- a/QTfrontend/pages.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/pages.h Tue Jan 04 12:53:46 2011 +0100
@@ -61,6 +61,8 @@
class IconedGroupBox;
class FreqSpinBox;
+class DrawMapWidget;
+
class AbstractPage : public QWidget
{
Q_OBJECT
@@ -69,8 +71,10 @@
protected:
AbstractPage(QWidget* parent = 0) {
+ Q_UNUSED(parent);
+
font14 = new QFont("MS Shell Dlg", 14);
- setFocusPolicy(Qt::StrongFocus);
+ //setFocusPolicy(Qt::StrongFocus);
}
virtual ~AbstractPage() {};
@@ -196,6 +200,9 @@
GameCFGWidget *gameCFG;
TeamSelWidget *teamsSelect;
QPushButton *BtnStartMPGame;
+
+signals:
+ void SetupClicked();
};
class PageOptions : public AbstractPage
@@ -205,11 +212,16 @@
public:
PageOptions(QWidget* parent = 0);
- QPushButton *WeaponsButt;
+ QCheckBox *WeaponTooltip;
+ QPushButton *WeaponNew;
QPushButton *WeaponEdit;
QPushButton *WeaponDelete;
QComboBox *WeaponsName;
- QCheckBox *WeaponTooltip;
+ QPushButton *SchemeNew;
+ QPushButton *SchemeEdit;
+ QPushButton *SchemeDelete;
+ QComboBox *SchemesName;
+
QComboBox *CBLanguage;
QPushButton *BtnBack;
@@ -324,6 +336,9 @@
public slots:
void setReadyStatus(bool isReady);
void setMasterMode(bool isMaster);
+
+signals:
+ void SetupClicked();
};
class PageInfo : public AbstractPage
@@ -389,8 +404,11 @@
QPushButton *BtnSave;
QPushButton *BtnDefault;
QPushButton *BtnDelete;
+ QPushButton *BtnNew;
+ QPushButton *BtnCopy;
QPushButton *BtnBack;
SelWeaponWidget* pWeapons;
+ QComboBox* selectWeaponSet;
};
class PageInGame : public AbstractPage
@@ -462,12 +480,19 @@
PageScheme(QWidget* parent = 0);
QPushButton * BtnBack;
+ QPushButton * BtnCopy;
QPushButton * BtnNew;
QPushButton * BtnDelete;
QPushButton * BtnSave;
+ QComboBox * selectScheme;
void setModel(QAbstractItemModel * model);
+public slots:
+ void newRow();
+ void copyRow();
+ void deleteRow();
+
private:
QDataWidgetMapper * mapper;
ToggleButtonWidget * TBW_mode_Forts;
@@ -507,16 +532,15 @@
QSpinBox * SB_Mines;
QSpinBox * SB_MineDuds;
QSpinBox * SB_Explosives;
+ QSpinBox * SB_RopeModifier;
QLineEdit * LE_name;
- QComboBox * selectScheme;
QGroupBox * gbGameModes;
QGroupBox * gbBasicSettings;
private slots:
- void newRow();
- void deleteRow();
void schemeSelected(int);
+
};
class PageAdmin : public AbstractPage
@@ -565,4 +589,21 @@
QPushButton * BtnOfficialServer;
};
+
+class PageDrawMap : public AbstractPage
+{
+ Q_OBJECT
+
+public:
+ PageDrawMap(QWidget* parent = 0);
+
+ QPushButton * BtnBack;
+
+ DrawMapWidget * drawMapWidget;
+
+private slots:
+ void load();
+ void save();
+};
+
#endif // PAGES_H
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/predefteams.h
--- a/QTfrontend/predefteams.h Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2010 Andrey Korotaev
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef PREDEFTEAMS_H
-#define PREDEFTEAMS_H
-
-#include
-
-#define PREDEFTEAMS_COUNT 3
-/*
-struct PredefinedTeam
-{
- const char * TeamName;
- const char * hh0name;
- const char * hh1name;
- const char * hh2name;
- const char * hh3name;
- const char * hh4name;
- const char * hh5name;
- const char * hh6name;
- const char * hh7name;
- const char * hh0hat;
- const char * hh1hat;
- const char * hh2hat;
- const char * hh3hat;
- const char * hh4hat;
- const char * hh5hat;
- const char * hh6hat;
- const char * hh7hat;
- QString Grave;
- QString Fort;
-};
-
-
-const PredefinedTeam pteams[PREDEFTEAMS_COUNT] =
-{
- {
- QT_TRANSLATE_NOOP("teams", "Hedgehogs"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 1"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 2"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 3"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 4"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 5"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 6"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 7"),
- QT_TRANSLATE_NOOP("teams", "hedgehog 8"),
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "Simple", "Island"
- },
- {
- QT_TRANSLATE_NOOP("teams", "Goddess"),
- QT_TRANSLATE_NOOP("teams", "Isis"),
- QT_TRANSLATE_NOOP("teams", "Astarte"),
- QT_TRANSLATE_NOOP("teams", "Diana"),
- QT_TRANSLATE_NOOP("teams", "Aphrodite"),
- QT_TRANSLATE_NOOP("teams", "Hecate"),
- QT_TRANSLATE_NOOP("teams", "Demeter"),
- QT_TRANSLATE_NOOP("teams", "Kali"),
- QT_TRANSLATE_NOOP("teams", "Inanna"),
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "Bone", "Island"
- },
- {
- QT_TRANSLATE_NOOP("teams", "Fruits"),
- QT_TRANSLATE_NOOP("teams", "Banana"),
- QT_TRANSLATE_NOOP("teams", "Apple"),
- QT_TRANSLATE_NOOP("teams", "Orange"),
- QT_TRANSLATE_NOOP("teams", "Lemon"),
- QT_TRANSLATE_NOOP("teams", "Pineapple"),
- QT_TRANSLATE_NOOP("teams", "Mango"),
- QT_TRANSLATE_NOOP("teams", "Peach"),
- QT_TRANSLATE_NOOP("teams", "Plum"),
- "banana",
- "apple",
- "orange",
- "lemon",
- "NoHat",
- "NoHat",
- "NoHat",
- "NoHat",
- "coffin", "Barrelhouse"
- }
-};
-*/
-#endif // PREDEFTEAMS_H
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/proto.cpp
--- a/QTfrontend/proto.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/proto.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -23,14 +23,19 @@
}
+QByteArray & HWProto::addByteArrayToBuffer(QByteArray & buf, const QByteArray & msg)
+{
+ QByteArray bmsg = msg;
+ bmsg = bmsg.left(250);
+ quint8 sz = bmsg.size();
+ buf.append(QByteArray((char *)&sz, 1));
+ buf.append(bmsg);
+ return buf;
+}
+
QByteArray & HWProto::addStringToBuffer(QByteArray & buf, const QString & string)
{
- QByteArray strmsg = string.toUtf8();
- strmsg = strmsg.left(250);
- quint8 sz = strmsg.size();
- buf.append(QByteArray((char *)&sz, 1));
- buf.append(strmsg);
- return buf;
+ return addByteArrayToBuffer(buf, string.toUtf8());
}
QByteArray & HWProto::addStringListToBuffer(QByteArray & buf, const QStringList & strList)
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/proto.h
--- a/QTfrontend/proto.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/proto.h Tue Jan 04 12:53:46 2011 +0100
@@ -31,6 +31,7 @@
public:
HWProto();
static QByteArray & addStringToBuffer(QByteArray & buf, const QString & string);
+ static QByteArray & addByteArrayToBuffer(QByteArray & buf, const QByteArray & msg);
static QByteArray & addStringListToBuffer(QByteArray & buf, const QStringList & strList);
static QString formatChatMsg(const QString & nick, const QString & msg);
};
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/qaspectratiolayout.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/qaspectratiolayout.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation.
+ */
+
+#include "qaspectratiolayout.h"
+
+QAspectRatioLayout::QAspectRatioLayout(QWidget* parent, int spacing) : QLayout(parent) {
+ init(spacing);
+}
+
+QAspectRatioLayout::QAspectRatioLayout(int spacing) {
+ init(spacing);
+}
+
+QAspectRatioLayout::~QAspectRatioLayout() {
+ delete item;
+ delete lastReceivedRect;
+ delete _geometry;
+}
+
+void QAspectRatioLayout::init(int spacing) {
+ item = 0;
+ lastReceivedRect = new QRect(0, 0, 0, 0);
+ _geometry = new QRect(0, 0, 0, 0);
+ setSpacing(spacing);
+}
+
+
+/* Adds item if place isn't already taken. */
+void QAspectRatioLayout::add(QLayoutItem* item) {
+ if(!hasItem()) {
+ replaceItem(item);
+ }
+}
+
+/* Adds item if place isn't already taken. */
+void QAspectRatioLayout::addItem(QLayoutItem* item) {
+ if(!hasItem()) {
+ replaceItem(item);
+ }
+}
+
+/* Adds widget if place isn't already taken. */
+void QAspectRatioLayout::addWidget(QWidget* widget) {
+ if(!hasItem()) {
+ replaceItem(new QWidgetItem(widget));
+ }
+}
+
+/* Returns the item pointer and dereferences it here. */
+QLayoutItem* QAspectRatioLayout::take() {
+ QLayoutItem* item = 0;
+ if(this->hasItem()) {
+ item = this->item;
+ this->item = 0;
+ }
+ return item;
+}
+
+/* Returns the item pointer and dereferences it here. */
+QLayoutItem* QAspectRatioLayout::takeAt(int index) {
+ if(index != 0) {
+ return 0;
+ }
+ return this->take();
+}
+
+/* Returns the item pointer. */
+QLayoutItem* QAspectRatioLayout::itemAt(int index) const {
+ if(index != 0) {
+ return 0;
+ }
+ if(hasItem()) {
+ return this->item;
+ }
+ return 0;
+}
+
+/* Checks if we have an item. */
+bool QAspectRatioLayout::hasItem() const {
+ return this->item != 0;
+}
+
+/* Returns the count of items which can be either 0 or 1. */
+int QAspectRatioLayout::count() const {
+ int returnValue = 0;
+ if(hasItem()) {
+ returnValue = 1;
+ }
+ return returnValue;
+}
+
+/* Replaces the item with the new and returns the old. */
+QLayoutItem* QAspectRatioLayout::replaceItem(QLayoutItem* item) {
+ QLayoutItem* old = 0;
+ if(this->hasItem()) {
+ old = this->item;
+ }
+ this->item = item;
+ setGeometry(*this->_geometry);
+ return old;
+}
+
+/* Tells which way layout expands. */
+Qt::Orientations QAspectRatioLayout::expandingDirections() const {
+ return Qt::Horizontal | Qt::Vertical;
+}
+
+/* Tells which size is preferred. */
+QSize QAspectRatioLayout::sizeHint() const {
+ return this->item->minimumSize();
+}
+
+/* Tells minimum size. */
+QSize QAspectRatioLayout::minimumSize() const {
+ return this->item->minimumSize();
+}
+
+/*
+ * Tells if heightForWidth calculations is handled.
+ * It isn't since width isn't enough to calculate
+ * proper size.
+ */
+bool QAspectRatioLayout::hasHeightForWidth() const {
+ return false;
+}
+
+/* Replaces lastReceivedRect. */
+void QAspectRatioLayout::setLastReceivedRect(const QRect& rect) {
+ QRect* oldRect = this->lastReceivedRect;
+ this->lastReceivedRect = new QRect(rect.topLeft(), rect.size());
+ delete oldRect;
+}
+
+/* Returns geometry */
+QRect QAspectRatioLayout::geometry() {
+ return QRect(*this->_geometry);
+}
+
+/* Sets geometry to given size. */
+void QAspectRatioLayout::setGeometry(const QRect& rect) {
+ /*
+ * We check if the item is set and
+ * if size is the same previously received.
+ * If either is false nothing is done.
+ */
+ if(!this->hasItem() ||
+ areRectsEqual(*this->lastReceivedRect, rect)) {
+ return;
+ }
+ /* Replace the last received rectangle. */
+ setLastReceivedRect(rect);
+ /* Calculate proper size for the item relative to the received size. */
+ QSize properSize = calculateProperSize(rect.size());
+ /* Calculate center location in the rect and with item size. */
+ QPoint properLocation = calculateCenterLocation(rect.size(), properSize);
+ /* Set items geometry */
+ this->item->setGeometry(QRect(properLocation, properSize));
+ QRect* oldRect = this->_geometry;
+ /* Cache the calculated geometry. */
+ this->_geometry = new QRect(properLocation, properSize);
+ delete oldRect;
+ /* Super classes setGeometry */
+ QLayout::setGeometry(*this->_geometry);
+}
+
+/* Takes the shortest side and creates QSize
+ * with the shortest side as width and height. */
+QSize QAspectRatioLayout::calculateProperSize(QSize from) const {
+ QSize properSize;
+ if(from.height() * 2 < from.width()) {
+ properSize.setHeight(from.height() - this->margin());
+ properSize.setWidth(from.height() * 2 - this->margin());
+ }
+ else {
+ properSize.setWidth(from.width() - this->margin());
+ properSize.setHeight(from.width() / 2 - this->margin());
+ }
+ return properSize;
+}
+
+/* Calculates center location from the given height and width for item size. */
+QPoint QAspectRatioLayout::calculateCenterLocation(QSize from,
+ QSize itemSize) const {
+ QPoint centerLocation;
+ if((from.width() - itemSize.width()) > 0) {
+ centerLocation.setX((from.width() - itemSize.width())/2);
+ }
+ if((from.height() - itemSize.height()) > 0) {
+ centerLocation.setY((from.height() - itemSize.height())/2);
+ }
+ return centerLocation;
+}
+
+/* Compares if two QRects are equal. */
+bool QAspectRatioLayout::areRectsEqual(const QRect& a,
+ const QRect& b) const {
+ bool result = false;
+ if(a.x() == b.x() &&
+ a.y() == b.y() &&
+ a.height() == b.height() &&
+ a.width() == b.width()) {
+ result = true;
+ }
+ return result;
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/qaspectratiolayout.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/qaspectratiolayout.h Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation.
+ */
+
+#ifndef QASPECTRATIOLAYOUT_H_
+#define QASPECTRATIOLAYOUT_H_
+
+#include
+#include
+#include
+#include
+#include
+
+
+class QAspectRatioLayout : public QLayout
+{
+ Q_OBJECT
+
+public:
+ QAspectRatioLayout(QWidget* parent, int spacing =-1);
+ QAspectRatioLayout(int spacing = -1);
+ ~QAspectRatioLayout();
+
+ /* Convenience method */
+ virtual void add(QLayoutItem* item);
+
+/* http://doc.trolltech.com/qlayout.html#addItem */
+ virtual void addItem(QLayoutItem* item);
+ /* http://doc.trolltech.com/qlayout.html#addWidget */
+ virtual void addWidget(QWidget* widget);
+ /* http://doc.trolltech.com/qlayout.html#takeAt */
+ virtual QLayoutItem* takeAt(int index);
+ /* http://doc.trolltech.com/qlayout.html#itemAt */
+ virtual QLayoutItem* itemAt(int index) const;
+ /* http://doc.trolltech.com/qlayout.html#count */
+ virtual int count() const;
+
+ /*
+ * These are ours since we do have only one item.
+ */
+ virtual QLayoutItem* replaceItem(QLayoutItem* item);
+ virtual QLayoutItem* take();
+ virtual bool hasItem() const;
+
+/* http://doc.trolltech.com/qlayout.html#expandingDirections */
+ virtual Qt::Orientations expandingDirections() const;
+
+ /*
+ * This method contains most of the juice of this article.
+ * http://doc.trolltech.com/qlayoutitem.html#setGeometry
+ */
+ virtual void setGeometry(const QRect& rect);
+ /* http://doc.trolltech.com/qlayoutitem.html#geometry */
+ virtual QRect geometry();
+
+ /* http://doc.trolltech.com/qlayoutitem.html#sizeHint */
+ virtual QSize sizeHint() const;
+ /* http://doc.trolltech.com/qlayout.html#minimumSize */
+ virtual QSize minimumSize() const;
+ /* http://doc.trolltech.com/qlayoutitem.html#hasHeightForWidth */
+ virtual bool hasHeightForWidth() const;
+
+private:
+ /* Saves the last received rect. */
+ void setLastReceivedRect(const QRect& rect);
+ /* Used to initialize the object. */
+ void init(int spacing);
+ /* Calculates the maximum size for the item from the assigned size. */
+ QSize calculateProperSize(QSize from) const;
+ /* Calculates the center location from the assigned size and
+ * the items size. */
+ QPoint calculateCenterLocation(QSize from, QSize itemSize) const;
+ /* Check if two QRects are equal */
+ bool areRectsEqual(const QRect& a, const QRect& b) const;
+ /* Contains item reference */
+ QLayoutItem* item;
+ /*
+ * Used for caching so we won't do calculations every time
+ * setGeometry is called.
+ */
+ QRect* lastReceivedRect;
+ /* Contains geometry */
+ QRect* _geometry;
+
+};
+
+#endif /* QASPECTRATIOLAYOUT_H_ */
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/ammopicboxgrey.png
Binary file QTfrontend/res/ammopicboxgrey.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/ammopicdelaygrey.png
Binary file QTfrontend/res/ammopicdelaygrey.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/ammopicgrey.png
Binary file QTfrontend/res/ammopicgrey.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/btnMoreWind.png
Binary file QTfrontend/res/btnMoreWind.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/btnNoWind.png
Binary file QTfrontend/res/btnNoWind.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/hh25x25grey.png
Binary file QTfrontend/res/hh25x25grey.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/iconRope.png
Binary file QTfrontend/res/iconRope.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/infinitygrey.png
Binary file QTfrontend/res/infinitygrey.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/lock.png
Binary file QTfrontend/res/lock.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/res/unlock.png
Binary file QTfrontend/res/unlock.png has changed
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/selectWeapon.cpp
--- a/QTfrontend/selectWeapon.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/selectWeapon.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -40,7 +40,7 @@
return ammo.copy(x, y, 32, 32);
}
-SelWeaponItem::SelWeaponItem(bool allowInfinite, int iconNum, int wNum, QImage image, QWidget* parent) :
+SelWeaponItem::SelWeaponItem(bool allowInfinite, int iconNum, int wNum, QImage image, QImage imagegrey, QWidget* parent) :
QWidget(parent)
{
QHBoxLayout* hbLayout = new QHBoxLayout(this);
@@ -53,7 +53,7 @@
lbl->setGeometry(0, 0, 30, 30);
hbLayout->addWidget(lbl);
- item = new WeaponItem(image, this);
+ item = new WeaponItem(image, imagegrey, this);
item->setItemsNum(wNum);
item->setInfinityState(allowInfinite);
hbLayout->addWidget(item);
@@ -74,6 +74,11 @@
return item->getItemsNum();
}
+void SelWeaponItem::setEnabled(bool value)
+{
+ item->setEnabled(value);
+}
+
SelWeaponWidget::SelWeaponWidget(int numItems, QWidget* parent) :
QFrame(parent),
m_numItems(numItems)
@@ -124,19 +129,19 @@
for(; i < m_numItems; ++i) {
if (i == 6) continue;
if (k % 4 == 0) ++j;
- SelWeaponItem * swi = new SelWeaponItem(true, i, currentState[i].digitValue(), QImage(":/res/ammopic.png"), this);
+ SelWeaponItem * swi = new SelWeaponItem(true, i, currentState[i].digitValue(), QImage(":/res/ammopic.png"), QImage(":/res/ammopicgrey.png"), this);
weaponItems[i].append(swi);
p1Layout->addWidget(swi, j, k % 4);
- SelWeaponItem * pwi = new SelWeaponItem(false, i, currentState[numItems + i].digitValue(), QImage(":/res/ammopicbox.png"), this);
+ SelWeaponItem * pwi = new SelWeaponItem(false, i, currentState[numItems + i].digitValue(), QImage(":/res/ammopicbox.png"), QImage(":/res/ammopicboxgrey.png"), this);
weaponItems[i].append(pwi);
p2Layout->addWidget(pwi, j, k % 4);
- SelWeaponItem * dwi = new SelWeaponItem(false, i, currentState[numItems*2 + i].digitValue(), QImage(":/res/ammopicdelay.png"), this);
+ SelWeaponItem * dwi = new SelWeaponItem(false, i, currentState[numItems*2 + i].digitValue(), QImage(":/res/ammopicdelay.png"), QImage(":/res/ammopicdelaygrey.png"), this);
weaponItems[i].append(dwi);
p3Layout->addWidget(dwi, j, k % 4);
- SelWeaponItem * awi = new SelWeaponItem(false, i, currentState[numItems*3 + i].digitValue(), QImage(":/res/ammopic.png"), this);
+ SelWeaponItem * awi = new SelWeaponItem(false, i, currentState[numItems*3 + i].digitValue(), QImage(":/res/ammopic.png"), QImage(":/res/ammopicgrey.png"), this);
weaponItems[i].append(awi);
p4Layout->addWidget(awi, j, k % 4);
@@ -150,6 +155,11 @@
void SelWeaponWidget::setWeapons(const QString& ammo)
{
+ bool enable = true;
+ for(int i = 0; i < cDefaultAmmos.size(); i++)
+ if (!cDefaultAmmos[i].first.compare(m_name->text())) {
+ enable = false;
+ }
for(int i = 0; i < m_numItems; ++i) {
twi::iterator it = weaponItems.find(i);
if (it == weaponItems.end()) continue;
@@ -157,12 +167,20 @@
it.value()[1]->setItemsNum(ammo[m_numItems + i].digitValue());
it.value()[2]->setItemsNum(ammo[m_numItems*2 + i].digitValue());
it.value()[3]->setItemsNum(ammo[m_numItems*3 + i].digitValue());
+ it.value()[0]->setEnabled(enable);
+ it.value()[1]->setEnabled(enable);
+ it.value()[2]->setEnabled(enable);
+ it.value()[3]->setEnabled(enable);
}
- update();
+ m_name->setEnabled(enable);
}
void SelWeaponWidget::setDefault()
{
+ for(int i = 0; i < cDefaultAmmos.size(); i++)
+ if (!cDefaultAmmos[i].first.compare(m_name->text())) {
+ return;
+ }
setWeapons(*cDefaultAmmoStore);
}
@@ -215,11 +233,11 @@
{
if (curWeaponsName == "") return;
- if (curWeaponsName == "Default") {
- QMessageBox impossible(QMessageBox::Warning, QMessageBox::tr("Weapons"), QMessageBox::tr("Can not delete default weapon set"));
- impossible.exec();
- return;
- }
+ for(int i = 0; i < cDefaultAmmos.size(); i++)
+ if (!cDefaultAmmos[i].first.compare(m_name->text())) {
+ QMessageBox::warning(0, QMessageBox::tr("Weapons"), QMessageBox::tr("Can not delete default weapon set '%1'!").arg(cDefaultAmmos[i].first));
+ return;
+ }
QMessageBox reallyDelete(QMessageBox::Question, QMessageBox::tr("Weapons"), QMessageBox::tr("Really delete this weapon set?"), QMessageBox::Ok | QMessageBox::Cancel);
@@ -229,18 +247,32 @@
}
}
+void SelWeaponWidget::newWeaponsName()
+{
+ setWeaponsName(tr("new"));
+}
+
void SelWeaponWidget::setWeaponsName(const QString& name)
{
- if(name != "" && wconf->contains(name)) {
- setWeapons(wconf->value(name).toString());
- }
+ m_name->setText(name);
curWeaponsName = name;
- m_name->setText(name);
+ if(name != "" && wconf->contains(name)) {
+ setWeapons(wconf->value(name).toString());
+ } else {
+ setWeapons(*cDefaultAmmoStore);
+ }
}
QStringList SelWeaponWidget::getWeaponNames() const
{
return wconf->allKeys();
}
+
+void SelWeaponWidget::copy()
+{
+ QString ammo = getWeaponsString(curWeaponsName);
+ setWeaponsName(tr("copy of") + " " + curWeaponsName);
+ setWeapons(ammo);
+}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/selectWeapon.h
--- a/QTfrontend/selectWeapon.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/selectWeapon.h Tue Jan 04 12:53:46 2011 +0100
@@ -33,10 +33,11 @@
Q_OBJECT
public:
- SelWeaponItem(bool allowInfinite, int iconNum, int wNum, QImage image, QWidget* parent=0);
+ SelWeaponItem(bool allowInfinite, int iconNum, int wNum, QImage image, QImage imagegrey, QWidget* parent=0);
unsigned char getItemsNum() const;
void setItemsNum(const unsigned char num);
+ void setEnabled(bool value);
private:
WeaponItem* item;
@@ -56,7 +57,9 @@
void setWeapons(const QString& ammo);
void setWeaponsName(const QString& name);
void deleteWeaponsName();
+ void newWeaponsName();
void save();
+ void copy();
signals:
void weaponsChanged();
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/statsPage.cpp
--- a/QTfrontend/statsPage.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/statsPage.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -31,6 +31,8 @@
void FitGraphicsView::resizeEvent(QResizeEvent * event)
{
+ Q_UNUSED(event);
+
fitInView(sceneRect());
}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/teamselect.cpp
--- a/QTfrontend/teamselect.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/teamselect.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -233,10 +233,6 @@
p.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00));
addScrArea(framePlaying, p.color(QPalette::Window).light(105), 250);
addScrArea(frameDontPlaying, p.color(QPalette::Window).dark(105), 0);
- QPushButton * btnSetup = new QPushButton(this);
- btnSetup->setText(QPushButton::tr("Setup"));
- connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
- mainLayout.addWidget(btnSetup);
}
void TeamSelWidget::setAcceptOuter(bool acceptOuter)
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/teamselect.h
--- a/QTfrontend/teamselect.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/teamselect.h Tue Jan 04 12:53:46 2011 +0100
@@ -56,7 +56,6 @@
signals:
void setEnabledGameStart(bool);
- void SetupClicked();
void teamWillPlay(HWTeam team);
void teamNotPlaying(const HWTeam& team);
void hhogsNumChanged(const HWTeam&);
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/teamselhelper.cpp
--- a/QTfrontend/teamselhelper.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/teamselhelper.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -73,7 +73,7 @@
connect(colorButt, SIGNAL(clicked()), this, SLOT(changeTeamColor()));
mainLayout.addWidget(colorButt);
- phhoger = new CHedgehogerWidget(QImage(":/res/hh25x25.png"), this);
+ phhoger = new CHedgehogerWidget(QImage(":/res/hh25x25.png"), QImage(":/res/hh25x25grey.png"), this);
connect(phhoger, SIGNAL(hedgehogsNumChanged()), this, SLOT(hhNumChanged()));
phhoger->setHHNum(team.numHedgehogs);
mainLayout.addWidget(phhoger);
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/togglebutton.cpp
--- a/QTfrontend/togglebutton.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/togglebutton.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -19,6 +19,7 @@
#include "togglebutton.h"
ToggleButtonWidget::ToggleButtonWidget(QWidget * parent, QString img)
+ : QPushButton(parent)
{
setCheckable(true);
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/ui_hwform.cpp
--- a/QTfrontend/ui_hwform.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/ui_hwform.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -116,4 +116,7 @@
pageCampaign = new PageCampaign();
Pages->addWidget(pageCampaign);
+
+ pageDrawMap = new PageDrawMap();
+ Pages->addWidget(pageDrawMap);
}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/ui_hwform.h
--- a/QTfrontend/ui_hwform.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/ui_hwform.h Tue Jan 04 12:53:46 2011 +0100
@@ -40,6 +40,7 @@
class PageScheme;
class PageAdmin;
class PageNetType;
+class PageDrawMap;
class QStackedLayout;
class QFont;
class QWidget;
@@ -72,6 +73,7 @@
PageAdmin *pageAdmin;
PageNetType *pageNetType;
PageCampaign *pageCampaign;
+ PageDrawMap *pageDrawMap;
QStackedLayout *Pages;
QFont *font14;
@@ -79,8 +81,6 @@
void setupUi(HWForm *HWForm);
void SetupFonts();
void SetupPages(QWidget *Parent, HWForm *HWForm);
- void SetupPageNetChat(QWidget *Parent);
- void SetupPageNetGame(QWidget *Parent);
};
#endif // UI_HWFORM_H
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/weaponItem.cpp
--- a/QTfrontend/weaponItem.cpp Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/weaponItem.cpp Tue Jan 04 12:53:46 2011 +0100
@@ -18,8 +18,8 @@
#include "weaponItem.h"
-WeaponItem::WeaponItem(const QImage& im, QWidget * parent) :
- ItemNum(im, parent, 0)
+WeaponItem::WeaponItem(const QImage& im, const QImage& img, QWidget * parent) :
+ ItemNum(im, img, parent, 0)
{
}
diff -r 0ddb100fea61 -r f924be23ffb4 QTfrontend/weaponItem.h
--- a/QTfrontend/weaponItem.h Mon Dec 27 23:57:44 2010 +0100
+++ b/QTfrontend/weaponItem.h Tue Jan 04 12:53:46 2011 +0100
@@ -26,7 +26,7 @@
Q_OBJECT
public:
- WeaponItem(const QImage& im, QWidget * parent);
+ WeaponItem(const QImage& im, const QImage& img, QWidget * parent);
virtual ~WeaponItem();
signals:
diff -r 0ddb100fea61 -r f924be23ffb4 bin/CMakeLists.txt
--- a/bin/CMakeLists.txt Mon Dec 27 23:57:44 2010 +0100
+++ b/bin/CMakeLists.txt Tue Jan 04 12:53:46 2011 +0100
@@ -1,7 +1,9 @@
if(WIN32 AND NOT UNIX)
file(GLOB DLLs *.dll)
+ file(GLOB ICOs *.ico)
install(FILES
${DLLs}
+ ${ICOs}
DESTINATION bin)
endif(WIN32 AND NOT UNIX)
diff -r 0ddb100fea61 -r f924be23ffb4 doc/Release.txt
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/Actions.hs
--- a/gameServer/Actions.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/Actions.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,134 +1,171 @@
-{-# LANGUAGE OverloadedStrings #-}
module Actions where
-import Control.Concurrent
+import Control.Concurrent.STM
import Control.Concurrent.Chan
+import Data.IntMap
import qualified Data.IntSet as IntSet
-import qualified Data.Set as Set
import qualified Data.Sequence as Seq
import System.Log.Logger
import Control.Monad
import Data.Time
import Data.Maybe
-import Control.Monad.Reader
-import Control.Monad.State.Strict
-import qualified Data.ByteString.Char8 as B
-----------------------------
import CoreTypes
import Utils
-import ClientIO
-import ServerState
data Action =
- AnswerClients ![ClientChan] ![B.ByteString]
+ AnswerThisClient [String]
+ | AnswerAll [String]
+ | AnswerAllOthers [String]
+ | AnswerThisRoom [String]
+ | AnswerOthersInRoom [String]
+ | AnswerSameClan [String]
+ | AnswerLobby [String]
| SendServerMessage
| SendServerVars
- | MoveToRoom RoomIndex
- | MoveToLobby B.ByteString
- | RemoveTeam B.ByteString
+ | RoomAddThisClient Int -- roomID
+ | RoomRemoveThisClient String
+ | RemoveTeam String
| RemoveRoom
| UnreadyRoomClients
- | JoinLobby
- | ProtocolError B.ByteString
- | Warning B.ByteString
- | ByeClient B.ByteString
- | KickClient ClientIndex
- | KickRoomClient ClientIndex
- | BanClient B.ByteString -- nick
- | RemoveClientTeams ClientIndex
+ | MoveToLobby
+ | ProtocolError String
+ | Warning String
+ | ByeClient String
+ | KickClient Int -- clID
+ | KickRoomClient Int -- clID
+ | BanClient String -- nick
+ | RemoveClientTeams Int -- clID
| ModifyClient (ClientInfo -> ClientInfo)
- | ModifyClient2 ClientIndex (ClientInfo -> ClientInfo)
+ | ModifyClient2 Int (ClientInfo -> ClientInfo)
| ModifyRoom (RoomInfo -> RoomInfo)
| ModifyServerInfo (ServerInfo -> ServerInfo)
- | AddRoom B.ByteString B.ByteString
+ | AddRoom String String
| CheckRegistered
| ClearAccountsCache
| ProcessAccountInfo AccountInfo
| Dump
| AddClient ClientInfo
- | DeleteClient ClientIndex
| PingAll
| StatsAction
-type CmdHandler = [B.ByteString] -> Reader (ClientIndex, IRnC) [Action]
+type CmdHandler = Int -> Clients -> Rooms -> [String] -> [Action]
+
+replaceID a (b, c, d, e) = (a, c, d, e)
+
+processAction :: (Int, ServerInfo, Clients, Rooms) -> Action -> IO (Int, ServerInfo, Clients, Rooms)
+
+
+processAction (clID, serverInfo, clients, rooms) (AnswerThisClient msg) = do
+ writeChan (sendChan $ clients ! clID) msg
+ return (clID, serverInfo, clients, rooms)
-processAction :: Action -> StateT ServerState IO ()
+processAction (clID, serverInfo, clients, rooms) (AnswerAll msg) = do
+ mapM_ (\cl -> writeChan (sendChan cl) msg) (elems clients)
+ return (clID, serverInfo, clients, rooms)
+
+
+processAction (clID, serverInfo, clients, rooms) (AnswerAllOthers msg) = do
+ mapM_ (\id' -> writeChan (sendChan $ clients ! id') msg) $
+ Prelude.filter (\id' -> (id' /= clID) && logonPassed (clients ! id')) (keys clients)
+ return (clID, serverInfo, clients, rooms)
+
+
+processAction (clID, serverInfo, clients, rooms) (AnswerThisRoom msg) = do
+ mapM_ (\id' -> writeChan (sendChan $ clients ! id') msg) roomClients
+ return (clID, serverInfo, clients, rooms)
+ where
+ roomClients = IntSet.elems $ playersIDs room
+ room = rooms ! rID
+ rID = roomID client
+ client = clients ! clID
-processAction (AnswerClients chans msg) = do
- liftIO $ map (flip seq ()) chans `seq` map (flip seq ()) msg `seq` mapM_ (flip writeChan msg) chans
+processAction (clID, serverInfo, clients, rooms) (AnswerOthersInRoom msg) = do
+ mapM_ (\id' -> writeChan (sendChan $ clients ! id') msg) $ Prelude.filter (/= clID) roomClients
+ return (clID, serverInfo, clients, rooms)
+ where
+ roomClients = IntSet.elems $ playersIDs room
+ room = rooms ! rID
+ rID = roomID client
+ client = clients ! clID
+
+
+processAction (clID, serverInfo, clients, rooms) (AnswerLobby msg) = do
+ mapM_ (\id' -> writeChan (sendChan $ clients ! id') msg) roomClients
+ return (clID, serverInfo, clients, rooms)
+ where
+ roomClients = IntSet.elems $ playersIDs room
+ room = rooms ! 0
-processAction SendServerMessage = do
- chan <- client's sendChan
- protonum <- client's clientProto
- si <- liftM serverInfo get
- let message = if protonum < latestReleaseVersion si then
+processAction (clID, serverInfo, clients, rooms) (AnswerSameClan msg) = do
+ mapM_ (\cl -> writeChan (sendChan cl) msg) sameClanOrSpec
+ return (clID, serverInfo, clients, rooms)
+ where
+ otherRoomClients = Prelude.map ((!) clients) $ IntSet.elems $ clID `IntSet.delete` (playersIDs room)
+ sameClanOrSpec = if teamsInGame client > 0 then sameClanClients else spectators
+ spectators = Prelude.filter (\cl -> teamsInGame cl == 0) otherRoomClients
+ sameClanClients = Prelude.filter (\cl -> teamsInGame cl > 0 && clientClan cl == thisClan) otherRoomClients
+ thisClan = clientClan client
+ room = rooms ! rID
+ rID = roomID client
+ client = clients ! clID
+
+
+processAction (clID, serverInfo, clients, rooms) SendServerMessage = do
+ writeChan (sendChan $ clients ! clID) ["SERVER_MESSAGE", message serverInfo]
+ return (clID, serverInfo, clients, rooms)
+ where
+ client = clients ! clID
+ message si = if clientProto client < latestReleaseVersion si then
serverMessageForOldVersions si
else
serverMessage si
- processAction $ AnswerClients [chan] ["SERVER_MESSAGE", message]
-{-
-processAction (clID, serverInfo, rnc) SendServerVars = do
+processAction (clID, serverInfo, clients, rooms) SendServerVars = do
writeChan (sendChan $ clients ! clID) ("SERVER_VARS" : vars)
- return (clID, serverInfo, rnc)
+ return (clID, serverInfo, clients, rooms)
where
client = clients ! clID
vars = [
- "MOTD_NEW", serverMessage serverInfo,
- "MOTD_OLD", serverMessageForOldVersions serverInfo,
+ "MOTD_NEW", serverMessage serverInfo,
+ "MOTD_OLD", serverMessageForOldVersions serverInfo,
"LATEST_PROTO", show $ latestReleaseVersion serverInfo
]
--}
+processAction (clID, serverInfo, clients, rooms) (ProtocolError msg) = do
+ writeChan (sendChan $ clients ! clID) ["ERROR", msg]
+ return (clID, serverInfo, clients, rooms)
-processAction (ProtocolError msg) = do
- chan <- client's sendChan
- processAction $ AnswerClients [chan] ["ERROR", msg]
+
+processAction (clID, serverInfo, clients, rooms) (Warning msg) = do
+ writeChan (sendChan $ clients ! clID) ["WARNING", msg]
+ return (clID, serverInfo, clients, rooms)
-processAction (Warning msg) = do
- chan <- client's sendChan
- processAction $ AnswerClients [chan] ["WARNING", msg]
-
-processAction (ByeClient msg) = do
- (Just ci) <- gets clientIndex
- rnc <- gets roomsClients
- ri <- clientRoomA
-
- chan <- client's sendChan
- ready <- client's isReady
+processAction (clID, serverInfo, clients, rooms) (ByeClient msg) = do
+ infoM "Clients" (show (clientUID client) ++ " quits: " ++ msg)
+ (_, _, newClients, newRooms) <-
+ if roomID client /= 0 then
+ processAction (clID, serverInfo, clients, rooms) $ RoomRemoveThisClient "quit"
+ else
+ return (clID, serverInfo, clients, rooms)
- when (ri /= lobbyId) $ do
- processAction $ MoveToLobby ("quit: " `B.append` msg)
- liftIO $ modifyRoom rnc (\r -> r{
- --playersIDs = IntSet.delete ci (playersIDs r)
- playersIn = (playersIn r) - 1,
- readyPlayers = if ready then readyPlayers r - 1 else readyPlayers r
- }) ri
- return ()
-
- liftIO $ do
- infoM "Clients" (show ci ++ " quits: " ++ (B.unpack msg))
-
- --mapM_ (processAction (ci, serverInfo, rnc)) $ answerOthersQuit ++ answerInformRoom
-
- processAction $ AnswerClients [chan] ["BYE", msg]
-
- s <- get
- put $! s{removedClients = ci `Set.insert` removedClients s}
-
-processAction (DeleteClient ci) = do
- rnc <- gets roomsClients
- liftIO $ removeClient rnc ci
-
- s <- get
- put $! s{removedClients = ci `Set.delete` removedClients s}
-
-{-
+ mapM_ (processAction (clID, serverInfo, newClients, newRooms)) $ answerOthersQuit ++ answerInformRoom
+ writeChan (sendChan $ clients ! clID) ["BYE", msg]
+ return (
+ 0,
+ serverInfo,
+ delete clID newClients,
+ adjust (\r -> r{
+ playersIDs = IntSet.delete clID (playersIDs r),
+ playersIn = (playersIn r) - 1,
+ readyPlayers = if isReady client then readyPlayers r - 1 else readyPlayers r
+ }) (roomID $ newClients ! clID) newRooms
+ )
where
client = clients ! clID
clientNick = nick client
@@ -147,57 +184,46 @@
else
[AnswerAll ["LOBBY:LEFT", clientNick]]
else
- []
--}
+ []
+
+
+processAction (clID, serverInfo, clients, rooms) (ModifyClient func) =
+ return (clID, serverInfo, adjust func clID clients, rooms)
+
-processAction (ModifyClient f) = do
- (Just ci) <- gets clientIndex
- rnc <- gets roomsClients
- liftIO $ modifyClient rnc f ci
- return ()
+processAction (clID, serverInfo, clients, rooms) (ModifyClient2 cl2ID func) =
+ return (clID, serverInfo, adjust func cl2ID clients, rooms)
+
-processAction (ModifyClient2 ci f) = do
- rnc <- gets roomsClients
- liftIO $ modifyClient rnc f ci
- return ()
+processAction (clID, serverInfo, clients, rooms) (ModifyRoom func) =
+ return (clID, serverInfo, clients, adjust func rID rooms)
+ where
+ rID = roomID $ clients ! clID
-processAction (ModifyRoom f) = do
- rnc <- gets roomsClients
- ri <- clientRoomA
- liftIO $ modifyRoom rnc f ri
- return ()
+processAction (clID, serverInfo, clients, rooms) (ModifyServerInfo func) =
+ return (clID, func serverInfo, clients, rooms)
-{-
-
-processAction (clID, serverInfo, rnc) (ModifyServerInfo func) =
- return (clID, func serverInfo, rnc)
-
--}
-processAction (MoveToRoom ri) = do
- (Just ci) <- gets clientIndex
- rnc <- gets roomsClients
- liftIO $ do
- modifyClient rnc (\cl -> cl{teamsInGame = 0}) ci
- modifyRoom rnc (\r -> r{playersIn = (playersIn r) + 1}) ri
-
- liftIO $ moveClientToRoom rnc ri ci
-
- chans <- liftM (map sendChan) $ roomClientsS ri
- clNick <- client's nick
+processAction (clID, serverInfo, clients, rooms) (RoomAddThisClient rID) =
+ processAction (
+ clID,
+ serverInfo,
+ adjust (\cl -> cl{roomID = rID, teamsInGame = if rID == 0 then teamsInGame cl else 0}) clID clients,
+ adjust (\r -> r{playersIDs = IntSet.insert clID (playersIDs r), playersIn = (playersIn r) + 1}) rID $
+ adjust (\r -> r{playersIDs = IntSet.delete clID (playersIDs r)}) 0 rooms
+ ) joinMsg
+ where
+ client = clients ! clID
+ joinMsg = if rID == 0 then
+ AnswerAllOthers ["LOBBY:JOINED", nick client]
+ else
+ AnswerThisRoom ["JOINED", nick client]
- processAction $ AnswerClients chans ["JOINED", clNick]
-processAction (MoveToLobby msg) = do
- (Just ci) <- gets clientIndex
- --ri <- clientRoomA
- rnc <- gets roomsClients
-
- liftIO $ moveClientToLobby rnc ci
-
-{-
+processAction (clID, serverInfo, clients, rooms) (RoomRemoveThisClient msg) = do
(_, _, newClients, newRooms) <-
+ if roomID client /= 0 then
if isMaster client then
if (gameinprogress room) && (playersIn room > 1) then
(changeMaster >>= (\state -> foldM processAction state
@@ -205,15 +231,16 @@
AnswerOthersInRoom ["WARNING", "Admin left the room"],
RemoveClientTeams clID]))
else -- not in game
- processAction (clID, serverInfo, rnc) RemoveRoom
+ processAction (clID, serverInfo, clients, rooms) RemoveRoom
else -- not master
foldM
processAction
- (clID, serverInfo, rnc)
+ (clID, serverInfo, clients, rooms)
[AnswerOthersInRoom ["LEFT", nick client, msg],
RemoveClientTeams clID]
-
-
+ else -- in lobby
+ return (clID, serverInfo, clients, rooms)
+
return (
clID,
serverInfo,
@@ -232,7 +259,7 @@
}
insertClientToRoom r = r{playersIDs = IntSet.insert clID (playersIDs r)}
changeMaster = do
- processAction (newMasterId, serverInfo, rnc) $ AnswerThisClient ["ROOM_CONTROL_ACCESS", "1"]
+ processAction (newMasterId, serverInfo, clients, rooms) $ AnswerThisClient ["ROOM_CONTROL_ACCESS", "1"]
return (
clID,
serverInfo,
@@ -243,35 +270,34 @@
otherPlayersSet = IntSet.delete clID (playersIDs room)
newMasterId = IntSet.findMin otherPlayersSet
newMasterClient = clients ! newMasterId
--}
+
-processAction (AddRoom roomName roomPassword) = do
- Just clId <- gets clientIndex
- rnc <- gets roomsClients
- proto <- liftIO $ client'sM rnc clientProto clId
-
+processAction (clID, serverInfo, clients, rooms) (AddRoom roomName roomPassword) = do
+ let newServerInfo = serverInfo {nextRoomID = newID}
let room = newRoom{
- masterID = clId,
+ roomUID = newID,
+ masterID = clID,
name = roomName,
password = roomPassword,
- roomProto = proto
+ roomProto = (clientProto client)
}
- rId <- liftIO $ addRoom rnc room
-
- processAction $ MoveToRoom rId
-
- chans <- liftM (map sendChan) $! roomClientsS lobbyId
+ processAction (clID, serverInfo, clients, rooms) $ AnswerLobby ["ROOM", "ADD", roomName]
- mapM_ processAction [
- AnswerClients chans ["ROOM", "ADD", roomName]
- , ModifyClient (\cl -> cl{isMaster = True})
- ]
+ processAction (
+ clID,
+ newServerInfo,
+ adjust (\cl -> cl{isMaster = True}) clID clients,
+ insert newID room rooms
+ ) $ RoomAddThisClient newID
+ where
+ newID = (nextRoomID serverInfo) - 1
+ client = clients ! clID
-{-
-processAction (clID, serverInfo, rnc) (RemoveRoom) = do
- processAction (clID, serverInfo, rnc) $ AnswerLobby ["ROOM", "DEL", name room]
- processAction (clID, serverInfo, rnc) $ AnswerOthersInRoom ["ROOMABANDONED", name room]
+
+processAction (clID, serverInfo, clients, rooms) (RemoveRoom) = do
+ processAction (clID, serverInfo, clients, rooms) $ AnswerLobby ["ROOM", "DEL", name room]
+ processAction (clID, serverInfo, clients, rooms) $ AnswerOthersInRoom ["ROOMABANDONED", name room]
return (clID,
serverInfo,
Data.IntMap.map (\cl -> if roomID cl == rID then cl{roomID = 0, isMaster = False, isReady = False, teamsInGame = undefined} else cl) clients,
@@ -282,163 +308,139 @@
rID = roomID client
client = clients ! clID
--}
-processAction (UnreadyRoomClients) = do
- rnc <- gets roomsClients
- ri <- clientRoomA
- roomPlayers <- roomClientsS ri
- roomClIDs <- liftIO $ roomClientsIndicesM rnc ri
- processAction $ AnswerClients (map sendChan roomPlayers) ("NOT_READY" : map nick roomPlayers)
- liftIO $ mapM_ (modifyClient rnc (\cl -> cl{isReady = False})) roomClIDs
- processAction $ ModifyRoom (\r -> r{readyPlayers = 0})
+
+processAction (clID, serverInfo, clients, rooms) (UnreadyRoomClients) = do
+ processAction (clID, serverInfo, clients, rooms) $ AnswerThisRoom ("NOT_READY" : roomPlayers)
+ return (clID,
+ serverInfo,
+ Data.IntMap.map (\cl -> if roomID cl == rID then cl{isReady = False} else cl) clients,
+ adjust (\r -> r{readyPlayers = 0}) rID rooms)
+ where
+ room = rooms ! rID
+ rID = roomID client
+ client = clients ! clID
+ roomPlayers = Prelude.map (nick . (clients !)) roomPlayersIDs
+ roomPlayersIDs = IntSet.elems $ playersIDs room
-processAction (RemoveTeam teamName) = do
- rnc <- gets roomsClients
- cl <- client's id
- ri <- clientRoomA
- inGame <- liftIO $ room'sM rnc gameinprogress ri
- chans <- liftM (map sendChan . filter (/= cl)) $ roomClientsS ri
- if inGame then
- mapM_ processAction [
- AnswerClients chans ["REMOVE_TEAM", teamName],
- ModifyRoom (\r -> r{teams = Prelude.filter (\t -> teamName /= teamname t) $ teams r})
- ]
+processAction (clID, serverInfo, clients, rooms) (RemoveTeam teamName) = do
+ newRooms <- if not $ gameinprogress room then
+ do
+ processAction (clID, serverInfo, clients, rooms) $ AnswerOthersInRoom ["REMOVE_TEAM", teamName]
+ return $
+ adjust (\r -> r{teams = Prelude.filter (\t -> teamName /= teamname t) $ teams r}) rID rooms
else
- mapM_ processAction [
- AnswerClients chans ["EM", rmTeamMsg],
- ModifyRoom (\r -> r{
- teams = Prelude.filter (\t -> teamName /= teamname t) $ teams r,
- leftTeams = teamName : leftTeams r,
- roundMsgs = roundMsgs r Seq.|> rmTeamMsg
- })
- ]
+ do
+ processAction (clID, serverInfo, clients, rooms) $ AnswerOthersInRoom ["EM", rmTeamMsg]
+ return $
+ adjust (\r -> r{
+ teams = Prelude.filter (\t -> teamName /= teamname t) $ teams r,
+ leftTeams = teamName : leftTeams r,
+ roundMsgs = roundMsgs r Seq.|> rmTeamMsg
+ }) rID rooms
+ return (clID, serverInfo, clients, newRooms)
where
- rmTeamMsg = toEngineMsg $ (B.singleton 'F') `B.append` teamName
+ room = rooms ! rID
+ rID = roomID client
+ client = clients ! clID
+ rmTeamMsg = toEngineMsg $ 'F' : teamName
-processAction CheckRegistered = do
- (Just ci) <- gets clientIndex
- n <- client's nick
- h <- client's host
- db <- gets (dbQueries . serverInfo)
- liftIO $ writeChan db $ CheckAccount ci n h
- return ()
-{-
-processAction (clID, serverInfo, rnc) (ClearAccountsCache) = do
- writeChan (dbQueries serverInfo) ClearCache
- return (clID, serverInfo, rnc)
+processAction (clID, serverInfo, clients, rooms) (CheckRegistered) = do
+ writeChan (dbQueries serverInfo) $ CheckAccount (clientUID client) (nick client) (host client)
+ return (clID, serverInfo, clients, rooms)
where
client = clients ! clID
-processAction (clID, serverInfo, rnc) (Dump) = do
+processAction (clID, serverInfo, clients, rooms) (ClearAccountsCache) = do
+ writeChan (dbQueries serverInfo) ClearCache
+ return (clID, serverInfo, clients, rooms)
+ where
+ client = clients ! clID
+
+
+processAction (clID, serverInfo, clients, rooms) (Dump) = do
writeChan (sendChan $ clients ! clID) ["DUMP", show serverInfo, showTree clients, showTree rooms]
- return (clID, serverInfo, rnc)
--}
+ return (clID, serverInfo, clients, rooms)
-processAction (ProcessAccountInfo info) =
+
+processAction (clID, serverInfo, clients, rooms) (ProcessAccountInfo info) =
case info of
HasAccount passwd isAdmin -> do
- chan <- client's sendChan
- processAction $ AnswerClients [chan] ["ASKPASSWORD"]
+ infoM "Clients" $ show clID ++ " has account"
+ writeChan (sendChan $ clients ! clID) ["ASKPASSWORD"]
+ return (clID, serverInfo, adjust (\cl -> cl{webPassword = passwd, isAdministrator = isAdmin}) clID clients, rooms)
Guest -> do
- processAction JoinLobby
+ infoM "Clients" $ show clID ++ " is guest"
+ processAction (clID, serverInfo, adjust (\cl -> cl{logonPassed = True}) clID clients, rooms) MoveToLobby
Admin -> do
- mapM processAction [ModifyClient (\cl -> cl{isAdministrator = True}), JoinLobby]
- chan <- client's sendChan
- processAction $ AnswerClients [chan] ["ADMIN_ACCESS"]
+ infoM "Clients" $ show clID ++ " is admin"
+ foldM processAction (clID, serverInfo, adjust (\cl -> cl{logonPassed = True, isAdministrator = True}) clID clients, rooms) [MoveToLobby, AnswerThisClient ["ADMIN_ACCESS"]]
-processAction JoinLobby = do
- chan <- client's sendChan
- clientNick <- client's nick
- (lobbyNicks, clientsChans) <- liftM (unzip . Prelude.map (\c -> (nick c, sendChan c)) . Prelude.filter logonPassed) $! allClientsS
- mapM_ processAction $
- (AnswerClients clientsChans ["LOBBY:JOINED", clientNick])
- : [AnswerClients [chan] ("LOBBY:JOINED" : clientNick : lobbyNicks)]
- ++ [ModifyClient (\cl -> cl{logonPassed = True}), SendServerMessage]
+processAction (clID, serverInfo, clients, rooms) (MoveToLobby) =
+ foldM processAction (clID, serverInfo, clients, rooms) $
+ (RoomAddThisClient 0)
+ : answerLobbyNicks
+ ++ [SendServerMessage]
-{-
-processAction (clID, serverInfo, rnc) (RoomAddThisClient rID) =
- processAction (
- clID,
- serverInfo,
- adjust (\cl -> cl{roomID = rID, teamsInGame = if rID == 0 then teamsInGame cl else 0}) clID clients,
- adjust (\r -> r{playersIDs = IntSet.insert clID (playersIDs r), playersIn = (playersIn r) + 1}) rID $
- adjust (\r -> r{playersIDs = IntSet.delete clID (playersIDs r)}) 0 rooms
- ) joinMsg
+ -- ++ (answerServerMessage client clients)
where
- client = clients ! clID
- joinMsg = if rID == 0 then
- AnswerAllOthers ["LOBBY:JOINED", nick client]
- else
- AnswerThisRoom ["JOINED", nick client]
-
-processAction (clID, serverInfo, rnc) (KickClient kickID) =
- liftM2 replaceID (return clID) (processAction (kickID, serverInfo, rnc) $ ByeClient "Kicked")
+ lobbyNicks = Prelude.map nick $ Prelude.filter logonPassed $ elems clients
+ answerLobbyNicks = [AnswerThisClient ("LOBBY:JOINED": lobbyNicks) | not $ Prelude.null lobbyNicks]
-processAction (clID, serverInfo, rnc) (BanClient banNick) =
- return (clID, serverInfo, rnc)
+processAction (clID, serverInfo, clients, rooms) (KickClient kickID) =
+ liftM2 replaceID (return clID) (processAction (kickID, serverInfo, clients, rooms) $ ByeClient "Kicked")
+
+
+processAction (clID, serverInfo, clients, rooms) (BanClient banNick) =
+ return (clID, serverInfo, clients, rooms)
-processAction (clID, serverInfo, rnc) (KickRoomClient kickID) = do
+processAction (clID, serverInfo, clients, rooms) (KickRoomClient kickID) = do
writeChan (sendChan $ clients ! kickID) ["KICKED"]
- liftM2 replaceID (return clID) (processAction (kickID, serverInfo, rnc) $ RoomRemoveThisClient "kicked")
+ liftM2 replaceID (return clID) (processAction (kickID, serverInfo, clients, rooms) $ RoomRemoveThisClient "kicked")
-processAction (clID, serverInfo, rnc) (RemoveClientTeams teamsClID) =
+processAction (clID, serverInfo, clients, rooms) (RemoveClientTeams teamsClID) =
liftM2 replaceID (return clID) $
- foldM processAction (teamsClID, serverInfo, rnc) removeTeamsActions
+ foldM processAction (teamsClID, serverInfo, clients, rooms) removeTeamsActions
where
client = clients ! teamsClID
room = rooms ! (roomID client)
teamsToRemove = Prelude.filter (\t -> teamowner t == nick client) $ teams room
removeTeamsActions = Prelude.map (RemoveTeam . teamname) teamsToRemove
--}
+
-processAction (AddClient client) = do
- rnc <- gets roomsClients
- si <- gets serverInfo
- liftIO $ do
- ci <- addClient rnc client
- forkIO $ clientRecvLoop (clientSocket client) (coreChan si) ci
- forkIO $ clientSendLoop (clientSocket client) (sendChan client) ci
+processAction (clID, serverInfo, clients, rooms) (AddClient client) = do
+ let updatedClients = insert (clientUID client) client clients
+ infoM "Clients" (show (clientUID client) ++ ": New client. Time: " ++ show (connectTime client))
+ writeChan (sendChan client) ["CONNECTED", "Hedgewars server http://www.hedgewars.org/"]
- infoM "Clients" (show ci ++ ": New client. Time: " ++ show (connectTime client))
-
- processAction $ AnswerClients [sendChan client] ["CONNECTED", "Hedgewars server http://www.hedgewars.org/"]
-{- let newLogins = takeWhile (\(_ , time) -> (connectTime client) `diffUTCTime` time <= 11) $ lastLogins serverInfo
+ let newLogins = takeWhile (\(_ , time) -> (connectTime client) `diffUTCTime` time <= 11) $ lastLogins serverInfo
- if False && (isJust $ host client `Prelude.lookup` newLogins) then
- processAction (ci, serverInfo{lastLogins = newLogins}, rnc) $ ByeClient "Reconnected too fast"
- else
- return (ci, serverInfo)
--}
-
+ if isJust $ host client `Prelude.lookup` newLogins then
+ processAction (clID, serverInfo{lastLogins = newLogins}, updatedClients, rooms) $ ByeClient "Reconnected too fast"
+ else
+ return (clID, serverInfo{lastLogins = (host client, connectTime client) : newLogins}, updatedClients, rooms)
-processAction PingAll = do
- rnc <- gets roomsClients
- liftIO (allClientsM rnc) >>= mapM_ (kickTimeouted rnc)
- cis <- liftIO $ allClientsM rnc
- chans <- liftIO $ mapM (client'sM rnc sendChan) cis
- liftIO $ mapM_ (modifyClient rnc (\cl -> cl{pingsQueue = pingsQueue cl + 1})) cis
- processAction $ AnswerClients chans ["PING"]
+processAction (clID, serverInfo, clients, rooms) PingAll = do
+ (_, _, newClients, newRooms) <- foldM kickTimeouted (clID, serverInfo, clients, rooms) $ elems clients
+ processAction (clID,
+ serverInfo,
+ Data.IntMap.map (\cl -> cl{pingsQueue = pingsQueue cl + 1}) newClients,
+ newRooms) $ AnswerAll ["PING"]
where
- kickTimeouted rnc ci = do
- pq <- liftIO $ client'sM rnc pingsQueue ci
- when (pq > 0) $
- withStateT (\as -> as{clientIndex = Just ci}) $
- processAction (ByeClient "Ping timeout")
+ kickTimeouted (clID, serverInfo, clients, rooms) client =
+ if pingsQueue client > 0 then
+ processAction (clientUID client, serverInfo, clients, rooms) $ ByeClient "Ping timeout"
+ else
+ return (clID, serverInfo, clients, rooms)
-processAction (StatsAction) = do
- rnc <- gets roomsClients
- si <- gets serverInfo
- (roomsNum, clientsNum) <- liftIO $ withRoomsAndClients rnc stats
- liftIO $ writeChan (dbQueries si) $ SendStats clientsNum (roomsNum - 1)
- where
- stats irnc = (length $ allRooms irnc, length $ allClients irnc)
-
+processAction (clID, serverInfo, clients, rooms) (StatsAction) = do
+ writeChan (dbQueries serverInfo) $ SendStats (size clients) (size rooms - 1)
+ return (clID, serverInfo, clients, rooms)
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/CMakeLists.txt
--- a/gameServer/CMakeLists.txt Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/CMakeLists.txt Tue Jan 04 12:53:46 2011 +0100
@@ -1,48 +1,43 @@
find_program(ghc_executable ghc)
if(NOT ghc_executable)
- message(FATAL_ERROR "Cannot find GHC")
+ message(FATAL_ERROR "Cannot find GHC")
endif(NOT ghc_executable)
set(hwserver_sources
- OfficialServer/DBInteraction.hs
- Actions.hs
- ClientIO.hs
- CoreTypes.hs
- HWProtoCore.hs
- HWProtoInRoomState.hs
- HWProtoLobbyState.hs
- HWProtoNEState.hs
- HandlerUtils.hs
- NetRoutines.hs
- Opts.hs
- RoomsAndClients.hs
- ServerCore.hs
- ServerState.hs
- Store.hs
- Utils.hs
- hedgewars-server.hs
- )
+ OfficialServer/DBInteraction.hs
+ Actions.hs
+ ClientIO.hs
+ CoreTypes.hs
+ HWProtoCore.hs
+ HWProtoInRoomState.hs
+ HWProtoLobbyState.hs
+ HWProtoNEState.hs
+ NetRoutines.hs
+ Opts.hs
+ ServerCore.hs
+ Utils.hs
+ hedgewars-server.hs
+ )
set(hwserv_main ${hedgewars_SOURCE_DIR}/gameServer/hedgewars-server.hs)
set(ghc_flags
- -Wall
- --make ${hwserv_main}
- -i${hedgewars_SOURCE_DIR}/gameServer
- -o ${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX}
- -odir ${CMAKE_CURRENT_BINARY_DIR}
- -hidir ${CMAKE_CURRENT_BINARY_DIR})
+ --make ${hwserv_main}
+ -i${hedgewars_SOURCE_DIR}/gameServer
+ -o ${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX}
+ -odir ${CMAKE_CURRENT_BINARY_DIR}
+ -hidir ${CMAKE_CURRENT_BINARY_DIR})
set(ghc_flags ${haskell_compiler_flags_cmn} ${ghc_flags})
add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX}"
- COMMAND "${ghc_executable}"
- ARGS ${ghc_flags}
- MAIN_DEPENDENCY ${hwserv_main}
- DEPENDS ${hwserver_sources}
- )
+ COMMAND "${ghc_executable}"
+ ARGS ${ghc_flags}
+ MAIN_DEPENDENCY ${hwserv_main}
+ DEPENDS ${hwserver_sources}
+ )
add_custom_target(hedgewars-server ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX}")
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/ClientIO.hs
--- a/gameServer/ClientIO.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/ClientIO.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,4 +1,4 @@
-{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
module ClientIO where
import qualified Control.Exception as Exception
@@ -6,71 +6,45 @@
import Control.Concurrent
import Control.Monad
import System.IO
-import Network
-import Network.Socket.ByteString
-import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.UTF8 as BUTF8
+import qualified Data.ByteString as B
----------------
import CoreTypes
-import RoomsAndClients
-import Utils
-
-pDelim :: B.ByteString
-pDelim = B.pack "\n\n"
-
-bs2Packets :: B.ByteString -> ([[B.ByteString]], B.ByteString)
-bs2Packets buf = unfoldrE extractPackets buf
- where
- extractPackets :: B.ByteString -> Either B.ByteString ([B.ByteString], B.ByteString)
- extractPackets buf =
- let buf' = until (not . B.isPrefixOf pDelim) (B.drop 2) buf in
- let (bsPacket, bufTail) = B.breakSubstring pDelim buf' in
- if B.null bufTail then
- Left bsPacket
- else
- if B.null bsPacket then
- Left bufTail
- else
- Right (B.splitWith (== '\n') bsPacket, bufTail)
-
+listenLoop :: Handle -> Int -> [String] -> Chan CoreMessage -> Int -> IO ()
+listenLoop handle linesNumber buf chan clientID = do
+ str <- liftM BUTF8.toString $ B.hGetLine handle
+ if (linesNumber > 50) || (length str > 20000) then
+ writeChan chan $ ClientMessage (clientID, ["QUIT", "Protocol violation"])
+ else
+ if str == "" then do
+ writeChan chan $ ClientMessage (clientID, buf)
+ yield
+ listenLoop handle 0 [] chan clientID
+ else
+ listenLoop handle (linesNumber + 1) (buf ++ [str]) chan clientID
-listenLoop :: Socket -> Chan CoreMessage -> ClientIndex -> IO ()
-listenLoop sock chan ci = recieveWithBufferLoop B.empty
- where
- recieveWithBufferLoop recvBuf = do
- recvBS <- recv sock 4096
--- putStrLn $ show sock ++ " got smth: " ++ (show $ B.length recvBS)
- unless (B.null recvBS) $ do
- let (packets, newrecvBuf) = bs2Packets $ B.append recvBuf recvBS
- forM_ packets sendPacket
- recieveWithBufferLoop newrecvBuf
-
- sendPacket packet = writeChan chan $ ClientMessage (ci, packet)
-
+clientRecvLoop :: Handle -> Chan CoreMessage -> Int -> IO ()
+clientRecvLoop handle chan clientID =
+ listenLoop handle 0 [] chan clientID
+ `catch` (\e -> clientOff (show e) >> return ())
+ where clientOff msg = writeChan chan $ ClientMessage (clientID, ["QUIT", msg]) -- if the client disconnects, we perform as if it sent QUIT message
-clientRecvLoop :: Socket -> Chan CoreMessage -> ClientIndex -> IO ()
-clientRecvLoop s chan ci = do
- msg <- (listenLoop s chan ci >> return "Connection closed") `catch` (return . B.pack . show)
- clientOff msg
- where
- clientOff msg = mapM_ (writeChan chan) [ClientMessage (ci, ["QUIT", msg]), Remove ci]
-
-
+clientSendLoop :: Handle -> Chan CoreMessage -> Chan [String] -> Int -> IO()
+clientSendLoop handle coreChan chan clientID = do
+ answer <- readChan chan
+ doClose <- Exception.handle
+ (\(e :: Exception.IOException) -> if isQuit answer then return True else sendQuit e >> return False) $ do
+ B.hPutStrLn handle $ BUTF8.fromString $ unlines answer
+ hFlush handle
+ return $ isQuit answer
-clientSendLoop :: Socket -> Chan [B.ByteString] -> ClientIndex -> IO ()
-clientSendLoop s chan ci = do
- answer <- readChan chan
- Exception.handle
- (\(e :: Exception.IOException) -> when (not $ isQuit answer) $ sendQuit e) $ do
- sendAll s $ (B.unlines answer) `B.append` (B.singleton '\n')
-
- if (isQuit answer) then
- Exception.handle (\(_ :: Exception.IOException) -> putStrLn "error on sClose") $ sClose s
+ if doClose then
+ Exception.handle (\(_ :: Exception.IOException) -> putStrLn "error on hClose") $ hClose handle
else
- clientSendLoop s chan ci
+ clientSendLoop handle coreChan chan clientID
where
- --sendQuit e = writeChan coreChan $ ClientMessage (ci, ["QUIT", B.pack $ show e])
- sendQuit e = putStrLn $ show e
+ sendQuit e = writeChan coreChan $ ClientMessage (clientID, ["QUIT", show e])
isQuit ("BYE":xs) = True
isQuit _ = False
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/CoreTypes.hs
--- a/gameServer/CoreTypes.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/CoreTypes.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,4 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
module CoreTypes where
import System.IO
@@ -6,95 +5,102 @@
import Control.Concurrent.STM
import Data.Word
import qualified Data.Map as Map
+import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
import Data.Sequence(Seq, empty)
import Data.Time
import Network
import Data.Function
-import Data.ByteString.Char8 as B
-import RoomsAndClients
-
-type ClientChan = Chan [B.ByteString]
data ClientInfo =
ClientInfo
{
- sendChan :: ClientChan,
- clientSocket :: Socket,
- host :: B.ByteString,
+ clientUID :: !Int,
+ sendChan :: Chan [String],
+ clientHandle :: Handle,
+ host :: String,
connectTime :: UTCTime,
- nick :: B.ByteString,
- webPassword :: B.ByteString,
+ nick :: String,
+ webPassword :: String,
logonPassed :: Bool,
clientProto :: !Word16,
- roomID :: RoomIndex,
+ roomID :: !Int,
pingsQueue :: !Word,
isMaster :: Bool,
- isReady :: !Bool,
+ isReady :: Bool,
isAdministrator :: Bool,
- clientClan :: B.ByteString,
+ clientClan :: String,
teamsInGame :: Word
}
instance Show ClientInfo where
- show ci = " nick: " ++ (unpack $ nick ci) ++ " host: " ++ (unpack $ host ci)
+ show ci = show (clientUID ci)
+ ++ " nick: " ++ (nick ci)
+ ++ " host: " ++ (host ci)
instance Eq ClientInfo where
- (==) = (==) `on` clientSocket
+ (==) = (==) `on` clientHandle
data HedgehogInfo =
- HedgehogInfo B.ByteString B.ByteString
+ HedgehogInfo String String
data TeamInfo =
TeamInfo
{
- teamownerId :: ClientIndex,
- teamowner :: B.ByteString,
- teamname :: B.ByteString,
- teamcolor :: B.ByteString,
- teamgrave :: B.ByteString,
- teamfort :: B.ByteString,
- teamvoicepack :: B.ByteString,
- teamflag :: B.ByteString,
+ teamownerId :: !Int,
+ teamowner :: String,
+ teamname :: String,
+ teamcolor :: String,
+ teamgrave :: String,
+ teamfort :: String,
+ teamvoicepack :: String,
+ teamflag :: String,
difficulty :: Int,
hhnum :: Int,
hedgehogs :: [HedgehogInfo]
}
instance Show TeamInfo where
- show ti = "owner: " ++ (unpack $ teamowner ti)
- ++ "name: " ++ (unpack $ teamname ti)
- ++ "color: " ++ (unpack $ teamcolor ti)
+ show ti = "owner: " ++ (teamowner ti)
+ ++ "name: " ++ (teamname ti)
+ ++ "color: " ++ (teamcolor ti)
data RoomInfo =
RoomInfo
{
- masterID :: ClientIndex,
- name :: B.ByteString,
- password :: B.ByteString,
+ roomUID :: !Int,
+ masterID :: !Int,
+ name :: String,
+ password :: String,
roomProto :: Word16,
teams :: [TeamInfo],
gameinprogress :: Bool,
playersIn :: !Int,
readyPlayers :: !Int,
+ playersIDs :: IntSet.IntSet,
isRestrictedJoins :: Bool,
isRestrictedTeams :: Bool,
- roundMsgs :: Seq B.ByteString,
- leftTeams :: [B.ByteString],
+ roundMsgs :: Seq String,
+ leftTeams :: [String],
teamsAtStart :: [TeamInfo],
- params :: Map.Map B.ByteString [B.ByteString]
+ params :: Map.Map String [String]
}
instance Show RoomInfo where
- show ri = ", players: " ++ show (playersIn ri)
+ show ri = show (roomUID ri)
+ ++ ", players ids: " ++ show (IntSet.size $ playersIDs ri)
+ ++ ", players: " ++ show (playersIn ri)
++ ", ready: " ++ show (readyPlayers ri)
++ ", teams: " ++ show (teams ri)
-newRoom :: RoomInfo
+instance Eq RoomInfo where
+ (==) = (==) `on` roomUID
+
newRoom = (
RoomInfo
- undefined
+ 0
+ 0
""
""
0
@@ -102,6 +108,7 @@
False
0
0
+ IntSet.empty
False
False
Data.Sequence.empty
@@ -121,30 +128,29 @@
ServerInfo
{
isDedicated :: Bool,
- serverMessage :: B.ByteString,
- serverMessageForOldVersions :: B.ByteString,
+ serverMessage :: String,
+ serverMessageForOldVersions :: String,
latestReleaseVersion :: Word16,
listenPort :: PortNumber,
nextRoomID :: Int,
- dbHost :: B.ByteString,
- dbLogin :: B.ByteString,
- dbPassword :: B.ByteString,
- lastLogins :: [(B.ByteString, UTCTime)],
+ dbHost :: String,
+ dbLogin :: String,
+ dbPassword :: String,
+ lastLogins :: [(String, UTCTime)],
stats :: TMVar StatisticsInfo,
coreChan :: Chan CoreMessage,
dbQueries :: Chan DBQuery
}
instance Show ServerInfo where
- show _ = "Server Info"
+ show si = "Server Info"
-newServerInfo :: TMVar StatisticsInfo -> Chan CoreMessage -> Chan DBQuery -> ServerInfo
newServerInfo = (
ServerInfo
True
"http://www.hedgewars.org/
"
- "Hedgewars 0.9.14.1 is out! Please update.
Download page here
"
- 35
+ "Hedgewars 0.9.15 is out! Please update.
Download page here
"
+ 37
46631
0
""
@@ -154,31 +160,29 @@
)
data AccountInfo =
- HasAccount B.ByteString Bool
+ HasAccount String Bool
| Guest
| Admin
deriving (Show, Read)
data DBQuery =
- CheckAccount ClientIndex B.ByteString B.ByteString
+ CheckAccount Int String String
| ClearCache
| SendStats Int Int
deriving (Show, Read)
data CoreMessage =
Accept ClientInfo
- | ClientMessage (ClientIndex, [B.ByteString])
- | ClientAccountInfo (ClientIndex, AccountInfo)
+ | ClientMessage (Int, [String])
+ | ClientAccountInfo (Int, AccountInfo)
| TimerAction Int
- | Remove ClientIndex
+
+type Clients = IntMap.IntMap ClientInfo
+type Rooms = IntMap.IntMap RoomInfo
-instance Show CoreMessage where
- show (Accept _) = "Accept"
- show (ClientMessage _) = "ClientMessage"
- show (ClientAccountInfo _) = "ClientAccountInfo"
- show (TimerAction _) = "TimerAction"
- show (Remove _) = "Remove"
-
-type MRnC = MRoomsAndClients RoomInfo ClientInfo
-type IRnC = IRoomsAndClients RoomInfo ClientInfo
+--type ClientsTransform = [ClientInfo] -> [ClientInfo]
+--type RoomsTransform = [RoomInfo] -> [RoomInfo]
+--type HandlesSelector = ClientInfo -> [ClientInfo] -> [RoomInfo] -> [ClientInfo]
+--type Answer = ServerInfo -> (HandlesSelector, [String])
+type ClientsSelector = Clients -> Rooms -> [Int]
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/HWProtoCore.hs
--- a/gameServer/HWProtoCore.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/HWProtoCore.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,10 +1,8 @@
-{-# LANGUAGE OverloadedStrings #-}
module HWProtoCore where
import qualified Data.IntMap as IntMap
import Data.Foldable
import Data.Maybe
-import Control.Monad.Reader
--------------------------------------
import CoreTypes
import Actions
@@ -12,37 +10,35 @@
import HWProtoNEState
import HWProtoLobbyState
import HWProtoInRoomState
-import HandlerUtils
-import RoomsAndClients
handleCmd, handleCmd_loggedin :: CmdHandler
-
-handleCmd ["PING"] = answerClient ["PONG"]
+handleCmd clID _ _ ["PING"] = [AnswerThisClient ["PONG"]]
-
-handleCmd ("QUIT" : xs) = return [ByeClient msg]
+handleCmd clID clients rooms ("QUIT" : xs) =
+ [ByeClient msg]
where
msg = if not $ null xs then head xs else ""
-{-
-handleCmd ["PONG"] =
+
+handleCmd clID clients _ ["PONG"] =
if pingsQueue client == 0 then
[ProtocolError "Protocol violation"]
else
[ModifyClient (\cl -> cl{pingsQueue = pingsQueue cl - 1})]
where
client = clients IntMap.! clID
--}
+
-handleCmd cmd = do
- (ci, irnc) <- ask
- if logonPassed (irnc `client` ci) then
- handleCmd_loggedin cmd
- else
- handleCmd_NotEntered cmd
+handleCmd clID clients rooms cmd =
+ if not $ logonPassed client then
+ handleCmd_NotEntered clID clients rooms cmd
+ else
+ handleCmd_loggedin clID clients rooms cmd
+ where
+ client = clients IntMap.! clID
-{-
+
handleCmd_loggedin clID clients rooms ["INFO", asknick] =
if noSuchClient then
[]
@@ -66,12 +62,11 @@
then if teamsInGame client > 0 then "(playing)" else "(spectating)"
else ""
--}
-
-handleCmd_loggedin cmd = do
- (ci, rnc) <- ask
- if clientRoom rnc ci == lobbyId then
- handleCmd_lobby cmd
- else
- handleCmd_inRoom cmd
+handleCmd_loggedin clID clients rooms cmd =
+ if roomID client == 0 then
+ handleCmd_lobby clID clients rooms cmd
+ else
+ handleCmd_inRoom clID clients rooms cmd
+ where
+ client = clients IntMap.! clID
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/HWProtoInRoomState.hs
--- a/gameServer/HWProtoInRoomState.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/HWProtoInRoomState.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,240 +1,182 @@
-{-# LANGUAGE OverloadedStrings #-}
module HWProtoInRoomState where
import qualified Data.Foldable as Foldable
+import qualified Data.IntMap as IntMap
import qualified Data.Map as Map
import Data.Sequence(Seq, (|>), (><), fromList, empty)
import Data.List
import Data.Maybe
-import qualified Data.ByteString.Char8 as B
-import Control.Monad
-import Control.Monad.Reader
--------------------------------------
import CoreTypes
import Actions
import Utils
-import HandlerUtils
-import RoomsAndClients
+
handleCmd_inRoom :: CmdHandler
-handleCmd_inRoom ["CHAT", msg] = do
- n <- clientNick
- s <- roomOthersChans
- return [AnswerClients s ["CHAT", n, msg]]
+handleCmd_inRoom clID clients _ ["CHAT", msg] =
+ [AnswerOthersInRoom ["CHAT", clientNick, msg]]
+ where
+ clientNick = nick $ clients IntMap.! clID
-handleCmd_inRoom ["PART"] = return [MoveToLobby "part"]
-handleCmd_inRoom ["PART", msg] = return [MoveToLobby $ "part: " `B.append` msg]
+handleCmd_inRoom clID clients rooms ["PART"] =
+ [RoomRemoveThisClient "part"]
+ where
+ client = clients IntMap.! clID
-handleCmd_inRoom ("CFG" : paramName : paramStrs)
- | null paramStrs = return [ProtocolError "Empty config entry"]
- | otherwise = do
- chans <- roomOthersChans
- cl <- thisClient
- if isMaster cl then
- return [
- ModifyRoom (\r -> r{params = Map.insert paramName paramStrs (params r)}),
- AnswerClients chans ("CFG" : paramName : paramStrs)]
- else
- return [ProtocolError "Not room master"]
+handleCmd_inRoom clID clients rooms ("CFG" : paramName : paramStrs)
+ | null paramStrs = [ProtocolError "Empty config entry"]
+ | isMaster client =
+ [ModifyRoom (\r -> r{params = Map.insert paramName paramStrs (params r)}),
+ AnswerOthersInRoom ("CFG" : paramName : paramStrs)]
+ | otherwise = [ProtocolError "Not room master"]
+ where
+ client = clients IntMap.! clID
-handleCmd_inRoom ("ADD_TEAM" : name : color : grave : fort : voicepack : flag : difStr : hhsInfo)
- | length hhsInfo /= 16 = return [ProtocolError "Corrupted hedgehogs info"]
- | otherwise = do
- (ci, rnc) <- ask
- r <- thisRoom
- clNick <- clientNick
- clChan <- thisClientChans
- othersChans <- roomOthersChans
- return $
- if not . null . drop 5 $ teams r then
- [Warning "too many teams"]
- else if canAddNumber r <= 0 then
- [Warning "too many hedgehogs"]
- else if isJust $ findTeam r then
- [Warning "There's already a team with same name in the list"]
- else if gameinprogress r then
- [Warning "round in progress"]
- else if isRestrictedTeams r then
- [Warning "restricted"]
- else
- [ModifyRoom (\r -> r{teams = teams r ++ [newTeam ci clNick r]}),
- ModifyClient (\c -> c{teamsInGame = teamsInGame c + 1, clientClan = color}),
- AnswerClients clChan ["TEAM_ACCEPTED", name],
- AnswerClients othersChans $ teamToNet $ newTeam ci clNick r,
- AnswerClients othersChans ["TEAM_COLOR", name, color]
- ]
- where
- canAddNumber r = 48 - (sum . map hhnum $ teams r)
- findTeam = find (\t -> name == teamname t) . teams
- newTeam ci clNick r = (TeamInfo ci clNick name color grave fort voicepack flag difficulty (newTeamHHNum r) (hhsList hhsInfo))
- difficulty = case B.readInt difStr of
- Just (i, t) | B.null t -> fromIntegral i
- otherwise -> 0
+handleCmd_inRoom clID clients rooms ("ADD_TEAM" : name : color : grave : fort : voicepack : flag : difStr : hhsInfo)
+ | length hhsInfo == 15 && clientProto client < 30 = handleCmd_inRoom clID clients rooms ("ADD_TEAM" : name : color : grave : fort : voicepack : " " : flag : difStr : hhsInfo)
+ | length hhsInfo /= 16 = [ProtocolError "Corrupted hedgehogs info"]
+ | length (teams room) == 8 = [Warning "too many teams"]
+ | canAddNumber <= 0 = [Warning "too many hedgehogs"]
+ | isJust findTeam = [Warning "There's already a team with same name in the list"]
+ | gameinprogress room = [Warning "round in progress"]
+ | isRestrictedTeams room = [Warning "restricted"]
+ | otherwise =
+ [ModifyRoom (\r -> r{teams = teams r ++ [newTeam]}),
+ ModifyClient (\c -> c{teamsInGame = teamsInGame c + 1, clientClan = color}),
+ AnswerThisClient ["TEAM_ACCEPTED", name],
+ AnswerOthersInRoom $ teamToNet (clientProto client) newTeam,
+ AnswerOthersInRoom ["TEAM_COLOR", name, color]
+ ]
+ where
+ client = clients IntMap.! clID
+ room = rooms IntMap.! (roomID client)
+ canAddNumber = 48 - (sum . map hhnum $ teams room)
+ findTeam = find (\t -> name == teamname t) $ teams room
+ newTeam = (TeamInfo clID (nick client) name color grave fort voicepack flag difficulty newTeamHHNum (hhsList hhsInfo))
+ difficulty = fromMaybe 0 (maybeRead difStr :: Maybe Int)
hhsList [] = []
- hhsList [_] = error "Hedgehogs list with odd elements number"
hhsList (n:h:hhs) = HedgehogInfo n h : hhsList hhs
- newTeamHHNum r = min 4 (canAddNumber r)
-
-handleCmd_inRoom ["REMOVE_TEAM", name] = do
- (ci, rnc) <- ask
- r <- thisRoom
- clNick <- clientNick
-
- let maybeTeam = findTeam r
- let team = fromJust maybeTeam
+ newTeamHHNum = min 4 canAddNumber
- return $
- if isNothing $ findTeam r then
- [Warning "REMOVE_TEAM: no such team"]
- else if clNick /= teamowner team then
- [ProtocolError "Not team owner!"]
- else
- [RemoveTeam name,
- ModifyClient
- (\c -> c{
- teamsInGame = teamsInGame c - 1,
- clientClan = if teamsInGame c == 1 then undefined else anotherTeamClan ci r
- })
- ]
+handleCmd_inRoom clID clients rooms ["REMOVE_TEAM", teamName]
+ | noSuchTeam = [Warning "REMOVE_TEAM: no such team"]
+ | nick client /= teamowner team = [ProtocolError "Not team owner!"]
+ | otherwise =
+ [RemoveTeam teamName,
+ ModifyClient (\c -> c{teamsInGame = teamsInGame c - 1, clientClan = if teamsInGame client == 1 then undefined else anotherTeamClan})
+ ]
where
- anotherTeamClan ci = teamcolor . fromJust . find (\t -> teamownerId t == ci) . teams
- findTeam = find (\t -> name == teamname t) . teams
+ client = clients IntMap.! clID
+ room = rooms IntMap.! (roomID client)
+ noSuchTeam = isNothing findTeam
+ team = fromJust findTeam
+ findTeam = find (\t -> teamName == teamname t) $ teams room
+ anotherTeamClan = teamcolor $ fromJust $ find (\t -> teamownerId t == clID) $ teams room
-handleCmd_inRoom ["HH_NUM", teamName, numberStr] = do
- cl <- thisClient
- others <- roomOthersChans
- r <- thisRoom
-
- let maybeTeam = findTeam r
- let team = fromJust maybeTeam
-
- return $
- if not $ isMaster cl then
- [ProtocolError "Not room master"]
- else if hhNumber < 1 || hhNumber > 8 || isNothing maybeTeam || hhNumber > (canAddNumber r) + (hhnum team) then
- []
- else
- [ModifyRoom $ modifyTeam team{hhnum = hhNumber},
- AnswerClients others ["HH_NUM", teamName, B.pack $ show hhNumber]]
+handleCmd_inRoom clID clients rooms ["HH_NUM", teamName, numberStr]
+ | not $ isMaster client = [ProtocolError "Not room master"]
+ | hhNumber < 1 || hhNumber > 8 || noSuchTeam || hhNumber > (canAddNumber + (hhnum team)) = []
+ | otherwise =
+ [ModifyRoom $ modifyTeam team{hhnum = hhNumber},
+ AnswerOthersInRoom ["HH_NUM", teamName, show hhNumber]]
where
- hhNumber = case B.readInt numberStr of
- Just (i, t) | B.null t -> fromIntegral i
- otherwise -> 0
- findTeam = find (\t -> teamName == teamname t) . teams
- canAddNumber = (-) 48 . sum . map hhnum . teams
-
+ client = clients IntMap.! clID
+ room = rooms IntMap.! (roomID client)
+ hhNumber = fromMaybe 0 (maybeRead numberStr :: Maybe Int)
+ noSuchTeam = isNothing findTeam
+ team = fromJust findTeam
+ findTeam = find (\t -> teamName == teamname t) $ teams room
+ canAddNumber = 48 - (sum . map hhnum $ teams room)
-handleCmd_inRoom ["TEAM_COLOR", teamName, newColor] = do
- cl <- thisClient
- others <- roomOthersChans
- r <- thisRoom
-
- let maybeTeam = findTeam r
- let team = fromJust maybeTeam
-
- return $
- if not $ isMaster cl then
- [ProtocolError "Not room master"]
- else if isNothing maybeTeam then
- []
- else
- [ModifyRoom $ modifyTeam team{teamcolor = newColor},
- AnswerClients others ["TEAM_COLOR", teamName, newColor],
+handleCmd_inRoom clID clients rooms ["TEAM_COLOR", teamName, newColor]
+ | not $ isMaster client = [ProtocolError "Not room master"]
+ | noSuchTeam = []
+ | otherwise = [ModifyRoom $ modifyTeam team{teamcolor = newColor},
+ AnswerOthersInRoom ["TEAM_COLOR", teamName, newColor],
ModifyClient2 (teamownerId team) (\c -> c{clientClan = newColor})]
where
- findTeam = find (\t -> teamName == teamname t) . teams
+ noSuchTeam = isNothing findTeam
+ team = fromJust findTeam
+ findTeam = find (\t -> teamName == teamname t) $ teams room
+ client = clients IntMap.! clID
+ room = rooms IntMap.! (roomID client)
-handleCmd_inRoom ["TOGGLE_READY"] = do
- cl <- thisClient
- chans <- roomClientsChans
- return [
- ModifyClient (\c -> c{isReady = not $ isReady cl}),
- ModifyRoom (\r -> r{readyPlayers = readyPlayers r + (if isReady cl then -1 else 1)}),
- AnswerClients chans [if isReady cl then "NOT_READY" else "READY", nick cl]
- ]
+handleCmd_inRoom clID clients rooms ["TOGGLE_READY"] =
+ [ModifyClient (\c -> c{isReady = not $ isReady client}),
+ ModifyRoom (\r -> r{readyPlayers = readyPlayers r + (if isReady client then -1 else 1)}),
+ AnswerThisRoom [if isReady client then "NOT_READY" else "READY", nick client]]
+ where
+ client = clients IntMap.! clID
-handleCmd_inRoom ["START_GAME"] = do
- cl <- thisClient
- r <- thisRoom
- chans <- roomClientsChans
- if isMaster cl && (playersIn r == readyPlayers r) && (not $ gameinprogress r) then
- if enoughClans r then
- return [
- ModifyRoom
+handleCmd_inRoom clID clients rooms ["START_GAME"] =
+ if isMaster client && (playersIn room == readyPlayers room) && (not . gameinprogress) room then
+ if enoughClans then
+ [ModifyRoom
(\r -> r{
gameinprogress = True,
roundMsgs = empty,
leftTeams = [],
teamsAtStart = teams r}
),
- AnswerClients chans ["RUN_GAME"]
- ]
- else
- return [Warning "Less than two clans!"]
+ AnswerThisRoom ["RUN_GAME"]]
else
- return []
+ [Warning "Less than two clans!"]
+ else
+ []
where
- enoughClans = not . null . drop 1 . group . map teamcolor . teams
+ client = clients IntMap.! clID
+ room = rooms IntMap.! (roomID client)
+ enoughClans = not $ null $ drop 1 $ group $ map teamcolor $ teams room
-handleCmd_inRoom ["EM", msg] = do
- cl <- thisClient
- r <- thisRoom
- chans <- roomOthersChans
-
- if (teamsInGame cl > 0) && isLegal then
- return $ (AnswerClients chans ["EM", msg]) : [ModifyRoom (\r -> r{roundMsgs = roundMsgs r |> msg}) | not isKeepAlive]
- else
- return []
+handleCmd_inRoom clID clients rooms ["EM", msg] =
+ if (teamsInGame client > 0) && isLegal then
+ (AnswerOthersInRoom ["EM", msg]) : [ModifyRoom (\r -> r{roundMsgs = roundMsgs r |> msg}) | not isKeepAlive]
+ else
+ []
where
+ client = clients IntMap.! clID
(isLegal, isKeepAlive) = checkNetCmd msg
-
-handleCmd_inRoom ["ROUNDFINISHED"] = do
- cl <- thisClient
- r <- thisRoom
- chans <- roomClientsChans
-
- if isMaster cl && (gameinprogress r) then
- return $ (ModifyRoom
+handleCmd_inRoom clID clients rooms ["ROUNDFINISHED"] =
+ if isMaster client then
+ [ModifyRoom
(\r -> r{
gameinprogress = False,
readyPlayers = 0,
roundMsgs = empty,
leftTeams = [],
teamsAtStart = []}
- ))
- : UnreadyRoomClients
- : answerRemovedTeams chans r
- else
- return []
+ ),
+ UnreadyRoomClients
+ ] ++ answerRemovedTeams
+ else
+ []
where
- answerRemovedTeams chans = map (\t -> AnswerClients chans ["REMOVE_TEAM", t]) . leftTeams
-
-handleCmd_inRoom ["TOGGLE_RESTRICT_JOINS"] = do
- cl <- thisClient
- return $
- if not $ isMaster cl then
- [ProtocolError "Not room master"]
- else
- [ModifyRoom (\r -> r{isRestrictedJoins = not $ isRestrictedJoins r})]
+ client = clients IntMap.! clID
+ room = rooms IntMap.! (roomID client)
+ answerRemovedTeams = map (\t -> AnswerThisRoom ["REMOVE_TEAM", t]) $ leftTeams room
-handleCmd_inRoom ["TOGGLE_RESTRICT_TEAMS"] = do
- cl <- thisClient
- return $
- if not $ isMaster cl then
- [ProtocolError "Not room master"]
- else
- [ModifyRoom (\r -> r{isRestrictedTeams = not $ isRestrictedTeams r})]
+handleCmd_inRoom clID clients _ ["TOGGLE_RESTRICT_JOINS"]
+ | isMaster client = [ModifyRoom (\r -> r{isRestrictedJoins = not $ isRestrictedJoins r})]
+ | otherwise = [ProtocolError "Not room master"]
+ where
+ client = clients IntMap.! clID
+
-{-
+handleCmd_inRoom clID clients _ ["TOGGLE_RESTRICT_TEAMS"]
+ | isMaster client = [ModifyRoom (\r -> r{isRestrictedTeams = not $ isRestrictedTeams r})]
+ | otherwise = [ProtocolError "Not room master"]
+ where
+ client = clients IntMap.! clID
+
handleCmd_inRoom clID clients rooms ["KICK", kickNick] =
[KickRoomClient kickID | isMaster client && not noSuchClient && (kickID /= clID) && (roomID client == roomID kickClient)]
where
@@ -250,5 +192,5 @@
where
client = clients IntMap.! clID
engineMsg = toEngineMsg $ 'b' : ((nick client) ++ "(team): " ++ msg ++ "\x20\x20")
--}
-handleCmd_inRoom _ = return [ProtocolError "Incorrect command (state: in room)"]
+
+handleCmd_inRoom clID _ _ _ = [ProtocolError "Incorrect command (state: in room)"]
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/HWProtoLobbyState.hs
--- a/gameServer/HWProtoLobbyState.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/HWProtoLobbyState.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,102 +1,73 @@
-{-# LANGUAGE OverloadedStrings #-}
module HWProtoLobbyState where
import qualified Data.Map as Map
+import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
import qualified Data.Foldable as Foldable
import Data.Maybe
import Data.List
import Data.Word
-import Control.Monad.Reader
-import qualified Data.ByteString.Char8 as B
--------------------------------------
import CoreTypes
import Actions
import Utils
-import HandlerUtils
-import RoomsAndClients
-{-answerAllTeams protocol teams = concatMap toAnswer teams
+answerAllTeams protocol teams = concatMap toAnswer teams
where
toAnswer team =
[AnswerThisClient $ teamToNet protocol team,
AnswerThisClient ["TEAM_COLOR", teamname team, teamcolor team],
AnswerThisClient ["HH_NUM", teamname team, show $ hhnum team]]
--}
+
handleCmd_lobby :: CmdHandler
-
-handleCmd_lobby ["LIST"] = do
- (ci, irnc) <- ask
- let cl = irnc `client` ci
- rooms <- allRoomInfos
- let roomsInfoList = concatMap (roomInfo irnc) . filter (\r -> (roomProto r == clientProto cl) && not (isRestrictedJoins r))
- return [AnswerClients [sendChan cl] ("ROOMS" : roomsInfoList rooms)]
+handleCmd_lobby clID clients rooms ["LIST"] =
+ [AnswerThisClient ("ROOMS" : roomsInfoList)]
where
- roomInfo irnc room = [
- showB $ gameinprogress room,
+ roomsInfoList = concatMap roomInfo sameProtoRooms
+ sameProtoRooms = filter (\r -> (roomProto r == protocol) && not (isRestrictedJoins r)) roomsList
+ roomsList = IntMap.elems rooms
+ protocol = clientProto client
+ client = clients IntMap.! clID
+ roomInfo room
+ | clientProto client < 28 = [
name room,
- showB $ playersIn room,
- showB $ length $ teams room,
- nick $ irnc `client` masterID room,
+ show (playersIn room) ++ "(" ++ show (length $ teams room) ++ ")",
+ show $ gameinprogress room
+ ]
+ | otherwise = [
+ show $ gameinprogress room,
+ name room,
+ show $ playersIn room,
+ show $ length $ teams room,
+ nick $ clients IntMap.! (masterID room),
head (Map.findWithDefault ["+gen+"] "MAP" (params room)),
head (Map.findWithDefault ["Default"] "SCHEME" (params room)),
head (Map.findWithDefault ["Default"] "AMMO" (params room))
]
-
-handleCmd_lobby ["CHAT", msg] = do
- n <- clientNick
- s <- roomOthersChans
- return [AnswerClients s ["CHAT", n, msg]]
-
-handleCmd_lobby ["CREATE_ROOM", newRoom, roomPassword]
- | illegalName newRoom = return [Warning "Illegal room name"]
- | otherwise = do
- rs <- allRoomInfos
- cl <- thisClient
- return $ if isJust $ find (\room -> newRoom == name room) rs then
- [Warning "Room exists"]
- else
- [
- AddRoom newRoom roomPassword,
- AnswerClients [sendChan cl] ["NOT_READY", nick cl]
- ]
-
-
-handleCmd_lobby ["CREATE_ROOM", newRoom] =
- handleCmd_lobby ["CREATE_ROOM", newRoom, ""]
+handleCmd_lobby clID clients _ ["CHAT", msg] =
+ [AnswerOthersInRoom ["CHAT", clientNick, msg]]
+ where
+ clientNick = nick $ clients IntMap.! clID
-handleCmd_lobby ["JOIN_ROOM", roomName, roomPassword] = do
- (ci, irnc) <- ask
- let ris = allRooms irnc
- cl <- thisClient
- let maybeRI = find (\ri -> roomName == name (irnc `room` ri)) ris
- let jRI = fromJust maybeRI
- let jRoom = irnc `room` jRI
- let jRoomClients = map (client irnc) $! roomClients irnc jRI -- no lazyness here!
- return $
- if isNothing maybeRI then
- [Warning "No such rooms"]
- else if isRestrictedJoins jRoom then
- [Warning "Joining restricted"]
- else if roomPassword /= password jRoom then
- [Warning "Wrong password"]
- else
- [
- MoveToRoom jRI,
- AnswerClients (map sendChan $ cl : jRoomClients) ["NOT_READY", nick cl]
- ]
- ++ [ AnswerClients [sendChan cl] $ "JOINED" : map nick jRoomClients | playersIn jRoom /= 0]
- ++ (map (readynessMessage cl) jRoomClients)
-
+handleCmd_lobby clID clients rooms ["CREATE_ROOM", newRoom, roomPassword]
+ | haveSameRoom = [Warning "Room exists"]
+ | illegalName newRoom = [Warning "Illegal room name"]
+ | otherwise =
+ [RoomRemoveThisClient "", -- leave lobby
+ AddRoom newRoom roomPassword,
+ AnswerThisClient ["NOT_READY", clientNick]
+ ]
where
- readynessMessage cl c = AnswerClients [sendChan cl] [if isReady c then "READY" else "NOT_READY", nick c]
+ clientNick = nick $ clients IntMap.! clID
+ haveSameRoom = isJust $ find (\room -> newRoom == name room) $ IntMap.elems rooms
+handleCmd_lobby clID clients rooms ["CREATE_ROOM", newRoom] =
+ handleCmd_lobby clID clients rooms ["CREATE_ROOM", newRoom, ""]
-{-
handleCmd_lobby clID clients rooms ["JOIN_ROOM", roomName, roomPassword]
| noSuchRoom = [Warning "No such room"]
@@ -112,6 +83,12 @@
++ answerTeams
++ watchRound
where
+ noSuchRoom = isNothing mbRoom
+ mbRoom = find (\r -> roomName == name r && roomProto r == clientProto client) $ IntMap.elems rooms
+ jRoom = fromJust mbRoom
+ rID = roomUID jRoom
+ client = clients IntMap.! clID
+ roomClientsIDs = IntSet.elems $ playersIDs jRoom
answerNicks =
[AnswerThisClient $ "JOINED" :
map (\clID -> nick $ clients IntMap.! clID) roomClientsIDs | playersIn jRoom /= 0]
@@ -123,9 +100,9 @@
roomClientsIDs
toAnswer (paramName, paramStrs) = AnswerThisClient $ "CFG" : paramName : paramStrs
-
- answerFullConfig = map toAnswer (leftConfigPart ++ rightConfigPart)
- (leftConfigPart, rightConfigPart) = partition (\(p, _) -> p /= "MAP") (Map.toList $ params jRoom)
+
+ answerFullConfig = map toAnswer ((Data.List.reverse . Data.List.sort $ leftConfigPart) ++ rightConfigPart)
+ (leftConfigPart, rightConfigPart) = partition (\(p, _) -> p == "MAP" || p == "MAPGEN" || p == "SCHEME") (Map.toList $ params jRoom)
watchRound = if not $ gameinprogress jRoom then
[]
@@ -137,12 +114,12 @@
answerAllTeams (clientProto client) (teamsAtStart jRoom)
else
answerAllTeams (clientProto client) (teams jRoom)
--}
+
-handleCmd_lobby ["JOIN_ROOM", roomName] =
- handleCmd_lobby ["JOIN_ROOM", roomName, ""]
+handleCmd_lobby clID clients rooms ["JOIN_ROOM", roomName] =
+ handleCmd_lobby clID clients rooms ["JOIN_ROOM", roomName, ""]
+
-{-
handleCmd_lobby clID clients rooms ["FOLLOW", asknick] =
if noSuchClient || roomID followClient == 0 then
[]
@@ -203,7 +180,6 @@
[ClearAccountsCache | isAdministrator client]
where
client = clients IntMap.! clID
--}
-handleCmd_lobby _ = return [ProtocolError "Incorrect command (state: in lobby)"]
+handleCmd_lobby clID _ _ _ = [ProtocolError "Incorrect command (state: in lobby)"]
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/HWProtoNEState.hs
--- a/gameServer/HWProtoNEState.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/HWProtoNEState.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,66 +1,54 @@
-{-# LANGUAGE OverloadedStrings #-}
module HWProtoNEState where
import qualified Data.IntMap as IntMap
import Data.Maybe
import Data.List
import Data.Word
-import Control.Monad.Reader
-import qualified Data.ByteString.Char8 as B
--------------------------------------
import CoreTypes
import Actions
import Utils
-import RoomsAndClients
handleCmd_NotEntered :: CmdHandler
-handleCmd_NotEntered ["NICK", newNick] = do
- (ci, irnc) <- ask
- let cl = irnc `client` ci
- if not . B.null $ nick cl then return [ProtocolError "Nickname already chosen"]
- else
- if haveSameNick irnc (nick cl) then return [AnswerClients [sendChan cl] ["WARNING", "Nickname already in use"], ByeClient ""]
- else
- if illegalName newNick then return [ByeClient "Illegal nickname"]
- else
- return $
- ModifyClient (\c -> c{nick = newNick}) :
- AnswerClients [sendChan cl] ["NICK", newNick] :
- [CheckRegistered | clientProto cl /= 0]
+handleCmd_NotEntered clID clients _ ["NICK", newNick]
+ | not . null $ nick client = [ProtocolError "Nickname already chosen"]
+ | haveSameNick = [AnswerThisClient ["WARNING", "Nickname already in use"], ByeClient ""]
+ | illegalName newNick = [ByeClient "Illegal nickname"]
+ | otherwise =
+ ModifyClient (\c -> c{nick = newNick}) :
+ AnswerThisClient ["NICK", newNick] :
+ [CheckRegistered | clientProto client /= 0]
where
- haveSameNick irnc clNick = isJust $ find (\cl -> newNick == clNick) $ map (client irnc) $ allClients irnc
-
-handleCmd_NotEntered ["PROTO", protoNum] = do
- (ci, irnc) <- ask
- let cl = irnc `client` ci
- if clientProto cl > 0 then return [ProtocolError "Protocol already known"]
- else
- if parsedProto == 0 then return [ProtocolError "Bad number"]
- else
- return $
- ModifyClient (\c -> c{clientProto = parsedProto}) :
- AnswerClients [sendChan cl] ["PROTO", B.pack $ show parsedProto] :
- [CheckRegistered | not . B.null $ nick cl]
- where
- parsedProto = case B.readInt protoNum of
- Just (i, t) | B.null t -> fromIntegral i
- otherwise -> 0
+ client = clients IntMap.! clID
+ haveSameNick = isJust $ find (\cl -> newNick == nick cl) $ IntMap.elems clients
-handleCmd_NotEntered ["PASSWORD", passwd] = do
- (ci, irnc) <- ask
- let cl = irnc `client` ci
+handleCmd_NotEntered clID clients _ ["PROTO", protoNum]
+ | clientProto client > 0 = [ProtocolError "Protocol already known"]
+ | parsedProto == 0 = [ProtocolError "Bad number"]
+ | otherwise =
+ ModifyClient (\c -> c{clientProto = parsedProto}) :
+ AnswerThisClient ["PROTO", show parsedProto] :
+ [CheckRegistered | (not . null) (nick client)]
+ where
+ client = clients IntMap.! clID
+ parsedProto = fromMaybe 0 (maybeRead protoNum :: Maybe Word16)
- if passwd == webPassword cl then
- return $ JoinLobby : [AnswerClients [sendChan cl] ["ADMIN_ACCESS"] | isAdministrator cl]
- else
- return [ByeClient "Authentication failed"]
-{-
+handleCmd_NotEntered clID clients _ ["PASSWORD", passwd] =
+ if passwd == webPassword client then
+ [ModifyClient (\cl -> cl{logonPassed = True}),
+ MoveToLobby] ++ adminNotice
+ else
+ [ByeClient "Authentication failed"]
+ where
+ client = clients IntMap.! clID
+ adminNotice = [AnswerThisClient ["ADMIN_ACCESS"] | isAdministrator client]
+
handleCmd_NotEntered clID clients _ ["DUMP"] =
if isAdministrator (clients IntMap.! clID) then [Dump] else []
--}
+
-handleCmd_NotEntered _ = return [ProtocolError "Incorrect command (state: not entered)"]
+handleCmd_NotEntered clID _ _ _ = [ProtocolError "Incorrect command (state: not entered)"]
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/HandlerUtils.hs
--- a/gameServer/HandlerUtils.hs Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-module HandlerUtils where
-
-import Control.Monad.Reader
-import qualified Data.ByteString.Char8 as B
-
-import RoomsAndClients
-import CoreTypes
-import Actions
-
-thisClient :: Reader (ClientIndex, IRnC) ClientInfo
-thisClient = do
- (ci, rnc) <- ask
- return $ rnc `client` ci
-
-thisRoom :: Reader (ClientIndex, IRnC) RoomInfo
-thisRoom = do
- (ci, rnc) <- ask
- let ri = clientRoom rnc ci
- return $ rnc `room` ri
-
-clientNick :: Reader (ClientIndex, IRnC) B.ByteString
-clientNick = liftM nick thisClient
-
-roomOthersChans :: Reader (ClientIndex, IRnC) [ClientChan]
-roomOthersChans = do
- (ci, rnc) <- ask
- let ri = clientRoom rnc ci
- return $ map (sendChan . client rnc) $ filter (/= ci) (roomClients rnc ri)
-
-roomClientsChans :: Reader (ClientIndex, IRnC) [ClientChan]
-roomClientsChans = do
- (ci, rnc) <- ask
- let ri = clientRoom rnc ci
- return $ map (sendChan . client rnc) (roomClients rnc ri)
-
-thisClientChans :: Reader (ClientIndex, IRnC) [ClientChan]
-thisClientChans = do
- (ci, rnc) <- ask
- return $ [sendChan (rnc `client` ci)]
-
-answerClient :: [B.ByteString] -> Reader (ClientIndex, IRnC) [Action]
-answerClient msg = thisClientChans >>= return . (: []) . flip AnswerClients msg
-
-allRoomInfos :: Reader (a, IRnC) [RoomInfo]
-allRoomInfos = liftM ((\irnc -> map (room irnc) $ allRooms irnc) . snd) ask
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/NetRoutines.hs
--- a/gameServer/NetRoutines.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/NetRoutines.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,41 +1,46 @@
-{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
module NetRoutines where
+import Network
import Network.Socket
import System.IO
+import Control.Concurrent
import Control.Concurrent.Chan
+import Control.Concurrent.STM
import qualified Control.Exception as Exception
import Data.Time
-import Control.Monad
-----------------------------
import CoreTypes
+import ClientIO
import Utils
-import RoomsAndClients
-acceptLoop :: Socket -> Chan CoreMessage -> IO ()
-acceptLoop servSock chan = forever $ do
+acceptLoop :: Socket -> Chan CoreMessage -> Int -> IO ()
+acceptLoop servSock coreChan clientCounter = do
Exception.handle
(\(_ :: Exception.IOException) -> putStrLn "exception on connect") $
do
- (sock, sockAddr) <- Network.Socket.accept servSock
+ (socket, sockAddr) <- Network.Socket.accept servSock
+ cHandle <- socketToHandle socket ReadWriteMode
+ hSetBuffering cHandle LineBuffering
clientHost <- sockAddr2String sockAddr
currentTime <- getCurrentTime
-
- sendChan' <- newChan
+
+ sendChan <- newChan
let newClient =
(ClientInfo
- sendChan'
- sock
+ nextID
+ sendChan
+ cHandle
clientHost
currentTime
""
""
False
0
- lobbyId
+ 0
0
False
False
@@ -44,5 +49,12 @@
undefined
)
- writeChan chan $ Accept newClient
+ writeChan coreChan $ Accept newClient
+
+ forkIO $ clientRecvLoop cHandle coreChan nextID
+ forkIO $ clientSendLoop cHandle coreChan sendChan nextID
return ()
+
+ acceptLoop servSock coreChan nextID
+ where
+ nextID = clientCounter + 1
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/OfficialServer/DBInteraction.hs
--- a/gameServer/OfficialServer/DBInteraction.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/OfficialServer/DBInteraction.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings #-}
+{-# LANGUAGE CPP, ScopedTypeVariables #-}
module OfficialServer.DBInteraction
(
startDBConnection
@@ -20,7 +20,7 @@
localAddressList = ["127.0.0.1", "0:0:0:0:0:0:0:1", "0:0:0:0:0:ffff:7f00:1"]
-fakeDbConnection serverInfo = forever $ do
+fakeDbConnection serverInfo = do
q <- readChan $ dbQueries serverInfo
case q of
CheckAccount clUid _ clHost -> do
@@ -29,6 +29,8 @@
ClearCache -> return ()
SendStats {} -> return ()
+ fakeDbConnection serverInfo
+
#if defined(OFFICIAL_SERVER)
pipeDbConnectionLoop queries coreChan hIn hOut accountsCache =
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/OfficialServer/extdbinterface.hs
--- a/gameServer/OfficialServer/extdbinterface.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/OfficialServer/extdbinterface.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,4 +1,4 @@
-{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
module Main where
@@ -26,7 +26,7 @@
case q of
CheckAccount clUid clNick _ -> do
statement <- prepare dbConn dbQueryAccount
- execute statement [SqlByteString $ clNick]
+ execute statement [SqlString $ clNick]
passAndRole <- fetchRow statement
finish statement
let response =
@@ -47,7 +47,7 @@
dbConnectionLoop mySQLConnectionInfo =
- Control.Exception.handle (\(e :: IOException) -> hPutStrLn stderr $ show e) $ handleSqlError $
+ Control.Exception.handle (\(_ :: IOException) -> return ()) $ handleSqlError $
bracket
(connectMySQL mySQLConnectionInfo)
(disconnect)
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/Opts.hs
--- a/gameServer/Opts.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/Opts.hs Tue Jan 04 12:53:46 2011 +0100
@@ -3,12 +3,10 @@
getOpts,
) where
-import System.Environment
+import System.Environment ( getArgs )
import System.Console.GetOpt
import Network
import Data.Maybe ( fromMaybe )
-import qualified Data.ByteString.Char8 as B
-
import CoreTypes
import Utils
@@ -32,9 +30,9 @@
where
readDedicated = fromMaybe True (maybeRead str :: Maybe Bool)
-readDbLogin str opts = opts{dbLogin = B.pack str}
-readDbPassword str opts = opts{dbPassword = B.pack str}
-readDbHost str opts = opts{dbHost = B.pack str}
+readDbLogin str opts = opts{dbLogin = str}
+readDbPassword str opts = opts{dbPassword = str}
+readDbHost str opts = opts{dbHost = str}
getOpts :: ServerInfo -> IO ServerInfo
getOpts opts = do
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/RoomsAndClients.hs
--- a/gameServer/RoomsAndClients.hs Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-module RoomsAndClients(
- RoomIndex(),
- ClientIndex(),
- MRoomsAndClients(),
- IRoomsAndClients(),
- newRoomsAndClients,
- addRoom,
- addClient,
- removeRoom,
- removeClient,
- modifyRoom,
- modifyClient,
- lobbyId,
- moveClientToLobby,
- moveClientToRoom,
- clientRoomM,
- clientExists,
- client,
- room,
- client'sM,
- room'sM,
- allClientsM,
- clientsM,
- roomClientsM,
- roomClientsIndicesM,
- withRoomsAndClients,
- allRooms,
- allClients,
- clientRoom,
- showRooms,
- roomClients
- ) where
-
-
-import Store
-import Control.Monad
-
-
-data Room r = Room {
- roomClients' :: [ClientIndex],
- room' :: r
- }
-
-
-data Client c = Client {
- clientRoom' :: RoomIndex,
- client' :: c
- }
-
-
-newtype RoomIndex = RoomIndex ElemIndex
- deriving (Eq)
-newtype ClientIndex = ClientIndex ElemIndex
- deriving (Eq, Show, Read, Ord)
-
-instance Show RoomIndex where
- show (RoomIndex i) = 'r' : show i
-
-unRoomIndex :: RoomIndex -> ElemIndex
-unRoomIndex (RoomIndex r) = r
-
-unClientIndex :: ClientIndex -> ElemIndex
-unClientIndex (ClientIndex c) = c
-
-
-newtype MRoomsAndClients r c = MRoomsAndClients (MStore (Room r), MStore (Client c))
-newtype IRoomsAndClients r c = IRoomsAndClients (IStore (Room r), IStore (Client c))
-
-
-lobbyId :: RoomIndex
-lobbyId = RoomIndex firstIndex
-
-
-newRoomsAndClients :: r -> IO (MRoomsAndClients r c)
-newRoomsAndClients r = do
- rooms <- newStore
- clients <- newStore
- let rnc = MRoomsAndClients (rooms, clients)
- ri <- addRoom rnc r
- when (ri /= lobbyId) $ error "Empty struct inserts not at firstIndex index"
- return rnc
-
-
-roomAddClient :: ClientIndex -> Room r -> Room r
-roomAddClient cl room = let cls = cl : roomClients' room; nr = room{roomClients' = cls} in cls `seq` nr `seq` nr
-
-roomRemoveClient :: ClientIndex -> Room r -> Room r
-roomRemoveClient cl room = let cls = filter (/= cl) $ roomClients' room; nr = room{roomClients' = cls} in cls `seq` nr `seq` nr
-
-
-addRoom :: MRoomsAndClients r c -> r -> IO RoomIndex
-addRoom (MRoomsAndClients (rooms, _)) room = do
- i <- addElem rooms (Room [] room)
- return $ RoomIndex i
-
-
-addClient :: MRoomsAndClients r c -> c -> IO ClientIndex
-addClient (MRoomsAndClients (rooms, clients)) client = do
- i <- addElem clients (Client lobbyId client)
- modifyElem rooms (roomAddClient (ClientIndex i)) (unRoomIndex lobbyId)
- return $ ClientIndex i
-
-removeRoom :: MRoomsAndClients r c -> RoomIndex -> IO ()
-removeRoom rnc@(MRoomsAndClients (rooms, _)) room@(RoomIndex ri)
- | room == lobbyId = error "Cannot delete lobby"
- | otherwise = do
- clIds <- liftM roomClients' $ readElem rooms ri
- forM_ clIds (moveClientToLobby rnc)
- removeElem rooms ri
-
-
-removeClient :: MRoomsAndClients r c -> ClientIndex -> IO ()
-removeClient (MRoomsAndClients (rooms, clients)) cl@(ClientIndex ci) = do
- RoomIndex ri <- liftM clientRoom' $ readElem clients ci
- modifyElem rooms (roomRemoveClient cl) ri
- removeElem clients ci
-
-
-modifyRoom :: MRoomsAndClients r c -> (r -> r) -> RoomIndex -> IO ()
-modifyRoom (MRoomsAndClients (rooms, _)) f (RoomIndex ri) = modifyElem rooms (\r -> r{room' = f $ room' r}) ri
-
-modifyClient :: MRoomsAndClients r c -> (c -> c) -> ClientIndex -> IO ()
-modifyClient (MRoomsAndClients (_, clients)) f (ClientIndex ci) = modifyElem clients (\c -> c{client' = f $ client' c}) ci
-
-moveClientInRooms :: MRoomsAndClients r c -> RoomIndex -> RoomIndex -> ClientIndex -> IO ()
-moveClientInRooms (MRoomsAndClients (rooms, clients)) (RoomIndex riFrom) rt@(RoomIndex riTo) cl@(ClientIndex ci) = do
- modifyElem rooms (roomRemoveClient cl) riFrom
- modifyElem rooms (roomAddClient cl) riTo
- modifyElem clients (\c -> c{clientRoom' = rt}) ci
-
-
-moveClientToLobby :: MRoomsAndClients r c -> ClientIndex -> IO ()
-moveClientToLobby rnc ci = do
- room <- clientRoomM rnc ci
- moveClientInRooms rnc room lobbyId ci
-
-
-moveClientToRoom :: MRoomsAndClients r c -> RoomIndex -> ClientIndex -> IO ()
-moveClientToRoom rnc ri ci = moveClientInRooms rnc lobbyId ri ci
-
-
-clientExists :: MRoomsAndClients r c -> ClientIndex -> IO Bool
-clientExists (MRoomsAndClients (_, clients)) (ClientIndex ci) = elemExists clients ci
-
-clientRoomM :: MRoomsAndClients r c -> ClientIndex -> IO RoomIndex
-clientRoomM (MRoomsAndClients (_, clients)) (ClientIndex ci) = liftM clientRoom' (clients `readElem` ci)
-
-client'sM :: MRoomsAndClients r c -> (c -> a) -> ClientIndex -> IO a
-client'sM (MRoomsAndClients (_, clients)) f (ClientIndex ci) = liftM (f . client') (clients `readElem` ci)
-
-room'sM :: MRoomsAndClients r c -> (r -> a) -> RoomIndex -> IO a
-room'sM (MRoomsAndClients (rooms, _)) f (RoomIndex ri) = liftM (f . room') (rooms `readElem` ri)
-
-allClientsM :: MRoomsAndClients r c -> IO [ClientIndex]
-allClientsM (MRoomsAndClients (_, clients)) = liftM (map ClientIndex) $ indicesM clients
-
-clientsM :: MRoomsAndClients r c -> IO [c]
-clientsM (MRoomsAndClients (_, clients)) = indicesM clients >>= mapM (\ci -> liftM client' $ readElem clients ci)
-
-roomClientsIndicesM :: MRoomsAndClients r c -> RoomIndex -> IO [ClientIndex]
-roomClientsIndicesM (MRoomsAndClients (rooms, clients)) (RoomIndex ri) = liftM roomClients' (rooms `readElem` ri)
-
-roomClientsM :: MRoomsAndClients r c -> RoomIndex -> IO [c]
-roomClientsM (MRoomsAndClients (rooms, clients)) (RoomIndex ri) = liftM roomClients' (rooms `readElem` ri) >>= mapM (\(ClientIndex ci) -> liftM client' $ readElem clients ci)
-
-withRoomsAndClients :: MRoomsAndClients r c -> (IRoomsAndClients r c -> a) -> IO a
-withRoomsAndClients (MRoomsAndClients (rooms, clients)) f =
- withIStore2 rooms clients (\r c -> f $ IRoomsAndClients (r, c))
-
-----------------------------------------
------------ IRoomsAndClients -----------
-
-showRooms :: (Show r, Show c) => IRoomsAndClients r c -> String
-showRooms rnc@(IRoomsAndClients (rooms, clients)) = concatMap showRoom (allRooms rnc)
- where
- showRoom r = unlines $ ((show r) ++ ": " ++ (show $ room' $ rooms ! (unRoomIndex r))) : (map showClient (roomClients' $ rooms ! (unRoomIndex r)))
- showClient c = " " ++ (show c) ++ ": " ++ (show $ client' $ clients ! (unClientIndex c))
-
-
-allRooms :: IRoomsAndClients r c -> [RoomIndex]
-allRooms (IRoomsAndClients (rooms, _)) = map RoomIndex $ indices rooms
-
-allClients :: IRoomsAndClients r c -> [ClientIndex]
-allClients (IRoomsAndClients (_, clients)) = map ClientIndex $ indices clients
-
-clientRoom :: IRoomsAndClients r c -> ClientIndex -> RoomIndex
-clientRoom (IRoomsAndClients (_, clients)) (ClientIndex ci) = clientRoom' (clients ! ci)
-
-client :: IRoomsAndClients r c -> ClientIndex -> c
-client (IRoomsAndClients (_, clients)) (ClientIndex ci) = client' (clients ! ci)
-
-room :: IRoomsAndClients r c -> RoomIndex -> r
-room (IRoomsAndClients (rooms, _)) (RoomIndex ri) = room' (rooms ! ri)
-
-roomClients :: IRoomsAndClients r c -> RoomIndex -> [ClientIndex]
-roomClients (IRoomsAndClients (rooms, _)) (RoomIndex ri) = roomClients' $ (rooms ! ri)
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/ServerCore.hs
--- a/gameServer/ServerCore.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/ServerCore.hs Tue Jan 04 12:53:46 2011 +0100
@@ -2,75 +2,69 @@
import Network
import Control.Concurrent
+import Control.Concurrent.STM
import Control.Concurrent.Chan
import Control.Monad
import qualified Data.IntMap as IntMap
import System.Log.Logger
-import Control.Monad.Reader
-import Control.Monad.State.Strict
-import Data.Set as Set
-import qualified Data.ByteString.Char8 as B
--------------------------------------
import CoreTypes
import NetRoutines
+import Utils
import HWProtoCore
import Actions
import OfficialServer.DBInteraction
-import ServerState
-
-
-timerLoop :: Int -> Chan CoreMessage -> IO ()
-timerLoop tick messagesChan = threadDelay (30 * 10^6) >> writeChan messagesChan (TimerAction tick) >> timerLoop (tick + 1) messagesChan
-reactCmd :: [B.ByteString] -> StateT ServerState IO ()
-reactCmd cmd = do
- (Just ci) <- gets clientIndex
- rnc <- gets roomsClients
- actions <- liftIO $ withRoomsAndClients rnc (\irnc -> runReader (handleCmd cmd) (ci, irnc))
- forM_ actions processAction
+timerLoop :: Int -> Chan CoreMessage -> IO()
+timerLoop tick messagesChan = threadDelay (30 * 10^6) >> writeChan messagesChan (TimerAction tick) >> timerLoop (tick + 1) messagesChan
+
+firstAway (_, a, b, c) = (a, b, c)
+
+reactCmd :: ServerInfo -> Int -> [String] -> Clients -> Rooms -> IO (ServerInfo, Clients, Rooms)
+reactCmd serverInfo clID cmd clients rooms =
+ liftM firstAway $ foldM processAction (clID, serverInfo, clients, rooms) $ handleCmd clID clients rooms cmd
-mainLoop :: StateT ServerState IO ()
-mainLoop = forever $ do
- get >>= \s -> put $! s
-
- si <- gets serverInfo
- r <- liftIO $ readChan $ coreChan si
-
- case r of
- Accept ci -> processAction (AddClient ci)
-
- ClientMessage (ci, cmd) -> do
- liftIO $ debugM "Clients" $ (show ci) ++ ": " ++ (show cmd)
+mainLoop :: ServerInfo -> Clients -> Rooms -> IO ()
+mainLoop serverInfo clients rooms = do
+ r <- readChan $ coreChan serverInfo
+
+ (newServerInfo, mClients, mRooms) <-
+ case r of
+ Accept ci ->
+ liftM firstAway $ processAction
+ (clientUID ci, serverInfo, clients, rooms) (AddClient ci)
- removed <- gets removedClients
- when (not $ ci `Set.member` removed) $ do
- as <- get
- put $! as{clientIndex = Just ci}
- reactCmd cmd
-
- Remove ci -> do
- liftIO $ debugM "Clients" $ "DeleteClient: " ++ show ci
- processAction (DeleteClient ci)
+ ClientMessage (clID, cmd) -> do
+ debugM "Clients" $ (show clID) ++ ": " ++ (show cmd)
+ if clID `IntMap.member` clients then
+ reactCmd serverInfo clID cmd clients rooms
+ else
+ do
+ debugM "Clients" "Message from dead client"
+ return (serverInfo, clients, rooms)
- --else
- --do
- --debugM "Clients" "Message from dead client"
- --return (serverInfo, rnc)
+ ClientAccountInfo (clID, info) ->
+ if clID `IntMap.member` clients then
+ liftM firstAway $ processAction
+ (clID, serverInfo, clients, rooms)
+ (ProcessAccountInfo info)
+ else
+ do
+ debugM "Clients" "Got info for dead client"
+ return (serverInfo, clients, rooms)
- ClientAccountInfo (ci, info) -> do
- rnc <- gets roomsClients
- exists <- liftIO $ clientExists rnc ci
- when (exists) $ do
- as <- get
- put $! as{clientIndex = Just ci}
- processAction (ProcessAccountInfo info)
- return ()
+ TimerAction tick ->
+ liftM firstAway $
+ foldM processAction (0, serverInfo, clients, rooms) $
+ PingAll : [StatsAction | even tick]
+
- TimerAction tick ->
- mapM_ processAction $
- PingAll : [StatsAction | even tick]
+ {- let hadRooms = (not $ null rooms) && (null mrooms)
+ in unless ((not $ isDedicated serverInfo) && ((null clientsIn) || hadRooms)) $
+ mainLoop serverInfo acceptChan messagesChan clientsIn mrooms -}
+ mainLoop newServerInfo mClients mRooms
startServer :: ServerInfo -> Socket -> IO ()
startServer serverInfo serverSocket = do
@@ -80,15 +74,14 @@
acceptLoop
serverSocket
(coreChan serverInfo)
+ 0
return ()
-
- --forkIO $ timerLoop 0 $ coreChan serverInfo
+
+ forkIO $ timerLoop 0 $ coreChan serverInfo
startDBConnection serverInfo
- rnc <- newRoomsAndClients newRoom
+ forkIO $ mainLoop serverInfo IntMap.empty (IntMap.singleton 0 newRoom)
- forkIO $ evalStateT mainLoop (ServerState Nothing serverInfo Set.empty rnc)
-
- forever $ threadDelay (60 * 60 * 10^6)
+ forever $ threadDelay (60 * 60 * 10^6) >> putStrLn "***"
\ No newline at end of file
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/ServerState.hs
--- a/gameServer/ServerState.hs Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-module ServerState
- (
- module RoomsAndClients,
- clientRoomA,
- ServerState(..),
- client's,
- allClientsS,
- roomClientsS
- ) where
-
-import Control.Monad.State.Strict
-import Data.Set as Set
-----------------------
-import RoomsAndClients
-import CoreTypes
-
-data ServerState = ServerState {
- clientIndex :: !(Maybe ClientIndex),
- serverInfo :: !ServerInfo,
- removedClients :: !(Set.Set ClientIndex),
- roomsClients :: !MRnC
- }
-
-
-clientRoomA :: StateT ServerState IO RoomIndex
-clientRoomA = do
- (Just ci) <- gets clientIndex
- rnc <- gets roomsClients
- liftIO $ clientRoomM rnc ci
-
-client's :: (ClientInfo -> a) -> StateT ServerState IO a
-client's f = do
- (Just ci) <- gets clientIndex
- rnc <- gets roomsClients
- liftIO $ client'sM rnc f ci
-
-allClientsS :: StateT ServerState IO [ClientInfo]
-allClientsS = gets roomsClients >>= liftIO . clientsM
-
-roomClientsS :: RoomIndex -> StateT ServerState IO [ClientInfo]
-roomClientsS ri = do
- rnc <- gets roomsClients
- liftIO $ roomClientsM rnc ri
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/Store.hs
--- a/gameServer/Store.hs Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-module Store(
- ElemIndex(),
- MStore(),
- IStore(),
- newStore,
- addElem,
- removeElem,
- readElem,
- writeElem,
- modifyElem,
- elemExists,
- firstIndex,
- indicesM,
- withIStore,
- withIStore2,
- (!),
- indices
- ) where
-
-import qualified Data.Array.IArray as IA
-import qualified Data.Array.IO as IOA
-import qualified Data.IntSet as IntSet
-import Data.IORef
-import Control.Monad
-
-
-newtype ElemIndex = ElemIndex Int
- deriving (Eq, Show, Read, Ord)
-newtype MStore e = MStore (IORef (IntSet.IntSet, IntSet.IntSet, IOA.IOArray Int e))
-newtype IStore e = IStore (IntSet.IntSet, IA.Array Int e)
-
-
-firstIndex :: ElemIndex
-firstIndex = ElemIndex 0
-
--- MStore code
-initialSize :: Int
-initialSize = 10
-
-
-growFunc :: Int -> Int
-growFunc a = a * 3 `div` 2
-
-
-newStore :: IO (MStore e)
-newStore = do
- newar <- IOA.newArray_ (0, initialSize - 1)
- new <- newIORef (IntSet.empty, IntSet.fromAscList [0..initialSize - 1], newar)
- return (MStore new)
-
-
-growStore :: MStore e -> IO ()
-growStore (MStore ref) = do
- (busyElems, freeElems, arr) <- readIORef ref
- (_, m') <- IOA.getBounds arr
- let newM' = growFunc (m' + 1) - 1
- newArr <- IOA.newArray_ (0, newM')
- sequence_ [IOA.readArray arr i >>= IOA.writeArray newArr i | i <- [0..m']]
- writeIORef ref (busyElems, freeElems `IntSet.union` (IntSet.fromAscList [m'+1..newM']), newArr)
-
-
-growIfNeeded :: MStore e -> IO ()
-growIfNeeded m@(MStore ref) = do
- (_, freeElems, _) <- readIORef ref
- when (IntSet.null freeElems) $ growStore m
-
-
-addElem :: MStore e -> e -> IO ElemIndex
-addElem m@(MStore ref) element = do
- growIfNeeded m
- (busyElems, freeElems, arr) <- readIORef ref
- let (n, freeElems') = IntSet.deleteFindMin freeElems
- IOA.writeArray arr n element
- writeIORef ref (IntSet.insert n busyElems, freeElems', arr)
- return $ ElemIndex n
-
-
-removeElem :: MStore e -> ElemIndex -> IO ()
-removeElem (MStore ref) (ElemIndex n) = do
- (busyElems, freeElems, arr) <- readIORef ref
- IOA.writeArray arr n (error $ "Store: no element " ++ show n)
- writeIORef ref (IntSet.delete n busyElems, IntSet.insert n freeElems, arr)
-
-
-readElem :: MStore e -> ElemIndex -> IO e
-readElem (MStore ref) (ElemIndex n) = readIORef ref >>= \(_, _, arr) -> IOA.readArray arr n
-
-
-writeElem :: MStore e -> ElemIndex -> e -> IO ()
-writeElem (MStore ref) (ElemIndex n) el = readIORef ref >>= \(_, _, arr) -> IOA.writeArray arr n el
-
-
-modifyElem :: MStore e -> (e -> e) -> ElemIndex -> IO ()
-modifyElem (MStore ref) f (ElemIndex n) = do
- (_, _, arr) <- readIORef ref
- IOA.readArray arr n >>= IOA.writeArray arr n . f
-
-elemExists :: MStore e -> ElemIndex -> IO Bool
-elemExists (MStore ref) (ElemIndex n) = do
- (_, free, _) <- readIORef ref
- return $ n `IntSet.notMember` free
-
-indicesM :: MStore e -> IO [ElemIndex]
-indicesM (MStore ref) = do
- (busy, _, _) <- readIORef ref
- return $ map ElemIndex $ IntSet.toList busy
-
-
--- A way to see MStore elements in pure code via IStore
-m2i :: MStore e -> IO (IStore e)
-m2i (MStore ref) = do
- (a, _, c') <- readIORef ref
- c <- IOA.unsafeFreeze c'
- return $ IStore (a, c)
-
-i2m :: (MStore e) -> IStore e -> IO ()
-i2m (MStore ref) (IStore (_, arr)) = do
- (b, e, _) <- readIORef ref
- a <- IOA.unsafeThaw arr
- writeIORef ref (b, e, a)
-
-withIStore :: MStore e -> (IStore e -> a) -> IO a
-withIStore m f = do
- i <- m2i m
- let res = f i
- res `seq` i2m m i
- return res
-
-
-withIStore2 :: MStore e1 -> MStore e2 -> (IStore e1 -> IStore e2 -> a) -> IO a
-withIStore2 m1 m2 f = do
- i1 <- m2i m1
- i2 <- m2i m2
- let res = f i1 i2
- res `seq` i2m m1 i1
- i2m m2 i2
- return res
-
-
--- IStore code
-(!) :: IStore e -> ElemIndex -> e
-(!) (IStore (_, arr)) (ElemIndex i) = (IA.!) arr i
-
-indices :: IStore e -> [ElemIndex]
-indices (IStore (busy, _)) = map ElemIndex $ IntSet.toList busy
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/Utils.hs
--- a/gameServer/Utils.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/Utils.hs Tue Jan 04 12:53:46 2011 +0100
@@ -1,4 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
module Utils where
import Control.Concurrent
@@ -17,34 +16,37 @@
import Data.Maybe
-------------------------------------------------
import qualified Codec.Binary.Base64 as Base64
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString as BW
+import qualified Data.ByteString.UTF8 as BUTF8
+import qualified Data.ByteString as B
import CoreTypes
-sockAddr2String :: SockAddr -> IO B.ByteString
-sockAddr2String (SockAddrInet _ hostAddr) = liftM B.pack $ inet_ntoa hostAddr
+sockAddr2String :: SockAddr -> IO String
+sockAddr2String (SockAddrInet _ hostAddr) = inet_ntoa hostAddr
sockAddr2String (SockAddrInet6 _ _ (a, b, c, d) _) =
- return $ B.pack $ (foldr1 (.)
+ return $ (foldr1 (.)
$ List.intersperse (\a -> ':':a)
$ concatMap (\n -> (\(a, b) -> [showHex a, showHex b]) $ divMod n 65536) [a, b, c, d]) []
-toEngineMsg :: B.ByteString -> B.ByteString
-toEngineMsg msg = B.pack $ Base64.encode (fromIntegral (BW.length msg) : (BW.unpack msg))
+toEngineMsg :: String -> String
+toEngineMsg msg = Base64.encode (fromIntegral (B.length encodedMsg) : (B.unpack encodedMsg))
+ where
+ encodedMsg = BUTF8.fromString msg
-fromEngineMsg :: B.ByteString -> Maybe B.ByteString
-fromEngineMsg msg = Base64.decode (B.unpack msg) >>= removeLength >>= return . BW.pack
+fromEngineMsg :: String -> Maybe String
+fromEngineMsg msg = liftM (map w2c) (Base64.decode msg >>= removeLength)
where
removeLength (x:xs) = if length xs == fromIntegral x then Just xs else Nothing
removeLength _ = Nothing
-checkNetCmd :: B.ByteString -> (Bool, Bool)
-checkNetCmd = check . liftM B.unpack . fromEngineMsg
+checkNetCmd :: String -> (Bool, Bool)
+checkNetCmd msg = check decoded
where
+ decoded = fromEngineMsg msg
check Nothing = (False, False)
check (Just (m:ms)) = (m `Set.member` legalMessages, m == '+')
check _ = (False, False)
- legalMessages = Set.fromList $ "M#+LlRrUuDdZzAaSjJ,sFNpPwtghb12345" ++ slotMessages
+ legalMessages = Set.fromList $ "M#+LlRrUuDdZzAaSjJ,sFNpPwtghbc12345" ++ slotMessages
slotMessages = "\128\129\130\131\132\133\134\135\136\137\138"
maybeRead :: Read a => String -> Maybe a
@@ -52,17 +54,29 @@
[(x, rest)] | all isSpace rest -> Just x
_ -> Nothing
-teamToNet :: TeamInfo -> [B.ByteString]
-teamToNet team =
- "ADD_TEAM"
- : teamname team
- : teamgrave team
- : teamfort team
- : teamvoicepack team
- : teamflag team
- : teamowner team
- : (B.pack $ show $ difficulty team)
- : hhsInfo
+teamToNet :: Word16 -> TeamInfo -> [String]
+teamToNet protocol team
+ | protocol < 30 = [
+ "ADD_TEAM",
+ teamname team,
+ teamgrave team,
+ teamfort team,
+ teamvoicepack team,
+ teamowner team,
+ show $ difficulty team
+ ]
+ ++ hhsInfo
+ | otherwise = [
+ "ADD_TEAM",
+ teamname team,
+ teamgrave team,
+ teamfort team,
+ teamvoicepack team,
+ teamflag team,
+ teamowner team,
+ show $ difficulty team
+ ]
+ ++ hhsInfo
where
hhsInfo = concatMap (\(HedgehogInfo name hat) -> [name, hat]) $ hedgehogs team
@@ -76,10 +90,10 @@
else
t : replaceTeam team teams
-illegalName :: B.ByteString -> Bool
-illegalName = all isSpace . B.unpack
+illegalName :: String -> Bool
+illegalName = all isSpace
-protoNumber2ver :: Word16 -> B.ByteString
+protoNumber2ver :: Word16 -> String
protoNumber2ver 17 = "0.9.7-dev"
protoNumber2ver 19 = "0.9.7"
protoNumber2ver 20 = "0.9.8-dev"
@@ -98,20 +112,12 @@
protoNumber2ver 33 = "0.9.14"
protoNumber2ver 34 = "0.9.15-dev"
protoNumber2ver 35 = "0.9.14.1"
-protoNumber2ver _ = "Unknown"
+protoNumber2ver 37 = "0.9.15"
+protoNumber2ver 38 = "0.9.16-dev"
+protoNumber2ver w = show w
askFromConsole :: String -> IO String
askFromConsole msg = do
putStr msg
hFlush stdout
getLine
-
-
-unfoldrE :: (b -> Either b (a, b)) -> b -> ([a], b)
-unfoldrE f b =
- case f b of
- Right (a, new_b) -> let (a', b') = unfoldrE f new_b in (a : a', b')
- Left new_b -> ([], new_b)
-
-showB :: Show a => a -> B.ByteString
-showB = B.pack .show
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/hedgewars-server.cabal
--- a/gameServer/hedgewars-server.cabal Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-Name: hedgewars-server
-Version: 0.1
-Synopsis: hedgewars server
-Description: hedgewars server
-Homepage: http://www.hedgewars.org/
-License: GPL-2
-Author: unC0Rr
-Maintainer: unC0Rr@hedgewars.org
-Category: Game
-Build-type: Simple
-Cabal-version: >=1.2
-
-
-Executable hedgewars-server
- main-is: hedgewars-server.hs
-
- Build-depends:
- base >= 4,
- unix,
- containers,
- array,
- bytestring,
- network-bytestring,
- network,
- time,
- stm,
- mtl,
- dataenc,
- hslogger,
- process
-
- ghc-options: -O2
\ No newline at end of file
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/hedgewars-server.hs
--- a/gameServer/hedgewars-server.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/hedgewars-server.hs Tue Jan 04 12:53:46 2011 +0100
@@ -2,15 +2,23 @@
module Main where
-import Network
+import Network.Socket
+import qualified Network
+import Network.BSD
import Control.Concurrent.STM
import Control.Concurrent.Chan
+#if defined(NEW_EXCEPTIONS)
+import qualified Control.OldException as Exception
+#else
import qualified Control.Exception as Exception
+#endif
import System.Log.Logger
-----------------------------------
import Opts
import CoreTypes
+import OfficialServer.DBInteraction
import ServerCore
+import Utils
#if !defined(mingw32_HOST_OS)
@@ -18,12 +26,10 @@
#endif
-setupLoggers :: IO ()
setupLoggers =
updateGlobalLogger "Clients"
(setLevel INFO)
-main :: IO ()
main = withSocketsDo $ do
#if !defined(mingw32_HOST_OS)
installHandler sigPIPE Ignore Nothing;
@@ -32,11 +38,11 @@
setupLoggers
- stats' <- atomically $ newTMVar (StatisticsInfo 0 0)
+ stats <- atomically $ newTMVar (StatisticsInfo 0 0)
dbQueriesChan <- newChan
- coreChan' <- newChan
- serverInfo' <- getOpts $ newServerInfo stats' coreChan' dbQueriesChan
-
+ coreChan <- newChan
+ serverInfo' <- getOpts $ newServerInfo stats coreChan dbQueriesChan
+
#if defined(OFFICIAL_SERVER)
dbHost' <- askFromConsole "DB host: "
dbLogin' <- askFromConsole "login: "
@@ -46,7 +52,14 @@
let serverInfo = serverInfo'
#endif
+
+ proto <- getProtocolNumber "tcp"
Exception.bracket
- (Network.listenOn $ Network.PortNumber $ listenPort serverInfo)
+ (socket AF_INET Stream proto)
sClose
- (startServer serverInfo)
+ (\sock -> do
+ setSocketOption sock ReuseAddr 1
+ bindSocket sock (SockAddrInet (listenPort serverInfo) iNADDR_ANY)
+ listen sock maxListenQueue
+ startServer serverInfo sock
+ )
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/stresstest.hs
--- a/gameServer/stresstest.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/stresstest.hs Tue Jan 04 12:53:46 2011 +0100
@@ -6,7 +6,7 @@
import System.IO
import Control.Concurrent
import Network
-import Control.OldException
+import Control.Exception
import Control.Monad
import System.Random
@@ -14,24 +14,24 @@
import System.Posix
#endif
-session1 nick room = ["NICK", nick, "", "PROTO", "32", "", "PING", "", "CHAT", "lobby 1", "", "CREATE_ROOM", room, "", "CHAT", "room 1", "", "QUIT", "creator", ""]
-session2 nick room = ["NICK", nick, "", "PROTO", "32", "", "LIST", "", "JOIN_ROOM", room, "", "CHAT", "room 2", "", "PART", "", "CHAT", "lobby after part", "", "QUIT", "part-quit", ""]
-session3 nick room = ["NICK", nick, "", "PROTO", "32", "", "LIST", "", "JOIN_ROON", room, "", "CHAT", "room 2", "", "QUIT", "quit", ""]
+session1 nick room = ["NICK", nick, "", "PROTO", "24", "", "CHAT", "lobby 1", "", "CREATE", room, "", "CHAT", "room 1", "", "QUIT", "bye-bye", ""]
+session2 nick room = ["NICK", nick, "", "PROTO", "24", "", "LIST", "", "JOIN", room, "", "CHAT", "room 2", "", "PART", "", "CHAT", "lobby after part", "", "QUIT", "bye-bye", ""]
+session3 nick room = ["NICK", nick, "", "PROTO", "24", "", "LIST", "", "JOIN", room, "", "CHAT", "room 2", "", "QUIT", "bye-bye", ""]
emulateSession sock s = do
- mapM_ (\x -> hPutStrLn sock x >> hFlush sock >> randomRIO (30000::Int, 59000) >>= threadDelay) s
+ mapM_ (\x -> hPutStrLn sock x >> hFlush sock >> randomRIO (50000::Int, 90000) >>= threadDelay) s
hFlush sock
threadDelay 225000
-testing = Control.OldException.handle print $ do
+testing = Control.Exception.handle print $ do
putStrLn "Start"
sock <- connectTo "127.0.0.1" (PortNumber 46631)
num1 <- randomRIO (70000::Int, 70100)
num2 <- randomRIO (0::Int, 2)
num3 <- randomRIO (0::Int, 5)
- let nick1 = 'n' : show num1
- let room1 = 'r' : show num2
+ let nick1 = show num1
+ let room1 = show num2
case num2 of
0 -> emulateSession sock $ session1 nick1 room1
1 -> emulateSession sock $ session2 nick1 room1
@@ -40,7 +40,7 @@
putStrLn "Finish"
forks = forever $ do
- delay <- randomRIO (30000::Int, 59000)
+ delay <- randomRIO (10000::Int, 19000)
threadDelay delay
forkIO testing
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/stresstest2.hs
--- a/gameServer/stresstest2.hs Mon Dec 27 23:57:44 2010 +0100
+++ b/gameServer/stresstest2.hs Tue Jan 04 12:53:46 2011 +0100
@@ -6,7 +6,7 @@
import System.IO
import Control.Concurrent
import Network
-import Control.OldException
+import Control.Exception
import Control.Monad
import System.Random
@@ -14,28 +14,22 @@
import System.Posix
#endif
-session1 nick room = ["NICK", nick, "", "PROTO", "32", ""]
-
-
-
-testing = Control.OldException.handle print $ do
- putStrLn "Start"
+testing = Control.Exception.handle print $ do
+ delay <- randomRIO (100::Int, 300)
+ threadDelay delay
sock <- connectTo "127.0.0.1" (PortNumber 46631)
+ hClose sock
- num1 <- randomRIO (70000::Int, 70100)
- num2 <- randomRIO (0::Int, 2)
- num3 <- randomRIO (0::Int, 5)
- let nick1 = 'n' : show num1
- let room1 = 'r' : show num2
- mapM_ (\x -> hPutStrLn sock x >> hFlush sock >> randomRIO (300::Int, 590) >>= threadDelay) $ session1 nick1 room1
- mapM_ (\x -> hPutStrLn sock x >> hFlush sock) $ concatMap (\x -> ["CHAT_MSG", show x, ""]) [1..]
- hClose sock
- putStrLn "Finish"
-
-forks = testing
+forks i = do
+ delay <- randomRIO (50::Int, 190)
+ if i `mod` 10 == 0 then putStr (show i) else putStr "."
+ hFlush stdout
+ threadDelay delay
+ forkIO testing
+ forks (i + 1)
main = withSocketsDo $ do
#if !defined(mingw32_HOST_OS)
installHandler sigPIPE Ignore Nothing;
#endif
- forks
+ forks 1
diff -r 0ddb100fea61 -r f924be23ffb4 gameServer/stresstest3.hs
--- a/gameServer/stresstest3.hs Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-{-# LANGUAGE CPP #-}
-
-module Main where
-
-import IO
-import System.IO
-import Control.Concurrent
-import Network
-import Control.OldException
-import Control.Monad
-import System.Random
-import Control.Monad.State
-import Data.List
-
-#if !defined(mingw32_HOST_OS)
-import System.Posix
-#endif
-
-type SState = Handle
-io = liftIO
-
-readPacket :: StateT SState IO [String]
-readPacket = do
- h <- get
- p <- io $ hGetPacket h []
- return p
- where
- hGetPacket h buf = do
- l <- hGetLine h
- if (not $ null l) then hGetPacket h (buf ++ [l]) else return buf
-
-waitPacket :: String -> StateT SState IO Bool
-waitPacket s = do
- p <- readPacket
- return $ head p == s
-
-sendPacket :: [String] -> StateT SState IO ()
-sendPacket s = do
- h <- get
- io $ do
- mapM_ (hPutStrLn h) s
- hPutStrLn h ""
- hFlush h
-
-emulateSession :: StateT SState IO ()
-emulateSession = do
- n <- io $ randomRIO (100000::Int, 100100)
- waitPacket "CONNECTED"
- sendPacket ["NICK", "test" ++ (show n)]
- waitPacket "NICK"
- sendPacket ["PROTO", "31"]
- waitPacket "PROTO"
- b <- waitPacket "LOBBY:JOINED"
- --io $ print b
- sendPacket ["QUIT", "BYE"]
- return ()
-
-testing = Control.OldException.handle print $ do
- putStr "+"
- sock <- connectTo "127.0.0.1" (PortNumber 46631)
- evalStateT emulateSession sock
- --hClose sock
- putStr "-"
- hFlush stdout
-
-forks = forM_ [1..100] $ const $ do
- delay <- randomRIO (10000::Int, 30000)
- threadDelay delay
- forkIO testing
-
-main = withSocketsDo $ do
-#if !defined(mingw32_HOST_OS)
- installHandler sigPIPE Ignore Nothing;
-#endif
- forks
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/CCHandlers.inc
--- a/hedgewars/CCHandlers.inc Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,849 +0,0 @@
-(*
-* Hedgewars, a free turn based strategy game
-* Copyright (c) 2004-2010 Andrey Korotaev
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; version 2 of the License
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-*)
-
-function CheckNoTeamOrHH: boolean;
-var bRes: boolean;
-begin
-bRes:= (CurrentTeam = nil) or (CurrentHedgehog^.Gear = nil);
-{$IFDEF DEBUGFILE}
-if bRes then
-if CurrentTeam = nil then AddFileLog('CONSOLE: CurTeam = nil')
- else AddFileLog('CONSOLE: CurTeam <> nil, Gear = nil');
-{$ENDIF}
-CheckNoTeamOrHH:= bRes;
-end;
-////////////////////////////////////////////////////////////////////////////////
-procedure chQuit(var s: shortstring);
-const prevGState: TGameState = gsConfirm;
-begin
-s:= s; // avoid compiler hint
-if GameState <> gsConfirm then
- begin
- prevGState:= GameState;
- GameState:= gsConfirm
- end else
- GameState:= prevGState
-end;
-
-procedure chConfirm(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if GameState = gsConfirm then
- begin
- SendIPC('Q');
- GameState:= gsExit
- end
-else
- begin
- GameState:= gsChat;
- KeyPressChat(27);
- KeyPressChat(47);
- KeyPressChat(116);
- KeyPressChat(101);
- KeyPressChat(97);
- KeyPressChat(109);
- KeyPressChat(32)
- end
-end;
-
-procedure chCheckProto(var s: shortstring);
-var i, c: LongInt;
-begin
-if isDeveloperMode then
-begin
-val(s, i, c);
-if (c <> 0) or (i = 0) then exit;
-TryDo(i <= cNetProtoVersion, 'Protocol version mismatch: engine is too old', true);
-TryDo(i >= cNetProtoVersion, 'Protocol version mismatch: engine is too new', true)
-end
-end;
-
-procedure chAddTeam(var s: shortstring);
-var Color: Longword;
- ts, cs: shortstring;
-begin
-cs:= '';
-ts:= '';
-if isDeveloperMode then
-begin
-SplitBySpace(s, cs);
-SplitBySpace(cs, ts);
-val(cs, Color);
-TryDo(Color <> 0, 'Error: black team color', true);
-
-// color is always little endian so the mask must be constant also in big endian archs
-Color:= Color or $FF000000;
-
-AddTeam(Color);
-CurrentTeam^.TeamName:= ts;
-CurrentTeam^.PlayerHash:= s;
-if GameType in [gmtDemo, gmtSave] then CurrentTeam^.ExtDriven:= true;
-
-CurrentTeam^.voicepack:= AskForVoicepack('Default')
-end
-end;
-
-procedure chTeamLocal(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if not isDeveloperMode then exit;
-if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/rdriven"', true);
-CurrentTeam^.ExtDriven:= true
-end;
-
-procedure chGrave(var s: shortstring);
-begin
-if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/grave"', true);
-if s[1]='"' then Delete(s, 1, 1);
-if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
-CurrentTeam^.GraveName:= s
-end;
-
-procedure chFort(var s: shortstring);
-begin
-if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/fort"', true);
-if s[1]='"' then Delete(s, 1, 1);
-if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
-CurrentTeam^.FortName:= s
-end;
-
-procedure chVoicepack(var s: shortstring);
-begin
-if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/voicepack"', true);
-if s[1]='"' then Delete(s, 1, 1);
-if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
-CurrentTeam^.voicepack:= AskForVoicepack(s)
-end;
-
-procedure chFlag(var s: shortstring);
-begin
-if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/flag"', true);
-if s[1]='"' then Delete(s, 1, 1);
-if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
-CurrentTeam^.flag:= s
-end;
-
-procedure chScript(var s: shortstring);
-begin
-if s[1]='"' then Delete(s, 1, 1);
-if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
-ScriptLoad(s)
-end;
-
-procedure chAddHH(var id: shortstring);
-var s: shortstring;
- Gear: PGear;
-begin
-s:= '';
-if (not isDeveloperMode) or (CurrentTeam = nil) then exit;
-with CurrentTeam^ do
- begin
- SplitBySpace(id, s);
- CurrentHedgehog:= @Hedgehogs[HedgehogsNumber];
- val(id, CurrentHedgehog^.BotLevel);
- Gear:= AddGear(0, 0, gtHedgehog, 0, _0, _0, 0);
- SplitBySpace(s, id);
- val(s, Gear^.Health);
- TryDo(Gear^.Health > 0, 'Invalid hedgehog health', true);
- PHedgehog(Gear^.Hedgehog)^.Team:= CurrentTeam;
- if (GameFlags and gfSharedAmmo) <> 0 then CurrentHedgehog^.AmmoStore:= Clan^.ClanIndex
- else if (GameFlags and gfPerHogAmmo) <> 0 then
- begin
- AddAmmoStore;
- CurrentHedgehog^.AmmoStore:= StoreCnt - 1
- end
- else CurrentHedgehog^.AmmoStore:= TeamsCount - 1;
- CurrentHedgehog^.Gear:= Gear;
- CurrentHedgehog^.Name:= id;
- CurrentHedgehog^.InitialHealth:= Gear^.Health;
- CurrHedgehog:= HedgehogsNumber;
- inc(HedgehogsNumber)
- end
-end;
-
-procedure chSetHat(var s: shortstring);
-begin
-if (not isDeveloperMode) or (CurrentTeam = nil) then exit;
-with CurrentTeam^ do
- begin
- if not CurrentHedgehog^.King then
- if (s = '') or
- (((GameFlags and gfKing) <> 0) and (s = 'crown')) or
- ((Length(s) > 39) and (Copy(s,1,8) = 'Reserved') and (Copy(s,9,32) <> PlayerHash)) then
- CurrentHedgehog^.Hat:= 'NoHat'
- else
- CurrentHedgehog^.Hat:= s
- end;
-end;
-
-procedure chSetHHCoords(var x: shortstring);
-var y: shortstring;
- t: Longint;
-begin
-y:= '';
-if (not isDeveloperMode) or (CurrentHedgehog = nil) or (CurrentHedgehog^.Gear = nil) then exit;
-SplitBySpace(x, y);
-val(x, t);
-CurrentHedgehog^.Gear^.X:= int2hwFloat(t);
-val(y, t);
-CurrentHedgehog^.Gear^.Y:= int2hwFloat(t)
-end;
-
-procedure chSetAmmoLoadout(var descr: shortstring);
-begin
-SetAmmoLoadout(descr)
-end;
-
-procedure chSetAmmoDelay(var descr: shortstring);
-begin
-SetAmmoDelay(descr)
-end;
-
-procedure chSetAmmoProbability(var descr: shortstring);
-begin
-SetAmmoProbability(descr)
-end;
-
-procedure chSetAmmoReinforcement(var descr: shortstring);
-begin
-SetAmmoReinforcement(descr)
-end;
-
-procedure chAddAmmoStore(var descr: shortstring);
-begin
-descr:= ''; // avoid compiler hint
-AddAmmoStore
-end;
-
-procedure chBind(var id: shortstring);
-var s: shortstring;
- b: LongInt;
-begin
-s:= '';
-if CurrentTeam = nil then exit;
-SplitBySpace(id, s);
-if s[1]='"' then Delete(s, 1, 1);
-if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
-b:= KeyNameToCode(id);
-if b = 0 then OutError(errmsgUnknownVariable + ' "' + id + '"', false)
- else CurrentTeam^.Binds[b]:= s
-end;
-
-procedure chCurU_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementY:= -1;
-end;
-
-procedure chCurU_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementY:= 0;
-end;
-
-procedure chCurD_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementY:= 1;
-end;
-
-procedure chCurD_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementY:= 0;
-end;
-
-procedure chCurL_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementX:= -1;
-end;
-
-procedure chCurL_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementX:= 0;
-end;
-
-procedure chCurR_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementX:= 1;
-end;
-
-procedure chCurR_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-CursorMovementX:= 0;
-end;
-
-procedure chLeft_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('L');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmLeft
-end;
-
-procedure chLeft_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('l');
-with CurrentHedgehog^.Gear^ do
- Message:= Message and not gmLeft
-end;
-
-procedure chRight_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('R');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmRight
-end;
-
-procedure chRight_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('r');
-with CurrentHedgehog^.Gear^ do
- Message:= Message and not gmRight
-end;
-
-procedure chUp_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('U');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmUp
-end;
-
-procedure chUp_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('u');
-with CurrentHedgehog^.Gear^ do
- Message:= Message and not gmUp
-end;
-
-procedure chDown_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('D');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmDown
-end;
-
-procedure chDown_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('d');
-with CurrentHedgehog^.Gear^ do
- Message:= Message and not gmDown
-end;
-
-procedure chPrecise_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('Z');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmPrecise
-end;
-
-procedure chPrecise_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('z');
-with CurrentHedgehog^.Gear^ do
- Message:= Message and not gmPrecise
-end;
-
-procedure chLJump(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('j');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmLJump
-end;
-
-procedure chHJump(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('J');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmHJump
-end;
-
-procedure chAttack_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- begin
- {$IFDEF DEBUGFILE}AddFileLog('/+attack: hedgehog''s Gear^.State = '+inttostr(State));{$ENDIF}
- if ((State and gstHHDriven) <> 0) then
- begin
- FollowGear:= CurrentHedgehog^.Gear;
- if not CurrentTeam^.ExtDriven then SendIPC('A');
- Message:= Message or gmAttack
- end
- end
-end;
-
-procedure chAttack_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then exit;
-with CurrentHedgehog^.Gear^ do
- begin
- if not CurrentTeam^.ExtDriven and
- ((Message and gmAttack) <> 0) then SendIPC('a');
- Message:= Message and not gmAttack
- end
-end;
-
-procedure chSwitch(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-if not CurrentTeam^.ExtDriven then SendIPC('S');
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- Message:= Message or gmSwitch
-end;
-
-procedure chNextTurn(var s: shortstring);
-begin
- s:= s; // avoid compiler hint
- TryDo(AllInactive, '/nextturn called when not all gears are inactive', true);
-
- if not CurrentTeam^.ExtDriven then SendIPC('N');
-{$IFDEF DEBUGFILE}
- AddFileLog('Doing SwitchHedgehog: time '+inttostr(GameTicks));
-{$ENDIF}
- perfExt_NewTurnBeginning();
-end;
-
-procedure chSay(var s: shortstring);
-begin
-SendIPC('s' + s);
-
-if copy(s, 1, 4) = '/me ' then
- s:= #2'* ' + UserNick + ' ' + copy(s, 5, Length(s) - 4)
-else
- s:= #1 + UserNick + ': ' + s;
-
-AddChatString(s)
-end;
-
-procedure chTeamSay(var s: shortstring);
-begin
-SendIPC('b' + s);
-
-s:= #4 + '[Team] ' + UserNick + ': ' + s;
-
-AddChatString(s)
-end;
-
-procedure chTimer(var s: shortstring);
-begin
-if (s[0] <> #1) or (s[1] < '1') or (s[1] > '5') or CheckNoTeamOrHH then exit;
-
-if not CurrentTeam^.ExtDriven then SendIPC(s);
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- begin
- Message:= Message or gmTimer;
- MsgParam:= byte(s[1]) - ord('0')
- end
-end;
-
-procedure chSlot(var s: shortstring);
-var slot: LongWord;
-begin
-if (s[0] <> #1) or CheckNoTeamOrHH then exit;
-slot:= byte(s[1]) - 49;
-if slot > cMaxSlotIndex then exit;
-if not CurrentTeam^.ExtDriven then SendIPC(char(byte(s[1]) + 79));
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-with CurrentHedgehog^.Gear^ do
- begin
- Message:= Message or gmSlot;
- MsgParam:= slot
- end
-end;
-
-procedure chSetWeapon(var s: shortstring);
-begin
- if (s[0] <> #1) or CheckNoTeamOrHH then exit;
-
- if TAmmoType(s[1]) > High(TAmmoType) then exit;
-
- if not CurrentTeam^.ExtDriven then SendIPC('w' + s);
-
- with CurrentHedgehog^.Gear^ do
- begin
- Message:= Message or gmWeapon;
- MsgParam:= byte(s[1]);
- end;
-end;
-
-procedure chTaunt(var s: shortstring);
-begin
-if (s[0] <> #1) or CheckNoTeamOrHH then exit;
-
-if TWave(s[1]) > High(TWave) then exit;
-
-if not CurrentTeam^.ExtDriven then SendIPC('t' + s);
-
-with CurrentHedgehog^.Gear^ do
- begin
- Message:= Message or gmAnimate;
- MsgParam:= byte(s[1])
- end
-end;
-
-procedure chHogSay(var s: shortstring);
-var Gear: PVisualGear;
- text: shortstring;
-begin
-text:= copy(s, 2, Length(s)-1);
-if CheckNoTeamOrHH
-or ((CurrentHedgehog^.Gear^.State and gstHHDriven) = 0) then
- begin
- chSay(text);
- exit
- end;
-
-if not CurrentTeam^.ExtDriven then SendIPC('h' + s);
-
-if byte(s[1]) < 4 then
- begin
- Gear:= AddVisualGear(0, 0, vgtSpeechBubble);
- if Gear <> nil then
- begin
- Gear^.Hedgehog:= CurrentHedgehog;
- Gear^.Text:= text;
- Gear^.FrameTicks:= byte(s[1])
- end
- end
-else
- begin
- SpeechType:= byte(s[1])-3;
- SpeechText:= text
- end;
-
-end;
-
-procedure doPut(putX, putY: LongInt; fromAI: boolean);
-begin
-if CheckNoTeamOrHH or isPaused then exit;
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-bShowFinger:= false;
-if not CurrentTeam^.ExtDriven and bShowAmmoMenu then
- begin
- bSelected:= true;
- exit
- end;
-
-with CurrentHedgehog^.Gear^,
- CurrentHedgehog^ do
- if (State and gstHHChooseTarget) <> 0 then
- begin
- isCursorVisible:= false;
- if not CurrentTeam^.ExtDriven then
- begin
- if fromAI then
- begin
- TargetPoint.X:= putX;
- TargetPoint.Y:= putY
- end else
- begin
- TargetPoint.X:= CursorPoint.X - WorldDx;
- TargetPoint.Y:= cScreenHeight - CursorPoint.Y - WorldDy;
- end;
- SendIPCXY('p', TargetPoint.X, TargetPoint.Y);
- end
- else
- begin
- TargetPoint.X:= putX;
- TargetPoint.Y:= putY
- end;
- {$IFDEF DEBUGFILE}AddFilelog('put: ' + inttostr(TargetPoint.X) + ', ' + inttostr(TargetPoint.Y));{$ENDIF}
- State:= State and not gstHHChooseTarget;
- if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AttackingPut) <> 0 then
- Message:= Message or gmAttack;
- end
- else
- if CurrentTeam^.ExtDriven then
- OutError('got /put while not being in choose target mode', false)
-end;
-
-procedure chPut(var s: shortstring);
-begin
- s:= s; // avoid compiler hint
- doPut(0, 0, false);
-end;
-
-procedure chCapture(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-flagMakeCapture:= true
-end;
-
-procedure chSkip(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if not CurrentTeam^.ExtDriven then SendIPC(',');
-uStats.Skipped;
-skipFlag:= true
-end;
-
-procedure chSetMap(var s: shortstring);
-begin
-if isDeveloperMode then
-begin
-Pathz[ptMapCurrent]:= Pathz[ptMaps] + '/' + s;
-InitStepsFlags:= InitStepsFlags or cifMap
-end
-end;
-
-procedure chSetTheme(var s: shortstring);
-begin
-if isDeveloperMode then
-begin
-Pathz[ptCurrTheme]:= Pathz[ptThemes] + '/' + s;
-InitStepsFlags:= InitStepsFlags or cifTheme
-end
-end;
-
-procedure chSetSeed(var s: shortstring);
-begin
-if isDeveloperMode then
-begin
-SetRandomSeed(s);
-cSeed:= s;
-InitStepsFlags:= InitStepsFlags or cifRandomize
-end
-end;
-
-procedure chAmmoMenu(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then
- bShowAmmoMenu:= true
-else
- begin
- with CurrentTeam^ do
- with Hedgehogs[CurrHedgehog] do
- begin
- bSelected:= false;
-
- if bShowAmmoMenu then bShowAmmoMenu:= false
- else if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
- ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0)) or
- ((Gear^.State and gstHHDriven) = 0) then else bShowAmmoMenu:= true
- end;
- if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1
- end
-end;
-
-procedure chFullScr(var s: shortstring);
-var flags: Longword = 0;
- ico: PSDL_Surface;
-{$IFDEF DEBUGFILE}
- buf: array[byte] of char;
-{$ENDIF}
-begin
- s:= s; // avoid compiler hint
- if Length(s) = 0 then cFullScreen:= not cFullScreen
- else cFullScreen:= s = '1';
-
-{$IFDEF DEBUGFILE}
- buf[0]:= char(0); // avoid compiler hint
- AddFileLog('Prepare to change video parameters...');
-{$ENDIF}
-
- flags:= SDL_OPENGL;// or SDL_RESIZABLE;
-
- if cFullScreen then
- flags:= flags or SDL_FULLSCREEN;
-
-{$IFDEF SDL_IMAGE_NEWER}
- WriteToConsole('Init SDL_image... ');
- SDLTry(IMG_Init(IMG_INIT_PNG) <> 0, true);
- WriteLnToConsole(msgOK);
-{$ENDIF}
- // load engine icon
-{$IFDEF DARWIN}
- ico:= LoadImage(Pathz[ptGraphics] + '/hwengine_mac', ifIgnoreCaps);
-{$ELSE}
- ico:= LoadImage(Pathz[ptGraphics] + '/hwengine', ifIgnoreCaps);
-{$ENDIF}
- if ico <> nil then
- begin
- SDL_WM_SetIcon(ico, 0);
- SDL_FreeSurface(ico)
- end;
-
- // set window caption
- SDL_WM_SetCaption('Hedgewars', nil);
-
- if SDLPrimSurface <> nil then
- begin
-{$IFDEF DEBUGFILE}
- AddFileLog('Freeing old primary surface...');
-{$ENDIF}
- SDL_FreeSurface(SDLPrimSurface);
- SDLPrimSurface:= nil;
- end;
-
-{$IFDEF SDL13}
- if SDLwindow = nil then
- begin
- SDLwindow:= SDL_CreateWindow('Hedgewars', 0, 0, cScreenWidth, cScreenHeight,
- SDL_WINDOW_OPENGL or SDL_WINDOW_SHOWN
- {$IFDEF IPHONEOS} or SDL_WINDOW_BORDERLESS{$ENDIF});
- SDL_CreateRenderer(SDLwindow, -1, 0);
- end;
-
- SDL_SetRenderDrawColor(0, 0, 0, 255);
- SDL_RenderFill(nil);
- SDL_RenderPresent();
-{$ELSE}
- SDLPrimSurface:= SDL_SetVideoMode(cScreenWidth, cScreenHeight, cBits, flags);
- SDLTry(SDLPrimSurface <> nil, true);
- PixelFormat:= SDLPrimSurface^.format;
-{$ENDIF}
-
-{$IFDEF DEBUGFILE}
- AddFileLog('Setting up OpenGL...');
- AddFileLog('SDL video driver: ' + shortstring(SDL_VideoDriverName(buf, sizeof(buf))));
-{$ENDIF}
- SetupOpenGL();
-end;
-
-procedure chVol_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-inc(cVolumeDelta, 3)
-end;
-
-procedure chVol_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-dec(cVolumeDelta, 3)
-end;
-
-procedure chFindhh(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if CheckNoTeamOrHH or isPaused then exit;
-bShowFinger:= true;
-FollowGear:= CurrentHedgehog^.Gear
-end;
-
-procedure chPause(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
-if gameType <> gmtNet then
- isPaused:= not isPaused;
-SDL_ShowCursor(ord(isPaused))
-end;
-
-procedure chRotateMask(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-if ((GameFlags and gfInvulnerable) = 0) then cTagsMask:= cTagsMasks[cTagsMask] else cTagsMask:= cTagsMasksNoHealth[cTagsMask];
-end;
-
-procedure chSpeedup_p(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-isSpeed:= true
-end;
-
-procedure chSpeedup_m(var s: shortstring);
-begin
-s:= s; // avoid compiler hint
-isSpeed:= false
-end;
-
-procedure chZoomIn(var s: shortstring);
-begin
- s:= s; // avoid compiler hint
- if ZoomValue < cMinZoomLevel then
- ZoomValue:= ZoomValue + cZoomDelta;
-end;
-
-procedure chZoomOut(var s: shortstring);
-begin
- s:= s; // avoid compiler hint
- if ZoomValue > cMaxZoomLevel then
- ZoomValue:= ZoomValue - cZoomDelta;
-end;
-
-procedure chZoomReset(var s: shortstring);
-begin
- s:= s; // avoid compiler hint
- ZoomValue:= cDefaultZoomLevel;
-end;
-
-procedure chChat(var s: shortstring);
-begin
- s:= s; // avoid compiler hint
- GameState:= gsChat;
- KeyPressChat(27)
-end;
-
-procedure chHistory(var s: shortstring);
-begin
- s:= s; // avoid compiler hint
- uChat.showAll:= not uChat.showAll
-end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/CMakeLists.txt
--- a/hedgewars/CMakeLists.txt Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/CMakeLists.txt Tue Jan 04 12:53:46 2011 +0100
@@ -11,24 +11,24 @@
#if the headers are not installed, the newer apis won't be activated
find_file(sdlmixer_h SDL_mixer.h ${SDLMIXER_INCLUDE_DIR})
if(sdlmixer_h)
- file(STRINGS ${sdlmixer_h} sdlmixer_version_tmp REGEX "SDL_MIXER_PATCHLEVEL[\t' ']+[0-9]+")
- string(REGEX MATCH ".([0-9]+)" sdlmixer_version "${sdlmixer_version_tmp}")
+ file(STRINGS ${sdlmixer_h} sdlmixer_version_tmp REGEX "SDL_MIXER_PATCHLEVEL[\t' ']+[0-9]+")
+ string(REGEX MATCH ".([0-9]+)" sdlmixer_version "${sdlmixer_version_tmp}")
- if(sdlmixer_version GREATER 9)
- message(STATUS "Enabling enhanced SDL_Mixer calls")
- set(pascal_compiler_flags_cmn "-dSDL_MIXER_NEWER" ${pascal_compiler_flags_cmn})
- endif()
+ if(sdlmixer_version GREATER 9)
+ message(STATUS "Enabling enhanced SDL_Mixer calls")
+ set(pascal_compiler_flags_cmn "-dSDL_MIXER_NEWER" ${pascal_compiler_flags_cmn})
+ endif()
endif()
find_file(sdlimage_h SDL_image.h ${SDLIMAGE_INCLUDE_DIR})
if(sdlimage_h)
- file(STRINGS ${sdlimage_h} sdlimage_version_tmp REGEX "SDL_IMAGE_PATCHLEVEL[\t' ']+[0-9]+")
- string(REGEX MATCH ".([0-9]+)" sdlimage_version "${sdlimage_version_tmp}")
+ file(STRINGS ${sdlimage_h} sdlimage_version_tmp REGEX "SDL_IMAGE_PATCHLEVEL[\t' ']+[0-9]+")
+ string(REGEX MATCH ".([0-9]+)" sdlimage_version "${sdlimage_version_tmp}")
- if(sdlimage_version GREATER 7)
- message(STATUS "Enabling enhanced SDL_Image calls")
- set(pascal_compiler_flags_cmn "-dSDL_IMAGE_NEWER" ${pascal_compiler_flags_cmn})
- endif()
+ if(sdlimage_version GREATER 7)
+ message(STATUS "Enabling enhanced SDL_Image calls")
+ set(pascal_compiler_flags_cmn "-dSDL_IMAGE_NEWER" ${pascal_compiler_flags_cmn})
+ endif()
endif()
#SOURCE AND PROGRAMS SECTION
@@ -36,86 +36,95 @@
set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwengine.pas)
set(engine_sources
- ${hwengine_project}
- SDLh.pas
- uAI.pas
- uAIActions.pas
- uAIAmmoTests.pas
- uAIMisc.pas
- uAmmos.pas
- uChat.pas
- uCollisions.pas
- uConsole.pas
- uConsts.pas
- uFloat.pas
- uGame.pas
- uGears.pas
- uIO.pas
- uKeys.pas
- uLand.pas
- uLandGraphics.pas
- uLandObjects.pas
- uLandTemplates.pas
- uLandTexture.pas
- uLocale.pas
- uMisc.pas
- uMobile.pas
- uRandom.pas
- uScript.pas
- adler32.pas
- uSound.pas
- uStats.pas
- uStore.pas
- uTeams.pas
- uVisualGears.pas
- uWorld.pas
- CCHandlers.inc
- GSHandlers.inc
- VGSHandlers.inc
- GearDrawing.inc
- HHHandlers.inc
- SinTable.inc
- ArgParsers.inc
- options.inc
- ${CMAKE_CURRENT_BINARY_DIR}/config.inc
- )
+ ${hwengine_project}
+ SDLh.pas
+ uAI.pas
+ uAIActions.pas
+ uAIAmmoTests.pas
+ uAIMisc.pas
+ uAmmos.pas
+ uCaptions.pas
+ uChat.pas
+ uCollisions.pas
+ uCommands.pas
+ uCommandHandlers.pas
+ uConsole.pas
+ uConsts.pas
+ uDebug.pas
+ uFloat.pas
+ uGame.pas
+ uGears.pas
+ uGearsRender.pas
+ uIO.pas
+ uKeys.pas
+ uLand.pas
+ uLandGraphics.pas
+ uLandObjects.pas
+ uLandPainted.pas
+ uLandTemplates.pas
+ uLandTexture.pas
+ uLocale.pas
+ uMisc.pas
+ uMobile.pas
+ uRandom.pas
+ uRender.pas
+ uRenderUtils.pas
+ uScript.pas
+ uSinTable.pas
+ uSound.pas
+ uStats.pas
+ uStore.pas
+ uTeams.pas
+ uTextures.pas
+ uTypes.pas
+ uUtils.pas
+ uVisualGears.pas
+ uWorld.pas
+ GSHandlers.inc
+ VGSHandlers.inc
+ HHHandlers.inc
+ ArgParsers.inc
+ options.inc
+ adler32.pas
+ ${CMAKE_CURRENT_BINARY_DIR}/config.inc
+ )
if(BUILD_ENGINE_LIBRARY)
- message(STATUS "Engine will be built as library (experimental)")
- set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwLibrary.pas)
- set(engine_sources ${hwengine_project} PascalExports.pas ${engine_sources})
- set(pascal_compiler_flags_cmn "-dHWLIBRARY" "-k-no_order_inits" "-fPIC" ${pascal_compiler_flags_cmn})
+ message(STATUS "Engine will be built as library (experimental)")
+ set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwLibrary.pas)
+ set(engine_sources ${hwengine_project} PascalExports.pas ${engine_sources})
+ set(pascal_compiler_flags_cmn "-dHWLIBRARY" "-k-no_order_inits" "-fPIC" ${pascal_compiler_flags_cmn})
endif(BUILD_ENGINE_LIBRARY)
find_program(fpc_executable ${fpc_tryexe})
if(fpc_executable)
- exec_program(${fpc_executable} ARGS "-iV" OUTPUT_VARIABLE fpc_output)
+ exec_program(${fpc_executable} ARGS "-iV" OUTPUT_VARIABLE fpc_output)
endif(fpc_executable)
set(noexecstack_flags "-k-z" "-knoexecstack")
file(WRITE ${EXECUTABLE_OUTPUT_PATH}/checkstack.pas "begin end.")
exec_program(${fpc_executable} ${EXECUTABLE_OUTPUT_PATH}
- ARGS ${noexecstack_flags} checkstack.pas
- OUTPUT_VARIABLE noout
- RETURN_VALUE testnoexecstack
- )
+ ARGS ${noexecstack_flags} checkstack.pas
+ OUTPUT_VARIABLE noout
+ RETURN_VALUE testnoexecstack
+ )
if(${testnoexecstack})
- set (noexecstack_flags "")
+ set (noexecstack_flags "")
endif(${testnoexecstack})
if(APPLE)
- string(REGEX MATCH "[pP][pP][cC]+" powerpc_build "${CMAKE_OSX_ARCHITECTURES}")
- string(REGEX MATCH "[iI]386+" i386_build "${CMAKE_OSX_ARCHITECTURES}")
- string(REGEX MATCH "[xX]86_64+" x86_64_build "${CMAKE_OSX_ARCHITECTURES}")
+ string(REGEX MATCH "[pP][pP][cC]+" powerpc_build "${CMAKE_OSX_ARCHITECTURES}")
+ string(REGEX MATCH "[iI]386+" i386_build "${CMAKE_OSX_ARCHITECTURES}")
+ string(REGEX MATCH "[xX]86_64+" x86_64_build "${CMAKE_OSX_ARCHITECTURES}")
- if(powerpc_build)
- set(powerpc_build "powerpc")
- endif()
+ if(powerpc_build)
+ set(powerpc_build "powerpc")
+ endif()
endif(APPLE)
@@ -123,19 +132,19 @@
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" fpc_version "${fpc_output}")
if(fpc_version)
- string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" fpc_vers_major "${fpc_version}")
- string(REGEX REPLACE "[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" fpc_vers_minor "${fpc_version}")
- string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" fpc_vers_patch "${fpc_version}")
- message(STATUS "Freepascal version detected: ${fpc_vers_major}.${fpc_vers_minor}")
- math(EXPR fpc_ver "${fpc_vers_major}*10000 + ${fpc_vers_minor}*100 + ${fpc_vers_patch}")
+ string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" fpc_vers_major "${fpc_version}")
+ string(REGEX REPLACE "[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" fpc_vers_minor "${fpc_version}")
+ string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" fpc_vers_patch "${fpc_version}")
+ message(STATUS "Freepascal version detected: ${fpc_vers_major}.${fpc_vers_minor}")
+ math(EXPR fpc_ver "${fpc_vers_major}*10000 + ${fpc_vers_minor}*100 + ${fpc_vers_patch}")
- if(fpc_ver LESS "020200")
- message(FATAL_ERROR "Minimum required version of FreePascal is 2.2.0")
- elseif(APPLE AND x86_64_build AND fpc_ver LESS "020400")
- message(FATAL_ERROR "Minimum required version of FreePascal is 2.4.0 for building 64 bit applications!")
- endif()
+ if(fpc_ver LESS "020200")
+ message(FATAL_ERROR "Minimum required version of FreePascal is 2.2.0")
+ elseif(APPLE AND x86_64_build AND fpc_ver LESS "020400")
+ message(FATAL_ERROR "Minimum required version of FreePascal is 2.4.0 for building 64 bit applications!")
+ endif()
else()
- message(FATAL_ERROR "No Pascal compiler found!")
+ message(FATAL_ERROR "No Pascal compiler found!")
endif()
set(pascal_compiler ${fpc_executable})
@@ -144,40 +153,40 @@
#DEPENDECIES AND EXECUTABLES SECTION
IF(NOT APPLE OR BUILD_ENGINE_LIBRARY)
- #here is the command for standard executables or for shared library
- add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}"
- COMMAND "${pascal_compiler}"
- ARGS ${pascal_compiler_flags}
- MAIN_DEPENDENCY ${hwengine_project}
- DEPENDS ${engine_sources}
- )
+ #here is the command for standard executables or for shared library
+ add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}"
+ COMMAND "${pascal_compiler}"
+ ARGS ${pascal_compiler_flags}
+ MAIN_DEPENDENCY ${hwengine_project}
+ DEPENDS ${engine_sources}
+ )
ELSE()
- #let's build sdlmain, which is absent from the framework
- find_package(SDL REQUIRED)
+ #let's build sdlmain, which is absent from the framework
+ find_package(SDL REQUIRED)
- set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
- include_directories(${SDL_INCLUDE_DIR})
+ set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
+ include_directories(${SDL_INCLUDE_DIR})
- add_library (SDLmain STATIC SDLMain.m)
+ add_library (SDLmain STATIC SDLMain.m)
- #these are the dependencies for building a universal binary on Mac OS X
- foreach (build_arch ${powerpc_build} ${i386_build} ${x86_64_build})
- set(lipo_args_list "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}" ${lipo_args_list})
- add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}"
- COMMAND "${pascal_compiler}"
- ARGS ${pascal_compiler_flags} -ohwengine.${build_arch} -P${build_arch}
- MAIN_DEPENDENCY ${hwengine_project}
- DEPENDS ${engine_sources} SDLmain lua
- )
- add_custom_target(hwengine.${build_arch} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}")
- endforeach()
+ #these are the dependencies for building a universal binary on Mac OS X
+ foreach (build_arch ${powerpc_build} ${i386_build} ${x86_64_build})
+ set(lipo_args_list "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}" ${lipo_args_list})
+ add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}"
+ COMMAND "${pascal_compiler}"
+ ARGS ${pascal_compiler_flags} -ohwengine.${build_arch} -P${build_arch}
+ MAIN_DEPENDENCY ${hwengine_project}
+ DEPENDS ${engine_sources} SDLmain lua
+ )
+ add_custom_target(hwengine.${build_arch} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}")
+ endforeach()
- add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine"
- COMMAND "lipo"
- ARGS ${lipo_args_list} -create -output ${EXECUTABLE_OUTPUT_PATH}/hwengine
- DEPENDS ${lipo_args_list}
- )
+ add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine"
+ COMMAND "lipo"
+ ARGS ${lipo_args_list} -create -output ${EXECUTABLE_OUTPUT_PATH}/hwengine
+ DEPENDS ${lipo_args_list}
+ )
ENDIF()
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/GSHandlers.inc
--- a/hedgewars/GSHandlers.inc Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/GSHandlers.inc Tue Jan 04 12:53:46 2011 +0100
@@ -28,32 +28,32 @@
// Gear is still on the same Pixel it was before
if steps < 1 then
- begin
+ begin
if onlyCheckIfChanged then
- begin
+ begin
Gear^.X := Gear^.X + dX;
Gear^.Y := Gear^.Y + dY;
EXIT;
- end
+ end
else
steps := 1;
- end;
+ end;
if steps > 1 then
- begin
+ begin
sX:= dX / steps;
sY:= dY / steps;
- end
+ end
else
- begin
+ begin
sX:= dX;
sY:= dY;
- end;
+ end;
caller:= Gear^.doStep;
for i:= 1 to steps do
- begin
+ begin
Gear^.X := Gear^.X + sX;
Gear^.Y := Gear^.Y + sY;
step(Gear);
@@ -61,7 +61,7 @@
or ((Gear^.State and gstCollision) <> 0)
or ((Gear^.State and gstMoving) = 0) then
break;
- end;
+ end;
end;
procedure makeHogsWorry(x, y: hwFloat; r: LongInt);
@@ -71,27 +71,27 @@
begin
gi := GearsList;
while gi <> nil do
- begin
+ begin
if (gi^.Kind = gtHedgehog) then
- begin
+ begin
d := r - hwRound(Distance(gi^.X - x, gi^.Y - y));
if (d > 1) and not gi^.Invulnerable and (GetRandom(2) = 0) then
- begin
+ begin
if (CurrentHedgehog^.Gear = gi) then
- PlaySound(sndOops, PHedgehog(gi^.Hedgehog)^.Team^.voicepack)
+ PlaySound(sndOops, gi^.Hedgehog^.Team^.voicepack)
else
- begin
+ begin
if (gi^.State and gstMoving) = 0 then
gi^.State := gi^.State or gstLoser;
if d > r div 2 then
- PlaySound(sndNooo, PHedgehog(gi^.Hedgehog)^.Team^.voicepack)
+ PlaySound(sndNooo, gi^.Hedgehog^.Team^.voicepack)
else
- PlaySound(sndUhOh, PHedgehog(gi^.Hedgehog)^.Team^.voicepack);
+ PlaySound(sndUhOh, gi^.Hedgehog^.Team^.voicepack);
+ end;
end;
end;
+ gi := gi^.NextGear
end;
- gi := gi^.NextGear
- end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure doStepDrowningGear(Gear: PGear);
@@ -107,37 +107,38 @@
isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
// probably needs tweaking. might need to be in a case statement based upon gear type
if cWaterLine < hwRound(Gear^.Y) + Gear^.Radius then
- begin
+ begin
skipSpeed := _0_25;
skipAngle := _1_9;
skipDecay := _0_87;
// this could perhaps be a tiny bit higher.
if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) and
(hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
- begin
+ begin
Gear^.dY.isNegative := true;
Gear^.dY := Gear^.dY * skipDecay;
Gear^.dX := Gear^.dX * skipDecay;
CheckGearDrowning := false;
PlaySound(sndSkip)
- end
+ end
else
- begin
+ begin
if not isSubmersible then
- begin
+ begin
CheckGearDrowning := true;
Gear^.State := gstDrowning;
Gear^.RenderTimer := false;
- if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot) and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
+ if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot) and
+ (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
if Gear^.Kind = gtHedgehog then
begin
- if PHedgehog(Gear^.Hedgehog)^.Effects[heResurrectable] then
+ if Gear^.Hedgehog^.Effects[heResurrectable] then
ResurrectHedgehog(Gear)
else
begin
Gear^.doStep := @doStepDrowningGear;
Gear^.State := Gear^.State and (not gstHHDriven);
- AddCaption(Format(GetEventString(eidDrowned), PHedgehog(Gear^.Hedgehog)^.Name), cWhiteColor, capgrpMessage);
+ AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
end
end
else
@@ -152,30 +153,38 @@
if ((cReducedQuality and rqPlainSplash) = 0) and
(((not isSubmersible) and (hwRound(Gear^.Y) < cWaterLine + 64 + Gear^.Radius)) or
(isSubmersible and (hwRound(Gear^.Y) < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0) and (CurAmmoGear^.dY < _0_01)))) then
- begin
+ begin
AddVisualGear(hwRound(Gear^.X), cWaterLine, vgtSplash);
maxDrops := (Gear^.Radius div 2) + hwRound(Gear^.dX * Gear^.Radius * 2) + hwRound(Gear^.
dY * Gear^.Radius * 2);
for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do
- begin
+ begin
particle := AddVisualGear(hwRound(Gear^.X) - 3 + Random(6), cWaterLine, vgtDroplet);
if particle <> nil then
- begin
+ begin
particle^.dX := particle^.dX - (Gear^.dX.QWordValue / 42949672960);
particle^.dY := particle^.dY - (Gear^.dY.QWordValue / 21474836480)
+ end
end
- end
- end;
+ end;
if isSubmersible and (CurAmmoGear^.Pos = 0) then CurAmmoGear^.Pos := 1000
end
else
CheckGearDrowning := false;
end;
-procedure CheckCollision(Gear: PGear);
+procedure CheckCollision(Gear: PGear); inline;
begin
- if TestCollisionXwithGear(Gear, hwSign(Gear^.X)) or TestCollisionYwithGear(Gear, hwSign(Gear^.Y)
+ if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) or TestCollisionYwithGear(Gear, hwSign(Gear^.dY)
+ )
+ then Gear^.State := Gear^.State or gstCollision
+ else Gear^.State := Gear^.State and not gstCollision
+end;
+
+procedure CheckCollisionWithLand(Gear: PGear); inline;
+begin
+ if TestCollisionX(Gear, hwSign(Gear^.dX)) or TestCollisionY(Gear, hwSign(Gear^.dY)
)
then Gear^.State := Gear^.State or gstCollision
else Gear^.State := Gear^.State and not gstCollision
@@ -188,24 +197,23 @@
particle: PVisualGear;
begin
if _0_4 < Gear^.dY then
- begin
+ begin
dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear);
PlaySound(sndBump);
if dmg < 1 then exit;
for i:= min(12, (3 + dmg div 10)) downto 0 do
- begin
- particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,
- vgtDust);
+ begin
+ particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
- end;
+ end;
if (Gear^.Invulnerable) then exit;
//if _0_6 < Gear^.dY then
- // PlaySound(sndOw4, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack)
+ // PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
//else
- // PlaySound(sndOw1, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+ // PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
ApplyDamage(Gear, dmg, dsFall);
end
@@ -233,10 +241,10 @@
AllInactive := false;
Gear^.Y := Gear^.Y + cDrownSpeed;
Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed;
- if (cWaterOpacity > $FE) or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
+ if (not SuddenDeathDmg and (cWaterOpacity > $FE)) or (SuddenDeathDmg and (cSDWaterOpacity > $FE)) or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
DeleteGear(Gear);
// Create some bubbles (0.5% might be better but causes too few bubbles sometimes)
- if (cWaterOpacity < $FF) and ((GameTicks and $1F) = 0) then
+ if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then
AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius,
vgtBubble)
@@ -267,60 +275,60 @@
if (hwRound(Gear^.X) < LAND_WIDTH div -2) or (hwRound(Gear^.X) > LAND_WIDTH * 3 div 2) then Gear^.State := Gear^.State or gstCollision;
if Gear^.dY.isNegative then
- begin
+ begin
isFalling := true;
if TestCollisionYwithGear(Gear, -1) then
- begin
+ begin
collV := -1;
Gear^.dX := Gear^.dX * Gear^.Friction;
Gear^.dY := - Gear^.dY * Gear^.Elasticity;
Gear^.State := Gear^.State or gstCollision
- end
+ end
else if (Gear^.AdvBounce=1) and TestCollisionYwithGear(Gear, 1) then collV := 1;
- end
+ end
else if TestCollisionYwithGear(Gear, 1) then
begin
- collV := 1;
- isFalling := false;
- Gear^.dX := Gear^.dX * Gear^.Friction;
- Gear^.dY := - Gear^.dY * Gear^.Elasticity;
- Gear^.State := Gear^.State or gstCollision
+ collV := 1;
+ isFalling := false;
+ Gear^.dX := Gear^.dX * Gear^.Friction;
+ Gear^.dY := - Gear^.dY * Gear^.Elasticity;
+ Gear^.State := Gear^.State or gstCollision
end
else
- begin
+ begin
isFalling := true;
if (Gear^.AdvBounce=1) and not Gear^.dY.isNegative and TestCollisionYwithGear(Gear, -1) then
collV := -1;
- end;
+ end;
if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
- begin
+ begin
collH := hwSign(Gear^.dX);
Gear^.dX := - Gear^.dX * Gear^.Elasticity;
Gear^.dY := Gear^.dY * Gear^.Elasticity;
Gear^.State := Gear^.State or gstCollision
- end
+ end
else if (Gear^.AdvBounce=1) and TestCollisionXwithGear(Gear, -hwSign(Gear^.dX)) then
collH := -hwSign(Gear^.dX);
//if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then
if (Gear^.AdvBounce=1) and (collV <>0) and (collH <> 0) and ((collV=-1) or ((tdX.QWordValue +
tdY.QWordValue) > _0_2.QWordValue)) then
- begin
+ begin
Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
Gear^.dY := tdX*Gear^.Elasticity;
//*Gear^.Friction;
Gear^.dY.isNegative := not tdY.isNegative;
isFalling := false;
Gear^.AdvBounce := 10;
- end;
+ end;
if Gear^.AdvBounce > 1 then dec(Gear^.AdvBounce);
if isFalling then
begin
Gear^.dY := Gear^.dY + cGravity;
- if (GameFlags and gfMoreWind) <> 0 then Gear^.dX := Gear^.dX + cWindSpeed * _16 / max(12,sqr(Gear^.Radius))
+ if (GameFlags and gfMoreWind) <> 0 then Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density
end;
Gear^.X := Gear^.X + Gear^.dX;
@@ -519,16 +527,169 @@
if (GameFlags and gfMoreWind) = 0 then Gear^.dX := Gear^.dX + cWindSpeed;
doStepFallingGear(Gear);
if (Gear^.State and gstCollision) <> 0 then
- begin
+ begin
doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
DeleteGear(Gear);
exit
- end;
+ end;
if (GameTicks and $3F) = 0 then
AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
end;
////////////////////////////////////////////////////////////////////////////////
+procedure doStepSnowball(Gear: PGear);
+var kick, i: LongInt;
+ particle: PVisualGear;
+begin
+ AllInactive := false;
+ if (GameFlags and gfMoreWind) = 0 then Gear^.dX := Gear^.dX + cWindSpeed;
+ doStepFallingGear(Gear);
+ CalcRotationDirAngle(Gear);
+ if (Gear^.State and gstCollision) <> 0 then
+ begin
+ kick:= hwRound((hwAbs(Gear^.dX)+hwAbs(Gear^.dY)) * _20);
+ Gear^.dY.isNegative:= not Gear^.dY.isNegative;
+ Gear^.dX.isNegative:= not Gear^.dX.isNegative;
+ AmmoShove(Gear, 1, kick);
+ for i:= 15 + kick div 10 downto 0 do
+ begin
+ particle := AddVisualGear(hwRound(Gear^.X) + Random(25), hwRound(Gear^.Y) + Random(25), vgtDust);
+ if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
+ end;
+ DeleteGear(Gear);
+ exit
+ end;
+ if ((GameTicks and $1F) = 0) and (Random(3) = 0) then
+ begin
+ particle:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtDust);
+ if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
+ end
+end;
+
+procedure doStepSnowflake(Gear: PGear);
+var xx, yy, px, py, i: LongInt;
+ move, allpx: Boolean;
+ s: PSDL_Surface;
+ p: PLongwordArray;
+ oAlpha, nAlpha: byte;
+begin
+if GameTicks and $7 = 0 then
+ begin
+ with Gear^ do
+ begin
+ X:= X + cWindSpeed * 1600 + dX;
+ Y:= Y + dY + cGravity * vobFallSpeed * 8; // using same value as flakes to try and get similar results
+ xx:= hwRound(X);
+ yy:= hwRound(Y);
+ if vobVelocity <> 0 then
+ begin
+ DirAngle := DirAngle + (Angle / 1250000000);
+ if DirAngle < 0 then DirAngle := DirAngle + 360
+ else if 360 < DirAngle then DirAngle := DirAngle - 360;
+ end;
+
+ inc(Health, 8);
+ if Health > vobFrameTicks then
+ begin
+ dec(Health, vobFrameTicks);
+ inc(Timer);
+ if Timer = vobFramesCount then Timer:= 0
+ end;
+
+ move:= false;
+ // move back to cloud layer
+ if yy > cWaterLine then move:= true
+ else if ((yy and LAND_HEIGHT_MASK) <> 0) or ((xx and LAND_WIDTH_MASK) <> 0) then move:=true
+ // Solid pixel encountered
+ else if (Land[yy, xx] <> 0) then
+ begin
+ // If there's room below keep falling
+ if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (Land[yy-1, xx] = 0) then
+ begin
+ X:= X - cWindSpeed * 1600 - dX;
+ end
+ // If there's room below, on the sides, fill the gaps
+ else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx-(1*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx-(1*hwSign(cWindSpeed)))] = 0) then
+ begin
+ X:= X - _0_8 * hwSign(cWindSpeed);
+ Y:= Y - dY - cGravity * vobFallSpeed * 8;
+ end
+ else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx-(2*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx-(2*hwSign(cWindSpeed)))] = 0) then
+ begin
+ X:= X - _0_8 * 2 * hwSign(cWindSpeed);
+ Y:= Y - dY - cGravity * vobFallSpeed * 8;
+ end
+ else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx+(1*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx+(1*hwSign(cWindSpeed)))] = 0) then
+ begin
+ X:= X + _0_8 * hwSign(cWindSpeed);
+ Y:= Y - dY - cGravity * vobFallSpeed * 8;
+ end
+ else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx+(2*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx+(2*hwSign(cWindSpeed)))] = 0) then
+ begin
+ X:= X + _0_8 * 2 * hwSign(cWindSpeed);
+ Y:= Y - dY - cGravity * vobFallSpeed * 8;
+ end
+ // if there's an hog/object below do nothing
+ else if ((((yy+1) and LAND_HEIGHT_MASK) = 0) and ((Land[yy+1, xx] and $FF) <> 0))
+ then move:=true
+ else
+ begin
+ // we've collided with land. draw some stuff and get back into the clouds
+ move:= true;
+ if (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtRope) then
+ begin
+ ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
+ dec(yy,3);
+ dec(xx,1);
+ s:= SpritesData[sprSnow].Surface;
+ p:= s^.pixels;
+ allpx:= true;
+ for py:= 0 to Pred(s^.h) do
+ begin
+ for px:= 0 to Pred(s^.w) do
+ if ((((yy + py) and LAND_HEIGHT_MASK) = 0) and (((xx + px) and LAND_WIDTH_MASK) = 0)) and ((Land[yy + py, xx + px] and $FF) = 0) then
+ begin
+ Land[yy + py, xx + px]:= Land[yy + py, xx + px] or lfObject;
+ if (cReducedQuality and rqBlurryLand) = 0 then
+ begin
+ LandPixels[yy + py, xx + px]:= addBgColor(LandPixels[yy + py, xx + px], p^[px]);
+ end
+ else
+ begin
+ LandPixels[(yy + py) div 2, (xx + px) div 2]:= addBgColor(LandPixels[(yy + py) div 2, (xx + px) div 2], p^[px]);
+ end;
+ end
+ else allpx:= false;
+ p:= @(p^[s^.pitch shr 2])
+ end;
+
+
+ Land[py, px+1]:= lfBasic;
+
+ if allpx then UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w))
+ else
+ begin
+ UpdateLandTexture(
+ max(0, min(LAND_WIDTH, xx)),
+ min(LAND_WIDTH - xx, Pred(s^.w)),
+ max(0, min(LAND_WIDTH, yy)),
+ min(LAND_HEIGHT - yy, Pred(s^.h))
+ );
+ end;
+ ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
+ end
+ end;
+ end;
+ if move then
+ begin
+ X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512);
+ Y:= int2hwFloat(750+(GetRandom(50)-25))
+ end
+ end
+ end
+end;
+
+////////////////////////////////////////////////////////////////////////////////
procedure doStepGrave(Gear: PGear);
begin
AllInactive := false;
@@ -626,8 +787,8 @@
dec(Gear^.Timer);
if Gear^.Timer = 0 then
begin
- PHedgehog(Gear^.Hedgehog)^.Gear^.Message:= PHedgehog(Gear^.Hedgehog)^.Gear^.Message and not gmAttack;
- PHedgehog(Gear^.Hedgehog)^.Gear^.State:= PHedgehog(Gear^.Hedgehog)^.Gear^.State and not gstAttacking;
+ Gear^.Hedgehog^.Gear^.Message:= Gear^.Hedgehog^.Gear^.Message and not gmAttack;
+ Gear^.Hedgehog^.Gear^.State:= Gear^.Hedgehog^.Gear^.State and not gstAttacking;
AttackBar:= 0;
Gear^.SoundChannel := LoopSound(sndBee);
@@ -736,7 +897,7 @@
dec(Gear^.Health, Gear^.Damage);
Gear^.Damage := 0
end;
- if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and (cWaterOpacity < $FF) then
+ if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) then
begin
for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do
begin
@@ -797,6 +958,9 @@
procedure doStepDEagleShot(Gear: PGear);
begin
PlaySound(sndGun);
+ // add an initial step to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths
+ Gear^.X := Gear^.X + Gear^.dX;
+ Gear^.Y := Gear^.Y + Gear^.dY;
Gear^.doStep := @doStepBulletWork
end;
@@ -806,7 +970,7 @@
shell: PVisualGear;
begin
cArtillery := true;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.State := HHGear^.State or gstNotKickable;
HedgehogChAngle(HHGear);
if not cLaserSighting then
@@ -830,6 +994,9 @@
Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _0_5;
Gear^.dY := -AngleCos(HHGear^.Angle) * _0_5;
PlaySound(sndGun);
+ // add an initial step to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths
+ Gear^.X := Gear^.X + Gear^.dX;
+ Gear^.Y := Gear^.Y + Gear^.dY;
Gear^.doStep := @doStepBulletWork;
end
else
@@ -895,61 +1062,66 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepPickHammerWork(Gear: PGear);
var
- i, ei: LongInt;
+ i, ei, x, y: LongInt;
HHGear: PGear;
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
dec(Gear^.Timer);
if (Gear^.Timer = 0)or((Gear^.Message and gmDestroy) <> 0)or((HHGear^.State and gstHHDriven) =
0) then
- begin
+ begin
StopSound(Gear^.SoundChannel);
DeleteGear(Gear);
AfterAttack;
doStepHedgehogMoving(HHGear); // for gfInfAttack
exit
- end;
-
+ end;
+
+ x:= hwRound(Gear^.X);
+ y:= hwRound(Gear^.Y);
if (Gear^.Timer mod 33) = 0 then
- begin
+ begin
HHGear^.State := HHGear^.State or gstNoDamage;
- doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y) + 7, 6, EXPLDontDraw);
+ doMakeExplosion(x, y + 7, 6, EXPLDontDraw);
HHGear^.State := HHGear^.State and not gstNoDamage
- end;
+ end;
if (Gear^.Timer mod 47) = 0 then
- begin
- for i:= 0 to 1 do
- AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
- i := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
- ei := hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
+ begin
+ // ok. this was an attempt to turn off dust if not actually drilling land. I have no idea why it isn't working as expected
+ if (( (y + 12) and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y + 12, x] > 255) then
+ for i:= 0 to 1 do
+ AddVisualGear(x - 5 + Random(10), y + 12, vgtDust);
+
+ i := x - Gear^.Radius - LongInt(GetRandom(2));
+ ei := x + Gear^.Radius + LongInt(GetRandom(2));
while i <= ei do
- begin
- DrawExplosion(i, hwRound(Gear^.Y) + 3, 3);
+ begin
+ DrawExplosion(i, y + 3, 3);
inc(i, 1)
- end;
+ end;
if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9)
, lfIndestructible) then
- begin
+ begin
Gear^.X := Gear^.X + Gear^.dX;
Gear^.Y := Gear^.Y + _1_9;
- end;
+ end;
SetAllHHToActive;
- end;
+ end;
if TestCollisionYwithGear(Gear, 1) then
- begin
+ begin
Gear^.dY := _0;
SetLittle(HHGear^.dX);
HHGear^.dY := _0;
- end
+ end
else
- begin
+ begin
Gear^.dY := Gear^.dY + cGravity;
Gear^.Y := Gear^.Y + Gear^.dY;
if hwRound(Gear^.Y) > cWaterLine then Gear^.Timer := 1
- end;
+ end;
Gear^.X := Gear^.X + HHGear^.dX;
HHGear^.X := Gear^.X;
@@ -973,7 +1145,7 @@
HHGear: PGear;
begin
i := 0;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
y := hwRound(Gear^.Y) - cHHRadius * 2;
while y < hwRound(Gear^.Y) do
@@ -1005,7 +1177,7 @@
begin
AllInactive := false;
dec(Gear^.Timer);
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HedgehogChAngle(HHGear);
@@ -1087,7 +1259,7 @@
begin
BTPrevAngle := High(LongInt);
BTSteps := 0;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.Message := 0;
HHGear^.State := HHGear^.State or gstNotKickable;
Gear^.doStep := @doStepBlowTorchWork
@@ -1102,14 +1274,14 @@
var
HHGear: PGear;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
if ((HHGear^.State and gstHHDriven) = 0)
or (CheckGearDrowning(HHGear))
or TestCollisionYwithGear(HHGear, 1) then
begin
DeleteGear(Gear);
isCursorVisible := false;
- ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+ ApplyAmmoChanges(HHGear^.Hedgehog^);
exit
end;
@@ -1121,18 +1293,18 @@
HHGear^.X := HHGear^.X + HHGear^.dX;
HHGear^.Y := HHGear^.Y + HHGear^.dY;
HHGear^.dY := HHGear^.dY + cGravity;
- if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed * _0_2;
+ if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density;
if (Gear^.Message and gmAttack) <> 0 then
begin
Gear^.X := HHGear^.X;
Gear^.Y := HHGear^.Y;
- ApplyAngleBounds(PHedgehog(Gear^.Hedgehog)^, amRope);
+ ApplyAngleBounds(Gear^.Hedgehog^, amRope);
Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX);
Gear^.dY := -AngleCos(HHGear^.Angle);
- Gear^.Friction := _450;
+ Gear^.Friction := _450 * _0_01 * cRopePercent;
Gear^.Elasticity := _0;
Gear^.State := Gear^.State and not gsttmpflag;
Gear^.doStep := @doStepRope;
@@ -1170,7 +1342,7 @@
end;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
if ((HHGear^.State and gstHHDriven) = 0)
or (CheckGearDrowning(HHGear)) then
@@ -1187,22 +1359,22 @@
if not TestCollisionYwithGear(HHGear, 1) then
begin
HHGear^.dY := HHGear^.dY + cGravity;
- if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed * _0_2
+ if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density;
end;
+ // vector between hedgehog and rope attaching point
ropeDx := HHGear^.X - Gear^.X;
- // vector between hedgehog and rope attaching point
ropeDy := HHGear^.Y - Gear^.Y;
mdX := ropeDx + HHGear^.dX;
mdY := ropeDy + HHGear^.dY;
len := _1 / Distance(mdX, mdY);
+ // rope vector plus hedgehog direction vector normalized
mdX := mdX * len;
- // rope vector plus hedgehog direction vector normalized
mdY := mdY * len;
+ // for visual purposes only
Gear^.dX := mdX;
- // for visual purposes only
Gear^.dY := mdY;
/////
@@ -1240,7 +1412,7 @@
begin
lx := hwRound(nx);
ly := hwRound(ny);
- if ((ly and LAND_HEIGHT_MASK) = 0) and ((lx and LAND_WIDTH_MASK) = 0) and (Land[ly, lx] <> 0) then
+ if ((ly and LAND_HEIGHT_MASK) = 0) and ((lx and LAND_WIDTH_MASK) = 0) and ((Land[ly, lx] and $FF00) <> 0) then
begin
ny := _1 / Distance(ropeDx, ropeDy);
// old rope pos
@@ -1330,10 +1502,47 @@
HHGear^.dY := HHGear^.dY * len;
end;
-
+ haveCollision:= ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) <> 0);
+
+ if not haveCollision then
+ begin
+ // backup gear location
+ tx:= Gear^.X;
+ ty:= Gear^.Y;
+
+ if RopePoints.Count > 0 then
+ begin
+ // set gear location to the remote end of the rope, the attachment point
+ Gear^.X:= RopePoints.ar[0].X;
+ Gear^.Y:= RopePoints.ar[0].Y;
+ end;
+
+ CheckCollisionWithLand(Gear);
+ // if we haven't found any collision yet then check the otheer side too
+ if (Gear^.State and gstCollision) = 0 then
+ begin
+ Gear^.dX.isNegative:= not Gear^.dX.isNegative;
+ Gear^.dY.isNegative:= not Gear^.dY.isNegative;
+ CheckCollisionWithLand(Gear);
+ Gear^.dX.isNegative:= not Gear^.dX.isNegative;
+ Gear^.dY.isNegative:= not Gear^.dY.isNegative;
+ end;
+
+ haveCollision:= (Gear^.State and gstCollision) <> 0;
+
+ // restore gear location
+ Gear^.X:= tx;
+ Gear^.Y:= ty;
+ end;
+
+ // if the attack key is pressed, lose rope contact as well
if (Gear^.Message and gmAttack) <> 0 then
+ haveCollision:= false;
+
+ if not haveCollision then
+ begin
if (Gear^.State and gsttmpFlag) <> 0 then
- with PHedgehog(Gear^.Hedgehog)^ do
+ with Gear^.Hedgehog^ do
begin
PlaySound(sndRopeRelease);
if CurAmmoType <> amParachute then
@@ -1341,10 +1550,11 @@
else
DeleteMe
end
- else
+ end
else
if (Gear^.State and gsttmpFlag) = 0 then
Gear^.State := Gear^.State or gsttmpFlag;
+
end;
procedure doStepRopeAttach(Gear: PGear);
@@ -1356,10 +1566,10 @@
begin
if (Gear^.State and gstAttacked) = 0 then
begin
- OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^);
+ OnUsedAmmo(HHGear^.Hedgehog^);
Gear^.State := Gear^.State or gstAttacked
end;
- ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^)
+ ApplyAmmoChanges(HHGear^.Hedgehog^)
end;
begin
@@ -1367,7 +1577,7 @@
Gear^.Y := Gear^.Y - Gear^.dY;
Gear^.Elasticity := Gear^.Elasticity + _1;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
DeleteCI(HHGear);
if (HHGear^.State and gstMoving) <> 0 then
@@ -1389,7 +1599,7 @@
HHGear^.Y := HHGear^.Y + HHGear^.dY;
Gear^.Y := Gear^.Y + HHGear^.dY;
HHGear^.dY := HHGear^.dY + cGravity;
- if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed * _0_2
+ if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density
end;
tt := Gear^.Elasticity;
@@ -1397,8 +1607,7 @@
ty := _0;
while tt > _20 do
begin
- if TestCollisionXwithXYShift(Gear, tx, hwRound(ty), -hwSign(Gear^.dX))
- or TestCollisionYwithXYShift(Gear, hwRound(tx), hwRound(ty), -hwSign(Gear^.dY)) then
+ if ((hwRound(Gear^.Y+ty) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X+tx) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y+ty), hwRound(Gear^.X+tx)] and $FF00) <> 0) then
begin
Gear^.X := Gear^.X + tx;
Gear^.Y := Gear^.Y + ty;
@@ -1422,7 +1631,7 @@
end;
end;
- CheckCollision(Gear);
+ CheckCollisionWithLand(Gear);
if (Gear^.State and gstCollision) <> 0 then
if Gear^.Elasticity < _10 then
@@ -1447,7 +1656,7 @@
or ((HHGear^.State and gstHHDriven) = 0)
or (HHGear^.Damage > 0) then
begin
- with PHedgehog(Gear^.Hedgehog)^.Gear^ do
+ with Gear^.Hedgehog^.Gear^ do
begin
State := State and not gstAttacking;
Message := Message and not gmAttack
@@ -1763,28 +1972,12 @@
if (Gear^.Tag = 0) and (Gear^.Timer < 1000) then
inc(Gear^.Timer)
else if Gear^.Tag = 1 then
- begin
- Gear^.Tag := 2;
- if (TrainingFlags and tfTimeTrial) <> 0 then
- begin
- inc(TurnTimeLeft, TrainingTimeInc);
-
- if TrainingTimeInc > TrainingTimeInM then
- dec(TrainingTimeInc, TrainingTimeInD);
- if TurnTimeLeft > TrainingTimeMax then
- TurnTimeLeft := TrainingTimeMax;
- end;
- end
+ Gear^.Tag := 2
else if Gear^.Tag = 2 then
if Gear^.Timer > 0 then
dec(Gear^.Timer)
else
begin
- if (TrainingFlags and tfTargetRespawn) <> 0 then
- begin
- TrainingTargetGear := AddGear(0, 0, gtTarget, 0, _0, _0, 0);
- FindPlace(TrainingTargetGear, false, 0, LAND_WIDTH);
- end;
DeleteGear(Gear);
exit;
end;
@@ -1808,7 +2001,7 @@
var
HHGear: PGear;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.State := HHGear^.State or gstNoDamage;
DeleteCI(HHGear);
@@ -1825,15 +2018,15 @@
HHGear: PGear;
i: LongInt;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.State := HHGear^.State or gstNoDamage;
DeleteCI(HHGear);
for i:= 0 to 3 do
- begin
+ begin
AmmoShove(Gear, 30, 25);
Gear^.X := Gear^.X + Gear^.dX * 5
- end;
+ end;
HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving;
@@ -1857,13 +2050,12 @@
if ((GameTicks mod 100) = 0) then
begin
- vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire);
+ vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire, gstTmpFlag);
if vgt <> nil then
begin
vgt^.dx:= 0;
vgt^.dy:= 0;
vgt^.FrameTicks:= 1800 div (Gear^.Tag mod 3 + 2);
- vgt^.State:= gstTmpFlag;
end;
end;
@@ -1978,7 +2170,7 @@
exit
end;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
if hwRound(HHGear^.Y) <= Gear^.Tag - 2 then
begin
Gear^.Tag := hwRound(HHGear^.Y);
@@ -2008,7 +2200,7 @@
HHGear: PGear;
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
DeleteCI(HHGear);
HHGear^.X := int2hwFloat(hwRound(HHGear^.X)) - _0_5;
HHGear^.dX := SignAs(cLittle, Gear^.dX);
@@ -2021,7 +2213,7 @@
Gear^.doStep := @doStepFirePunchWork;
DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y + _1, _0_5, _0, cHHRadius * 4, 5);
- PlaySound(TSound(ord(sndFirePunch1) + GetRandom(6)), PHedgehog(HHGear^.Hedgehog)^.Team^.
+ PlaySound(TSound(ord(sndFirePunch1) + GetRandom(6)), HHGear^.Hedgehog^.Team^.
voicepack)
end;
@@ -2031,7 +2223,7 @@
var
HHGear: PGear;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
inc(Gear^.Timer);
@@ -2049,18 +2241,20 @@
end;
DeleteGear(Gear);
isCursorVisible := false;
- ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+ ApplyAmmoChanges(HHGear^.Hedgehog^);
exit
end;
- if not TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
- HHGear^.X := HHGear^.X + cWindSpeed * 200;
+ HHGear^.X := HHGear^.X + cWindSpeed * 200;
if (Gear^.Message and gmLeft) <> 0 then HHGear^.X := HHGear^.X - cMaxWindSpeed * 80
else if (Gear^.Message and gmRight) <> 0 then HHGear^.X := HHGear^.X + cMaxWindSpeed * 80;
if (Gear^.Message and gmUp) <> 0 then HHGear^.Y := HHGear^.Y - cGravity * 40
else if (Gear^.Message and gmDown) <> 0 then HHGear^.Y := HHGear^.Y + cGravity * 40;
+ // don't drift into obstacles
+ if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+ HHGear^.X := HHGear^.X - int2hwFloat(hwSign(HHGear^.dX));
HHGear^.Y := HHGear^.Y + cGravity * 100;
Gear^.X := HHGear^.X;
Gear^.Y := HHGear^.Y
@@ -2070,7 +2264,7 @@
var
HHGear: PGear;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
DeleteCI(HHGear);
@@ -2133,9 +2327,13 @@
Gear^.Y := int2hwFloat(topY-300);
Gear^.dX := int2hwFloat(TargetPoint.X - 5 * Gear^.Tag * 15);
- if (int2hwFloat(TargetPoint.Y) - Gear^.Y > _0) then
- Gear^.dX := Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(TargetPoint.Y) - Gear^.Y) * 2 /
- cGravity) * Gear^.Tag;
+ // calcs for Napalm Strike, so that it will hit the target (without wind at least :P)
+ if (Gear^.State = 2) then
+ Gear^.dX := Gear^.dX - cBombsSpeed * Gear^.Tag * 1000 // ^.Timer of gtNapalmBomb, make it a constant var if you prefer that :P
+ // calcs for regular falling gears
+ else if (int2hwFloat(TargetPoint.Y) - Gear^.Y > _0) then
+ Gear^.dX := Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(TargetPoint.Y) - Gear^.Y) * 2 /
+ cGravity) * Gear^.Tag;
Gear^.Health := 6;
Gear^.doStep := @doStepAirAttackWork;
@@ -2167,7 +2365,7 @@
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
tx := int2hwFloat(TargetPoint.X);
ty := int2hwFloat(TargetPoint.Y);
x := HHGear^.X;
@@ -2202,8 +2400,8 @@
var
HHGear: PGear;
begin
- PHedgehog(Gear^.Hedgehog)^.Unplaced := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ Gear^.Hedgehog^.Unplaced := false;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.Y := HHGear^.Y + HHGear^.dY;
// hedgehog falling to collect cases
HHGear^.dY := HHGear^.dY + cGravity;
@@ -2233,7 +2431,7 @@
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
if not TryPlaceOnLand(TargetPoint.X - SpritesData[sprHHTelepMask].Width div 2,
TargetPoint.Y - SpritesData[sprHHTelepMask].Height div 2,
sprHHTelepMask, 0, false) then
@@ -2275,14 +2473,14 @@
if ((Gear^.Message and not gmSwitch) <> 0) or (TurnTimeLeft = 0) then
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
Msg := Gear^.Message and not gmSwitch;
DeleteGear(Gear);
- OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^);
- ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+ OnUsedAmmo(HHGear^.Hedgehog^);
+ ApplyAmmoChanges(HHGear^.Hedgehog^);
HHGear := CurrentHedgehog^.Gear;
- ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+ ApplyAmmoChanges(HHGear^.Hedgehog^);
HHGear^.Message := Msg;
exit
end;
@@ -2326,7 +2524,7 @@
begin
Gear^.doStep := @doStepSwitcherWork;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
with HHGear^ do
begin
State := State and not gstAttacking;
@@ -2377,7 +2575,7 @@
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.State := HHGear^.State or gstNoDamage;
DeleteCI(HHGear);
@@ -2437,7 +2635,7 @@
if Gear^.Timer = 0 then
begin
Gear^.Pos := 1;
- PlaySound(sndKamikaze, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+ PlaySound(sndKamikaze, Gear^.Hedgehog^.Team^.voicepack);
Gear^.doStep := @doStepKamikazeWork
end
end;
@@ -2448,7 +2646,7 @@
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.dX := Gear^.dX;
HHGear^.dY := Gear^.dY;
@@ -2637,7 +2835,7 @@
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.Message := HHGear^.Message and (not gmAttack);
DeleteCI(HHGear);
Gear^.IntersectGear:= nil;
@@ -2661,7 +2859,7 @@
if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) then
if (Land[y, x] <> 0) then
- begin
+ begin
Gear^.dX.isNegative := not Gear^.dX.isNegative;
Gear^.dY.isNegative := not Gear^.dY.isNegative;
Gear^.dX := Gear^.dX * _1_5;
@@ -2669,13 +2867,13 @@
AmmoShove(Gear, 0, 40);
AfterAttack;
DeleteGear(Gear)
- end
+ end
+ else
else
- else
- begin
+ begin
AfterAttack;
DeleteGear(Gear)
- end
+ end
end;
procedure doStepSeductionWear(Gear: PGear);
@@ -2687,7 +2885,7 @@
Gear^.Timer := 0;
inc(Gear^.Pos);
if Gear^.Pos = 5 then
- PlaySound(sndYoohoo, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack)
+ PlaySound(sndYoohoo, Gear^.Hedgehog^.Team^.voicepack)
end;
if Gear^.Pos = 14 then
@@ -2697,7 +2895,7 @@
procedure doStepSeduction(Gear: PGear);
begin
AllInactive := false;
- DeleteCI(PHedgehog(Gear^.Hedgehog)^.Gear);
+ DeleteCI(Gear^.Hedgehog^.Gear);
Gear^.doStep := @doStepSeductionWear
end;
@@ -2732,6 +2930,9 @@
end;
////////////////////////////////////////////////////////////////////////////////
+procedure doStepDrill(Gear: PGear);
+forward;
+
procedure doStepDrillDrilling(Gear: PGear);
var
t: PGearArray;
@@ -2760,10 +2961,11 @@
if (Gear^.Timer = 0)
or (t^.Count <> 0)
or (not TestCollisionYWithGear(Gear, hwSign(Gear^.dY))
- and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)))
+ and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))
+ and ((Gear^.State and gsttmpFlag) = 0))
// CheckLandValue returns true if the type isn't matched
or not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible) then
- begin
+ begin
//out of time or exited ground
StopSound(Gear^.SoundChannel);
if (Gear^.State and gsttmpFlag) <> 0 then
@@ -2772,7 +2974,12 @@
doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
DeleteGear(Gear);
exit
- end;
+ end
+ else if not TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) then
+ begin
+ StopSound(Gear^.SoundChannel);
+ Gear^.doStep := @doStepDrill
+ end;
dec(Gear^.Timer);
end;
@@ -2836,7 +3043,7 @@
begin
AllInactive := false;
dec(Gear^.Timer);
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HedgehogChAngle(HHGear);
gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle);
gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle);
@@ -2864,7 +3071,7 @@
var
HHGear: PGear;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.Message := HHGear^.Message and not (gmUp or gmDown);
HHGear^.State := HHGear^.State or gstNotKickable;
Gear^.doStep := @doStepBallgunWork
@@ -2884,12 +3091,7 @@
begin
AllInactive := false;
- if ((TrainingFlags and tfRCPlane) = 0) and (Gear^.Timer > 0) then dec(Gear^.Timer);
-
- if ((TrainingFlags and tfRCPlane) <> 0) and ((TrainingFlags and tfTimeTrial) <> 0 ) and (
- TimeTrialStartTime = 0) then TimeTrialStartTime := RealTicks;
-
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
FollowGear := Gear;
fChanged := false;
@@ -2931,71 +3133,42 @@
Gear^.X := Gear^.X + Gear^.dX;
Gear^.Y := Gear^.Y + Gear^.dY;
- if (TrainingFlags and tfRCPlane) = 0 then
+ if (GameTicks and $FF) = 0 then
+ if Gear^.Timer < 3500 then
+ AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace)
+ else
+ AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
+
+ if ((HHGear^.Message and gmAttack) <> 0) and (Gear^.Health <> 0) then
begin
- if (GameTicks and $FF) = 0 then
- if Gear^.Timer < 3500 then
- AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace)
- else
- AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
-
- if ((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 *
- _0_5, 0);
- dec(Gear^.Health)
- end;
-
- if ((HHGear^.Message and gmLJump) <> 0)
- and ((Gear^.State and gsttmpFlag) = 0) then
- begin
- Gear^.State := Gear^.State or gsttmpFlag;
- PauseMusic;
- playSound(sndRideOfTheValkyries);
- end;
-
- // pickup bonuses
- t := CheckGearNear(Gear, gtCase, 36, 36);
- if t <> nil then
- PickUp(HHGear, t);
- end
- else
+ HHGear^.Message := HHGear^.Message and not gmAttack;
+ AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY *
+ _0_5, 0);
+ dec(Gear^.Health)
+ end;
+
+ if ((HHGear^.Message and gmLJump) <> 0)
+ and ((Gear^.State and gsttmpFlag) = 0) then
begin
- if (GameTicks and $FF) = 0 then
- AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
-
- // pickup targets
- t := CheckGearNear(Gear, gtTarget, 36, 36);
- if t <> nil then
- begin
- if t^.Tag <> 0 then // collect it only once
- exit;
- PlaySound(sndShotgunReload);
- t^.Tag := 1;
- TrainingTargetGear := nil;
- // remove target cursor
- exit;
- end;
-
- if (TurnTimeLeft > 0) then
- dec(TurnTimeLeft)
+ Gear^.State := Gear^.State or gsttmpFlag;
+ PauseMusic;
+ playSound(sndRideOfTheValkyries);
end;
+ // pickup bonuses
+ t := CheckGearNear(Gear, gtCase, 36, 36);
+ if t <> nil then
+ PickUp(HHGear, t);
+
CheckCollision(Gear);
- if ((Gear^.State and gstCollision) <> 0) or (((TrainingFlags and tfRCPlane) <> 0) and (
- TurnTimeLeft = 0))
- or CheckGearDrowning(Gear) then
+ if ((Gear^.State and gstCollision) <> 0) or CheckGearDrowning(Gear) then
begin
- if ((TrainingFlags and tfRCPlane) <> 0) and ((TrainingFlags and tfTimeTrial) <> 0 ) and (
- TimeTrialStopTime = 0) then TimeTrialStopTime := RealTicks;
StopSound(Gear^.SoundChannel);
StopSound(sndRideOfTheValkyries);
ResumeMusic;
- if ((Gear^.State and gstCollision) <> 0) or (((TrainingFlags and tfRCPlane) <> 0) and (
- TurnTimeLeft = 0)) then
+ if ((Gear^.State and gstCollision) <> 0) then
begin
doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, EXPLAutoSound);
for i:= 0 to 32 do
@@ -3012,10 +3185,6 @@
CurAmmoGear := nil;
if (GameFlags and gfInfAttack) = 0 then TurnTimeLeft := 14 * 125;
- if (TrainingFlags and tfRCPlane) <> 0 then
- TurnTimeLeft := 0;
- // HACK: RCPlane training allows unlimited plane starts in last 2 seconds
-
HHGear^.Message := 0;
ParseCommand('/taunt '#1, true)
end
@@ -3025,7 +3194,7 @@
var
HHGear: PGear;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.Message := 0;
HHGear^.State := HHGear^.State or gstNotKickable;
Gear^.Angle := HHGear^.Angle;
@@ -3045,7 +3214,7 @@
isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
if Gear^.Pos > 0 then dec(Gear^.Pos);
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
//dec(Gear^.Timer);
move := _0_2;
fuel := 50;
@@ -3152,7 +3321,7 @@
end;
DeleteGear(Gear);
isCursorVisible := false;
- ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+ ApplyAmmoChanges(HHGear^.Hedgehog^);
// if Gear^.Tex <> nil then FreeTexture(Gear^.Tex);
// Gear^.Tex:= RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(round(Gear^.Health / 20)) + '%', cWhiteColor, fntSmall)
@@ -3169,7 +3338,7 @@
Gear^.Pos:= 0;
Gear^.doStep := @doStepJetpackWork;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
FollowGear := HHGear;
AfterAttack;
with HHGear^ do
@@ -3376,7 +3545,7 @@
if (Gear^.State and gstCollision) <> 0 then
begin
- doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 11, EXPLPoisoned, $C0E0FFE0);
+ doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 10, EXPLPoisoned, $C0E0FFE0);
PlaySound(sndEggBreak);
AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
vg := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
@@ -3396,8 +3565,7 @@
////////////////////////////////////////////////////////////////////////////////
procedure doPortalColorSwitch();
-var flags: LongWord;
- CurWeapon: PAmmo;
+var CurWeapon: PAmmo;
begin
if (CurrentHedgehog <> nil)
and (CurrentHedgehog^.Gear <> nil)
@@ -3408,11 +3576,10 @@
CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and not gmSwitch;
CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
- flags := CurWeapon^.Timer and not 2;
- if (flags and 1) = 0 then
- CurWeapon^.Timer := flags or 1
+ if CurWeapon^.Pos <> 0 then
+ CurWeapon^.Pos := 0
else
- CurWeapon^.Timer := flags and not 1;
+ CurWeapon^.Pos := 1;
end;
end;
@@ -3427,7 +3594,7 @@
// destroy portal if ground it was attached too is gone
if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0)
or (Gear^.Timer < 1)
- or (PHedgehog(Gear^.Hedgehog) <> CurrentHedgehog)
+ or (Gear^.Hedgehog <> CurrentHedgehog)
or (hwRound(Gear^.Y) > cWaterLine) then
begin
deleteGear(Gear);
@@ -3636,7 +3803,7 @@
iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y))
end;
- if not isbullet then
+ if not isbullet and (iterator^.Kind <> gtFlake) then
FollowGear := iterator;
//AddFileLog('portal''d');
@@ -3681,8 +3848,7 @@
s: hwFloat;
procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean);
-var
- flags: LongWord;
+var
CurWeapon: PAmmo;
begin
if CurrentHedgehog <> nil then
@@ -3691,18 +3857,19 @@
CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
if (CurAmmoType = amPortalGun) then
begin
- flags := CurWeapon^.Timer;
-
- if destroyGear xor ((oldPortal^.Tag and 2) = 0) then
- flags := flags or 1
- else
- flags := flags and not 1;
-
- CurWeapon^.Timer := flags and not 2;
+ if not destroyGear then
+ begin
+ // switch color of ball to opposite of oldPortal
+ if (oldPortal^.Tag and 2) = 0 then
+ CurWeapon^.Pos:= 1
+ else
+ CurWeapon^.Pos:= 0;
+ end;
+
// make the ball visible
+ CurWeapon^.Timer := 0;
end
end;
-
if destroyGear then oldPortal^.Timer:= 0;
end;
@@ -3754,7 +3921,7 @@
doPortalColorSwitch();
doStepPerPixel(Gear, @doStepMovingPortal_real, true);
if (Gear^.Timer < 1)
- or (PHedgehog(Gear^.Hedgehog) <> CurrentHedgehog) then
+ or (Gear^.Hedgehog <> CurrentHedgehog) then
deleteGear(Gear);
end;
@@ -3787,11 +3954,8 @@
newPortal^.Elasticity.isNegative := not newPortal^.Elasticity.isNegative;
// make portal gun look unloaded
- CurWeapon^.Timer := CurWeapon^.Timer or 2;
-
- // set portal to the currently chosen color
- if ((CurWeapon^.Timer and 1) <> 0) then
- newPortal^.Tag := newPortal^.Tag or 2;
+ if (CurWeapon <> nil) and (CurAmmoType = amPortalGun) then
+ CurWeapon^.Timer := CurWeapon^.Timer or 2;
iterator := GearsList;
while iterator <> nil do
@@ -4047,7 +4211,7 @@
Fire: PGear;
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HedgehogChAngle(HHGear);
gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle);
gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle);
@@ -4111,7 +4275,7 @@
var
HHGear: PGear;
begin
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
HHGear^.Message := HHGear^.Message and not (gmUp or gmDown or gmLeft or gmRight);
HHGear^.State := HHGear^.State or gstNotKickable;
Gear^.doStep := @doStepFlamethrowerWork
@@ -4140,7 +4304,7 @@
t: PGearArray;
i: LongInt;
begin
-HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
+HHGear:= Gear^.Hedgehog^.Gear;
HHGear^.State:= HHGear^.State or gstNoDamage;
DeleteCI(HHGear);
@@ -4181,7 +4345,7 @@
HHGear: PGear;
begin
AllInactive := false;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
dec(Gear^.Timer);
if (HHGear = nil) or (Gear^.Timer = 0) or ((Gear^.Message and gmDestroy) <> 0) then
begin
@@ -4234,7 +4398,7 @@
HHGear: PGear;
begin
i := 0;
- HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ HHGear := Gear^.Hedgehog^.Gear;
y := hwRound(Gear^.Y) - cHHRadius * 2;
while y < hwRound(Gear^.Y) do
@@ -4265,9 +4429,12 @@
dec(TurnTimeLeft);
AllInactive := false;
- hh := PHedgehog(Gear^.Hedgehog);
- DrawCentered(hwRound(hh^.Gear^.X) + WorldDx, hwRound(hh^.Gear^.Y) + WorldDy -
+ hh := Gear^.Hedgehog;
+
+ // no, you can't do that here
+ {DrawCentered(hwRound(hh^.Gear^.X) + WorldDx, hwRound(hh^.Gear^.Y) + WorldDy -
cHHRadius - 14 - hh^.HealthTagTex^.h, hh^.HealthTagTex);
+ }
(*DrawCircle(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, 1.5, 0, 0, $FF,
$FF);*)
@@ -4321,13 +4488,13 @@
resgear^.Health := graves[i]^.Health;
PHedgehog(graves[i]^.Hedgehog)^.Gear := resgear;
DeleteGear(graves[i]);
- RenderHealth(PHedgehog(resgear^.Hedgehog)^);
- RecountTeamHealth(Phedgehog(resgear^.Hedgehog)^.Team);
- PHedgehog(resgear^.Hedgehog)^.Effects[heResurrected]:= true;
- if PHedgehog(resgear^.Hedgehog)^.Hat = 'NoHat' then
+ RenderHealth(resgear^.Hedgehog^);
+ RecountTeamHealth(resgear^.Hedgehog^.Team);
+ resgear^.Hedgehog^.Effects[heResurrected]:= true;
+ if resgear^.Hedgehog^.Hat = 'NoHat' then
begin
- FreeTexture(PHedgehog(resgear^.Hedgehog)^.HatTex);
- PHedgehog(resgear^.Hedgehog)^.HatTex := Surface2Tex(
+ FreeTexture(resgear^.Hedgehog^.HatTex);
+ resgear^.Hedgehog^.HatTex := Surface2Tex(
LoadImage(Pathz[ptHats] + '/Reserved/Zombie', ifNone),
True)
end
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/GearDrawing.inc
--- a/hedgewars/GearDrawing.inc Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,854 +0,0 @@
-procedure DrawHH(Gear: PGear; ox, oy: LongInt);
-var i, t: LongInt;
- amt: TAmmoType;
- sign, hx, hy, cx, cy, tx, ty, sx, sy, m: LongInt; // hedgehog, crosshair, temp, sprite, direction
- dx, dy, ax, ay, aAngle, dAngle, hAngle, lx, ly: real; // laser, change
- defaultPos, HatVisible: boolean;
- HH: PHedgehog;
- CurWeapon: PAmmo;
-begin
-HH:= PHedgehog(Gear^.Hedgehog);
-if HH^.Unplaced then exit;
-m:= 1;
-if ((Gear^.State and gstHHHJump) <> 0) and not cArtillery then m:= -1;
-sx:= ox + 1; // this offset is very common
-sy:= oy - 3;
-sign:= hwSign(Gear^.dX);
-
-if (Gear^.State and gstHHDeath) <> 0 then
- begin
- DrawSprite(sprHHDeath, ox - 16, oy - 26, Gear^.Pos);
- Tint(HH^.Team^.Clan^.Color);
- DrawSprite(sprHHDeath, ox - 16, oy - 26, Gear^.Pos + 8);
- Tint($FF, $FF, $FF, $FF);
- exit
- end
-else if (Gear^.State and gstHHGone) <> 0 then
- begin
- DrawRotatedF(sprTeleport, sx, sy, Gear^.Pos, sign, 0);
- exit
- end;
-
-defaultPos:= true;
-HatVisible:= false;
-
-
-if HH^.Effects[hePoisoned] then
- begin
- Tint($00, $FF, $40, $40);
- DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 2, 0, 0, sx, sy, 0, 1, 22, 22, (RealTicks shr 36) mod 360);
- Tint($FF, $FF, $FF, $FF)
- end;
-
-if ((Gear^.State and gstWinner) <> 0) and
- ((CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtPickHammer)) then
- begin
- DrawHedgehog(sx, sy,
- sign,
- 2,
- 0,
- 0);
- defaultPos:= false
- end;
-if (Gear^.State and gstDrowning) <> 0 then
- begin
- DrawHedgehog(sx, sy,
- sign,
- 1,
- 7,
- 0);
- defaultPos:= false
- end else
-if (Gear^.State and gstLoser) <> 0 then
- begin
- DrawHedgehog(sx, sy,
- sign,
- 2,
- 3,
- 0);
- defaultPos:= false
- end else
-
-if (Gear^.State and gstHHDriven) <> 0 then
- begin
- if ((Gear^.State and gstHHThinking) = 0) and
- (ShowCrosshair or ((CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtRope))) and
- ((Gear^.State and (gstAttacked or gstAnimation)) = 0) then
- begin
-(* These calculations are a little complex for a few reasons:
- 1: I need to draw the laser from weapon origin to nearest land
- 2: I need to start the beam outside the hedgie for attractiveness.
- 3: I need to extend the beam beyond land.
- This routine perhaps should be pushed into uStore or somesuch instead of continuuing the increase in size of this function.
-*)
- dx:= sign * m * Sin(Gear^.Angle * pi / cMaxAngle);
- dy:= -Cos(Gear^.Angle * pi / cMaxAngle);
- if cLaserSighting then
- begin
- lx:= GetLaunchX(HH^.CurAmmoType, sign * m, Gear^.Angle);
- ly:= GetLaunchY(HH^.CurAmmoType, Gear^.Angle);
-
- // ensure we start outside the hedgehog (he's solid after all)
- while abs(lx * lx + ly * ly) < (Gear^.radius * Gear^.radius) do
- begin
- lx:= lx + dx;
- ly:= ly + dy
- end;
-
- // add hog's position
- lx:= lx + ox - WorldDx;
- ly:= ly + oy - WorldDy;
-
- // decrease number of iterations required
- ax:= dx * 4;
- ay:= dy * 4;
-
- tx:= round(lx);
- ty:= round(ly);
- hx:= tx;
- hy:= ty;
- while ((ty and LAND_HEIGHT_MASK) = 0) and
- ((tx and LAND_WIDTH_MASK) = 0) and
- (Land[ty, tx] = 0) do // TODO: check for constant variable instead
- begin
- lx:= lx + ax;
- ly:= ly + ay;
- tx:= round(lx);
- ty:= round(ly)
- end;
- // reached edge of land. assume infinite beam. Extend it way out past camera
- if ((ty and LAND_HEIGHT_MASK) <> 0) or ((tx and LAND_WIDTH_MASK) <> 0) then
- begin
- tx:= round(lx + ax * (LAND_WIDTH div 4));
- ty:= round(ly + ay * (LAND_WIDTH div 4));
- end;
-
- //if (abs(lx-tx)>8) or (abs(ly-ty)>8) then
- begin
- DrawLine(hx, hy, tx, ty, 1.0, $FF, $00, $00, $C0);
- end;
- end;
- // draw crosshair
- cx:= Round(hwRound(Gear^.X) + dx * 80 + GetLaunchX(HH^.CurAmmoType, sign * m, Gear^.Angle));
- cy:= Round(hwRound(Gear^.Y) + dy * 80 + GetLaunchY(HH^.CurAmmoType, Gear^.Angle));
- DrawRotatedTex(HH^.Team^.CrosshairTex,
- 12, 12, cx + WorldDx, cy + WorldDy, 0,
- sign * (Gear^.Angle * 180.0) / cMaxAngle);
- end;
- hx:= ox + 8 * sign;
- hy:= oy - 2;
- aangle:= Gear^.Angle * 180 / cMaxAngle - 90;
- if CurAmmoGear <> nil then
- begin
- case CurAmmoGear^.Kind of
- gtShotgunShot: begin
- if (CurAmmoGear^.State and gstAnimation <> 0) then
- DrawRotated(sprShotgun, hx, hy, sign, aangle)
- else
- DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
- end;
- gtDEagleShot: DrawRotated(sprDEagle, hx, hy, sign, aangle);
- gtSniperRifleShot: begin
- if (CurAmmoGear^.State and gstAnimation <> 0) then
- DrawRotatedF(sprSniperRifle, hx, hy, 1, sign, aangle)
- else
- DrawRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle)
- end;
- gtBallgun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
- gtRCPlane: begin
- DrawRotated(sprHandPlane, hx, hy, sign, 0);
- defaultPos:= false
- end;
- gtRope: begin
- if Gear^.X < CurAmmoGear^.X then
- begin
- dAngle:= 0;
- hAngle:= 180;
- i:= 1
- end else
- begin
- dAngle:= 180;
- hAngle:= 0;
- i:= -1
- end;
- if ((Gear^.State and gstWinner) = 0) then
- begin
- DrawHedgehog(ox, oy,
- i,
- 1,
- 0,
- DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + dAngle);
- with HH^ do
- if (HatTex <> nil) then
- begin
- DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32,
- i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle);
- if HatTex^.w > 64 then
- begin
- Tint(HH^.Team^.Clan^.Color);
- DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32,
- i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle);
- Tint($FF, $FF, $FF, $FF)
- end
- end
- end;
- DrawAltWeapon(Gear, ox, oy);
- defaultPos:= false
- end;
- gtBlowTorch: begin
- DrawRotated(sprBlowTorch, hx, hy, sign, aangle);
- DrawHedgehog(sx, sy,
- sign,
- 3,
- HH^.visStepPos div 2,
- 0);
- with HH^ do
- if (HatTex <> nil) then
- begin
- DrawTextureF(HatTex,
- 1,
- sx,
- sy - 5,
- 0,
- sign,
- 32,
- 32);
- if HatTex^.w > 64 then
- begin
- Tint(HH^.Team^.Clan^.Color);
- DrawTextureF(HatTex,
- 1,
- sx,
- sy - 5,
- 32,
- sign,
- 32,
- 32);
- Tint($FF, $FF, $FF, $FF)
- end
- end;
- defaultPos:= false
- end;
- gtShover: DrawRotated(sprHandBaseball, hx, hy, sign, aangle + 180);
- gtFirePunch: begin
- DrawHedgehog(sx, sy,
- sign,
- 1,
- 4,
- 0);
- defaultPos:= false
- end;
- gtPickHammer: begin
- defaultPos:= false;
- dec(sy,20);
- end;
- gtTeleport: defaultPos:= false;
- gtWhip: begin
- DrawRotatedF(sprWhip,
- sx,
- sy,
- 1,
- sign,
- 0);
- defaultPos:= false
- end;
- gtHammer: begin
- DrawRotatedF(sprHammer,
- sx,
- sy,
- 1,
- sign,
- 0);
- defaultPos:= false
- end;
- gtResurrector: begin
- DrawRotated(sprHandResurrector, sx, sy, 0, 0);
- defaultPos:= false
- end;
- gtKamikaze: begin
- if CurAmmoGear^.Pos = 0 then
- DrawHedgehog(sx, sy,
- sign,
- 1,
- 6,
- 0)
- else
- DrawRotatedF(sprKamikaze,
- ox, oy,
- CurAmmoGear^.Pos - 1,
- sign,
- aangle);
- defaultPos:= false
- end;
- gtSeduction: begin
- if CurAmmoGear^.Pos >= 6 then
- DrawHedgehog(sx, sy,
- sign,
- 2,
- 2,
- 0)
- else
- begin
- DrawRotatedF(sprDress,
- ox, oy,
- CurAmmoGear^.Pos,
- sign,
- 0);
- DrawSprite(sprCensored, ox - 32, oy - 20, 0)
- end;
- defaultPos:= false
- end;
- gtFlamethrower: begin
- DrawRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
- if CurAmmoGear^.Tex <> nil then DrawCentered(sx, sy - 40, CurAmmoGear^.Tex)
- end;
- end;
-
- case CurAmmoGear^.Kind of
- gtShotgunShot,
- gtDEagleShot,
- gtSniperRifleShot,
- gtShover: begin
- DrawHedgehog(sx, sy,
- sign,
- 0,
- 4,
- 0);
- defaultPos:= false;
- HatVisible:= true
- end
- end
- end else
-
- if ((Gear^.State and gstHHJumping) <> 0) then
- begin
- DrawHedgehog(sx, sy,
- sign*m,
- 1,
- 1,
- 0);
- HatVisible:= true;
- defaultPos:= false
- end else
-
- if (Gear^.Message and (gmLeft or gmRight) <> 0) and (not isCursorVisible) then
- begin
- DrawHedgehog(sx, sy,
- sign,
- 0,
- HH^.visStepPos div 2,
- 0);
- defaultPos:= false;
- HatVisible:= true
- end
- else
-
- if ((Gear^.State and gstAnimation) <> 0) then
- begin
- if (TWave(Gear^.Tag) < Low(TWave)) or (TWave(Gear^.Tag) > High(TWave)) then
- begin
- Gear^.State:= Gear^.State and not gstAnimation;
- end
- else
- begin
- DrawRotatedF(Wavez[TWave(Gear^.Tag)].Sprite,
- sx,
- sy,
- Gear^.Pos,
- sign,
- 0.0);
- defaultPos:= false
- end
- end
- else
- if ((Gear^.State and gstAttacked) = 0) then
- begin
- if HH^.Timer > 0 then
- begin
- // There must be a tidier way to do this. Anyone?
- if aangle <= 90 then aangle:= aangle+360;
- if Gear^.dX > _0 then aangle:= aangle-((aangle-240)*HH^.Timer/10)
- else aangle:= aangle+((240-aangle)*HH^.Timer/10);
- dec(HH^.Timer)
- end;
- amt:= CurrentHedgehog^.CurAmmoType;
- CurWeapon:= GetAmmoEntry(HH^);
- case amt of
- amBazooka: DrawRotated(sprHandBazooka, hx, hy, sign, aangle);
- amMortar: DrawRotated(sprHandMortar, hx, hy, sign, aangle);
- amMolotov: DrawRotated(sprHandMolotov, hx, hy, sign, aangle);
- amBallgun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
- amDrill: DrawRotated(sprHandDrill, hx, hy, sign, aangle);
- amRope: DrawRotated(sprHandRope, hx, hy, sign, aangle);
- amShotgun: DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
- amDEagle: DrawRotated(sprHandDEagle, hx, hy, sign, aangle);
- amSineGun: DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
- amPortalGun: if (CurWeapon^.Timer and 2) <> 0 then // Add a new Hedgehog value instead of abusing timer?
- DrawRotatedF(sprPortalGun, hx, hy, 0, sign, aangle)
- else
- DrawRotatedF(sprPortalGun, hx, hy, 1+(CurWeapon^.Timer and 1), sign, aangle);
- amSniperRifle: DrawRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle);
- amBlowTorch: DrawRotated(sprHandBlowTorch, hx, hy, sign, aangle);
- amCake: DrawRotated(sprHandCake, hx, hy, sign, aangle);
- amGrenade: DrawRotated(sprHandGrenade, hx, hy, sign, aangle);
- amWatermelon: DrawRotated(sprHandMelon, hx, hy, sign, aangle);
- amSkip: DrawRotated(sprHandSkip, hx, hy, sign, aangle);
- amClusterBomb: DrawRotated(sprHandCluster, hx, hy, sign, aangle);
- amDynamite: DrawRotated(sprHandDynamite, hx, hy, sign, aangle);
- amHellishBomb: DrawRotated(sprHandHellish, hx, hy, sign, aangle);
- amGasBomb: DrawRotated(sprHandCheese, hx, hy, sign, aangle);
- amMine: DrawRotated(sprHandMine, hx, hy, sign, aangle);
- amSMine: DrawRotated(sprHandSMine, hx, hy, sign, aangle);
- amSeduction: DrawRotated(sprHandSeduction, hx, hy, sign, aangle);
- amVampiric: DrawRotatedF(sprHandVamp, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
- amRCPlane: begin
- DrawRotated(sprHandPlane, hx, hy, sign, 0);
- defaultPos:= false
- end;
- amGirder: begin
- DrawRotated(sprHandConstruction, hx, hy, sign, aangle);
- DrawSpriteClipped(sprGirder,
- ox-256,
- oy-256,
- LongInt(topY)+WorldDy,
- LongInt(rightX)+WorldDx,
- cWaterLine+WorldDy,
- LongInt(leftX)+WorldDx)
- end;
- amBee: DrawRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
- amFlamethrower: DrawRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
- amResurrector: DrawCircle(ox, oy, 98, 4, $F5, $DB, $35, $AA); // I'd rather not like to hardcode 100 here
- end;
-
- case amt of
- amAirAttack,
- amMineStrike,
- amDrillStrike: DrawRotated(sprHandAirAttack, sx, oy, sign, 0);
- amPickHammer: DrawHedgehog(sx, sy,
- sign,
- 1,
- 2,
- 0);
- amTeleport: DrawRotatedF(sprTeleport, sx, sy, 0, sign, 0);
- amKamikaze: DrawHedgehog(sx, sy,
- sign,
- 1,
- 5,
- 0);
- amWhip: DrawRotatedF(sprWhip,
- sx,
- sy,
- 0,
- sign,
- 0);
- amHammer: DrawRotatedF(sprHammer,
- sx,
- sy,
- 0,
- sign,
- 0);
- else
- DrawHedgehog(sx, sy,
- sign,
- 0,
- 4,
- 0);
-
- HatVisible:= true;
- (* with HH^ do
- if (HatTex <> nil)
- and (HatVisibility > 0) then
- DrawTextureF(HatTex,
- HatVisibility,
- sx,
- sy - 5,
- 0,
- sign,
- 32,
- 32); *)
- end;
-
- case amt of
- amBaseballBat: DrawRotated(sprHandBaseball,
- sx - 4 * sign,
- sy + 9, sign, aangle);
- end;
-
- defaultPos:= false
- end;
-
-end else // not gstHHDriven
- begin
- if (Gear^.Damage > 0)
- and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then
- begin
- DrawHedgehog(sx, sy,
- sign,
- 2,
- 1,
- Gear^.DirAngle);
- defaultPos:= false
- end else
-
- if ((Gear^.State and gstHHJumping) <> 0) then
- begin
- DrawHedgehog(sx, sy,
- sign*m,
- 1,
- 1,
- 0);
- defaultPos:= false
- end;
- end;
-
-with HH^ do
- begin
- if defaultPos then
- begin
- DrawRotatedF(sprHHIdle,
- sx,
- sy,
- (RealTicks div 128 + Gear^.Pos) mod 19,
- sign,
- 0);
- HatVisible:= true;
- end;
-
- if HatVisible then
- if HatVisibility < 1.0 then
- HatVisibility:= HatVisibility + 0.2
- else
- else
- if HatVisibility > 0.0 then
- HatVisibility:= HatVisibility - 0.2;
-
- if (HatTex <> nil)
- and (HatVisibility > 0) then
- if DefaultPos then
- begin
- DrawTextureF(HatTex,
- HatVisibility,
- sx,
- sy - 5,
- (RealTicks div 128 + Gear^.Pos) mod 19,
- sign,
- 32,
- 32);
- if HatTex^.w > 64 then
- begin
- Tint(HH^.Team^.Clan^.Color);
- DrawTextureF(HatTex,
- HatVisibility,
- sx,
- sy - 5,
- (RealTicks div 128 + Gear^.Pos) mod 19 + 32,
- sign,
- 32,
- 32);
- Tint($FF, $FF, $FF, $FF)
- end
- end
- else
- begin
- DrawTextureF(HatTex,
- HatVisibility,
- sx,
- sy - 5,
- 0,
- sign*m,
- 32,
- 32);
- if HatTex^.w > 64 then
- begin
- Tint(HH^.Team^.Clan^.Color);
- DrawTextureF(HatTex,
- HatVisibility,
- sx,
- sy - 5,
- 32,
- sign*m,
- 32,
- 32);
- Tint($FF, $FF, $FF, $FF)
- end
- end
- end;
-if (Gear^.State and gstHHDriven) <> 0 then
- begin
-(* if (CurAmmoGear = nil) then
- begin
- amt:= CurrentHedgehog^.CurAmmoType;
- case amt of
- amJetpack: DrawSprite(sprJetpack, sx-32, sy-32, 0);
- end
- end; *)
- if CurAmmoGear <> nil then
- begin
- case CurAmmoGear^.Kind of
- gtJetpack: begin
- DrawSprite(sprJetpack, sx-32, sy-32, 0);
- if cWaterLine > hwRound(Gear^.Y) + Gear^.Radius then
- begin
- if (CurAmmoGear^.MsgParam and gmUp) <> 0 then DrawSprite(sprJetpack, sx-32, sy-28, 1);
- if (CurAmmoGear^.MsgParam and gmLeft) <> 0 then DrawSprite(sprJetpack, sx-28, sy-28, 2);
- if (CurAmmoGear^.MsgParam and gmRight) <> 0 then DrawSprite(sprJetpack, sx-36, sy-28, 3)
- end;
- if CurAmmoGear^.Tex <> nil then DrawCentered(sx, sy - 40, CurAmmoGear^.Tex);
- DrawAltWeapon(Gear, sx, sy)
- end;
- end;
- end
- end;
-
-with HH^ do
- begin
- if ((Gear^.State and not gstWinner) = 0)
- or ((Gear^.State = gstWait) and (Gear^.dY.QWordValue = 0))
- or (bShowFinger and ((Gear^.State and gstHHDriven) <> 0)) then
- begin
- t:= sy - cHHRadius - 9;
- if (cTagsMask and htTransparent) <> 0 then
- Tint($FF, $FF, $FF, $80);
- if ((cTagsMask and htHealth) <> 0) then
- begin
- dec(t, HealthTagTex^.h + 2);
- DrawCentered(ox, t, HealthTagTex)
- end;
- if (cTagsMask and htName) <> 0 then
- begin
- dec(t, NameTagTex^.h + 2);
- DrawCentered(ox, t, NameTagTex)
- end;
- if (cTagsMask and htTeamName) <> 0 then
- begin
- dec(t, Team^.NameTagTex^.h + 2);
- DrawCentered(ox, t, Team^.NameTagTex)
- end;
- if (cTagsMask and htTransparent) <> 0 then
- Tint($FF, $FF, $FF, $FF)
- end;
- if (Gear^.State and gstHHDriven) <> 0 then // Current hedgehog
- begin
- if bShowFinger and ((Gear^.State and gstHHDriven) <> 0) then
- DrawSprite(sprFinger, ox - 16, oy - 64,
- GameTicks div 32 mod 16);
-
- if (Gear^.State and gstDrowning) = 0 then
- if (Gear^.State and gstHHThinking) <> 0 then
- DrawSprite(sprQuestion, ox - 10, oy - cHHRadius - 34, (RealTicks shr 9) mod 8)
- end
- end;
-
-if HH^.Effects[hePoisoned] then
- begin
- Tint($00, $FF, $40, $80);
- DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 1.5, 0, 0, sx, sy, 0, 1, 22, 22, 360 - (RealTicks shr 37) mod 360);
- end;
-if HH^.Effects[heResurrected] then
- begin
- Tint($f5, $db, $35, $20);
- DrawSprite(sprVampiric, sx - 24, sy - 24, 0);
- end;
-
-if Gear^.Invulnerable then
- begin
- Tint($FF, $FF, $FF, max($40, floor($FF * abs(1 - ((RealTicks div 2 + Gear^.uid * 491) mod 1500) / 750))));
- DrawSprite(sprInvulnerable, sx - 24, sy - 24, 0);
- end;
-if cVampiric and
- (CurrentHedgehog^.Gear <> nil) and
- (CurrentHedgehog^.Gear = Gear) then
- begin
- Tint($FF, 0, 0, max($40, floor($FF * abs(1 - (RealTicks mod 1500) / 750))));
- DrawSprite(sprVampiric, sx - 24, sy - 24, 0);
- end;
- Tint($FF, $FF, $FF, $FF)
-end;
-
-procedure DrawGears;
-var Gear, HHGear: PGear;
- i: Longword;
- x, y, startX, endX, startY, endY: LongInt;
-begin
-Gear:= GearsList;
-while Gear<>nil do
- begin
- x:= hwRound(Gear^.X) + WorldDx;
- y:= hwRound(Gear^.Y) + WorldDy;
- case Gear^.Kind of
- gtBomb: DrawRotated(sprBomb, x, y, 0, Gear^.DirAngle);
- gtGasBomb: DrawRotated(sprCheese, x, y, 0, Gear^.DirAngle);
- gtMolotov: DrawRotated(sprMolotov, x, y, 0, Gear^.DirAngle);
-
- gtRCPlane: begin
- if (Gear^.Tag = -1) then
- DrawRotated(sprPlane, x, y, -1, DxDy2Angle(Gear^.dX, Gear^.dY) + 90)
- else
- DrawRotated(sprPlane, x, y,0,DxDy2Angle(Gear^.dY, Gear^.dX));
- if ((TrainingFlags and tfRCPlane) <> 0) and (TrainingTargetGear <> nil) and ((Gear^.State and gstDrowning) = 0) then
- DrawRotatedf(sprFinger, x, y, GameTicks div 32 mod 16, 0, DxDy2Angle(Gear^.X - TrainingTargetGear^.X, TrainingTargetGear^.Y - Gear^.Y));
- end;
- gtBall: DrawRotatedf(sprBalls, x, y, Gear^.Tag,0, Gear^.DirAngle);
-
- gtPortal: if ((Gear^.Tag and 1) = 0) // still moving?
- or (Gear^.IntersectGear = nil) or (Gear^.IntersectGear^.IntersectGear <> Gear) // not linked&backlinked?
- or ((Gear^.IntersectGear^.Tag and 1) = 0) then // linked portal still moving?
- DrawRotatedf(sprPortal, x, y, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle)
- else DrawRotatedf(sprPortal, x, y, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle);
-
- gtDrill: if (Gear^.State and gsttmpFlag) <> 0 then
- DrawRotated(sprAirDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX))
- else
- DrawRotated(sprDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
-
- gtHedgehog: DrawHH(Gear, x, y);
-
- gtShell: DrawRotated(sprBazookaShell, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
-
- gtGrave: begin
- DrawTextureF(PHedgehog(Gear^.Hedgehog)^.Team^.GraveTex, 1, x, y, (GameTicks shr 7+Gear^.uid) and 7, 1, 32, 32);
- if Gear^.Health > 0 then
- begin
- //Tint($33, $33, $FF, max($40, floor($FF * abs(1 - (GameTicks mod (6000 div Gear^.Health)) / 750))));
- Tint($f5, $db, $35, max($40, floor($FF * abs(1 - (GameTicks mod 1500) / (750 + Gear^.Health)))));
- //Tint($FF, $FF, $FF, max($40, floor($FF * abs(1 - (RealTicks mod 1500) / 750))));
- DrawSprite(sprVampiric, x - 24, y - 24, 0);
- Tint($FF, $FF, $FF, $FF)
- end
- end;
- gtBee: DrawRotatedF(sprBee, x, y, (GameTicks shr 5) mod 2, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
- gtPickHammer: DrawSprite(sprPHammer, x - 16, y - 50 + LongInt(((GameTicks shr 5) and 1) * 2), 0);
- gtRope: DrawRope(Gear);
- gtMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
- DrawRotated(sprMineOff, x, y, 0, Gear^.DirAngle)
- else if Gear^.Health <> 0 then DrawRotated(sprMineOn, x, y, 0, Gear^.DirAngle)
- else DrawRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
- gtSMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
- DrawRotated(sprSMineOff, x, y, 0, Gear^.DirAngle)
- else if Gear^.Health <> 0 then DrawRotated(sprSMineOn, x, y, 0, Gear^.DirAngle)
- else DrawRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
- gtCase: case Gear^.Pos of
- posCaseAmmo : begin
- i:= (GameTicks shr 6) mod 64;
- if i > 18 then i:= 0;
- DrawSprite(sprCase, x - 24, y - 24, i);
- end;
- posCaseHealth: begin
- i:= ((GameTicks shr 6) + 38) mod 64;
- if i > 13 then i:= 0;
- DrawSprite(sprFAid, x - 24, y - 24, i);
- end;
- posCaseUtility: begin
- i:= (GameTicks shr 6) mod 70;
- if i > 23 then i:= 0;
- i:= i mod 12;
- DrawSprite(sprUtility, x - 24, y - 24, i);
- end;
- end;
- gtExplosives: begin
- if ((Gear^.State and gstDrowning) <> 0) then
- DrawSprite(sprExplosivesRoll, x - 24, y - 24, 0)
- else if Gear^.State and gstAnimation = 0 then
- begin
- i:= (GameTicks shr 6 + Gear^.uid*3) mod 64;
- if i > 18 then i:= 0;
- DrawSprite(sprExplosives, x - 24, y - 24, i)
- end
- else if Gear^.State and gsttmpFlag = 0 then
- DrawRotatedF(sprExplosivesRoll, x, y + 4, 0, 0, Gear^.DirAngle)
- else
- DrawRotatedF(sprExplosivesRoll, x, y + 4, 1, 0, Gear^.DirAngle);
- end;
- gtDynamite: DrawSprite2(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
- gtClusterBomb: DrawRotated(sprClusterBomb, x, y, 0, Gear^.DirAngle);
- gtCluster: DrawSprite(sprClusterParticle, x - 8, y - 8, 0);
- gtFlame: DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), x, y, (GameTicks shr 7 + LongWord(Gear^.Tag)) mod 8, 1, 16, 16);
- gtParachute: begin
- DrawSprite(sprParachute, x - 24, y - 48, 0);
- DrawAltWeapon(Gear, x + 1, y - 3)
- end;
- gtAirAttack: if Gear^.Tag > 0 then DrawSprite(sprAirplane, x - SpritesData[sprAirplane].Width div 2, y - SpritesData[sprAirplane].Height div 2, 0)
- else DrawSprite(sprAirplane, x - SpritesData[sprAirplane].Width div 2, y - SpritesData[sprAirplane].Height div 2, 1);
- gtAirBomb: DrawRotated(sprAirBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
- gtTeleport: begin
- HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
- if not PHedgehog(Gear^.Hedgehog)^.Unplaced then DrawRotatedF(sprTeleport, x + 1, y - 3, Gear^.Pos, hwSign(Gear^.dX), 0);
- DrawRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0);
- end;
- gtSwitcher: DrawSprite(sprSwitch, x - 16, y - 56, (GameTicks shr 6) mod 12);
- gtTarget: begin
- Tint($FF, $FF, $FF, floor($FF * Gear^.Timer / 1000));
- DrawSprite(sprTarget, x - 16, y - 16, 0);
- Tint($FF, $FF, $FF, $FF);
- end;
- gtMortar: DrawRotated(sprMortar, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
- gtCake: if Gear^.Pos = 6 then
- DrawRotatedf(sprCakeWalk, x, y, (GameTicks div 40) mod 6, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90)
- else
- DrawRotatedf(sprCakeDown, x, y, 5 - Gear^.Pos, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90);
- gtSeduction: if Gear^.Pos >= 14 then DrawSprite(sprSeduction, x - 16, y - 16, 0);
- gtWatermelon: DrawRotatedf(sprWatermelon, x, y, 0, 0, Gear^.DirAngle);
- gtMelonPiece: DrawRotatedf(sprWatermelon, x, y, 1, 0, Gear^.DirAngle);
- gtHellishBomb: DrawRotated(sprHellishBomb, x, y, 0, Gear^.DirAngle);
- gtBirdy: begin
- if Gear^.State and gstAnimation = gstAnimation then
- begin
- if Gear^.State and gstTmpFlag = 0 then // Appearing
- begin
- endX:= x - WorldDx;
- endY:= y - WorldDy;
- if Gear^.Tag < 0 then
- startX:= max(LAND_WIDTH + 1024, endX + 2048)
- else
- startX:= max(-LAND_WIDTH - 1024, endX - 2048);
- startY:= endY - 256;
- DrawTextureF(SpritesData[sprBirdy].Texture, 1, startX + WorldDx + floor((endX - startX) * (-power(2, -10 * LongInt(Gear^.Timer)/2000) + 1)), startY + WorldDy + floor((endY - startY) * sqrt(1 - power((LongInt(Gear^.Timer)/2000)-1, 2))), ((Gear^.Pos shr 6) or (RealTicks shr 8)) mod 2, Gear^.Tag, 75, 75);
- end
- else // Disappearing
- begin
- startX:= x - WorldDx;
- startY:= y - WorldDy;
- if Gear^.Tag > 0 then
- endX:= max(LAND_WIDTH + 1024, startX + 2048)
- else
- endX:= max(-LAND_WIDTH - 1024, startX - 2048);
- endY:= startY + 256;
- DrawTextureF(SpritesData[sprBirdy].Texture, 1, startX + WorldDx + floor((endX - startX) * power(2, 10 * (LongInt(Gear^.Timer)/2000 - 1))) + hwRound(Gear^.dX * Gear^.Timer), startY + WorldDy + floor((endY - startY) * cos(LongInt(Gear^.Timer)/2000 * (Pi/2)) - (endY - startY)) + hwRound(Gear^.dY * Gear^.Timer), ((Gear^.Pos shr 6) or (RealTicks shr 8)) mod 2, Gear^.Tag, 75, 75);
- end;
- end
- else
- DrawTextureF(SpritesData[sprBirdy].Texture, 1, x, y, ((Gear^.Pos shr 6) or (RealTicks shr 8)) mod 2, Gear^.Tag, 75, 75);
- end;
- gtEgg: DrawRotatedTextureF(SpritesData[sprEgg].Texture, 1, 0, 0, x, y, 0, 1, 16, 16, Gear^.DirAngle);
- gtPiano: begin
- if (Gear^.State and gstDrowning) = 0 then
- begin
- Tint($FF, $FF, $FF, $10);
- for i:= 8 downto 1 do
- DrawRotatedTextureF(SpritesData[sprPiano].Texture, 1, 0, 0, x, y - hwRound(Gear^.dY * 4 * i), 0, 1, 128, 128, 0);
- Tint($FF, $FF, $FF, $FF)
- end;
- DrawRotatedTextureF(SpritesData[sprPiano].Texture, 1, 0, 0, x, y, 0, 1, 128, 128, 0);
- end;
- gtPoisonCloud: begin
- if Gear^.Timer < 1020 then
- Tint($C0, $C0, $00, Gear^.Timer div 8)
- else if Gear^.Timer > 3980 then
- Tint($C0, $C0, $00, (5000 - Gear^.Timer) div 8)
- else
- Tint($C0, $C0, $00, $C0);
- DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 3, 0, 0, x, y, 0, 1, 22, 22, (RealTicks shr 36 + Gear^.UID * 100) mod 360);
- Tint($FF, $FF, $FF, $FF)
- end;
- gtResurrector: begin
- DrawRotated(sprCross, x, y, 0, 0);
- Tint($f5, $db, $35, max($00, floor($C0 * abs(1 - (GameTicks mod 6000) / 3000))));
- DrawTexture(x - 108, y - 108, SpritesData[sprVampiric].Texture, 4.5);
- Tint($FF, $FF, $FF, $FF);
- end;
- gtNapalmBomb: DrawRotated(sprNapalmBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
- end;
- if Gear^.RenderTimer and (Gear^.Tex <> nil) then DrawCentered(x + 8, y + 8, Gear^.Tex);
- Gear:= Gear^.NextGear
- end;
-end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/HHHandlers.inc
--- a/hedgewars/HHHandlers.inc Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/HHHandlers.inc Tue Jan 04 12:53:46 2011 +0100
@@ -48,7 +48,7 @@
ChangeAmmo:= false;
slot:= Gear^.MsgParam;
-with PHedgehog(Gear^.Hedgehog)^ do
+with Gear^.Hedgehog^ do
begin
Gear^.Message:= Gear^.Message and not gmSlot;
ammoidx:= 0;
@@ -60,7 +60,7 @@
while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx);
- if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(PHedgehog(Gear^.Hedgehog)^);
+ if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(Gear^.Hedgehog^);
MultiShootAttacks:= 0;
Gear^.Message:= Gear^.Message and not (gmLJump or gmHJump);
@@ -101,7 +101,7 @@
s: boolean;
begin
weap:= TAmmoType(Gear^.MsgParam);
-Hedgehog:= PHedgehog(Gear^.Hedgehog);
+Hedgehog:= Gear^.Hedgehog;
if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
@@ -118,15 +118,15 @@
dec(t)
end;
-if s then ApplyAmmoChanges(PHedgehog(Gear^.Hedgehog)^)
+if s then ApplyAmmoChanges(Gear^.Hedgehog^)
end;
procedure HHSetTimer(Gear: PGear);
var CurWeapon: PAmmo;
begin
Gear^.Message:= Gear^.Message and not gmTimer;
-CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
-with PHedgehog(Gear^.Hedgehog)^ do
+CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
+with Gear^.Hedgehog^ do
if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
begin
CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
@@ -143,9 +143,9 @@
altUse: boolean;
begin
bShowFinger:= false;
-CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
+CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
with Gear^,
- PHedgehog(Gear^.Hedgehog)^ do
+ Gear^.Hedgehog^ do
begin
if ((State and gstHHDriven) <> 0)and
((State and (gstAttacked or gstHHChooseTarget)) = 0) and
@@ -207,6 +207,7 @@
amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb, 0, newDx, newDy, CurWeapon^.Timer);
amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb, 0, newDx, newDy, CurWeapon^.Timer);
amBazooka: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtShell, 0, newDx, newDy, 0);
+ amSnowball: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtSnowball, 0, newDx, newDy, 0);
amBee: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtBee, 0, newDx, newDy, 0);
amShotgun: begin
PlaySound(sndShotgunReload);
@@ -222,7 +223,11 @@
amSMine: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtSMine, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
amDEagle: CurAmmoGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
amSineGun: CurAmmoGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSineGunShot, 0, xx * _0_5, yy * _0_5, 0);
- amPortalGun: AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 0);
+ amPortalGun: begin
+ AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6,
+ // set selected color
+ CurWeapon^.Pos);
+ end;
amSniperRifle: begin
PlaySound(sndSniperReload);
CurAmmoGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
@@ -275,7 +280,8 @@
end;
amLowGravity: begin
PlaySound(sndLowGravity);
- cGravity:= cMaxWindSpeed
+ cGravity:= cMaxWindSpeed;
+ cGravityf:= 0.00025
end;
amExtraDamage:begin
PlaySound(sndHellishImpact4);
@@ -386,7 +392,7 @@
const frametime = 200;
timertime = frametime * 6;
begin
-if PHedgehog(Gear^.Hedgehog)^.Unplaced then exit;
+if Gear^.Hedgehog^.Unplaced then exit;
if Gear^.Timer > 1 then
begin
AllInactive:= false;
@@ -406,7 +412,7 @@
Gear^.Z:= cCurrHHZ;
RemoveGearFromList(Gear);
InsertGearToList(Gear);
- PlaySound(sndByeBye, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+ PlaySound(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
Gear^.Pos:= 0;
Gear^.Timer:= timertime
end
@@ -417,7 +423,7 @@
const frametime = 65;
timertime = frametime * 11;
begin
-if PHedgehog(Gear^.Hedgehog)^.Unplaced then exit;
+if Gear^.Hedgehog^.Unplaced then exit;
if Gear^.Timer > 1 then
begin
AllInactive:= false;
@@ -434,7 +440,7 @@
Gear^.Z:= cCurrHHZ;
RemoveGearFromList(Gear);
InsertGearToList(Gear);
- PlaySound(sndByeBye, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+ PlaySound(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
PlaySound(sndWarp);
Gear^.Pos:= 0;
Gear^.Timer:= timertime
@@ -454,16 +460,16 @@
posCaseUtility,
posCaseAmmo: begin
a:= Gear^.AmmoType;
- AddAmmo(PHedgehog(HH^.Hedgehog)^, a);
+ AddAmmo(HH^.Hedgehog^, a);
// Possibly needs to check shared clan ammo game flag once added.
// On the other hand, no obvious reason that clan members shouldn't know what ammo another clan member picked up
- if (not (PHedgehog(HH^.Hedgehog)^.Team^.ExtDriven
- or (PHedgehog(HH^.Hedgehog)^.BotLevel > 0)))
- or (PHedgehog(HH^.Hedgehog)^.Team^.Clan^.ClanIndex = LocalClan)
+ if (not (HH^.Hedgehog^.Team^.ExtDriven
+ or (HH^.Hedgehog^.BotLevel > 0)))
+ or (HH^.Hedgehog^.Team^.Clan^.ClanIndex = LocalClan)
or (GameType = gmtDemo) then
begin
s:= trammo[Ammoz[a].NameId] + ' (+' + IntToStr(Ammoz[a].NumberInCase) + ')';
- AddCaption(s, PHedgehog(HH^.Hedgehog)^.Team^.Clan^.Color, capgrpAmmoinfo);
+ AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
// show ammo icon
vga:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtAmmo);
@@ -474,12 +480,12 @@
end;
posCaseHealth: begin
inc(HH^.Health, Gear^.Health);
- PHedgehog(HH^.Hedgehog)^.Effects[hePoisoned] := false;
+ HH^.Hedgehog^.Effects[hePoisoned] := false;
str(Gear^.Health, s);
s:= '+' + s;
- AddCaption(s, PHedgehog(HH^.Hedgehog)^.Team^.Clan^.Color, capgrpAmmoinfo);
- RenderHealth(PHedgehog(HH^.Hedgehog)^);
- RecountTeamHealth(PHedgehog(HH^.Hedgehog)^.Team);
+ AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
+ RenderHealth(HH^.Hedgehog^);
+ RecountTeamHealth(HH^.Hedgehog^.Team);
i:= 0;
while i < Gear^.Health do
@@ -497,11 +503,11 @@
var PrevdX: LongInt;
CurWeapon: PAmmo;
begin
-CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
+CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
begin
if isCursorVisible then
- with PHedgehog(Gear^.Hedgehog)^ do
+ with Gear^.Hedgehog^ do
with CurWeapon^ do
begin
if (Gear^.Message and gmLeft ) <> 0 then
@@ -536,7 +542,7 @@
Gear^.dY:= -_0_15;
if not cArtillery then Gear^.dX:= SignAs(_0_15, Gear^.dX);
Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
- PlaySound(sndJump1, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+ PlaySound(sndJump1, Gear^.Hedgehog^.Team^.voicepack);
exit
end;
end;
@@ -549,7 +555,7 @@
Gear^.dY:= -_0_2;
SetLittle(Gear^.dX);
Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
- PlaySound(sndJump3, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+ PlaySound(sndJump3, Gear^.Hedgehog^.Team^.voicepack);
exit
end;
@@ -570,7 +576,7 @@
end;
DeleteCI(Gear); // must be after exit!! (see previous line)
- PHedgehog(Gear^.Hedgehog)^.visStepPos:= (PHedgehog(Gear^.Hedgehog)^.visStepPos + 1) and 7;
+ Gear^.Hedgehog^.visStepPos:= (Gear^.Hedgehog^.visStepPos + 1) and 7;
if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
begin
if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
@@ -630,7 +636,7 @@
procedure HedgehogChAngle(Gear: PGear);
var da: LongWord;
begin
-with PHedgehog(Gear^.Hedgehog)^ do
+with Gear^.Hedgehog^ do
if (CurAmmoType = amRope)
and ((Gear^.State and (gstMoving or gstHHJumping)) = gstMoving) then da:= 2 else da:= 1;
@@ -649,7 +655,7 @@
if Gear^.dX.QWordValue > 8160437862 then Gear^.dX.QWordValue:= 8160437862;
if Gear^.dY.QWordValue > 8160437862 then Gear^.dY.QWordValue:= 8160437862;
-if PHedgehog(Gear^.Hedgehog)^.Unplaced then
+if Gear^.Hedgehog^.Unplaced then
begin
Gear^.dY:= _0;
Gear^.dX:= _0;
@@ -667,12 +673,12 @@
Gear^.dY:= Gear^.dY + cGravity;
// this set of circumstances could be less complex if jumping was more clearly identified
if ((GameFlags and gfMoreWind) <> 0) and
- (Gear^.Damage <> 0) or
+ (((Gear^.Damage <> 0) or
((CurAmmoGear <> nil) and
((CurAmmoGear^.AmmoType = amJetpack) or
(CurAmmoGear^.AmmoType = amBirdy))) or
- ((Gear^.dY.QWordValue + Gear^.dX.QWordValue) > _0_55.QWordValue)
- then Gear^.dX := Gear^.dX + cWindSpeed * _0_2
+ ((Gear^.dY.QWordValue + Gear^.dX.QWordValue) > _0_55.QWordValue)))
+ then Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density
end
end
else
@@ -773,7 +779,7 @@
wasJumping: boolean;
Hedgehog: PHedgehog;
begin
-Hedgehog:= PHedgehog(Gear^.Hedgehog);
+Hedgehog:= Gear^.Hedgehog;
if not isInMultiShoot then
AllInactive:= false
else
@@ -919,16 +925,16 @@
PrvInactive:= false;
AllInactive:= false;
- if not PHedgehog(Gear^.Hedgehog)^.Team^.hasGone then
+ if not Gear^.Hedgehog^.Team^.hasGone then
begin
- PHedgehog(Gear^.Hedgehog)^.Effects[hePoisoned] := false;
- if PHedgehog(Gear^.Hedgehog)^.Effects[heResurrectable] then begin
+ Gear^.Hedgehog^.Effects[hePoisoned] := false;
+ if Gear^.Hedgehog^.Effects[heResurrectable] then begin
ResurrectHedgehog(Gear);
end else begin
Gear^.State:= Gear^.State or gstHHDeath;
Gear^.doStep:= @doStepHedgehogDead;
// Death message
- AddCaption(Format(GetEventString(eidDied), PHedgehog(Gear^.Hedgehog)^.Name), cWhiteColor, capgrpMessage);
+ AddCaption(Format(GetEventString(eidDied), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
end;
end
else
@@ -936,7 +942,7 @@
Gear^.State:= Gear^.State or gstHHGone;
Gear^.doStep:= @doStepHedgehogGone;
// Gone message
- AddCaption(Format(GetEventString(eidGone), PHedgehog(Gear^.Hedgehog)^.Name), cWhiteColor, capgrpMessage);
+ AddCaption(Format(GetEventString(eidGone), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
end
end;
exit
@@ -974,7 +980,7 @@
doStepHedgehogFree(Gear)
else
begin
- with PHedgehog(Gear^.Hedgehog)^ do
+ with Gear^.Hedgehog^ do
if Team^.hasGone then TeamGoneEffect(Team^);
doStepHedgehogDriven(Gear)
end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/PascalExports.pas
--- a/hedgewars/PascalExports.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/PascalExports.pas Tue Jan 04 12:53:46 2011 +0100
@@ -21,23 +21,21 @@
unit PascalExports;
interface
-uses uKeys, GLunit, uWorld, uMisc, uConsole, uTeams, uConsts, uChat,
- uGears, uSound, hwengine, uAmmos, uLocale; // don't change the order!
+uses uTypes, uConsts, uVariables, GLunit, uKeys, uChat, uSound, uAmmos, uUtils,
+ uCommands;
{$INCLUDE "config.inc"}
-var dummy: boolean; // avoid compiler hint
-
implementation
{$IFDEF HWLIBRARY}
var cZoomVal: GLfloat;
+ previousGameState: TGameState;
// retrieve protocol information
-procedure HW_versionInfo(netProto: PShortInt; versionStr: PPChar); cdecl; export;
+procedure HW_versionInfo(netProto: PLongInt; versionStr: PPChar); cdecl; export;
begin
-// http://bugs.freepascal.org/view.php?id=16156
- if netProto <> nil then netProto^:= cNetProtoVersion;
- if versionStr <> nil then versionStr^:= cVersionString;
+ netProto^:= cNetProtoVersion;
+ versionStr^:= cVersionString;
end;
procedure HW_click; cdecl; export;
@@ -167,9 +165,31 @@
procedure HW_pause; cdecl; export;
begin
+ if isPaused = false then
+ pauseAction:= true;
+end;
+
+procedure HW_pauseToggle; cdecl; export;
+begin
pauseAction:= true;
end;
+function HW_isPaused: boolean; cdecl; export;
+begin
+ exit( isPaused );
+end;
+
+procedure HW_suspend; cdecl; export;
+begin
+ previousGameState:= GameState;
+ GameState:= gsSuspend;
+end;
+
+procedure HW_resume; cdecl; export;
+begin
+ GameState:= previousGameState;
+end;
+
procedure HW_terminate(closeFrontend: boolean); cdecl; export;
begin
isTerminated:= true;
@@ -199,11 +219,6 @@
((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) = 0)) and hideAmmoMenu)) );
end;
-function HW_isPaused: boolean; cdecl; export;
-begin
- exit( isPaused );
-end;
-
function HW_isWaiting: boolean; cdecl; export;
begin
exit( ReadyTimeLeft > 0 );
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/SDLMain.m
--- a/hedgewars/SDLMain.m Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/SDLMain.m Tue Jan 04 12:53:46 2011 +0100
@@ -216,9 +216,11 @@
#endif /* SDL_USE_CPS */
/* Set up the menubar */
- [NSApp setMainMenu:[[NSMenu alloc] init]];
+ NSMenu *menu = [[NSMenu alloc] init];
+ [NSApp setMainMenu:menu];
setApplicationMenu();
setupWindowMenu();
+ [menu release];
/* Create SDLMain and make it the app delegate */
sdlMain = [[SDLMain alloc] init];
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/SDLh.pas
--- a/hedgewars/SDLh.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/SDLh.pas Tue Jan 04 12:53:46 2011 +0100
@@ -511,6 +511,17 @@
{$ENDIF}
end;
+ TSDL_UserEvent = record
+{$IFDEF SDL13}
+ type_: LongInt;
+ windowID: LongInt;
+{$ELSE}
+ type_: Byte;
+{$ENDIF}
+ code: LongInt;
+ data1, data2: Pointer;
+ end;
+
PSDL_Event = ^TSDL_Event;
TSDL_Event = record
{$IFDEF SDL13}
@@ -531,6 +542,7 @@
SDL_JOYBALLMOTION: (jball: TSDL_JoyBallEvent);
SDL_JOYBUTTONDOWN,
SDL_JOYBUTTONUP: (jbutton: TSDL_JoyButtonEvent);
+ SDL_USEREVENT: (user: TSDL_UserEvent);
{$ELSE}
case Byte of
SDL_NOEVENT: (type_: byte);
@@ -774,7 +786,7 @@
function TTF_Init: LongInt; cdecl; external SDL_TTFLibName;
procedure TTF_Quit; cdecl; external SDL_TTFLibName;
-function TTF_SizeUTF8(font: PTTF_Font; const text: PChar; var w, h: LongInt): LongInt; cdecl; external SDL_TTFLibName;
+function TTF_SizeUTF8(font: PTTF_Font; const text: PChar; out w, h: LongInt): LongInt; cdecl; external SDL_TTFLibName;
function TTF_RenderUTF8_Solid(font: PTTF_Font; const text: PChar; fg: TSDL_Color): PSDL_Surface; cdecl; external SDL_TTFLibName;
function TTF_RenderUTF8_Blended(font: PTTF_Font; const text: PChar; fg: TSDL_Color): PSDL_Surface; cdecl; external SDL_TTFLibName;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/SinTable.inc
--- a/hedgewars/SinTable.inc Mon Dec 27 23:57:44 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1045 +0,0 @@
-(*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007 Andrey Korotaev
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *)
-
-const SinTable: array[0..1024] of QWord = (
- $00000000,
- $006487EB,
- $00C90FC6,
- $012D9782,
- $01921F10,
- $01F6A660,
- $025B2D62,
- $02BFB407,
- $03243A40,
- $0388BFFC,
- $03ED452D,
- $0451C9C3,
- $04B64DAF,
- $051AD0E0,
- $057F5348,
- $05E3D4D7,
- $0648557E,
- $06ACD52C,
- $071153D3,
- $0775D163,
- $07DA4DCC,
- $083EC900,
- $08A342EE,
- $0907BB86,
- $096C32BB,
- $09D0A87B,
- $0A351CB8,
- $0A998F62,
- $0AFE0069,
- $0B626FBF,
- $0BC6DD53,
- $0C2B4916,
- $0C8FB2F9,
- $0CF41AEB,
- $0D5880DF,
- $0DBCE4C3,
- $0E214689,
- $0E85A622,
- $0EEA037D,
- $0F4E5E8B,
- $0FB2B73D,
- $10170D83,
- $107B614E,
- $10DFB28F,
- $11440135,
- $11A84D31,
- $120C9675,
- $1270DCF0,
- $12D52093,
- $1339614E,
- $139D9F13,
- $1401D9D1,
- $14661179,
- $14CA45FC,
- $152E774A,
- $1592A554,
- $15F6D00B,
- $165AF75E,
- $16BF1B3E,
- $17233B9D,
- $1787586A,
- $17EB7197,
- $184F8713,
- $18B398CF,
- $1917A6BC,
- $197BB0CB,
- $19DFB6EB,
- $1A43B90E,
- $1AA7B724,
- $1B0BB11E,
- $1B6FA6EC,
- $1BD3987F,
- $1C3785C8,
- $1C9B6EB6,
- $1CFF533B,
- $1D633348,
- $1DC70ECC,
- $1E2AE5B8,
- $1E8EB7FE,
- $1EF2858D,
- $1F564E57,
- $1FBA124B,
- $201DD15B,
- $20818B77,
- $20E5408F,
- $2148F095,
- $21AC9B79,
- $2210412C,
- $2273E19E,
- $22D77CBF,
- $233B1281,
- $239EA2D5,
- $24022DAA,
- $2465B2F1,
- $24C9329C,
- $252CAC9A,
- $259020DD,
- $25F38F55,
- $2656F7F3,
- $26BA5AA7,
- $271DB762,
- $27810E14,
- $27E45EB0,
- $2847A924,
- $28AAED62,
- $290E2B5B,
- $297162FF,
- $29D4943F,
- $2A37BF0B,
- $2A9AE355,
- $2AFE010D,
- $2B611823,
- $2BC42889,
- $2C27322F,
- $2C8A3506,
- $2CED30FF,
- $2D50260A,
- $2DB31418,
- $2E15FB1A,
- $2E78DB01,
- $2EDBB3BD,
- $2F3E853F,
- $2FA14F78,
- $30041258,
- $3066CDD1,
- $30C981D3,
- $312C2E50,
- $318ED336,
- $31F17079,
- $32540608,
- $32B693D3,
- $331919CD,
- $337B97E6,
- $33DE0E0E,
- $34407C36,
- $34A2E250,
- $3505404B,
- $3567961A,
- $35C9E3AC,
- $362C28F3,
- $368E65DE,
- $36F09A61,
- $3752C66A,
- $37B4E9EB,
- $381704D5,
- $38791719,
- $38DB20A7,
- $393D2170,
- $399F1966,
- $3A010879,
- $3A62EE9A,
- $3AC4CBBA,
- $3B269FCB,
- $3B886ABB,
- $3BEA2C7E,
- $3C4BE503,
- $3CAD943C,
- $3D0F3A1A,
- $3D70D68C,
- $3DD26986,
- $3E33F2F6,
- $3E9572CF,
- $3EF6E901,
- $3F58557E,
- $3FB9B836,
- $401B111A,
- $407C601B,
- $40DDA52A,
- $413EE039,
- $41A01138,
- $42013818,
- $426254CA,
- $42C3673F,
- $43246F69,
- $43856D38,
- $43E6609E,
- $4447498B,
- $44A827F0,
- $4508FBBF,
- $4569C4E9,
- $45CA835E,
- $462B3710,
- $468BDFF0,
- $46EC7DEE,
- $474D10FD,
- $47AD990D,
- $480E160F,
- $486E87F5,
- $48CEEEAF,
- $492F4A2F,
- $498F9A65,
- $49EFDF44,
- $4A5018BB,
- $4AB046BD,
- $4B10693A,
- $4B708024,
- $4BD08B6C,
- $4C308B02,
- $4C907ED9,
- $4CF066E1,
- $4D50430C,
- $4DB0134A,
- $4E0FD78D,
- $4E6F8FC7,
- $4ECF3BE8,
- $4F2EDBE2,
- $4F8E6FA6,
- $4FEDF725,
- $504D7250,
- $50ACE11A,
- $510C4372,
- $516B994B,
- $51CAE295,
- $522A1F43,
- $52894F44,
- $52E8728C,
- $5347890A,
- $53A692B0,
- $54058F70,
- $54647F3B,
- $54C36203,
- $552237B8,
- $5581004C,
- $55DFBBB0,
- $563E69D7,
- $569D0AB0,
- $56FB9E2E,
- $575A2443,
- $57B89CDE,
- $581707F3,
- $58756572,
- $58D3B54D,
- $5931F775,
- $59902BDC,
- $59EE5273,
- $5A4C6B2B,
- $5AAA75F7,
- $5B0872C8,
- $5B66618E,
- $5BC4423C,
- $5C2214C4,
- $5C7FD916,
- $5CDD8F25,
- $5D3B36E1,
- $5D98D03D,
- $5DF65B29,
- $5E53D798,
- $5EB1457C,
- $5F0EA4C4,
- $5F6BF565,
- $5FC9374E,
- $60266A71,
- $60838EC1,
- $60E0A42F,
- $613DAAAC,
- $619AA22A,
- $61F78A9B,
- $625463F0,
- $62B12E1B,
- $630DE90E,
- $636A94BB,
- $63C73113,
- $6423BE08,
- $64803B8B,
- $64DCA98F,
- $65390805,
- $659556DF,
- $65F1960E,
- $664DC585,
- $66A9E535,
- $6705F510,
- $6761F508,
- $67BDE50F,
- $6819C516,
- $6875950F,
- $68D154EC,
- $692D049F,
- $6988A41B,
- $69E4334F,
- $6A3FB230,
- $6A9B20AE,
- $6AF67EBB,
- $6B51CC49,
- $6BAD094B,
- $6C0835B2,
- $6C635170,
- $6CBE5C77,
- $6D1956B9,
- $6D744028,
- $6DCF18B5,
- $6E29E054,
- $6E8496F6,
- $6EDF3C8C,
- $6F39D10A,
- $6F945460,
- $6FEEC681,
- $70492760,
- $70A376EE,
- $70FDB51D,
- $7157E1DF,
- $71B1FD26,
- $720C06E5,
- $7265FF0E,
- $72BFE593,
- $7319BA65,
- $73737D77,
- $73CD2EBC,
- $7426CE24,
- $74805BA4,
- $74D9D72C,
- $753340AF,
- $758C981F,
- $75E5DD6E,
- $763F108F,
- $76983174,
- $76F1400F,
- $774A3C52,
- $77A32630,
- $77FBFD9B,
- $7854C285,
- $78AD74E0,
- $7906149F,
- $795EA1B5,
- $79B71C13,
- $7A0F83AC,
- $7A67D872,
- $7AC01A58,
- $7B184950,
- $7B70654C,
- $7BC86E3F,
- $7C20641B,
- $7C7846D3,
- $7CD01659,
- $7D27D2A0,
- $7D7F7B99,
- $7DD71139,
- $7E2E9370,
- $7E860232,
- $7EDD5D71,
- $7F34A51F,
- $7F8BD930,
- $7FE2F995,
- $803A0641,
- $8090FF28,
- $80E7E43A,
- $813EB56C,
- $819572AF,
- $81EC1BF7,
- $8242B135,
- $8299325D,
- $82EF9F62,
- $8345F835,
- $839C3CC9,
- $83F26D12,
- $84488902,
- $849E908B,
- $84F483A1,
- $854A6236,
- $85A02C3C,
- $85F5E1A8,
- $864B826B,
- $86A10E78,
- $86F685C2,
- $874BE83C,
- $87A135D9,
- $87F66E8C,
- $884B9247,
- $88A0A0FD,
- $88F59AA1,
- $894A7F26,
- $899F4E7F,
- $89F408A0,
- $8A48AD7A,
- $8A9D3D00,
- $8AF1B727,
- $8B461BE0,
- $8B9A6B1F,
- $8BEEA4D7,
- $8C42C8FA,
- $8C96D77C,
- $8CEAD050,
- $8D3EB368,
- $8D9280B9,
- $8DE63834,
- $8E39D9CD,
- $8E8D6578,
- $8EE0DB27,
- $8F343ACD,
- $8F87845E,
- $8FDAB7CC,
- $902DD50C,
- $9080DC0F,
- $90D3CCCA,
- $9126A72F,
- $91796B31,
- $91CC18C5,
- $921EAFDD,
- $9271306C,
- $92C39A66,
- $9315EDBE,
- $93682A67,
- $93BA5055,
- $940C5F7A,
- $945E57CB,
- $94B0393B,
- $950203BD,
- $9553B744,
- $95A553C4,
- $95F6D930,
- $9648477C,
- $96999E9A,
- $96EADE80,
- $973C071F,
- $978D186C,
- $97DE125A,
- $982EF4DD,
- $987FBFE7,
- $98D0736D,
- $99210F62,
- $997193BA,
- $99C20068,
- $9A125560,
- $9A629296,
- $9AB2B7FD,
- $9B02C588,
- $9B52BB2C,
- $9BA298DC,
- $9BF25E8C,
- $9C420C2F,
- $9C91A1B9,
- $9CE11F1F,
- $9D308453,
- $9D7FD149,
- $9DCF05F6,
- $9E1E224C,
- $9E6D2640,
- $9EBC11C6,
- $9F0AE4D1,
- $9F599F56,
- $9FA84148,
- $9FF6CA9A,
- $A0453B42,
- $A0939332,
- $A0E1D25F,
- $A12FF8BC,
- $A17E063F,
- $A1CBFAD9,
- $A219D681,
- $A2679928,
- $A2B542C5,
- $A302D349,
- $A3504AAB,
- $A39DA8DD,
- $A3EAEDD3,
- $A4381983,
- $A4852BDF,
- $A4D224DD,
- $A51F046F,
- $A56BCA8B,
- $A5B87724,
- $A6050A2F,
- $A65183A0,
- $A69DE36B,
- $A6EA2984,
- $A73655DF,
- $A7826871,
- $A7CE612E,
- $A81A400B,
- $A86604FB,
- $A8B1AFF3,
- $A8FD40E7,
- $A948B7CB,
- $A9941495,
- $A9DF5738,
- $AA2A7FA9,
- $AA758DDB,
- $AAC081C5,
- $AB0B5B59,
- $AB561A8D,
- $ABA0BF54,
- $ABEB49A4,
- $AC35B971,
- $AC800EB0,
- $ACCA4954,
- $AD146953,
- $AD5E6EA1,
- $ADA85932,
- $ADF228FC,
- $AE3BDDF3,
- $AE85780B,
- $AECEF73A,
- $AF185B73,
- $AF61A4AC,
- $AFAAD2D9,
- $AFF3E5EF,
- $B03CDDE3,
- $B085BAA9,
- $B0CE7C36,
- $B117227F,
- $B15FAD79,
- $B1A81D19,
- $B1F07153,
- $B238AA1C,
- $B280C769,
- $B2C8C930,
- $B310AF64,
- $B35879FB,
- $B3A028E9,
- $B3E7BC25,
- $B42F33A1,
- $B4768F55,
- $B4BDCF34,
- $B504F334,
- $B54BFB49,
- $B592E769,
- $B5D9B789,
- $B6206B9E,
- $B667039D,
- $B6AD7F7A,
- $B6F3DF2C,
- $B73A22A7,
- $B78049E1,
- $B7C654CE,
- $B80C4364,
- $B8521599,
- $B897CB60,
- $B8DD64B0,
- $B922E17E,
- $B96841BF,
- $B9AD8569,
- $B9F2AC70,
- $BA37B6CB,
- $BA7CA46D,
- $BAC1754E,
- $BB062962,
- $BB4AC09E,
- $BB8F3AF8,
- $BBD39866,
- $BC17D8DD,
- $BC5BFC52,
- $BCA002BA,
- $BCE3EC0D,
- $BD27B83E,
- $BD6B6744,
- $BDAEF913,
- $BDF26DA3,
- $BE35C4E7,
- $BE78FED6,
- $BEBC1B66,
- $BEFF1A8C,
- $BF41FC3E,
- $BF84C071,
- $BFC7671B,
- $C009F032,
- $C04C5BAB,
- $C08EA97D,
- $C0D0D99E,
- $C112EC02,
- $C154E0A0,
- $C196B76D,
- $C1D87060,
- $C21A0B6E,
- $C25B888D,
- $C29CE7B4,
- $C2DE28D7,
- $C31F4BEE,
- $C36050ED,
- $C3A137CB,
- $C3E2007E,
- $C422AAFC,
- $C463373A,
- $C4A3A530,
- $C4E3F4D2,
- $C5242618,
- $C56438F7,
- $C5A42D65,
- $C5E40359,
- $C623BAC8,
- $C66353A9,
- $C6A2CDF2,
- $C6E22999,
- $C7216694,
- $C76084DA,
- $C79F8461,
- $C7DE651F,
- $C81D270B,
- $C85BCA1B,
- $C89A4E44,
- $C8D8B37F,
- $C916F9C0,
- $C95520FE,
- $C9932930,
- $C9D1124D,
- $CA0EDC49,
- $CA4C871D,
- $CA8A12BF,
- $CAC77F24,
- $CB04CC45,
- $CB41FA16,
- $CB7F088F,
- $CBBBF7A6,
- $CBF8C752,
- $CC35778A,
- $CC720844,
- $CCAE7977,
- $CCEACB19,
- $CD26FD21,
- $CD630F87,
- $CD9F0240,
- $CDDAD543,
- $CE168888,
- $CE521C04,
- $CE8D8FAF,
- $CEC8E380,
- $CF04176E,
- $CF3F2B6E,
- $CF7A1F79,
- $CFB4F385,
- $CFEFA78A,
- $D02A3B7D,
- $D064AF56,
- $D09F030C,
- $D0D93696,
- $D11349EB,
- $D14D3D02,
- $D1870FD2,
- $D1C0C253,
- $D1FA547A,
- $D233C641,
- $D26D179C,
- $D2A64885,
- $D2DF58F1,
- $D31848D8,
- $D3511832,
- $D389C6F5,
- $D3C25519,
- $D3FAC295,
- $D4330F60,
- $D46B3B73,
- $D4A346C3,
- $D4DB3148,
- $D512FAFB,
- $D54AA3D1,
- $D5822BC4,
- $D5B992C9,
- $D5F0D8D8,
- $D627FDEA,
- $D65F01F5,
- $D695E4F1,
- $D6CCA6D6,
- $D703479A,
- $D739C736,
- $D77025A2,
- $D7A662D4,
- $D7DC7EC5,
- $D812796C,
- $D84852C1,
- $D87E0ABB,
- $D8B3A152,
- $D8E9167F,
- $D91E6A38,
- $D9539C76,
- $D988AD30,
- $D9BD9C5E,
- $D9F269F8,
- $DA2715F5,
- $DA5BA04F,
- $DA9008FC,
- $DAC44FF5,
- $DAF87531,
- $DB2C78A8,
- $DB605A53,
- $DB941A29,
- $DBC7B822,
- $DBFB3437,
- $DC2E8E60,
- $DC61C694,
- $DC94DCCB,
- $DCC7D0FF,
- $DCFAA326,
- $DD2D533A,
- $DD5FE131,
- $DD924D06,
- $DDC496AF,
- $DDF6BE25,
- $DE28C360,
- $DE5AA658,
- $DE8C6707,
- $DEBE0563,
- $DEEF8167,
- $DF20DB09,
- $DF521242,
- $DF83270B,
- $DFB4195C,
- $DFE4E92D,
- $E0159678,
- $E0462134,
- $E076895A,
- $E0A6CEE2,
- $E0D6F1C6,
- $E106F1FD,
- $E136CF81,
- $E1668A4A,
- $E1962250,
- $E1C5978C,
- $E1F4E9F7,
- $E224198A,
- $E253263D,
- $E2821009,
- $E2B0D6E7,
- $E2DF7AD0,
- $E30DFBBC,
- $E33C59A4,
- $E36A9482,
- $E398AC4D,
- $E3C6A0FF,
- $E3F47291,
- $E42220FC,
- $E44FAC38,
- $E47D143F,
- $E4AA590A,
- $E4D77A91,
- $E50478CE,
- $E53153B9,
- $E55E0B4D,
- $E58A9F81,
- $E5B71050,
- $E5E35DB2,
- $E60F87A0,
- $E63B8E14,
- $E6677106,
- $E6933071,
- $E6BECC4C,
- $E6EA4493,
- $E715993D,
- $E740CA44,
- $E76BD7A2,
- $E796C150,
- $E7C18746,
- $E7EC2980,
- $E816A7F6,
- $E84102A1,
- $E86B397B,
- $E8954C7D,
- $E8BF3BA2,
- $E8E906E2,
- $E912AE37,
- $E93C319B,
- $E9659107,
- $E98ECC75,
- $E9B7E3DE,
- $E9E0D73D,
- $EA09A68A,
- $EA3251C0,
- $EA5AD8D9,
- $EA833BCD,
- $EAAB7A97,
- $EAD39531,
- $EAFB8B94,
- $EB235DBB,
- $EB4B0B9E,
- $EB729539,
- $EB99FA84,
- $EBC13B7B,
- $EBE85816,
- $EC0F5050,
- $EC362422,
- $EC5CD387,
- $EC835E7A,
- $ECA9C4F3,
- $ECD006EC,
- $ECF62461,
- $ED1C1D4B,
- $ED41F1A4,
- $ED67A167,
- $ED8D2C8E,
- $EDB29312,
- $EDD7D4EE,
- $EDFCF21D,
- $EE21EA98,
- $EE46BE5A,
- $EE6B6D5D,
- $EE8FF79C,
- $EEB45D11,
- $EED89DB6,
- $EEFCB986,
- $EF20B07B,
- $EF448290,
- $EF682FBF,
- $EF8BB802,
- $EFAF1B55,
- $EFD259B1,
- $EFF57311,
- $F0186771,
- $F03B36C9,
- $F05DE116,
- $F0806651,
- $F0A2C676,
- $F0C5017F,
- $F0E71767,
- $F1090828,
- $F12AD3BD,
- $F14C7A22,
- $F16DFB50,
- $F18F5744,
- $F1B08DF6,
- $F1D19F64,
- $F1F28B86,
- $F2135259,
- $F233F3D8,
- $F2546FFC,
- $F274C6C2,
- $F294F824,
- $F2B5041D,
- $F2D4EAA8,
- $F2F4ABC1,
- $F3144762,
- $F333BD87,
- $F3530E2B,
- $F3723949,
- $F3913EDB,
- $F3B01EDE,
- $F3CED94D,
- $F3ED6E23,
- $F40BDD5A,
- $F42A26F0,
- $F4484ADD,
- $F466491F,
- $F48421B1,
- $F4A1D48D,
- $F4BF61B0,
- $F4DCC915,
- $F4FA0AB6,
- $F5172691,
- $F5341C9F,
- $F550ECDE,
- $F56D9747,
- $F58A1BD8,
- $F5A67A8B,
- $F5C2B35C,
- $F5DEC647,
- $F5FAB347,
- $F6167A59,
- $F6321B77,
- $F64D969E,
- $F668EBC9,
- $F6841AF5,
- $F69F241C,
- $F6BA073B,
- $F6D4C44E,
- $F6EF5B50,
- $F709CC3E,
- $F7241713,
- $F73E3BCB,
- $F7583A63,
- $F77212D5,
- $F78BC51F,
- $F7A5513C,
- $F7BEB729,
- $F7D7F6E1,
- $F7F11060,
- $F80A03A4,
- $F822D0A6,
- $F83B7765,
- $F853F7DD,
- $F86C5208,
- $F88485E4,
- $F89C936D,
- $F8B47AA0,
- $F8CC3B78,
- $F8E3D5F1,
- $F8FB4A09,
- $F91297BC,
- $F929BF05,
- $F940BFE2,
- $F9579A4F,
- $F96E4E48,
- $F984DBCA,
- $F99B42D2,
- $F9B1835B,
- $F9C79D63,
- $F9DD90E6,
- $F9F35DE1,
- $FA090450,
- $FA1E8430,
- $FA33DD7E,
- $FA491036,
- $FA5E1C55,
- $FA7301D8,
- $FA87C0BC,
- $FA9C58FD,
- $FAB0CA99,
- $FAC5158C,
- $FAD939D2,
- $FAED376A,
- $FB010E50,
- $FB14BE80,
- $FB2847F8,
- $FB3BAAB4,
- $FB4EE6B3,
- $FB61FBF0,
- $FB74EA69,
- $FB87B21A,
- $FB9A5302,
- $FBACCD1D,
- $FBBF2068,
- $FBD14CE1,
- $FBE35284,
- $FBF5314F,
- $FC06E93F,
- $FC187A52,
- $FC29E484,
- $FC3B27D4,
- $FC4C443D,
- $FC5D39BE,
- $FC6E0855,
- $FC7EAFFD,
- $FC8F30B6,
- $FC9F8A7C,
- $FCAFBD4D,
- $FCBFC926,
- $FCCFAE05,
- $FCDF6BE8,
- $FCEF02CB,
- $FCFE72AD,
- $FD0DBB8C,
- $FD1CDD64,
- $FD2BD833,
- $FD3AABF8,
- $FD4958B0,
- $FD57DE58,
- $FD663CEF,
- $FD747472,
- $FD8284DF,
- $FD906E34,
- $FD9E306F,
- $FDABCB8D,
- $FDB93F8C,
- $FDC68C6B,
- $FDD3B228,
- $FDE0B0BF,
- $FDED8830,
- $FDFA3878,
- $FE06C196,
- $FE132387,
- $FE1F5E4A,
- $FE2B71DC,
- $FE375E3C,
- $FE432368,
- $FE4EC15E,
- $FE5A381D,
- $FE6587A2,
- $FE70AFEB,
- $FE7BB0F8,
- $FE868AC7,
- $FE913D55,
- $FE9BC8A1,
- $FEA62CAA,
- $FEB0696D,
- $FEBA7EEA,
- $FEC46D1F,
- $FECE3409,
- $FED7D3A9,
- $FEE14BFB,
- $FEEA9D00,
- $FEF3C6B4,
- $FEFCC918,
- $FF05A429,
- $FF0E57E6,
- $FF16E44E,
- $FF1F495F,
- $FF278719,
- $FF2F9D79,
- $FF378C80,
- $FF3F542A,
- $FF46F478,
- $FF4E6D68,
- $FF55BEF9,
- $FF5CE92A,
- $FF63EBF9,
- $FF6AC766,
- $FF717B6F,
- $FF780814,
- $FF7E6D54,
- $FF84AB2C,
- $FF8AC19E,
- $FF90B0A7,
- $FF967847,
- $FF9C187C,
- $FFA19147,
- $FFA6E2A6,
- $FFAC0C97,
- $FFB10F1C,
- $FFB5EA32,
- $FFBA9DD9,
- $FFBF2A10,
- $FFC38ED7,
- $FFC7CC2C,
- $FFCBE210,
- $FFCFD082,
- $FFD39780,
- $FFD7370B,
- $FFDAAF21,
- $FFDDFFC3,
- $FFE128F0,
- $FFE42AA6,
- $FFE704E7,
- $FFE9B7B1,
- $FFEC4304,
- $FFEEA6E0,
- $FFF0E344,
- $FFF2F82F,
- $FFF4E5A2,
- $FFF6AB9D,
- $FFF84A1E,
- $FFF9C126,
- $FFFB10B5,
- $FFFC38CA,
- $FFFD3965,
- $FFFE1286,
- $FFFEC42C,
- $FFFF4E59,
- $FFFFB10B,
- $FFFFEC43,
- $100000000
- );
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/VGSHandlers.inc
--- a/hedgewars/VGSHandlers.inc Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/VGSHandlers.inc Tue Jan 04 12:53:46 2011 +0100
@@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*)
procedure doStepFlake(Gear: PVisualGear; Steps: Longword);
-var sign: float;
+var sign: real;
begin
if vobCount = 0 then exit;
@@ -24,14 +24,23 @@
with Gear^ do
begin
inc(FrameTicks, Steps);
- if FrameTicks > vobFrameTicks then
+ if not SuddenDeathDmg and (FrameTicks > vobFrameTicks) then
begin
dec(FrameTicks, vobFrameTicks);
inc(Frame);
if Frame = vobFramesCount then Frame:= 0
+ end
+ else if SuddenDeathDmg and (FrameTicks > vobSDFrameTicks) then
+ begin
+ dec(FrameTicks, vobSDFrameTicks);
+ inc(Frame);
+ if Frame = vobSDFramesCount then Frame:= 0
end;
X:= X + (cWindSpeedf * 200 + dX + tdX) * Steps;
- Y:= Y + (dY + tdY + cGravityf * vobFallSpeed) * Steps;
+ if SuddenDeathDmg then
+ Y:= Y + (dY + tdY + cGravityf * vobSDFallSpeed) * Steps
+ else
+ Y:= Y + (dY + tdY + cGravityf * vobFallSpeed) * Steps;
Angle:= Angle + dAngle * Steps;
if Angle > 360 then
Angle:= Angle - 360
@@ -59,8 +68,8 @@
begin
if round(X) < cLeftScreenBorder then X:= X + cScreenSpace else
if round(X) > cRightScreenBorder then X:= X - cScreenSpace;
- // if round(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + float(25); // For if flag is set for flakes rising upwards?
- if round(Y) - 75 > LAND_HEIGHT then Y:= Y - float(1024 + 150); // TODO - configure in theme (jellies for example could use limited range)
+ // if round(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + 25.0; // For if flag is set for flakes rising upwards?
+ if round(Y) - 75 > LAND_HEIGHT then Y:= Y - (1024 + 150); // TODO - configure in theme (jellies for example could use limited range)
Timer:= 0;
tdX:= 0;
tdY:= 0
@@ -81,7 +90,7 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepCloud(Gear: PVisualGear; Steps: Longword);
var s: Longword;
- t: float;
+ t: real;
begin
Gear^.X:= Gear^.X + (cWindSpeedf * 750 * Gear^.dX) * Steps;
@@ -444,16 +453,16 @@
begin
if Gear^.Timer > Steps then dec(Gear^.Timer, Steps) else Gear^.Timer:= 0;
-if (PHedgehog(Gear^.Hedgehog)^.Gear <> nil) then
+if (Gear^.Hedgehog^.Gear <> nil) then
begin
- Gear^.X:= PHedgehog(Gear^.Hedgehog)^.Gear^.X.QWordValue/4294967296 + (Gear^.Tex^.w div 2 - Gear^.FrameTicks);
- Gear^.Y:= PHedgehog(Gear^.Hedgehog)^.Gear^.Y.QWordValue/4294967296 - (16 + Gear^.Tex^.h);
+ Gear^.X:= Gear^.Hedgehog^.Gear^.X.QWordValue/4294967296 + (Gear^.Tex^.w div 2 - Gear^.FrameTicks);
+ Gear^.Y:= Gear^.Hedgehog^.Gear^.Y.QWordValue/4294967296 - (16 + Gear^.Tex^.h);
end;
if Gear^.Timer = 0 then
begin
- if PHedgehog(Gear^.Hedgehog)^.SpeechGear = Gear then
- PHedgehog(Gear^.Hedgehog)^.SpeechGear:= nil;
+ if Gear^.Hedgehog^.SpeechGear = Gear then
+ Gear^.Hedgehog^.SpeechGear:= nil;
DeleteVisualGear(Gear)
end;
end;
@@ -462,10 +471,10 @@
begin
Steps:= Steps; // avoid compiler hint
-with PHedgehog(Gear^.Hedgehog)^ do
+with Gear^.Hedgehog^ do
if SpeechGear <> nil then SpeechGear^.Timer:= 0;
-PHedgehog(Gear^.Hedgehog)^.SpeechGear:= Gear;
+Gear^.Hedgehog^.SpeechGear:= Gear;
Gear^.Timer:= max(Length(Gear^.Text) * 150, 3000);
@@ -479,7 +488,7 @@
Gear^.doStep:= @doStepSpeechBubbleWork;
-Gear^.Y:= Gear^.Y - float(Gear^.Tex^.h)
+Gear^.Y:= Gear^.Y - Gear^.Tex^.h
end;
////////////////////////////////////////////////////////////////////////////////
@@ -512,7 +521,7 @@
str(Gear^.State, s);
if Gear^.Hedgehog <> nil then
- Gear^.Tex:= RenderStringTex(s, PHedgehog(Gear^.Hedgehog)^.Team^.Clan^.Color, fnt16)
+ Gear^.Tex:= RenderStringTex(s, Gear^.Hedgehog^.Team^.Clan^.Color, fnt16)
else
Gear^.Tex:= RenderStringTex(s, cWhiteColor, fnt16);
@@ -521,7 +530,7 @@
else
Gear^.doStep:= @doStepHealthTagWorkUnderWater;
-Gear^.Y:= Gear^.Y - float(Gear^.Tex^.h);
+Gear^.Y:= Gear^.Y - Gear^.Tex^.h;
if Steps > 1 then Gear^.doStep(Gear, Steps-1);
end;
@@ -558,11 +567,20 @@
procedure doStepExplosion(Gear: PVisualGear; Steps: Longword);
var i: LongWord;
-gX,gY: LongInt;
+ gX,gY: LongInt;
+ vg: PVisualGear;
begin
gX:= round(Gear^.X);
gY:= round(Gear^.Y);
-for i:= 0 to 31 do AddVisualGear(gX, gY, vgtFire);
+for i:= 0 to 31 do
+ begin
+ vg:= AddVisualGear(gX, gY, vgtFire);
+ if vg <> nil then
+ begin
+ vg^.State:= gstTmpFlag;
+ inc(vg^.FrameTicks, vg^.FrameTicks)
+ end
+ end;
for i:= 0 to 8 do AddVisualGear(gX, gY, vgtExplPart);
for i:= 0 to 8 do AddVisualGear(gX, gY, vgtExplPart2);
Gear^.doStep:= @doStepExplosionWork;
@@ -590,12 +608,21 @@
procedure doStepBigExplosion(Gear: PVisualGear; Steps: Longword);
var i: LongWord;
-gX,gY: LongInt;
+ gX,gY: LongInt;
+ vg: PVisualGear;
begin
gX:= round(Gear^.X);
gY:= round(Gear^.Y);
AddVisualGear(gX, gY, vgtSmokeRing);
-for i:= 0 to 46 do AddVisualGear(gX, gY, vgtFire);
+for i:= 0 to 46 do
+ begin
+ vg:= AddVisualGear(gX, gY, vgtFire);
+ if vg <> nil then
+ begin
+ vg^.State:= gstTmpFlag;
+ inc(vg^.FrameTicks, vg^.FrameTicks)
+ end
+ end;
for i:= 0 to 15 do AddVisualGear(gX, gY, vgtExplPart);
for i:= 0 to 15 do AddVisualGear(gX, gY, vgtExplPart2);
Gear^.doStep:= @doStepBigExplosionWork;
@@ -627,3 +654,27 @@
else
dec(Gear^.FrameTicks, Steps);
end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepCircle(Gear: PVisualGear; Steps: Longword);
+var tmp: LongInt;
+ i: LongWord;
+begin
+with Gear^ do
+ if Frame <> 0 then
+ for i:= 1 to Steps do
+ begin
+ inc(FrameTicks);
+ if (FrameTicks mod Frame) = 0 then
+ begin
+ tmp:= Gear^.Tint and $FF;
+ if tdY >= 0 then inc(tmp)
+ else dec(tmp);
+ if tmp < round(dX) then tdY:= 1;
+ if tmp > round(dY) then tdY:= -1;
+ if tmp > 255 then tmp := 255;
+ if tmp < 0 then tmp := 0;
+ Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or tmp
+ end
+ end
+end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/hwLibrary.pas
--- a/hedgewars/hwLibrary.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/hwLibrary.pas Tue Jan 04 12:53:46 2011 +0100
@@ -12,10 +12,9 @@
// these procedures/functions to the PascalImports.h file (also in the "Pascal Sources" group)
// to make these functions available in the C/C++/Objective-C source files
// (add "#include PascalImports.h" near the top of these files if it's not there yet)
-uses cmem, hwengine, PascalExports;
+uses cmem, uVariables, PascalExports, hwengine;
begin
// avoid compiler warnings about units not being used
isTerminated:= isTerminated;
- dummy:= dummy;
end.
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/hwengine.pas
--- a/hedgewars/hwengine.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/hwengine.pas Tue Jan 04 12:53:46 2011 +0100
@@ -30,10 +30,8 @@
{$ENDIF}
uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uKeys, uSound,
- uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions, uMobile, sysutils;
-
-var isTerminated: boolean = false;
- alsoShutdownFrontend: boolean = false;
+ uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions, uMobile,
+ sysutils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted;
{$IFDEF HWLIBRARY}
procedure initEverything(complete:boolean);
@@ -50,16 +48,19 @@
procedure DoTimer(Lag: LongInt);
var s: shortstring;
begin
- if not isPaused then inc(RealTicks, Lag);
+ if isPaused = false then
+ inc(RealTicks, Lag);
case GameState of
gsLandGen: begin
GenMap;
+ ParseCommand('sendlanddigest', true);
GameState:= gsStart;
end;
gsStart: begin
if HasBorder then DisableSomeWeapons;
AddClouds;
+ AddFlakes;
AssignHHCoords;
AddMiscGears;
StoreLoad;
@@ -98,6 +99,7 @@
gsExit: begin
isTerminated:= true;
end;
+ gsSuspend: exit;
end;
{$IFDEF SDL13}
@@ -105,12 +107,13 @@
{$ELSE}
SDL_GL_SwapBuffers();
{$ENDIF}
- // not going to make captures on the iPhone
+
if flagMakeCapture then
begin
flagMakeCapture:= false;
s:= 'hw_' + FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now()) + inttostr(GameTicks);
WriteLnToConsole('Saving ' + s + '...');
+ playSound(sndShutter);
MakeScreenshot(s);
//SDL_SaveBMP_RW(SDLPrimSurface, SDL_RWFromFile(Str2PChar(s), 'wb'), 1)
end;
@@ -123,7 +126,6 @@
FreeActionsList();
StoreRelease();
ControllerClose();
- SendKB();
CloseIPC();
TTF_Quit();
{$IFDEF SDL13}
@@ -147,19 +149,16 @@
begin
case event.type_ of
SDL_KEYDOWN: if GameState = gsChat then
-{$IFDEF IPHONEOS}
+{$IFDEF SDL13}
// sdl on iphone supports only ashii keyboards and the unicode field is deprecated in sdl 1.3
KeyPressChat(event.key.keysym.sym);
+ SDL_WINDOWEVENT:
+ if event.wevent.event = SDL_WINDOWEVENT_SHOWN then
+ cHasFocus:= true;
{$ELSE}
KeyPressChat(event.key.keysym.unicode);
SDL_MOUSEBUTTONDOWN: if event.button.button = SDL_BUTTON_WHEELDOWN then uKeys.wheelDown:= true;
SDL_MOUSEBUTTONUP: if event.button.button = SDL_BUTTON_WHEELUP then uKeys.wheelUp:= true;
-{$ENDIF}
-{$IFDEF SDL13}
- SDL_WINDOWEVENT:
- if event.wevent.event = SDL_WINDOWEVENT_SHOWN then
- cHasFocus:= true;
-{$ELSE}
SDL_ACTIVEEVENT:
if (event.active.state and SDL_APPINPUTFOCUS) <> 0 then
cHasFocus:= event.active.gain = 1;
@@ -169,8 +168,8 @@
SDL_JOYBUTTONDOWN: ControllerButtonEvent(event.jbutton.which, event.jbutton.button, true);
SDL_JOYBUTTONUP: ControllerButtonEvent(event.jbutton.which, event.jbutton.button, false);
SDL_QUITEV: isTerminated:= true
- end; // end case event.type_
- end; // end while SDL_PollEvent(@event) <> 0
+ end; //end case event.type_ of
+ end; //end while SDL_PollEvent(@event) <> 0 do
if isTerminated = false then
begin
@@ -319,10 +318,16 @@
Randomize();
// uConsts does not need initialization as they are all consts
+ uUtils.initModule;
uMisc.initModule;
+ uVariables.initModule;
uConsole.initModule; // MUST happen after uMisc
+ uCommands.initModule;
+ uCommandHandlers.initModule;
uLand.initModule;
+ uLandPainted.initModule;
+
uIO.initModule;
if complete then
@@ -351,6 +356,7 @@
uTeams.initModule;
uVisualGears.initModule;
uWorld.initModule;
+ uCaptions.initModule;
end;
end;
@@ -358,6 +364,7 @@
begin
if complete then
begin
+ uCaptions.freeModule;
uWorld.freeModule;
uVisualGears.freeModule;
uTeams.freeModule;
@@ -387,7 +394,11 @@
uIO.freeModule; //stub
uLand.freeModule;
+ uCommandHandlers.freeModule;
+ uCommands.freeModule;
uConsole.freeModule;
+ uVariables.freeModule;
+ uUtils.freeModule;
uMisc.freeModule; // uMisc closes the debug log.
end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uAI.pas
--- a/hedgewars/uAI.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uAI.pas Tue Jan 04 12:53:46 2011 +0100
@@ -29,8 +29,9 @@
procedure FreeActionsList;
implementation
-uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc,
- uAmmos, uConsole, SysUtils{$IFDEF UNIX}, cthreads{$ENDIF};
+uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions,
+ uAmmos, SysUtils{$IFDEF UNIX}, cthreads{$ENDIF}, uTypes,
+ uVariables, uCommands, uUtils, uDebug;
var BestActions: TActions;
CanUseAmmo: array [TAmmoType] of boolean;
@@ -65,7 +66,7 @@
Score, i: LongInt;
a, aa: TAmmoType;
begin
-BotLevel:= PHedgehog(Me^.Hedgehog)^.BotLevel;
+BotLevel:= Me^.Hedgehog^.BotLevel;
for i:= 0 to Pred(Targets.Count) do
if (Targets.ar[i].Score >= 0) and (not StopThinking) then
@@ -194,18 +195,18 @@
Actions.Pos:= 0;
Actions.Score:= 0;
Stack.Count:= 0;
-BotLevel:= PHedgehog(Me^.Hedgehog)^.BotLevel;
+BotLevel:= Me^.Hedgehog^.BotLevel;
tmp:= random(2) + 1;
Push(0, Actions, Me^, tmp);
Push(0, Actions, Me^, tmp xor 3);
-if (Me^.State and gstAttacked) = 0 then maxticks:= max(0, TurnTimeLeft - 5000 - LongWord(4000 * BotLevel))
+if (Me^.State and gstAttacked) = 0 then maxticks:= Max(0, TurnTimeLeft - 5000 - LongWord(4000 * BotLevel))
else maxticks:= TurnTimeLeft;
if (Me^.State and gstAttacked) = 0 then TestAmmos(Actions, Me, false);
BestRate:= RatePlace(Me);
-BaseRate:= max(BestRate, 0);
+BaseRate:= Max(BestRate, 0);
while (Stack.Count > 0) and (not StopThinking) and (GameFlags and gfArtillery = 0) do
begin
@@ -321,7 +322,7 @@
FillBonuses((Me^.State and gstAttacked) <> 0);
for a:= Low(TAmmoType) to High(TAmmoType) do
- CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and HHHasAmmo(PHedgehog(Me^.Hedgehog)^, a);
+ CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and HHHasAmmo(Me^.Hedgehog^, a);
{$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
BeginThread(@Think, Me, ThinkThread)
end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uAIActions.pas
--- a/hedgewars/uAIActions.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uAIActions.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,7 +20,7 @@
unit uAIActions;
interface
-uses uGears, uFloat;
+uses uFloat, uTypes;
const MAXACTIONS = 96;
aia_none = 0;
@@ -62,7 +62,7 @@
procedure ProcessAction(var Actions: TActions; Me: PGear);
implementation
-uses uMisc, uConsts, uConsole, uAIMisc, uAI, uAmmos;
+uses uAIMisc, uAI, uAmmos, uVariables, uCommands, uUtils, uDebug, uIO;
const ActionIdToStr: array[0..6] of string[16] = (
{aia_none} '',
@@ -95,8 +95,8 @@
else begin
WriteLnToConsole('AI action: '+SpecActionIdToStr[Action.Action]);
if (Action.Action = aia_WaitXL) or (Action.Action = aia_WaitXR) then
- WriteLnToConsole('AI action Wait X = '+inttostr(Action.Param)+', current X = '+inttostr(hwRound(Me^.X)))
- else if (Action.Action = aia_AwareExpl) then WriteLnToConsole('Aware X = ' + inttostr(Action.X) + ', Y = ' + inttostr(Action.Y));
+ WriteLnToConsole('AI action Wait X = '+IntToStr(Action.Param)+', current X = '+IntToStr(hwRound(Me^.X)))
+ else if (Action.Action = aia_AwareExpl) then WriteLnToConsole('Aware X = ' + IntToStr(Action.X) + ', Y = ' + IntToStr(Action.Y));
end
end;
{$ENDIF}
@@ -199,7 +199,7 @@
aim_push: s:= '+' + s;
aim_release: s:= '-' + s;
end
- else if Param <> 0 then s:= s + ' ' + inttostr(Param);
+ else if Param <> 0 then s:= s + ' ' + IntToStr(Param);
ParseCommand(s, true)
end
end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uAIAmmoTests.pas
--- a/hedgewars/uAIAmmoTests.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uAIAmmoTests.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,7 +20,7 @@
unit uAIAmmoTests;
interface
-uses SDLh, uGears, uConsts, uFloat;
+uses SDLh, uConsts, uFloat, uTypes;
const amtest_OnTurn = $00000001;
type TAttackParams = record
@@ -31,6 +31,7 @@
end;
function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
function TestClusterBomb(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
@@ -102,13 +103,14 @@
(proc: @TestGrenade; flags: 0), // amSMine
(proc: @TestFirePunch; flags: 0), // amHammer
(proc: nil; flags: 0), // amResurrector
- (proc: nil; flags: 0) // amDrillStrike
+ (proc: nil; flags: 0),// amDrillStrike
+ (proc: @TestSnowball; flags: 0) // amSnowball
);
const BadTurn = Low(LongInt) div 4;
implementation
-uses uMisc, uAIMisc, uLand;
+uses uAIMisc, uVariables, uUtils;
function Metric(x1, y1, x2, y2: LongInt): LongInt;
begin
@@ -172,6 +174,63 @@
TestBazooka:= valueResult
end;
+function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+var Vx, Vy, r: hwFloat;
+ rTime: LongInt;
+ Score, EX, EY: LongInt;
+ valueResult: LongInt;
+
+ function CheckTrace: LongInt;
+ var x, y, dX, dY: hwFloat;
+ t: LongInt;
+ value: LongInt;
+ begin
+ x:= Me^.X;
+ y:= Me^.Y;
+ dX:= Vx;
+ dY:= -Vy;
+ t:= rTime;
+ repeat
+ x:= x + dX;
+ y:= y + dY;
+ dX:= dX + cWindSpeed;
+ dY:= dY + cGravity;
+ dec(t)
+ until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t <= 0);
+ EX:= hwRound(x);
+ EY:= hwRound(y);
+ value:= RateExplosion(Me, EX, EY, 5);
+ if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
+ CheckTrace:= value;
+ end;
+
+begin
+ap.Time:= 0;
+rTime:= 350;
+ap.ExplR:= 0;
+valueResult:= BadTurn;
+repeat
+ rTime:= rTime + 300 + Level * 50 + random(300);
+ Vx:= - cWindSpeed * rTime * _0_5 + (int2hwFloat(Targ.X + AIrndSign(2)) - Me^.X) / int2hwFloat(rTime);
+ Vy:= cGravity * rTime * _0_5 - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(rTime);
+ r:= Distance(Vx, Vy);
+ if not (r > _1) then
+ begin
+ Score:= CheckTrace;
+ if valueResult <= Score then
+ begin
+ ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
+ ap.Power:= hwRound(r * cMaxPower) - random((Level - 1) * 17 + 1);
+ ap.ExplR:= 100;
+ ap.ExplX:= EX;
+ ap.ExplY:= EY;
+ valueResult:= Score
+ end;
+ end
+until (rTime > 4250);
+TestSnowball:= valueResult
+end;
+
function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
var Vx, Vy, r: hwFloat;
Score, EX, EY, valueResult: LongInt;
@@ -539,7 +598,7 @@
or (y.Round > LongWord(LAND_HEIGHT))
or (d > 200);
-if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then valueResult:= max(0, (4 - d div 50) * 7 * 1024)
+if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then valueResult:= Max(0, (4 - d div 50) * 7 * 1024)
else valueResult:= BadTurn;
TestDesertEagle:= valueResult
end;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uAIMisc.pas
--- a/hedgewars/uAIMisc.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uAIMisc.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,7 +20,7 @@
unit uAIMisc;
interface
-uses SDLh, uConsts, uGears, uFloat;
+uses SDLh, uConsts, uFloat, uTypes;
const MAXBONUS = 1024;
@@ -68,8 +68,7 @@
end;
implementation
-uses uTeams, uMisc, uLand, uCollisions;
-
+uses uCollisions, uVariables, uUtils, uDebug;
const KillScore = 200;
@@ -131,7 +130,7 @@
begin
bonuses.Count:= 0;
-MyClan:= PHedgehog(ThinkingHH^.Hedgehog)^.Team^.Clan;
+MyClan:= ThinkingHH^.Hedgehog^.Team^.Clan;
Gear:= GearsList;
while Gear <> nil do
begin
@@ -150,7 +149,7 @@
AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 60, -25)
else
if isAfterAttack and (ThinkingHH^.Hedgehog <> Gear^.Hedgehog) then
- if (MyClan = PHedgehog(Gear^.Hedgehog)^.Team^.Clan) then
+ if (MyClan = Gear^.Hedgehog^.Team^.Clan) then
AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -3) // hedgehog-friend
else
AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, 3)
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uAmmos.pas
--- a/hedgewars/uAmmos.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uAmmos.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,7 +20,7 @@
unit uAmmos;
interface
-uses uConsts, uTeams, uStats;
+uses uConsts, uTypes;
procedure initModule;
procedure freeModule;
@@ -47,7 +47,7 @@
var StoreCnt: Longword;
implementation
-uses uMisc, uGears, uWorld, uLocale, uConsole, uMobile;
+uses uLocale, uMobile, uVariables, uCommands, uUtils, uCaptions, uDebug;
type TAmmoCounts = array[TAmmoType] of Longword;
var StoresList: array[0..Pred(cMaxHHs)] of PHHAmmo;
@@ -68,20 +68,7 @@
begin
TryDo(mi[Ammoz[a].Slot] <= cMaxSlotAmmoIndex, 'Ammo slot overflow', true);
Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]]:= Ammoz[a].Ammo;
- with Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]] do
- begin
- Count:= cnts[a];
- if (TotalRounds < 0) and ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then Count:= AMMO_INFINITE;
- end;
- inc(mi[Ammoz[a].Slot])
- end
- else if (TotalRounds < 0) and ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then
- begin
- TryDo(mi[Ammoz[a].Slot] <= cMaxSlotAmmoIndex, 'Ammo slot overflow', true);
- Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]]:= Ammoz[a].Ammo;
-
- Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]].Count:= AMMO_INFINITE;
-
+ with Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]] do Count:= cnts[a];
inc(mi[Ammoz[a].Slot])
end
end
@@ -107,7 +94,6 @@
Ammoz[a].Probability:= probability[byte(ammoProbability[ord(a)]) - byte('0')];
Ammoz[a].SkipTurns:= (byte(ammoDelay[ord(a)]) - byte('0'));
Ammoz[a].NumberInCase:= (byte(ammoReinforcement[ord(a)]) - byte('0'));
- if (TrainingFlags and tfIgnoreDelays) <> 0 then Ammoz[a].SkipTurns:= 0;
cnt:= byte(ammoLoadout[ord(a)]) - byte('0');
// avoid things we already have infinite number
if cnt = 9 then
@@ -134,10 +120,14 @@
if ((GameFlags and gfPlaceHog) <> 0) and
(a <> amTeleport) and (a <> amSkip) and
- (Ammoz[a].SkipTurns < 10000) then inc(Ammoz[a].SkipTurns,10000)
+ (Ammoz[a].SkipTurns < 10000) then inc(Ammoz[a].SkipTurns,10000);
+ if ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then ammos[a]:= AMMO_INFINITE
end
else ammos[a]:= AMMO_INFINITE;
- InitialCounts[Pred(StoreCnt)][a]:= ammos[a];
+ if ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then
+ InitialCounts[Pred(StoreCnt)][a]:= cnt
+ else
+ InitialCounts[Pred(StoreCnt)][a]:= ammos[a];
end;
FillAmmoStore(StoresList[Pred(StoreCnt)], ammos)
end;
@@ -329,15 +319,12 @@
with CurWeapon^ do
begin
- if AmmoType <> amNothing then
- begin
- s:= trammo[Ammoz[AmmoType].NameId];
- if (Count <> AMMO_INFINITE) and not (Hedgehog.Team^.ExtDriven or (Hedgehog.BotLevel > 0)) then
- s:= s + ' (' + IntToStr(Count) + ')';
- if (Propz and ammoprop_Timerable) <> 0 then
- s:= s + ', ' + inttostr(Timer div 1000) + ' ' + trammo[sidSeconds];
- AddCaption(s, Team^.Clan^.Color, capgrpAmmoinfo);
- end;
+ s:= trammo[Ammoz[AmmoType].NameId];
+ if (Count <> AMMO_INFINITE) and not (Hedgehog.Team^.ExtDriven or (Hedgehog.BotLevel > 0)) then
+ s:= s + ' (' + IntToStr(Count) + ')';
+ if (Propz and ammoprop_Timerable) <> 0 then
+ s:= s + ', ' + IntToStr(Timer div 1000) + ' ' + trammo[sidSeconds];
+ AddCaption(s, Team^.Clan^.Color, capgrpAmmoinfo);
if (Propz and ammoprop_NeedTarget) <> 0
then begin
Gear^.State:= Gear^.State or gstHHChooseTarget;
@@ -427,8 +414,22 @@
if Ammoz[a].SkipTurns >= 10000 then dec(Ammoz[a].SkipTurns,10000)
end;
+
+
+procedure chAddAmmoStore(var descr: shortstring);
+begin
+descr:= ''; // avoid compiler hint
+AddAmmoStore
+end;
+
procedure initModule;
begin
+ RegisterVariable('ammloadt', vtCommand, @SetAmmoLoadout, false);
+ RegisterVariable('ammdelay', vtCommand, @SetAmmoDelay, false);
+ RegisterVariable('ammprob', vtCommand, @SetAmmoProbability, false);
+ RegisterVariable('ammreinf', vtCommand, @SetAmmoReinforcement, false);
+ RegisterVariable('ammstore', vtCommand, @chAddAmmoStore , false);
+
StoreCnt:= 0;
ammoLoadout:= '';
ammoProbability:= '';
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uCaptions.pas
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uCaptions.pas Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,72 @@
+unit uCaptions;
+
+interface
+uses uTypes;
+
+procedure AddCaption(s: shortstring; Color: Longword; Group: TCapGroup);
+procedure DrawCaptions;
+
+procedure initModule;
+procedure freeModule;
+
+implementation
+uses uTextures, uRenderUtils, uVariables, uRender, uConsts;
+
+type TCaptionStr = record
+ Tex: PTexture;
+ EndTime: LongWord;
+ end;
+var
+ Captions: array[TCapGroup] of TCaptionStr;
+
+procedure AddCaption(s: shortstring; Color: Longword; Group: TCapGroup);
+begin
+ if Captions[Group].Tex <> nil then
+ FreeTexture(Captions[Group].Tex);
+ Captions[Group].Tex:= nil;
+
+ Captions[Group].Tex:= RenderStringTex(s, Color, fntBig);
+
+ case Group of
+ capgrpGameState: Captions[Group].EndTime:= RealTicks + 2200
+ else
+ Captions[Group].EndTime:= RealTicks + 1400 + LongWord(Captions[Group].Tex^.w) * 3;
+ end;
+end;
+
+procedure DrawCaptions;
+var
+ grp: TCapGroup;
+ offset: LongInt;
+begin
+{$IFDEF IPHONEOS}
+ offset:= 40;
+{$ELSE}
+ offset:= 8;
+{$ENDIF}
+
+ for grp:= Low(TCapGroup) to High(TCapGroup) do
+ with Captions[grp] do
+ if Tex <> nil then
+ begin
+ DrawCentered(0, offset, Tex);
+ inc(offset, Tex^.h + 2);
+ if EndTime <= RealTicks then
+ begin
+ FreeTexture(Tex);
+ Tex:= nil;
+ EndTime:= 0
+ end;
+ end;
+end;
+
+procedure initModule;
+begin
+ FillChar(Captions, sizeof(Captions), 0)
+end;
+
+procedure freeModule;
+begin
+end;
+
+end.
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uChat.pas
--- a/hedgewars/uChat.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uChat.pas Tue Jan 04 12:53:46 2011 +0100
@@ -34,7 +34,7 @@
showAll: boolean;
implementation
-uses uMisc, uStore, uConsts, SDLh, uConsole, uKeys, uTeams;
+uses SDLh, uKeys, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO;
const MaxStrIndex = 27;
@@ -181,44 +181,42 @@
visibleCount:= cnt;
end;
+procedure SendHogSpeech(s: shortstring);
+begin
+SendIPC('h' + s);
+ParseCommand('/hogsay '+s, true)
+end;
+
procedure AcceptChatString(s: shortstring);
var i: TWave;
-
+ c, t: LongInt;
+ x: byte;
begin
-// "Make hedgehog say something"
-if (s[1] = '"') and (s[Length(s)] = '"') then
+t:= LocalTeam;
+x:= 0;
+if (s[1] = '"') and (s[Length(s)] = '"') then x:= 1
+else if (s[1] = '''') and (s[Length(s)] = '''') then x:= 2
+else if (s[1] = '-') and (s[Length(s)] = '-') then x:= 3;
+if not CurrentTeam^.ExtDriven and (x <> 0) then
+ for c:= 0 to Pred(TeamsCount) do
+ if (TeamsArray[c] = CurrentTeam) then t:= c;
+
+if x <> 0 then
begin
- if CurrentTeam^.ExtDriven then
+ if t = -1 then
ParseCommand('/say ' + copy(s, 2, Length(s)-2), true)
else
- ParseCommand('/hogsay '#1 + copy(s, 2, Length(s)-2), true);
+ SendHogSpeech(char(x) + char(t) + copy(s, 2, Length(s)-2));
exit
end;
-// 'Make hedgehog think something'
-if (s[1] = '''') and (s[Length(s)] = '''') then
- begin
- if CurrentTeam^.ExtDriven then
- ParseCommand('/say ' + copy(s, 2, Length(s)-2), true)
- else
- ParseCommand('/hogsay '#2 + copy(s, 2, Length(s)-2), true);
- exit
- end;
-// -Make hedgehog yell something-
-if (s[1] = '-') and (s[Length(s)] = '-') then
- begin
- if CurrentTeam^.ExtDriven then
- ParseCommand('/say ' + copy(s, 2, Length(s)-2), true)
- else
- ParseCommand('/hogsay '#3 + copy(s, 2, Length(s)-2), true);
- exit
- end;
+
// These 3 are same as above, only are to make the hedgehog say it on next attack
if (s[1] = '/') and (copy(s, 1, 5) = '/hsa ') then
begin
if CurrentTeam^.ExtDriven then
ParseCommand('/say ' + copy(s, 6, Length(s)-5), true)
else
- ParseCommand('/hogsay '#4 + copy(s, 6, Length(s)-5), true);
+ SendHogSpeech(#4 + copy(s, 6, Length(s)-5));
exit
end;
if (s[1] = '/') and (copy(s, 1, 5) = '/hta ') then
@@ -226,7 +224,7 @@
if CurrentTeam^.ExtDriven then
ParseCommand('/say ' + copy(s, 6, Length(s)-5), true)
else
- ParseCommand('/hogsay '#5 + copy(s, 6, Length(s)-5), true);
+ SendHogSpeech(#5 + copy(s, 6, Length(s)-5));
exit
end;
if (s[1] = '/') and (copy(s, 1, 5) = '/hya ') then
@@ -234,7 +232,7 @@
if CurrentTeam^.ExtDriven then
ParseCommand('/say ' + copy(s, 6, Length(s)-5), true)
else
- ParseCommand('/hogsay '#6 + copy(s, 6, Length(s)-5), true);
+ SendHogSpeech(#6 + copy(s, 6, Length(s)-5));
exit
end;
@@ -308,8 +306,64 @@
end
end;
+procedure chChatMessage(var s: shortstring);
+begin
+ AddChatString(s)
+end;
+
+procedure chSay(var s: shortstring);
+begin
+ SendIPC('s' + s);
+
+ if copy(s, 1, 4) = '/me ' then
+ s:= #2'* ' + UserNick + ' ' + copy(s, 5, Length(s) - 4)
+ else
+ s:= #1 + UserNick + ': ' + s;
+
+ AddChatString(s)
+end;
+
+procedure chTeamSay(var s: shortstring);
+begin
+ SendIPC('b' + s);
+
+ s:= #4 + '[Team] ' + UserNick + ': ' + s;
+
+ AddChatString(s)
+end;
+
+procedure chHistory(var s: shortstring);
+begin
+ s:= s; // avoid compiler hint
+ uChat.showAll:= not uChat.showAll
+end;
+
+procedure chChat(var s: shortstring);
+begin
+ s:= s; // avoid compiler hint
+ GameState:= gsChat;
+ if length(s) = 0 then
+ KeyPressChat(27)
+ else
+ begin
+ KeyPressChat(27);
+ KeyPressChat(47);
+ KeyPressChat(116);
+ KeyPressChat(101);
+ KeyPressChat(97);
+ KeyPressChat(109);
+ KeyPressChat(32)
+ end
+end;
+
procedure initModule;
begin
+ RegisterVariable('chatmsg', vtCommand, @chChatMessage, true);
+ RegisterVariable('say', vtCommand, @chSay, true);
+ RegisterVariable('team', vtCommand, @chTeamSay, true);
+ RegisterVariable('history', vtCommand, @chHistory, true );
+ RegisterVariable('chat', vtCommand, @chChat, true );
+
lastStr:= 0;
visibleCount:= 0;
showAll:= false;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uCollisions.pas
--- a/hedgewars/uCollisions.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uCollisions.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,7 +20,7 @@
unit uCollisions;
interface
-uses uGears, uFloat;
+uses uFloat, uTypes;
const cMaxGearArrayInd = 255;
@@ -44,6 +44,7 @@
function TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean;
function TestCollisionYKick(Gear: PGear; Dir: LongInt): boolean;
+function TestCollisionX(Gear: PGear; Dir: LongInt): boolean;
function TestCollisionY(Gear: PGear; Dir: LongInt): boolean;
function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): boolean;
@@ -52,7 +53,7 @@
function calcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): Boolean;
implementation
-uses uMisc, uConsts, uLand, uLandGraphics;
+uses uConsts, uLandGraphics, uVariables, uDebug;
type TCollisionEntry = record
X, Y, Radius: LongInt;
@@ -289,6 +290,24 @@
Gear^.X:= Gear^.X - ShiftX;
Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY)
end;
+function TestCollisionX(Gear: PGear; Dir: LongInt): boolean;
+var x, y, i: LongInt;
+begin
+x:= hwRound(Gear^.X);
+if Dir < 0 then x:= x - Gear^.Radius
+ else x:= x + Gear^.Radius;
+if (x and LAND_WIDTH_MASK) = 0 then
+ begin
+ y:= hwRound(Gear^.Y) - Gear^.Radius + 1;
+ i:= y + Gear^.Radius * 2 - 2;
+ repeat
+ if (y and LAND_HEIGHT_MASK) = 0 then
+ if Land[y, x] > 255 then exit(true);
+ inc(y)
+ until (y > i);
+ end;
+TestCollisionX:= false
+end;
function TestCollisionY(Gear: PGear; Dir: LongInt): boolean;
var x, y, i: LongInt;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uCommandHandlers.pas
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uCommandHandlers.pas Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,617 @@
+{$INCLUDE "options.inc"}
+unit uCommandHandlers;
+
+interface
+
+procedure initModule;
+procedure freeModule;
+
+implementation
+uses uCommands, uTypes, uVariables, uIO, uDebug, uConsts, uScript, uUtils, SDLh, uRandom;
+
+procedure chGenCmd(var s: shortstring);
+begin
+case s[1] of
+ 'R': if ReadyTimeLeft > 1 then
+ begin
+ ReadyTimeLeft:= 1;
+ if not CurrentTeam^.ExtDriven then SendIPC('c'+s);
+ end
+ end
+end;
+
+procedure chQuit(var s: shortstring);
+const prevGState: TGameState = gsConfirm;
+begin
+s:= s; // avoid compiler hint
+if GameState <> gsConfirm then
+ begin
+ prevGState:= GameState;
+ GameState:= gsConfirm
+ end else
+ GameState:= prevGState
+end;
+
+procedure chConfirm(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if GameState = gsConfirm then
+ begin
+ SendIPC('Q');
+ GameState:= gsExit
+ end
+else
+ ParseCommand('chat team', true);
+end;
+
+procedure chCheckProto(var s: shortstring);
+var i, c: LongInt;
+begin
+if isDeveloperMode then
+begin
+val(s, i, c);
+if (c <> 0) or (i = 0) then exit;
+TryDo(i <= cNetProtoVersion, 'Protocol version mismatch: engine is too old', true);
+TryDo(i >= cNetProtoVersion, 'Protocol version mismatch: engine is too new', true)
+end
+end;
+
+procedure chTeamLocal(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if not isDeveloperMode then exit;
+if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/rdriven"', true);
+CurrentTeam^.ExtDriven:= true
+end;
+
+procedure chGrave(var s: shortstring);
+begin
+if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/grave"', true);
+if s[1]='"' then Delete(s, 1, 1);
+if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
+CurrentTeam^.GraveName:= s
+end;
+
+procedure chFort(var s: shortstring);
+begin
+if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/fort"', true);
+if s[1]='"' then Delete(s, 1, 1);
+if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
+CurrentTeam^.FortName:= s
+end;
+
+procedure chFlag(var s: shortstring);
+begin
+if CurrentTeam = nil then OutError(errmsgIncorrectUse + ' "/flag"', true);
+if s[1]='"' then Delete(s, 1, 1);
+if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
+CurrentTeam^.flag:= s
+end;
+
+procedure chScript(var s: shortstring);
+begin
+if s[1]='"' then Delete(s, 1, 1);
+if s[byte(s[0])]='"' then Delete(s, byte(s[0]), 1);
+ScriptLoad(s)
+end;
+
+procedure chSetHat(var s: shortstring);
+begin
+if (not isDeveloperMode) or (CurrentTeam = nil) then exit;
+with CurrentTeam^ do
+ begin
+ if not CurrentHedgehog^.King then
+ if (s = '') or
+ (((GameFlags and gfKing) <> 0) and (s = 'crown')) or
+ ((Length(s) > 39) and (Copy(s,1,8) = 'Reserved') and (Copy(s,9,32) <> PlayerHash)) then
+ CurrentHedgehog^.Hat:= 'NoHat'
+ else
+ CurrentHedgehog^.Hat:= s
+ end;
+end;
+
+procedure chCurU_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementY:= -1;
+end;
+
+procedure chCurU_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementY:= 0;
+end;
+
+procedure chCurD_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementY:= 1;
+end;
+
+procedure chCurD_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementY:= 0;
+end;
+
+procedure chCurL_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementX:= -1;
+end;
+
+procedure chCurL_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementX:= 0;
+end;
+
+procedure chCurR_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementX:= 1;
+end;
+
+procedure chCurR_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+CursorMovementX:= 0;
+end;
+
+procedure chLeft_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('L');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmLeft and InputMask);
+ ScriptCall('onLeft');
+end;
+
+procedure chLeft_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('l');
+with CurrentHedgehog^.Gear^ do
+ Message:= Message and not (gmLeft and InputMask);
+ ScriptCall('onLeftUp');
+end;
+
+procedure chRight_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('R');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmRight and InputMask);
+ ScriptCall('onRight');
+end;
+
+procedure chRight_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('r');
+with CurrentHedgehog^.Gear^ do
+ Message:= Message and not (gmRight and InputMask);
+ ScriptCall('onRightUp');
+end;
+
+procedure chUp_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('U');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmUp and InputMask);
+ ScriptCall('onUp');
+end;
+
+procedure chUp_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('u');
+with CurrentHedgehog^.Gear^ do
+ Message:= Message and not (gmUp and InputMask);
+ ScriptCall('onUpUp');
+end;
+
+procedure chDown_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('D');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmDown and InputMask);
+ ScriptCall('onDown');
+end;
+
+procedure chDown_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('d');
+with CurrentHedgehog^.Gear^ do
+ Message:= Message and not (gmDown and InputMask);
+ ScriptCall('onDownUp');
+end;
+
+procedure chPrecise_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('Z');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmPrecise and InputMask);
+ ScriptCall('onPrecise');
+end;
+
+procedure chPrecise_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('z');
+with CurrentHedgehog^.Gear^ do
+ Message:= Message and not (gmPrecise and InputMask);
+ ScriptCall('onPreciseUp');
+end;
+
+procedure chLJump(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('j');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmLJump and InputMask);
+ ScriptCall('onLJump');
+end;
+
+procedure chHJump(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('J');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmHJump and InputMask);
+ ScriptCall('onHJump');
+end;
+
+procedure chAttack_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ begin
+ {$IFDEF DEBUGFILE}AddFileLog('/+attack: hedgehog''s Gear^.State = '+inttostr(State));{$ENDIF}
+ if ((State and gstHHDriven) <> 0) then
+ begin
+ FollowGear:= CurrentHedgehog^.Gear;
+ if not CurrentTeam^.ExtDriven then SendIPC('A');
+ Message:= Message or (gmAttack and InputMask);
+ ScriptCall('onAttack');
+ end
+ end
+end;
+
+procedure chAttack_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH then exit;
+with CurrentHedgehog^.Gear^ do
+ begin
+ if not CurrentTeam^.ExtDriven and
+ ((Message and gmAttack) <> 0) then SendIPC('a');
+ Message:= Message and not (gmAttack and InputMask);
+ ScriptCall('onAttackUp');
+ end
+end;
+
+procedure chSwitch(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+if not CurrentTeam^.ExtDriven then SendIPC('S');
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ Message:= Message or (gmSwitch and InputMask);
+ ScriptCall('onSwitch');
+end;
+
+procedure chNextTurn(var s: shortstring);
+begin
+ s:= s; // avoid compiler hint
+ TryDo(AllInactive, '/nextturn called when not all gears are inactive', true);
+
+ if not CurrentTeam^.ExtDriven then SendIPC('N');
+{$IFDEF DEBUGFILE}
+ AddFileLog('Doing SwitchHedgehog: time '+inttostr(GameTicks));
+{$ENDIF}
+end;
+
+procedure chTimer(var s: shortstring);
+begin
+if (s[0] <> #1) or (s[1] < '1') or (s[1] > '5') or CheckNoTeamOrHH then exit;
+
+if not CurrentTeam^.ExtDriven then SendIPC(s);
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ begin
+ Message:= Message or (gmTimer and InputMask);
+ MsgParam:= byte(s[1]) - ord('0');
+ ScriptCall('onTimer');
+ end
+end;
+
+procedure chSlot(var s: shortstring);
+var slot: LongWord;
+begin
+if (s[0] <> #1) or CheckNoTeamOrHH then exit;
+slot:= byte(s[1]) - 49;
+if slot > cMaxSlotIndex then exit;
+if not CurrentTeam^.ExtDriven then SendIPC(char(byte(s[1]) + 79));
+bShowFinger:= false;
+with CurrentHedgehog^.Gear^ do
+ begin
+ Message:= Message or (gmSlot and InputMask);
+ MsgParam:= slot;
+ ScriptCall('onSlot');
+ end
+end;
+
+procedure chSetWeapon(var s: shortstring);
+begin
+ if (s[0] <> #1) or CheckNoTeamOrHH then exit;
+
+ if TAmmoType(s[1]) > High(TAmmoType) then exit;
+
+ if not CurrentTeam^.ExtDriven then SendIPC('w' + s);
+
+ with CurrentHedgehog^.Gear^ do
+ begin
+ Message:= Message or (gmWeapon and InputMask);
+ MsgParam:= byte(s[1]);
+ ScriptCall('onSetWeapon');
+ end;
+end;
+
+procedure chTaunt(var s: shortstring);
+begin
+if (s[0] <> #1) or CheckNoTeamOrHH then exit;
+
+if TWave(s[1]) > High(TWave) then exit;
+
+if not CurrentTeam^.ExtDriven then SendIPC('t' + s);
+
+with CurrentHedgehog^.Gear^ do
+ begin
+ Message:= Message or (gmAnimate and InputMask);
+ MsgParam:= byte(s[1]) ;
+ ScriptCall('onTaunt');
+ end
+end;
+
+procedure chPut(var s: shortstring);
+begin
+ s:= s; // avoid compiler hint
+ doPut(0, 0, false);
+end;
+
+procedure chCapture(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+flagMakeCapture:= true
+end;
+
+procedure chSetMap(var s: shortstring);
+begin
+if isDeveloperMode then
+begin
+Pathz[ptMapCurrent]:= Pathz[ptMaps] + '/' + s;
+InitStepsFlags:= InitStepsFlags or cifMap
+end
+end;
+
+procedure chSetTheme(var s: shortstring);
+begin
+if isDeveloperMode then
+begin
+Pathz[ptCurrTheme]:= Pathz[ptThemes] + '/' + s;
+Theme:= s;
+InitStepsFlags:= InitStepsFlags or cifTheme
+end
+end;
+
+procedure chSetSeed(var s: shortstring);
+begin
+if isDeveloperMode then
+begin
+SetRandomSeed(s);
+cSeed:= s;
+InitStepsFlags:= InitStepsFlags or cifRandomize
+end
+end;
+
+procedure chAmmoMenu(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH then
+ bShowAmmoMenu:= true
+else
+ begin
+ with CurrentTeam^ do
+ with Hedgehogs[CurrHedgehog] do
+ begin
+ bSelected:= false;
+
+ if bShowAmmoMenu then bShowAmmoMenu:= false
+ else if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
+ ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0)) or
+ ((Gear^.State and gstHHDriven) = 0) then else bShowAmmoMenu:= true
+ end;
+ end
+end;
+
+procedure chVol_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+inc(cVolumeDelta, 3)
+end;
+
+procedure chVol_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+dec(cVolumeDelta, 3)
+end;
+
+procedure chFindhh(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if CheckNoTeamOrHH or isPaused then exit;
+bShowFinger:= true;
+FollowGear:= CurrentHedgehog^.Gear
+end;
+
+procedure chPause(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if gameType <> gmtNet then
+ isPaused:= not isPaused;
+SDL_ShowCursor(ord(isPaused))
+end;
+
+procedure chRotateMask(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if ((GameFlags and gfInvulnerable) = 0) then cTagsMask:= cTagsMasks[cTagsMask] else cTagsMask:= cTagsMasksNoHealth[cTagsMask];
+end;
+
+procedure chSpeedup_p(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+isSpeed:= true
+end;
+
+procedure chSpeedup_m(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+isSpeed:= false
+end;
+
+procedure chZoomIn(var s: shortstring);
+begin
+ s:= s; // avoid compiler hint
+ if ZoomValue < cMinZoomLevel then
+ ZoomValue:= ZoomValue + cZoomDelta;
+end;
+
+procedure chZoomOut(var s: shortstring);
+begin
+ s:= s; // avoid compiler hint
+ if ZoomValue > cMaxZoomLevel then
+ ZoomValue:= ZoomValue - cZoomDelta;
+end;
+
+procedure chZoomReset(var s: shortstring);
+begin
+ s:= s; // avoid compiler hint
+ ZoomValue:= cDefaultZoomLevel;
+end;
+
+
+procedure initModule;
+begin
+//////// Begin top sorted by freq analysis not including chatmsg
+ RegisterVariable('+right' , vtCommand, @chRight_p , false);
+ RegisterVariable('-right' , vtCommand, @chRight_m , false);
+ RegisterVariable('+up' , vtCommand, @chUp_p , false);
+ RegisterVariable('-up' , vtCommand, @chUp_m , false);
+ RegisterVariable('+left' , vtCommand, @chLeft_p , false);
+ RegisterVariable('-left' , vtCommand, @chLeft_m , false);
+ RegisterVariable('+attack' , vtCommand, @chAttack_p , false);
+ RegisterVariable('+down' , vtCommand, @chDown_p , false);
+ RegisterVariable('-down' , vtCommand, @chDown_m , false);
+ RegisterVariable('hjump' , vtCommand, @chHJump , false);
+ RegisterVariable('ljump' , vtCommand, @chLJump , false);
+ RegisterVariable('nextturn', vtCommand, @chNextTurn , false);
+ RegisterVariable('-attack' , vtCommand, @chAttack_m , false);
+ RegisterVariable('slot' , vtCommand, @chSlot , false);
+ RegisterVariable('setweap' , vtCommand, @chSetWeapon , false);
+//////// End top by freq analysis
+ RegisterVariable('gencmd' , vtCommand, @chGenCmd , false);
+ RegisterVariable('flag' , vtCommand, @chFlag , false);
+ RegisterVariable('script' , vtCommand, @chScript , false);
+ RegisterVariable('proto' , vtCommand, @chCheckProto , true );
+ RegisterVariable('spectate', vtBoolean, @fastUntilLag , false);
+ RegisterVariable('capture' , vtCommand, @chCapture , true );
+ RegisterVariable('rotmask' , vtCommand, @chRotateMask , true );
+ RegisterVariable('rdriven' , vtCommand, @chTeamLocal , false);
+ RegisterVariable('map' , vtCommand, @chSetMap , false);
+ RegisterVariable('theme' , vtCommand, @chSetTheme , false);
+ RegisterVariable('seed' , vtCommand, @chSetSeed , false);
+ RegisterVariable('template_filter', vtLongInt, @cTemplateFilter, false);
+ RegisterVariable('mapgen' , vtLongInt, @cMapGen , false);
+ RegisterVariable('maze_size',vtLongInt, @cMazeSize , false);
+ RegisterVariable('delay' , vtLongInt, @cInactDelay , false);
+ RegisterVariable('ready' , vtLongInt, @cReadyDelay , false);
+ RegisterVariable('casefreq', vtLongInt, @cCaseFactor , false);
+ RegisterVariable('healthprob', vtLongInt, @cHealthCaseProb, false);
+ RegisterVariable('hcaseamount', vtLongInt, @cHealthCaseAmount, false);
+ RegisterVariable('sd_turns', vtLongInt, @cSuddenDTurns , false);
+ RegisterVariable('waterrise', vtLongInt, @cWaterRise , false);
+ RegisterVariable('healthdec', vtLongInt, @cHealthDecrease, false);
+ RegisterVariable('damagepct',vtLongInt, @cDamagePercent , false);
+ RegisterVariable('ropepct' , vtLongInt, @cRopePercent , false);
+ RegisterVariable('minedudpct',vtLongInt,@cMineDudPercent, false);
+ RegisterVariable('minesnum', vtLongInt, @cLandMines , false);
+ RegisterVariable('explosives',vtLongInt,@cExplosives , false);
+ RegisterVariable('gmflags' , vtLongInt, @GameFlags , false);
+ RegisterVariable('turntime', vtLongInt, @cHedgehogTurnTime, false);
+ RegisterVariable('minestime',vtLongInt, @cMinesTime , false);
+ RegisterVariable('fort' , vtCommand, @chFort , false);
+ RegisterVariable('grave' , vtCommand, @chGrave , false);
+ RegisterVariable('hat' , vtCommand, @chSetHat , false);
+ RegisterVariable('quit' , vtCommand, @chQuit , true );
+ RegisterVariable('confirm' , vtCommand, @chConfirm , true );
+ RegisterVariable('+speedup', vtCommand, @chSpeedup_p , true );
+ RegisterVariable('-speedup', vtCommand, @chSpeedup_m , true );
+ RegisterVariable('zoomin' , vtCommand, @chZoomIn , true );
+ RegisterVariable('zoomout' , vtCommand, @chZoomOut , true );
+ RegisterVariable('zoomreset',vtCommand, @chZoomReset , true );
+ RegisterVariable('ammomenu', vtCommand, @chAmmoMenu , true);
+ RegisterVariable('+precise', vtCommand, @chPrecise_p , false);
+ RegisterVariable('-precise', vtCommand, @chPrecise_m , false);
+ RegisterVariable('switch' , vtCommand, @chSwitch , false);
+ RegisterVariable('timer' , vtCommand, @chTimer , false);
+ RegisterVariable('taunt' , vtCommand, @chTaunt , false);
+ RegisterVariable('put' , vtCommand, @chPut , false);
+ RegisterVariable('+volup' , vtCommand, @chVol_p , true );
+ RegisterVariable('-volup' , vtCommand, @chVol_m , true );
+ RegisterVariable('+voldown', vtCommand, @chVol_m , true );
+ RegisterVariable('-voldown', vtCommand, @chVol_p , true );
+ RegisterVariable('findhh' , vtCommand, @chFindhh , true );
+ RegisterVariable('pause' , vtCommand, @chPause , true );
+ RegisterVariable('+cur_u' , vtCommand, @chCurU_p , true );
+ RegisterVariable('-cur_u' , vtCommand, @chCurU_m , true );
+ RegisterVariable('+cur_d' , vtCommand, @chCurD_p , true );
+ RegisterVariable('-cur_d' , vtCommand, @chCurD_m , true );
+ RegisterVariable('+cur_l' , vtCommand, @chCurL_p , true );
+ RegisterVariable('-cur_l' , vtCommand, @chCurL_m , true );
+ RegisterVariable('+cur_r' , vtCommand, @chCurR_p , true );
+ RegisterVariable('-cur_r' , vtCommand, @chCurR_m , true );
+end;
+
+procedure freeModule;
+begin
+end;
+
+end.
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uCommands.pas
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uCommands.pas Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,135 @@
+{$INCLUDE "options.inc"}
+
+unit uCommands;
+
+interface
+
+var isDeveloperMode: boolean;
+type TVariableType = (vtCommand, vtLongInt, vthwFloat, vtBoolean);
+ TCommandHandler = procedure (var params: shortstring);
+
+procedure initModule;
+procedure freeModule;
+procedure RegisterVariable(Name: shortstring; VType: TVariableType; p: pointer; Trusted: boolean);
+procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean);
+procedure StopMessages(Message: Longword);
+
+implementation
+uses Types, uConsts, uVariables, uConsole, uUtils, uDebug;
+
+type PVariable = ^TVariable;
+ TVariable = record
+ Next: PVariable;
+ Name: string[15];
+ VType: TVariableType;
+ Handler: pointer;
+ Trusted: boolean;
+ end;
+
+var
+ Variables: PVariable;
+
+procedure RegisterVariable(Name: shortstring; VType: TVariableType; p: pointer; Trusted: boolean);
+var value: PVariable;
+begin
+New(value);
+TryDo(value <> nil, 'RegisterVariable: value = nil', true);
+FillChar(value^, sizeof(TVariable), 0);
+value^.Name:= Name;
+value^.VType:= VType;
+value^.Handler:= p;
+value^.Trusted:= Trusted;
+
+if Variables = nil then Variables:= value
+ else begin
+ value^.Next:= Variables;
+ Variables:= value
+ end;
+end;
+
+
+procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean);
+var ii: LongInt;
+ s: shortstring;
+ t: PVariable;
+ c: char;
+begin
+//WriteLnToConsole(CmdStr);
+if CmdStr[0]=#0 then exit;
+c:= CmdStr[1];
+if c in ['/', '$'] then Delete(CmdStr, 1, 1) else c:= '/';
+s:= '';
+SplitBySpace(CmdStr, s);
+{$IFDEF DEBUGFILE}AddFileLog('[Cmd] ' + c + CmdStr + ' (' + inttostr(length(s)) + ')');{$ENDIF}
+t:= Variables;
+while t <> nil do
+ begin
+ if t^.Name = CmdStr then
+ begin
+ if TrustedSource or t^.Trusted then
+ case t^.VType of
+ vtCommand: if c='/' then
+ begin
+ TCommandHandler(t^.Handler)(s);
+ end;
+ vtLongInt: if c='$' then
+ if s[0]=#0 then
+ begin
+ str(PLongInt(t^.Handler)^, s);
+ WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
+ end else val(s, PLongInt(t^.Handler)^);
+ vthwFloat: if c='$' then
+ if s[0]=#0 then
+ begin
+ //str(PhwFloat(t^.Handler)^:4:6, s);
+ WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
+ end else; //val(s, PhwFloat(t^.Handler)^, i);
+ vtBoolean: if c='$' then
+ if s[0]=#0 then
+ begin
+ str(ord(boolean(t^.Handler^)), s);
+ WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
+ end else
+ begin
+ val(s, ii);
+ boolean(t^.Handler^):= not (ii = 0)
+ end;
+ end;
+ exit
+ end else t:= t^.Next
+ end;
+case c of
+ '$': WriteLnToConsole(errmsgUnknownVariable + ': "$' + CmdStr + '"')
+ else WriteLnToConsole(errmsgUnknownCommand + ': "/' + CmdStr + '"') end
+end;
+
+
+procedure StopMessages(Message: Longword);
+begin
+if (Message and gmLeft) <> 0 then ParseCommand('/-left', true) else
+if (Message and gmRight) <> 0 then ParseCommand('/-right', true) else
+if (Message and gmUp) <> 0 then ParseCommand('/-up', true) else
+if (Message and gmDown) <> 0 then ParseCommand('/-down', true) else
+if (Message and gmAttack) <> 0 then ParseCommand('/-attack', true)
+end;
+
+procedure initModule;
+begin
+ Variables:= nil;
+ isDeveloperMode:= true;
+end;
+
+procedure freeModule;
+var t, tt: PVariable;
+begin
+ tt:= Variables;
+ Variables:= nil;
+ while tt <> nil do
+ begin
+ t:= tt;
+ tt:= tt^.Next;
+ Dispose(t)
+ end;
+end;
+
+end.
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uConsole.pas
--- a/hedgewars/uConsole.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uConsole.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,44 +20,26 @@
unit uConsole;
interface
-uses uFloat;
-
-var isDeveloperMode: boolean;
-type TVariableType = (vtCommand, vtLongInt, vthwFloat, vtBoolean);
- TCommandHandler = procedure (var params: shortstring);
procedure initModule;
procedure freeModule;
procedure WriteToConsole(s: shortstring);
procedure WriteLnToConsole(s: shortstring);
-procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean);
-procedure StopMessages(Message: Longword);
function GetLastConsoleLine: shortstring;
-procedure doPut(putX, putY: LongInt; fromAI: boolean);
-
implementation
-uses uMisc, uStore, Types, uConsts, uGears, uTeams, uIO, uKeys, uWorld, uMobile,
- uRandom, uAmmos, uStats, uChat, SDLh, uSound, uVisualGears, uScript;
+uses Types, uVariables, uUtils;
const cLineWidth: LongInt = 0;
- cLinesCount = 256;
+ cLinesCount = 8;
-type PVariable = ^TVariable;
- TVariable = record
- Next: PVariable;
- Name: string[15];
- VType: TVariableType;
- Handler: pointer;
- Trusted: boolean;
- end;
+type
TTextLine = record
s: shortstring;
end;
var ConsoleLines: array[byte] of TTextLine;
CurrLine: LongInt;
- Variables: PVariable;
procedure SetLine(var tl: TTextLine; str: shortstring);
begin
@@ -65,32 +47,12 @@
s:= str;
end;
-function RegisterVariable(Name: shortstring; VType: TVariableType; p: pointer; Trusted: boolean): PVariable;
-var value: PVariable;
-begin
-New(value);
-TryDo(value <> nil, 'RegisterVariable: value = nil', true);
-FillChar(value^, sizeof(TVariable), 0);
-value^.Name:= Name;
-value^.VType:= VType;
-value^.Handler:= p;
-value^.Trusted:= Trusted;
-
-if Variables = nil then Variables:= value
- else begin
- value^.Next:= Variables;
- Variables:= value
- end;
-
-RegisterVariable:= value;
-end;
-
procedure WriteToConsole(s: shortstring);
var Len: LongInt;
done: boolean;
begin
{$IFNDEF NOCONSOLE}
-{$IFDEF DEBUGFILE}AddFileLog('Console write: ' + s);{$ENDIF}
+{$IFDEF DEBUGFILE}AddFileLog('[Con] ' + s);{$ENDIF}
Write(s);
done:= false;
@@ -122,60 +84,6 @@
{$ENDIF}
end;
-procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean);
-var ii: LongInt;
- s: shortstring;
- t: PVariable;
- c: char;
-begin
-//WriteLnToConsole(CmdStr);
-if CmdStr[0]=#0 then exit;
-{$IFDEF DEBUGFILE}AddFileLog('ParseCommand "' + CmdStr + '"');{$ENDIF}
-c:= CmdStr[1];
-if c in ['/', '$'] then Delete(CmdStr, 1, 1) else c:= '/';
-s:= '';
-SplitBySpace(CmdStr, s);
-t:= Variables;
-while t <> nil do
- begin
- if t^.Name = CmdStr then
- begin
- if TrustedSource or t^.Trusted then
- case t^.VType of
- vtCommand: if c='/' then
- begin
- TCommandHandler(t^.Handler)(s);
- end;
- vtLongInt: if c='$' then
- if s[0]=#0 then
- begin
- str(PLongInt(t^.Handler)^, s);
- WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
- end else val(s, PLongInt(t^.Handler)^);
- vthwFloat: if c='$' then
- if s[0]=#0 then
- begin
- //str(PhwFloat(t^.Handler)^:4:6, s);
- WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
- end else; //val(s, PhwFloat(t^.Handler)^, i);
- vtBoolean: if c='$' then
- if s[0]=#0 then
- begin
- str(ord(boolean(t^.Handler^)), s);
- WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
- end else
- begin
- val(s, ii);
- boolean(t^.Handler^):= not (ii = 0)
- end;
- end;
- exit
- end else t:= t^.Next
- end;
-case c of
- '$': WriteLnToConsole(errmsgUnknownVariable + ': "$' + CmdStr + '"')
- else WriteLnToConsole(errmsgUnknownCommand + ': "/' + CmdStr + '"') end
-end;
function GetLastConsoleLine: shortstring;
var valueStr: shortstring;
@@ -192,22 +100,10 @@
GetLastConsoleLine:= valueStr;
end;
-procedure StopMessages(Message: Longword);
-begin
-if (Message and gmLeft) <> 0 then ParseCommand('/-left', true) else
-if (Message and gmRight) <> 0 then ParseCommand('/-right', true) else
-if (Message and gmUp) <> 0 then ParseCommand('/-up', true) else
-if (Message and gmDown) <> 0 then ParseCommand('/-down', true) else
-if (Message and gmAttack) <> 0 then ParseCommand('/-attack', true)
-end;
-
-{$INCLUDE "CCHandlers.inc"}
procedure initModule;
var i: LongInt;
begin
CurrLine:= 0;
- Variables:= nil;
- isDeveloperMode:= true;
// initConsole
cLineWidth:= cScreenWidth div 10;
@@ -215,113 +111,11 @@
cLineWidth:= 255;
for i:= 0 to Pred(cLinesCount) do
PByte(@ConsoleLines[i])^:= 0;
-
- // NOTE: please, keep most frequently used commands on bottom
- RegisterVariable('flag' , vtCommand, @chFlag , false);
- RegisterVariable('script' , vtCommand, @chScript , false);
- RegisterVariable('proto' , vtCommand, @chCheckProto , true );
- RegisterVariable('spectate', vtBoolean, @fastUntilLag , false);
- RegisterVariable('capture' , vtCommand, @chCapture , true );
- RegisterVariable('rotmask' , vtCommand, @chRotateMask , true );
- RegisterVariable('addteam' , vtCommand, @chAddTeam , false);
- RegisterVariable('rdriven' , vtCommand, @chTeamLocal , false);
- RegisterVariable('map' , vtCommand, @chSetMap , false);
- RegisterVariable('theme' , vtCommand, @chSetTheme , false);
- RegisterVariable('seed' , vtCommand, @chSetSeed , false);
- RegisterVariable('template_filter', vtLongInt, @cTemplateFilter, false);
- RegisterVariable('mapgen' , vtLongInt, @cMapGen , false);
- RegisterVariable('maze_size',vtLongInt, @cMazeSize , false);
- RegisterVariable('delay' , vtLongInt, @cInactDelay , false);
- RegisterVariable('ready' , vtLongInt, @cReadyDelay , false);
- RegisterVariable('casefreq', vtLongInt, @cCaseFactor , false);
- RegisterVariable('healthprob', vtLongInt, @cHealthCaseProb, false);
- RegisterVariable('hcaseamount', vtLongInt, @cHealthCaseAmount, false);
- RegisterVariable('sd_turns', vtLongInt, @cSuddenDTurns , false);
- RegisterVariable('waterrise', vtLongInt, @cWaterRise , false);
- RegisterVariable('healthdec', vtLongInt, @cHealthDecrease, false);
- RegisterVariable('damagepct',vtLongInt, @cDamagePercent , false);
- RegisterVariable('minedudpct',vtLongInt,@cMineDudPercent, false);
- RegisterVariable('minesnum', vtLongInt, @cLandMines , false);
- RegisterVariable('explosives',vtLongInt,@cExplosives , false);
- RegisterVariable('gmflags' , vtLongInt, @GameFlags , false);
- RegisterVariable('trflags' , vtLongInt, @TrainingFlags , false);
- RegisterVariable('turntime', vtLongInt, @cHedgehogTurnTime, false);
- RegisterVariable('minestime',vtLongInt, @cMinesTime , false);
- RegisterVariable('fort' , vtCommand, @chFort , false);
- RegisterVariable('voicepack',vtCommand, @chVoicepack , false);
- RegisterVariable('grave' , vtCommand, @chGrave , false);
- RegisterVariable('bind' , vtCommand, @chBind , true );
- RegisterVariable('addhh' , vtCommand, @chAddHH , false);
- RegisterVariable('hat' , vtCommand, @chSetHat , false);
- RegisterVariable('hhcoords', vtCommand, @chSetHHCoords , false);
- RegisterVariable('ammloadt', vtCommand, @chSetAmmoLoadout, false);
- RegisterVariable('ammdelay', vtCommand, @chSetAmmoDelay, false);
- RegisterVariable('ammprob', vtCommand, @chSetAmmoProbability, false);
- RegisterVariable('ammreinf', vtCommand, @chSetAmmoReinforcement, false);
- RegisterVariable('ammstore', vtCommand, @chAddAmmoStore , false);
- RegisterVariable('quit' , vtCommand, @chQuit , true );
- RegisterVariable('confirm' , vtCommand, @chConfirm , true );
- RegisterVariable('+speedup', vtCommand, @chSpeedup_p , true );
- RegisterVariable('-speedup', vtCommand, @chSpeedup_m , true );
- RegisterVariable('zoomin' , vtCommand, @chZoomIn , true );
- RegisterVariable('zoomout' , vtCommand, @chZoomOut , true );
- RegisterVariable('zoomreset',vtCommand, @chZoomReset , true );
- RegisterVariable('skip' , vtCommand, @chSkip , false);
- RegisterVariable('history' , vtCommand, @chHistory , true );
- RegisterVariable('chat' , vtCommand, @chChat , true );
- RegisterVariable('say' , vtCommand, @chSay , true );
- RegisterVariable('hogsay' , vtCommand, @chHogSay , true );
- RegisterVariable('team' , vtCommand, @chTeamSay , true );
- RegisterVariable('ammomenu', vtCommand, @chAmmoMenu , true);
- RegisterVariable('+precise', vtCommand, @chPrecise_p , false);
- RegisterVariable('-precise', vtCommand, @chPrecise_m , false);
- RegisterVariable('+left' , vtCommand, @chLeft_p , false);
- RegisterVariable('-left' , vtCommand, @chLeft_m , false);
- RegisterVariable('+right' , vtCommand, @chRight_p , false);
- RegisterVariable('-right' , vtCommand, @chRight_m , false);
- RegisterVariable('+up' , vtCommand, @chUp_p , false);
- RegisterVariable('-up' , vtCommand, @chUp_m , false);
- RegisterVariable('+down' , vtCommand, @chDown_p , false);
- RegisterVariable('-down' , vtCommand, @chDown_m , false);
- RegisterVariable('+attack' , vtCommand, @chAttack_p , false);
- RegisterVariable('-attack' , vtCommand, @chAttack_m , false);
- RegisterVariable('switch' , vtCommand, @chSwitch , false);
- RegisterVariable('nextturn', vtCommand, @chNextTurn , false);
- RegisterVariable('timer' , vtCommand, @chTimer , false);
- RegisterVariable('taunt' , vtCommand, @chTaunt , false);
- RegisterVariable('setweap' , vtCommand, @chSetWeapon , false);
- RegisterVariable('slot' , vtCommand, @chSlot , false);
- RegisterVariable('put' , vtCommand, @chPut , false);
- RegisterVariable('ljump' , vtCommand, @chLJump , false);
- RegisterVariable('hjump' , vtCommand, @chHJump , false);
- RegisterVariable('fullscr' , vtCommand, @chFullScr , true );
- RegisterVariable('+volup' , vtCommand, @chVol_p , true );
- RegisterVariable('-volup' , vtCommand, @chVol_m , true );
- RegisterVariable('+voldown', vtCommand, @chVol_m , true );
- RegisterVariable('-voldown', vtCommand, @chVol_p , true );
- RegisterVariable('findhh' , vtCommand, @chFindhh , true );
- RegisterVariable('pause' , vtCommand, @chPause , true );
- RegisterVariable('+cur_u' , vtCommand, @chCurU_p , true );
- RegisterVariable('-cur_u' , vtCommand, @chCurU_m , true );
- RegisterVariable('+cur_d' , vtCommand, @chCurD_p , true );
- RegisterVariable('-cur_d' , vtCommand, @chCurD_m , true );
- RegisterVariable('+cur_l' , vtCommand, @chCurL_p , true );
- RegisterVariable('-cur_l' , vtCommand, @chCurL_m , true );
- RegisterVariable('+cur_r' , vtCommand, @chCurR_p , true );
- RegisterVariable('-cur_r' , vtCommand, @chCurR_m , true );
end;
procedure freeModule;
-var t, tt: PVariable;
begin
- tt:= Variables;
- Variables:= nil;
- while tt <> nil do
- begin
- t:= tt;
- tt:= tt^.Next;
- Dispose(t)
- end;
+
end;
end.
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uConsts.pas
--- a/hedgewars/uConsts.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uConsts.pas Tue Jan 04 12:53:46 2011 +0100
@@ -21,181 +21,10 @@
unit uConsts;
interface
-uses SDLh, uFloat, uLocale, GLunit;
-
+uses SDLh, uFloat, GLunit;
{$INCLUDE "config.inc"}
-// typed const is a variable despite const qualifier
-// in freepascal you may actually use var for the same purpose
-
-type
- HwColor4f = record
- r, g, b, a: byte
- end;
-
- TGameState = (gsLandGen, gsStart, gsGame, gsChat, gsConfirm, gsExit);
-
- TGameType = (gmtLocal, gmtDemo, gmtNet, gmtSave, gmtLandPreview, gmtSyntax);
-
- TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptTeams, ptMaps,
- ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts,
- ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps);
-
- TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame,
- sprLag, sprArrow, sprBazookaShell, sprTargetP, sprBee,
- sprSmokeTrace, sprRopeHook, sprExplosion50, sprMineOff,
- sprMineOn, sprMineDead, sprCase, sprFAid, sprDynamite, sprPower,
- sprClusterBomb, sprClusterParticle, sprFlame, sprHorizont,
- sprHorizontL, sprHorizontR, sprSky, sprSkyL,
- sprSkyR, sprAMBorderHorizontal, sprAMBorderVertical, sprAMSlot, sprAMAmmos,
- sprAMSlotKeys, sprAMCorners, sprFinger, sprAirBomb,
- sprAirplane, sprAmAirplane, sprAmGirder, sprHHTelepMask,
- sprSwitch, sprParachute, sprTarget, sprRopeNode,
- sprQuestion, sprPowerBar, sprWindBar, sprWindL, sprWindR,
- sprFlake, sprHandRope, sprHandBazooka, sprHandShotgun,
- sprHandDEagle, sprHandAirAttack, sprHandBaseball, sprPHammer,
- sprHandBlowTorch, sprBlowTorch, sprTeleport, sprHHDeath,
- sprShotgun, sprDEagle, sprHHIdle, sprMortar, sprTurnsLeft,
- sprKamikaze, sprWhip, sprKowtow, sprSad, sprWave,
- sprHurrah, sprLemonade, sprShrug, sprJuggle, sprExplPart, sprExplPart2,
- sprCakeWalk, sprCakeDown, sprAMAmmosBW, sprWatermelon,
- sprEvilTrace, sprHellishBomb, sprSeduction, sprDress,
- sprCensored, sprDrill, sprHandDrill, sprHandBallgun, sprBalls,
- sprPlane, sprHandPlane, sprUtility, sprInvulnerable, sprVampiric, sprGirder,
- sprSpeechCorner, sprSpeechEdge, sprSpeechTail,
- sprThoughtCorner, sprThoughtEdge, sprThoughtTail,
- sprShoutCorner, sprShoutEdge, sprShoutTail,
- sprSniperRifle, sprBubbles, sprJetpack, sprHealth, sprHandMolotov, sprMolotov,
- sprSmoke, sprSmokeWhite, sprShell, sprDust, sprExplosives, sprExplosivesRoll,
- sprAmTeleport, sprSplash, sprDroplet, sprBirdy, sprHandCake, sprHandConstruction,
- sprHandGrenade, sprHandMelon, sprHandMortar, sprHandSkip, sprHandCluster,
- sprHandDynamite, sprHandHellish, sprHandMine, sprHandSeduction, sprHandVamp,
- sprBigExplosion, sprSmokeRing, sprBeeTrace, sprEgg, sprTargetBee, sprHandBee,
- sprFeather, sprPiano, sprHandSineGun, sprPortalGun, sprPortal,
- sprCheese, sprHandCheese, sprHandFlamethrower, sprChunk, sprNote,
- sprSMineOff, sprSMineOn, sprHandSMine, sprHammer,
- sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb,
- sprBulletHit
- );
-
- // Gears that interact with other Gears and/or Land
- TGearType = (gtBomb, gtHedgehog, gtShell, gtGrave, gtBee, // 4
- gtShotgunShot, gtPickHammer, gtRope, gtMine, gtCase, // 9
- gtDEagleShot, gtDynamite, gtClusterBomb, gtCluster, gtShover, // 14
- gtFlame, gtFirePunch, gtATStartGame, gtATSmoothWindCh, // 18
- gtATFinishGame, gtParachute, gtAirAttack, gtAirBomb, gtBlowTorch, // 23
- gtGirder, gtTeleport, gtSwitcher, gtTarget, gtMortar, // 28
- gtWhip, gtKamikaze, gtCake, gtSeduction, gtWatermelon, gtMelonPiece, // 34
- gtHellishBomb, gtWaterUp, gtDrill, gtBallGun, gtBall, gtRCPlane, // 40
- gtSniperRifleShot, gtJetpack, gtMolotov, gtExplosives, gtBirdy, // 45
- gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 51
- gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 56
- gtNapalmBomb); // 57
-
- // Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
- TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
- vgtSmallDamageTag, vgtTeamHealthSorter, vgtSpeechBubble, vgtBubble,
- vgtSteam, vgtAmmo, vgtSmoke, vgtSmokeWhite, vgtHealth, vgtShell,
- vgtDust, vgtSplash, vgtDroplet, vgtSmokeRing, vgtBeeTrace, vgtEgg,
- vgtFeather, vgtHealthTag, vgtSmokeTrace, vgtEvilTrace, vgtExplosion,
- vgtBigExplosion, vgtChunk, vgtNote, vgtLineTrail,
- vgtBulletHit);
-
- TGearsType = set of TGearType;
-
- TDamageSource = (dsUnknown, dsFall, dsBullet, dsExplosion, dsShove, dsPoison);
-
- TSound = (sndNone,
- sndGrenadeImpact, sndExplosion, sndThrowPowerUp, sndThrowRelease,
- sndSplash, sndShotgunReload, sndShotgunFire, sndGraveImpact,
- sndMineTick, sndPickhammer, sndGun, sndBee, sndJump1, sndJump2,
- sndJump3, sndYesSir, sndLaugh, sndIllGetYou, sndIncoming,
- sndMissed, sndStupid, sndFirstBlood, sndBoring, sndByeBye,
- sndSameTeam, sndNutter, sndReinforce, sndTraitor, sndRegret,
- sndEnemyDown, sndCoward, sndHurry, sndWatchIt, sndKamikaze,
- sndCake, sndOw1, sndOw2, sndOw3, sndOw4, sndFirePunch1, sndFirePunch2,
- sndFirePunch3, sndFirePunch4, sndFirePunch5, sndFirePunch6,
- sndMelon, sndHellish, sndYoohoo, sndRCPlane, sndWhipCrack,
- sndRideOfTheValkyries, sndDenied, sndPlaced, sndBaseballBat,
- sndVaporize, sndWarp, sndSuddenDeath, sndMortar, sndShutter,
- sndHomerun, sndMolotov, sndCover, sndUhOh, sndOops,
- sndNooo, sndHello, sndRopeShot, sndRopeAttach, sndRopeRelease,
- sndSwitchHog, sndVictory, sndSniperReload, sndSteps, sndLowGravity,
- sndHellishImpact1, sndHellishImpact2, sndHellishImpact3, sndHellishImpact4,
- sndMelonImpact, sndDroplet1, sndDroplet2, sndDroplet3, sndEggBreak, sndDrillRocket,
- sndPoisonCough, sndPoisonMoan, sndBirdyLay, sndWhistle, sndBeeWater,
- sndPiano0, sndPiano1, sndPiano2, sndPiano3, sndPiano4, sndPiano5, sndPiano6, sndPiano7, sndPiano8,
- sndSkip, sndSineGun, sndOoff1, sndOoff2, sndOoff3, sndWhack,
- sndComeonthen, sndParachute, sndBump, sndResurrector);
-
- TAmmoType = (amNothing, amGrenade, amClusterBomb, amBazooka, amBee, amShotgun, amPickHammer, // 6
- amSkip, amRope, amMine, amDEagle, amDynamite, amFirePunch, amWhip, // 13
- amBaseballBat, amParachute, amAirAttack, amMineStrike, amBlowTorch, // 18
- amGirder, amTeleport, amSwitch, amMortar, amKamikaze, amCake, // 24
- amSeduction, amWatermelon, amHellishBomb, amNapalm, amDrill, amBallgun, // 30
- amRCPlane, amLowGravity, amExtraDamage, amInvulnerable, amExtraTime, // 35
- amLaserSight, amVampiric, amSniperRifle, amJetpack, amMolotov, amBirdy, amPortalGun, // 42
- amPiano, amGasBomb, amSineGun, amFlamethrower, amSMine, amHammer, // 48
- amResurrector, amDrillStrike);
-
- TCrateType = (HealthCrate, AmmoCrate, UtilityCrate);
-
- THWFont = (fnt16, fntBig, fntSmall {$IFNDEF IPHONEOS}, CJKfnt16, CJKfntBig, CJKfntSmall{$ENDIF});
-
- TCapGroup = (capgrpGameState, capgrpAmmoinfo, capgrpVolume,
- capgrpMessage, capgrpAmmostate);
-
- TStatInfoType = (siGameResult, siMaxStepDamage, siMaxStepKills, siKilledHHs,
- siClanHealth, siTeamStats, siPlayerKills, siMaxTeamDamage,
- siMaxTeamKills, siMaxTurnSkips );
-
- TWave = (waveRollup, waveSad, waveWave, waveHurrah, waveLemonade, waveShrug, waveJuggle);
-
- TRenderMode = (rmDefault, rmLeftEye, rmRightEye);
- TStereoMode = (smNone, smRedCyan, smCyanRed, smRedBlue, smBlueRed, smRedGreen, smGreenRed, smHorizontal, smVertical, smAFR);
-
- THHFont = record
- Handle: PTTF_Font;
- Height: LongInt;
- style: LongInt;
- Name: string[21];
- end;
-
- PAmmo = ^TAmmo;
- TAmmo = record
- Propz: LongWord;
- Count: LongWord;
-(* Using for place hedgehogs mode, but for any other situation where the initial count would be needed I guess.
-For example, say, a mode where the weaponset is reset each turn, or on sudden death *)
- NumPerTurn: LongWord;
- Timer: LongWord;
- Pos: LongWord;
- AmmoType: TAmmoType;
- AttackVoice: TSound;
- end;
-
- TVertex2f = record
- X, Y: GLfloat;
- end;
-
- TVertex2i = record
- X, Y: GLint;
- end;
-
- PTexture = ^TTexture;
- TTexture = record
- id: GLuint;
- w, h, scale: LongInt;
- rx, ry: GLfloat;
- priority: GLfloat;
- vb, tb: array [0..3] of TVertex2f;
- PrevTexture, NextTexture: PTexture;
- end;
-
- THogEffect = (heInvulnerable, heResurrectable, hePoisoned, heResurrected);
-
- TScreenFade = (sfNone, sfInit, sfToBlack, sfFromBlack, sfToWhite, sfFromWhite);
const
sfMax = 1000;
cDefaultParamNum = 17;
@@ -236,7 +65,7 @@
rqNoBackground= $00000004; // don't draw background
rqSimpleRope = $00000008; // draw rope using lines only
rq2DWater = $00000010; // disable 3D water effect
- rqFancyBoom = $00000020; // no fancy explosion effects
+ rqAntiBoom = $00000020; // no fancy explosion effects
rqKillFlakes = $00000040; // no flakes
rqSlowMenu = $00000080; // ammomenu appears with no animation
rqPlainSplash = $00000100; // no droplets
@@ -270,6 +99,7 @@
cPowerDivisor = 1500;
MAXNAMELEN = 192;
+ MAXROPEPOINTS = 3840;
// some opengl headers do not have these macros
GL_BGR = $80E0;
@@ -282,6 +112,7 @@
cCursorEdgesDist : LongInt = 100;
cTeamHealthWidth : LongInt = 128;
cWaterOpacity : byte = $80;
+ cSDWaterOpacity : byte = $80;
cifRandomize = $00000001;
cifTheme = $00000002;
@@ -290,7 +121,7 @@
cTransparentColor: Longword = $00000000;
- cMaxTeams = 6;
+ cMaxTeams = 8;
cMaxHHIndex = 7;
cMaxHHs = 48;
cMaxSpawnPoints = 1024;
@@ -328,14 +159,6 @@
cSendEmptyPacketTime = 1000;
trigTurns = $80000001;
- // Training Flags
- tfNone = $00000000;
- tfTimeTrial = $00000001;
- tfRCPlane = $00000002;
- tfSpawnTargets = $00000004;
- tfIgnoreDelays = $00000008;
- tfTargetRespawn = $00000010;
-
gfAny = $FFFFFFFF;
gfOneClanMode = $00000001; // used in trainings
gfMultiWeapon = $00000002; // used in trainings
@@ -360,7 +183,7 @@
gfInfAttack = $00100000;
gfResetWeps = $00200000;
gfPerHogAmmo = $00400000;
- gfDisableWind = $00800000; // only lua for now
+ gfDisableWind = $00800000;
gfMoreWind = $01000000;
// NOTE: When adding new game flags, ask yourself
// if a "game start notice" would be useful. If so,
@@ -445,1847 +268,7 @@
htHealth = $04;
htTransparent = $08;
- cHHFileName = 'Hedgehog';
- cCHFileName = 'Crosshair';
- cThemeCFGFilename = 'theme.cfg';
- FontBorder = 2;
- cPathz: array[TPathType] of shortstring = (
- '', // ptNone
- '', // ptData
- 'Graphics', // ptGraphics
- 'Themes', // ptThemes
- 'Themes/avematan', // ptCurrTheme
- 'Teams', // ptTeams
- 'Maps', // ptMaps
- '', // ptMapCurrent
- 'Demos', // ptDemos
- 'Sounds', // ptSounds
- 'Graphics/Graves', // ptGraves
- 'Fonts', // ptFonts
- 'Forts', // ptForts
- 'Locale', // ptLocale
- 'Graphics/AmmoMenu', // ptAmmoMenu
- 'Graphics/Hedgehog', // ptHedgehog
- 'Sounds/voices', // ptVoices
- 'Graphics/Hats', // ptHats
- 'Graphics/Flags', // ptFlags
- 'Missions/Maps' // ptMissionMaps
- );
-
- cTagsMasks : array[0..15] of byte = (7, 0, 0, 0, 15, 6, 4, 5, 0, 0, 0, 0, 0, 14, 12, 13);
- cTagsMasksNoHealth: array[0..15] of byte = (3, 2, 11, 1, 0, 0, 0, 0, 0, 10, 0, 9, 0, 0, 0, 0);
-
- Fontz: array[THWFont] of THHFont = (
- (Handle: nil;
- Height: 12;
- style: TTF_STYLE_NORMAL;
- Name: 'DejaVuSans-Bold.ttf'),
- (Handle: nil;
- Height: 24;
- style: TTF_STYLE_NORMAL;
- Name: 'DejaVuSans-Bold.ttf'),
- (Handle: nil;
- Height: 10;
- style: TTF_STYLE_NORMAL;
- Name: 'DejaVuSans-Bold.ttf')
- {$IFNDEF IPHONEOS}, // remove chinese fonts for now
- (Handle: nil;
- Height: 12;
- style: TTF_STYLE_NORMAL;
- Name: 'wqy-zenhei.ttc'),
- (Handle: nil;
- Height: 24;
- style: TTF_STYLE_NORMAL;
- Name: 'wqy-zenhei.ttc'),
- (Handle: nil;
- Height: 10;
- style: TTF_STYLE_NORMAL;
- Name: 'wqy-zenhei.ttc')
- {$ENDIF}
- );
-
- SpritesData: array[TSprite] of record
- FileName: String[16];
- Path, AltPath: TPathType;
- Texture: PTexture;
- Surface: PSDL_Surface;
- Width, Height, imageWidth, imageHeight: LongInt;
- saveSurf: boolean;
- priority: GLfloat;
- getDimensions, getImageDimensions: boolean;
- end = (
- (FileName: 'BlueWater'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprWater
- (FileName: 'Clouds'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCloud
- (FileName: 'Bomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBomb
- (FileName: 'BigDigits'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigit
- (FileName: 'Frame'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 4; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFrame
- (FileName: 'Lag'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 65; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLag
- (FileName: 'Arrow'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCursor
- (FileName:'BazookaShell'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBazookaShell
- (FileName: 'Targetp'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetP
- (FileName: 'Bee'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBee
- (FileName: 'SmokeTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeTrace
- (FileName: 'RopeHook'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprRopeHook
- (FileName: 'Expl50'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosion50
- (FileName: 'MineOff'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOff
- (FileName: 'MineOn'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOn
- (FileName: 'MineDead'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineDead
- (FileName: 'Case'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCase
- (FileName: 'FirstAid'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprFAid
- (FileName: 'dynamite'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDynamite
- (FileName: 'Power'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprPower
- (FileName: 'ClBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterBomb
- (FileName: 'ClParticle'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterParticle
- (FileName: 'Flame'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlame
- (FileName: 'horizont'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
- (FileName: 'horizontL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
- (FileName: 'horizontR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
- (FileName: 'Sky'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
- (FileName: 'SkyL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
- (FileName: 'SkyR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
- (FileName: 'BorderHorizontal'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 33; Height: 2; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprAMBorderHorizontal
- (FileName: 'BorderVertical'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 2; Height: 33; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprAMBorderVertical
- (FileName: 'Slot'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 33; Height: 33; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot
- (FileName: 'Ammos'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMAmmos
- (FileName: 'SlotKeys'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlotKeys
- (FileName: 'Corners'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 2; Height: 2; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMCorners
- (FileName: 'Finger'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFinger
- (FileName: 'AirBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirBomb
- (FileName: 'Airplane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 254; Height: 101; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirplane
- (FileName: 'amAirplane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmAirplane
- (FileName: 'amGirder'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 160; Height:160; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmGirder
- (FileName: 'hhMask'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHHTelepMask
- (FileName: 'Switch'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSwitch
- (FileName: 'Parachute'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprParachute
- (FileName: 'Target'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTarget
- (FileName: 'RopeNode'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 6; Height: 6; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprRopeNode
- (FileName: 'thinking'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprQuestion
- (FileName: 'PowerBar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 256; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPowerBar
- (FileName: 'WindBar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 151; Height: 17; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindBar
- (FileName: 'WindL'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindL
- (FileName: 'WindR'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindR
- (FileName: 'Flake'; Path:ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlake
- (FileName: 'amRope'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandRope
- (FileName: 'amBazooka'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBazooka
- (FileName: 'amShotgun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandShotgun
- (FileName: 'amDEagle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDEagle
- (FileName:'amAirAttack'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandAirAttack
- (FileName: 'amBaseball'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBaseball
- (FileName: 'Hammer'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPHammer
- (FileName: 'amBTorch_i'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBlowTorch
- (FileName: 'amBTorch_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBlowTorch
- (FileName: 'Teleport'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTeleport
- (FileName: 'HHDeath'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHHDeath
- (FileName:'amShotgun_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprShotgun
- (FileName: 'amDEagle_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDEagle
- (FileName: 'Idle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHHIdle
- (FileName: 'Mortar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMortar
- (FileName: 'TurnsLeft'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTurnsLeft
- (FileName: 'amKamikaze'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 256; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprKamikaze
- (FileName: 'amWhip'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWhip
- (FileName: 'Kowtow'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprKowtow
- (FileName: 'Sad'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSad
- (FileName: 'Wave'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprWave
- (FileName: 'Hurrah'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHurrah
- (FileName:'ILoveLemonade';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLemonade
- (FileName: 'Shrug'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShrug
- (FileName: 'Juggle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprJuggle
- (FileName: 'ExplPart'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart
- (FileName: 'ExplPart2'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart2
- (FileName: 'Cake_walk'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeWalk
- (FileName: 'Cake_down'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeDown
- (FileName: 'Ammos_bw'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprAMAmmosBW
- (FileName: 'Watermelon'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWatermelon
- (FileName: 'EvilTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprEvilTrace
- (FileName:'HellishBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHellishBomb
- (FileName: 'Seduction'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSeduction
- (FileName: 'HHDress'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprDress
- (FileName: 'Censored'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprCensored
- (FileName: 'Drill'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDrill
- (FileName: 'amDrill'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDrill
- (FileName: 'amBallgun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBallgun
- (FileName: 'Balls'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBalls
- (FileName: 'RCPlane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPlane
- (FileName: 'amRCPlane'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandPlane
- (FileName: 'Utility'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprUtility
- (FileName:'Invulnerable';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprInvulnerable
- (FileName: 'Vampiric'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprVampiric
- (FileName: 'amGirder'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 512; Height:512; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprGirder
- (FileName:'SpeechCorner';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 12; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechCorner
- (FileName: 'SpeechEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 25; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechEdge
- (FileName: 'SpeechTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 25; Height: 26; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechTail
- (FileName:'ThoughtCorner';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 49; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtCorner
- (FileName:'ThoughtEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 23; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtEdge
- (FileName:'ThoughtTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 45; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtTail
- (FileName:'ShoutCorner'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 34; Height: 23; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutCorner
- (FileName: 'ShoutEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 30; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutEdge
- (FileName: 'ShoutTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 30; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutTail
- (FileName:'amSniperRifle';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSniperRifle
- (FileName: 'Bubbles'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBubbles
- (FileName: 'amJetpack'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprJetpack
- (FileName: 'Health'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHealth
- (FileName: 'amMolotov'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),//sprHandMolotov
- (FileName: 'Molotov'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMolotov
- (FileName: 'Smoke'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmoke
- (FileName: 'SmokeWhite'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeWhite
- (FileName: 'Shells'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprShell
- (FileName: 'Dust'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDust
- (FileName: 'Explosives'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosives
- (FileName: 'ExplosivesRoll'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosivesRoll
- (FileName: 'amTeleport'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmTeleport
- (FileName: 'Splash'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSplash
- (FileName: 'Droplet'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDroplet
- (FileName: 'Birdy'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 75; Height: 75; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBirdy
- (FileName: 'amCake'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCake
- (FileName: 'amConstruction'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandConstruction
- (FileName: 'amGrenade'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandGrenade
- (FileName: 'amMelon'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMelon
- (FileName: 'amMortar'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMortar
- (FileName: 'amSkip'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSkip
- (FileName: 'amCluster'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCluster
- (FileName: 'amDynamite'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDynamite
- (FileName: 'amHellish'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandHellish
- (FileName: 'amMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMine
- (FileName: 'amSeduction'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSeduction
- (FileName: 'amVamp'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandVamp
- (FileName: 'BigExplosion'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 385; Height: 385; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigExplosion
- (FileName: 'SmokeRing'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 200; Height: 200; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSmokeRing
- (FileName: 'BeeTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprBeeTrace
- (FileName: 'Egg'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprEgg
- (FileName: 'TargetBee'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetBee
- (FileName: 'amBee'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBee
- (FileName: 'Feather'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 15; Height: 25; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFeather
- (FileName: 'Piano'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPiano
- (FileName: 'amSineGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSineGun
- (FileName: 'amPortalGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortalGun
- (FileName: 'Portal'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortal
- (FileName: 'cheese'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCheese
- (FileName: 'amCheese'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCheese
- (FileName: 'amFlamethrower'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandFlamethrower
- (FileName: 'Chunk'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprChunk
- (FileName: 'Note'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprNote
- (FileName: 'SMineOff'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOff
- (FileName: 'SMineOn'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOn
- (FileName: 'amSMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSMine
- (FileName: 'amHammer'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprWhip
- (FileName: 'amResurrector'; Path: ptHedgehog; AltPath: ptNone;
- Texture: nil; Surface: nil; Width: 32; Height: 32;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
- tpMedium; getDimensions: false; getImageDimensions: true),
- //sprHandResurrector
- (FileName: 'Cross'; Path: ptGraphics; altPath: ptNone;
- Texture: nil; Surface: nil; Width: 108; Height: 138;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
- tpMedium; getDimensions: false; getImageDimensions: true),
- //sprCross
- (FileName: 'AirDrill'; Path: ptGraphics; AltPath: ptNone;
- Texture: nil; Surface: nil; Width: 16; Height: 16;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
- tpMedium; getDimensions: false; getImageDimensions: true),
- // sprAirDrill
- (FileName: 'NapalmBomb'; Path: ptGraphics; AltPath: ptNone;
- Texture: nil; Surface: nil; Width: 16; Height: 16;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
- tpMedium; getDimensions: false; getImageDimensions: true),
- // sprNapalmBomb
- (FileName: 'BulletHit'; Path: ptGraphics; AltPath: ptNone;
- Texture: nil; Surface: nil; Width: 32; Height: 32;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
- tpMedium; getDimensions: false; getImageDimensions: true)
- // sprNapalmBomb
- );
-
-
- Wavez: array [TWave] of record
- Sprite: TSprite;
- FramesCount: Longword;
- Interval: Longword;
- cmd: String[20];
- Voice: TSound;
- VoiceDelay: LongWord;
- end = (
- (Sprite: sprKowtow; FramesCount: 12; Interval: 125; cmd: '/rollup'; Voice: sndNone; VoiceDelay: 0),
- (Sprite: sprSad; FramesCount: 14; Interval: 125; cmd: '/sad'; Voice: sndNone; VoiceDelay: 0),
- (Sprite: sprWave; FramesCount: 16; Interval: 125; cmd: '/wave'; Voice: sndHello; VoiceDelay: 5),
- (Sprite: sprHurrah; FramesCount: 14; Interval: 125; cmd: '/hurrah'; Voice: sndNone; VoiceDelay: 0),
- (Sprite: sprLemonade; FramesCount: 24; Interval: 125; cmd: '/ilovelotsoflemonade'; Voice: sndNone; VoiceDelay: 0),
- (Sprite: sprShrug; FramesCount: 24; Interval: 125; cmd: '/shrug'; Voice: sndNone; VoiceDelay: 0),
- (Sprite: sprJuggle; FramesCount: 49; Interval: 38; cmd: '/juggle'; Voice: sndNone; VoiceDelay: 0)
- );
-
- Soundz: array[TSound] of record
- FileName: String[25];
- Path : TPathType;
- end = (
- (FileName: ''; Path: ptNone ),// sndNone
- (FileName: 'grenadeimpact.ogg'; Path: ptSounds),// sndGrenadeImpact
- (FileName: 'explosion.ogg'; Path: ptSounds),// sndExplosion
- (FileName: 'throwpowerup.ogg'; Path: ptSounds),// sndThrowPowerUp
- (FileName: 'throwrelease.ogg'; Path: ptSounds),// sndThrowRelease
- (FileName: 'splash.ogg'; Path: ptSounds),// sndSplash
- (FileName: 'shotgunreload.ogg'; Path: ptSounds),// sndShotgunReload
- (FileName: 'shotgunfire.ogg'; Path: ptSounds),// sndShotgunFire
- (FileName: 'graveimpact.ogg'; Path: ptSounds),// sndGraveImpact
- (FileName: 'minetick.ogg'; Path: ptSounds),// sndMineTicks
- (FileName: 'pickhammer.ogg'; Path: ptSounds),// sndPickhammer
- (FileName: 'gun.ogg'; Path: ptSounds),// sndGun
- (FileName: 'bee.ogg'; Path: ptSounds),// sndBee
- (FileName: 'Jump1.ogg'; Path: ptVoices),// sndJump1
- (FileName: 'Jump2.ogg'; Path: ptVoices),// sndJump2
- (FileName: 'Jump3.ogg'; Path: ptVoices),// sndJump3
- (FileName: 'Yessir.ogg'; Path: ptVoices),// sndYesSir
- (FileName: 'Laugh.ogg'; Path: ptVoices),// sndLaugh
- (FileName: 'Illgetyou.ogg'; Path: ptVoices),// sndIllGetYou
- (FileName: 'Incoming.ogg'; Path: ptVoices),// sndIncoming
- (FileName: 'Missed.ogg'; Path: ptVoices),// sndMissed
- (FileName: 'Stupid.ogg'; Path: ptVoices),// sndStupid
- (FileName: 'Firstblood.ogg'; Path: ptVoices),// sndFirstBlood
- (FileName: 'Boring.ogg'; Path: ptVoices),// sndBoring
- (FileName: 'Byebye.ogg'; Path: ptVoices),// sndByeBye
- (FileName: 'Sameteam.ogg'; Path: ptVoices),// sndSameTeam
- (FileName: 'Nutter.ogg'; Path: ptVoices),// sndNutter
- (FileName: 'Reinforcements.ogg'; Path: ptVoices),// sndReinforce
- (FileName: 'Traitor.ogg'; Path: ptVoices),// sndTraitor
- (FileName: 'Youllregretthat.ogg'; Path: ptVoices),// sndRegret
- (FileName: 'Enemydown.ogg'; Path: ptVoices),// sndEnemyDown
- (FileName: 'Coward.ogg'; Path: ptVoices),// sndCoward
- (FileName: 'Hurry.ogg'; Path: ptVoices),// sndHurry
- (FileName: 'Watchit.ogg'; Path: ptVoices),// sndWatchIt
- (FileName: 'Kamikaze.ogg'; Path: ptVoices),// sndKamikaze
- (FileName: 'cake2.ogg'; Path: ptSounds),// sndCake
- (FileName: 'Ow1.ogg'; Path: ptVoices),// sndOw1
- (FileName: 'Ow2.ogg'; Path: ptVoices),// sndOw2
- (FileName: 'Ow3.ogg'; Path: ptVoices),// sndOw3
- (FileName: 'Ow4.ogg'; Path: ptVoices),// sndOw4
- (FileName: 'Firepunch1.ogg'; Path: ptVoices),// sndFirepunch1
- (FileName: 'Firepunch2.ogg'; Path: ptVoices),// sndFirepunch2
- (FileName: 'Firepunch3.ogg'; Path: ptVoices),// sndFirepunch3
- (FileName: 'Firepunch4.ogg'; Path: ptVoices),// sndFirepunch4
- (FileName: 'Firepunch5.ogg'; Path: ptVoices),// sndFirepunch5
- (FileName: 'Firepunch6.ogg'; Path: ptVoices),// sndFirepunch6
- (FileName: 'Melon.ogg'; Path: ptVoices),// sndMelon
- (FileName: 'Hellish.ogg'; Path: ptSounds),// sndHellish
- (FileName: 'Yoohoo.ogg'; Path: ptSounds),// sndYoohoo
- (FileName: 'rcplane.ogg'; Path: ptSounds),// sndRCPlane
- (FileName: 'whipcrack.ogg'; Path: ptSounds),// sndWhipCrack
- (FileName:'ride_of_the_valkyries.ogg'; Path: ptSounds),// sndRideOfTheValkyries
- (FileName: 'denied.ogg'; Path: ptSounds),// sndDenied
- (FileName: 'placed.ogg'; Path: ptSounds),// sndPlaced
- (FileName: 'baseballbat.ogg'; Path: ptSounds),// sndBaseballBat
- (FileName: 'steam.ogg'; Path: ptSounds),// sndVaporize
- (FileName: 'warp.ogg'; Path: ptSounds),// sndWarp
- (FileName: 'suddendeath.ogg'; Path: ptSounds),// sndSuddenDeath
- (FileName: 'mortar.ogg'; Path: ptSounds),// sndMortar
- (FileName: 'shutterclick.ogg'; Path: ptSounds),// sndShutter
- (FileName: 'homerun.ogg'; Path: ptSounds),// sndHomerun
- (FileName: 'molotov.ogg'; Path: ptSounds),// sndMolotov
- (FileName: 'Takecover.ogg'; Path: ptVoices),// sndCover
- (FileName: 'Uh-oh.ogg'; Path: ptVoices),// sndUhOh
- (FileName: 'Oops.ogg'; Path: ptVoices),// sndOops
- (FileName: 'Nooo.ogg'; Path: ptVoices),// sndNooo
- (FileName: 'Hello.ogg'; Path: ptVoices),// sndHello
- (FileName: 'ropeshot.ogg'; Path: ptSounds),// sndRopeShot
- (FileName: 'ropeattach.ogg'; Path: ptSounds),// sndRopeAttach
- (FileName: 'roperelease.ogg'; Path: ptSounds),// sndRopeRelease
- (FileName: 'switchhog.ogg'; Path: ptSounds),// sndSwitchHog
- (FileName: 'victory.ogg'; Path: ptVoices),// sndVictory
- (FileName: 'sniperreload.ogg'; Path: ptSounds),// sndSniperReload
- (FileName: 'steps.ogg'; Path: ptSounds),// sndSteps
- (FileName: 'lowgravity.ogg'; Path: ptSounds),// sndLowGravity
- (FileName: 'hell_growl.ogg'; Path: ptSounds),// sndHellishImpact1
- (FileName: 'hell_ooff.ogg'; Path: ptSounds),// sndHellishImpact2
- (FileName: 'hell_ow.ogg'; Path: ptSounds),// sndHellishImpact3
- (FileName: 'hell_ugh.ogg'; Path: ptSounds),// sndHellishImpact4
- (FileName: 'melonimpact.ogg'; Path: ptSounds),// sndMelonImpact
- (FileName: 'Droplet1.ogg'; Path: ptSounds),// sndDroplet1
- (FileName: 'Droplet2.ogg'; Path: ptSounds),// sndDroplet2
- (FileName: 'Droplet3.ogg'; Path: ptSounds),// sndDroplet3
- (FileName: 'egg.ogg'; Path: ptSounds),// sndEggBreak
- (FileName: 'drillgun.ogg'; Path: ptSounds),// sndDrillRocket
- (FileName: 'PoisonCough.ogg'; Path: ptVoices),// sndPoisonCough
- (FileName: 'PoisonMoan.ogg'; Path: ptVoices),// sndPoisonMoan
- (FileName: 'BirdyLay.ogg'; Path: ptSounds),// sndBirdyLay
- (FileName: 'Whistle.ogg'; Path: ptSounds),// sndWhistle
- (FileName: 'beewater.ogg'; Path: ptSounds),// sndBeeWater
- (FileName: '1C.ogg'; Path: ptSounds),// sndPiano0
- (FileName: '2D.ogg'; Path: ptSounds),// sndPiano1
- (FileName: '3E.ogg'; Path: ptSounds),// sndPiano2
- (FileName: '4F.ogg'; Path: ptSounds),// sndPiano3
- (FileName: '5G.ogg'; Path: ptSounds),// sndPiano4
- (FileName: '6A.ogg'; Path: ptSounds),// sndPiano5
- (FileName: '7B.ogg'; Path: ptSounds),// sndPiano6
- (FileName: '8C.ogg'; Path: ptSounds),// sndPiano7
- (FileName: '9D.ogg'; Path: ptSounds),// sndPiano8
- (FileName: 'skip.ogg'; Path: ptSounds),// sndSkip
- (FileName: 'shotgunfire.ogg'; Path: ptSounds),// sndSineGun
- (FileName: 'Ooff1.ogg'; Path: ptVoices),// sndOoff1
- (FileName: 'Ooff2.ogg'; Path: ptVoices),// sndOoff2
- (FileName: 'Ooff3.ogg'; Path: ptVoices),// sndOoff3
- (FileName: 'whipcrack.ogg'; Path: ptSounds),// sndWhack
- (FileName: 'Comeonthen.ogg'; Path: ptVoices),// sndComeonthen
- (FileName: 'parachute.ogg'; Path: ptSounds),// sndParachute
- (FileName: 'bump.ogg'; Path: ptSounds),// sndBump
- (FileName: 'hogchant3.ogg'; Path: ptSounds) // sndResurrector
- );
-
- Ammoz: array [TAmmoType] of record
- NameId: TAmmoStrId;
- NameTex: PTexture;
- Probability, NumberInCase: Longword;
- Ammo: TAmmo;
- Slot: 0..cMaxSlotIndex;
- TimeAfterTurn: Longword;
- minAngle, maxAngle: Longword;
- isDamaging: boolean;
- SkipTurns: Longword;
- PosCount: Longword;
- PosSprite: TSprite;
- ejectX, ejectY: Longint;
- end = (
- (NameId: sidNothing;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 0;
- Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_DontHold or ammoprop_Effect;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amNothing;
- AttackVoice: sndNone);
- Slot: 0;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 9999;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Grenade
- (NameId: sidGrenade;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 3000;
- Pos: 0;
- AmmoType: amGrenade;
- AttackVoice: sndCover);
- Slot: 1;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// ClusterBomb
- (NameId: sidClusterBomb;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 3;
- Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
- Count: 5;
- NumPerTurn: 0;
- Timer: 3000;
- Pos: 0;
- AmmoType: amClusterBomb;
- AttackVoice: sndCover);
- Slot: 1;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Bazooka
- (NameId: sidBazooka;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amBazooka;
- AttackVoice: sndNone);
- Slot: 0;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //20;
- ejectY: -6),
-
-// Bee
- (NameId: sidBee;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Power or ammoprop_NeedTarget or ammoprop_DontHold;
- Count: 2;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amBee;
- AttackVoice: sndNone);
- Slot: 0;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //16;
- ejectY: 0),
-
-// Shotgun
- (NameId: sidShotgun;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs;
- Count: AMMO_INFINITE;
- NumPerTurn: 1;
- Timer: 0;
- Pos: 0;
- AmmoType: amShotgun;
- AttackVoice: sndNone);
- Slot: 2;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //26;
- ejectY: -6),
-
-// PickHammer
- (NameId: sidPickHammer;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_AttackInMove or ammoprop_NoCrosshair or ammoprop_DontHold;
- Count: 2;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amPickHammer;
- AttackVoice: sndNone);
- Slot: 6;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Skip
- (NameId: sidSkip;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_DontHold;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amSkip;
- AttackVoice: sndNone);
- Slot: 9;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Rope
- (NameId: sidRope;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 3;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_ForwMsgs or
- ammoprop_AttackInMove or
- ammoprop_Utility or
- ammoprop_AltAttack;
- Count: 5;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amRope;
- AttackVoice: sndNone);
- Slot: 7;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: cMaxAngle div 2;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Mine
- (NameId: sidMine;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_AttackInMove or ammoprop_DontHold or ammoprop_AltUse;
- Count: 2;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amMine;
- AttackVoice: sndLaugh);
- Slot: 4;
- TimeAfterTurn: 5000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// DEagle
- (NameId: sidDEagle;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 2;
- Ammo: (Propz: 0;
- Count: 3;
- NumPerTurn: 3;
- Timer: 0;
- Pos: 0;
- AmmoType: amDEagle;
- AttackVoice: sndNone);
- Slot: 2;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //23;
- ejectY: -6),
-
-// Dynamite
- (NameId: sidDynamite;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_AttackInMove or ammoprop_DontHold or ammoprop_AltUse;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amDynamite;
- AttackVoice: sndLaugh);
- Slot: 4;
- TimeAfterTurn: 5000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// FirePunch
- (NameId: sidFirePunch;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_ForwMsgs or ammoprop_AttackInMove;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amFirePunch;
- AttackVoice: sndNone);
- Slot: 3;
- TimeAfterTurn: 3000;
- MinAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Whip
- (NameId: sidWhip;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amWhip;
- AttackVoice: sndNone);
- Slot: 3;
- TimeAfterTurn: 3000;
- MinAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// BaseballBat
- (NameId: sidBaseballBat;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_DontHold;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amBaseballBat;
- AttackVoice: sndNone);
- Slot: 3;
- TimeAfterTurn: 5000;
- minAngle: 0;
- maxAngle: cMaxAngle div 2;
- isDamaging: true;
- SkipTurns: 2;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Parachute
- (NameId: sidParachute;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_ForwMsgs or
- ammoprop_AttackInMove or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_Utility or
- ammoprop_AltAttack;
- Count: 2;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amParachute;
- AttackVoice: sndNone);
- Slot: 7;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// AirAttack
- (NameId: sidAirAttack;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or
- ammoprop_NeedTarget or
- ammoprop_AttackingPut or
- ammoprop_DontHold or
- ammoprop_NotBorder;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amAirAttack;
- AttackVoice: sndIncoming);
- Slot: 5;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 5;
- PosCount: 2;
- PosSprite: sprAmAirplane;
- ejectX: 0;
- ejectY: 0),
-
-// MineStrike
- (NameId: sidMineStrike;
- NameTex: nil;
- Probability: 200;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or
- ammoprop_NeedTarget or
- ammoprop_AttackingPut or
- ammoprop_DontHold or
- ammoprop_NotBorder;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amMineStrike;
- AttackVoice: sndIncoming);
- Slot: 5;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 5;
- PosCount: 2;
- PosSprite: sprAmAirplane;
- ejectX: 0;
- ejectY: 0),
-
-// BlowTorch
- (NameId: sidBlowTorch;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 2;
- Ammo: (Propz: ammoprop_ForwMsgs;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amBlowTorch;
- AttackVoice: sndNone);
- Slot: 6;
- TimeAfterTurn: 3000;
- minAngle: 768;
- maxAngle: 1280;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Girder
- (NameId: sidGirder;
- NameTex: nil;
- Probability: 150;
- NumberInCase: 3;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_NoCrosshair or
- ammoprop_NeedTarget or
- ammoprop_Utility or
- ammoprop_AttackingPut;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amGirder;
- AttackVoice: sndNone);
- Slot: 6;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 8;
- PosSprite: sprAmGirder;
- ejectX: 0;
- ejectY: 0),
-
-// Teleport
- (NameId: sidTeleport;
- NameTex: nil;
- Probability: 200;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or
- ammoprop_NoCrosshair or
- ammoprop_NeedTarget or
- ammoprop_AttackingPut or
- ammoprop_Utility or
- ammoprop_DontHold;
- Count: 2;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amTeleport;
- AttackVoice: sndNone);
- Slot: 7;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 2;
- PosSprite: sprAmTeleport;
- ejectX: 0;
- ejectY: 0),
-
-// Switch
- (NameId: sidSwitch;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_ForwMsgs or
- ammoprop_NoCrosshair or
- ammoprop_Utility or
- ammoprop_DontHold;
- Count: 3;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amSwitch;
- AttackVoice: sndNone);
- Slot: 9;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Mortar
- (NameId: sidMortar;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 4;
- Ammo: (Propz: 0;
- Count: 4;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amMortar;
- AttackVoice: sndNone);
- Slot: 0;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //20;
- ejectY: -6),
-
-// Kamikaze
- (NameId: sidKamikaze;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold or ammoprop_AttackInMove;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amKamikaze;
- AttackVoice: sndNone);
- Slot: 3;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Cake
- (NameId: sidCake;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_NoCrosshair or ammoprop_DontHold;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amCake;
- AttackVoice: sndLaugh);
- Slot: 4;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 4;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Seduction
- (NameId: sidSeduction;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amSeduction;
- AttackVoice: sndNone);
- Slot: 3;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Watermelon
- (NameId: sidWatermelon;
- NameTex: nil;
- Probability: 400;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
- Count: 0;
- NumPerTurn: 0;
- Timer: 3000;
- Pos: 0;
- AmmoType: amWatermelon;
- AttackVoice: sndMelon);
- Slot: 1;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// HellishBomb ("Hellish Hand-Grenade")
- (NameId: sidHellishBomb;
- NameTex: nil;
- Probability: 400;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
- Count: 0;
- NumPerTurn: 0;
- Timer: 5000;
- Pos: 0;
- AmmoType: amHellishBomb;
- AttackVoice: sndNone);
- Slot: 1;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Napalm
- (NameId: sidNapalm;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or
- ammoprop_NeedTarget or
- ammoprop_AttackingPut or
- ammoprop_DontHold or
- ammoprop_NotBorder;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amNapalm;
- AttackVoice: sndIncoming);
- Slot: 5;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 7;
- PosCount: 2;
- PosSprite: sprAmAirplane;
- ejectX: 0;
- ejectY: 0),
-
-// Drill ("Drill Rocket")
- (NameId: sidDrill;
- NameTex: nil;
- Probability: 300;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amDrill;
- AttackVoice: sndNone);
- Slot: 0;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprDrill;
- ejectX: 0; //20;
- ejectY: -6),
-
-// Ballgun
- (NameId: sidBallgun;
- NameTex: nil;
- Probability: 400;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 5001;
- Pos: 0;
- AmmoType: amBallgun;
- AttackVoice: sndNone);
- Slot: 4;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //20;
- ejectY: -3),
-
-// RC-Plane
- (NameId: sidRCPlane;
- NameTex: nil;
- Probability: 200;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs{ or
- ammoprop_DontHold or
- ammoprop_AltAttack};
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amRCPlane;
- AttackVoice: sndNone);
- Slot: 4;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 4;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// LowGravity
- (NameId: sidLowGravity;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_AltUse or
- ammoprop_Utility or
- ammoprop_Effect;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amLowGravity;
- AttackVoice: sndNone);
- Slot: 9;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// ExtraDamage
- (NameId: sidExtraDamage;
- NameTex: nil;
- Probability: 15;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_AltUse or
- ammoprop_Utility or
- ammoprop_Effect;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amExtraDamage;
- AttackVoice: sndNone);
- Slot: 9;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Invulnerable
- (NameId: sidInvulnerable;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_AltUse or
- ammoprop_Utility or
- ammoprop_Effect;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amInvulnerable;
- AttackVoice: sndNone);
- Slot: 8;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// ExtraTime
- (NameId: sidExtraTime;
- NameTex: nil;
- Probability: 30;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_AltUse or
- ammoprop_Utility or
- ammoprop_Effect;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amExtraTime;
- AttackVoice: sndNone);
- Slot: 9;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// LaserSight
- (NameId: sidLaserSight;
- NameTex: nil;
- Probability: 15;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_AltUse or
- ammoprop_Utility or
- ammoprop_Effect;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amLaserSight;
- AttackVoice: sndNone);
- Slot: 8;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Vampiric
- (NameId: sidVampiric;
- NameTex: nil;
- Probability: 15;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_AltUse or
- ammoprop_Utility or
- ammoprop_Effect;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amVampiric;
- AttackVoice: sndNone);
- Slot: 8;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// SniperRifle
- (NameId: sidSniperRifle;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 2;
- Ammo: (Propz: 0;
- Count: 2;
- NumPerTurn: 1;
- Timer: 0;
- Pos: 0;
- AmmoType: amSniperRifle;
- AttackVoice: sndNone);
- Slot: 2;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //40;
- ejectY: -5),
-
-// Jetpack ("Flying Saucer")
- (NameId: sidJetpack;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_ForwMsgs or
- ammoprop_AttackInMove or
- ammoprop_NoCrosshair or
- ammoprop_DontHold or
- ammoprop_Utility or
- ammoprop_AltAttack;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amJetpack;
- AttackVoice: sndNone);
- Slot: 7;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Molotov
- (NameId: sidMolotov;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 3000;
- Pos: 0;
- AmmoType: amMolotov;
- AttackVoice: sndNone);
- Slot: 1;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Birdy
- (NameId: sidBirdy;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or
- ammoprop_NoCrosshair or
- ammoprop_DontHold;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amBirdy;
- AttackVoice: sndNone);
- Slot: 7;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// PortalGun
- (NameId: sidPortalGun;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoRoundEnd or
- ammoprop_AttackInMove or
- ammoprop_DontHold or
- ammoprop_Utility;
- Count: 1;
- NumPerTurn: 3;
- Timer: 0;
- Pos: 0;
- AmmoType: amPortalGun;
- AttackVoice: sndNone);
- Slot: 6;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: false;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: -5; //29;
- ejectY: -7),
-
-// Piano
- (NameId: sidPiano;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or
- ammoprop_NeedTarget or
- ammoprop_AttackingPut or
- ammoprop_DontHold or
- ammoprop_NotBorder;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amPiano;
- AttackVoice: sndIncoming);
- Slot: 5;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 7;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// GasBomb
- (NameId: sidGasBomb;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
- Count: AMMO_INFINITE;
- NumPerTurn: 0;
- Timer: 3000;
- Pos: 0;
- AmmoType: amGasBomb;
- AttackVoice: sndCover);
- Slot: 1;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// SineGun
- (NameId: sidSineGun;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 2;
- Ammo: (Propz: ammoprop_AttackInMove;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amSineGun;
- AttackVoice: sndNone);
- Slot: 2;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Flamethrower
- (NameId: sidFlamethrower;
- NameTex: nil;
- Probability: 20;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold;
- Count: 1;
- NumPerTurn: 0;
- Timer: 5001;
- Pos: 0;
- AmmoType: amFlamethrower;
- AttackVoice: sndNone);
- Slot: 2;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0; //20;
- ejectY: -3),
-
-// Sticky Mine
- (NameId: sidSMine;
- NameTex: nil;
- Probability: 100;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_Power; //FIXME: enable multishoot at altuse, until then removed ammoprop_AltUse
- Count: 1;
- NumPerTurn: 1;
- Timer: 0;
- Pos: 0;
- AmmoType: amSMine;
- AttackVoice: sndLaugh);
- Slot: 4;
- TimeAfterTurn: 5000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Hammer
- (NameId: sidHammer;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amHammer;
- AttackVoice: sndNone);
- Slot: 3;
- TimeAfterTurn: 1000;
- MinAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// Ressurrector
- (NameId: sidResurrector;
- NameTex: nil;
- Probability: 0;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or
- ammoprop_Utility or
- ammoprop_NoRoundEnd;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amResurrector;
- AttackVoice: sndNone);
- Slot: 8;
- TimeAfterTurn: 3000;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 0;
- PosCount: 1;
- PosSprite: sprWater;
- ejectX: 0;
- ejectY: 0),
-
-// DrillStrike
- (NameId: sidDrillStrike;
- NameTex: nil;
- Probability: 200;
- NumberInCase: 1;
- Ammo: (Propz: ammoprop_NoCrosshair or
- ammoprop_NeedTarget or
- ammoprop_AttackingPut or
- ammoprop_DontHold or
- ammoprop_NotBorder;
- Count: 1;
- NumPerTurn: 0;
- Timer: 0;
- Pos: 0;
- AmmoType: amDrillStrike;
- AttackVoice: sndIncoming);
- Slot: 5;
- TimeAfterTurn: 0;
- minAngle: 0;
- maxAngle: 0;
- isDamaging: true;
- SkipTurns: 6;
- PosCount: 2;
- PosSprite: sprAmAirplane;
- ejectX: 0;
- ejectY: 0)
- );
-
-
-
- conversionFormat: TSDL_PixelFormat = (
- palette: nil;
- BitsPerPixel : 32;
- BytesPerPixel: 4;
- Rloss : 0;
- Gloss : 0;
- Bloss : 0;
- Aloss : 0;
-{$IFDEF ENDIAN_LITTLE}
- Rshift: 0;
- Gshift: 8;
- Bshift: 16;
- Ashift: 24;
-{$ELSE}
- Rshift: 24;
- Gshift: 16;
- Bshift: 8;
- Ashift: 0;
-{$ENDIF}
- RMask : RMask;
- GMask : GMask;
- BMask : BMask;
- AMask : AMask;
- colorkey: 0;
- alpha : 255
- );
implementation
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uDebug.pas
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uDebug.pas Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,35 @@
+{$INCLUDE "options.inc"}
+
+unit uDebug;
+
+interface
+
+procedure OutError(Msg: shortstring; isFatalError: boolean);
+procedure TryDo(Assert: boolean; Msg: shortstring; isFatal: boolean); inline;
+procedure SDLTry(Assert: boolean; isFatal: boolean);
+
+implementation
+uses SDLh, uConsole, uCommands;
+
+procedure OutError(Msg: shortstring; isFatalError: boolean);
+begin
+WriteLnToConsole(Msg);
+if isFatalError then
+ begin
+ ParseCommand('fatal ' + GetLastConsoleLine, true);
+ SDL_Quit;
+ halt(1)
+ end
+end;
+
+procedure TryDo(Assert: boolean; Msg: shortstring; isFatal: boolean);
+begin
+if not Assert then OutError(Msg, isFatal)
+end;
+
+procedure SDLTry(Assert: boolean; isFatal: boolean);
+begin
+if not Assert then OutError(SDL_GetError, isFatal)
+end;
+
+end.
\ No newline at end of file
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uFloat.pas
--- a/hedgewars/uFloat.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uFloat.pas Tue Jan 04 12:53:46 2011 +0100
@@ -62,6 +62,7 @@
function AngleSin(const Angle: Longword): hwFloat;
function AngleCos(const Angle: Longword): hwFloat;
function SignAs(const num, signum: hwFloat): hwFloat; inline;
+function hwSign(r: hwFloat): LongInt; inline;
{$IFDEF FPC}
{$J-}
@@ -147,7 +148,7 @@
{$ENDIF}
implementation
-//uses uMisc;
+uses uSinTable;
{$IFDEF FPC}
@@ -342,7 +343,12 @@
SignAs.isNegative:= signum.isNegative
end;
-{$INCLUDE "SinTable.inc"}
+function hwSign(r: hwFloat): LongInt;
+begin
+// yes, we have negative zero for a reason
+if r.isNegative then hwSign:= -1 else hwSign:= 1
+end;
+
function AngleSin(const Angle: Longword): hwFloat;
begin
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uGame.pas
--- a/hedgewars/uGame.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uGame.pas Tue Jan 04 12:53:46 2011 +0100
@@ -26,7 +26,7 @@
////////////////////
implementation
////////////////////
-uses uMisc, uConsts, uKeys, uTeams, uIO, uAI, uGears, uScript, uSound, uMobile, uVisualGears;
+uses uKeys, uTeams, uIO, uAI, uGears, uSound, uMobile, uVisualGears, uTypes, uVariables;
procedure DoGameTick(Lag: LongInt);
var i: LongInt;
@@ -45,7 +45,6 @@
i:= 1;
while (GameState <> gsExit) and (i <= Lag) do
begin
- ScriptCall('onGameTick');
if not CurrentTeam^.ExtDriven then
begin
if CurrentHedgehog^.BotLevel <> 0 then ProcessBot;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uGears.pas
--- a/hedgewars/uGears.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uGears.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,63 +20,7 @@
unit uGears;
interface
-uses SDLh, uConsts, uFloat, Math;
-
-
-type
- PGear = ^TGear;
- TGearStepProcedure = procedure (Gear: PGear);
- TGear = record
- NextGear, PrevGear: PGear;
- Active: Boolean;
- AdvBounce: Longword;
- Invulnerable: Boolean;
- RenderTimer: Boolean;
- AmmoType : TAmmoType;
- State : Longword;
- X : hwFloat;
- Y : hwFloat;
- dX: hwFloat;
- dY: hwFloat;
- Kind: TGearType;
- Pos: Longword;
- doStep: TGearStepProcedure;
- Radius: LongInt;
- Angle, Power : Longword;
- DirAngle: real;
- Timer : LongWord;
- Elasticity: hwFloat;
- Friction : hwFloat;
- Message, MsgParam : Longword;
- Hedgehog: pointer;
- Health, Damage, Karma: LongInt;
- CollisionIndex: LongInt;
- Tag: LongInt;
- Tex: PTexture;
- Z: Longword;
- IntersectGear: PGear;
- FlightTime: Longword;
- uid: Longword;
- ImpactSound: TSound; // first sound, others have to be after it in the sounds def.
- nImpactSounds: Word; // count of ImpactSounds
- SoundChannel: LongInt;
- PortalCounter: LongWord // Hopefully temporary, but avoids infinite portal loops in a guaranteed fashion.
- end;
- TPGearArray = Array of PGear;
-
-var AllInactive: boolean;
- PrvInactive: boolean;
- CurAmmoGear: PGear;
- GearsList: PGear;
- KilledHHs: Longword;
- SuddenDeathDmg: Boolean;
- SpeechType: Longword;
- SpeechText: shortstring;
- TrainingTargetGear: PGear;
- skipFlag: boolean;
- PlacingHogs: boolean; // a convenience flag to indicate placement of hogs is still in progress
- StepSoundTimer: LongInt;
- StepSoundChannel: LongInt;
+uses SDLh, uConsts, uFloat, uTypes;
procedure initModule;
procedure freeModule;
@@ -96,27 +40,16 @@
procedure InsertGearToList(Gear: PGear);
procedure RemoveGearFromList(Gear: PGear);
function ModifyDamage(dmg: Longword; Gear: PGear): Longword;
-procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt);
-function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt;
-function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt;
+procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean = false);
+procedure DeleteGear(Gear: PGear);
+
implementation
-uses uWorld, uMisc, uStore, uConsole, uSound, uTeams, uRandom, uCollisions, uLand, uIO, uLandGraphics,
- uAIMisc, uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile;
+uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics,
+ uAIMisc, uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile, uVariables,
+ uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture;
-const MAXROPEPOINTS = 384;
-var RopePoints: record
- Count: Longword;
- HookAngle: GLfloat;
- ar: array[0..MAXROPEPOINTS] of record
- X, Y: hwFloat;
- dLen: hwFloat;
- b: boolean;
- end;
- rounded: array[0..MAXROPEPOINTS + 2] of TVertex2f;
- end;
-procedure DeleteGear(Gear: PGear); forward;
procedure doMakeExplosion(X, Y, Radius: LongInt; Mask: LongWord); forward;
procedure doMakeExplosion(X, Y, Radius: LongInt; Mask, Tint: LongWord); forward;
procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
@@ -133,22 +66,6 @@
procedure HHSetWeapon(Gear: PGear); forward;
procedure doStepCase(Gear: PGear); forward;
-function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt;
-begin
- if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then
- GetLaunchX:= sign(dir) * (8 + hwRound(AngleSin(angle) * Ammoz[at].ejectX) + hwRound(AngleCos(angle) * Ammoz[at].ejectY))
- else
- GetLaunchX:= 0
-end;
-
-function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt;
-begin
- if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then
- GetLaunchY:= hwRound(AngleSin(angle) * Ammoz[at].ejectY) - hwRound(AngleCos(angle) * Ammoz[at].ejectX) - 2
- else
- GetLaunchY:= 0
-end;
-
{$INCLUDE "GSHandlers.inc"}
{$INCLUDE "HHHandlers.inc"}
@@ -210,7 +127,9 @@
@doStepHammer,
@doStepHammerHit,
@doStepResurrector,
- @doStepNapalmBomb
+ @doStepNapalmBomb,
+ @doStepSnowball,
+ @doStepSnowflake
);
procedure InsertGearToList(Gear: PGear);
@@ -253,7 +172,7 @@
begin
tag:= AddVisualGear(hwRound(HHGear^.X), hwRound(HHGear^.Y), vgtHealthTag, dmg);
if (tag <> nil) then
- tag^.Hedgehog:= PHedgehog(HHGear^.Hedgehog); // the tag needs the tag to determine the text color
+ tag^.Hedgehog:= HHGear^.Hedgehog; // the tag needs the tag to determine the text color
AllInactive:= false;
HHGear^.Active:= true;
end;
@@ -302,6 +221,7 @@
gear^.Radius:= 5;
gear^.Elasticity:= _0_8;
gear^.Friction:= _0_8;
+ gear^.Density:= _1_5;
gear^.RenderTimer:= true;
if gear^.Timer = 0 then gear^.Timer:= 3000
end;
@@ -312,22 +232,49 @@
gear^.Radius:= 6;
gear^.Elasticity:= _0_8;
gear^.Friction:= _0_995;
+ gear^.Density:= _2;
gear^.RenderTimer:= true;
if gear^.Timer = 0 then gear^.Timer:= 3000
end;
+ gtMelonPiece: begin
+ gear^.Density:= _2;
+ end;
gtHedgehog: begin
gear^.AdvBounce:= 1;
gear^.Radius:= cHHRadius;
gear^.Elasticity:= _0_35;
gear^.Friction:= _0_999;
gear^.Angle:= cMaxAngle div 2;
+ gear^.Density:= _3;
gear^.Z:= cHHZ;
if (GameFlags and gfAISurvival) <> 0 then
- if PHedgehog(gear^.Hedgehog)^.BotLevel > 0 then
- PHedgehog(gear^.Hedgehog)^.Effects[heResurrectable] := true;
+ if gear^.Hedgehog^.BotLevel > 0 then
+ gear^.Hedgehog^.Effects[heResurrectable] := true;
end;
gtShell: begin
gear^.Radius:= 4;
+ gear^.Density:= _1;
+ end;
+ gtSnowball: begin
+ gear^.Radius:= 4;
+ gear^.Elasticity:= _1;
+ gear^.Friction:= _1;
+ gear^.Density:= _0_5;
+ end;
+
+ gtFlake: begin
+ with Gear^ do
+ begin
+ DirAngle:= random * 360;
+ dx.isNegative:= GetRandom(2) = 0;
+ dx.QWordValue:= GetRandom(100000000);
+ dy.isNegative:= false;
+ dy.QWordValue:= GetRandom(70000000);
+ if GetRandom(2) = 0 then dx := -dx;
+ Health:= random(vobFrameTicks);
+ Timer:= random(vobFramesCount);
+ Angle:= (random(2) * 2 - 1) * (1 + random(10000)) * vobVelocity
+ end
end;
gtGrave: begin
gear^.ImpactSound:= sndGraveImpact;
@@ -356,7 +303,7 @@
end;
gtRope: begin
gear^.Radius:= 3;
- gear^.Friction:= _450;
+ gear^.Friction:= _450 * _0_01 * cRopePercent;
RopePoints.Count:= 0;
end;
gtMine: begin
@@ -365,10 +312,11 @@
gear^.Radius:= 2;
gear^.Elasticity:= _0_55;
gear^.Friction:= _0_995;
+ gear^.Density:= _0_9;
if cMinesTime < 0 then
gear^.Timer:= getrandom(51)*100
else
- gear^.Timer:= cMinesTime*1000;
+ gear^.Timer:= cMinesTime;
end;
gtSMine: begin
gear^.Health:= 10;
@@ -376,6 +324,7 @@
gear^.Radius:= 2;
gear^.Elasticity:= _0_55;
gear^.Friction:= _0_995;
+ gear^.Density:= _0_9;
gear^.Timer:= 500;
end;
gtCase: begin
@@ -390,6 +339,7 @@
gear^.Radius:= 16;
gear^.Elasticity:= _0_4;
gear^.Friction:= _0_995;
+ gear^.Density:= _6;
gear^.Health:= cBarrelHealth
end;
gtDEagleShot: begin
@@ -404,10 +354,12 @@
gear^.Radius:= 3;
gear^.Elasticity:= _0_55;
gear^.Friction:= _0_03;
+ gear^.Density:= _2;
gear^.Timer:= 5000;
end;
gtCluster: begin
gear^.Radius:= 2;
+ gear^.Density:= _1_5;
gear^.RenderTimer:= true
end;
gtShover: gear^.Radius:= 20;
@@ -415,6 +367,7 @@
gear^.Tag:= GetRandom(32);
gear^.Radius:= 1;
gear^.Health:= 5;
+ gear^.Density:= _1;
if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then
begin
gear^.dY:= (getrandom - _0_8) * _0_03;
@@ -427,6 +380,7 @@
end;
gtAirBomb: begin
gear^.Radius:= 5;
+ gear^.Density:= _2;
end;
gtBlowTorch: begin
gear^.Radius:= cHHRadius + cBlowTorchC;
@@ -445,7 +399,8 @@
gtMortar: begin
gear^.Radius:= 4;
gear^.Elasticity:= _0_2;
- gear^.Friction:= _0_08
+ gear^.Friction:= _0_08;
+ gear^.Density:= _1;
end;
gtWhip: gear^.Radius:= 20;
gtHammer: gear^.Radius:= 20;
@@ -468,12 +423,14 @@
gear^.Radius:= 4;
gear^.Elasticity:= _0_5;
gear^.Friction:= _0_96;
+ gear^.Density:= _1_5;
gear^.RenderTimer:= true;
gear^.Timer:= 5000
end;
gtDrill: begin
gear^.Timer:= 5000;
- gear^.Radius:= 4
+ gear^.Radius:= 4;
+ gear^.Density:= _1;
end;
gtBall: begin
gear^.ImpactSound:= sndGrenadeImpact;
@@ -484,6 +441,7 @@
gear^.Timer:= 5000;
gear^.Elasticity:= _0_7;
gear^.Friction:= _0_995;
+ gear^.Density:= _1_5;
end;
gtBallgun: begin
gear^.Timer:= 5001;
@@ -499,6 +457,7 @@
end;
gtMolotov: begin
gear^.Radius:= 6;
+ gear^.Density:= _2;
end;
gtBirdy: begin
gear^.Radius:= 16; // todo: check
@@ -510,6 +469,7 @@
gear^.Radius:= 4;
gear^.Elasticity:= _0_6;
gear^.Friction:= _0_96;
+ gear^.Density:= _1;
if gear^.Timer = 0 then gear^.Timer:= 3000
end;
gtPortal: begin
@@ -517,13 +477,15 @@
gear^.nImpactSounds:= 1;
gear^.AdvBounce:= 0;
gear^.Radius:= 16;
- gear^.Tag:= 0;
+ // set color
+ gear^.Tag:= 2 * gear^.Timer;
gear^.Timer:= 15000;
gear^.RenderTimer:= false;
gear^.Health:= 100;
end;
gtPiano: begin
- gear^.Radius:= 32
+ gear^.Radius:= 32;
+ gear^.Density:= _50;
end;
gtSineGunShot: begin
gear^.Radius:= 5;
@@ -549,6 +511,7 @@
gtNapalmBomb: begin
gear^.Timer:= 1000;
gear^.Radius:= 5;
+ gear^.Density:= _1_5;
end;
end;
@@ -594,17 +557,17 @@
begin
t:= max(Gear^.Damage, Gear^.Health);
Gear^.Damage:= t;
- if (cWaterOpacity < $FF) and (hwRound(Gear^.Y) < cWaterLine + 256) then
+ if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cWaterOpacity < $FF))) and (hwRound(Gear^.Y) < cWaterLine + 256) then
spawnHealthTagForHH(Gear, t);
uStats.HedgehogDamaged(Gear)
end;
- team:= PHedgehog(Gear^.Hedgehog)^.Team;
+ team:= Gear^.Hedgehog^.Team;
if CurrentHedgehog^.Gear = Gear then
FreeActionsList; // to avoid ThinkThread on drawned gear
- PHedgehog(Gear^.Hedgehog)^.Gear:= nil;
- if PHedgehog(Gear^.Hedgehog)^.King then
+ Gear^.Hedgehog^.Gear:= nil;
+ if Gear^.Hedgehog^.King then
begin
// are there any other kings left? Just doing nil check. Presumably a mortally wounded king will get reaped soon enough
k:= false;
@@ -618,7 +581,14 @@
end
end;
inc(KilledHHs);
- RecountTeamHealth(team)
+ RecountTeamHealth(team);
+ if (CurrentHedgehog <> nil) and CurrentHedgehog^.Effects[heResurrectable] and not Gear^.Hedgehog^.Effects[heResurrectable] then
+ with CurrentHedgehog^ do
+ begin
+ inc(Team^.stats.AIKills);
+ if Team^.AIKillsTex <> nil then FreeTexture(Team^.AIKillsTex);
+ Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
+ end
end;
{$IFDEF DEBUGFILE}
with Gear^ do AddFileLog('Delete: #' + inttostr(uid) + ' (' + inttostr(hwRound(x)) + ',' + inttostr(hwRound(y)) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
@@ -626,6 +596,7 @@
if CurAmmoGear = Gear then CurAmmoGear:= nil;
if FollowGear = Gear then FollowGear:= nil;
+if lastGearByUID = Gear then lastGearByUID := nil;
RemoveGearFromList(Gear);
Dispose(Gear)
end;
@@ -655,17 +626,17 @@
else
dec(Gear^.Health, dmg);
- if (PHedgehog(Gear^.Hedgehog)^.Team = CurrentTeam) and
+ if (Gear^.Hedgehog^.Team = CurrentTeam) and
(Gear^.Damage <> Gear^.Karma) and
- not PHedgehog(Gear^.Hedgehog)^.King and
- not PHedgehog(Gear^.Hedgehog)^.Effects[hePoisoned] and
+ not Gear^.Hedgehog^.King and
+ not Gear^.Hedgehog^.Effects[hePoisoned] and
not SuddenDeathDmg then
Gear^.State:= Gear^.State or gstLoser;
spawnHealthTagForHH(Gear, dmg);
- RenderHealth(PHedgehog(Gear^.Hedgehog)^);
- RecountTeamHealth(PHedgehog(Gear^.Hedgehog)^.Team);
+ RenderHealth(Gear^.Hedgehog^);
+ RecountTeamHealth(Gear^.Hedgehog^.Team);
end;
if (not isInMultiShoot) then Gear^.Karma:= 0;
@@ -689,20 +660,20 @@
if Gear^.Kind = gtHedgehog then
begin
tmp:= 0;
- if PHedgehog(Gear^.Hedgehog)^.Effects[hePoisoned] then
+ if Gear^.Hedgehog^.Effects[hePoisoned] then
begin
inc(tmp, ModifyDamage(5, Gear));
- if (GameFlags and gfResetHealth) <> 0 then dec(PHedgehog(Gear^.Hedgehog)^.InitialHealth) // does not need a minimum check since <= 1 basically disables it
+ if (GameFlags and gfResetHealth) <> 0 then dec(Gear^.Hedgehog^.InitialHealth) // does not need a minimum check since <= 1 basically disables it
end;
if (TotalRounds > cSuddenDTurns - 1) then
begin
inc(tmp, cHealthDecrease);
- if (GameFlags and gfResetHealth) <> 0 then dec(PHedgehog(Gear^.Hedgehog)^.InitialHealth, cHealthDecrease)
+ if (GameFlags and gfResetHealth) <> 0 then dec(Gear^.Hedgehog^.InitialHealth, cHealthDecrease)
end;
- if PHedgehog(Gear^.Hedgehog)^.King then
+ if Gear^.Hedgehog^.King then
begin
flag:= false;
- team:= PHedgehog(Gear^.Hedgehog)^.Team;
+ team:= Gear^.Hedgehog^.Team;
for i:= 0 to Pred(team^.HedgehogsNumber) do
if (team^.Hedgehogs[i].Gear <> nil) and
(not team^.Hedgehogs[i].King) and
@@ -711,7 +682,7 @@
if not flag then
begin
inc(tmp, 5);
- if (GameFlags and gfResetHealth) <> 0 then dec(PHedgehog(Gear^.Hedgehog)^.InitialHealth, 5)
+ if (GameFlags and gfResetHealth) <> 0 then dec(Gear^.Hedgehog^.InitialHealth, 5)
end
end;
if tmp > 0 then
@@ -764,7 +735,7 @@
end;
Gear^.doStep(Gear);
// might be useful later
- //ScriptCall('OnGearStep', Gear^.uid);
+ //ScriptCall('onGearStep', Gear^.uid);
end
end;
@@ -822,11 +793,19 @@
stHealth: begin
if (cWaterRise <> 0) or (cHealthDecrease <> 0) then
begin
- if (TotalRounds = cSuddenDTurns) and not SuddenDeathDmg and not isInMultiShoot then
+ if (TotalRounds = cSuddenDTurns) and not SuddenDeath and not isInMultiShoot then
begin
- SuddenDeathDmg:= true;
+ SuddenDeath:= true;
+ if cHealthDecrease <> 0 then
+ begin
+ SuddenDeathDmg:= true;
+ ChangeToSDClouds;
+ ChangeToSDFlakes;
+ end;
AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
- playSound(sndSuddenDeath)
+ playSound(sndSuddenDeath);
+ MusicFN:= SDMusic;
+ ChangeMusic
end
else if (TotalRounds < cSuddenDTurns) and not isInMultiShoot then
begin
@@ -939,6 +918,7 @@
inc(hiTicks) // we do not recieve a message for this
end;
+ScriptCall('onGameTick');
inc(GameTicks)
end;
@@ -951,7 +931,10 @@
SpeechText:= ''; // in case it has not been consumed
if (GameFlags and gfLowGravity) = 0 then
+ begin
cGravity:= cMaxWindSpeed * 2;
+ cGravityf:= 0.00025 * 2
+ end;
if (GameFlags and gfVampiric) = 0 then
cVampiric:= false;
@@ -969,11 +952,13 @@
for i:= 0 to cMaxHHIndex do
with Hedgehogs[i] do
begin
+(*
if (SpeechGear <> nil) then
begin
DeleteVisualGear(SpeechGear); // remove to restore persisting beyond end of turn. Tiy says was too much of a gameplay issue
SpeechGear:= nil
end;
+*)
if (Gear <> nil) then
begin
@@ -985,15 +970,15 @@
while t <> nil do
begin
t^.PortalCounter:= 0;
- if ((GameFlags and gfResetHealth) <> 0) and (t^.Kind = gtHedgehog) and (t^.Health < PHedgehog(t^.Hedgehog)^.InitialHealth) then
+ if ((GameFlags and gfResetHealth) <> 0) and (t^.Kind = gtHedgehog) and (t^.Health < t^.Hedgehog^.InitialHealth) then
begin
- t^.Health:= PHedgehog(t^.Hedgehog)^.InitialHealth;
- RenderHealth(PHedgehog(t^.Hedgehog)^);
+ t^.Health:= t^.Hedgehog^.InitialHealth;
+ RenderHealth(t^.Hedgehog^);
end;
t:= t^.NextGear
end;
- if (GameFlags and gfResetWeps) <> 0 then
+ if ((GameFlags and gfResetWeps) <> 0) and not PlacingHogs then
ResetWeapons;
if (GameFlags and gfResetHealth) <> 0 then
@@ -1009,7 +994,7 @@
if (Gear^.Kind = gtHedgehog) and (Damage>=1) then
begin
HHHurt(Gear^.Hedgehog, Source);
- AddDamageTag(hwRound(Gear^.X), hwRound(Gear^.Y), Damage, PHedgehog(Gear^.Hedgehog)^.Team^.Clan^.Color);
+ AddDamageTag(hwRound(Gear^.X), hwRound(Gear^.Y), Damage, Gear^.Hedgehog^.Team^.Clan^.Color);
tmpDmg:= min(Damage, max(0,Gear^.Health-Gear^.Damage));
if (Gear <> CurrentHedgehog^.Gear) and (CurrentHedgehog^.Gear <> nil) and (tmpDmg >= 1) then
begin
@@ -1045,7 +1030,7 @@
end;
end;
inc(Gear^.Damage, Damage);
- ScriptCall('OnGearDamage', Gear^.UID, Damage);
+ ScriptCall('onGearDamage', Gear^.UID, Damage);
end;
procedure SetAllToActive;
@@ -1072,151 +1057,21 @@
end
end;
-procedure DrawAltWeapon(Gear: PGear; sx, sy: LongInt);
+
+procedure DrawGears;
+var Gear: PGear;
+ x, y: LongInt;
begin
-with PHedgehog(Gear^.Hedgehog)^ do
+Gear:= GearsList;
+while Gear <> nil do
begin
- if not (((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) and ((Gear^.State and gstAttacked) = 0)) then
- exit;
- DrawTexture(sx + 16, sy + 16, ropeIconTex);
- DrawTextureF(SpritesData[sprAMAmmos].Texture, 0.75, sx + 30, sy + 30, ord(CurAmmoType) - 1, 1, 32, 32);
+ x:= hwRound(Gear^.X) + WorldDx;
+ y:= hwRound(Gear^.Y) + WorldDy;
+ RenderGear(Gear, x, y);
+ Gear:= Gear^.NextGear
end;
end;
-procedure DrawRopeLinesRQ(Gear: PGear);
-begin
-with RopePoints do
- begin
- rounded[Count].X:= hwRound(Gear^.X);
- rounded[Count].Y:= hwRound(Gear^.Y);
- rounded[Count + 1].X:= hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.X);
- rounded[Count + 1].Y:= hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.Y);
- end;
-
-if (RopePoints.Count > 0) or (Gear^.Elasticity.QWordValue > 0) then
- begin
- glDisable(GL_TEXTURE_2D);
- //glEnable(GL_LINE_SMOOTH);
-
- glPushMatrix;
-
- glTranslatef(WorldDx, WorldDy, 0);
-
- glLineWidth(4.0);
-
- Tint($C0, $C0, $C0, $FF);
-
- glVertexPointer(2, GL_FLOAT, 0, @RopePoints.rounded[0]);
- glDrawArrays(GL_LINE_STRIP, 0, RopePoints.Count + 2);
- Tint($FF, $FF, $FF, $FF);
-
- glPopMatrix;
-
- glEnable(GL_TEXTURE_2D);
- //glDisable(GL_LINE_SMOOTH)
- end
-end;
-
-procedure DrawRope(Gear: PGear);
-var roplen: LongInt;
- i: Longword;
-
- procedure DrawRopeLine(X1, Y1, X2, Y2: LongInt);
- var eX, eY, dX, dY: LongInt;
- i, sX, sY, x, y, d: LongInt;
- b: boolean;
- begin
- if (X1 = X2) and (Y1 = Y2) then
- begin
- //OutError('WARNING: zero length rope line!', false);
- exit
- end;
- eX:= 0;
- eY:= 0;
- dX:= X2 - X1;
- dY:= Y2 - Y1;
-
- if (dX > 0) then sX:= 1
- else
- if (dX < 0) then
- begin
- sX:= -1;
- dX:= -dX
- end else sX:= dX;
-
- if (dY > 0) then sY:= 1
- else
- if (dY < 0) then
- begin
- sY:= -1;
- dY:= -dY
- end else sY:= dY;
-
- if (dX > dY) then d:= dX
- else d:= dY;
-
- x:= X1;
- y:= Y1;
-
- for i:= 0 to d do
- begin
- inc(eX, dX);
- inc(eY, dY);
- b:= false;
- if (eX > d) then
- begin
- dec(eX, d);
- inc(x, sX);
- b:= true
- end;
- if (eY > d) then
- begin
- dec(eY, d);
- inc(y, sY);
- b:= true
- end;
- if b then
- begin
- inc(roplen);
- if (roplen mod 4) = 0 then DrawSprite(sprRopeNode, x - 2, y - 2, 0)
- end
- end
- end;
-begin
- if (cReducedQuality and rqSimpleRope) <> 0 then
- DrawRopeLinesRQ(Gear)
- else
- begin
- roplen:= 0;
- if RopePoints.Count > 0 then
- begin
- i:= 0;
- while i < Pred(RopePoints.Count) do
- begin
- DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy,
- hwRound(RopePoints.ar[Succ(i)].X) + WorldDx, hwRound(RopePoints.ar[Succ(i)].Y) + WorldDy);
- inc(i)
- end;
- DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy,
- hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy);
- DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy,
- hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.X) + WorldDx, hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.Y) + WorldDy);
- end else
- if Gear^.Elasticity.QWordValue > 0 then
- DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy,
- hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.X) + WorldDx, hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.Y) + WorldDy);
- end;
-
-
-if RopePoints.Count > 0 then
- DrawRotated(sprRopeHook, hwRound(RopePoints.ar[0].X) + WorldDx, hwRound(RopePoints.ar[0].Y) + WorldDy, 1, RopePoints.HookAngle)
- else
- if Gear^.Elasticity.QWordValue > 0 then
- DrawRotated(sprRopeHook, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
-end;
-
-{$INCLUDE "GearDrawing.inc"}
-
procedure FreeGearsList;
var t, tt: PGear;
begin
@@ -1236,12 +1091,6 @@
begin
AddGear(0, 0, gtATStartGame, 0, _0, _0, 2000);
-if (TrainingFlags and tfSpawnTargets) <> 0 then
- begin
- TrainingTargetGear:= AddGear(0, 0, gtTarget, 0, _0, _0, 0);
- FindPlace(TrainingTargetGear, false, 0, LAND_WIDTH);
- end;
-
for i:= 0 to Pred(cLandMines) do
begin
Gear:= AddGear(0, 0, gtMine, 0, _0, _0, 0);
@@ -1254,7 +1103,10 @@
end;
if (GameFlags and gfLowGravity) <> 0 then
+ begin
cGravity:= cMaxWindSpeed;
+ cGravityf:= 0.00025
+ end;
if (GameFlags and gfVampiric) <> 0 then
cVampiric:= true;
@@ -1271,7 +1123,14 @@
cLaserSighting:= true;
if (GameFlags and gfArtillery) <> 0 then
- cArtillery:= true
+ cArtillery:= true;
+
+if not hasBorder and ((Theme = 'Snow') or (Theme = 'Christmas')) and ((cReducedQuality and rqLowRes) = 0) then
+ begin
+ for i:= 0 to Pred(vobCount*2) do
+ AddGear(GetRandom(LAND_WIDTH+1024)-512, LAND_HEIGHT - GetRandom(LAND_HEIGHT div 2), gtFlake, 0, _0, _0, 0);
+ disableLandBack:= true
+ end
end;
procedure doMakeExplosion(X, Y, Radius: LongInt; Mask: LongWord);
@@ -1349,7 +1208,7 @@
if Gear^.Kind <> gtFlame then FollowGear:= Gear
end;
if ((Mask and EXPLPoisoned) <> 0) and (Gear^.Kind = gtHedgehog) then
- PHedgehog(Gear^.Hedgehog)^.Effects[hePoisoned] := true;
+ Gear^.Hedgehog^.Effects[hePoisoned] := true;
end;
end;
@@ -1448,13 +1307,10 @@
begin
if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then
- begin
+ begin
VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
- if VGear <> nil then
- begin
- VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
+ if VGear <> nil then VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
end;
- end;
if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1;
@@ -1473,7 +1329,7 @@
if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then ApplyDamage(Gear, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch
DeleteCI(Gear);
- if (Gear^.Kind = gtHedgehog) and PHedgehog(Gear^.Hedgehog)^.King then
+ if (Gear^.Kind = gtHedgehog) and Gear^.Hedgehog^.King then
begin
Gear^.dX:= Ammo^.dX * Power * _0_005;
Gear^.dY:= Ammo^.dY * Power * _0_005
@@ -1663,17 +1519,20 @@
gear^.State := gstWait;
uStats.HedgehogDamaged(gear);
gear^.Damage := 0;
- gear^.Health := 100;
- with CurrentHedgehog^ do begin
- inc(Team^.stats.AIKills);
- if Team^.AIKillsTex <> nil then FreeTexture(Team^.AIKillsTex);
- Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
- end;
- tempTeam := PHedgehog(gear^.Hedgehog)^.Team;
+ gear^.Health := gear^.Hedgehog^.InitialHealth;
+ gear^.Hedgehog^.Effects[hePoisoned] := false;
+ if not CurrentHedgehog^.Effects[heResurrectable] then
+ with CurrentHedgehog^ do
+ begin
+ inc(Team^.stats.AIKills);
+ if Team^.AIKillsTex <> nil then FreeTexture(Team^.AIKillsTex);
+ Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
+ end;
+ tempTeam := gear^.Hedgehog^.Team;
DeleteCI(gear);
- FindPlace(gear, false, 0, LAND_WIDTH);
+ FindPlace(gear, false, 0, LAND_WIDTH, true);
if gear <> nil then begin
- RenderHealth(PHedgehog(gear^.Hedgehog)^);
+ RenderHealth(gear^.Hedgehog^);
ScriptCall('onGearResurrect', gear^.uid);
end;
RecountTeamHealth(tempTeam);
@@ -1801,7 +1660,7 @@
end
end;
-procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt);
+procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean = false);
function CountNonZeroz(x, y, r, c: LongInt): LongInt;
var i: LongInt;
@@ -1823,57 +1682,66 @@
ar2: array[0..1023] of TPoint;
cnt, cnt2: Longword;
delta: LongInt;
+ reallySkip, tryAgain: boolean;
begin
-delta:= 250;
-cnt2:= 0;
-repeat
- x:= Left + LongInt(GetRandom(Delta));
+reallySkip:= false; // try not skipping proximity at first
+tryAgain:= true;
+while tryAgain do
+ begin
+ delta:= 250;
+ cnt2:= 0;
repeat
- inc(x, Delta);
- cnt:= 0;
- y:= min(1024, topY) - 2 * Gear^.Radius;
- while y < cWaterLine do
- begin
- repeat
- inc(y, 2);
- until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) = 0);
+ x:= Left + LongInt(GetRandom(Delta));
+ repeat
+ inc(x, Delta);
+ cnt:= 0;
+ y:= min(1024, topY) - 2 * Gear^.Radius;
+ while y < cWaterLine do
+ begin
+ repeat
+ inc(y, 2);
+ until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) = 0);
- sy:= y;
+ sy:= y;
- repeat
- inc(y);
- until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0);
+ repeat
+ inc(y);
+ until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0);
- if (y - sy > Gear^.Radius * 2) and
- (((Gear^.Kind = gtExplosives)
- and (y < cWaterLine)
- and (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 60, 60) = nil)
- and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius))
- or
- ((Gear^.Kind <> gtExplosives)
- and (y < cWaterLine)
- and (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 110, 110) = nil))) then
- begin
- ar[cnt].X:= x;
- if withFall then ar[cnt].Y:= sy + Gear^.Radius
- else ar[cnt].Y:= y - Gear^.Radius;
- inc(cnt)
+ if (y - sy > Gear^.Radius * 2) and
+ (((Gear^.Kind = gtExplosives)
+ and (y < cWaterLine)
+ and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 60, 60) = nil))
+ and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius))
+ or
+ ((Gear^.Kind <> gtExplosives)
+ and (y < cWaterLine)
+ and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 110, 110) = nil)))) then
+ begin
+ ar[cnt].X:= x;
+ if withFall then ar[cnt].Y:= sy + Gear^.Radius
+ else ar[cnt].Y:= y - Gear^.Radius;
+ inc(cnt)
+ end;
+
+ inc(y, 45)
end;
- inc(y, 45)
- end;
+ if cnt > 0 then
+ with ar[GetRandom(cnt)] do
+ begin
+ ar2[cnt2].x:= x;
+ ar2[cnt2].y:= y;
+ inc(cnt2)
+ end
+ until (x + Delta > Right);
- if cnt > 0 then
- with ar[GetRandom(cnt)] do
- begin
- ar2[cnt2].x:= x;
- ar2[cnt2].y:= y;
- inc(cnt2)
- end
- until (x + Delta > Right);
-
- dec(Delta, 60)
-until (cnt2 > 0) or (Delta < 70);
+ dec(Delta, 60)
+ until (cnt2 > 0) or (Delta < 70);
+ if (cnt2 = 0) and skipProximity and not reallySkip then tryAgain:= true
+ else tryAgain:= false;
+ reallySkip:= true;
+ end;
if cnt2 > 0 then
with ar2[GetRandom(cnt2)] do
@@ -1887,7 +1755,7 @@
else
begin
OutError('Can''t find place for Gear', false);
- if Gear^.Kind = gtHedgehog then PHedgehog(Gear^.Hedgehog)^.Effects[heResurrectable] := false;
+ if Gear^.Kind = gtHedgehog then Gear^.Hedgehog^.Effects[heResurrectable] := false;
DeleteGear(Gear);
Gear:= nil
end
@@ -1902,7 +1770,7 @@
*)
i:= _1;
if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then i:= _1_5;
-if (Gear^.Hedgehog <> nil) and (PHedgehog(Gear^.Hedgehog)^.King) then
+if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.King) then
ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent * _0_5)
else
ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent)
@@ -1912,26 +1780,114 @@
var gear: PGear;
begin
GearByUID:= nil;
+if uid = 0 then exit;
+if (lastGearByUID <> nil) and (lastGearByUID^.uid = uid) then
+ begin
+ GearByUID:= lastGearByUID;
+ exit
+ end;
gear:= GearsList;
while gear <> nil do
begin
if gear^.uid = uid then
begin
- GearByUID:= gear;
- exit
+ lastGearByUID:= gear;
+ GearByUID:= gear;
+ exit
end;
gear:= gear^.NextGear
end
end;
+
+procedure chSkip(var s: shortstring);
+begin
+s:= s; // avoid compiler hint
+if not CurrentTeam^.ExtDriven then SendIPC(',');
+uStats.Skipped;
+skipFlag:= true
+end;
+
+procedure chHogSay(var s: shortstring);
+var Gear: PVisualGear;
+ text: shortstring;
+ hh: PHedgehog;
+ i, x, t, h: byte;
+ c, j: LongInt;
+begin
+ hh:= nil;
+ i:= 0;
+ t:= 0;
+ x:= byte(s[1]); // speech type
+ if x < 4 then
+ begin
+ t:= byte(s[2]); // team
+ if Length(s) > 2 then h:= byte(s[3]) // target hog
+ end;
+ // allow targetting a hog by specifying a number as the first portion of the text
+ if (x < 4) and (h > byte('0')) and (h < byte('9')) then i:= h - 48;
+ if i <> 0 then text:= copy(s, 4, Length(s) - 1)
+ else if x < 4 then text:= copy(s, 3, Length(s) - 1)
+ else text:= copy(s, 2, Length(s) - 1);
+
+ (*
+ if CheckNoTeamOrHH then
+ begin
+ ParseCommand('say ' + text, true);
+ exit
+ end;
+ *)
+
+ if (x < 4) and (TeamsArray[t] <> nil) then
+ begin
+ // if team matches current hedgehog team, default to current hedgehog
+ if (i = 0) and (CurrentHedgehog <> nil) and (CurrentHedgehog^.Team = TeamsArray[t]) then hh:= CurrentHedgehog
+ else
+ begin
+ // otherwise use the first living hog or the hog amongs the remaining ones indicated by i
+ j:= 0;
+ c:= 0;
+ while (j <= cMaxHHIndex) and (hh = nil) do
+ begin
+ if (TeamsArray[t]^.Hedgehogs[j].Gear <> nil) then
+ begin
+ inc(c);
+ if (i=0) or (i=c) then
+ hh:= @TeamsArray[t]^.Hedgehogs[j]
+ end;
+ inc(j)
+ end
+ end;
+ if hh <> nil then
+ begin
+ Gear:= AddVisualGear(0, 0, vgtSpeechBubble);
+ if Gear <> nil then
+ begin
+ Gear^.Hedgehog:= hh;
+ Gear^.Text:= text;
+ Gear^.FrameTicks:= x
+ end
+ end
+ //else ParseCommand('say ' + text, true)
+ end
+ else if (x >= 4) then
+ begin
+ SpeechType:= x-3;
+ SpeechText:= text
+ end;
+end;
+
procedure initModule;
begin
+ RegisterVariable('skip', vtCommand, @chSkip, false);
+ RegisterVariable('hogsay', vtCommand, @chHogSay, true );
+
CurAmmoGear:= nil;
GearsList:= nil;
KilledHHs:= 0;
+ SuddenDeath:= false;
SuddenDeathDmg:= false;
SpeechType:= 1;
- TrainingTargetGear:= nil;
skipFlag:= false;
AllInactive:= false;
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uGearsRender.pas
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uGearsRender.pas Tue Jan 04 12:53:46 2011 +0100
@@ -0,0 +1,1032 @@
+{$INCLUDE "options.inc"}
+unit uGearsRender;
+
+interface
+uses uTypes, uConsts, GLunit, uFloat;
+
+procedure RenderGear(Gear: PGear; x, y: LongInt);
+
+var RopePoints: record
+ Count: Longword;
+ HookAngle: GLfloat;
+ ar: array[0..MAXROPEPOINTS] of record
+ X, Y: hwFloat;
+ dLen: hwFloat;
+ b: boolean;
+ end;
+ rounded: array[0..MAXROPEPOINTS + 2] of TVertex2f;
+ end;
+
+implementation
+uses uRender, uUtils, uVariables, uAmmos, Math;
+
+procedure DrawRopeLinesRQ(Gear: PGear);
+begin
+with RopePoints do
+ begin
+ rounded[Count].X:= hwRound(Gear^.X);
+ rounded[Count].Y:= hwRound(Gear^.Y);
+ rounded[Count + 1].X:= hwRound(Gear^.Hedgehog^.Gear^.X);
+ rounded[Count + 1].Y:= hwRound(Gear^.Hedgehog^.Gear^.Y);
+ end;
+
+if (RopePoints.Count > 0) or (Gear^.Elasticity.QWordValue > 0) then
+ begin
+ glDisable(GL_TEXTURE_2D);
+ //glEnable(GL_LINE_SMOOTH);
+
+ glPushMatrix;
+
+ glTranslatef(WorldDx, WorldDy, 0);
+
+ glLineWidth(4.0);
+
+ Tint($C0, $C0, $C0, $FF);
+
+ glVertexPointer(2, GL_FLOAT, 0, @RopePoints.rounded[0]);
+ glDrawArrays(GL_LINE_STRIP, 0, RopePoints.Count + 2);
+ Tint($FF, $FF, $FF, $FF);
+
+ glPopMatrix;
+
+ glEnable(GL_TEXTURE_2D);
+ //glDisable(GL_LINE_SMOOTH)
+ end
+end;
+
+
+procedure DrawRope(Gear: PGear);
+var roplen: LongInt;
+ i: Longword;
+
+ procedure DrawRopeLine(X1, Y1, X2, Y2: LongInt);
+ var eX, eY, dX, dY: LongInt;
+ i, sX, sY, x, y, d: LongInt;
+ b: boolean;
+ begin
+ if (X1 = X2) and (Y1 = Y2) then
+ begin
+ //OutError('WARNING: zero length rope line!', false);
+ exit
+ end;
+ eX:= 0;
+ eY:= 0;
+ dX:= X2 - X1;
+ dY:= Y2 - Y1;
+
+ if (dX > 0) then sX:= 1
+ else
+ if (dX < 0) then
+ begin
+ sX:= -1;
+ dX:= -dX
+ end else sX:= dX;
+
+ if (dY > 0) then sY:= 1
+ else
+ if (dY < 0) then
+ begin
+ sY:= -1;
+ dY:= -dY
+ end else sY:= dY;
+
+ if (dX > dY) then d:= dX
+ else d:= dY;
+
+ x:= X1;
+ y:= Y1;
+
+ for i:= 0 to d do
+ begin
+ inc(eX, dX);
+ inc(eY, dY);
+ b:= false;
+ if (eX > d) then
+ begin
+ dec(eX, d);
+ inc(x, sX);
+ b:= true
+ end;
+ if (eY > d) then
+ begin
+ dec(eY, d);
+ inc(y, sY);
+ b:= true
+ end;
+ if b then
+ begin
+ inc(roplen);
+ if (roplen mod 4) = 0 then DrawSprite(sprRopeNode, x - 2, y - 2, 0)
+ end
+ end
+ end;
+begin
+ if (cReducedQuality and rqSimpleRope) <> 0 then
+ DrawRopeLinesRQ(Gear)
+ else
+ begin
+ roplen:= 0;
+ if RopePoints.Count > 0 then
+ begin
+ i:= 0;
+ while i < Pred(RopePoints.Count) do
+ begin
+ DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy,
+ hwRound(RopePoints.ar[Succ(i)].X) + WorldDx, hwRound(RopePoints.ar[Succ(i)].Y) + WorldDy);
+ inc(i)
+ end;
+ DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy,
+ hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy);
+ DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy,
+ hwRound(Gear^.Hedgehog^.Gear^.X) + WorldDx, hwRound(Gear^.Hedgehog^.Gear^.Y) + WorldDy);
+ end else
+ if Gear^.Elasticity.QWordValue > 0 then
+ DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy,
+ hwRound(Gear^.Hedgehog^.Gear^.X) + WorldDx, hwRound(Gear^.Hedgehog^.Gear^.Y) + WorldDy);
+ end;
+
+
+if RopePoints.Count > 0 then
+ DrawRotated(sprRopeHook, hwRound(RopePoints.ar[0].X) + WorldDx, hwRound(RopePoints.ar[0].Y) + WorldDy, 1, RopePoints.HookAngle)
+ else
+ if Gear^.Elasticity.QWordValue > 0 then
+ DrawRotated(sprRopeHook, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+end;
+
+
+procedure DrawAltWeapon(Gear: PGear; sx, sy: LongInt);
+begin
+with Gear^.Hedgehog^ do
+ begin
+ if not (((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) and ((Gear^.State and gstAttacked) = 0)) then
+ exit;
+ DrawTexture(sx + 16, sy + 16, ropeIconTex);
+ DrawTextureF(SpritesData[sprAMAmmos].Texture, 0.75, sx + 30, sy + 30, ord(CurAmmoType) - 1, 1, 32, 32);
+ end;
+end;
+
+
+procedure DrawHH(Gear: PGear; ox, oy: LongInt);
+var i, t: LongInt;
+ amt: TAmmoType;
+ sign, hx, hy, cx, cy, tx, ty, sx, sy, m: LongInt; // hedgehog, crosshair, temp, sprite, direction
+ dx, dy, ax, ay, aAngle, dAngle, hAngle, lx, ly: real; // laser, change
+ defaultPos, HatVisible: boolean;
+ HH: PHedgehog;
+ CurWeapon: PAmmo;
+begin
+ HH:= Gear^.Hedgehog;
+ if HH^.Unplaced then exit;
+ m:= 1;
+ if ((Gear^.State and gstHHHJump) <> 0) and not cArtillery then m:= -1;
+ sx:= ox + 1; // this offset is very common
+ sy:= oy - 3;
+ sign:= hwSign(Gear^.dX);
+
+ if (Gear^.State and gstHHDeath) <> 0 then
+ begin
+ DrawSprite(sprHHDeath, ox - 16, oy - 26, Gear^.Pos);
+ Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ DrawSprite(sprHHDeath, ox - 16, oy - 26, Gear^.Pos + 8);
+ Tint($FF, $FF, $FF, $FF);
+ exit
+ end
+ else if (Gear^.State and gstHHGone) <> 0 then
+ begin
+ DrawRotatedF(sprTeleport, sx, sy, Gear^.Pos, sign, 0);
+ exit
+ end;
+
+ defaultPos:= true;
+ HatVisible:= false;
+
+
+ if HH^.Effects[hePoisoned] then
+ begin
+ Tint($00, $FF, $40, $40);
+ DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 2, 0, 0, sx, sy, 0, 1, 22, 22, (RealTicks shr 36) mod 360);
+ Tint($FF, $FF, $FF, $FF)
+ end;
+
+ if ((Gear^.State and gstWinner) <> 0) and
+ ((CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtPickHammer)) then
+ begin
+ DrawHedgehog(sx, sy,
+ sign,
+ 2,
+ 0,
+ 0);
+ defaultPos:= false
+ end;
+ if (Gear^.State and gstDrowning) <> 0 then
+ begin
+ DrawHedgehog(sx, sy,
+ sign,
+ 1,
+ 7,
+ 0);
+ defaultPos:= false
+ end else
+ if (Gear^.State and gstLoser) <> 0 then
+ begin
+ DrawHedgehog(sx, sy,
+ sign,
+ 2,
+ 3,
+ 0);
+ defaultPos:= false
+ end else
+
+ if (Gear^.State and gstHHDriven) <> 0 then
+ begin
+ if ((Gear^.State and gstHHThinking) = 0) and
+ (ShowCrosshair or ((CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtRope))) and
+ ((Gear^.State and (gstAttacked or gstAnimation)) = 0) then
+ begin
+ (* These calculations are a little complex for a few reasons:
+ 1: I need to draw the laser from weapon origin to nearest land
+ 2: I need to start the beam outside the hedgie for attractiveness.
+ 3: I need to extend the beam beyond land.
+ This routine perhaps should be pushed into uStore or somesuch instead of continuuing the increase in size of this function.
+ *)
+ dx:= sign * m * Sin(Gear^.Angle * pi / cMaxAngle);
+ dy:= -Cos(Gear^.Angle * pi / cMaxAngle);
+ if cLaserSighting then
+ begin
+ lx:= GetLaunchX(HH^.CurAmmoType, sign * m, Gear^.Angle);
+ ly:= GetLaunchY(HH^.CurAmmoType, Gear^.Angle);
+
+ // ensure we start outside the hedgehog (he's solid after all)
+ while abs(lx * lx + ly * ly) < (Gear^.radius * Gear^.radius) do
+ begin
+ lx:= lx + dx;
+ ly:= ly + dy
+ end;
+
+ // add hog's position
+ lx:= lx + ox - WorldDx;
+ ly:= ly + oy - WorldDy;
+
+ // decrease number of iterations required
+ ax:= dx * 4;
+ ay:= dy * 4;
+
+ tx:= round(lx);
+ ty:= round(ly);
+ hx:= tx;
+ hy:= ty;
+ while ((ty and LAND_HEIGHT_MASK) = 0) and
+ ((tx and LAND_WIDTH_MASK) = 0) and
+ (Land[ty, tx] = 0) do // TODO: check for constant variable instead
+ begin
+ lx:= lx + ax;
+ ly:= ly + ay;
+ tx:= round(lx);
+ ty:= round(ly)
+ end;
+ // reached edge of land. assume infinite beam. Extend it way out past camera
+ if ((ty and LAND_HEIGHT_MASK) <> 0) or ((tx and LAND_WIDTH_MASK) <> 0) then
+ begin
+ tx:= round(lx + ax * (LAND_WIDTH div 4));
+ ty:= round(ly + ay * (LAND_WIDTH div 4));
+ end;
+
+ //if (abs(lx-tx)>8) or (abs(ly-ty)>8) then
+ begin
+ DrawLine(hx, hy, tx, ty, 1.0, $FF, $00, $00, $C0);
+ end;
+ end;
+ // draw crosshair
+ cx:= Round(hwRound(Gear^.X) + dx * 80 + GetLaunchX(HH^.CurAmmoType, sign * m, Gear^.Angle));
+ cy:= Round(hwRound(Gear^.Y) + dy * 80 + GetLaunchY(HH^.CurAmmoType, Gear^.Angle));
+ DrawRotatedTex(HH^.Team^.CrosshairTex,
+ 12, 12, cx + WorldDx, cy + WorldDy, 0,
+ sign * (Gear^.Angle * 180.0) / cMaxAngle);
+ end;
+ hx:= ox + 8 * sign;
+ hy:= oy - 2;
+ aangle:= Gear^.Angle * 180 / cMaxAngle - 90;
+ if CurAmmoGear <> nil then
+ begin
+ case CurAmmoGear^.Kind of
+ gtShotgunShot: begin
+ if (CurAmmoGear^.State and gstAnimation <> 0) then
+ DrawRotated(sprShotgun, hx, hy, sign, aangle)
+ else
+ DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
+ end;
+ gtDEagleShot: DrawRotated(sprDEagle, hx, hy, sign, aangle);
+ gtSniperRifleShot: begin
+ if (CurAmmoGear^.State and gstAnimation <> 0) then
+ DrawRotatedF(sprSniperRifle, hx, hy, 1, sign, aangle)
+ else
+ DrawRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle)
+ end;
+ gtBallgun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
+ gtRCPlane: begin
+ DrawRotated(sprHandPlane, hx, hy, sign, 0);
+ defaultPos:= false
+ end;
+ gtRope: begin
+ if Gear^.X < CurAmmoGear^.X then
+ begin
+ dAngle:= 0;
+ hAngle:= 180;
+ i:= 1
+ end else
+ begin
+ dAngle:= 180;
+ hAngle:= 0;
+ i:= -1
+ end;
+ if ((Gear^.State and gstWinner) = 0) then
+ begin
+ DrawHedgehog(ox, oy,
+ i,
+ 1,
+ 0,
+ DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + dAngle);
+ with HH^ do
+ if (HatTex <> nil) then
+ begin
+ DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32,
+ i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle);
+ if HatTex^.w > 64 then
+ begin
+ Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32,
+ i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle);
+ Tint($FF, $FF, $FF, $FF)
+ end
+ end
+ end;
+ DrawAltWeapon(Gear, ox, oy);
+ defaultPos:= false
+ end;
+ gtBlowTorch: begin
+ DrawRotated(sprBlowTorch, hx, hy, sign, aangle);
+ DrawHedgehog(sx, sy,
+ sign,
+ 3,
+ HH^.visStepPos div 2,
+ 0);
+ with HH^ do
+ if (HatTex <> nil) then
+ begin
+ DrawTextureF(HatTex,
+ 1,
+ sx,
+ sy - 5,
+ 0,
+ sign,
+ 32,
+ 32);
+ if HatTex^.w > 64 then
+ begin
+ Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ DrawTextureF(HatTex,
+ 1,
+ sx,
+ sy - 5,
+ 32,
+ sign,
+ 32,
+ 32);
+ Tint($FF, $FF, $FF, $FF)
+ end
+ end;
+ defaultPos:= false
+ end;
+ gtShover: DrawRotated(sprHandBaseball, hx, hy, sign, aangle + 180);
+ gtFirePunch: begin
+ DrawHedgehog(sx, sy,
+ sign,
+ 1,
+ 4,
+ 0);
+ defaultPos:= false
+ end;
+ gtPickHammer: begin
+ defaultPos:= false;
+ dec(sy,20);
+ end;
+ gtTeleport: defaultPos:= false;
+ gtWhip: begin
+ DrawRotatedF(sprWhip,
+ sx,
+ sy,
+ 1,
+ sign,
+ 0);
+ defaultPos:= false
+ end;
+ gtHammer: begin
+ DrawRotatedF(sprHammer,
+ sx,
+ sy,
+ 1,
+ sign,
+ 0);
+ defaultPos:= false
+ end;
+ gtResurrector: begin
+ DrawRotated(sprHandResurrector, sx, sy, 0, 0);
+ defaultPos:= false
+ end;
+ gtKamikaze: begin
+ if CurAmmoGear^.Pos = 0 then
+ DrawHedgehog(sx, sy,
+ sign,
+ 1,
+ 6,
+ 0)
+ else
+ DrawRotatedF(sprKamikaze,
+ ox, oy,
+ CurAmmoGear^.Pos - 1,
+ sign,
+ aangle);
+ defaultPos:= false
+ end;
+ gtSeduction: begin
+ if CurAmmoGear^.Pos >= 6 then
+ DrawHedgehog(sx, sy,
+ sign,
+ 2,
+ 2,
+ 0)
+ else
+ begin
+ DrawRotatedF(sprDress,
+ ox, oy,
+ CurAmmoGear^.Pos,
+ sign,
+ 0);
+ DrawSprite(sprCensored, ox - 32, oy - 20, 0)
+ end;
+ defaultPos:= false
+ end;
+ gtFlamethrower: begin
+ DrawRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+ if CurAmmoGear^.Tex <> nil then DrawCentered(sx, sy - 40, CurAmmoGear^.Tex)
+ end;
+ end;
+
+ case CurAmmoGear^.Kind of
+ gtShotgunShot,
+ gtDEagleShot,
+ gtSniperRifleShot,
+ gtShover: begin
+ DrawHedgehog(sx, sy,
+ sign,
+ 0,
+ 4,
+ 0);
+ defaultPos:= false;
+ HatVisible:= true
+ end
+ end
+ end else
+
+ if ((Gear^.State and gstHHJumping) <> 0) then
+ begin
+ DrawHedgehog(sx, sy,
+ sign*m,
+ 1,
+ 1,
+ 0);
+ HatVisible:= true;
+ defaultPos:= false
+ end else
+
+ if (Gear^.Message and (gmLeft or gmRight) <> 0) and (not isCursorVisible) then
+ begin
+ DrawHedgehog(sx, sy,
+ sign,
+ 0,
+ HH^.visStepPos div 2,
+ 0);
+ defaultPos:= false;
+ HatVisible:= true
+ end
+ else
+
+ if ((Gear^.State and gstAnimation) <> 0) then
+ begin
+ if (TWave(Gear^.Tag) < Low(TWave)) or (TWave(Gear^.Tag) > High(TWave)) then
+ begin
+ Gear^.State:= Gear^.State and not gstAnimation;
+ end
+ else
+ begin
+ DrawRotatedF(Wavez[TWave(Gear^.Tag)].Sprite,
+ sx,
+ sy,
+ Gear^.Pos,
+ sign,
+ 0.0);
+ defaultPos:= false
+ end
+ end
+ else
+ if ((Gear^.State and gstAttacked) = 0) then
+ begin
+ if HH^.Timer > 0 then
+ begin
+ // There must be a tidier way to do this. Anyone?
+ if aangle <= 90 then aangle:= aangle+360;
+ if Gear^.dX > _0 then aangle:= aangle-((aangle-240)*HH^.Timer/10)
+ else aangle:= aangle+((240-aangle)*HH^.Timer/10);
+ dec(HH^.Timer)
+ end;
+ amt:= CurrentHedgehog^.CurAmmoType;
+ CurWeapon:= GetAmmoEntry(HH^);
+ case amt of
+ amBazooka: DrawRotated(sprHandBazooka, hx, hy, sign, aangle);
+ amSnowball: DrawRotated(sprHandSnowball, hx, hy, sign, aangle);
+ amMortar: DrawRotated(sprHandMortar, hx, hy, sign, aangle);
+ amMolotov: DrawRotated(sprHandMolotov, hx, hy, sign, aangle);
+ amBallgun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
+ amDrill: DrawRotated(sprHandDrill, hx, hy, sign, aangle);
+ amRope: DrawRotated(sprHandRope, hx, hy, sign, aangle);
+ amShotgun: DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
+ amDEagle: DrawRotated(sprHandDEagle, hx, hy, sign, aangle);
+ amSineGun: DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
+ amPortalGun: if (CurWeapon^.Timer and 2) <> 0 then // Add a new Hedgehog value instead of abusing timer?
+ DrawRotatedF(sprPortalGun, hx, hy, 0, sign, aangle)
+ else
+ DrawRotatedF(sprPortalGun, hx, hy, 1+CurWeapon^.Pos, sign, aangle);
+ amSniperRifle: DrawRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle);
+ amBlowTorch: DrawRotated(sprHandBlowTorch, hx, hy, sign, aangle);
+ amCake: DrawRotated(sprHandCake, hx, hy, sign, aangle);
+ amGrenade: DrawRotated(sprHandGrenade, hx, hy, sign, aangle);
+ amWatermelon: DrawRotated(sprHandMelon, hx, hy, sign, aangle);
+ amSkip: DrawRotated(sprHandSkip, hx, hy, sign, aangle);
+ amClusterBomb: DrawRotated(sprHandCluster, hx, hy, sign, aangle);
+ amDynamite: DrawRotated(sprHandDynamite, hx, hy, sign, aangle);
+ amHellishBomb: DrawRotated(sprHandHellish, hx, hy, sign, aangle);
+ amGasBomb: DrawRotated(sprHandCheese, hx, hy, sign, aangle);
+ amMine: DrawRotated(sprHandMine, hx, hy, sign, aangle);
+ amSMine: DrawRotated(sprHandSMine, hx, hy, sign, aangle);
+ amSeduction: DrawRotated(sprHandSeduction, hx, hy, sign, aangle);
+ amVampiric: DrawRotatedF(sprHandVamp, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+ amRCPlane: begin
+ DrawRotated(sprHandPlane, hx, hy, sign, 0);
+ defaultPos:= false
+ end;
+ amGirder: begin
+ DrawRotated(sprHandConstruction, hx, hy, sign, aangle);
+ DrawSpriteClipped(sprGirder,
+ ox-256,
+ oy-256,
+ LongInt(topY)+WorldDy,
+ LongInt(rightX)+WorldDx,
+ cWaterLine+WorldDy,
+ LongInt(leftX)+WorldDx)
+ end;
+ amBee: DrawRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+ amFlamethrower: DrawRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+ amResurrector: DrawCircle(ox, oy, 98, 4, $F5, $DB, $35, $AA); // I'd rather not like to hardcode 100 here
+ end;
+
+ case amt of
+ amAirAttack,
+ amMineStrike,
+ amDrillStrike: DrawRotated(sprHandAirAttack, sx, oy, sign, 0);
+ amPickHammer: DrawHedgehog(sx, sy,
+ sign,
+ 1,
+ 2,
+ 0);
+ amTeleport: DrawRotatedF(sprTeleport, sx, sy, 0, sign, 0);
+ amKamikaze: DrawHedgehog(sx, sy,
+ sign,
+ 1,
+ 5,
+ 0);
+ amWhip: DrawRotatedF(sprWhip,
+ sx,
+ sy,
+ 0,
+ sign,
+ 0);
+ amHammer: DrawRotatedF(sprHammer,
+ sx,
+ sy,
+ 0,
+ sign,
+ 0);
+ else
+ DrawHedgehog(sx, sy,
+ sign,
+ 0,
+ 4,
+ 0);
+
+ HatVisible:= true;
+ (* with HH^ do
+ if (HatTex <> nil)
+ and (HatVisibility > 0) then
+ DrawTextureF(HatTex,
+ HatVisibility,
+ sx,
+ sy - 5,
+ 0,
+ sign,
+ 32,
+ 32); *)
+ end;
+
+ case amt of
+ amBaseballBat: DrawRotated(sprHandBaseball,
+ sx - 4 * sign,
+ sy + 9, sign, aangle);
+ end;
+
+ defaultPos:= false
+ end;
+
+ end else // not gstHHDriven
+ begin
+ if (Gear^.Damage > 0)
+ and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then
+ begin
+ DrawHedgehog(sx, sy,
+ sign,
+ 2,
+ 1,
+ Gear^.DirAngle);
+ defaultPos:= false
+ end else
+
+ if ((Gear^.State and gstHHJumping) <> 0) then
+ begin
+ DrawHedgehog(sx, sy,
+ sign*m,
+ 1,
+ 1,
+ 0);
+ defaultPos:= false
+ end;
+ end;
+
+ with HH^ do
+ begin
+ if defaultPos then
+ begin
+ DrawRotatedF(sprHHIdle,
+ sx,
+ sy,
+ (RealTicks div 128 + Gear^.Pos) mod 19,
+ sign,
+ 0);
+ HatVisible:= true;
+ end;
+
+ if HatVisible then
+ if HatVisibility < 1.0 then
+ HatVisibility:= HatVisibility + 0.2
+ else
+ else
+ if HatVisibility > 0.0 then
+ HatVisibility:= HatVisibility - 0.2;
+
+ if (HatTex <> nil)
+ and (HatVisibility > 0) then
+ if DefaultPos then
+ begin
+ DrawTextureF(HatTex,
+ HatVisibility,
+ sx,
+ sy - 5,
+ (RealTicks div 128 + Gear^.Pos) mod 19,
+ sign,
+ 32,
+ 32);
+ if HatTex^.w > 64 then
+ begin
+ Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ DrawTextureF(HatTex,
+ HatVisibility,
+ sx,
+ sy - 5,
+ (RealTicks div 128 + Gear^.Pos) mod 19 + 32,
+ sign,
+ 32,
+ 32);
+ Tint($FF, $FF, $FF, $FF)
+ end
+ end
+ else
+ begin
+ DrawTextureF(HatTex,
+ HatVisibility,
+ sx,
+ sy - 5,
+ 0,
+ sign*m,
+ 32,
+ 32);
+ if HatTex^.w > 64 then
+ begin
+ Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ DrawTextureF(HatTex,
+ HatVisibility,
+ sx,
+ sy - 5,
+ 32,
+ sign*m,
+ 32,
+ 32);
+ Tint($FF, $FF, $FF, $FF)
+ end
+ end
+ end;
+ if (Gear^.State and gstHHDriven) <> 0 then
+ begin
+ (* if (CurAmmoGear = nil) then
+ begin
+ amt:= CurrentHedgehog^.CurAmmoType;
+ case amt of
+ amJetpack: DrawSprite(sprJetpack, sx-32, sy-32, 0);
+ end
+ end; *)
+ if CurAmmoGear <> nil then
+ begin
+ case CurAmmoGear^.Kind of
+ gtJetpack: begin
+ DrawSprite(sprJetpack, sx-32, sy-32, 0);
+ if cWaterLine > hwRound(Gear^.Y) + Gear^.Radius then
+ begin
+ if (CurAmmoGear^.MsgParam and gmUp) <> 0 then DrawSprite(sprJetpack, sx-32, sy-28, 1);
+ if (CurAmmoGear^.MsgParam and gmLeft) <> 0 then DrawSprite(sprJetpack, sx-28, sy-28, 2);
+ if (CurAmmoGear^.MsgParam and gmRight) <> 0 then DrawSprite(sprJetpack, sx-36, sy-28, 3)
+ end;
+ if CurAmmoGear^.Tex <> nil then DrawCentered(sx, sy - 40, CurAmmoGear^.Tex);
+ DrawAltWeapon(Gear, sx, sy)
+ end;
+ end;
+ end
+ end;
+
+ with HH^ do
+ begin
+ if ((Gear^.State and not gstWinner) = 0)
+ or ((Gear^.State = gstWait) and (Gear^.dY.QWordValue = 0))
+ or (bShowFinger and ((Gear^.State and gstHHDriven) <> 0)) then
+ begin
+ t:= sy - cHHRadius - 9;
+ if (cTagsMask and htTransparent) <> 0 then
+ Tint($FF, $FF, $FF, $80);
+ if ((cTagsMask and htHealth) <> 0) then
+ begin
+ dec(t, HealthTagTex^.h + 2);
+ DrawCentered(ox, t, HealthTagTex)
+ end;
+ if (cTagsMask and htName) <> 0 then
+ begin
+ dec(t, NameTagTex^.h + 2);
+ DrawCentered(ox, t, NameTagTex)
+ end;
+ if (cTagsMask and htTeamName) <> 0 then
+ begin
+ dec(t, Team^.NameTagTex^.h + 2);
+ DrawCentered(ox, t, Team^.NameTagTex)
+ end;
+ if (cTagsMask and htTransparent) <> 0 then
+ Tint($FF, $FF, $FF, $FF)
+ end;
+ if (Gear^.State and gstHHDriven) <> 0 then // Current hedgehog
+ begin
+ if (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtResurrector) then
+ DrawCentered(ox, sy - cHHRadius - 7 - HealthTagTex^.h, HealthTagTex);
+
+ if bShowFinger and ((Gear^.State and gstHHDriven) <> 0) then
+ DrawSprite(sprFinger, ox - 16, oy - 64,
+ GameTicks div 32 mod 16);
+
+ if (Gear^.State and gstDrowning) = 0 then
+ if (Gear^.State and gstHHThinking) <> 0 then
+ DrawSprite(sprQuestion, ox - 10, oy - cHHRadius - 34, (RealTicks shr 9) mod 8)
+ end
+ end;
+
+ if HH^.Effects[hePoisoned] then
+ begin
+ Tint($00, $FF, $40, $80);
+ DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 1.5, 0, 0, sx, sy, 0, 1, 22, 22, 360 - (RealTicks shr 37) mod 360);
+ end;
+ if HH^.Effects[heResurrected] then
+ begin
+ Tint($f5, $db, $35, $20);
+ DrawSprite(sprVampiric, sx - 24, sy - 24, 0);
+ end;
+
+ if Gear^.Invulnerable then
+ begin
+ Tint($FF, $FF, $FF, max($40, round($FF * abs(1 - ((RealTicks div 2 + Gear^.uid * 491) mod 1500) / 750))));
+ DrawSprite(sprInvulnerable, sx - 24, sy - 24, 0);
+ end;
+ if cVampiric and
+ (CurrentHedgehog^.Gear <> nil) and
+ (CurrentHedgehog^.Gear = Gear) then
+ begin
+ Tint($FF, 0, 0, max($40, round($FF * abs(1 - (RealTicks mod 1500) / 750))));
+ DrawSprite(sprVampiric, sx - 24, sy - 24, 0);
+ end;
+ Tint($FF, $FF, $FF, $FF)
+end;
+
+
+procedure RenderGear(Gear: PGear; x, y: LongInt);
+var
+ HHGear: PGear;
+ i: Longword;
+ startX, endX, startY, endY: LongInt;
+begin
+ case Gear^.Kind of
+ gtBomb: DrawRotated(sprBomb, x, y, 0, Gear^.DirAngle);
+ gtSnowball: DrawRotated(sprSnowball, x, y, 0, Gear^.DirAngle);
+ gtGasBomb: DrawRotated(sprCheese, x, y, 0, Gear^.DirAngle);
+ gtMolotov: DrawRotated(sprMolotov, x, y, 0, Gear^.DirAngle);
+
+ gtRCPlane: begin
+ if (Gear^.Tag = -1) then
+ DrawRotated(sprPlane, x, y, -1, DxDy2Angle(Gear^.dX, Gear^.dY) + 90)
+ else
+ DrawRotated(sprPlane, x, y,0,DxDy2Angle(Gear^.dY, Gear^.dX));
+ end;
+ gtBall: DrawRotatedf(sprBalls, x, y, Gear^.Tag,0, Gear^.DirAngle);
+
+ gtPortal: if ((Gear^.Tag and 1) = 0) // still moving?
+ or (Gear^.IntersectGear = nil) or (Gear^.IntersectGear^.IntersectGear <> Gear) // not linked&backlinked?
+ or ((Gear^.IntersectGear^.Tag and 1) = 0) then // linked portal still moving?
+ DrawRotatedf(sprPortal, x, y, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle)
+ else DrawRotatedf(sprPortal, x, y, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle);
+
+ gtDrill: if (Gear^.State and gsttmpFlag) <> 0 then
+ DrawRotated(sprAirDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX))
+ else
+ DrawRotated(sprDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+
+ gtHedgehog: DrawHH(Gear, x, y);
+
+ gtShell: DrawRotated(sprBazookaShell, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+
+ gtGrave: begin
+ DrawTextureF(Gear^.Hedgehog^.Team^.GraveTex, 1, x, y, (GameTicks shr 7+Gear^.uid) and 7, 1, 32, 32);
+ if Gear^.Health > 0 then
+ begin
+ //Tint($33, $33, $FF, max($40, round($FF * abs(1 - (GameTicks mod (6000 div Gear^.Health)) / 750))));
+ Tint($f5, $db, $35, max($40, round($FF * abs(1 - (GameTicks mod 1500) / (750 + Gear^.Health)))));
+ //Tint($FF, $FF, $FF, max($40, round($FF * abs(1 - (RealTicks mod 1500) / 750))));
+ DrawSprite(sprVampiric, x - 24, y - 24, 0);
+ Tint($FF, $FF, $FF, $FF)
+ end
+ end;
+ gtBee: DrawRotatedF(sprBee, x, y, (GameTicks shr 5) mod 2, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+ gtPickHammer: DrawSprite(sprPHammer, x - 16, y - 50 + LongInt(((GameTicks shr 5) and 1) * 2), 0);
+ gtRope: DrawRope(Gear);
+ gtMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
+ DrawRotated(sprMineOff, x, y, 0, Gear^.DirAngle)
+ else if Gear^.Health <> 0 then DrawRotated(sprMineOn, x, y, 0, Gear^.DirAngle)
+ else DrawRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
+ gtSMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
+ DrawRotated(sprSMineOff, x, y, 0, Gear^.DirAngle)
+ else if Gear^.Health <> 0 then DrawRotated(sprSMineOn, x, y, 0, Gear^.DirAngle)
+ else DrawRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
+ gtCase: case Gear^.Pos of
+ posCaseAmmo : begin
+ i:= (GameTicks shr 6) mod 64;
+ if i > 18 then i:= 0;
+ DrawSprite(sprCase, x - 24, y - 24, i);
+ end;
+ posCaseHealth: begin
+ i:= ((GameTicks shr 6) + 38) mod 64;
+ if i > 13 then i:= 0;
+ DrawSprite(sprFAid, x - 24, y - 24, i);
+ end;
+ posCaseUtility: begin
+ i:= (GameTicks shr 6) mod 70;
+ if i > 23 then i:= 0;
+ i:= i mod 12;
+ DrawSprite(sprUtility, x - 24, y - 24, i);
+ end;
+ end;
+ gtExplosives: begin
+ if ((Gear^.State and gstDrowning) <> 0) then
+ DrawSprite(sprExplosivesRoll, x - 24, y - 24, 0)
+ else if Gear^.State and gstAnimation = 0 then
+ begin
+ i:= (GameTicks shr 6 + Gear^.uid*3) mod 64;
+ if i > 18 then i:= 0;
+ DrawSprite(sprExplosives, x - 24, y - 24, i)
+ end
+ else if Gear^.State and gsttmpFlag = 0 then
+ DrawRotatedF(sprExplosivesRoll, x, y + 4, 0, 0, Gear^.DirAngle)
+ else
+ DrawRotatedF(sprExplosivesRoll, x, y + 4, 1, 0, Gear^.DirAngle);
+ end;
+ gtDynamite: DrawSprite2(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
+ gtClusterBomb: DrawRotated(sprClusterBomb, x, y, 0, Gear^.DirAngle);
+ gtCluster: DrawSprite(sprClusterParticle, x - 8, y - 8, 0);
+ gtFlame: DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), x, y, (GameTicks shr 7 + LongWord(Gear^.Tag)) mod 8, 1, 16, 16);
+ gtParachute: begin
+ DrawSprite(sprParachute, x - 24, y - 48, 0);
+ DrawAltWeapon(Gear, x + 1, y - 3)
+ end;
+ gtAirAttack: if Gear^.Tag > 0 then DrawSprite(sprAirplane, x - SpritesData[sprAirplane].Width div 2, y - SpritesData[sprAirplane].Height div 2, 0)
+ else DrawSprite(sprAirplane, x - SpritesData[sprAirplane].Width div 2, y - SpritesData[sprAirplane].Height div 2, 1);
+ gtAirBomb: DrawRotated(sprAirBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+ gtTeleport: begin
+ HHGear:= Gear^.Hedgehog^.Gear;
+ if not Gear^.Hedgehog^.Unplaced then DrawRotatedF(sprTeleport, x + 1, y - 3, Gear^.Pos, hwSign(Gear^.dX), 0);
+ DrawRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0);
+ end;
+ gtSwitcher: DrawSprite(sprSwitch, x - 16, y - 56, (GameTicks shr 6) mod 12);
+ gtTarget: begin
+ Tint($FF, $FF, $FF, round($FF * Gear^.Timer / 1000));
+ DrawSprite(sprTarget, x - 16, y - 16, 0);
+ Tint($FF, $FF, $FF, $FF);
+ end;
+ gtMortar: DrawRotated(sprMortar, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+ gtCake: if Gear^.Pos = 6 then
+ DrawRotatedf(sprCakeWalk, x, y, (GameTicks div 40) mod 6, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90)
+ else
+ DrawRotatedf(sprCakeDown, x, y, 5 - Gear^.Pos, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90);
+ gtSeduction: if Gear^.Pos >= 14 then DrawSprite(sprSeduction, x - 16, y - 16, 0);
+ gtWatermelon: DrawRotatedf(sprWatermelon, x, y, 0, 0, Gear^.DirAngle);
+ gtMelonPiece: DrawRotatedf(sprWatermelon, x, y, 1, 0, Gear^.DirAngle);
+ gtHellishBomb: DrawRotated(sprHellishBomb, x, y, 0, Gear^.DirAngle);
+ gtBirdy: begin
+ if Gear^.State and gstAnimation = gstAnimation then
+ begin
+ if Gear^.State and gstTmpFlag = 0 then // Appearing
+ begin
+ endX:= x - WorldDx;
+ endY:= y - WorldDy;
+ if Gear^.Tag < 0 then
+ startX:= max(LAND_WIDTH + 1024, endX + 2048)
+ else
+ startX:= max(-LAND_WIDTH - 1024, endX - 2048);
+ startY:= endY - 256;
+ DrawTextureF(SpritesData[sprBirdy].Texture, 1, startX + WorldDx + round((endX - startX) * (-power(2, -10 * LongInt(Gear^.Timer)/2000) + 1)), startY + WorldDy + round((endY - startY) * sqrt(1 - power((LongInt(Gear^.Timer)/2000)-1, 2))), ((Gear^.Pos shr 6) or (RealTicks shr 8)) mod 2, Gear^.Tag, 75, 75);
+ end
+ else // Disappearing
+ begin
+ startX:= x - WorldDx;
+ startY:= y - WorldDy;
+ if Gear^.Tag > 0 then
+ endX:= max(LAND_WIDTH + 1024, startX + 2048)
+ else
+ endX:= max(-LAND_WIDTH - 1024, startX - 2048);
+ endY:= startY + 256;
+ DrawTextureF(SpritesData[sprBirdy].Texture, 1, startX + WorldDx + round((endX - startX) * power(2, 10 * (LongInt(Gear^.Timer)/2000 - 1))) + hwRound(Gear^.dX * Gear^.Timer), startY + WorldDy + round((endY - startY) * cos(LongInt(Gear^.Timer)/2000 * (Pi/2)) - (endY - startY)) + hwRound(Gear^.dY * Gear^.Timer), ((Gear^.Pos shr 6) or (RealTicks shr 8)) mod 2, Gear^.Tag, 75, 75);
+ end;
+ end
+ else
+ DrawTextureF(SpritesData[sprBirdy].Texture, 1, x, y, ((Gear^.Pos shr 6) or (RealTicks shr 8)) mod 2, Gear^.Tag, 75, 75);
+ end;
+ gtEgg: DrawRotatedTextureF(SpritesData[sprEgg].Texture, 1, 0, 0, x, y, 0, 1, 16, 16, Gear^.DirAngle);
+ gtPiano: begin
+ if (Gear^.State and gstDrowning) = 0 then
+ begin
+ Tint($FF, $FF, $FF, $10);
+ for i:= 8 downto 1 do
+ DrawRotatedTextureF(SpritesData[sprPiano].Texture, 1, 0, 0, x, y - hwRound(Gear^.dY * 4 * i), 0, 1, 128, 128, 0);
+ Tint($FF, $FF, $FF, $FF)
+ end;
+ DrawRotatedTextureF(SpritesData[sprPiano].Texture, 1, 0, 0, x, y, 0, 1, 128, 128, 0);
+ end;
+ gtPoisonCloud: begin
+ if Gear^.Timer < 1020 then
+ Tint($C0, $C0, $00, Gear^.Timer div 8)
+ else if Gear^.Timer > 3980 then
+ Tint($C0, $C0, $00, (5000 - Gear^.Timer) div 8)
+ else
+ Tint($C0, $C0, $00, $C0);
+ DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 3, 0, 0, x, y, 0, 1, 22, 22, (RealTicks shr 36 + Gear^.UID * 100) mod 360);
+ Tint($FF, $FF, $FF, $FF)
+ end;
+ gtResurrector: begin
+ DrawRotated(sprCross, x, y, 0, 0);
+ Tint($f5, $db, $35, max($00, round($C0 * abs(1 - (GameTicks mod 6000) / 3000))));
+ DrawTexture(x - 108, y - 108, SpritesData[sprVampiric].Texture, 4.5);
+ Tint($FF, $FF, $FF, $FF);
+ end;
+ gtNapalmBomb: DrawRotated(sprNapalmBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+ gtFlake: if not isInLag then
+ begin
+ if vobVelocity = 0 then
+ //DrawSprite(sprFlake, x-SpritesData[sprFlake].Width div 2, y-SpritesData[sprFlake].Height div 2, Gear^.Timer)
+ DrawSprite(sprFlake, x, y, Gear^.Timer)
+ else
+ //DrawRotatedF(sprFlake, x-SpritesData[sprFlake].Width div 2, y-SpritesData[sprFlake].Height div 2, Gear^.Timer, 1, Gear^.DirAngle);
+ DrawRotatedF(sprFlake, x, y, Gear^.Timer, 1, Gear^.DirAngle)
+ end;
+
+ end;
+ if Gear^.RenderTimer and (Gear^.Tex <> nil) then DrawCentered(x + 8, y + 8, Gear^.Tex);
+end;
+
+end.
diff -r 0ddb100fea61 -r f924be23ffb4 hedgewars/uIO.pas
--- a/hedgewars/uIO.pas Mon Dec 27 23:57:44 2010 +0100
+++ b/hedgewars/uIO.pas Tue Jan 04 12:53:46 2011 +0100
@@ -20,7 +20,7 @@
unit uIO;
interface
-uses SDLh;
+uses SDLh, uTypes;
var ipcPort: Word = 0;
hiTicks: Word;
@@ -35,14 +35,16 @@
procedure SendIPCTimeInc;
procedure SendKeepAliveMessage(Lag: Longword);
procedure LoadRecordFromFile(fileName: shortstring);
+procedure SendStat(sit: TStatInfoType; s: shortstring);
procedure IPCWaitPongEvent;
procedure IPCCheckSock;
procedure InitIPC;
procedure CloseIPC;
procedure NetGetNextCmd;
+procedure doPut(putX, putY: LongInt; fromAI: boolean);
implementation
-uses uConsole, uConsts, uWorld, uMisc, uLand, uChat, uTeams;
+uses uConsole, uConsts, uVariables, uCommands, uUtils, uDebug;
type PCmd = ^TCmd;
TCmd = packed record
@@ -64,7 +66,6 @@
SendEmptyPacketTicks: LongWord;
-
function AddCmd(Time: Word; str: shortstring): PCmd;
var command: PCmd;
begin
@@ -128,7 +129,7 @@
'e': ParseCommand(copy(s, 2, Length(s) - 1), true);
'E': OutError(copy(s, 2, Length(s) - 1), true);
'W': OutError(copy(s, 2, Length(s) - 1), false);
- 'M': CheckLandDigest(s);
+ 'M': ParseCommand('landcheck ' + s, true);
'T': case s[2] of
'L': GameType:= gmtLocal;
'D': GameType:= gmtDemo;
@@ -138,7 +139,7 @@
else
loTicks:= SDLNet_Read16(@s[byte(s[0]) - 1]);
AddCmd(loTicks, s);
- {$IFDEF DEBUGFILE}AddFileLog('IPC in: '+s[1]+' ticks '+inttostr(lastcmd^.loTime));{$ENDIF}
+ {$IFDEF DEBUGFILE}AddFileLog('[IPC in] '+s[1]+' ticks '+IntToStr(lastcmd^.loTime));{$ENDIF}
end
end;
@@ -203,6 +204,15 @@
close(f)
end;
+procedure SendStat(sit: TStatInfoType; s: shortstring);
+const stc: array [TStatInfoType] of char = 'rDkKHTPsSB';
+var buf: shortstring;
+begin
+buf:= 'i' + stc[sit] + s;
+SendIPCRaw(@buf[0], length(buf) + 1)
+end;
+
+
procedure SendIPC(s: shortstring);
begin
if IPCSock <> nil then
@@ -210,7 +220,7 @@
SendEmptyPacketTicks:= 0;
if s[0]>#251 then s[0]:= #251;
SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]);
- {$IFDEF DEBUGFILE}AddFileLog('IPC send: '+ s[1]);{$ENDIF}
+ {$IFDEF DEBUGFILE}AddFileLog('[IPC out] '+ s[1]);{$ENDIF}
inc(s[0], 2);
SDLNet_TCP_Send(IPCSock, @s, Succ(byte(s[0])))
end
@@ -237,7 +247,7 @@
procedure SendIPCTimeInc;
const timeinc: shortstring = '#';
begin
-{$IFDEF DEBUGFILE}AddFileLog('IPC Send #');{$ENDIF}
+{$IFDEF DEBUGFILE}AddFileLog('[IPC out]