--- a/.hgignore Thu Aug 26 23:59:18 2010 +0200
+++ b/.hgignore Wed Oct 27 14:02:20 2010 +0200
@@ -1,24 +1,34 @@
-glob:CMakeCache.txt
-glob:CMakeFiles
-glob:moc_*.cxx
-glob:qrc_*.cxx
-glob:*.o
-glob:Makefile
-glob:bin
-glob:*.hi
-glob:*.*~
-glob:*.core
-glob:hedgewars/config.inc
-glob:cmake_install.cmake
-glob:QTfrontend/hwconsts.cpp
-glob:CPackConfig.cmake
-glob:CPackSourceConfig.cmake
-glob:tools/cmake_uninstall.cmake
-glob:install_manifest.txt
-glob:.DS_Store
-glob:*.swp
-glob:*.orig
-glob:*.diff
-glob:project_files/HedgewarsMobile/Data/
-glob:project_files/HedgewarsMobile/build/
-glob:project_files/HedgewarsMobile/Hedgewars.xcodeproj/vittorio.*
+glob:CMakeCache.txt
+glob:CMakeFiles
+glob:moc_*.cxx
+glob:qrc_*.cxx
+glob:*.o
+glob:Makefile
+glob:bin
+glob:*.hi
+glob:*.*~
+glob:*.core
+glob:hedgewars/config.inc
+glob:cmake_install.cmake
+glob:QTfrontend/hwconsts.cpp
+glob:CPackConfig.cmake
+glob:CPackSourceConfig.cmake
+glob:tools/cmake_uninstall.cmake
+glob:install_manifest.txt
+glob:.DS_Store
+glob:*.swp
+glob:*.orig
+glob:*.diff
+glob:project_files/HedgewarsMobile/Data/
+glob:project_files/HedgewarsMobile/build/
+glob:project_files/HedgewarsMobile/audio/
+glob:project_files/HedgewarsMobile/Hedgewars.xcodeproj/vittorio.*
+glob:moc_*.cxx_parameters
+relre:^release\/
+glob:*.log
+glob:*.cmd
+glob:*.diff
+glob:*.patch
+glob:*.orig
+glob:*.bak
+glob:*.rej
--- a/.hgtags Thu Aug 26 23:59:18 2010 +0200
+++ b/.hgtags Wed Oct 27 14:02:20 2010 +0200
@@ -11,3 +11,14 @@
bb56f0682655b18f229be97085a409e3c76f578e hedgewars-0.8.1
fee68e3a303998fdfcc69f74775dc84a36f587fb 0.9.9
fee68e3a303998fdfcc69f74775dc84a36f587fb 0.9.9.1
+fd6c20cd90e33fa5e4f03e1c1f220b3eb14d169a Hedgewars-iOS-1.0
+fd6c20cd90e33fa5e4f03e1c1f220b3eb14d169a Hedgewars-iOS-1.0
+0000000000000000000000000000000000000000 Hedgewars-iOS-1.0
+0000000000000000000000000000000000000000 Hedgewars-iOS-1.0
+81db3c85784b4f35c7ff1ef9a5d64f5bdd383f08 Hedgewars-iOS-1.0
+296ec09490d92a74619aa8595df1bbcfd0dff4e5 Hedgewars-iOS-1.0.1
+296ec09490d92a74619aa8595df1bbcfd0dff4e5 Hedgewars-iOS-1.0.1
+0000000000000000000000000000000000000000 Hedgewars-iOS-1.0.1
+0000000000000000000000000000000000000000 Hedgewars-iOS-1.0.1
+3620607258cdc1213dce20cb6ad7872f6b8085e0 Hedgewars-iOS-1.0.1
+adffb668f06e265b45d1e4aedc283e6f4e5ba7e8 Hedgewars-iOS-1.1
--- a/CMakeLists.txt Thu Aug 26 23:59:18 2010 +0200
+++ b/CMakeLists.txt Wed Oct 27 14:02:20 2010 +0200
@@ -11,10 +11,10 @@
set(version_suffix "-dev") #UNSET THIS VARIABLE AT RELEASE TIME
IF(version_suffix MATCHES "-dev")
set(HW_DEV true)
- IF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.hg)
+ IF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.hg)
FIND_PROGRAM(HGCOMMAND hg)
IF(HGCOMMAND)
- exec_program(${HGCOMMAND}
+ exec_program(${HGCOMMAND}
ARGS identify -in ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE version_suffix
)
@@ -55,16 +55,16 @@
if(APPLE)
set(CMAKE_FIND_FRAMEWORK "FIRST")
-
+
#paths for creating the bundle
set(bundle_name Hedgewars.app)
- set(CMAKE_INSTALL_PREFIX ${bundle_name}/Contents/MacOS/)
+ set(CMAKE_INSTALL_PREFIX ${bundle_name}/Contents/MacOS/)
set(DATA_INSTALL_DIR "../Resources/")
set(target_dir ".")
-
+
#what system are we building for
set(minimum_macosx $ENV{MACOSX_DEPLOYMENT_TARGET})
-
+
#detect on which system are we
EXEC_PROGRAM("/usr/bin/sw_vers" OUTPUT_VARIABLE MACOSX_VERSION_TMP)
STRING(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" MACOSX_VERSION_TMP "${MACOSX_VERSION_TMP}")
@@ -97,9 +97,9 @@
if(current_macosx_version MATCHES "10.6")
set(CMAKE_OSX_ARCHITECTURES "x86_64")
endif()
- ENDIF()
+ ENDIF()
- message(STATUS "Target system: Mac OS X ${minimum_macosx} ${CMAKE_OSX_ARCHITECTURES}")
+ message(STATUS "Target system: Mac OS X ${minimum_macosx} ${CMAKE_OSX_ARCHITECTURES}")
if(minimum_macosx MATCHES "10.4")
set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.4u.sdk/")
@@ -132,10 +132,10 @@
endif (NOT CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE MATCHES RELEASE OR CMAKE_BUILD_TYPE MATCHES "Release")
- message(STATUS "Building Release")
+ message(STATUS "Building Release")
set(Optz true)
else()
- message(STATUS "Building Debug")
+ message(STATUS "Building Debug")
#set(CMAKE_VERBOSE_MAKEFILE true)
set(Optz false)
endif()
@@ -205,7 +205,7 @@
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Hedgewars ${HEDGEWARS_VERSION}")
if(WIN32 AND NOT UNIX)
- set(CPACK_NSIS_DISPLAY_NAME ${CPACK_PACKAGE_DESCRIPTION_SUMMARY})
+ set(CPACK_NSIS_DISPLAY_NAME "Hedgewars")
set(CPACK_NSIS_HELP_LINK "http://www.hedgewars.org/")
set(CPACK_NSIS_URL_INFO_ABOUT "http://www.hedgewars.org/")
set(CPACK_NSIS_CONTACT "unC0Rr@gmail.com")
--- a/QTfrontend/CMakeLists.txt Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/CMakeLists.txt Wed Oct 27 14:02:20 2010 +0200
@@ -183,7 +183,7 @@
)
-set( HW_LINK_LIBS
+set( HW_LINK_LIBS
${QT_LIBRARIES}
${SDL_LIBRARY}
${SDLMIXER_LIBRARY}
@@ -195,7 +195,7 @@
set(HW_LINK_LIBS ${HW_LINK_LIBS} SDL)
endif()
- set( HW_LINK_LIBS
+ set( HW_LINK_LIBS
${HW_LINK_LIBS}
ole32
oleaut32
--- a/QTfrontend/CocoaInitializer.mm Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/CocoaInitializer.mm Wed Oct 27 14:02:20 2010 +0200
@@ -8,7 +8,7 @@
#include <Cocoa/Cocoa.h>
#include <QtDebug>
-class CocoaInitializer::Private
+class CocoaInitializer::Private
{
public:
NSAutoreleasePool* autoReleasePool_;
--- a/QTfrontend/InstallController.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/InstallController.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -1,6 +1,6 @@
/*
* InstallController.cpp
- *
+ *
*
* Created by Vittorio on 28/09/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
--- a/QTfrontend/InstallController.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/InstallController.h Wed Oct 27 14:02:20 2010 +0200
@@ -1,6 +1,6 @@
/*
* InstallController.h
- *
+ *
*
* Created by Vittorio on 28/09/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
@@ -14,8 +14,8 @@
{
public:
virtual ~InstallController();
-
+
virtual void showInstallController() = 0;
};
-#endif
\ No newline at end of file
+#endif
--- a/QTfrontend/M3InstallController.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/M3InstallController.h Wed Oct 27 14:02:20 2010 +0200
@@ -1,10 +1,10 @@
/*****************************************************************
M3InstallController.m
-
+
Created by Martin Pilkington on 02/06/2007.
-
+
Copyright (c) 2006-2009 M Cubed Software
-
+
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
@@ -13,10 +13,10 @@
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
-
+
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
-
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -25,7 +25,7 @@
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
-
+
*****************************************************************/
#import <Cocoa/Cocoa.h>
--- a/QTfrontend/M3InstallController.m Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/M3InstallController.m Wed Oct 27 14:02:20 2010 +0200
@@ -1,10 +1,10 @@
/*****************************************************************
M3InstallController.m
-
+
Created by Martin Pilkington on 02/06/2007.
-
+
Copyright (c) 2006-2009 M Cubed Software
-
+
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
@@ -13,10 +13,10 @@
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
-
+
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
-
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -25,7 +25,7 @@
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
-
+
*****************************************************************/
#import "M3InstallController.h"
@@ -40,7 +40,7 @@
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"%@ is currently running from a disk image", @"AppName is currently running from a disk image"), appName];
NSString *body = [NSString stringWithFormat:NSLocalizedString(@"Would you like to install %@ in your applications folder before quitting?", @"Would you like to install App Name in your applications folder before quitting?"), appName];
- alert = [[NSAlert alertWithMessageText:title
+ alert = [[NSAlert alertWithMessageText:title
defaultButton:NSLocalizedString(@"Install", @"Install")
alternateButton:NSLocalizedString(@"Don't Install", @"Don't Install")
otherButton:nil
@@ -67,16 +67,16 @@
NSString *appsPath = [[NSString stringWithString:@"/Applications"] stringByAppendingPathComponent:[[[NSBundle mainBundle] bundlePath] lastPathComponent]];
NSString *userAppsPath = [[[NSString stringWithString:@"~/Applications"] stringByAppendingPathComponent:[[[NSBundle mainBundle] bundlePath] lastPathComponent]] stringByExpandingTildeInPath];
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
-
+
//Delete the app that is installed
if ([[NSFileManager defaultManager] fileExistsAtPath:appsPath]) {
[[NSFileManager defaultManager] removeFileAtPath:appsPath handler:nil];
}
//Delete the app that is installed
- if ([[NSFileManager defaultManager] copyPath:[[NSBundle mainBundle] bundlePath] toPath:appsPath
+ if ([[NSFileManager defaultManager] copyPath:[[NSBundle mainBundle] bundlePath] toPath:appsPath
handler:nil]) {
- NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"App Name installed successfully"), appName],
- [NSString stringWithFormat:NSLocalizedString(@"%@ was installed in /Applications", @"App Name was installed in /Applications"), appName],
+ NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"App Name installed successfully"), appName],
+ [NSString stringWithFormat:NSLocalizedString(@"%@ was installed in /Applications", @"App Name was installed in /Applications"), appName],
NSLocalizedString(@"Quit", @"Quit"), nil, nil);
} else {
if ([[NSFileManager defaultManager] fileExistsAtPath:userAppsPath]) {
@@ -84,11 +84,11 @@
}
if ([[NSFileManager defaultManager] copyPath:[[NSBundle mainBundle] bundlePath] toPath:userAppsPath
handler:nil]) {
- NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"AppName installed successfully"), appName],
- [NSString stringWithFormat:NSLocalizedString(@"%@ was installed in %@", @"App Name was installed in %@"), appName, [[NSString stringWithString:@"~/Applications"] stringByExpandingTildeInPath]],
+ NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"AppName installed successfully"), appName],
+ [NSString stringWithFormat:NSLocalizedString(@"%@ was installed in %@", @"App Name was installed in %@"), appName, [[NSString stringWithString:@"~/Applications"] stringByExpandingTildeInPath]],
NSLocalizedString(@"Quit", @"Quit"), nil, nil);
} else {
- NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"Could not install %@", @"Could not install App Name"), appName],
+ NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"Could not install %@", @"Could not install App Name"), appName],
NSLocalizedString(@"An error occurred when installing", @"An error occurred when installing"), NSLocalizedString(@"Quit", @"Quit"), nil, nil);
}
}
--- a/QTfrontend/M3Panel.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/M3Panel.h Wed Oct 27 14:02:20 2010 +0200
@@ -1,6 +1,6 @@
/*
* M3Panel.h
- *
+ *
*
* Created by Vittorio on 28/09/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
@@ -17,9 +17,9 @@
public:
M3Panel(void);
~M3Panel();
-
+
void showInstallController();
-
+
private:
class Private;
Private* c;
--- a/QTfrontend/M3Panel.mm Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/M3Panel.mm Wed Oct 27 14:02:20 2010 +0200
@@ -1,6 +1,6 @@
/*
* M3Panel.cpp
- *
+ *
*
* Created by Vittorio on 28/09/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
@@ -21,10 +21,10 @@
M3Panel::M3Panel(void)
{
c = new Private;
-
+
c->install = [[M3InstallController alloc] init];
[c->install retain];
-
+
}
M3Panel::~M3Panel()
--- a/QTfrontend/NSWorkspace_RBAdditions.m Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/NSWorkspace_RBAdditions.m Wed Oct 27 14:02:20 2010 +0200
@@ -107,7 +107,7 @@
}
NSString* cls = [(NSString*)IOObjectCopyClass(nextParent) autorelease];
if (![cls isEqualToString:@"IOPCIDevice"]) {
-
+
// Uncomment the following line to have the device tree dumped to the console.
// NSLog(@"=================================> %@:%@\n",cls,props);
@@ -207,7 +207,7 @@
}
}
//Don't need this for disk images, gets around warnings for some deprecated functions
-
+
/* else {
// For a network volume, get the volume reference number and use to get the server URL.
FSRef ref;
--- a/QTfrontend/SDLs.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/SDLs.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -35,7 +35,7 @@
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
-
+
musicInitialized = 0;
music = NULL;
if(SDL_NumJoysticks())
@@ -86,7 +86,7 @@
for(int jid = 0; jid < SDL_NumJoysticks(); jid++)
{
SDL_Joystick* joy = SDL_JoystickOpen(jid);
-
+
// Retrieve the game controller's name and strip "Controller (...)" that's added by some drivers (English only)
QString joyname = QString(SDL_JoystickName(jid)).replace(QRegExp("^Controller \\((.*)\\)$"), "\\1");
@@ -102,7 +102,7 @@
{
// Again store the part of the string not changing for multiple uses
QString axis = prefix + QApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1);
-
+
// Entry for "Axis Up"
sprintf(sdlkeys[i][0], "j%da%du", jid, aid);
sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + QApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + QApplication::translate("binds (keys)", "(Up)")).toStdString().c_str());
@@ -119,33 +119,33 @@
QString hat = prefix + (isxb ? (QApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : QApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1));
// Entry for "Hat Up"
- sprintf(sdlkeys[i][0], "j%dh%du", jid, hid);
+ sprintf(sdlkeys[i][0], "j%dh%du", jid, hid);
sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Up)")).toStdString().c_str());
// Entry for "Hat Down"
- sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid);
+ sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid);
sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Down)")).toStdString().c_str());
// Entry for "Hat Left"
- sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid);
+ sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid);
sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Left)")).toStdString().c_str());
// Entry for "Hat Right"
- sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid);
+ sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid);
sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Right)")).toStdString().c_str());
}
-
+
// Register entries for all buttons of this joystick/gamepad
for(int bid = 0; bid < SDL_JoystickNumButtons(joy) && i < 1022; bid++)
{
// Buttons
- sprintf(sdlkeys[i][0], "j%db%d", jid, bid);
+ sprintf(sdlkeys[i][0], "j%db%d", jid, bid);
sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (QApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : QApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toStdString().c_str());
}
// Close the game controller as we no longer need it
SDL_JoystickClose(joy);
}
-
+
// Terminate the list
sdlkeys[i][0][0] = '\0';
sdlkeys[i][1][0] = '\0';
@@ -167,7 +167,7 @@
if (music == NULL) {
music = Mix_LoadMUS((datadir->absolutePath() + "/Music/main theme.ogg").toLocal8Bit().constData());
-
+
}
Mix_VolumeMusic(MIX_MAX_VOLUME - 28);
Mix_FadeInMusic(music, -1, 1750);
--- a/QTfrontend/SDLs.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/SDLs.h Wed Oct 27 14:02:20 2010 +0200
@@ -32,7 +32,7 @@
private:
Mix_Music *music;
- int musicInitialized;
+ int musicInitialized;
public:
SDLInteraction();
@@ -41,7 +41,7 @@
void addGameControllerKeys() const;
void StartMusic();
void StopMusic();
- void SDLMusicInit();
+ void SDLMusicInit();
};
--- a/QTfrontend/about.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/about.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -90,7 +90,7 @@
"<br>"
"Julien Koesten <<a href=\"mailto:julienkoesten@aol.com\">julienkoesten@aol.com</a>>"
"<br>"
- "Joshua O'Sullivan <<a href=\"mailto:battysausage@hotmail.co.uk\">battysausage@hotmail.co.uk</a>>"
+ "Joshua O'Sullivan <<a href=\"mailto:coheedftw@hotmail.co.uk\">coheedftw@hotmail.co.uk</a>>"
"<br>"
"Nils Lück <<a href=\"mailto:nils.luck.design@gmail.com\">nils.luck.design@gmail.com</a>>"
"<br>"
@@ -118,7 +118,7 @@
"German: Peter Hüwe <<a href=\"mailto:PeterHuewe@gmx.de\">PeterHuewe@gmx.de</a>>, Mario Liebisch <<a href=\"mailto:mario.liebisch@gmail.com\">mario.liebisch@gmail.com</a>><br>"
"Italian: Luca Bonora <<a href=\"mailto:bonora.luca@gmail.com\">bonora.luca@gmail.com</a>><br>"
"Japanese: ADAM Etienne <<a href=\"mailto:etienne.adam@gmail.com\">etienne.adam@gmail.com</a>><br>"
- "Polish: Maciej Mroziński <<a href=\"mailto:mynick2@o2.pl\">mynick2@o2.pl</a>>, Wojciech Latkowski <<a href=\"mailto:magik17l@gmail.com\">magikmagik17l@gmail.com</a>>, Maciej Górny<br>"
+ "Polish: Maciej Mroziński <<a href=\"mailto:mynick2@o2.pl\">mynick2@o2.pl</a>>, Wojciech Latkowski <<a href=\"mailto:magik17l@gmail.com\">magik17l@gmail.com</a>>, Piotr Mitana, Maciej Górny<br>"
"Portuguese: Fábio Canário <<a href=\"mailto:inufabie@gmail.com\">inufabie@gmail.com</a>><br>"
"Russian: Andrey Korotaev <<a href=\"mailto:unC0Rr@gmail.com\">unC0Rr@gmail.com</a>><br>"
"Slovak: Jose Riha<br>"
--- a/QTfrontend/achievements.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/achievements.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -33,5 +33,5 @@
{"skipping", QT_TRANSLATE_NOOP("achievements", "Skipped"), QT_TRANSLATE_NOOP("achievements", "Let a single hog skip over the surface of the water for at least 5 times."), "skipped", "1", "hidden"},
{"cgunman", QT_TRANSLATE_NOOP("achievements", "Crazy Gunman"), QT_TRANSLATE_NOOP("achievements", "Eliminate 3 hogs with a single shot of the sniper rifle."), "cgunman", "1", ""},
*/
- {0, 0, 0, 0, 0, 0} // "terminator" line
+ { {0, 0, 0, 0, 0, 0} } // "terminator" line
};
--- a/QTfrontend/ammoSchemeModel.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/ammoSchemeModel.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -41,15 +41,19 @@
<< QVariant(false) // shared ammo 15
<< QVariant(false) //disable girders 16
<< QVariant(false) // disable land objects 17
- << QVariant(100) // damage modfier 18
- << QVariant(45) // turn time 19
- << QVariant(100) // init health 20
- << QVariant(15) // sudden death 21
- << QVariant(5) // case prob 22
- << QVariant(3) // mines time 23
- << QVariant(4) // landadds 24
- << QVariant(0) // mine dud pct 25
- << QVariant(2) // explosives 26
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(false) // per hog ammo 21
+ << QVariant(100) // damage modfier 22
+ << QVariant(45) // turn time 23
+ << QVariant(100) // init health 24
+ << QVariant(15) // sudden death 25
+ << QVariant(5) // case prob 26
+ << QVariant(3) // mines time 27
+ << QVariant(4) // landadds 28
+ << QVariant(0) // mine dud pct 29
+ << QVariant(2) // explosives 30
;
AmmoSchemeModel::AmmoSchemeModel(QObject* parent, const QString & fileName) :
@@ -87,15 +91,19 @@
<< "sharedammo" // 15
<< "disablegirders" // 16
<< "disablelandobjects" // 17
- << "damagefactor" // 18
- << "turntime" // 19
- << "health" // 20
- << "suddendeath" // 21
- << "caseprobability" // 22
- << "minestime" // 23
- << "landadds" // 24
- << "minedudpct" // 25
- << "explosives" // 26
+ << "aisurvival" // 18
+ << "infattack" // 19
+ << "resetweps" // 20
+ << "perhogammo" // 21
+ << "damagefactor" // 22
+ << "turntime" // 23
+ << "health" // 24
+ << "suddendeath" // 25
+ << "caseprobability" // 26
+ << "minestime" // 27
+ << "landadds" // 28
+ << "minedudpct" // 29
+ << "explosives" // 30
;
QList<QVariant> proMode;
@@ -118,15 +126,19 @@
<< QVariant(true) // shared ammo 15
<< QVariant(false) //disable girders 16
<< QVariant(false) // disable land objects 17
- << QVariant(100) // damage modfier 18
- << QVariant(15) // turn time 19
- << QVariant(100) // init health 20
- << QVariant(15) // sudden death 21
- << QVariant(0) // case prob 22
- << QVariant(3) // mines time 23
- << QVariant(4) // landadds 24
- << QVariant(0) // mine dud pct 25
- << QVariant(2) // explosives 26
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(false) // per hog ammo 21
+ << QVariant(100) // damage modfier 22
+ << QVariant(15) // turn time 23
+ << QVariant(100) // init health 24
+ << QVariant(15) // sudden death 25
+ << QVariant(0) // case prob 26
+ << QVariant(3) // mines time 27
+ << QVariant(4) // landadds 28
+ << QVariant(0) // mine dud pct 29
+ << QVariant(2) // explosives 30
;
QList<QVariant> shoppa;
@@ -149,15 +161,19 @@
<< QVariant(true) // shared ammo 15
<< QVariant(true) //disable girders 16
<< QVariant(false) // disable land objects 17
- << QVariant(100) // damage modfier 18
- << QVariant(30) // turn time 19
- << QVariant(100) // init health 20
- << QVariant(50) // sudden death 21
- << QVariant(1) // case prob 22
- << QVariant(3) // mines time 23
- << QVariant(4) // landadds 24
- << QVariant(0) // mine dud pct 25
- << QVariant(0) // explosives 26
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(false) // per hog ammo 21
+ << QVariant(100) // damage modfier 22
+ << QVariant(30) // turn time 23
+ << QVariant(100) // init health 24
+ << QVariant(50) // sudden death 25
+ << QVariant(1) // case prob 26
+ << QVariant(3) // mines time 27
+ << QVariant(4) // landadds 28
+ << QVariant(0) // mine dud pct 29
+ << QVariant(0) // explosives 30
;
QList<QVariant> basketball;
@@ -180,15 +196,19 @@
<< QVariant(true) // shared ammo 15
<< QVariant(true) //disable girders 16
<< QVariant(false) // disable land objects 17
- << QVariant(100) // damage modfier 18
- << QVariant(30) // turn time 19
- << QVariant(100) // init health 20
- << QVariant(15) // sudden death 21
- << QVariant(0) // case prob 22
- << QVariant(3) // mines time 23
- << QVariant(4) // landadds 24
- << QVariant(0) // mine dud pct 25
- << QVariant(0) // explosives 26
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(false) // per hog ammo 21
+ << QVariant(100) // damage modfier 22
+ << QVariant(30) // turn time 23
+ << QVariant(100) // init health 24
+ << QVariant(15) // sudden death 25
+ << QVariant(0) // case prob 26
+ << QVariant(3) // mines time 27
+ << QVariant(4) // landadds 28
+ << QVariant(0) // mine dud pct 29
+ << QVariant(0) // explosives 30
;
QList<QVariant> minefield;
@@ -211,15 +231,19 @@
<< QVariant(true) // shared ammo 15
<< QVariant(true) //disable girders 16
<< QVariant(false) // disable land objects 17
- << QVariant(150) // damage modfier 18
- << QVariant(30) // turn time 19
- << QVariant(50) // init health 20
- << QVariant(15) // sudden death 21
- << QVariant(0) // case prob 22
- << QVariant(0) // mines time 23
- << QVariant(80) // landadds 24
- << QVariant(0) // mine dud pct 25
- << QVariant(0) // explosives 26
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(false) // per hog ammo 21
+ << QVariant(150) // damage modfier 22
+ << QVariant(30) // turn time 23
+ << QVariant(50) // init health 24
+ << QVariant(15) // sudden death 25
+ << QVariant(0) // case prob 26
+ << QVariant(0) // mines time 27
+ << QVariant(80) // landadds 28
+ << QVariant(0) // mine dud pct 29
+ << QVariant(0) // explosives 30
;
QList<QVariant> barrelmayhem;
@@ -242,15 +266,19 @@
<< QVariant(true) // shared ammo 15
<< QVariant(false) //disable girders 16
<< QVariant(false) // disable land objects 17
- << QVariant(100) // damage modfier 18
- << QVariant(30) // turn time 19
- << QVariant(100) // init health 20
- << QVariant(15) // sudden death 21
- << QVariant(0) // case prob 22
- << QVariant(0) // mines time 23
- << QVariant(0) // landadds 24
- << QVariant(0) // mine dud pct 25
- << QVariant(80) // explosives 26
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(false) // per hog ammo 21
+ << QVariant(100) // damage modfier 22
+ << QVariant(30) // turn time 23
+ << QVariant(100) // init health 24
+ << QVariant(15) // sudden death 25
+ << QVariant(0) // case prob 26
+ << QVariant(0) // mines time 27
+ << QVariant(0) // landadds 28
+ << QVariant(0) // mine dud pct 29
+ << QVariant(80) // explosives 30
;
QList<QVariant> tunnelhogs;
@@ -273,15 +301,19 @@
<< QVariant(true) // shared ammo 15
<< QVariant(true) //disable girders 16
<< QVariant(true) // disable land objects 17
- << QVariant(100) // damage modfier 18
- << QVariant(30) // turn time 19
- << QVariant(100) // init health 20
- << QVariant(15) // sudden death 21
- << QVariant(5) // case prob 22
- << QVariant(3) // mines time 23
- << QVariant(10) // landadds 24
- << QVariant(10) // mine dud pct 25
- << QVariant(10) // explosives 26
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(false) // per hog ammo 21
+ << QVariant(100) // damage modfier 22
+ << QVariant(30) // turn time 23
+ << QVariant(100) // init health 24
+ << QVariant(15) // sudden death 25
+ << QVariant(5) // case prob 26
+ << QVariant(3) // mines time 27
+ << QVariant(10) // landadds 28
+ << QVariant(10) // mine dud pct 29
+ << QVariant(10) // explosives 30
;
schemes.append(defaultScheme);
--- a/QTfrontend/chatwidget.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/chatwidget.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -54,14 +54,14 @@
mainLayout.setSpacing(1);
mainLayout.setMargin(1);
mainLayout.setSizeConstraint(QLayout::SetMinimumSize);
- mainLayout.setColumnStretch(0, 75);
- mainLayout.setColumnStretch(1, 25);
+ mainLayout.setColumnStretch(0, 76);
+ mainLayout.setColumnStretch(1, 24);
chatEditLine = new QLineEdit(this);
chatEditLine->setMaxLength(300);
connect(chatEditLine, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
- mainLayout.addWidget(chatEditLine, 1, 0, 1, 2);
+ mainLayout.addWidget(chatEditLine, 1, 0);
chatText = new QTextBrowser(this);
chatText->setMinimumHeight(20);
@@ -81,7 +81,7 @@
connect(chatNicks, SIGNAL(currentRowChanged(int)),
this, SLOT(chatNickSelected(int)));
- mainLayout.addWidget(chatNicks, 0, 1);
+ mainLayout.addWidget(chatNicks, 0, 1, -1, 1);
acInfo = new QAction(QAction::tr("Info"), chatNicks);
acInfo->setIcon(QIcon(":/res/info.png"));
@@ -106,7 +106,7 @@
chatNicks->insertAction(0, acFollow);
chatNicks->insertAction(0, acIgnore);
chatNicks->insertAction(0, acFriend);
-
+
showReady = false;
}
@@ -151,17 +151,17 @@
if(ignoreList.contains(nick, Qt::CaseInsensitive))
{
- item->setIcon(QIcon(showReady ? (item->data(Qt::UserRole).toBool() ? ":/res/chat_ignore_on" : ":/res/chat_ignore_off") : ":/res/chat_ignore.png"));
+ item->setIcon(QIcon(showReady ? (item->data(Qt::UserRole).toBool() ? ":/res/chat_ignore_on.png" : ":/res/chat_ignore_off.png") : ":/res/chat_ignore.png"));
item->setForeground(Qt::gray);
}
else if(friendsList.contains(nick, Qt::CaseInsensitive))
{
- item->setIcon(QIcon(showReady ? (item->data(Qt::UserRole).toBool() ? ":/res/chat_friend_on" : ":/res/chat_friend_off") : ":/res/chat_friend.png"));
+ item->setIcon(QIcon(showReady ? (item->data(Qt::UserRole).toBool() ? ":/res/chat_friend_on.png" : ":/res/chat_friend_off.png") : ":/res/chat_friend.png"));
item->setForeground(Qt::green);
}
else
{
- item->setIcon(QIcon(showReady ? (item->data(Qt::UserRole).toBool() ? ":/res/chat_default_on" : ":/res/chat_default_off") : ":/res/chat_default.png"));
+ item->setIcon(QIcon(showReady ? (item->data(Qt::UserRole).toBool() ? ":/res/chat_default_on.png" : ":/res/chat_default_off.png") : ":/res/chat_default.png"));
item->setForeground(QBrush(QColor(0xff, 0xcc, 0x00)));
}
}
@@ -209,7 +209,7 @@
QString color("");
bool isFriend = friendsList.contains(parts[0], Qt::CaseInsensitive);
-
+
if (str.startsWith("\x03"))
color = QString("#c0c0c0");
else if (str.startsWith("\x02"))
--- a/QTfrontend/frameTeam.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/frameTeam.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -35,12 +35,9 @@
mainLayout.setSpacing(1);
mainLayout.setContentsMargins(4, 4, 4, 4);
- availableColors.push_back(*color1);
- availableColors.push_back(*color2);
- availableColors.push_back(*color3);
- availableColors.push_back(*color4);
- availableColors.push_back(*color5);
- availableColors.push_back(*color6);
+ int i = 0;
+ while(colors[i])
+ availableColors.push_back(*colors[i++]);
resetColors();
}
@@ -57,7 +54,7 @@
void FrameTeams::resetColors()
{
- currentColor=availableColors.begin();
+ currentColor=availableColors.end() - 1; // ensure next color is the first one
}
QColor FrameTeams::getNextColor() const
--- a/QTfrontend/game.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/game.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -30,7 +30,7 @@
#include <QTextStream>
-QString training; // TODO: Cleaner solution?
+QString training, campaign; // TODO: Cleaner solution?
HWGame::HWGame(GameUIConfig * config, GameCFGWidget * gamecfg, QString ammo, TeamSelWidget* pTeamSelWidget) :
TCPBase(true),
@@ -84,13 +84,13 @@
QList<HWTeam> teams = m_pTeamSelWidget->getPlayingTeams();
for(QList<HWTeam>::iterator it = teams.begin(); it != teams.end(); ++it)
{
- HWProto::addStringListToBuffer(buf,
- (*it).TeamGameConfig(gamecfg->getInitHealth()));
HWProto::addStringToBuffer(buf, QString("eammloadt %1").arg(ammostr.mid(0, cAmmoNumber)));
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"));
+ HWProto::addStringListToBuffer(buf,
+ (*it).TeamGameConfig(gamecfg->getInitHealth()));
}
}
RawSendIPC(buf);
@@ -115,7 +115,7 @@
HWTeam * team1;
team1 = new HWTeam;
team1->difficulty = 0;
- team1->teamColor = *color1;
+ team1->teamColor = *colors[0];
team1->numHedgehogs = 4;
namegen.TeamRandomNames(team1,TRUE);
HWProto::addStringListToBuffer(teamscfg,
@@ -124,7 +124,7 @@
HWTeam * team2;
team2 = new HWTeam;
team2->difficulty = 4;
- team2->teamColor = *color2;
+ team2->teamColor = *colors[1];
team2->numHedgehogs = 4;
do
namegen.TeamRandomNames(team2,TRUE);
@@ -146,11 +146,21 @@
QByteArray traincfg;
HWProto::addStringToBuffer(traincfg, "TL");
- HWProto::addStringToBuffer(traincfg, "escript " + datadir->absolutePath() + "/Missions/Training/" + training + ".lua");
+ HWProto::addStringToBuffer(traincfg, "escript " + training);
RawSendIPC(traincfg);
}
+void HWGame::SendCampaignConfig()
+{
+ QByteArray campaigncfg;
+ HWProto::addStringToBuffer(campaigncfg, "TL");
+
+ HWProto::addStringToBuffer(campaigncfg, "escript " + campaign);
+
+ RawSendIPC(campaigncfg);
+}
+
void HWGame::SendNetConfig()
{
commonConfig();
@@ -182,6 +192,10 @@
SendTrainingConfig();
break;
}
+ case gtCampaign: {
+ SendCampaignConfig();
+ break;
+ }
}
break;
}
@@ -277,18 +291,17 @@
arguments << QString("%1").arg(ipc_port);
arguments << (config->vid_Fullscreen() ? "1" : "0");
arguments << (config->isSoundEnabled() ? "1" : "0");
- arguments << "0"; //(config->isSoundHardware() ? "1" : "0");
- arguments << "0"; //(config->isWeaponTooltip() ? "1" : "0");
- arguments << tr("en.txt");
+ arguments << (config->isMusicEnabled() ? "1" : "0");
arguments << QString::number(config->volume()); // sound volume
arguments << QString::number(config->timerInterval());
arguments << datadir->absolutePath();
arguments << (config->isShowFPSEnabled() ? "1" : "0");
arguments << (config->isAltDamageEnabled() ? "1" : "0");
arguments << config->netNick().toUtf8().toBase64();
- arguments << (config->isMusicEnabled() ? "1" : "0");
arguments << QString::number(config->translateQuality());
arguments << QString::number(config->stereoMode());
+ arguments << tr("en.txt");
+
return arguments;
}
@@ -345,7 +358,16 @@
void HWGame::StartTraining(const QString & file)
{
gameType = gtTraining;
- training = file;
+ training = "Missions/Training/" + file + ".lua";
+ demo.clear();
+ Start();
+ SetGameState(gsStarted);
+}
+
+void HWGame::StartCampaign(const QString & file)
+{
+ gameType = gtCampaign;
+ campaign = "Missions/Campaign/" + file + ".lua";
demo.clear();
Start();
SetGameState(gsStarted);
--- a/QTfrontend/game.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/game.h Wed Oct 27 14:02:20 2010 +0200
@@ -51,6 +51,7 @@
void StartQuick();
void StartNet();
void StartTraining(const QString & file);
+ void StartCampaign(const QString & file);
protected:
virtual QStringList setArguments();
@@ -76,7 +77,8 @@
gtQLocal = 2,
gtDemo = 3,
gtNet = 4,
- gtTraining = 5
+ gtTraining = 5,
+ gtCampaign = 6,
};
char msgbuf[MAXMSGCHARS];
QString teams[5];
@@ -93,6 +95,7 @@
void SendQuickConfig();
void SendNetConfig();
void SendTrainingConfig();
+ void SendCampaignConfig();
void ParseMessage(const QByteArray & msg);
void SetGameState(GameState state);
};
--- a/QTfrontend/gamecfgwidget.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/gamecfgwidget.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -101,46 +101,54 @@
quint32 result = 0;
if (schemeData(1).toBool())
- result |= 0x01;
+ result |= 0x00001000;
if (schemeData(2).toBool())
- result |= 0x10;
+ result |= 0x00000010;
if (schemeData(3).toBool())
- result |= 0x04;
+ result |= 0x00000004;
if (schemeData(4).toBool())
- result |= 0x08;
+ result |= 0x00000008;
if (schemeData(5).toBool())
- result |= 0x20;
+ result |= 0x00000020;
if (schemeData(6).toBool())
- result |= 0x40;
+ result |= 0x00000040;
if (schemeData(7).toBool())
- result |= 0x80;
+ result |= 0x00000080;
if (schemeData(8).toBool())
- result |= 0x100;
+ result |= 0x00000100;
if (schemeData(9).toBool())
- result |= 0x200;
+ result |= 0x00000200;
if (schemeData(10).toBool())
- result |= 0x400;
+ result |= 0x00000400;
if (schemeData(11).toBool())
- result |= 0x800;
+ result |= 0x00000800;
if (schemeData(12).toBool())
- result |= 0x2000;
+ result |= 0x00002000;
if (schemeData(13).toBool())
- result |= 0x4000;
+ result |= 0x00004000;
if (schemeData(14).toBool())
- result |= 0x8000;
+ result |= 0x00008000;
if (schemeData(15).toBool())
- result |= 0x10000;
+ result |= 0x00010000;
if (schemeData(16).toBool())
- result |= 0x20000;
+ result |= 0x00020000;
if (schemeData(17).toBool())
- result |= 0x80000;
+ result |= 0x00040000;
+ if (schemeData(18).toBool())
+ result |= 0x00080000;
+ if (schemeData(19).toBool())
+ result |= 0x00100000;
+ if (schemeData(20).toBool())
+ result |= 0x00200000;
+ if (schemeData(21).toBool())
+ result |= 0x00400000;
return result;
}
quint32 GameCFGWidget::getInitHealth() const
{
- return schemeData(20).toInt();
+ return schemeData(24).toInt();
}
QStringList GameCFGWidget::getFullConfig() const
@@ -148,14 +156,14 @@
QStringList sl;
sl.append("eseed " + pMapContainer->getCurrentSeed());
sl.append(QString("e$gmflags %1").arg(getGameFlags()));
- sl.append(QString("e$damagepct %1").arg(schemeData(18).toInt()));
- sl.append(QString("e$turntime %1").arg(schemeData(19).toInt() * 1000));
- sl.append(QString("e$minestime %1").arg(schemeData(23).toInt() * 1000));
- sl.append(QString("e$landadds %1").arg(schemeData(24).toInt()));
- sl.append(QString("e$sd_turns %1").arg(schemeData(21).toInt()));
- sl.append(QString("e$casefreq %1").arg(schemeData(22).toInt()));
- sl.append(QString("e$minedudpct %1").arg(schemeData(25).toInt()));
- sl.append(QString("e$explosives %1").arg(schemeData(26).toInt()));
+ sl.append(QString("e$damagepct %1").arg(schemeData(22).toInt()));
+ sl.append(QString("e$turntime %1").arg(schemeData(23).toInt() * 1000));
+ sl.append(QString("e$minestime %1").arg(schemeData(27).toInt() * 1000));
+ sl.append(QString("e$landadds %1").arg(schemeData(28).toInt()));
+ sl.append(QString("e$sd_turns %1").arg(schemeData(25).toInt()));
+ sl.append(QString("e$casefreq %1").arg(schemeData(26).toInt()));
+ sl.append(QString("e$minedudpct %1").arg(schemeData(29).toInt()));
+ sl.append(QString("e$explosives %1").arg(schemeData(30).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()));
@@ -165,8 +173,7 @@
{
sl.append("emap " + currentMap);
if(pMapContainer->getCurrentIsMission())
- sl.append(QString("escript %1/Maps/%2/map.lua")
- .arg(datadir->absolutePath())
+ sl.append(QString("escript Maps/%1/map.lua")
.arg(currentMap));
}
sl.append("etheme " + pMapContainer->getCurrentTheme());
--- a/QTfrontend/gameuiconfig.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/gameuiconfig.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -94,10 +94,10 @@
{
QDir teamdir;
teamdir.cd(cfgdir->absolutePath() + "/Teams");
- QStringList teamslist = teamdir.entryList(QStringList("*.ini"));
+ QStringList teamslist = teamdir.entryList(QStringList("*.hwt"));
QStringList cleanedList;
for (QStringList::Iterator it = teamslist.begin(); it != teamslist.end(); ++it ) {
- QString tmpTeamStr=(*it).replace(QRegExp("^(.*)\\.ini$"), "\\1");
+ QString tmpTeamStr=(*it).replace(QRegExp("^(.*)\\.hwt$"), "\\1");
cleanedList.push_back(tmpTeamStr);
}
return cleanedList;
@@ -180,7 +180,7 @@
quint32 GameUIConfig::translateQuality()
{
quint32 rqNone = 0x00000000; // don't reduce quality
- quint32 rqLowRes = 0x00000001; // use half land array
+ //quint32 rqLowRes = 0x00000001; // use half land array
quint32 rqBlurryLand = 0x00000002; // downscaled terrain
quint32 rqNoBackground = 0x00000004; // don't draw background
quint32 rqSimpleRope = 0x00000008; // avoid drawing rope
--- a/QTfrontend/hedgehogerWidget.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/hedgehogerWidget.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -23,34 +23,36 @@
CHedgehogerWidget::CHedgehogerWidget(const QImage& im, QWidget * parent) :
ItemNum(im, parent, 1)
{
- if(parent) {
+ // TODO: maxHedgehogsPerGame doesn't reset properly and won't match map limits for now
+ /*if(parent) {
pOurFrameTeams = dynamic_cast<FrameTeams*>(parent->parentWidget());
}
if(pOurFrameTeams->overallHedgehogs + 4 > pOurFrameTeams->maxHedgehogsPerGame) {
numItems = pOurFrameTeams->maxHedgehogsPerGame - pOurFrameTeams->overallHedgehogs;
} else numItems = 4;
- pOurFrameTeams->overallHedgehogs += numItems;
+ pOurFrameTeams->overallHedgehogs += numItems;*/
}
void CHedgehogerWidget::incItems()
{
- if (pOurFrameTeams->overallHedgehogs < pOurFrameTeams->maxHedgehogsPerGame) {
+ //if (pOurFrameTeams->overallHedgehogs < pOurFrameTeams->maxHedgehogsPerGame) {
numItems++;
- pOurFrameTeams->overallHedgehogs++;
+ //pOurFrameTeams->overallHedgehogs++;
emit hedgehogsNumChanged();
- }
+ //}
}
void CHedgehogerWidget::decItems()
{
numItems--;
- pOurFrameTeams->overallHedgehogs--;
+ //pOurFrameTeams->overallHedgehogs--;
emit hedgehogsNumChanged();
}
CHedgehogerWidget::~CHedgehogerWidget()
{
- pOurFrameTeams->overallHedgehogs-=numItems;
+ // TODO: not called?
+ //pOurFrameTeams->overallHedgehogs-=numItems;
}
void CHedgehogerWidget::setNonInteractive()
@@ -60,9 +62,10 @@
void CHedgehogerWidget::setHHNum(unsigned int num)
{
- unsigned int diff = num - numItems;
+ /*unsigned int diff = num - numItems;
numItems += diff;
- pOurFrameTeams->overallHedgehogs += diff;
+ pOurFrameTeams->overallHedgehogs += diff;*/
+ numItems = num;
repaint();
}
--- a/QTfrontend/hedgewars.qrc Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/hedgewars.qrc Wed Oct 27 14:02:20 2010 +0200
@@ -66,6 +66,10 @@
<file>res/btnSharedAmmo.png</file>
<file>res/btnDisableGirders.png</file>
<file>res/btnDisableLandObjects.png</file>
+ <file>res/btnAISurvival.png</file>
+ <file>res/btnInfAttack.png</file>
+ <file>res/btnResetWeps.png</file>
+ <file>res/btnPerHogAmmo.png</file>
<file>res/iconBox.png</file>
<file>res/iconHealth.png</file>
<file>res/iconSuddenDeath.png</file>
@@ -95,5 +99,23 @@
<file>res/follow.png</file>
<file>res/info.png</file>
<file>res/kick.png</file>
+ <file>res/StatsMedal1.png</file>
+ <file>res/StatsMedal2.png</file>
+ <file>res/StatsMedal3.png</file>
+ <file>res/StatsMedal4.png</file>
+ <file>res/StatsR.png</file>
+ <file>res/StatsH.png</file>
+ <file>res/StatsD.png</file>
+ <file>res/StatsBestKiller.png</file>
+ <file>res/StatsBestShot.png</file>
+ <file>res/StatsHedgehogsKilled.png</file>
+ <file>res/StatsMostSelfDamage.png</file>
+ <file>res/StatsSelfKilled.png</file>
+ <file>res/StatsSkipped.png</file>
+ <file>res/mapRandom.png</file>
+ <file>res/mapMaze.png</file>
+ <file>res/mapMissing.png</file>
+ <file>res/mapCustom.png</file>
+ <file>res/mapMission.png</file>
</qresource>
</RCC>
--- a/QTfrontend/hwconsts.cpp.in Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/hwconsts.cpp.in Wed Oct 27 14:02:20 2010 +0200
@@ -30,50 +30,65 @@
QStringList * Themes;
QStringList * mapList;
+bool custom_config = false;
+bool custom_data = false;
+
+int cMaxTeams = 6;
+
QString * cDefaultAmmoStore = new QString(
- "9391929422199121032235111001201000000211110111"
- "0405040541600655546554464776576666666155510111"
- "0000000000000205500000040007004000000000200000"
- "1311110312111111123114111111111111111211111111"
- );
+ "9391929422199121032235111001201000000211110101011"
+ "0405040541600655546554464776576666666155510101117"
+ "0000000000000205500000040007004000000000200000000"
+ "1311110312111111123114111111111111111211111101111"
+ );
int cAmmoNumber = cDefaultAmmoStore->size() / 4;
QList< QPair<QString, QString> > cDefaultAmmos =
- QList< QPair<QString, QString> >()
- << qMakePair(QString("Default"), *cDefaultAmmoStore)
- << qMakePair(QString("Crazy"), QString(
- "9999999999999999992999999999999999299999999999" // TODO: Remove Piano's unlimited uses!
- "1111110111111111111111111111111111111111111111"
- "0000000000000000000000000000000000000000000000"
- "1311110312111111123114111111111111111211110101"))
- << qMakePair(QString("Pro mode"), QString(
- "9090009000000000000009000000000000000000000900"
- "0000000000000000000000000000000000000000000000"
- "0000000000000205500000040007004000000000200000"
- "1111111111111111111111111111111111111111100111"))
- << qMakePair(QString("Shoppa"), QString(
- "0000009900000000000000000000000000000000000000"
- "4444410044244402210112121222422000000002000400"
- "0000000000000000000000000000000000000000000000"
- "1111111111111111111111111111111111111111101111"))
- << qMakePair(QString("Basketball"),QString(
- "0000009000000900000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000"
- "0000000000000005500000040007004000000000200000"
- "1111111111111111111111111111111111111111111111"))
- << qMakePair(QString("Minefield"), QString(
- "0000009900090000000300000000000000000000000000"
- "0000000000000000000000000000000000000000000000"
- "0000000000000205500000040007004000000000200000"
- "1111111111111111111111111111111111111111111111"))
- ;
+ QList< QPair<QString, QString> >()
+ << qMakePair(QString("Default"), *cDefaultAmmoStore)
+ << qMakePair(QString("Crazy"), QString(
+ // TODO: Remove Piano's unlimited uses!
+ "9999999999999999992999999999999999299999999909999"
+ "1111110111111111111111111111111111111111111101111"
+ "0000000000000000000000000000000000000000000000000"
+ "1311110312111111123114111111111111111211110101111"
+ ))
+ << qMakePair(QString("Pro mode"), QString(
+ "9090009000000000000009000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000"
+ "0000000000000205500000040007004000000000200000000"
+ "1111111111111111111111111111111111111111100101111"
+ ))
+ << qMakePair(QString("Shoppa"), QString(
+ "0000009900000000000000000000000000000000000000000"
+ "4444410044244402210112121222422000000002000400010"
+ "0000000000000000000000000000000000000000000000000"
+ "1111111111111111111111111111111111111111101101111"
+ ))
+ << qMakePair(QString("Basketball"),QString(
+ "0000009000000900000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000"
+ "0000000000000005500000040007004000000000200000000"
+ "1111111111111111111111111111111111111111111101111"
+ ))
+ << qMakePair(QString("Minefield"), QString(
+ "0000009900090000000300000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000"
+ "0000000000000205500000040007004000000000200000000"
+ "1111111111111111111111111111111111111111111101111"
+ ));
-QColor * color1 = new QColor(221, 0, 0);
-QColor * color2 = new QColor( 67, 118, 233);
-QColor * color3 = new QColor( 62, 147, 33);
-QColor * color4 = new QColor(162, 61, 187);
-QColor * color5 = new QColor(255, 147, 41);
-QColor * color6 = new QColor(115, 115, 115);
+QColor *colors[] = {
+ new QColor(221, 0, 0), // classic red
+ new QColor( 67, 118, 233), // classic blue
+ new QColor( 62, 147, 33), // classic green
+ new QColor(162, 61, 187), // classic purple
+ new QColor(255, 147, 41), // classic orange
+ new QColor(115, 115, 115), // classic gray
+ new QColor(187, 162, 61), // gold
+ new QColor( 61, 162, 187), // cyan
+ // add new colors here
+ 0};
QString * netHost = new QString();
quint16 netPort = 46631;
--- a/QTfrontend/hwconsts.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/hwconsts.h Wed Oct 27 14:02:20 2010 +0200
@@ -31,6 +31,11 @@
extern QDir * cfgdir;
extern QDir * datadir;
+extern bool custom_config;
+extern bool custom_data;
+
+extern int cMaxTeams;
+
extern QStringList * Themes;
extern QStringList * mapList;
@@ -38,12 +43,7 @@
extern int cAmmoNumber;
extern QList< QPair<QString, QString> > cDefaultAmmos;
-extern QColor * color1;
-extern QColor * color2;
-extern QColor * color3;
-extern QColor * color4;
-extern QColor * color5;
-extern QColor * color6;
+extern QColor *colors[];
extern QString * netHost;
extern quint16 netPort;
--- a/QTfrontend/hwform.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/hwform.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -83,9 +83,9 @@
ui.setupUi(this);
setMinimumSize(760, 580);
-
+ setFocusPolicy(Qt::StrongFocus);
CustomizePalettes();
-
+
ui.pageOptions->CBResolution->addItems(sdli.getResolutions());
config = new GameUIConfig(this, cfgdir->absolutePath() + "/hedgewars.ini");
@@ -93,17 +93,18 @@
namegen = new HWNamegen();
#ifdef __APPLE__
- panel = new M3Panel;
+ panel = new M3Panel;
#ifdef SPARKLE_ENABLED
- AutoUpdater* updater;
- CocoaInitializer initializer;
- updater = new SparkleAutoUpdater(SPARKLE_APPCAST_URL);
- if(updater && config->isAutoUpdateEnabled())
- updater->checkForUpdates();
-#endif
+ AutoUpdater* updater;
+ CocoaInitializer initializer;
+ updater = new SparkleAutoUpdater(SPARKLE_APPCAST_URL);
+ if (updater && config->isAutoUpdateEnabled())
+ updater->checkForUpdates();
+#endif
#endif
UpdateTeamsLists();
+ UpdateCampaignPage(0);
UpdateWeapons();
connect(config, SIGNAL(frontendFullscreen(bool)), this, SLOT(onFrontendFullscreen(bool)));
@@ -140,6 +141,9 @@
connect(ui.pageOptions->BtnDeleteTeam, SIGNAL(clicked()), this, SLOT(DeleteTeam()));
connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), config, SLOT(SaveOptions()));
connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), this, SLOT(GoBack()));
+#ifdef _WIN32
+ connect(ui.pageOptions->BtnAssociateFiles, SIGNAL(clicked()), this, SLOT(AssociateFiles()));
+#endif
connect(ui.pageOptions->WeaponEdit, SIGNAL(clicked()), this, SLOT(GoToSelectWeapon()));
connect(ui.pageOptions->WeaponsButt, SIGNAL(clicked()), this, SLOT(GoToSelectNewWeapon()));
@@ -171,6 +175,7 @@
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->BtnLoad, SIGNAL(clicked()), this, SLOT(GoToSaves()));
connect(ui.pageSinglePlayer->BtnDemos, SIGNAL(clicked()), this, SLOT(GoToDemos()));
@@ -179,6 +184,10 @@
connect(ui.pageTraining->BtnStartTrain, SIGNAL(clicked()), this, SLOT(StartTraining()));
connect(ui.pageTraining->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
+ connect(ui.pageCampaign->BtnStartCampaign, SIGNAL(clicked()), this, SLOT(StartCampaign()));
+ connect(ui.pageCampaign->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
+ connect(ui.pageCampaign->CBTeam, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateCampaignPage(int)));
+
connect(ui.pageSelectWeapon->BtnBack, SIGNAL(clicked()), this, SLOT(GoBack()));
connect(ui.pageSelectWeapon->BtnDelete, SIGNAL(clicked()),
@@ -265,6 +274,12 @@
}
}
+void HWForm::keyReleaseEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Escape /*|| event->key() == Qt::Key_Backspace*/ )
+ this->GoBack();
+}
+
void HWForm::CustomizePalettes()
{
QList<QScrollBar *> allSBars = findChildren<QScrollBar *>();
@@ -310,13 +325,15 @@
}
if(teamslist.empty()) {
- HWTeam defaultTeam("DefaultTeam");
+ HWTeam defaultTeam(tr("DefaultTeam"));
defaultTeam.SaveToFile();
- teamslist.push_back("DefaultTeam");
+ teamslist.push_back(tr("DefaultTeam"));
}
ui.pageOptions->CBTeamName->clear();
ui.pageOptions->CBTeamName->addItems(teamslist);
+ ui.pageCampaign->CBTeam->clear();
+ ui.pageCampaign->CBTeam->addItems(teamslist);
}
void HWForm::GoToMain()
@@ -334,6 +351,11 @@
GoToPage(ID_PAGE_TRAINING);
}
+void HWForm::GoToCampaign()
+{
+ GoToPage(ID_PAGE_CAMPAIGN);
+}
+
void HWForm::GoToSetup()
{
GoToPage(ID_PAGE_SETUP);
@@ -513,11 +535,11 @@
{
if (eggTimer.elapsed() < 3000){
#ifdef __APPLE__
- panel->showInstallController();
+ panel->showInstallController();
#endif
close();
}
- else
+ else
{
QPushButton * btn = findChild<QPushButton *>("imageButt");
if (btn)
@@ -543,7 +565,8 @@
for(QList<HWTeam>::iterator it = teams.begin(); it != teams.end(); ++it) {
tmnames += it->TeamName;
}
- UpdateTeamsLists(&tmnames); // FIXME: still need more work if teamname is updated while configuring
+ //UpdateTeamsLists(&tmnames); // FIXME: still need more work if teamname is updated while configuring
+ UpdateTeamsLists();
GoToPage(ID_PAGE_SETUP);
}
@@ -961,7 +984,14 @@
{
CreateGame(0, 0, 0);
- game->StartTraining(ui.pageTraining->CBSelect->currentText());
+ game->StartTraining(ui.pageTraining->CBSelect->itemData(ui.pageTraining->CBSelect->currentIndex()).toString());
+}
+
+void HWForm::StartCampaign()
+{
+ CreateGame(0, 0, 0);
+
+ game->StartCampaign(ui.pageCampaign->CBSelect->itemData(ui.pageCampaign->CBSelect->currentIndex()).toString());
}
void HWForm::CreateNetGame()
@@ -1074,3 +1104,33 @@
wBackground->move(0, 0);
}
}
+
+void HWForm::UpdateCampaignPage(int index)
+{
+ HWTeam team(ui.pageCampaign->CBTeam->currentText());
+ ui.pageCampaign->CBSelect->clear();
+
+ QDir tmpdir;
+ tmpdir.cd(datadir->absolutePath());
+ tmpdir.cd("Missions/Campaign");
+ tmpdir.setFilter(QDir::Files);
+ 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"));
+}
+
+void HWForm::AssociateFiles()
+{
+ QSettings registry_hkcr("HKEY_CLASSES_ROOT", QSettings::NativeFormat);
+ registry_hkcr.setValue(".hwd/Default", "Hedgewars.Demo");
+ registry_hkcr.setValue(".hws/Default", "Hedgewars.Save");
+ registry_hkcr.setValue("Hedgewars.Demo/Default", tr("Hedgewars Demo File", "File Types"));
+ registry_hkcr.setValue("Hedgewars.Save/Default", tr("Hedgewars Save File", "File Types"));
+ registry_hkcr.setValue("Hedgewars.Demo/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwdfile.ico\",0");
+ registry_hkcr.setValue("Hedgewars.Save/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwsfile.ico\",0");
+ registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\"");
+ registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\"");
+ QMessageBox::information(0, "", QMessageBox::tr("All file associations have been set."));
+}
+
--- a/QTfrontend/hwform.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/hwform.h Wed Oct 27 14:02:20 2010 +0200
@@ -69,6 +69,7 @@
void GoToNetType();
void GoToInfo();
void GoToTraining();
+ void GoToCampaign();
void GoToSelectWeapon();
void GoToSelectWeaponSet(const QString & name);
void GoToSelectNewWeapon();
@@ -77,6 +78,7 @@
void GoToAdmin();
void GoToPage(quint8 id);
void GoBack();
+ void AssociateFiles();
void btnExitPressed();
void btnExitClicked();
void IntermediateSetup();
@@ -90,6 +92,7 @@
void SimpleGame();
void PlayDemo();
void StartTraining();
+ void StartCampaign();
void NetConnect();
void NetConnectServer(const QString & host, quint16 port);
void NetConnectOfficialServer();
@@ -107,6 +110,7 @@
void UpdateWeapons();
void onFrontendFullscreen(bool value);
void Music(bool checked);
+ void UpdateCampaignPage(int index);
void NetGameChangeStatus(bool isMaster);
void NetGameMaster();
@@ -123,7 +127,8 @@
void closeEvent(QCloseEvent *event);
void CustomizePalettes();
void resizeEvent(QResizeEvent * event);
-
+ void keyReleaseEvent(QKeyEvent *event);
+
enum PageIDs {
ID_PAGE_SETUP_TEAM = 0,
ID_PAGE_SETUP = 1,
@@ -143,7 +148,8 @@
ID_PAGE_CONNECTING = 15,
ID_PAGE_SCHEME = 16,
ID_PAGE_ADMIN = 17,
- ID_PAGE_NETTYPE = 18
+ ID_PAGE_NETTYPE = 18,
+ ID_PAGE_CAMPAIGN = 19
};
HWGame * game;
HWNetServer* pnetserver;
@@ -155,11 +161,11 @@
QStack<quint8> PagesStack;
QTime eggTimer;
BGWidget * wBackground;
-
+
#ifdef __APPLE__
InstallController * panel;
#endif
-
+
void OnPageShown(quint8 id, quint8 lastid=0);
};
--- a/QTfrontend/main.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/main.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -47,7 +47,7 @@
return true;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QStringList arguments = app.arguments();
@@ -73,11 +73,13 @@
qWarning() << "WARNING: Cannot open DATA_PATH=" << f.absoluteFilePath();
}
*cDataDir = f.absoluteFilePath();
+ custom_data = true;
}
if(parsedArgs.contains("config-dir")) {
QFileInfo f(parsedArgs["config-dir"]);
*cConfigDir = f.absoluteFilePath();
+ custom_config = true;
}
app.setStyle(new QPlastiqueStyle);
@@ -180,6 +182,7 @@
"}"
"QTableView {"
"alternate-background-color: #2f213a;"
+ "gridline-color: transparent;"
"}"
"QTabBar::tab {"
@@ -294,6 +297,18 @@
"SquareLabel, ItemNum {"
"background-color: #000000;"
"}"
+ "QSlider::groove::horizontal {"
+ "height: 2px;"
+ "margin: 2px 0px;"
+ "background-color: #ffcc00;"
+ "}"
+ "QSlider::handle::horizontal {"
+ "border: 0px;"
+ "margin: -2px 0px;"
+ "border-radius: 3px;"
+ "background-color: #ffcc00;"
+ "width: 8px;"
+ "}"
)
);
@@ -307,62 +322,53 @@
if(cConfigDir->length() == 0)
{
#ifdef __APPLE__
- if (checkForDir(cfgdir->absolutePath() + "/Library/Application Support/Hedgewars"))
- {
- checkForDir(cfgdir->absolutePath() + "/Library/Application Support/Hedgewars/Demos");
- checkForDir(cfgdir->absolutePath() + "/Library/Application Support/Hedgewars/Saves");
- checkForDir(cfgdir->absolutePath() + "/Library/Application Support/Hedgewars/Screenshots");
- checkForDir(cfgdir->absolutePath() + "/Library/Application Support/Hedgewars/Teams");
- }
+ checkForDir(cfgdir->absolutePath() + "/Library/Application Support/Hedgewars");
cfgdir->cd("Library/Application Support/Hedgewars");
#elif defined _WIN32
char path[1024];
if(!SHGetFolderPathA(0, CSIDL_PERSONAL, NULL, 0, path))
{
cfgdir->cd(path);
- if (checkForDir(cfgdir->absolutePath() + "/Hedgewars"))
- {
- checkForDir(cfgdir->absolutePath() + "/Hedgewars/Demos");
- checkForDir(cfgdir->absolutePath() + "/Hedgewars/Saves");
- checkForDir(cfgdir->absolutePath() + "/Hedgewars/Screenshots");
- checkForDir(cfgdir->absolutePath() + "/Hedgewars/Teams");
- }
+ checkForDir(cfgdir->absolutePath() + "/Hedgewars");
cfgdir->cd("Hedgewars");
}
- else
+ else // couldn't retrieve documents folder? almost impossible, but in case fall back to classic path
{
- if (checkForDir(cfgdir->absolutePath() + "/.hedgewars"))
- {
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Demos");
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Saves");
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Screenshots");
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Teams");
- }
+ checkForDir(cfgdir->absolutePath() + "/.hedgewars");
cfgdir->cd(".hedgewars");
}
#else
- if (checkForDir(cfgdir->absolutePath() + "/.hedgewars"))
- {
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Demos");
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Saves");
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Screenshots");
- checkForDir(cfgdir->absolutePath() + "/.hedgewars/Teams");
- }
+ checkForDir(cfgdir->absolutePath() + "/.hedgewars");
cfgdir->cd(".hedgewars");
#endif
}
- else
+
+ if (checkForDir(cfgdir->absolutePath()))
{
- if (checkForDir(cfgdir->absolutePath()))
- {
- checkForDir(cfgdir->absolutePath() + "/Demos");
- checkForDir(cfgdir->absolutePath() + "/Saves");
- checkForDir(cfgdir->absolutePath() + "/Screenshots");
- checkForDir(cfgdir->absolutePath() + "/Teams");
- }
+ // alternative loading/lookup paths
+ // TODO: Uncomment paths as they're implemented
+ checkForDir(cfgdir->absolutePath() + "/Data");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Forts");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Graphics");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Graphics/Flags");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Graphics/Graves");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Graphics/Hats");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Maps");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Missions");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Missions/Campaign");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Missions/Training");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Sounds");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Sounds/voices");
+ //checkForDir(cfgdir->absolutePath() + "/Data/Themes");
+
+ // config/save paths
+ checkForDir(cfgdir->absolutePath() + "/Demos");
+ checkForDir(cfgdir->absolutePath() + "/Saves");
+ checkForDir(cfgdir->absolutePath() + "/Screenshots");
+ checkForDir(cfgdir->absolutePath() + "/Teams");
+ checkForDir(cfgdir->absolutePath() + "/Logs");
}
-
datadir->cd(bindir->absolutePath());
datadir->cd(*cDataDir);
if(!datadir->cd("hedgewars/Data")) {
@@ -406,12 +412,11 @@
// Win32 registry setup (used for xfire detection etc. - don't set it if we're running in "portable" mode with a custom config dir)
#ifdef _WIN32
- if(cConfigDir->length() == 0)
+ if(!custom_config)
{
- QSettings registry(QSettings::NativeFormat, QSettings::UserScope, "Hedgewars Project", "Hedgewars");
- QFileInfo f(argv[0]);
- registry.setValue("file", f.absoluteFilePath());
- registry.setValue("path", f.absolutePath());
+ QSettings registry_hklm("HKEY_LOCAL_MACHINE", QSettings::NativeFormat);
+ registry_hklm.setValue("Software/Hedgewars/Frontend", bindir->absolutePath().replace("/", "\\") + "\\hedgewars.exe");
+ registry_hklm.setValue("Software/Hedgewars/Path", bindir->absolutePath().replace("/", "\\"));
}
#endif
--- a/QTfrontend/mapContainer.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/mapContainer.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -56,16 +56,18 @@
imageButt->setFlat(true);
imageButt->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);//QSizePolicy::Minimum, QSizePolicy::Minimum);
mainLayout.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(setRandomSeed()));
+ //connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomTheme()));
+ connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomMap()));
chooseMap = new QComboBox(this);
chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- chooseMap->addItem(QComboBox::tr("generated map..."));
- chooseMap->addItem(QComboBox::tr("generated maze..."));
+ chooseMap->addItem(QIcon(":/res/mapRandom.png"), QComboBox::tr("generated map..."));
+ chooseMap->addItem(QIcon(":/res/mapMaze.png"), QComboBox::tr("generated maze..."));
chooseMap->insertSeparator(chooseMap->count()); // separator between generators and missions
int missionindex = chooseMap->count();
+ numMissions = 0;
for (int i = 0; i < mapList->size(); ++i) {
QString map = (*mapList)[i];
QFile mapCfgFile(
@@ -92,9 +94,12 @@
mapInfo.push_back(18);
mapInfo.push_back(mapLuaFile.exists());
if(mapLuaFile.exists())
- chooseMap->insertItem(missionindex++, QComboBox::tr("Mission") + ": " + map, mapInfo);
+ {
+ chooseMap->insertItem(missionindex++, QIcon(":/res/mapMission.png"), QComboBox::tr("Mission") + ": " + map, mapInfo);
+ numMissions++;
+ }
else
- chooseMap->addItem(map, mapInfo);
+ chooseMap->addItem(QIcon(":/res/mapCustom.png"), map, mapInfo);
mapCfgFile.close();
}
}
@@ -149,11 +154,12 @@
gbTLayout->setSpacing(0);
lwThemes = new QListWidget(this);
lwThemes->setMinimumHeight(30);
- lwThemes->setFixedWidth(120);
+ lwThemes->setFixedWidth(140);
for (int i = 0; i < Themes->size(); ++i) {
QListWidgetItem * lwi = new QListWidgetItem();
lwi->setText(Themes->at(i));
- lwi->setTextAlignment(Qt::AlignHCenter);
+ lwi->setIcon(QIcon(QString("%1/Themes/%2/icon.png").arg(datadir->absolutePath()).arg(Themes->at(i))));
+ //lwi->setTextAlignment(Qt::AlignHCenter);
lwThemes->addItem(lwi);
}
connect(lwThemes, SIGNAL(currentRowChanged(int)), this, SLOT(themeSelected(int)));
@@ -167,7 +173,7 @@
"border-color: transparent;"
"background-color: #0d0544;"
"color: #ffcc00;"
- "font: bold 14px;"
+ "font: bold 13px;"
"}"
)
);
@@ -389,6 +395,36 @@
if(items.size())
lwThemes->setCurrentItem(items.at(0));
}
+#include <QMessageBox>
+void HWMapContainer::setRandomMap()
+{
+ switch(chooseMap->currentIndex())
+ {
+ case MAPGEN_REGULAR:
+ case MAPGEN_MAZE:
+ setRandomSeed();
+ setRandomTheme();
+ break;
+ default:
+ if(chooseMap->currentIndex() < numMissions + 3)
+ setRandomMission();
+ else
+ setRandomStatic();
+ break;
+ }
+}
+
+void HWMapContainer::setRandomStatic()
+{
+ chooseMap->setCurrentIndex(4 + numMissions + rand() % (chooseMap->count() - 4 - numMissions));
+ m_seed = QUuid::createUuid().toString();
+}
+
+void HWMapContainer::setRandomMission()
+{
+ chooseMap->setCurrentIndex(3 + rand() % numMissions);
+ m_seed = QUuid::createUuid().toString();
+}
void HWMapContainer::setRandomSeed()
{
--- a/QTfrontend/mapContainer.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/mapContainer.h Wed Oct 27 14:02:20 2010 +0200
@@ -72,6 +72,9 @@
void mapChanged(int index);
void setRandomSeed();
void setRandomTheme();
+ void setRandomMap();
+ void setRandomStatic();
+ void setRandomMission();
void themeSelected(int currentRow);
void addInfoToPreview(QPixmap image);
void templateFilterChanged(int filter);
@@ -95,6 +98,7 @@
QLabel *maze_size_label;
QComboBox *maze_size_selection;
MapGenerator mapgen;
+ int numMissions;
int maze_size;
void loadMap(int index);
--- a/QTfrontend/newnetclient.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/newnetclient.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -305,7 +305,7 @@
if(tmp[0] == "MOTD_NEW") emit serverMessageNew(tmp[1]);
else if(tmp[0] == "MOTD_OLD") emit serverMessageOld(tmp[1]);
else if(tmp[0] == "LATEST_PROTO") emit latestProtocolVar(tmp[1].toInt());
-
+
tmp.removeFirst();
tmp.removeFirst();
}
@@ -472,13 +472,13 @@
int passLength = config->value("net/passwordlength", 0).toInt();
QString hash = config->value("net/passwordhash", "").toString();
QString password = QInputDialog::getText(0, tr("Password"), tr("Your nickname %1 is\nregistered on Hedgewars.org\nPlease provide your password below\nor pick another nickname in game config:").arg(mynick), QLineEdit::Password, passLength==0?NULL:QString(passLength,'\0'), &ok);
-
+
if (!ok) {
Disconnect();
emit Disconnected();
return;
}
-
+
if (!passLength || password!=QString(passLength, '\0')) {
hash = QCryptographicHash::hash(password.toLatin1(), QCryptographicHash::Md5).toHex();
config->setValue("net/passwordhash", hash);
@@ -750,5 +750,5 @@
void HWNewNet::askServerVars()
{
- RawSendNet(QString("GET_SERVER_VAR"));
+ RawSendNet(QString("GET_SERVER_VAR"));
}
--- a/QTfrontend/newnetclient.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/newnetclient.h Wed Oct 27 14:02:20 2010 +0200
@@ -48,7 +48,7 @@
QString getNick();
QString getRoom();
QString getHost();
-
+
private:
GameUIConfig* config;
GameCFGWidget* m_pGameCFGWidget;
--- a/QTfrontend/pages.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/pages.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -92,39 +92,69 @@
mainNote = new QLabel(this);
mainNote->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
mainNote->setWordWrap(true);
+ mainNote->setOpenExternalLinks(true);
- QStringList Tips;
- Tips << tr("Simply pick the same color as a friend to play together as a team. Each of you will still control his or her own hedgehogs but they'll win or lose together.", "Tips");
- Tips << tr("Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water.", "Tips");
- Tips << tr("If you're unsure what to do and don't want to waste ammo, skip one round. But don't let too much time pass as there will be Sudden Death!", "Tips");
- Tips << tr("Want to save ropse? Release the rope in mid air and then shoot again. As long as you don't touch the ground you'll reuse your rope without wasting ammo!", "Tips");
- Tips << tr("If you'd like to keep others from using your preferred nickname on the official server, register an account at http://www.hedgewars.org/.", "Tips");
- Tips << tr("You're bored of default gameplay? Try one of the missions - they'll offer different gameplay depending on the one you picked.", "Tips");
- Tips << tr("By default the game will always record the last game played as a demo. Select 'Local Game' and pick the 'Demos' button on the lower right corner to play or manage them.", "Tips");
- Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If you've got problems, ask on our forums but please don't expect 24/7 support!", "Tips");
- Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If you like it, help us with a small donation or contribute your own work!", "Tips");
- Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. Share it with your family and friends as you like!", "Tips");
- Tips << tr("From time to time there will be official tournaments. Upcoming events will be announced at http://www.hedgewars.org/ some days in advance.", "Tips");
- Tips << tr("Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us!", "Tips");
- Tips << tr("Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and Linux.", "Tips");
- Tips << tr("Always remember you're able to set up your own games in local and network/online play. You're not restricted to the 'Simple Game' option.", "Tips");
- Tips << tr("Connect one or more gamepads before launching the game to be able to assign their controls to your teams.", "Tips");
- Tips << tr("Create an account on http://www.hedgewars.org/ to keep others from using your most favourite nickname while playing on the official server.", "Tips");
- Tips << tr("While playing you should give yourself a short break at least once an hour.", "Tips");
- Tips << tr("If your graphics card isn't able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance.", "Tips");
- Tips << tr("We're open to suggestions and constructive feedback. If you don't like something or got a great idea, let us know!", "Tips");
- Tips << tr("Especially while playing online be polite and always remember there might be some minors playing with or against you as well!", "Tips");
- Tips << tr("Special game modes such as 'Vampirism' or 'Karma' allow you to develop completely new tactics. Try them in a custom game!", "Tips");
- Tips << tr("The Windows version of Hedgewars supports Xfire. Make sure to add Hedgwars to its game list so your friends can see you playing.", "Tips");
- Tips << tr("You should never install Hedgewars on computers you don't own (school, university, work, etc.). Please ask the responsible person instead!", "Tips");
- Tips << tr("Hedgewars can be perfect for short games during breaks. Just ensure you don't add too many hedgehogs or use an huge map. Reducing time and health might help as well.", "Tips");
- Tips << tr("No hedgehogs were harmed in making this game.", "Tips");
-
-
- if(isDevBuild)
+ if(!isDevBuild)
+ {
+ QStringList Tips;
+ Tips << tr("Simply pick the same color as a friend to play together as a team. Each of you will still control his or her own hedgehogs but they'll win or lose together.", "Tips");
+ Tips << tr("Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water.", "Tips");
+ Tips << tr("If you're unsure what to do and don't want to waste ammo, skip one round. But don't let too much time pass as there will be Sudden Death!", "Tips");
+ Tips << tr("Want to save ropse? Release the rope in mid air and then shoot again. As long as you don't touch the ground you'll reuse your rope without wasting ammo!", "Tips");
+ Tips << tr("If you'd like to keep others from using your preferred nickname on the official server, register an account at http://www.hedgewars.org/.", "Tips");
+ Tips << tr("You're bored of default gameplay? Try one of the missions - they'll offer different gameplay depending on the one you picked.", "Tips");
+ Tips << tr("By default the game will always record the last game played as a demo. Select 'Local Game' and pick the 'Demos' button on the lower right corner to play or manage them.", "Tips");
+ Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If you've got problems, ask on our forums but please don't expect 24/7 support!", "Tips");
+ Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If you like it, help us with a small donation or contribute your own work!", "Tips");
+ Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. Share it with your family and friends as you like!", "Tips");
+ Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If someone sold you the game, you should try get a refund!", "Tips");
+ Tips << tr("From time to time there will be official tournaments. Upcoming events will be announced at http://www.hedgewars.org/ some days in advance.", "Tips");
+ Tips << tr("Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us!", "Tips");
+ Tips << tr("Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and Linux.", "Tips");
+ Tips << tr("Always remember you're able to set up your own games in local and network/online play. You're not restricted to the 'Simple Game' option.", "Tips");
+ Tips << tr("Connect one or more gamepads before starting the game to be able to assign their controls to your teams.", "Tips");
+ Tips << tr("Create an account on %1 to keep others from using your most favourite nickname while playing on the official server.", "Tips").arg("<a href=\"http://www.hedgewars.org/\">http://www.hedgewars.org/</a>");
+ Tips << tr("While playing you should give yourself a short break at least once an hour.", "Tips");
+ Tips << tr("If your graphics card isn't able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance.", "Tips");
+ Tips << tr("If your graphics card isn't able to provide hardware accelerated OpenGL, try to update the associated drivers.", "Tips");
+ Tips << tr("We're open to suggestions and constructive feedback. If you don't like something or got a great idea, let us know!", "Tips");
+ Tips << tr("Especially while playing online be polite and always remember there might be some minors playing with or against you as well!", "Tips");
+ Tips << tr("Special game modes such as 'Vampirism' or 'Karma' allow you to develop completely new tactics. Try them in a custom game!", "Tips");
+ Tips << tr("The Windows version of Hedgewars supports Xfire. Make sure to add Hedgwars to its game list so your friends can see you playing.", "Tips");
+ Tips << tr("You should never install Hedgewars on computers you don't own (school, university, work, etc.). Please ask the responsible person instead!", "Tips");
+ Tips << tr("Hedgewars can be perfect for short games during breaks. Just ensure you don't add too many hedgehogs or use an huge map. Reducing time and health might help as well.", "Tips");
+ Tips << tr("No hedgehogs were harmed in making this game.", "Tips");
+ Tips << tr("There are three different jumps available. Tap [high jump] twice to do a very high/backwards jump.", "Tips");
+ Tips << tr("Afraid of falling off a cliff? Hold down [precise] to turn [left] or [right] without actually moving.", "Tips");
+ Tips << tr("Some weapons require special strategies or just lots of training, so don't give up on a particular tool if you miss an enemy once.", "Tips");
+ Tips << tr("Most weapons won't work once they touch the water. The Homing Bee as well as the Cake are exceptions to this.", "Tips");
+ Tips << tr("The Old Limbuger only causes a small explosion. However the wind affected smelly cloud can poison lots of hogs at once.", "Tips");
+ Tips << tr("The Piano Strike is the most damaging air strike. You'll lose the hedgehog performing it, so there's a huge downside as well.", "Tips");
+ Tips << tr("The Homing Bee can be tricky to use. It's turn radius depends on it's velocity, so try to not use full power.", "Tips");
+ Tips << tr("Sticky Mines are a perfect tool to create small chain reactions knocking enemy hedgehogs into dire situations ... or water.", "Tips");
+ Tips << tr("The Hammer is most effective when used on bridges or girders. Hit hogs will just break through the ground.", "Tips");
+ Tips << tr("If you're stuck behind an enemy hedgehog, use the Hammer to free yourself without getting damaged by an explosion.", "Tips");
+ Tips << tr("The Cake's maximum walking distance depends on the ground it has to pass. Use [attack] to detonate it early.", "Tips");
+ Tips << tr("The Flame Thrower is a weapon but it can be used for tunnel digging as well.", "Tips");
+ Tips << tr("Use the Incinerating Grenade to temporary keep hedgehogs from passing terrain such as tunnels or platforms.", "Tips");
+ Tips << tr("Want to know who's behind the game? Click on the Hedgewars logo in the main menu to see the credits.", "Tips");
+ Tips << tr("Like Hedgewars? Become a fan on %1 or join our group at %2. You could follow us on %3 as well!", "Tips").arg("<a href=\"http://www.facebook.com/Hedgewars\">Facebook</a>").arg("<a href=\"http://steamcommunity.com/groups/hedgewars\">Steam Community</a>").arg("<a href=\"http://twitter.com/hedgewars\">Twitter</a>");
+ Tips << tr("Feel free to draw your own graves, hats, flags or even maps and themes! But note that you'll have to share them somewhere to use them online.", "Tips");
+ Tips << tr("Really want to wear a specific hat? Donate to us and receive an exclusive hat of your choice!", "Tips");
+ // The following tip will require links to app store entries first.
+ //Tips << tr("Want to play Hedgewars any time? Grab the Mobile version for %1 and %2.", "Tips").arg("").arg("");
+ Tips << tr("Keep your video card drivers up to date to avoid issues playing the game.", "Tips");
+ //Tips << tr("", "Tips");
+#ifdef _WIN32
+ Tips << tr("You can find your Hedgewars configuration files under \"My Documents\\Hedgewars\". Create backups or take the files with you, but don't edit them by hand.", "Tips");
+ Tips << tr("You're able to associate Hedgewars related files (savegames and demo recordings) with the game to launch them right from your favorite file or internet browser.", "Tips");
+#else
+ Tips << tr("You can find your Hedgewars configuration files under \"Hedgewars\" in your home directory. Create backups or take the files with you, but don't edit them by hand.", "Tips");
+#endif
+ mainNote->setText(QLabel::tr("Tip: ") + Tips[QTime(0, 0, 0).secsTo(QTime::currentTime()) % Tips.length()]);
+ }
+ else
mainNote->setText(QLabel::tr("This development build is 'work in progress' and may not be compatible with other versions of the game. Some features might be broken or incomplete. Use at your own risk!"));
- else
- mainNote->setText(QLabel::tr("Tip: ") + Tips[QTime(0, 0, 0).secsTo(QTime::currentTime()) % Tips.length()]);
pageLayout->addWidget(mainNote, 4, 1, 1, 2);
@@ -301,12 +331,33 @@
tmpdir.cd(datadir->absolutePath());
tmpdir.cd("Graphics/Flags");
list = tmpdir.entryList(QStringList("*.png"));
+
+ // add the default flag
+ CBFlag->addItem(QIcon(QPixmap(datadir->absolutePath() + "/Graphics/Flags/hedgewars.png").copy(0, 0, 22, 15)), "Hedgewars", "hedgewars");
+
+ CBFlag->insertSeparator(CBFlag->count());
+ // add all country flags
for (QStringList::Iterator it = list.begin(); it != list.end(); ++it )
{
QPixmap pix(datadir->absolutePath() + "/Graphics/Flags/" + *it);
QIcon icon(pix.copy(0, 0, 22, 15));
- if(it->compare("cpu.png")) // skip cpu flag
- CBFlag->addItem(icon, (*it).replace(QRegExp("^(.*)\\.png"), "\\1"));
+ if(it->compare("cpu.png") && it->compare("hedgewars.png") && (it->indexOf("cm_") == -1)) // skip cpu and hedgewars flags as well as all community flags
+ {
+ QString flag = (*it).replace(QRegExp("^(.*)\\.png"), "\\1");
+ CBFlag->addItem(icon, QString(flag).replace("_", " "), flag);
+ }
+ }
+ CBFlag->insertSeparator(CBFlag->count());
+ // add all community flags
+ for (QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ QPixmap pix(datadir->absolutePath() + "/Graphics/Flags/" + *it);
+ QIcon icon(pix.copy(0, 0, 22, 15));
+ if(it->indexOf("cm_") > -1) // skip non community flags this time
+ {
+ QString flag = (*it).replace(QRegExp("^(.*)\\.png"), "\\1");
+ CBFlag->addItem(icon, QString(flag).replace("cm_", QComboBox::tr("Community") + ": "), flag);
+ }
}
vbox1->addStretch();
@@ -560,7 +611,12 @@
CBAutoUpdate->setText(QCheckBox::tr("Check for updates at startup"));
MiscLayout->addWidget(CBAutoUpdate, 4, 0, 1, 2);
#endif
-
+#ifdef _WIN32
+ BtnAssociateFiles = new QPushButton(groupMisc);
+ BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions"));
+ BtnAssociateFiles->setEnabled(!custom_data && !custom_config);
+ MiscLayout->addWidget(BtnAssociateFiles, 4, 0, 1, 2);
+#endif
gbTBLayout->addWidget(groupMisc, 2, 0);
}
@@ -613,6 +669,7 @@
QLabel * quality = new QLabel(AGGroupBox);
quality->setText(QLabel::tr("Quality"));
+ quality->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
GBAqualayout->addWidget(quality);
SLQuality = new QSlider(Qt::Horizontal, AGGroupBox);
@@ -622,7 +679,6 @@
SLQuality->setFixedWidth(150);
GBAqualayout->addWidget(SLQuality);
GBAlayout->addLayout(GBAqualayout);
-
QLabel * stereo = new QLabel(AGGroupBox);
stereo->setText(QLabel::tr("Stereo rendering"));
GBAstereolayout->addWidget(stereo);
@@ -962,7 +1018,10 @@
topLine->addStretch();
- BtnTrainPage = addButton(":/res/Trainings.png", middleLine, 0, true);
+ BtnCampaignPage = addButton(":/res/SimpleGame.png", middleLine, 0, true);
+ BtnCampaignPage->setToolTip(tr("Campaign Mode (...). IN DEVELOPMENT"));
+
+ BtnTrainPage = addButton(":/res/Trainings.png", middleLine, 1, true);
BtnTrainPage->setToolTip(tr("Training Mode (Practice your skills in a range of training missions). IN DEVELOPMENT"));
BtnBack = addButton(":/res/Exit.png", bottomLine, 0, true);
@@ -993,6 +1052,8 @@
tmpdir.cd("Missions/Training");
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));
pageLayout->addWidget(CBSelect, 1, 1);
@@ -1004,6 +1065,29 @@
BtnBack = addButton(":/res/Exit.png", pageLayout, 3, 0, true);
}
+PageCampaign::PageCampaign(QWidget* parent) : AbstractPage(parent)
+{
+ QGridLayout * pageLayout = new QGridLayout(this);
+ pageLayout->setColumnStretch(0, 1);
+ pageLayout->setColumnStretch(1, 2);
+ pageLayout->setColumnStretch(2, 1);
+ pageLayout->setRowStretch(0, 1);
+ pageLayout->setRowStretch(3, 1);
+
+ CBSelect = new QComboBox(this);
+ CBTeam = new QComboBox(this);
+
+ pageLayout->addWidget(CBTeam, 1, 1);
+ pageLayout->addWidget(CBSelect, 2, 1);
+
+ BtnStartCampaign = new QPushButton(this);
+ BtnStartCampaign->setFont(*font14);
+ BtnStartCampaign->setText(QPushButton::tr("Go!"));
+ pageLayout->addWidget(BtnStartCampaign, 2, 2);
+
+ BtnBack = addButton(":/res/Exit.png", pageLayout, 4, 0, true);
+}
+
PageSelectWeapon::PageSelectWeapon(QWidget* parent) :
AbstractPage(parent)
{
@@ -1050,24 +1134,85 @@
roomsList->verticalHeader()->setVisible(false);
roomsList->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
roomsList->setAlternatingRowColors(true);
+ roomsList->setShowGrid(false);
+ roomsList->setSelectionMode(QAbstractItemView::SingleSelection);
pageLayout->addWidget(roomsList, 1, 0, 3, 1);
pageLayout->setRowStretch(2, 100);
+
+ QHBoxLayout * filterLayout = new QHBoxLayout();
+
+ QLabel * stateLabel = new QLabel(this);
+ stateLabel->setText(tr("State:"));
+ CBState = new QComboBox(this);
+ CBState->addItem(QComboBox::tr("Any"));
+ CBState->addItem(QComboBox::tr("In lobby"));
+ CBState->addItem(QComboBox::tr("In progress"));
+ filterLayout->addWidget(stateLabel);
+ filterLayout->addWidget(CBState);
+ filterLayout->addSpacing(30);
+
+ QLabel * ruleLabel = new QLabel(this);
+ ruleLabel->setText(tr("Rules:"));
+ CBRules = new QComboBox(this);
+ CBRules->addItem(QComboBox::tr("Any"));
+ CBRules->addItem(QComboBox::tr("Default"));
+ CBRules->addItem(QComboBox::tr("Pro mode"));
+ CBRules->addItem(QComboBox::tr("Shoppa"));
+ CBRules->addItem(QComboBox::tr("Basketball"));
+ CBRules->addItem(QComboBox::tr("Minefield"));
+ CBRules->addItem(QComboBox::tr("Barrel mayhem"));
+ CBRules->addItem(QComboBox::tr("Tunnel hogs"));
+ filterLayout->addWidget(ruleLabel);
+ filterLayout->addWidget(CBRules);
+ filterLayout->addSpacing(30);
+
+ QLabel * weaponLabel = new QLabel(this);
+ weaponLabel->setText(tr("Weapons:"));
+ CBWeapons = new QComboBox(this);
+ CBWeapons->addItem(QComboBox::tr("Any"));
+ CBWeapons->addItem(QComboBox::tr("Basketball"));
+ CBWeapons->addItem(QComboBox::tr("Crazy"));
+ CBWeapons->addItem(QComboBox::tr("Default"));
+ CBWeapons->addItem(QComboBox::tr("Minefield"));
+ CBWeapons->addItem(QComboBox::tr("Pro mode"));
+ CBWeapons->addItem(QComboBox::tr("Shoppa"));
+ filterLayout->addWidget(weaponLabel);
+ filterLayout->addWidget(CBWeapons);
+ filterLayout->addSpacing(30);
+
+ QLabel * searchLabel = new QLabel(this);
+ searchLabel->setText(tr("Search:"));
+ searchText = new QLineEdit(this);
+ searchText->setMaxLength(60);
+ filterLayout->addWidget(searchLabel);
+ filterLayout->addWidget(searchText);
+
+ pageLayout->addLayout(filterLayout, 4, 0);
chatWidget = new HWChatWidget(this, gameSettings, sdli, false);
- pageLayout->addWidget(chatWidget, 4, 0, 1, 2);
- pageLayout->setRowStretch(4, 350);
+ pageLayout->addWidget(chatWidget, 5, 0, 1, 2);
+ pageLayout->setRowStretch(5, 350);
BtnCreate = addButton(tr("Create"), pageLayout, 0, 1);
BtnJoin = addButton(tr("Join"), pageLayout, 1, 1);
BtnRefresh = addButton(tr("Refresh"), pageLayout, 3, 1);
+ BtnClear = addButton(tr("Clear"), pageLayout, 4, 1);
- BtnBack = addButton(":/res/Exit.png", pageLayout, 5, 0, true);
- BtnAdmin = addButton(tr("Admin features"), pageLayout, 5, 1);
+ BtnBack = addButton(":/res/Exit.png", pageLayout, 6, 0, true);
+ BtnAdmin = addButton(tr("Admin features"), pageLayout, 6, 1);
connect(BtnCreate, SIGNAL(clicked()), this, SLOT(onCreateClick()));
connect(BtnJoin, SIGNAL(clicked()), this, SLOT(onJoinClick()));
connect(BtnRefresh, SIGNAL(clicked()), this, SLOT(onRefreshClick()));
+ connect(BtnClear, SIGNAL(clicked()), this, SLOT(onClearClick()));
connect(roomsList, SIGNAL(doubleClicked (const QModelIndex &)), this, SLOT(onJoinClick()));
+ connect(CBState, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
+ connect(CBRules, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
+ connect(CBWeapons, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
+ connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onRefreshClick()));
+ connect(this, SIGNAL(askJoinConfirmation (const QString &)), this, SLOT(onJoinConfirmation(const QString &)), Qt::QueuedConnection);
+
+ gameInLobby = false;
}
void PageRoomsList::setAdmin(bool flag)
@@ -1077,6 +1222,18 @@
void PageRoomsList::setRoomsList(const QStringList & list)
{
+ QBrush red(QColor(255, 0, 0));
+ QBrush orange(QColor(127, 127, 0));
+ QBrush yellow(QColor(255, 255, 0));
+ QBrush green(QColor(0, 255, 0));
+
+ listFromServer = list;
+
+ QString selection = "";
+
+ if(QTableWidgetItem *item = roomsList->item(roomsList->currentRow(), 0))
+ selection = item->text();
+
roomsList->clear();
roomsList->setColumnCount(7);
roomsList->setHorizontalHeaderLabels(
@@ -1102,12 +1259,46 @@
// set resize modes
// roomsList->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
+ bool gameCanBeJoined = true;
+
if (list.size() % 8)
return;
roomsList->setRowCount(list.size() / 8);
for(int i = 0, r = 0; i < list.size(); i += 8, r++)
{
+ // if we are joining a game
+ // TODO: Should NOT be done here
+ if (gameInLobby) {
+ if (gameInLobbyName == list[i + 1]) {
+ gameCanBeJoined = list[i].compare("True");
+ }
+ }
+
+ // check filter settings
+ #define NO_FILTER_MATCH roomsList->setRowCount(roomsList->rowCount() - 1); --r; continue
+
+ if (list[i].compare("True") && CBState->currentIndex() == 2) { NO_FILTER_MATCH; }
+ if (list[i].compare("False") && CBState->currentIndex() == 1) { NO_FILTER_MATCH; }
+ if (CBRules->currentIndex() != 0 && list[i + 6].compare(CBRules->currentText())) { NO_FILTER_MATCH; }
+ if (CBWeapons->currentIndex() != 0 && list[i + 7].compare(CBWeapons->currentText())) { NO_FILTER_MATCH; }
+ bool found = list[i + 1].contains(searchText->text(), Qt::CaseInsensitive);
+ if (!found) {
+ for (int a = 4; a <= 7; ++a) {
+ QString compString = list[i + a];
+ if (a == 5 && compString == "+rnd+") {
+ compString = "Random Map";
+ } else if (a == 5 && compString == "+maze+") {
+ compString = "Random Maze";
+ }
+ if (compString.contains(searchText->text(), Qt::CaseInsensitive)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!searchText->text().isEmpty() && !found) { NO_FILTER_MATCH; }
+
QTableWidgetItem * item;
item = new QTableWidgetItem(list[i + 1]); // room name
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
@@ -1136,6 +1327,9 @@
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
item->setTextAlignment(Qt::AlignCenter);
item->setToolTip(tr("There are %1 teams participating in this room.", "", list[i + 3].toInt()).arg(list[i + 3]));
+ //Should we highlight "full" games? Might get misinterpreted
+ //if(list[i + 3].toInt() >= cMaxTeams)
+ // item->setForeground(red);
roomsList->setItem(r, 2, item);
item = new QTableWidgetItem(list[i + 4].left(15)); // name of host
@@ -1144,9 +1338,15 @@
roomsList->setItem(r, 3, item);
if(list[i + 5] == "+rnd+")
+ {
item = new QTableWidgetItem(tr("Random Map")); // selected map (is randomized)
+ item->setIcon(QIcon(":/res/mapRandom.png"));
+ }
else if (list[i+5] == "+maze+")
+ {
item = new QTableWidgetItem(tr("Random Maze"));
+ item->setIcon(QIcon(":/res/mapMaze.png"));
+ }
else
{
item = new QTableWidgetItem(list[i + 5]); // selected map
@@ -1154,7 +1354,15 @@
// check to see if we've got this map
// not perfect but a start
if(!mapList->contains(list[i + 5]))
- item->setForeground(QBrush(QColor(255, 0, 0)));
+ {
+ item->setForeground(red);
+ item->setIcon(QIcon(":/res/mapMissing.png"));
+ }
+ else
+ {
+ // todo: mission icon?
+ item->setIcon(QIcon(":/res/mapCustom.png"));
+ }
}
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
@@ -1171,14 +1379,27 @@
item->setToolTip(tr("The Weapon Scheme defines available weapons and their ammunition count."));
roomsList->setItem(r, 6, item);
+ if(!list[i + 1].compare(selection) && !selection.isEmpty())
+ roomsList->selectionModel()->setCurrentIndex(roomsList->model()->index(r, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}
- roomsList->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
- roomsList->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
- roomsList->horizontalHeader()->setResizeMode(2, QHeaderView::ResizeToContents);
- roomsList->horizontalHeader()->setResizeMode(3, QHeaderView::ResizeToContents);
- roomsList->horizontalHeader()->setResizeMode(4, QHeaderView::ResizeToContents);
- roomsList->horizontalHeader()->setResizeMode(5, QHeaderView::ResizeToContents);
- roomsList->horizontalHeader()->setResizeMode(6, QHeaderView::ResizeToContents);
+
+ roomsList->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
+ roomsList->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
+ roomsList->horizontalHeader()->setResizeMode(2, QHeaderView::ResizeToContents);
+ roomsList->horizontalHeader()->setResizeMode(3, QHeaderView::ResizeToContents);
+ roomsList->horizontalHeader()->setResizeMode(4, QHeaderView::ResizeToContents);
+ roomsList->horizontalHeader()->setResizeMode(5, QHeaderView::ResizeToContents);
+ roomsList->horizontalHeader()->setResizeMode(6, QHeaderView::ResizeToContents);
+
+ // TODO: Should NOT be done here
+ if (gameInLobby) {
+ gameInLobby = false;
+ if (gameCanBeJoined) {
+ emit askForJoinRoom(gameInLobbyName);
+ } else {
+ emit askJoinConfirmation(gameInLobbyName);
+ }
+ }
// roomsList->resizeColumnsToContents();
}
@@ -1203,9 +1424,22 @@
tr("Error"),
tr("Please select room from the list"),
tr("OK"));
- return ;
+ return;
}
- emit askForJoinRoom(curritem->data(Qt::DisplayRole).toString());
+
+ for (int i = 0; i < listFromServer.size(); i += 8) {
+ if (listFromServer[i + 1] == curritem->data(Qt::DisplayRole).toString()) {
+ gameInLobby = listFromServer[i].compare("True");
+ break;
+ }
+ }
+
+ if (gameInLobby) {
+ gameInLobbyName = curritem->data(Qt::DisplayRole).toString();
+ emit askForRoomList();
+ } else {
+ emit askForJoinRoom(curritem->data(Qt::DisplayRole).toString());
+ }
}
void PageRoomsList::onRefreshClick()
@@ -1213,6 +1447,24 @@
emit askForRoomList();
}
+void PageRoomsList::onClearClick()
+{
+ CBState->setCurrentIndex(0);
+ CBRules->setCurrentIndex(0);
+ CBWeapons->setCurrentIndex(0);
+ searchText->clear();
+}
+
+void PageRoomsList::onJoinConfirmation(const QString & room)
+{
+ if (QMessageBox::warning(this,
+ tr("Warning"),
+ tr("The game you are trying to join has started.\nDo you still want to join the room?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
+ {
+ emit askForJoinRoom(room);
+ }
+}
PageConnecting::PageConnecting(QWidget* parent) :
AbstractPage(parent)
@@ -1277,55 +1529,71 @@
TBW_lowGravity = new ToggleButtonWidget(gbGameModes, ":/res/btnLowGravity.png");
TBW_lowGravity->setToolTip("<b>" + ToggleButtonWidget::tr("Low Gravity") + "</b>:<br />" + tr("Lower gravity"));
- glGMLayout->addWidget(TBW_lowGravity,1,0,1,1);
+ glGMLayout->addWidget(TBW_lowGravity,0,4,1,1);
TBW_laserSight = new ToggleButtonWidget(gbGameModes, ":/res/btnLaserSight.png");
TBW_laserSight->setToolTip("<b>" + ToggleButtonWidget::tr("Laser Sight") + "</b>:<br />" + tr("Assisted aiming with laser sight"));
- glGMLayout->addWidget(TBW_laserSight,1,1,1,1);
+ glGMLayout->addWidget(TBW_laserSight,1,0,1,1);
TBW_invulnerable = new ToggleButtonWidget(gbGameModes, ":/res/btnInvulnerable.png");
TBW_invulnerable->setToolTip("<b>" + ToggleButtonWidget::tr("Invulnerable") + "</b>:<br />" + tr("All hogs have a personal forcefield"));
- glGMLayout->addWidget(TBW_invulnerable,1,2,1,1);
+ glGMLayout->addWidget(TBW_invulnerable,1,1,1,1);
TBW_mines = new ToggleButtonWidget(gbGameModes, ":/res/btnMines.png");
TBW_mines->setToolTip("<b>" + ToggleButtonWidget::tr("Add Mines") + "</b>:<br />" + tr("Enable random mines"));
- glGMLayout->addWidget(TBW_mines,1,3,1,1);
+ glGMLayout->addWidget(TBW_mines,1,2,1,1);
TBW_vampiric = new ToggleButtonWidget(gbGameModes, ":/res/btnVampiric.png");
TBW_vampiric->setToolTip("<b>" + ToggleButtonWidget::tr("Vampirism") + "</b>:<br />" + tr("Gain 80% of the damage you do back in health"));
- glGMLayout->addWidget(TBW_vampiric,2,0,1,1);
+ glGMLayout->addWidget(TBW_vampiric,1,3,1,1);
TBW_karma = new ToggleButtonWidget(gbGameModes, ":/res/btnKarma.png");
TBW_karma->setToolTip("<b>" + ToggleButtonWidget::tr("Karma") + "</b>:<br />" + tr("Share your opponents pain, share their damage"));
- glGMLayout->addWidget(TBW_karma,2,1,1,1);
+ glGMLayout->addWidget(TBW_karma,1,4,1,1);
TBW_artillery = new ToggleButtonWidget(gbGameModes, ":/res/btnArtillery.png");
TBW_artillery->setToolTip("<b>" + ToggleButtonWidget::tr("Artillery") + "</b>:<br />" + tr("Your hogs are unable to move, put your artillery skills to the test"));
- glGMLayout->addWidget(TBW_artillery,2,2,1,1);
+ glGMLayout->addWidget(TBW_artillery,2,0,1,1);
TBW_randomorder = new ToggleButtonWidget(gbGameModes, ":/res/btnRandomOrder.png");
TBW_randomorder->setToolTip("<b>" + ToggleButtonWidget::tr("Random Order") + "</b>:<br />" + tr("Order of play is random instead of in room order."));
- glGMLayout->addWidget(TBW_randomorder,2,3,1,1);
+ glGMLayout->addWidget(TBW_randomorder,2,1,1,1);
TBW_king = new ToggleButtonWidget(gbGameModes, ":/res/btnKing.png");
TBW_king->setToolTip("<b>" + ToggleButtonWidget::tr("King") + "</b>:<br />" + tr("Play with a King. If he dies, your side dies."));
- glGMLayout->addWidget(TBW_king,3,0,1,1);
+ glGMLayout->addWidget(TBW_king,2,2,1,1);
TBW_placehog = new ToggleButtonWidget(gbGameModes, ":/res/btnPlaceHog.png");
TBW_placehog->setToolTip("<b>" + ToggleButtonWidget::tr("Place Hedgehogs") + "</b>:<br />" + tr("Take turns placing your hedgehogs before the start of play."));
- glGMLayout->addWidget(TBW_placehog,3,1,1,1);
+ glGMLayout->addWidget(TBW_placehog,2,3,1,1);
TBW_sharedammo = new ToggleButtonWidget(gbGameModes, ":/res/btnSharedAmmo.png");
TBW_sharedammo->setToolTip("<b>" + ToggleButtonWidget::tr("Clan Shares Ammo") + "</b>:<br />" + tr("Ammo is shared between all teams that share a colour."));
- glGMLayout->addWidget(TBW_sharedammo,3,2,1,1);
+ glGMLayout->addWidget(TBW_sharedammo,2,4,1,1);
TBW_disablegirders = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableGirders.png");
TBW_disablegirders->setToolTip("<b>" + ToggleButtonWidget::tr("Disable Girders") + "</b>:<br />" + tr("Disable girders when generating random maps."));
- glGMLayout->addWidget(TBW_disablegirders,3,3,1,1);
+ glGMLayout->addWidget(TBW_disablegirders,3,0,1,1);
TBW_disablelandobjects = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableLandObjects.png");
TBW_disablelandobjects->setToolTip("<b>" + ToggleButtonWidget::tr("Disable Land Objects") + "</b>:<br />" + tr("Disable land objects when generating random maps."));
- glGMLayout->addWidget(TBW_disablelandobjects,4,0,1,1);
+ glGMLayout->addWidget(TBW_disablelandobjects,3,1,1,1);
+
+ TBW_aisurvival = new ToggleButtonWidget(gbGameModes, ":/res/btnAISurvival.png");
+ TBW_aisurvival->setToolTip("<b>" + ToggleButtonWidget::tr("AI Survival Mode") + "</b>:<br />" + tr("AI respawns on death."));
+ glGMLayout->addWidget(TBW_aisurvival,3,2,1,1);
+
+ TBW_infattack = new ToggleButtonWidget(gbGameModes, ":/res/btnInfAttack.png");
+ TBW_infattack->setToolTip("<b>" + ToggleButtonWidget::tr("Unlimited Attacks") + "</b>:<br />" + tr("Attacking does not end your turn."));
+ glGMLayout->addWidget(TBW_infattack,3,3,1,1);
+
+ TBW_resetweps = new ToggleButtonWidget(gbGameModes, ":/res/btnResetWeps.png");
+ TBW_resetweps->setToolTip("<b>" + ToggleButtonWidget::tr("Reset Weapons") + "</b>:<br />" + tr("Weapons are reset to starting values each turn."));
+ glGMLayout->addWidget(TBW_resetweps,3,4,1,1);
+
+ TBW_perhogammo = new ToggleButtonWidget(gbGameModes, ":/res/btnPerHogAmmo.png");
+ TBW_perhogammo->setToolTip("<b>" + ToggleButtonWidget::tr("Per Hedgehog Ammo") + "</b>:<br />" + tr("Each hedgehog has its own ammo. It does not share with the team."));
+ glGMLayout->addWidget(TBW_perhogammo,4,0,1,1);
// Right
QLabel * l;
@@ -1355,7 +1623,7 @@
glBSLayout->addWidget(l,1,1,1,1);
SB_TurnTime = new QSpinBox(gbBasicSettings);
- SB_TurnTime->setRange(1, 99);
+ SB_TurnTime->setRange(1, 9999);
SB_TurnTime->setValue(45);
SB_TurnTime->setSingleStep(15);
glBSLayout->addWidget(SB_TurnTime,1,2,1,1);
@@ -1510,15 +1778,19 @@
mapper->addMapping(TBW_sharedammo, 15);
mapper->addMapping(TBW_disablegirders, 16);
mapper->addMapping(TBW_disablelandobjects, 17);
- mapper->addMapping(SB_DamageModifier, 18);
- mapper->addMapping(SB_TurnTime, 19);
- mapper->addMapping(SB_InitHealth, 20);
- mapper->addMapping(SB_SuddenDeath, 21);
- mapper->addMapping(SB_CaseProb, 22);
- mapper->addMapping(SB_MinesTime, 23);
- mapper->addMapping(SB_Mines, 24);
- mapper->addMapping(SB_MineDuds, 25);
- mapper->addMapping(SB_Explosives, 26);
+ mapper->addMapping(TBW_aisurvival, 18);
+ mapper->addMapping(TBW_infattack, 19);
+ mapper->addMapping(TBW_resetweps, 20);
+ mapper->addMapping(TBW_perhogammo, 21);
+ mapper->addMapping(SB_DamageModifier, 22);
+ mapper->addMapping(SB_TurnTime, 23);
+ mapper->addMapping(SB_InitHealth, 24);
+ mapper->addMapping(SB_SuddenDeath, 25);
+ mapper->addMapping(SB_CaseProb, 26);
+ mapper->addMapping(SB_MinesTime, 27);
+ mapper->addMapping(SB_Mines, 28);
+ mapper->addMapping(SB_MineDuds, 29);
+ mapper->addMapping(SB_Explosives, 30);
mapper->toFirst();
}
--- a/QTfrontend/pages.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/pages.h Wed Oct 27 14:02:20 2010 +0200
@@ -70,6 +70,7 @@
protected:
AbstractPage(QWidget* parent = 0) {
font14 = new QFont("MS Shell Dlg", 14);
+ setFocusPolicy(Qt::StrongFocus);
}
virtual ~AbstractPage() {};
@@ -216,6 +217,7 @@
QPushButton *BtnNewTeam;
QPushButton *BtnEditTeam;
QPushButton *BtnDeleteTeam;
+ QPushButton *BtnAssociateFiles;
QLabel *LblNoEditTeam;
QComboBox *CBTeamName;
IconedGroupBox *AGGroupBox;
@@ -340,6 +342,7 @@
QPushButton *BtnSimpleGamePage;
QPushButton *BtnTrainPage;
+ QPushButton *BtnCampaignPage;
QPushButton *BtnMultiplayer;
QPushButton *BtnLoad;
QPushButton *BtnDemos;
@@ -359,6 +362,19 @@
QComboBox *CBSelect;
};
+class PageCampaign : public AbstractPage
+{
+ Q_OBJECT
+
+public:
+ PageCampaign(QWidget* parent = 0);
+
+ QPushButton *BtnStartCampaign;
+ QPushButton *BtnBack;
+ QComboBox *CBSelect;
+ QComboBox *CBTeam;
+};
+
class PageSelectWeapon : public AbstractPage
{
Q_OBJECT
@@ -389,14 +405,24 @@
PageRoomsList(QWidget* parent, QSettings * config, SDLInteraction * sdli);
QLineEdit * roomName;
+ QLineEdit * searchText;
QTableWidget * roomsList;
QPushButton * BtnBack;
QPushButton * BtnCreate;
QPushButton * BtnJoin;
QPushButton * BtnRefresh;
QPushButton * BtnAdmin;
+ QPushButton * BtnClear;
+ QComboBox * CBState;
+ QComboBox * CBRules;
+ QComboBox * CBWeapons;
HWChatWidget * chatWidget;
+private:
+ bool gameInLobby;
+ QString gameInLobbyName;
+ QStringList listFromServer;
+
public slots:
void setRoomsList(const QStringList & list);
void setAdmin(bool);
@@ -405,11 +431,14 @@
void onCreateClick();
void onJoinClick();
void onRefreshClick();
+ void onClearClick();
+ void onJoinConfirmation(const QString &);
signals:
void askForCreateRoom(const QString &);
void askForJoinRoom(const QString &);
void askForRoomList();
+ void askJoinConfirmation(const QString &);
};
class PageConnecting : public AbstractPage
@@ -453,6 +482,10 @@
ToggleButtonWidget * TBW_sharedammo;
ToggleButtonWidget * TBW_disablegirders;
ToggleButtonWidget * TBW_disablelandobjects;
+ ToggleButtonWidget * TBW_aisurvival;
+ ToggleButtonWidget * TBW_infattack;
+ ToggleButtonWidget * TBW_resetweps;
+ ToggleButtonWidget * TBW_perhogammo;
QSpinBox * SB_DamageModifier;
QSpinBox * SB_TurnTime;
Binary file QTfrontend/res/StatsBestKiller.png has changed
Binary file QTfrontend/res/StatsBestShot.png has changed
Binary file QTfrontend/res/StatsD.png has changed
Binary file QTfrontend/res/StatsH.png has changed
Binary file QTfrontend/res/StatsHedgehogsKilled.png has changed
Binary file QTfrontend/res/StatsMedal1.png has changed
Binary file QTfrontend/res/StatsMedal2.png has changed
Binary file QTfrontend/res/StatsMedal3.png has changed
Binary file QTfrontend/res/StatsMedal4.png has changed
Binary file QTfrontend/res/StatsMostSelfDamage.png has changed
Binary file QTfrontend/res/StatsR.png has changed
Binary file QTfrontend/res/StatsSelfKilled.png has changed
Binary file QTfrontend/res/StatsSkipped.png has changed
Binary file QTfrontend/res/btnAISurvival.png has changed
Binary file QTfrontend/res/btnInfAttack.png has changed
Binary file QTfrontend/res/btnPerHogAmmo.png has changed
Binary file QTfrontend/res/btnResetWeps.png has changed
Binary file QTfrontend/res/mapCustom.png has changed
Binary file QTfrontend/res/mapMaze.png has changed
Binary file QTfrontend/res/mapMissing.png has changed
Binary file QTfrontend/res/mapMission.png has changed
Binary file QTfrontend/res/mapRandom.png has changed
--- a/QTfrontend/sdlkeys.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/sdlkeys.h Wed Oct 27 14:02:20 2010 +0200
@@ -39,7 +39,7 @@
{")", ")"},
{"*", "*"},
{"+", "+"},
- {", ", ", "},
+ {",", ","},
{"-", "-"},
{".", "."},
{"/", "/"},
--- a/QTfrontend/selectWeapon.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/selectWeapon.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -131,11 +131,11 @@
SelWeaponItem * pwi = new SelWeaponItem(false, i, currentState[numItems + i].digitValue(), QImage(":/res/ammopicbox.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);
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);
weaponItems[i].append(awi);
p4Layout->addWidget(awi, j, k % 4);
--- a/QTfrontend/statsPage.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/statsPage.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -19,7 +19,8 @@
#include <QLabel>
#include <QGridLayout>
#include <QGraphicsScene>
-
+#include <QGroupBox>
+#include <QSizePolicy>
#include "statsPage.h"
#include "team.h"
@@ -36,20 +37,59 @@
PageGameStats::PageGameStats(QWidget* parent) : AbstractPage(parent)
{
QGridLayout * pageLayout = new QGridLayout(this);
+ pageLayout->setSpacing(20);
pageLayout->setColumnStretch(0, 1);
pageLayout->setColumnStretch(1, 1);
- pageLayout->setColumnStretch(2, 1);
+
+ BtnBack = addButton(":/res/Exit.png", pageLayout, 3, 0, true);
+ BtnBack->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- BtnBack = addButton(":/res/Exit.png", pageLayout, 2, 0, true);
+ QGroupBox * gb = new QGroupBox(this);
+ QVBoxLayout * gbl = new QVBoxLayout;
+ // details
labelGameStats = new QLabel(this);
+ QLabel * l = new QLabel(this);
+ l->setTextFormat(Qt::RichText);
+ l->setText("<h1><img src=\":/res/StatsD.png\"> " + PageGameStats::tr("Details") + "</h1>");
+ l->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
labelGameStats->setTextFormat(Qt::RichText);
- pageLayout->addWidget(labelGameStats, 0, 0, 1, 3);
-
- graphic = new FitGraphicsView(this);
+ labelGameStats->setAlignment(Qt::AlignTop);
+ gbl->addWidget(l);
+ gbl->addWidget(labelGameStats);
+ gb->setLayout(gbl);
+ pageLayout->addWidget(gb, 1, 1);
+
+ // graph
+ graphic = new FitGraphicsView(gb);
+ l = new QLabel(this);
+ l->setTextFormat(Qt::RichText);
+ l->setText("<br><h1><img src=\":/res/StatsH.png\"> " + PageGameStats::tr("Health graph") + "</h1>");
+ l->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ gbl->addWidget(l);
+ gbl->addWidget(graphic);
graphic->scale(1.0, -1.0);
graphic->setBackgroundBrush(QBrush(Qt::black));
- pageLayout->addWidget(graphic, 1, 0, 1, 3);
+
+ labelGameWin = new QLabel(this);
+ labelGameWin->setTextFormat(Qt::RichText);
+ pageLayout->addWidget(labelGameWin, 0, 0, 1, 2);
+
+ // ranking box
+ gb = new QGroupBox(this);
+ gbl = new QVBoxLayout;
+ labelGameRank = new QLabel(gb);
+ l = new QLabel(this);
+ l->setTextFormat(Qt::RichText);
+ l->setText("<h1><img src=\":/res/StatsR.png\"> " + PageGameStats::tr("Ranking") + "</h1>");
+ l->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ gbl->addWidget(l);
+ gbl->addWidget(labelGameRank);
+ gb->setLayout(gbl);
+
+ labelGameRank->setTextFormat(Qt::RichText);
+ labelGameRank->setAlignment(Qt::AlignTop);
+ pageLayout->addWidget(gb, 1, 0);
}
void PageGameStats::AddStatText(const QString & msg)
@@ -61,6 +101,9 @@
{
labelGameStats->setText("");
healthPoints.clear();
+ labelGameRank->setText("");
+ playerPosition = 0;
+ lastColor = 0;
}
void PageGameStats::renderStats()
@@ -93,27 +136,25 @@
{
switch(type) {
case 'r' : {
- AddStatText(QString("<h1 align=\"center\">%1</h1>").arg(info));
+ labelGameWin->setText(QString("<h1 align=\"center\">%1</h1>").arg(info));
break;
}
case 'D' : {
int i = info.indexOf(' ');
- QString message = PageGameStats::tr("<p>The best shot award was won by <b>%1</b> with <b>%2</b> pts.</p>")
- .arg(info.mid(i + 1), info.left(i));
+ QString message = "<p><img src=\":/res/StatsBestShot.png\"> " + PageGameStats::tr("The best shot award was won by <b>%1</b> with <b>%2</b> pts.").arg(info.mid(i + 1), info.left(i)) + "</p>";
AddStatText(message);
break;
}
case 'k' : {
int i = info.indexOf(' ');
int num = info.left(i).toInt();
- QString message = PageGameStats::tr("<p>The best killer is <b>%1</b> with <b>%2</b> kills in a turn.</p>", "", num)
- .arg(info.mid(i + 1), info.left(i));
+ QString message = "<p><img src=\":/res/StatsBestKiller.png\"> " + PageGameStats::tr("The best killer is <b>%1</b> with <b>%2</b> kills in a turn.", "", num).arg(info.mid(i + 1), info.left(i)) + "</p>";
AddStatText(message);
break;
}
case 'K' : {
int num = info.toInt();
- QString message = PageGameStats::tr("<p>A total of <b>%1</b> hedgehog(s) were killed during this round.</p>", "", num).arg(num);
+ QString message = "<p><img src=\":/res/StatsHedgehogsKilled.png\"> " + PageGameStats::tr("A total of <b>%1</b> hedgehog(s) were killed during this round.", "", num).arg(num) + "</p>";
AddStatText(message);
break;
}
@@ -136,6 +177,75 @@
team.Wins++; // should draws count as wins?
//team.SaveToFile(); // don't save yet
}
+ break;
}
+
+ case 'P' : {
+ int i = info.indexOf(' ');
+ playerPosition++;
+ QString color = info.left(i);
+ quint32 c = color.toInt();
+ QColor clanColor = QColor(qRgb((c >> 16) & 255, (c >> 8) & 255, c & 255));
+
+ QString playerinfo = info.mid(i + 1);
+
+ i = playerinfo.indexOf(' ');
+
+ QString kills = playerinfo.left(i);
+ QString playername = playerinfo.mid(i + 1);
+ QString image;
+
+ if (lastColor == c && playerPosition <= 2) playerPosition = 1;
+ lastColor = c;
+
+ switch (playerPosition)
+ {
+ case 1:
+ image = "<img src=\":/res/StatsMedal1.png\">";
+ break;
+ case 2:
+ image = "<img src=\":/res/StatsMedal2.png\">";
+ break;
+ case 3:
+ image = "<img src=\":/res/StatsMedal3.png\">";
+ break;
+ default:
+ image = "<img src=\":/res/StatsMedal4.png\">";
+ break;
+ }
+
+ QString message;
+ QString killstring;
+ if (kills.toInt() == 1)
+ {
+ killstring = PageGameStats::tr("(%1 kill)").arg(kills);
+ } else {
+ killstring = PageGameStats::tr("(%1 kills)").arg(kills);
+ }
+
+ message = QString("<p><h2>%1 %2. <font color=\"%4\">%3</font> ").arg(image, QString::number(playerPosition), playername, clanColor.name()) + killstring + "</h2></p>";
+
+ labelGameRank->setText(labelGameRank->text() + message);
+ break;
+ }
+ case 's' : {
+ int i = info.indexOf(' ');
+ QString message = "<p><img src=\":/res/StatsMostSelfDamage.png\"> " + PageGameStats::tr("<b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts.").arg(info.mid(i + 1), info.left(i)) + "</p>";
+ AddStatText(message);
+ break;
+ }
+ case 'S' : {
+ int i = info.indexOf(' ');
+ QString message = "<p><img src=\":/res/StatsSelfKilled.png\"> " + PageGameStats::tr("<b>%1</b> killed <b>%2</b> of his own hedgehogs.").arg(info.mid(i + 1), info.left(i)) + "</p>";
+ AddStatText(message);
+ break;
+ }
+ case 'B' : {
+ int i = info.indexOf(' ');
+ QString message = "<p><img src=\":/res/StatsSkipped.png\"> " + PageGameStats::tr("<b>%1</b> was scared and skipped turn <b>%2</b> times.").arg(info.mid(i + 1), info.left(i)) + "</p>";
+ AddStatText(message);
+ break;
+ }
+
}
}
--- a/QTfrontend/statsPage.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/statsPage.h Wed Oct 27 14:02:20 2010 +0200
@@ -44,6 +44,8 @@
QPushButton *BtnBack;
QLabel *labelGameStats;
+ QLabel *labelGameWin;
+ QLabel *labelGameRank;
FitGraphicsView * graphic;
public slots:
@@ -55,6 +57,8 @@
void AddStatText(const QString & msg);
QMap<quint32, QVector<quint32> > healthPoints;
+ unsigned int playerPosition;
+ quint32 lastColor;
};
#endif // STATSPAGE_H
--- a/QTfrontend/tcpBase.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/tcpBase.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -72,7 +72,7 @@
process = new QProcess;
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(StartProcessError(QProcess::ProcessError)));
QStringList arguments=setArguments();
-
+
// redirect everything written on stdout/stderr
if(isDevBuild)
process->setProcessChannelMode(QProcess::ForwardedChannels);
--- a/QTfrontend/team.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/team.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -52,6 +52,7 @@
}
Rounds = 0;
Wins = 0;
+ CampaignProgress = 0;
}
HWTeam::HWTeam(const QStringList& strLst) :
@@ -73,10 +74,11 @@
Hedgehogs[i].Hat=strLst[i * 2 + 8];
// Somehow claymore managed an empty hat. Until we figure out how, this should avoid a repeat
// Checking net teams is probably pointless, but can't hurt.
- if (Hedgehogs[i].Hat.length() == 0) Hedgehogs[i].Hat = "NoHat";
+ if (Hedgehogs[i].Hat.isEmpty()) Hedgehogs[i].Hat = "NoHat";
}
Rounds = 0;
Wins = 0;
+ CampaignProgress = 0;
}
HWTeam::HWTeam() :
@@ -103,12 +105,13 @@
}
Rounds = 0;
Wins = 0;
+ CampaignProgress = 0;
}
bool HWTeam::LoadFromFile()
{
- QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + TeamName + ".ini", QSettings::IniFormat, 0);
+ QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + TeamName + ".hwt", QSettings::IniFormat, 0);
teamfile.setIniCodec("UTF-8");
TeamName = teamfile.value("Team/Name", TeamName).toString();
Grave = teamfile.value("Team/Grave", "Statue").toString();
@@ -118,6 +121,7 @@
difficulty = teamfile.value("Team/Difficulty", 0).toInt();
Rounds = teamfile.value("Team/Rounds", 0).toInt();
Wins = teamfile.value("Team/Wins", 0).toInt();
+ CampaignProgress = teamfile.value("Team/CampaignProgress", 0).toInt();
for(int i = 0; i < 8; i++)
{
QString hh = QString("Hedgehog%1/").arg(i);
@@ -140,7 +144,7 @@
bool HWTeam::FileExists()
{
- QFile f(cfgdir->absolutePath() + "/Teams/" + TeamName + ".ini");
+ QFile f(cfgdir->absolutePath() + "/Teams/" + TeamName + ".hwt");
return f.exists();
}
@@ -148,7 +152,7 @@
{
if(m_isNetTeam)
return false;
- QFile cfgfile(cfgdir->absolutePath() + "/Teams/" + TeamName + ".ini");
+ QFile cfgfile(cfgdir->absolutePath() + "/Teams/" + TeamName + ".hwt");
cfgfile.remove();
return true;
}
@@ -157,11 +161,11 @@
{
if (OldTeamName != TeamName)
{
- QFile cfgfile(cfgdir->absolutePath() + "/Teams/" + OldTeamName + ".ini");
+ QFile cfgfile(cfgdir->absolutePath() + "/Teams/" + OldTeamName + ".hwt");
cfgfile.remove();
OldTeamName = TeamName;
}
- QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + TeamName + ".ini", QSettings::IniFormat, 0);
+ QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + TeamName + ".hwt", QSettings::IniFormat, 0);
teamfile.setIniCodec("UTF-8");
teamfile.setValue("Team/Name", TeamName);
teamfile.setValue("Team/Grave", Grave);
@@ -171,6 +175,7 @@
teamfile.setValue("Team/Difficulty", difficulty);
teamfile.setValue("Team/Rounds", Rounds);
teamfile.setValue("Team/Wins", Wins);
+ teamfile.setValue("Team/CampaignProgress", CampaignProgress);
for(int i = 0; i < 8; i++)
{
QString hh = QString("Hedgehog%1/").arg(i);
@@ -204,7 +209,7 @@
hwform->ui.pageEditTeam->HHHats[i]->setCurrentIndex(hwform->ui.pageEditTeam->HHHats[i]->findData(Hedgehogs[i].Hat, Qt::DisplayRole));
}
hwform->ui.pageEditTeam->CBGrave->setCurrentIndex(hwform->ui.pageEditTeam->CBGrave->findText(Grave));
- hwform->ui.pageEditTeam->CBFlag->setCurrentIndex(hwform->ui.pageEditTeam->CBFlag->findText(Flag));
+ hwform->ui.pageEditTeam->CBFlag->setCurrentIndex(hwform->ui.pageEditTeam->CBFlag->findData(Flag));
hwform->ui.pageEditTeam->CBFort->setCurrentIndex(hwform->ui.pageEditTeam->CBFort->findText(Fort));
hwform->ui.pageEditTeam->CBVoicepack->setCurrentIndex(hwform->ui.pageEditTeam->CBVoicepack->findText(Voicepack));
@@ -232,7 +237,7 @@
Grave = hwform->ui.pageEditTeam->CBGrave->currentText();
Fort = hwform->ui.pageEditTeam->CBFort->currentText();
Voicepack = hwform->ui.pageEditTeam->CBVoicepack->currentText();
- Flag = hwform->ui.pageEditTeam->CBFlag->currentText();
+ Flag = hwform->ui.pageEditTeam->CBFlag->itemData(hwform->ui.pageEditTeam->CBFlag->currentIndex()).toString();
for(int i = 0; i < BINDS_NUMBER; i++)
{
binds[i].strbind = hwform->ui.pageEditTeam->CBBind[i]->itemData(hwform->ui.pageEditTeam->CBBind[i]->currentIndex()).toString();
--- a/QTfrontend/team.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/team.h Wed Oct 27 14:02:20 2010 +0200
@@ -56,6 +56,7 @@
QString Owner;
int Rounds;
int Wins;
+ int CampaignProgress;
HWHog Hedgehogs[8];
unsigned int AchievementProgress[MAX_ACHIEVEMENTS];
unsigned int difficulty;
--- a/QTfrontend/teamselhelper.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/teamselhelper.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -75,6 +75,7 @@
phhoger = new CHedgehogerWidget(QImage(":/res/hh25x25.png"), this);
connect(phhoger, SIGNAL(hedgehogsNumChanged()), this, SLOT(hhNumChanged()));
+ phhoger->setHHNum(team.numHedgehogs);
mainLayout.addWidget(phhoger);
} else {
}
--- a/QTfrontend/ui_hwform.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/ui_hwform.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -113,4 +113,7 @@
pageNetType = new PageNetType();
Pages->addWidget(pageNetType);
+
+ pageCampaign = new PageCampaign();
+ Pages->addWidget(pageCampaign);
}
--- a/QTfrontend/ui_hwform.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/ui_hwform.h Wed Oct 27 14:02:20 2010 +0200
@@ -32,6 +32,7 @@
class PageGameStats;
class PageSinglePlayer;
class PageTraining;
+class PageCampaign;
class PageSelectWeapon;
class PageInGame;
class PageRoomsList;
@@ -70,6 +71,7 @@
PageScheme *pageScheme;
PageAdmin *pageAdmin;
PageNetType *pageNetType;
+ PageCampaign *pageCampaign;
QStackedLayout *Pages;
QFont *font14;
--- a/QTfrontend/xfire.cpp Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/xfire.cpp Wed Oct 27 14:02:20 2010 +0200
@@ -1,6 +1,6 @@
/*
* Hedgewars Xfire integration
- * Copyright (c) 2010 Mario Liebisch <mario.liebisch AT googlemail.com>
+ * Copyright (c) 2010 Andrey Korotaev <unC0Rr@gmail.com>
*
* 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
@@ -34,10 +34,10 @@
if(use_xfire)
return;
use_xfire = XfireIsLoaded() == 1;
-
+
if(!use_xfire)
return;
-
+
for(int i = 0; i < XFIRE_KEY_COUNT; i++)
{
keys[i] = new char[256];
@@ -45,7 +45,7 @@
strcpy(keys[i], "");
strcpy(values[i], "");
}
-
+
strcpy(keys[XFIRE_NICKNAME], "Nickname");
strcpy(keys[XFIRE_ROOM], "Room");
strcpy(keys[XFIRE_SERVER], "Server");
@@ -58,7 +58,7 @@
{
if(!use_xfire)
return;
-
+
for(int i = 0; i < XFIRE_KEY_COUNT; i++)
{
delete [] keys[i];
--- a/QTfrontend/xfire.h Thu Aug 26 23:59:18 2010 +0200
+++ b/QTfrontend/xfire.h Wed Oct 27 14:02:20 2010 +0200
@@ -1,6 +1,6 @@
/*
* Hedgewars Xfire integration
- * Copyright (c) 2010 Mario Liebisch <mario.liebisch AT googlemail.com>
+ * Copyright (c) 2010 Andrey Korotaev <unC0Rr@gmail.com>
*
* 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
Binary file bin/hwdfile.ico has changed
Binary file bin/hwsfile.ico has changed
--- a/gameServer/Actions.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/Actions.hs Wed Oct 27 14:02:20 2010 +0200
@@ -11,7 +11,7 @@
import Data.Time
import Data.Maybe
import Control.Monad.Reader
-import Control.Monad.State
+import Control.Monad.State.Strict
import qualified Data.ByteString.Char8 as B
-----------------------------
import CoreTypes
@@ -57,9 +57,7 @@
processAction (AnswerClients chans msg) = do
- liftIO (putStr $ "AnswerClients... " ++ (show $ length chans) ++ " (" ++ (show msg) ++")")
- liftIO $ map (flip seq ()) chans `seq` mapM_ (flip writeChan msg) chans
- liftIO (putStrLn "done")
+ liftIO $ map (flip seq ()) chans `seq` map (flip seq ()) msg `seq` mapM_ (flip writeChan msg) chans
processAction SendServerMessage = do
@@ -100,30 +98,35 @@
(Just ci) <- gets clientIndex
rnc <- gets roomsClients
ri <- clientRoomA
- when (ri /= lobbyId) $ do
- processAction $ MoveToLobby ("quit: " `B.append` msg)
- return ()
chan <- client's sendChan
ready <- client's isReady
+ 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
- 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
processAction $ AnswerClients [chan] ["BYE", msg]
- modify (\s -> s{removedClients = ci `Set.insert` removedClients s})
+
+ s <- get
+ put $! s{removedClients = ci `Set.insert` removedClients s}
processAction (DeleteClient ci) = do
rnc <- gets roomsClients
liftIO $ removeClient rnc ci
- modify (\s -> s{removedClients = ci `Set.delete` removedClients s})
+
+ s <- get
+ put $! s{removedClients = ci `Set.delete` removedClients s}
{-
where
@@ -258,7 +261,7 @@
processAction $ MoveToRoom rId
- chans <- liftM (map sendChan) $ roomClientsS lobbyId
+ chans <- liftM (map sendChan) $! roomClientsS lobbyId
mapM_ processAction [
AnswerClients chans ["ROOM", "ADD", roomName]
@@ -401,7 +404,7 @@
liftIO $ do
ci <- addClient rnc client
forkIO $ clientRecvLoop (clientSocket client) (coreChan si) ci
- forkIO $ clientSendLoop (clientSocket client) (coreChan si) (sendChan client) ci
+ forkIO $ clientSendLoop (clientSocket client) (sendChan client) ci
infoM "Clients" (show ci ++ ": New client. Time: " ++ show (connectTime client))
--- a/gameServer/ClientIO.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/ClientIO.hs Wed Oct 27 14:02:20 2010 +0200
@@ -57,8 +57,8 @@
-clientSendLoop :: Socket -> Chan CoreMessage -> Chan [B.ByteString] -> ClientIndex -> IO()
-clientSendLoop s coreChan chan ci = do
+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
@@ -67,7 +67,7 @@
if (isQuit answer) then
Exception.handle (\(_ :: Exception.IOException) -> putStrLn "error on sClose") $ sClose s
else
- clientSendLoop s coreChan chan ci
+ clientSendLoop s chan ci
where
--sendQuit e = writeChan coreChan $ ClientMessage (ci, ["QUIT", B.pack $ show e])
--- a/gameServer/CoreTypes.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/CoreTypes.hs Wed Oct 27 14:02:20 2010 +0200
@@ -31,7 +31,7 @@
roomID :: RoomIndex,
pingsQueue :: !Word,
isMaster :: Bool,
- isReady :: Bool,
+ isReady :: !Bool,
isAdministrator :: Bool,
clientClan :: B.ByteString,
teamsInGame :: Word
@@ -78,7 +78,6 @@
gameinprogress :: Bool,
playersIn :: !Int,
readyPlayers :: !Int,
- playersIDs :: IntSet.IntSet,
isRestrictedJoins :: Bool,
isRestrictedTeams :: Bool,
roundMsgs :: Seq B.ByteString,
@@ -88,8 +87,7 @@
}
instance Show RoomInfo where
- show ri = ", players ids: " ++ show (IntSet.size $ playersIDs ri)
- ++ ", players: " ++ show (playersIn ri)
+ show ri = ", players: " ++ show (playersIn ri)
++ ", ready: " ++ show (readyPlayers ri)
++ ", teams: " ++ show (teams ri)
@@ -104,7 +102,6 @@
False
0
0
- IntSet.empty
False
False
Data.Sequence.empty
--- a/gameServer/OfficialServer/extdbinterface.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/OfficialServer/extdbinterface.hs Wed Oct 27 14:02:20 2010 +0200
@@ -1,4 +1,4 @@
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}
module Main where
@@ -26,7 +26,7 @@
case q of
CheckAccount clUid clNick _ -> do
statement <- prepare dbConn dbQueryAccount
- execute statement [SqlString $ clNick]
+ execute statement [SqlByteString $ clNick]
passAndRole <- fetchRow statement
finish statement
let response =
@@ -47,7 +47,7 @@
dbConnectionLoop mySQLConnectionInfo =
- Control.Exception.handle (\(_ :: IOException) -> return ()) $ handleSqlError $
+ Control.Exception.handle (\(e :: IOException) -> hPutStrLn stderr $ show e) $ handleSqlError $
bracket
(connectMySQL mySQLConnectionInfo)
(disconnect)
--- a/gameServer/RoomsAndClients.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/RoomsAndClients.hs Wed Oct 27 14:02:20 2010 +0200
@@ -1,193 +1,196 @@
-module RoomsAndClients(
- RoomIndex(),
- ClientIndex(),
- MRoomsAndClients(),
- IRoomsAndClients(),
- newRoomsAndClients,
- addRoom,
- addClient,
- removeRoom,
- removeClient,
- modifyRoom,
- modifyClient,
- lobbyId,
- moveClientToLobby,
- moveClientToRoom,
- clientRoom,
- clientRoomM,
- 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 = room{roomClients' = cl : roomClients' room}
-
-roomRemoveClient :: ClientIndex -> Room r -> Room r
-roomRemoveClient cl room = room{roomClients' = filter (/= cl) $ roomClients' room}
-
-
-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
-
-
-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)
+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)
--- a/gameServer/ServerCore.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/ServerCore.hs Wed Oct 27 14:02:20 2010 +0200
@@ -7,7 +7,7 @@
import qualified Data.IntMap as IntMap
import System.Log.Logger
import Control.Monad.Reader
-import Control.Monad.State
+import Control.Monad.State.Strict
import Data.Set as Set
import qualified Data.ByteString.Char8 as B
--------------------------------------
@@ -19,7 +19,7 @@
import ServerState
-timerLoop :: Int -> Chan CoreMessage -> IO()
+timerLoop :: Int -> Chan CoreMessage -> IO ()
timerLoop tick messagesChan = threadDelay (30 * 10^6) >> writeChan messagesChan (TimerAction tick) >> timerLoop (tick + 1) messagesChan
@@ -32,10 +32,11 @@
mainLoop :: StateT ServerState IO ()
mainLoop = forever $ do
+ get >>= \s -> put $! s
+
si <- gets serverInfo
r <- liftIO $ readChan $ coreChan si
- liftIO $ putStrLn $ "Core msg: " ++ show r
case r of
Accept ci -> processAction (AddClient ci)
@@ -44,7 +45,8 @@
removed <- gets removedClients
when (not $ ci `Set.member` removed) $ do
- modify (\as -> as{clientIndex = Just ci})
+ as <- get
+ put $! as{clientIndex = Just ci}
reactCmd cmd
Remove ci -> do
@@ -57,13 +59,14 @@
--return (serverInfo, rnc)
ClientAccountInfo (ci, info) -> do
- --should instead check ci exists and has same nick/hostname
- --removed <- gets removedClients
- --when (not $ ci `Set.member` removed) $ do
- -- modify (\as -> as{clientIndex = Just ci})
- -- processAction (ProcessAccountInfo info)
- return ()
-
+ rnc <- gets roomsClients
+ exists <- liftIO $ clientExists rnc ci
+ when (exists) $ do
+ as <- get
+ put $! as{clientIndex = Just ci}
+ processAction (ProcessAccountInfo info)
+ return ()
+
TimerAction tick ->
mapM_ processAction $
PingAll : [StatsAction | even tick]
--- a/gameServer/ServerState.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/ServerState.hs Wed Oct 27 14:02:20 2010 +0200
@@ -8,17 +8,17 @@
roomClientsS
) where
-import Control.Monad.State
+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
+ clientIndex :: !(Maybe ClientIndex),
+ serverInfo :: !ServerInfo,
+ removedClients :: !(Set.Set ClientIndex),
+ roomsClients :: !MRnC
}
--- a/gameServer/Store.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/Store.hs Wed Oct 27 14:02:20 2010 +0200
@@ -1,128 +1,145 @@
-module Store(
- ElemIndex(),
- MStore(),
- IStore(),
- newStore,
- addElem,
- removeElem,
- readElem,
- writeElem,
- modifyElem,
- 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
-
-
-indicesM :: MStore e -> IO [ElemIndex]
-indicesM (MStore ref) = do
- (busy, _, _) <- readIORef ref
- return $ map ElemIndex $ IntSet.toList busy
-
-
--- A way to use see MStore elements in pure code via IStore
-m2i :: MStore e -> IO (IStore e)
-m2i (MStore ref) = do
- (a, _, c') <- readIORef ref
- c <- IOA.freeze c'
- return $ IStore (a, c)
-
-
-withIStore :: MStore e -> (IStore e -> a) -> IO a
-withIStore m f = liftM f (m2i m)
-
-
-withIStore2 :: MStore e1 -> MStore e2 -> (IStore e1 -> IStore e2 -> a) -> IO a
-withIStore2 m1 m2 f = do
- i1 <- m2i m1
- i2 <- m2i m2
- return $ f i1 i2
-
-
--- 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
+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
--- a/gameServer/hedgewars-server.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/hedgewars-server.hs Wed Oct 27 14:02:20 2010 +0200
@@ -21,7 +21,7 @@
setupLoggers :: IO ()
setupLoggers =
updateGlobalLogger "Clients"
- (setLevel DEBUG)
+ (setLevel INFO)
main :: IO ()
main = withSocketsDo $ do
--- a/gameServer/stresstest.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/stresstest.hs Wed Oct 27 14:02:20 2010 +0200
@@ -19,7 +19,7 @@
session3 nick room = ["NICK", nick, "", "PROTO", "32", "", "LIST", "", "JOIN_ROON", room, "", "CHAT", "room 2", "", "QUIT", "quit", ""]
emulateSession sock s = do
- mapM_ (\x -> hPutStrLn sock x >> hFlush sock >> randomRIO (300000::Int, 590000) >>= threadDelay) s
+ mapM_ (\x -> hPutStrLn sock x >> hFlush sock >> randomRIO (30000::Int, 59000) >>= threadDelay) s
hFlush sock
threadDelay 225000
@@ -40,7 +40,7 @@
putStrLn "Finish"
forks = forever $ do
- delay <- randomRIO (300000::Int, 590000)
+ delay <- randomRIO (30000::Int, 59000)
threadDelay delay
forkIO testing
--- a/gameServer/stresstest2.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/stresstest2.hs Wed Oct 27 14:02:20 2010 +0200
@@ -6,7 +6,7 @@
import System.IO
import Control.Concurrent
import Network
-import Control.Exception
+import Control.OldException
import Control.Monad
import System.Random
@@ -14,22 +14,28 @@
import System.Posix
#endif
-testing = Control.Exception.handle print $ do
- delay <- randomRIO (100::Int, 300)
- threadDelay delay
+session1 nick room = ["NICK", nick, "", "PROTO", "32", ""]
+
+
+
+testing = Control.OldException.handle print $ do
+ putStrLn "Start"
sock <- connectTo "127.0.0.1" (PortNumber 46631)
- hClose sock
-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)
+ 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
main = withSocketsDo $ do
#if !defined(mingw32_HOST_OS)
installHandler sigPIPE Ignore Nothing;
#endif
- forks 1
+ forks
--- a/gameServer/stresstest3.hs Thu Aug 26 23:59:18 2010 +0200
+++ b/gameServer/stresstest3.hs Wed Oct 27 14:02:20 2010 +0200
@@ -44,7 +44,7 @@
emulateSession :: StateT SState IO ()
emulateSession = do
- n <- io $ randomRIO (100000::Int, 100000)
+ n <- io $ randomRIO (100000::Int, 100100)
waitPacket "CONNECTED"
sendPacket ["NICK", "test" ++ (show n)]
waitPacket "NICK"
@@ -52,6 +52,7 @@
waitPacket "PROTO"
b <- waitPacket "LOBBY:JOINED"
--io $ print b
+ sendPacket ["QUIT", "BYE"]
return ()
testing = Control.OldException.handle print $ do
@@ -62,7 +63,7 @@
putStr "-"
hFlush stdout
-forks = forever $ do
+forks = forM_ [1..100] $ const $ do
delay <- randomRIO (10000::Int, 30000)
threadDelay delay
forkIO testing
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/ArgParsers.inc Wed Oct 27 14:02:20 2010 +0200
@@ -0,0 +1,202 @@
+
+procedure internalSetGameTypeLandPreviewFromParameters();
+begin
+ val(ParamStr(2), ipcPort);
+ GameType:= gmtLandPreview;
+ if ParamStr(3) <> 'landpreview' then
+ GameType:= gmtSyntax
+end;
+
+procedure internalStartGameWithParameters();
+var tmp: LongInt;
+begin
+ val(ParamStr(2), cScreenWidth);
+ val(ParamStr(3), cScreenHeight);
+ val(ParamStr(4), cBits);
+ val(ParamStr(5), ipcPort);
+ cFullScreen:= ParamStr(6) = '1';
+ isSoundEnabled:= ParamStr(7) = '1';
+ isMusicEnabled:= ParamStr(8) = '1';
+ val(ParamStr(9), cInitVolume);
+ val(ParamStr(10), cTimerInterval);
+ PathPrefix:= ParamStr(11);
+ cShowFPS:= ParamStr(12) = '1';
+ cAltDamage:= ParamStr(13) = '1';
+ UserNick:= DecodeBase64(ParamStr(14));
+ val(ParamStr(15), cReducedQuality);
+ val(ParamStr(16), tmp);
+ cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp)));
+ cLocaleFName:= ParamStr(17);
+end;
+
+procedure setVideo(screenWidth: LongInt; screenHeight: LongInt; bitsStr: LongInt);
+begin
+ cScreenWidth:= screenWidth;
+ cScreenHeight:= screenHeight;
+ cBits:= bitsStr
+end;
+
+procedure setVideoWithParameters(screenWidthParam: string; screenHeightParam: string; bitsParam: string);
+var screenWidthAsInt, screenHeightAsInt, bitsStrAsInt: LongInt;
+begin
+ val(screenWidthParam, screenWidthAsInt);
+ val(screenHeightParam, screenHeightAsInt);
+ val(bitsParam, bitsStrAsInt);
+ setVideo(screenWidthAsInt,screenHeightAsInt,bitsStrAsInt)
+end;
+
+procedure setOtherOptions(languageFile: string; fullScreen: boolean);
+begin
+ cLocaleFName:= languageFile;
+ cFullScreen:= fullScreen
+end;
+
+procedure setShowFPS(showFPS: boolean);
+begin
+ cShowFPS:= showFPS
+end;
+
+procedure setOtherOptionsWithParameters(languageFileParam: string; fullScreenParam: string; showFPSParam: string);
+var fullScreen, showFPS: boolean;
+begin
+ fullScreen:= fullScreenParam = '1';
+ showFPS:= showFPSParam = '1';
+ setOtherOptions(languageFileParam,fullScreen);
+ setShowFPS(showFPS)
+end;
+
+procedure setAudio(initialVolume: LongInt; musicEnabled: boolean; soundEnabled: boolean);
+begin
+ cInitVolume:= initialVolume;
+ isMusicEnabled:= musicEnabled;
+ isSoundEnabled:= soundEnabled
+end;
+
+procedure setAudioWithParameters(initialVolumeParam: string; musicEnabledParam: string; soundEnabledParam: string);
+var initialVolumeAsInt: LongInt;
+ musicEnabled, soundEnabled: boolean;
+begin
+ val(initialVolumeParam, initialVolumeAsInt);
+ musicEnabled:= musicEnabledParam = '1';
+ soundEnabled:= soundEnabledParam = '1';
+ setAudio(initialVolumeAsInt,musicEnabled, soundEnabled)
+end;
+
+procedure setMultimediaOptionsWithParameters(screenWidthParam, screenHeightParam, bitsParam: string;
+ initialVolumeParam, musicEnabledParam, soundEnabledParam: string;
+ languageFileParam, fullScreenParam: string);
+begin
+ setVideoWithParameters(screenWidthParam,screenHeightParam, bitsParam);
+ setAudioWithParameters(initialVolumeParam,musicEnabledParam,soundEnabledParam);
+ setOtherOptions(languageFileParam,fullScreenParam = '1')
+end;
+
+procedure setAltDamageTimerValueAndQuality(altDamage: boolean; timeIterval: LongInt; reducedQuality: boolean);
+begin
+ cAltDamage:= altDamage;
+ cTimerInterval:= timeIterval;
+ if (reducedQuality) then //HACK
+ cReducedQuality:= $FFFFFFFF xor rqLowRes
+end;
+
+procedure setAllOptionsWithParameters(screenWidthParam:string; screenHeightParam:string; bitsParam:string;
+ initialVolumeParam:string; musicEnabledParam:string; soundEnabledParam:string;
+ languageFileParam:string; fullScreenParam:string; showFPSParam:string;
+ altDamageParam:string; timeItervalParam:string; reducedQualityParam: string);
+var showFPS, altDamage, reducedQuality: boolean;
+ timeIterval: LongInt;
+begin
+ setMultimediaOptionsWithParameters(screenWidthParam,screenHeightParam, bitsParam,
+ initialVolumeParam,musicEnabledParam,soundEnabledParam,
+ languageFileParam,fullScreenParam);
+ showFPS := showFPSParam = '1';
+ setShowFPS(showFPS);
+
+ altDamage:= altDamageParam = '1';
+ val(timeItervalParam, timeIterval);
+ reducedQuality:= reducedQualityParam = '1';
+ setAltDamageTimerValueAndQuality(altDamage,timeIterval,reducedQuality);
+end;
+
+procedure playReplayFileWithParameters();
+var paramIndex: LongInt;
+ wrongParameter: boolean;
+begin
+ PathPrefix:= ParamStr(1);
+ recordFileName:= ParamStr(2);
+ paramIndex:= 3;
+ wrongParameter:= false;
+ while (paramIndex <= ParamCount) and not wrongParameter do
+ begin
+ if ParamStr(paramIndex) = '--set-video' then
+//--set-video [screen width] [screen height] [color dept]
+ begin
+ if(ParamCount-paramIndex < 3) then
+ begin
+ wrongParameter:= true;
+ GameType:= gmtSyntax
+ end;
+ setVideoWithParameters(ParamStr(paramIndex+1), ParamStr(paramIndex+2), ParamStr(paramIndex+3));
+ paramIndex:= paramIndex + 4
+ end
+ else
+//--set-audio [volume] [enable music] [enable sounds]
+ if ParamStr(paramIndex) = '--set-audio' then
+ begin
+ if(ParamCount-paramIndex < 3) then
+ begin
+ wrongParameter := true;
+ GameType:= gmtSyntax
+ end;
+ setAudioWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2), ParamStr(paramIndex+3));
+ paramIndex:= paramIndex + 4
+ end
+ else
+// --set-other [language file] [full screen] [show FPS]
+ if ParamStr(paramIndex) = '--set-other' then
+ begin
+ if(ParamCount-paramIndex < 3) then
+ begin
+ wrongParameter:= true;
+ GameType:= gmtSyntax
+ end;
+ setOtherOptionsWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2), ParamStr(paramIndex+3));
+ paramIndex:= paramIndex + 4
+ end
+ else
+//--set-multimedia [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]
+ if ParamStr(paramIndex) = '--set-multimedia' then
+ begin
+ if ParamCount-paramIndex < 8 then
+ begin
+ wrongParameter:= true;
+ GameType:= gmtSyntax
+ end;
+ setMultimediaOptionsWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2),ParamStr(paramIndex+3),
+ ParamStr(paramIndex+4),ParamStr(paramIndex+5),ParamStr(paramIndex+6),
+ ParamStr(paramIndex+7),ParamStr(paramIndex+8));
+ paramIndex:= paramIndex + 9
+ end
+ else
+//--set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]
+ if ParamStr(paramIndex) = '--set-everything' then
+ begin
+ if ParamCount-paramIndex < 12 then
+ begin
+ wrongParameter:= true;
+ GameType:= gmtSyntax
+ end;
+ setAllOptionsWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2),ParamStr(paramIndex+3),
+ ParamStr(paramIndex+4),ParamStr(paramIndex+5),ParamStr(paramIndex+6),
+ ParamStr(paramIndex+7),ParamStr(paramIndex+8),ParamStr(paramIndex+9),
+ ParamStr(paramIndex+10),ParamStr(paramIndex+11),ParamStr(paramIndex+12));
+ paramIndex:= paramIndex + 13
+ end
+ else
+ begin
+ wrongParameter:= true;
+ GameType:= gmtSyntax
+ end
+ end
+end;
+
--- a/hedgewars/CCHandlers.inc Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/CCHandlers.inc Wed Oct 27 14:02:20 2010 +0200
@@ -162,6 +162,11 @@
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;
@@ -290,10 +295,11 @@
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;
-if not CurrentTeam^.ExtDriven then SendIPC('L');
with CurrentHedgehog^.Gear^ do
- Message:= Message or gm_Left
+ Message:= Message or gmLeft
end;
procedure chLeft_m(var s: shortstring);
@@ -302,17 +308,18 @@
if CheckNoTeamOrHH then exit;
if not CurrentTeam^.ExtDriven then SendIPC('l');
with CurrentHedgehog^.Gear^ do
- Message:= Message and not gm_Left
+ 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;
-if not CurrentTeam^.ExtDriven then SendIPC('R');
with CurrentHedgehog^.Gear^ do
- Message:= Message or gm_Right
+ Message:= Message or gmRight
end;
procedure chRight_m(var s: shortstring);
@@ -321,17 +328,18 @@
if CheckNoTeamOrHH then exit;
if not CurrentTeam^.ExtDriven then SendIPC('r');
with CurrentHedgehog^.Gear^ do
- Message:= Message and not gm_Right
+ 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;
-if not CurrentTeam^.ExtDriven then SendIPC('U');
with CurrentHedgehog^.Gear^ do
- Message:= Message or gm_Up
+ Message:= Message or gmUp
end;
procedure chUp_m(var s: shortstring);
@@ -340,17 +348,18 @@
if CheckNoTeamOrHH then exit;
if not CurrentTeam^.ExtDriven then SendIPC('u');
with CurrentHedgehog^.Gear^ do
- Message:= Message and not gm_Up
+ 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;
-if not CurrentTeam^.ExtDriven then SendIPC('D');
with CurrentHedgehog^.Gear^ do
- Message:= Message or gm_Down
+ Message:= Message or gmDown
end;
procedure chDown_m(var s: shortstring);
@@ -359,17 +368,18 @@
if CheckNoTeamOrHH then exit;
if not CurrentTeam^.ExtDriven then SendIPC('d');
with CurrentHedgehog^.Gear^ do
- Message:= Message and not gm_Down
+ 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;
-if not CurrentTeam^.ExtDriven then SendIPC('Z');
with CurrentHedgehog^.Gear^ do
- Message:= Message or gm_Precise
+ Message:= Message or gmPrecise
end;
procedure chPrecise_m(var s: shortstring);
@@ -378,33 +388,36 @@
if CheckNoTeamOrHH then exit;
if not CurrentTeam^.ExtDriven then SendIPC('z');
with CurrentHedgehog^.Gear^ do
- Message:= Message and not gm_Precise
+ 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;
-if not CurrentTeam^.ExtDriven then SendIPC('j');
with CurrentHedgehog^.Gear^ do
- Message:= Message or gm_LJump
+ 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;
-if not CurrentTeam^.ExtDriven then SendIPC('J');
with CurrentHedgehog^.Gear^ do
- Message:= Message or gm_HJump
+ 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
@@ -413,7 +426,7 @@
begin
FollowGear:= CurrentHedgehog^.Gear;
if not CurrentTeam^.ExtDriven then SendIPC('A');
- Message:= Message or gm_Attack
+ Message:= Message or gmAttack
end
end
end;
@@ -425,8 +438,8 @@
with CurrentHedgehog^.Gear^ do
begin
if not CurrentTeam^.ExtDriven and
- ((Message and gm_Attack) <> 0) then SendIPC('a');
- Message:= Message and not gm_Attack
+ ((Message and gmAttack) <> 0) then SendIPC('a');
+ Message:= Message and not gmAttack
end
end;
@@ -435,8 +448,10 @@
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 gm_Switch
+ Message:= Message or gmSwitch
end;
procedure chNextTurn(var s: shortstring);
@@ -448,9 +463,7 @@
{$IFDEF DEBUGFILE}
AddFileLog('Doing SwitchHedgehog: time '+inttostr(GameTicks));
{$ENDIF}
-{$IFDEF IPHONEOS}
- clearView();
-{$ENDIF}
+ perfExt_NewTurnBeginning();
end;
procedure chSay(var s: shortstring);
@@ -477,12 +490,13 @@
procedure chTimer(var s: shortstring);
begin
if (s[0] <> #1) or (s[1] < '1') or (s[1] > '5') or CheckNoTeamOrHH then exit;
-bShowFinger:= false;
if not CurrentTeam^.ExtDriven then SendIPC(s);
+if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1;
+bShowFinger:= false;
with CurrentHedgehog^.Gear^ do
begin
- Message:= Message or gm_Timer;
+ Message:= Message or gmTimer;
MsgParam:= byte(s[1]) - ord('0')
end
end;
@@ -491,13 +505,14 @@
var slot: LongWord;
begin
if (s[0] <> #1) or CheckNoTeamOrHH then exit;
-bShowFinger:= false;
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 gm_Slot;
+ Message:= Message or gmSlot;
MsgParam:= slot
end
end;
@@ -512,7 +527,7 @@
with CurrentHedgehog^.Gear^ do
begin
- Message:= Message or gm_Weapon;
+ Message:= Message or gmWeapon;
MsgParam:= byte(s[1]);
end;
end;
@@ -527,7 +542,7 @@
with CurrentHedgehog^.Gear^ do
begin
- Message:= Message or gm_Animate;
+ Message:= Message or gmAnimate;
MsgParam:= byte(s[1])
end
end;
@@ -564,18 +579,11 @@
end;
-procedure chNewGrave;
-begin
-if CheckNoTeamOrHH or isPaused then exit;
-
-if not CurrentTeam^.ExtDriven then SendIPC('g');
-
-AddGear(hwRound(CurrentHedgehog^.Gear^.X), hwRound(CurrentHedgehog^.Gear^.Y), gtGrave, 0, _0, _0, 0)
-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;
@@ -607,8 +615,8 @@
end;
{$IFDEF DEBUGFILE}AddFilelog('put: ' + inttostr(TargetPoint.X) + ', ' + inttostr(TargetPoint.Y));{$ENDIF}
State:= State and not gstHHChooseTarget;
- if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_AttackingPut) <> 0 then
- Message:= Message or gm_Attack;
+ if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AttackingPut) <> 0 then
+ Message:= Message or gmAttack;
end
else
if CurrentTeam^.ExtDriven then
@@ -666,19 +674,22 @@
procedure chAmmoMenu(var s: shortstring);
begin
s:= s; // avoid compiler hint
-if CheckNoTeamOrHH then
-bShowAmmoMenu:= true
+if CheckNoTeamOrHH then
+ bShowAmmoMenu:= true
else
-with CurrentTeam^ do
+ 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 ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) = 0)) or
+ ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEndHint) = 0)) or
((Gear^.State and gstHHDriven) = 0) then else bShowAmmoMenu:= true
- end
+ end;
+ if ReadyTimeLeft > 1 then ReadyTimeLeft:= 1
+ end
end;
procedure chFullScr(var s: shortstring);
@@ -779,6 +790,7 @@
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))
@@ -824,13 +836,13 @@
procedure chChat(var s: shortstring);
begin
-s:= s; // avoid compiler hint
-GameState:= gsChat;
-KeyPressChat(27)
+ 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
+ s:= s; // avoid compiler hint
+ uChat.showAll:= not uChat.showAll
end;
--- a/hedgewars/CMakeLists.txt Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/CMakeLists.txt Wed Oct 27 14:02:20 2010 +0200
@@ -31,7 +31,7 @@
endif()
endif()
-#SOURCE AND PROGRAMS SECTION
+#SOURCE AND PROGRAMS SECTION
set(fpc_tryexe fpc)
set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwengine.pas)
@@ -59,6 +59,7 @@
uLandTexture.pas
uLocale.pas
uMisc.pas
+ uMobile.pas
uRandom.pas
uScript.pas
adler32.pas
@@ -74,6 +75,7 @@
GearDrawing.inc
HHHandlers.inc
SinTable.inc
+ ArgParsers.inc
options.inc
${CMAKE_CURRENT_BINARY_DIR}/config.inc
)
--- a/hedgewars/GSHandlers.inc Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/GSHandlers.inc Wed Oct 27 14:02:20 2010 +0200
@@ -102,7 +102,9 @@
skipSpeed, skipAngle, skipDecay: hwFloat;
i, maxDrops: LongInt;
particle: PVisualGear;
+ isSubmersible: boolean;
begin
+ 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
@@ -121,23 +123,35 @@
end
else
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
- Gear^.doStep := @doStepDrowningGear;
- if Gear^.Kind = gtHedgehog then
+ if not isSubmersible then
begin
- Gear^.State := Gear^.State and (not gstHHDriven);
- AddCaption(Format(GetEventString(eidDrowned), PHedgehog(Gear^.Hedgehog)^.Name),
- cWhiteColor, capgrpMessage);
+ 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 = gtHedgehog then
+ begin
+ if PHedgehog(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);
+ end
+ end
+ else
+ Gear^.doStep := @doStepDrowningGear
end;
- if hwRound(Gear^.Y) < cWaterLine + 64 + Gear^.Radius then
+ if ((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
// don't play splash if they are already way past the surface
PlaySound(sndSplash)
end;
- if ((cReducedQuality and rqPlainSplash) = 0) and (hwRound(Gear^.Y) < cWaterLine + 64 + Gear^.Radius) then
+ 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
AddVisualGear(hwRound(Gear^.X), cWaterLine, vgtSplash);
@@ -153,9 +167,10 @@
end
end
end;
+ if isSubmersible and (CurAmmoGear^.Pos = 0) then CurAmmoGear^.Pos := 1000
end
else
- CheckGearDrowning := false
+ CheckGearDrowning := false;
end;
procedure CheckCollision(Gear: PGear);
@@ -175,6 +190,7 @@
if _0_4 < Gear^.dY then
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
@@ -237,8 +253,9 @@
tdX, tdY: hwFloat;
collV, collH: LongInt;
begin
- if Gear^.dX > _0_995 then Gear^.dX := _0_995;
- if Gear^.dY > _0_995 then Gear^.dY := _0_995;
+ // clip velocity at 1.9 - over 1 per pixel, but really shouldn't cause many actual problems.
+ if Gear^.dX.QWordValue > 8160437862 then Gear^.dX.QWordValue:= 8160437862;
+ if Gear^.dY.QWordValue > 8160437862 then Gear^.dY.QWordValue:= 8160437862;
Gear^.State := Gear^.State and not gstCollision;
collV := 0;
collH := 0;
@@ -401,7 +418,12 @@
if i mod 2 <> 0 then Fire^.State := Fire^.State or gsttmpFlag;
end
end;
- gtGasBomb: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, EXPLAutoSound or EXPLPoisoned);
+ gtGasBomb:
+ begin
+ doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, EXPLAutoSound);
+ for i:= 0 to 2 do
+ AddGear(int64(hwRound(Gear^.X)) - 30 + GetRandom(60), int64(hwRound(Gear^.Y)) - 20 + GetRandom(40), gtPoisonCloud, 0, _0, _0, 0);
+ end;
end;
DeleteGear(Gear);
exit
@@ -688,7 +710,7 @@
if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0)
and (Land[y, x] <> 0) then inc(Gear^.Damage);
if Gear^.Damage > 5 then
- if Gear^.Ammo^.AmmoType = amDEagle then
+ if Gear^.AmmoType = amDEagle then
AmmoShove(Gear, 7, 20)
else
AmmoShove(Gear, Gear^.Timer, 20);
@@ -718,7 +740,7 @@
begin
if (Gear^.Kind = gtSniperRifleShot) and ((GameFlags and gfLaserSight) = 0) then
cLaserSighting := false;
- if (Gear^.Ammo^.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and
+ if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and
((GameFlags and gfArtillery) = 0) then cArtillery := false;
Gear^.doStep := @doStepShotIdle
end;
@@ -747,7 +769,7 @@
if (HHGear^.Angle - 32 >= 0) then dec(HHGear^.Angle,32)
end;
- if (HHGear^.Message and gm_Attack) <> 0 then
+ if (HHGear^.Message and gmAttack) <> 0 then
begin
shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell);
if shell <> nil then
@@ -831,12 +853,13 @@
AllInactive := false;
HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
dec(Gear^.Timer);
- if (Gear^.Timer = 0)or((Gear^.Message and gm_Destroy) <> 0)or((HHGear^.State and gstHHDriven) =
+ if (Gear^.Timer = 0)or((Gear^.Message and gmDestroy) <> 0)or((HHGear^.State and gstHHDriven) =
0) then
begin
StopSound(Gear^.SoundChannel);
DeleteGear(Gear);
AfterAttack;
+ doStepHedgehogMoving(HHGear); // for gfInfAttack
exit
end;
@@ -849,6 +872,8 @@
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));
while i <= ei do
@@ -882,14 +907,14 @@
HHGear^.X := Gear^.X;
HHGear^.Y := Gear^.Y - int2hwFloat(cHHRadius);
- if (Gear^.Message and gm_Attack) <> 0 then
+ if (Gear^.Message and gmAttack) <> 0 then
if (Gear^.State and gsttmpFlag) <> 0 then Gear^.Timer := 1
else
else
if (Gear^.State and gsttmpFlag) = 0 then Gear^.State := Gear^.State or gsttmpFlag;
- if ((Gear^.Message and gm_Left) <> 0) then Gear^.dX := - _0_3
+ if ((Gear^.Message and gmLeft) <> 0) then Gear^.dX := - _0_3
else
- if ((Gear^.Message and gm_Right) <> 0) then Gear^.dX := _0_3
+ if ((Gear^.Message and gmRight) <> 0) then Gear^.dX := _0_3
else Gear^.dX := _0;
end;
@@ -956,9 +981,9 @@
begin
b := true;
if Gear^.dX.isNegative then
- HHGear^.Message := (HHGear^.Message and (gm_Attack or gm_Up or gm_Down)) or gm_Left
+ HHGear^.Message := (HHGear^.Message and (gmAttack or gmUp or gmDown)) or gmLeft
else
- HHGear^.Message := (HHGear^.Message and (gm_Attack or gm_Up or gm_Down)) or gm_Right;
+ HHGear^.Message := (HHGear^.Message and (gmAttack or gmUp or gmDown)) or gmRight;
if ((HHGear^.State and gstMoving) = 0) then
begin
@@ -999,7 +1024,7 @@
Gear^.dX, Gear^.dY,
cHHRadius * 5, cHHRadius * 2 + 7);
- if (Gear^.Timer = 0) or ((HHGear^.Message and gm_Attack) <> 0) then
+ if (Gear^.Timer = 0) or ((HHGear^.Message and gmAttack) <> 0) then
begin
HHGear^.Message := 0;
HHGear^.State := HHGear^.State and (not gstNotKickable);
@@ -1049,7 +1074,7 @@
HHGear^.Y := HHGear^.Y + HHGear^.dY;
HHGear^.dY := HHGear^.dY + cGravity;
- if (Gear^.Message and gm_Attack) <> 0 then
+ if (Gear^.Message and gmAttack) <> 0 then
begin
Gear^.X := HHGear^.X;
Gear^.Y := HHGear^.Y;
@@ -1077,7 +1102,7 @@
begin
with HHGear^ do
begin
- Message := Message and not gm_Attack;
+ Message := Message and not gmAttack;
State := (State or gstMoving) and not gstWinner;
end;
DeleteGear(Gear)
@@ -1087,7 +1112,7 @@
begin
with HHGear^ do
begin
- Message := Message and not gm_Attack;
+ Message := Message and not gmAttack;
State := State or gstMoving;
end;
RopePoints.Count := 0;
@@ -1100,15 +1125,15 @@
if ((HHGear^.State and gstHHDriven) = 0)
or (CheckGearDrowning(HHGear)) then
- begin
+ begin
PlaySound(sndRopeRelease);
DeleteMe;
exit
- end;
-
- if (Gear^.Message and gm_Left <> 0) then HHGear^.dX := HHGear^.dX - _0_0002
+ end;
+
+ if (Gear^.Message and gmLeft <> 0) then HHGear^.dX := HHGear^.dX - _0_0002
else
- if (Gear^.Message and gm_Right <> 0) then HHGear^.dX := HHGear^.dX + _0_0002;
+ if (Gear^.Message and gmRight <> 0) then HHGear^.dX := HHGear^.dX + _0_0002;
if not TestCollisionYwithGear(HHGear, 1) then HHGear^.dY := HHGear^.dY + cGravity;
@@ -1131,12 +1156,12 @@
tx := HHGear^.X;
ty := HHGear^.Y;
- if ((Gear^.Message and gm_Down) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
+ if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
or TestCollisionYwithGear(HHGear, hwSign(ropeDy))) then
Gear^.Elasticity := Gear^.Elasticity + _0_3;
- if ((Gear^.Message and gm_Up) <> 0) and (Gear^.Elasticity > _30) then
+ if ((Gear^.Message and gmUp) <> 0) and (Gear^.Elasticity > _30) then
if not (TestCollisionXwithGear(HHGear, -hwSign(ropeDx))
or TestCollisionYwithGear(HHGear, -hwSign(ropeDy))) then
Gear^.Elasticity := Gear^.Elasticity - _0_3;
@@ -1159,30 +1184,29 @@
ty := mdY * _0_3;
while len > _3 do
- begin
+ 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
- begin
+ if ((ly and LAND_HEIGHT_MASK) = 0) and ((lx and LAND_WIDTH_MASK) = 0) and (Land[ly, lx] <> 0) then
+ begin
ny := _1 / Distance(ropeDx, ropeDy);
// old rope pos
nx := ropeDx * ny;
ny := ropeDy * ny;
with RopePoints.ar[RopePoints.Count] do
- begin
+ begin
X := Gear^.X;
Y := Gear^.Y;
if RopePoints.Count = 0 then RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX);
b := (nx * HHGear^.dY) > (ny * HHGear^.dX);
dLen := len
- end;
+ end;
with RopePoints.rounded[RopePoints.Count] do
- begin
+ begin
X := hwRound(Gear^.X);
Y := hwRound(Gear^.Y);
- end;
+ end;
Gear^.X := Gear^.X + nx * len;
Gear^.Y := Gear^.Y + ny * len;
@@ -1192,23 +1216,24 @@
Gear^.Friction := Gear^.Friction - len;
haveDivided := true;
break
- end;
+ end;
nx := nx - tx;
ny := ny - ty;
+ lx := hwRound(nx);
+ ly := hwRound(ny);
// len := len - _0_3 // should be the same as increase step
len.QWordValue := len.QWordValue - _0_3.QWordValue;
- end;
+ end;
if not haveDivided then
if RopePoints.Count > 0 then // check whether the last dividing point could be removed
- begin
+ begin
tx := RopePoints.ar[Pred(RopePoints.Count)].X;
ty := RopePoints.ar[Pred(RopePoints.Count)].Y;
mdX := tx - Gear^.X;
mdY := ty - Gear^.Y;
- if RopePoints.ar[Pred(RopePoints.Count)].b xor (mdX * (ty - HHGear^.Y) > (tx - HHGear^.X
- ) * mdY) then
- begin
+ if RopePoints.ar[Pred(RopePoints.Count)].b xor (mdX * (ty - HHGear^.Y) > (tx - HHGear^.X) * mdY) then
+ begin
dec(RopePoints.Count);
Gear^.X := RopePoints.ar[RopePoints.Count].X;
Gear^.Y := RopePoints.ar[RopePoints.Count].Y;
@@ -1222,48 +1247,48 @@
HHGear^.X := Gear^.X - mdX * Gear^.Elasticity;
HHGear^.Y := Gear^.Y - mdY * Gear^.Elasticity;
- end
- end;
+ end
+ end;
haveCollision := false;
if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
- begin
+ begin
HHGear^.dX := -_0_6 * HHGear^.dX;
haveCollision := true
- end;
+ end;
if TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) then
- begin
+ begin
HHGear^.dY := -_0_6 * HHGear^.dY;
haveCollision := true
- end;
+ end;
if haveCollision
- and (Gear^.Message and (gm_Left or gm_Right) <> 0)
- and (Gear^.Message and (gm_Up or gm_Down) <> 0) then
- begin
+ and (Gear^.Message and (gmLeft or gmRight) <> 0)
+ and (Gear^.Message and (gmUp or gmDown) <> 0) then
+ begin
HHGear^.dX := SignAs(hwAbs(HHGear^.dX) + _0_2, HHGear^.dX);
HHGear^.dY := SignAs(hwAbs(HHGear^.dY) + _0_2, HHGear^.dY)
- end;
+ end;
len := hwSqr(HHGear^.dX) + hwSqr(HHGear^.dY);
if len > _0_64 then
- begin
+ begin
len := _0_8 / hwSqrt(len);
HHGear^.dX := HHGear^.dX * len;
HHGear^.dY := HHGear^.dY * len;
- end;
-
-
- if (Gear^.Message and gm_Attack) <> 0 then
+ end;
+
+
+ if (Gear^.Message and gmAttack) <> 0 then
if (Gear^.State and gsttmpFlag) <> 0 then
with PHedgehog(Gear^.Hedgehog)^ do
- begin
+ begin
PlaySound(sndRopeRelease);
- if Ammo^[CurSlot, CurAmmo].AmmoType <> amParachute then
+ if CurAmmoType <> amParachute then
WaitCollision
else
DeleteMe
- end
+ end
else
else
if (Gear^.State and gsttmpFlag) = 0 then
@@ -1359,14 +1384,14 @@
end;
if (Gear^.Elasticity > Gear^.Friction)
- or ((Gear^.Message and gm_Attack) = 0)
+ or ((Gear^.Message and gmAttack) = 0)
or ((HHGear^.State and gstHHDriven) = 0)
or (HHGear^.Damage > 0) then
begin
with PHedgehog(Gear^.Hedgehog)^.Gear^ do
begin
State := State and not gstAttacking;
- Message := Message and not gm_Attack
+ Message := Message and not gmAttack
end;
DeleteGear(Gear)
end
@@ -1432,6 +1457,49 @@
dec(Gear^.Timer);
end
else // gsttmpFlag = 0
+ if (TurnTimeLeft = 0) or ((GameFlags and gfInfAttack) <> 0) then Gear^.State := Gear^.State or gsttmpFlag;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepSMine(Gear: PGear);
+begin
+ DeleteCI(Gear);
+ // TODO: do real calculation?
+ if TestCollisionXwithGear(Gear, 2) or TestCollisionYwithGear(Gear, -2) or TestCollisionXwithGear(Gear, -2) or TestCollisionYwithGear(Gear, 2) then
+ begin
+ if (hwAbs(Gear^.dX) > _0) or (hwAbs(Gear^.dY) > _0) then
+ PlaySound(sndRopeAttach);
+ Gear^.dX:= _0;
+ Gear^.dY:= _0;
+ end
+ else
+ begin
+ doStepFallingGear(Gear);
+ AllInactive := false;
+ CalcRotationDirAngle(Gear);
+ end;
+ AddGearCI(Gear);
+
+ if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then
+ if ((Gear^.State and gstAttacking) = 0) then
+ begin
+ if ((GameTicks and $1F) = 0) then
+ if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then Gear^.State := Gear^.State or
+ gstAttacking
+ end
+ else // gstAttacking <> 0
+ begin
+ AllInactive := false;
+ if (Gear^.Timer and $FF) = 0 then PlaySound(sndMineTick);
+ if Gear^.Timer = 0 then
+ begin
+ doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
+ DeleteGear(Gear);
+ exit
+ end;
+ dec(Gear^.Timer);
+ end
+ else // gsttmpFlag = 0
if TurnTimeLeft = 0 then Gear^.State := Gear^.State or gsttmpFlag;
end;
@@ -1542,14 +1610,14 @@
k := Gear^.Kind;
exBoom := false;
- if (Gear^.Message and gm_Destroy) > 0 then
+ if (Gear^.Message and gmDestroy) > 0 then
begin
DeleteGear(Gear);
FreeActionsList;
SetAllToActive;
// something (hh, mine, etc...) could be on top of the case
with CurrentHedgehog^ do
- if Gear <> nil then Gear^.Message := Gear^.Message and not (gm_LJump or gm_HJump);
+ if Gear <> nil then Gear^.Message := Gear^.Message and not (gmLJump or gmHJump);
exit
end;
@@ -1718,6 +1786,7 @@
var
gX,gY,i: LongInt;
sticky: Boolean;
+ vgt: PVisualGear;
begin
sticky:= (Gear^.State and gsttmpFlag) <> 0;
if not sticky then AllInactive := false;
@@ -1725,6 +1794,20 @@
if not TestCollisionYwithGear(Gear, 1) then
begin
AllInactive := false;
+
+ if ((GameTicks mod 100) = 0) then
+ begin
+ vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire);
+ 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;
+
+
if Gear^.dX.QWordValue > _0_01.QWordValue then
Gear^.dX := Gear^.dX * _0_995;
Gear^.dY := Gear^.dY + cGravity;
@@ -1828,7 +1911,7 @@
HHGear: PGear;
begin
AllInactive := false;
- if ((Gear^.Message and gm_Destroy) <> 0) then
+ if ((Gear^.Message and gmDestroy) <> 0) then
begin
DeleteGear(Gear);
AfterAttack;
@@ -1895,7 +1978,7 @@
if TestCollisionYwithGear(HHGear, 1)
or ((HHGear^.State and gstHHDriven) = 0)
or CheckGearDrowning(HHGear)
- or ((Gear^.Message and gm_Attack) <> 0) then
+ or ((Gear^.Message and gmAttack) <> 0) then
begin
with HHGear^ do
begin
@@ -1913,10 +1996,10 @@
if not TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
HHGear^.X := HHGear^.X + cWindSpeed * 200;
- if (Gear^.Message and gm_Left) <> 0 then HHGear^.X := HHGear^.X - cMaxWindSpeed * 80
- else if (Gear^.Message and gm_Right) <> 0 then HHGear^.X := HHGear^.X + cMaxWindSpeed * 80;
- if (Gear^.Message and gm_Up) <> 0 then HHGear^.Y := HHGear^.Y - cGravity * 40
- else if (Gear^.Message and gm_Down) <> 0 then HHGear^.Y := HHGear^.Y + cGravity * 40;
+ 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;
HHGear^.Y := HHGear^.Y + cGravity * 100;
Gear^.X := HHGear^.X;
@@ -1934,7 +2017,7 @@
AfterAttack;
HHGear^.State := HHGear^.State and not (gstAttacking or gstAttacked or gstMoving);
- HHGear^.Message := HHGear^.Message and not gm_Attack;
+ HHGear^.Message := HHGear^.Message and not gmAttack;
Gear^.doStep := @doStepParachuteWork;
@@ -2034,7 +2117,7 @@
sprAmGirder, Gear^.State, true) then
begin
PlaySound(sndDenied);
- HHGear^.Message := HHGear^.Message and not gm_Attack;
+ HHGear^.Message := HHGear^.Message and not gmAttack;
HHGear^.State := HHGear^.State and not gstAttacking;
HHGear^.State := HHGear^.State or gstHHChooseTarget;
isCursorVisible := true;
@@ -2048,7 +2131,7 @@
end;
HHGear^.State := HHGear^.State and not (gstAttacking or gstAttacked);
- HHGear^.Message := HHGear^.Message and not gm_Attack;
+ HHGear^.Message := HHGear^.Message and not gmAttack;
TargetPoint.X := NoPointX
end;
@@ -2093,7 +2176,7 @@
TargetPoint.Y - SpritesData[sprHHTelepMask].Height div 2,
sprHHTelepMask, 0, false) then
begin
- HHGear^.Message := HHGear^.Message and not gm_Attack;
+ HHGear^.Message := HHGear^.Message and not gmAttack;
HHGear^.State := HHGear^.State and not gstAttacking;
HHGear^.State := HHGear^.State or gstHHChooseTarget;
DeleteGear(Gear);
@@ -2128,10 +2211,10 @@
begin
AllInactive := false;
- if ((Gear^.Message and not gm_Switch) <> 0) or (TurnTimeLeft = 0) then
+ if ((Gear^.Message and not gmSwitch) <> 0) or (TurnTimeLeft = 0) then
begin
HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
- Msg := Gear^.Message and not gm_Switch;
+ Msg := Gear^.Message and not gmSwitch;
DeleteGear(Gear);
OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^);
ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
@@ -2142,11 +2225,11 @@
exit
end;
- if (Gear^.Message and gm_Switch) <> 0 then
+ if (Gear^.Message and gmSwitch) <> 0 then
begin
HHGear := CurrentHedgehog^.Gear;
- HHGear^.Message := HHGear^.Message and not gm_Switch;
- Gear^.Message := Gear^.Message and not gm_Switch;
+ HHGear^.Message := HHGear^.Message and not gmSwitch;
+ Gear^.Message := Gear^.Message and not gmSwitch;
State := HHGear^.State;
HHGear^.State := 0;
HHGear^.Active := false;
@@ -2185,7 +2268,7 @@
with HHGear^ do
begin
State := State and not gstAttacking;
- Message := Message and not gm_Attack
+ Message := Message and not gmAttack
end
end;
@@ -2236,6 +2319,9 @@
HHGear^.State := HHGear^.State or gstNoDamage;
DeleteCI(HHGear);
+ Gear^.X := HHGear^.X;
+ Gear^.Y := HHGear^.Y;
+
i := 2;
repeat
Gear^.X := Gear^.X + HHGear^.dX;
@@ -2417,7 +2503,7 @@
begin
Gear^.Tag := 0;
Gear^.X := Gear^.X + int2hwFloat(xx);
- if not TestCollisionYwithGear(Gear, yyn) then
+ if not TestCollisionY(Gear, yyn) then
begin
Gear^.Y := Gear^.Y + int2hwFloat(yyn);
NextAngle
@@ -2438,7 +2524,7 @@
Gear^.Timer := Gear^.Health*10;
Gear^.PortalCounter:= 0;
// This is not seconds, but at least it is *some* feedback
- if (Gear^.Health = 0) or ((Gear^.Message and gm_Attack) <> 0) then
+ if (Gear^.Health = 0) or ((Gear^.Message and gmAttack) <> 0) then
begin
FollowGear := Gear;
Gear^.RenderTimer := false;
@@ -2490,8 +2576,9 @@
AllInactive := false;
HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
- HHGear^.Message := HHGear^.Message and (not gm_Attack);
+ HHGear^.Message := HHGear^.Message and (not gmAttack);
DeleteCI(HHGear);
+ Gear^.IntersectGear:= nil;
FollowGear := Gear;
@@ -2607,7 +2694,7 @@
or (not TestCollisionYWithGear(Gear, hwSign(Gear^.dY))
and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)))
// CheckLandValue returns true if the type isn't matched
- or not CheckLandValue(hwRound(Gear^.Y), hwRound(Gear^.X), lfIndestructible) then
+ or not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible) then
begin
//out of time or exited ground
StopSound(Gear^.SoundChannel);
@@ -2702,7 +2789,7 @@
HHGear: PGear;
begin
HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
- HHGear^.Message := HHGear^.Message and not (gm_Up or gm_Down);
+ HHGear^.Message := HHGear^.Message and not (gmUp or gmDown);
HHGear^.State := HHGear^.State or gstNotKickable;
Gear^.doStep := @doStepBallgunWork
end;
@@ -2740,13 +2827,13 @@
end
else
begin
- if ((Gear^.Message and gm_Left) <> 0) then
+ if ((Gear^.Message and gmLeft) <> 0) then
begin
fChanged := true;
Gear^.Angle := (Gear^.Angle + (4096 - cAngleSpeed)) mod 4096
end;
- if ((Gear^.Message and gm_Right) <> 0) then
+ if ((Gear^.Message and gmRight) <> 0) then
begin
fChanged := true;
Gear^.Angle := (Gear^.Angle + cAngleSpeed) mod 4096
@@ -2776,15 +2863,15 @@
else
AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
- if ((HHGear^.Message and gm_Attack) <> 0) and (Gear^.Health <> 0) then
+ if ((HHGear^.Message and gmAttack) <> 0) and (Gear^.Health <> 0) then
begin
- HHGear^.Message := HHGear^.Message and not gm_Attack;
+ 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 gm_LJump) <> 0)
+ if ((HHGear^.Message and gmLJump) <> 0)
and ((Gear^.State and gsttmpFlag) = 0) then
begin
Gear^.State := Gear^.State or gsttmpFlag;
@@ -2847,7 +2934,7 @@
AfterAttack;
CurAmmoGear := nil;
- TurnTimeLeft := 14 * 125;
+ if (GameFlags and gfInfAttack) = 0 then TurnTimeLeft := 14 * 125;
if (TrainingFlags and tfRCPlane) <> 0 then
TurnTimeLeft := 0;
@@ -2874,37 +2961,71 @@
procedure doStepJetpackWork(Gear: PGear);
var
HHGear: PGear;
- fuel: LongInt;
+ fuel, i: LongInt;
move: hwFloat;
+ isUnderwater: Boolean;
+ bubble: PVisualGear;
begin
+ isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
+ if Gear^.Pos > 0 then dec(Gear^.Pos);
AllInactive := false;
HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
//dec(Gear^.Timer);
- move := _0_1;
+ move := _0_2;
fuel := 50;
-(*if (HHGear^.Message and gm_Precise) <> 0 then
+(*if (HHGear^.Message and gmPrecise) <> 0 then
begin
move:= _0_02;
fuel:= 5;
end;*)
- if (HHGear^.Message and gm_Up) <> 0 then
- begin
- if (not HHGear^.dY.isNegative) or (HHGear^.Y > -_256) then
- HHGear^.dY := HHGear^.dY - move;
- HHGear^.dY := HHGear^.dY - move;
- dec(Gear^.Health, fuel);
- Gear^.MsgParam := Gear^.MsgParam or gm_Up;
- Gear^.Timer := GameTicks
- end;
- if (HHGear^.Message and gm_Left) <> 0 then move.isNegative := true;
- if (HHGear^.Message and (gm_Left or gm_Right)) <> 0 then
- begin
- HHGear^.dX := HHGear^.dX + (move * _0_2);
- dec(Gear^.Health, fuel div 5);
- Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gm_Left or gm_Right));
- Gear^.Timer := GameTicks
- end;
+ if Gear^.Health > 0 then
+ begin
+ if (HHGear^.Message and gmUp) <> 0 then
+ begin
+ if (not HHGear^.dY.isNegative) or (HHGear^.Y > -_256) then
+ begin
+ if isUnderwater then
+ begin
+ HHGear^.dY := HHGear^.dY - (move * _0_7);
+ for i:= random(10)+10 downto 0 do
+ begin
+ bubble := AddVisualGear(hwRound(HHGear^.X) - 8 + random(16), hwRound(HHGear^.Y) + 16 + random(8), vgtBubble);
+ if bubble <> nil then bubble^.dY:= random(20)/10+0.1;
+ end
+ end
+ else HHGear^.dY := HHGear^.dY - move;
+ end;
+ dec(Gear^.Health, fuel);
+ Gear^.MsgParam := Gear^.MsgParam or gmUp;
+ Gear^.Timer := GameTicks
+ end;
+ move.isNegative := (HHGear^.Message and gmLeft) <> 0;
+ if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then
+ begin
+ HHGear^.dX := HHGear^.dX + (move * _0_1);
+ if isUnderwater then
+ begin
+ for i:= random(5)+5 downto 0 do
+ begin
+ bubble := AddVisualGear(hwRound(HHGear^.X)+random(8), hwRound(HHGear^.Y) - 8 + random(16), vgtBubble);
+ if bubble <> nil then
+ begin
+ bubble^.dX:= (random(10)/10 + 0.02) * -1;
+ if (move.isNegative) then
+ begin
+ bubble^.X := bubble^.X + 28;
+ bubble^.dX *= -1
+ end
+ else bubble^.X := bubble^.X - 28;
+ end;
+ end
+ end;
+ dec(Gear^.Health, fuel div 5);
+ Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight));
+ Gear^.Timer := GameTicks
+ end
+ end;
// erases them all at once :-/
if (Gear^.Timer <> 0) and (GameTicks - Gear^.Timer > 250) then
@@ -2915,16 +3036,16 @@
if Gear^.Health < 0 then Gear^.Health := 0;
if (GameTicks and $3F) = 0 then
- begin
+ begin
//AddCaption('Fuel: '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate);
if Gear^.Tex <> nil then FreeTexture(Gear^.Tex);
Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(round(Gear^.Health / 20)) +
'%', cWhiteColor, fntSmall)
- end;
-
- if HHGear^.Message and (gm_Attack or gm_Up or gm_Precise or gm_Left or gm_Right) <> 0 then Gear^
+ end;
+
+ if HHGear^.Message and (gmAttack or gmUp or gmPrecise or gmLeft or gmRight) <> 0 then Gear^
.State := Gear^.State and not gsttmpFlag;
- HHGear^.Message := HHGear^.Message and not (gm_Up or gm_Precise or gm_Left or gm_Right);
+ HHGear^.Message := HHGear^.Message and not (gmUp or gmPrecise or gmLeft or gmRight);
HHGear^.State := HHGear^.State or gstMoving;
Gear^.X := HHGear^.X;
@@ -2934,15 +3055,16 @@
if ((Gear^.State and gsttmpFlag) = 0) or (HHGear^.dY < _0) then doStepHedgehogMoving(HHGear);
- if (Gear^.Health = 0)
- or (HHGear^.Damage <> 0)
- or CheckGearDrowning(HHGear)
- or (TurnTimeLeft = 0)
- // allow brief ground touches - to be fair on this, might need another counter
- or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and TestCollisionYwithGear(
- HHGear, 1))
- or ((Gear^.Message and gm_Attack) <> 0) then
- begin
+ if // (Gear^.Health = 0)
+ (HHGear^.Damage <> 0)
+ //or CheckGearDrowning(HHGear)
+ or (cWaterLine + 512 < hwRound(HHGear^.Y))
+ or (TurnTimeLeft = 0)
+ // allow brief ground touches - to be fair on this, might need another counter
+ or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and TestCollisionYwithGear(
+ HHGear, 1))
+ or ((Gear^.Message and gmAttack) <> 0) then
+ begin
with HHGear^ do
begin
Message := 0;
@@ -2965,6 +3087,7 @@
var
HHGear: PGear;
begin
+ Gear^.Pos:= 0;
Gear^.doStep := @doStepJetpackWork;
HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
@@ -2973,7 +3096,7 @@
with HHGear^ do
begin
State := State and not gstAttacking;
- Message := Message and not (gm_Attack or gm_Up or gm_Precise or gm_Left or gm_Right);
+ Message := Message and not (gmAttack or gmUp or gmPrecise or gmLeft or gmRight);
if (dY < _0_1) and (dY > -_0_1) then
begin
Gear^.State := Gear^.State or gsttmpFlag;
@@ -3004,12 +3127,12 @@
begin
HHGear := CurrentHedgehog^.Gear;
- move := _0_1;
+ move := _0_2;
fuel := 50;
if Gear^.Pos > 0 then
dec(Gear^.Pos, 1)
- else if (HHGear^.Message and (gm_Left or gm_Right or gm_Up)) <> 0 then
+ else if (HHGear^.Message and (gmLeft or gmRight or gmUp)) <> 0 then
Gear^.Pos := 500;
if HHGear^.dX.isNegative then
@@ -3017,20 +3140,19 @@
else
Gear^.Tag := 1;
- if (HHGear^.Message and gm_Up) <> 0 then
+ if (HHGear^.Message and gmUp) <> 0 then
begin
if (not HHGear^.dY.isNegative) or (HHGear^.Y > -_256) then
HHGear^.dY := HHGear^.dY - move;
- HHGear^.dY := HHGear^.dY - move;
dec(Gear^.Health, fuel);
- Gear^.MsgParam := Gear^.MsgParam or gm_Up;
+ Gear^.MsgParam := Gear^.MsgParam or gmUp;
end;
- if (HHGear^.Message and gm_Left) <> 0 then move.isNegative := true;
- if (HHGear^.Message and (gm_Left or gm_Right)) <> 0 then
+ if (HHGear^.Message and gmLeft) <> 0 then move.isNegative := true;
+ if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then
begin
- HHGear^.dX := HHGear^.dX + (move * _0_2);
+ HHGear^.dX := HHGear^.dX + (move * _0_1);
dec(Gear^.Health, fuel div 5);
- Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gm_Left or gm_Right));
+ Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight));
end;
if Gear^.Health < 0 then Gear^.Health := 0;
@@ -3038,9 +3160,9 @@
for i:= ((500-Gear^.Health) div 250) downto 0 do
AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFeather);
- if (HHGear^.Message and gm_Attack <> 0) then
+ if (HHGear^.Message and gmAttack <> 0) then
begin
- HHGear^.Message := HHGear^.Message and not gm_Attack;
+ HHGear^.Message := HHGear^.Message and not gmAttack;
if Gear^.FlightTime > 0 then
begin
AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) + 32, gtEgg, 0, Gear^.dX * _0_5, Gear^.dY, 0)
@@ -3050,9 +3172,9 @@
end;
end;
- if HHGear^.Message and (gm_Up or gm_Precise or gm_Left or gm_Right) <> 0 then
+ if HHGear^.Message and (gmUp or gmPrecise or gmLeft or gmRight) <> 0 then
Gear^.State := Gear^.State and not gsttmpFlag;
- HHGear^.Message := HHGear^.Message and not (gm_Up or gm_Precise or gm_Left or gm_Right);
+ HHGear^.Message := HHGear^.Message and not (gmUp or gmPrecise or gmLeft or gmRight);
HHGear^.State := HHGear^.State or gstMoving;
Gear^.X := HHGear^.X;
@@ -3069,7 +3191,7 @@
// allow brief ground touches - to be fair on this, might need another counter
or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and TestCollisionYwithGear(
HHGear, 1))
- or ((Gear^.Message and gm_Attack) <> 0) then
+ or ((Gear^.Message and gmAttack) <> 0) then
begin
with HHGear^ do
begin
@@ -3105,7 +3227,7 @@
exit
end;
HHGear := CurrentHedgehog^.Gear;
- HHGear^.Message := HHGear^.Message and not (gm_Up or gm_Precise or gm_Left or gm_Right);
+ HHGear^.Message := HHGear^.Message and not (gmUp or gmPrecise or gmLeft or gmRight);
if abs(hwRound(HHGear^.Y - Gear^.Y)) > 32 then
begin
if Gear^.Timer = 0 then
@@ -3158,7 +3280,7 @@
with HHGear^ do
begin
State := State and not gstAttacking;
- Message := Message and not (gm_Attack or gm_Up or gm_Precise or gm_Left or gm_Right)
+ Message := Message and not (gmAttack or gmUp or gmPrecise or gmLeft or gmRight)
end
end;
@@ -3176,7 +3298,7 @@
if (Gear^.State and gstCollision) <> 0 then
begin
- doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 11, EXPLPoisoned, $C000FFC0);
+ doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 11, EXPLPoisoned, $C0E0FFE0);
PlaySound(sndEggBreak);
AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
vg := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
@@ -3196,22 +3318,23 @@
////////////////////////////////////////////////////////////////////////////////
procedure doPortalColorSwitch();
-var
- flags: LongWord;
+var flags: LongWord;
+ CurWeapon: PAmmo;
begin
if (CurrentHedgehog <> nil)
and (CurrentHedgehog^.Gear <> nil)
- and ((CurrentHedgehog^.Gear^.Message and gm_Switch) <> 0) then
+ and ((CurrentHedgehog^.Gear^.Message and gmSwitch) <> 0) then
With CurrentHedgehog^ do
- if (Ammo^[CurSlot, CurAmmo].AmmoType = amPortalGun) then
+ if (CurAmmoType = amPortalGun) then
begin
- CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and not gm_Switch;
-
- flags := Ammo^[CurSlot, CurAmmo].Timer and not 2;
+ CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and not gmSwitch;
+
+ CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
+ flags := CurWeapon^.Timer and not 2;
if (flags and 1) = 0 then
- Ammo^[CurSlot, CurAmmo].Timer := flags or 1
+ CurWeapon^.Timer := flags or 1
else
- Ammo^[CurSlot, CurAmmo].Timer := flags and not 1;
+ CurWeapon^.Timer := flags and not 1;
end;
end;
@@ -3219,7 +3342,7 @@
var
iterator, conPortal: PGear;
s, acptRadius, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed: hwFloat;
- noTrap, hasdxy: Boolean;
+ hasdxy: Boolean;
begin
doPortalColorSwitch();
@@ -3378,13 +3501,13 @@
{ // breaks (some) loops
if Distance(iterator^.dX, iterator^.dY) > _0_96 then
- begin
+ begin
iterator^.dX := iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX);
iterator^.dY := iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY);
s := _0_96 / Distance(iterator^.dX, iterator^.dY);
iterator^.dX := s * iterator^.dX;
iterator^.dY := s * iterator^.dX;
- end;
+ end;
}
end;
end;
@@ -3397,20 +3520,24 @@
procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean);
var
flags: LongWord;
+ CurWeapon: PAmmo;
begin
if CurrentHedgehog <> nil then
- With CurrentHedgehog^ do
- if (Ammo^[CurSlot, CurAmmo].AmmoType = amPortalGun) then
+ with CurrentHedgehog^ do
begin
- flags := Ammo^[CurSlot, CurAmmo].Timer;
+ 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;
- Ammo^[CurSlot, CurAmmo].Timer := flags and not 2;
+ CurWeapon^.Timer := flags and not 2;
// make the ball visible
+ end
end;
if destroyGear then oldPortal^.Timer:= 0;
@@ -3472,6 +3599,7 @@
var
iterator: PGear;
s: hwFloat;
+ CurWeapon: PAmmo;
begin
s:= Distance (newPortal^.dX, newPortal^.dY);
@@ -3488,6 +3616,7 @@
if CurrentHedgehog <> nil then
With CurrentHedgehog^ do
begin
+ CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
// let's save the HH's dX's direction so we can decide where the "top" of the portal hole
newPortal^.Elasticity.isNegative := CurrentHedgehog^.Gear^.dX.isNegative;
// when doing a backjump the dx is the opposite of the facing direction
@@ -3495,10 +3624,10 @@
newPortal^.Elasticity.isNegative := not newPortal^.Elasticity.isNegative;
// make portal gun look unloaded
- Ammo^[CurSlot, CurAmmo].Timer := Ammo^[CurSlot, CurAmmo].Timer or 2;
+ CurWeapon^.Timer := CurWeapon^.Timer or 2;
// set portal to the currently chosen color
- if ((Ammo^[CurSlot, CurAmmo].Timer and 1) <> 0) then
+ if ((CurWeapon^.Timer and 1) <> 0) then
newPortal^.Tag := newPortal^.Tag or 2;
iterator := GearsList;
@@ -3531,10 +3660,11 @@
procedure doStepPiano(Gear: PGear);
var
r0, r1: LongInt;
+ odY: hwFloat;
begin
AllInactive := false;
if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and ((CurrentHedgehog^.Gear^.
- Message and gm_Slot) <> 0) then
+ Message and gmSlot) <> 0) then
begin
case CurrentHedgehog^.Gear^.MsgParam of
0: PlaySound(sndPiano0);
@@ -3547,14 +3677,15 @@
7: PlaySound(sndPiano7);
else PlaySound(sndPiano8);
end;
+ AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote);
CurrentHedgehog^.Gear^.MsgParam := 0;
- CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and not gm_Slot;
+ CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and not gmSlot;
end;
- if ((Gear^.Pos = 3) and ((GameFlags and gfSolidLand) <> 0)) or (Gear^.Pos = 20) then
- // bounce up to 20 times (3 times on gameflagged solid land) before dropping past landscape
+ if (*((Gear^.Pos = 3) and ((GameFlags and gfSolidLand) <> 0)) or*) (Gear^.Pos = 5) then
+ // bounce up to 10 times (3 times on gameflagged solid land) before dropping past landscape
begin
- Gear^.dY := Gear^.dY + cGravity * 3;
+ Gear^.dY := Gear^.dY + cGravity * 2;
Gear^.Y := Gear^.Y + Gear^.dY;
CheckGearDrowning(Gear);
if (Gear^.State and gstDrowning) <> 0 then
@@ -3565,13 +3696,15 @@
CurrentHedgehog^.Gear^.Active := true;
CurrentHedgehog^.Gear^.X := Gear^.X;
CurrentHedgehog^.Gear^.Y := int2hwFloat(cWaterLine+cVisibleWater)+_128;
- CurrentHedgehog^.Unplaced := false
+ CurrentHedgehog^.Unplaced := false;
+ TurnTimeLeft:= 0
end;
ResumeMusic
end;
exit
end;
+ odY:= Gear^.dY;
doStepFallingGear(Gear);
if (Gear^.State and gstDrowning) <> 0 then
@@ -3582,7 +3715,8 @@
CurrentHedgehog^.Gear^.Active := true;
CurrentHedgehog^.Gear^.X := Gear^.X;
CurrentHedgehog^.Gear^.Y := int2hwFloat(cWaterLine+cVisibleWater)+_128;
- CurrentHedgehog^.Unplaced := false
+ CurrentHedgehog^.Unplaced := false;
+ TurnTimeLeft:= 0
end;
ResumeMusic
end
@@ -3593,7 +3727,9 @@
doMakeExplosion(hwRound(Gear^.X) - 30 - r0, hwRound(Gear^.Y) + 40, 40 + r1, 0);
doMakeExplosion(hwRound(Gear^.X) + 30 + r1, hwRound(Gear^.Y) + 40, 40 + r0, 0);
doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 80 + r0, EXPLAutoSound);
- Gear^.dY := -_1;
+ for r0:= 0 to 4 do
+ AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote);
+ Gear^.dY := odY * -1 + cGravity * 2;
Gear^.Pos := Gear^.Pos + 1;
end
else
@@ -3754,12 +3890,12 @@
if (GameTicks and $FF) = 0 then
begin
- if (HHGear^.Message and gm_Right) <> 0 then
+ if (HHGear^.Message and gmRight) <> 0 then
begin
if HHGear^.dX.isNegative and (Gear^.Tag < 20) then inc(Gear^.Tag)
else if Gear^.Tag > 5 then dec(Gear^.Tag);
end
- else if (HHGear^.Message and gm_Left) <> 0 then
+ else if (HHGear^.Message and gmLeft) <> 0 then
begin
if HHGear^.dX.isNegative and (Gear^.Tag > 5) then dec(Gear^.Tag)
else if Gear^.Tag < 20 then inc(Gear^.Tag);
@@ -3807,9 +3943,230 @@
HHGear: PGear;
begin
HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
- HHGear^.Message := HHGear^.Message and not (gm_Up or gm_Down or gm_Left or gm_Right);
+ HHGear^.Message := HHGear^.Message and not (gmUp or gmDown or gmLeft or gmRight);
HHGear^.State := HHGear^.State or gstNotKickable;
Gear^.doStep := @doStepFlamethrowerWork
end;
-
+procedure doStepPoisonCloud(Gear: PGear);
+begin
+ if Gear^.Timer = 0 then
+ begin
+ DeleteGear(Gear);
+ exit
+ end;
+ dec(Gear^.Timer);
+ Gear^.X:= Gear^.X + Gear^.dX;
+ Gear^.Y:= Gear^.Y + Gear^.dY;
+ Gear^.dX := Gear^.dX + cWindSpeed / 4;
+ Gear^.dY := Gear^.dY + cGravity / 100;
+ if (GameTicks mod 250) = 0 then
+ doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, EXPLDontDraw or EXPLNoGfx or EXPLNoDamage or EXPLDoNotTouchAny or EXPLPoisoned);
+ AllInactive:= false;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHammer(Gear: PGear);
+var HHGear, tmp, tmp2: PGear;
+ t: PGearArray;
+ i: LongInt;
+begin
+HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
+HHGear^.State:= HHGear^.State or gstNoDamage;
+DeleteCI(HHGear);
+
+t:= CheckGearsCollision(Gear);
+
+for i:= 5 downto 0 do
+ AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
+
+i:= t^.Count;
+while i > 0 do
+ begin
+ dec(i);
+ tmp:= t^.ar[i];
+ if (tmp^.State and gstNoDamage) = 0 then
+ if (tmp^.Kind = gtHedgehog) then
+ begin
+ //tmp^.State:= tmp^.State or gstFlatened;
+ ApplyDamage(tmp, tmp^.Health div 3, dsUnknown);
+ //DrawTunnel(tmp^.X, tmp^.Y - _1, _0, _0_5, cHHRadius * 6, cHHRadius * 3);
+ tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0);
+ tmp2^.Hedgehog:= tmp^.Hedgehog;
+ SetAllToActive
+ end
+ else
+ begin
+ end
+ end;
+
+HHGear^.State:= HHGear^.State and not gstNoDamage;
+Gear^.Timer:= 250;
+Gear^.doStep:= @doStepIdle
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHammerHitWork(Gear: PGear);
+var
+ i, ei: LongInt;
+ HHGear: PGear;
+begin
+ AllInactive := false;
+ HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+ dec(Gear^.Timer);
+ if (HHGear = nil) or (Gear^.Timer = 0) or ((Gear^.Message and gmDestroy) <> 0) then
+ begin
+ DeleteGear(Gear);
+ exit
+ end;
+
+ if (Gear^.Timer mod 5) = 0 then
+ begin
+ 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));
+ while i <= ei do
+ begin
+ DrawExplosion(i, hwRound(Gear^.Y) + 3, 3);
+ inc(i, 1)
+ end;
+
+ if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9)
+ , lfIndestructible) then
+ begin
+ Gear^.X := Gear^.X + Gear^.dX;
+ Gear^.Y := Gear^.Y + _1_9;
+ end;
+ SetAllHHToActive;
+ end;
+ if TestCollisionYwithGear(Gear, 1) then
+ begin
+ Gear^.dY := _0;
+ SetLittle(HHGear^.dX);
+ HHGear^.dY := _0;
+ end
+ else
+ begin
+ Gear^.dY := Gear^.dY + cGravity;
+ Gear^.Y := Gear^.Y + Gear^.dY;
+ if hwRound(Gear^.Y) > cWaterLine then Gear^.Timer := 1
+ end;
+
+ Gear^.X := Gear^.X + HHGear^.dX;
+ HHGear^.X := Gear^.X;
+ HHGear^.Y := Gear^.Y - int2hwFloat(cHHRadius);
+end;
+
+procedure doStepHammerHit(Gear: PGear);
+var
+ i, y: LongInt;
+ ar: TRangeArray;
+ HHGear: PGear;
+begin
+ i := 0;
+ HHGear := PHedgehog(Gear^.Hedgehog)^.Gear;
+
+ y := hwRound(Gear^.Y) - cHHRadius * 2;
+ while y < hwRound(Gear^.Y) do
+ begin
+ ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
+ ar[i].Right := hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
+ inc(y, 2);
+ inc(i)
+ end;
+
+ DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius * 2, 2, Pred(i));
+ Gear^.dY := HHGear^.dY;
+ DeleteCI(HHGear);
+
+ doStepHammerHitWork(Gear);
+ Gear^.doStep := @doStepHammerHitWork
+end;
+
+
+procedure doStepResurrectorWork(Gear: PGear);
+var
+ graves: TPGearArray;
+ resgear: PGear;
+ hh: PHedgehog;
+ i: LongInt;
+begin
+ AllInactive := false;
+ hh := PHedgehog(Gear^.Hedgehog);
+ RenderHealth(hh^);
+ DrawCentered(hwRound(Gear^.X) + WorldDx, hwRound(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);
+
+ doStepHedgehogMoving(hh^.Gear);
+
+ if ((Gear^.Message and gmUp) <> 0) then begin
+ if (GameTicks and $F) <> 0 then exit;
+ end else begin
+ if (GameTicks and $1FF) <> 0 then exit;
+ end;
+
+ graves := GearsNear(hh^.Gear, gtGrave, Gear^.Radius);
+
+ if Length(graves) = 0 then begin
+ StopSound(Gear^.SoundChannel);
+ Gear^.Timer := 250;
+ Gear^.doStep := @doStepIdle;
+ exit;
+ end;
+
+ if ((Gear^.Message and gmAttack) <> 0) and (hh^.Gear^.Health > 0) then begin
+ i := getRandom(Length(graves));
+ dec(hh^.Gear^.Health);
+ inc(graves[i]^.Health);
+{-for i:= 0 to High(graves) do begin
+ if hh^.Gear^.Health > 0 then begin
+ dec(hh^.Gear^.Health);
+ inc(graves[i]^.Health);
+ end;
+ end; -}
+ end else begin
+ // now really resurrect the hogs with the hp saved in the graves
+ for i:= 0 to High(graves) do begin
+ if graves[i]^.Health > 0 then begin
+ resgear := AddGear(hwRound(graves[i]^.X), hwRound(graves[i]^.Y),
+ gtHedgehog, gstWait, _0, _0, 0);
+ resgear^.Hedgehog := graves[i]^.Hedgehog;
+ resgear^.Health := graves[i]^.Health;
+ PHedgehog(graves[i]^.Hedgehog)^.Gear := resgear;
+ DeleteGear(graves[i]);
+ RenderHealth(PHedgehog(resgear^.Hedgehog)^);
+ RecountTeamHealth(Phedgehog(resgear^.Hedgehog)^.Team);
+ end;
+ end;
+ StopSound(Gear^.SoundChannel);
+ Gear^.Timer := 250;
+ Gear^.doStep := @doStepIdle;
+ end;
+end;
+
+procedure doStepResurrector(Gear: PGear);
+var
+ graves: TPGearArray;
+ hh: PHedgehog;
+ i: LongInt;
+begin
+ AllInactive := false;
+ hh := PHedgehog(Gear^.Hedgehog);
+ graves := GearsNear(hh^.Gear, gtGrave, Gear^.Radius);
+
+ if Length(graves) > 0 then begin
+ for i:= 0 to High(graves) do begin
+ PHedgehog(graves[i]^.Hedgehog)^.Gear := nil;
+ graves[i]^.Health := 0;
+ end;
+ Gear^.doStep := @doStepResurrectorWork;
+ end else begin
+ StopSound(Gear^.SoundChannel);
+ Gear^.Timer := 250;
+ Gear^.doStep := @doStepIdle;
+ end;
+end;
+
--- a/hedgewars/GearDrawing.inc Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/GearDrawing.inc Wed Oct 27 14:02:20 2010 +0200
@@ -6,6 +6,7 @@
defaultPos, HatVisible: boolean;
VertexBuffer: array [0..1] of TVertex2f;
HH: PHedgehog;
+ CurWeapon: PAmmo;
begin
HH:= PHedgehog(Gear^.Hedgehog);
if HH^.Unplaced then exit;
@@ -14,6 +15,9 @@
if (Gear^.State and gstHHDeath) <> 0 then
begin
DrawSprite(sprHHDeath, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 26 + WorldDy, Gear^.Pos);
+ Tint(HH^.Team^.Clan^.Color);
+ DrawSprite(sprHHDeath, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 26 + WorldDy, Gear^.Pos + 8);
+ Tint($FF, $FF, $FF, $FF);
exit
end
else if (Gear^.State and gstHHGone) <> 0 then
@@ -80,8 +84,8 @@
dy:= -Cos(Gear^.Angle * pi / cMaxAngle);
if cLaserSighting then
begin
- lx:= GetLaunchX(HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].AmmoType, hwSign(Gear^.dX) * m, Gear^.Angle);
- ly:= GetLaunchY(HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].AmmoType, Gear^.Angle);
+ lx:= GetLaunchX(HH^.CurAmmoType, hwSign(Gear^.dX) * 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
@@ -139,8 +143,8 @@
end;
end;
// draw crosshair
- cx:= Round(hwRound(Gear^.X) + dx * 80 + GetLaunchX(HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].AmmoType, hwSign(Gear^.dX) * m, Gear^.Angle));
- cy:= Round(hwRound(Gear^.Y) + dy * 80 + GetLaunchY(HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].AmmoType, Gear^.Angle));
+ cx:= Round(hwRound(Gear^.X) + dx * 80 + GetLaunchX(HH^.CurAmmoType, hwSign(Gear^.dX) * 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,
hwSign(Gear^.dX) * (Gear^.Angle * 180.0) / cMaxAngle);
@@ -195,7 +199,7 @@
begin
DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, sx, sy, 0, i, 32, 32,
i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle);
- if HatTex^.w > 32 then
+ if HatTex^.w > 64 then
begin
Tint(HH^.Team^.Clan^.Color);
DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, sx, sy, 32, i, 32, 32,
@@ -225,7 +229,7 @@
hwSign(Gear^.dX),
32,
32);
- if HatTex^.w > 32 then
+ if HatTex^.w > 64 then
begin
Tint(HH^.Team^.Clan^.Color);
DrawTextureF(HatTex,
@@ -264,6 +268,20 @@
0);
defaultPos:= false
end;
+ gtHammer: begin
+ DrawRotatedF(sprHammer,
+ sx,
+ sy,
+ 1,
+ hwSign(Gear^.dX),
+ 0);
+ defaultPos:= false
+ end;
+ gtResurrector: begin
+ DrawRotated(sprHandResurrector, hwRound(Gear^.X) + WorldDx,
+ hwRound(Gear^.Y) + WorldDy, 0, 0);
+ defaultPos := false;
+ end;
gtKamikaze: begin
if CurAmmoGear^.Pos = 0 then
DrawHedgehog(sx, sy,
@@ -332,7 +350,7 @@
defaultPos:= false
end else
- if (Gear^.Message and (gm_Left or gm_Right) <> 0) and (not isCursorVisible) then
+ if (Gear^.Message and (gmLeft or gmRight) <> 0) and (not isCursorVisible) then
begin
DrawHedgehog(sx, sy,
hwSign(Gear^.dX),
@@ -372,7 +390,8 @@
else aangle:= aangle+((240-aangle)*HH^.Timer/10);
dec(HH^.Timer)
end;
- amt:= CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].AmmoType;
+ amt:= CurrentHedgehog^.CurAmmoType;
+ CurWeapon:= GetAmmoEntry(HH^);
case amt of
amBazooka: DrawRotated(sprHandBazooka, hx, hy, hwSign(Gear^.dX), aangle);
amMortar: DrawRotated(sprHandMortar, hx, hy, hwSign(Gear^.dX), aangle);
@@ -383,10 +402,10 @@
amShotgun: DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle);
amDEagle: DrawRotated(sprHandDEagle, hx, hy, hwSign(Gear^.dX), aangle);
amSineGun: DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle);
- amPortalGun: if (HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].Timer and 2) <> 0 then // Add a new Hedgehog value instead of abusing timer?
+ amPortalGun: if (CurWeapon^.Timer and 2) <> 0 then // Add a new Hedgehog value instead of abusing timer?
DrawRotatedF(sprPortalGun, hx, hy, 0, hwSign(Gear^.dX), aangle)
else
- DrawRotatedF(sprPortalGun, hx, hy, 1+(HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].Timer and 1), hwSign(Gear^.dX), aangle);
+ DrawRotatedF(sprPortalGun, hx, hy, 1+(CurWeapon^.Timer and 1), hwSign(Gear^.dX), aangle);
amSniperRifle: DrawRotatedF(sprSniperRifle, hx, hy, 0, hwSign(Gear^.dX), aangle);
amBlowTorch: DrawRotated(sprHandBlowTorch, hx, hy, hwSign(Gear^.dX), aangle);
amCake: DrawRotated(sprHandCake, hx, hy, hwSign(Gear^.dX), aangle);
@@ -398,6 +417,7 @@
amHellishBomb: DrawRotated(sprHandHellish, hx, hy, hwSign(Gear^.dX), aangle);
amGasBomb: DrawRotated(sprHandCheese, hx, hy, hwSign(Gear^.dX), aangle);
amMine: DrawRotated(sprHandMine, hx, hy, hwSign(Gear^.dX), aangle);
+ amSMine: DrawRotated(sprHandSMine, hx, hy, hwSign(Gear^.dX), aangle);
amSeduction: DrawRotated(sprHandSeduction, hx, hy, hwSign(Gear^.dX), aangle);
amVampiric: DrawRotatedF(sprHandVamp, hx, hy, (RealTicks div 125) mod 4, hwSign(Gear^.dX), aangle);
amRCPlane: begin
@@ -416,6 +436,10 @@
end;
amBee: DrawRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, hwSign(Gear^.dX), aangle);
amFlamethrower: DrawRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, hwSign(Gear^.dX), aangle);
+ amResurrector: begin
+ DrawCircle(hwRound(Gear^.X), hwRound(Gear^.y), 100, 1.5, 0, 0,
+ $FF, $FF); // I'd rather not like to hardcore 100 here
+ end;
end;
case amt of
@@ -438,6 +462,12 @@
0,
hwSign(Gear^.dX),
0);
+ amHammer: DrawRotatedF(sprHammer,
+ sx,
+ sy,
+ 0,
+ hwSign(Gear^.dX),
+ 0);
else
DrawHedgehog(sx, sy,
hwSign(Gear^.dX),
@@ -525,7 +555,7 @@
hwSign(Gear^.dX),
32,
32);
- if HatTex^.w > 32 then
+ if HatTex^.w > 64 then
begin
Tint(HH^.Team^.Clan^.Color);
DrawTextureF(HatTex,
@@ -549,7 +579,7 @@
hwSign(Gear^.dX)*m,
32,
32);
- if HatTex^.w > 32 then
+ if HatTex^.w > 64 then
begin
Tint(HH^.Team^.Clan^.Color);
DrawTextureF(HatTex,
@@ -568,7 +598,7 @@
begin
(* if (CurAmmoGear = nil) then
begin
- amt:= CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].AmmoType;
+ amt:= CurrentHedgehog^.CurAmmoType;
case amt of
amJetpack: DrawSprite(sprJetpack, sx-32, sy-32, 0);
end
@@ -578,9 +608,12 @@
case CurAmmoGear^.Kind of
gtJetpack: begin
DrawSprite(sprJetpack, sx-32, sy-32, 0);
- if (CurAmmoGear^.MsgParam and gm_Up) <> 0 then DrawSprite(sprJetpack, sx-32, sy-32, 1);
- if (CurAmmoGear^.MsgParam and gm_Left) <> 0 then DrawSprite(sprJetpack, sx-32, sy-32, 2);
- if (CurAmmoGear^.MsgParam and gm_Right) <> 0 then DrawSprite(sprJetpack, sx-32, sy-32, 3);
+ 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;
@@ -692,6 +725,10 @@
DrawRotated(sprMineOff, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, Gear^.DirAngle)
else if Gear^.Health <> 0 then DrawRotated(sprMineOn, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, Gear^.DirAngle)
else DrawRotated(sprMineDead, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, Gear^.DirAngle);
+ gtSMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
+ DrawRotated(sprSMineOff, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, Gear^.DirAngle)
+ else if Gear^.Health <> 0 then DrawRotated(sprSMineOn, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, Gear^.DirAngle)
+ else DrawRotated(sprMineDead, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, Gear^.DirAngle);
gtCase: case Gear^.Pos of
posCaseAmmo : begin
i:= (GameTicks shr 6) mod 64;
@@ -727,7 +764,7 @@
gtDynamite: DrawSprite2(sprDynamite, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 25 + WorldDy, Gear^.Tag and 1, Gear^.Tag shr 1);
gtClusterBomb: DrawRotated(sprClusterBomb, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, Gear^.DirAngle);
gtCluster: DrawSprite(sprClusterParticle, hwRound(Gear^.X) - 8 + WorldDx, hwRound(Gear^.Y) - 8 + WorldDy, 0);
- gtFlame: DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, (GameTicks div 128 + LongWord(Gear^.Tag)) mod 8, 1, 16, 16);
+ gtFlame: DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, (GameTicks shr 7 + LongWord(Gear^.Tag)) mod 8, 1, 16, 16);
gtParachute: begin
DrawSprite(sprParachute, hwRound(Gear^.X) - 24 + WorldDx, hwRound(Gear^.Y) - 48 + WorldDy, 0);
DrawAltWeapon(Gear, hwRound(Gear^.X) + 1 + WorldDx, hwRound(Gear^.Y) - 3 + WorldDy)
@@ -795,6 +832,16 @@
end;
DrawRotatedTextureF(SpritesData[sprPiano].Texture, 1, 0, 0, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 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, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, 1, 22, 22, (RealTicks shr 36 + Gear^.UID * 100) mod 360);
+ Tint($FF, $FF, $FF, $FF)
+ end;
end;
if Gear^.RenderTimer and (Gear^.Tex <> nil) then DrawCentered(hwRound(Gear^.X) + 8 + WorldDx, hwRound(Gear^.Y) + 8 + WorldDy, Gear^.Tex);
Gear:= Gear^.NextGear
--- a/hedgewars/HHHandlers.inc Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/HHHandlers.inc Wed Oct 27 14:02:20 2010 +0200
@@ -40,37 +40,43 @@
end
end;
+// Shouldn't more of this ammo switching stuff be moved to uAmmos ?
procedure ChangeAmmo(Gear: PGear);
var slot, i: Longword;
+ ammoidx: LongInt;
begin
slot:= Gear^.MsgParam;
with PHedgehog(Gear^.Hedgehog)^ do
begin
- Gear^.Message:= Gear^.Message and not gm_Slot;
+ Gear^.Message:= Gear^.Message and not gmSlot;
+ ammoidx:= 0;
+ while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx);
if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
- ((MultiShootAttacks > 0) and ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) = 0)) or
+ ((MultiShootAttacks > 0) and (CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_NoRoundEndHint) = 0)) or
((Gear^.State and gstHHDriven) = 0) then exit;
- if ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(PHedgehog(Gear^.Hedgehog)^);
+ if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEndHint) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(PHedgehog(Gear^.Hedgehog)^);
MultiShootAttacks:= 0;
- Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
-
- if CurSlot = slot then
+ Gear^.Message:= Gear^.Message and not (gmLJump or gmHJump);
+
+ if Ammoz[CurAmmoType].Slot = slot then
begin
i:= 0;
repeat
- inc(CurAmmo);
- if (CurAmmo > cMaxSlotAmmoIndex) then
+ inc(ammoidx);
+ if (ammoidx > cMaxSlotAmmoIndex) then
begin
- CurAmmo:= 0;
inc(i);
- TryDo(i < 2, 'Engine bug: no ammo in current slot', true)
+ CurAmmoType:= amNothing;
+ ammoidx:= -1;
+ //TryDo(i < 2, 'Engine bug: no ammo in current slot', true)
end;
- until (Ammo^[slot, CurAmmo].Count > 0) and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, CurAmmo].AmmoType].SkipTurns)
- end else
+ until ((Ammo^[slot, ammoidx].Count > 0) and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, ammoidx].AmmoType].SkipTurns)) or (i = 1)
+ end
+ else
begin
i:= 0;
// check whether there is ammo in slot
@@ -78,31 +84,31 @@
and ((Ammo^[slot, i].Count = 0)
or (Team^.Clan^.TurnNumber <= Ammoz[Ammo^[slot, i].AmmoType].SkipTurns)) do inc(i);
- if i <= cMaxSlotAmmoIndex then
- begin
- CurSlot:= slot;
- CurAmmo:= i
- end
- end
+ if i <= cMaxSlotAmmoIndex then ammoidx:= i
+ else ammoidx:= -1
+ end;
+ if ammoidx >= 0 then CurAmmoType:= Ammo^[slot, ammoidx].AmmoType;
end
end;
procedure HHSetWeapon(Gear: PGear);
var t: LongInt;
weap: TAmmoType;
+ Hedgehog: PHedgehog;
begin
weap:= TAmmoType(Gear^.MsgParam);
+Hedgehog:= PHedgehog(Gear^.Hedgehog);
-if PHedgehog(Gear^.Hedgehog)^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
+if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
Gear^.MsgParam:= Ammoz[weap].Slot;
t:= cMaxSlotAmmoIndex;
-Gear^.Message:= Gear^.Message and not gm_Weapon;
+Gear^.Message:= Gear^.Message and not gmWeapon;
-with PHedgehog(Gear^.Hedgehog)^ do
- while (Ammo^[CurSlot, CurAmmo].AmmoType <> weap) and (t >= 0) do
+with Hedgehog^ do
+ while (CurAmmoType <> weap) and (t >= 0) do
begin
ChangeAmmo(Gear);
dec(t)
@@ -112,12 +118,14 @@
end;
procedure HHSetTimer(Gear: PGear);
+var CurWeapon: PAmmo;
begin
-Gear^.Message:= Gear^.Message and not gm_Timer;
+Gear^.Message:= Gear^.Message and not gmTimer;
+CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
with PHedgehog(Gear^.Hedgehog)^ do
- if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Timerable) <> 0 then
+ if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
begin
- Ammo^[CurSlot, CurAmmo].Timer:= 1000 * Gear^.MsgParam;
+ CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
with CurrentTeam^ do
ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
end;
@@ -127,9 +135,10 @@
procedure Attack(Gear: PGear);
var xx, yy, lx, ly: hwFloat;
tmpGear: PVisualGear;
- tmpGear2: PGear;
+ CurWeapon: PAmmo;
begin
bShowFinger:= false;
+CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
with Gear^,
PHedgehog(Gear^.Hedgehog)^ do
begin
@@ -138,12 +147,12 @@
(((State and gstMoving) = 0) or
// Allow attacks while moving on ammo with AltAttack
((CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)) or
- ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_AttackInMove) <> 0)) and
- ((TargetPoint.X <> NoPointX) or ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NeedTarget) = 0)) then
+ ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AttackInMove) <> 0)) and
+ ((TargetPoint.X <> NoPointX) or ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) = 0)) then
begin
State:= State or gstAttacking;
- if Power = cMaxPower then Message:= Message and not gm_Attack
- else if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) = 0 then Message:= Message and not gm_Attack
+ if Power = cMaxPower then Message:= Message and not gmAttack
+ else if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) = 0 then Message:= Message and not gmAttack
else begin
if Power = 0 then
begin
@@ -152,9 +161,9 @@
end;
inc(Power)
end;
- if ((Message and gm_Attack) <> 0) then exit;
+ if ((Message and gmAttack) <> 0) then exit;
- if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0 then
+ if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0 then
begin
StopSound(sndThrowPowerUp);
PlaySound(sndThrowRelease);
@@ -163,17 +172,17 @@
xx:= SignAs(AngleSin(Angle), dX);
yy:= -AngleCos(Angle);
- lx:= X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(dX), Angle)));
- ly:= Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Angle)));
+ lx:= X + int2hwfloat(round(GetLaunchX(CurAmmoType, hwSign(dX), Angle)));
+ ly:= Y + int2hwfloat(round(GetLaunchY(CurAmmoType, Angle)));
if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then xx:= - xx;
- if Ammo^[CurSlot, CurAmmo].AttackVoice <> sndNone then
- PlaySound(Ammo^[CurSlot, CurAmmo].AttackVoice, CurrentTeam^.voicepack);
- case Ammo^[CurSlot, CurAmmo].AmmoType of
- amGrenade: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Bomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
+ if Ammoz[CurAmmoType].Ammo.AttackVoice <> sndNone then
+ PlaySound(Ammoz[CurAmmoType].Ammo.AttackVoice, CurrentTeam^.voicepack);
+ case CurAmmoType of
+ amGrenade: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Bomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
amMolotov: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
- amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
- amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
+ amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
+ amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
amBazooka: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Grenade, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
amBee: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtBee, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
amShotgun: begin
@@ -184,6 +193,7 @@
amSkip: ParseCommand('/skip', true);
amRope: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtRope, 0, xx, yy, 0);
amMine: AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000);
+ 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);
@@ -197,17 +207,24 @@
CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtWhip, 0, SignAs(_1, dX), - _0_8, 0);
PlaySound(sndWhipCrack)
end;
+ amHammer: begin
+ CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtHammer, 0, SignAs(_1, dX), - _0_8, 0);
+ PlaySound(sndWhack)
+ end;
amBaseballBat: begin
CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtShover, gsttmpFlag, xx * _0_5, yy * _0_5, 0);
PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
end;
- amParachute: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
- // we save Ammo^[CurSlot, CurAmmo].Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
- amAirAttack: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 0, _0, _0, 0);
- amMineStrike: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 1, _0, _0, 0);
+ amParachute: begin
+ CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
+ PlaySound(sndParachute)
+ end;
+ // we save CurWeapon^.Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
+ amAirAttack: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 0, _0, _0, 0);
+ amMineStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 1, _0, _0, 0);
amBlowTorch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
- amGirder: CurAmmoGear:= AddGear(0, 0, gtGirder, Ammo^[CurSlot, CurAmmo].Pos, _0, _0, 0);
- amTeleport: CurAmmoGear:= AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtTeleport, 0, _0, _0, 0);
+ amGirder: CurAmmoGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
+ amTeleport: CurAmmoGear:= AddGear(CurWeapon^.Pos, 0, gtTeleport, 0, _0, _0, 0);
amSwitch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
amMortar: begin
playSound(sndMortar);
@@ -220,9 +237,9 @@
amKamikaze: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtKamikaze, 0, xx * _0_5, yy * _0_5, 0);
amCake: CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 3, hwRound(ly), gtCake, 0, xx, _0, 0);
amSeduction: CurAmmoGear:= AddGear(hwRound(lx + xx * cHHRadius * 2), hwRound(ly + yy * cHHRadius * 2), gtSeduction, 0, xx * _0_4, yy * _0_4, 0);
- amWatermelon: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
+ amWatermelon: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
amHellishBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtHellishBomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
- amNapalm: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 2, _0, _0, 0);
+ amNapalm: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 2, _0, _0, 0);
amDrill: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtDrill, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
amBallgun: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtBallgun, 0, xx * _0_5, yy * _0_5, 0);
amJetpack: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtJetpack, 0, _0, _0, 0);
@@ -251,9 +268,14 @@
PauseMusic
end;
amFlamethrower: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower, 0, xx * _0_5, yy * _0_5, 0);
+ amResurrector: begin
+ CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly),
+ gtResurrector, 0, _0, _0, 0);
+ CurAmmoGear^.SoundChannel := LoopSound(sndResurrector);
+ end;
end;
- uStats.AmmoUsed(Ammo^[CurSlot, CurAmmo].AmmoType);
+ uStats.AmmoUsed(CurAmmoType);
if not (SpeechText = '') then
begin
@@ -269,56 +291,51 @@
Power:= 0;
if (CurAmmoGear <> nil)
- and (((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
+ and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
begin
- CurAmmoGear^.Ammo:= @(Ammo^[CurSlot, CurAmmo]);
- CurAmmoGear^.AmmoType:= CurAmmoGear^.Ammo^.AmmoType;
- Message:= Message or gm_Attack;
+ CurAmmoGear^.AmmoType:= CurAmmoType;
+ Message:= Message or gmAttack;
CurAmmoGear^.Message:= Message
end else begin
if not CurrentTeam^.ExtDriven and
- ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0) then SendIPC('a');
+ ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then SendIPC('a');
AfterAttack;
end
- end else Message:= Message and not gm_Attack;
+ end else Message:= Message and not gmAttack;
end
end;
procedure AfterAttack;
var s: shortstring;
+ a: TAmmoType;
begin
with CurrentHedgehog^.Gear^,
CurrentHedgehog^ do
begin
+ a:= CurAmmoType;
State:= State and not gstAttacking;
- if ((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_Effect) = 0 then
+ if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then
begin
Inc(MultiShootAttacks);
- if (Ammo^[CurSlot, CurAmmo].NumPerTurn >= MultiShootAttacks) then
+ if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks) then
begin
- s:= inttostr(Ammo^[CurSlot, CurAmmo].NumPerTurn - MultiShootAttacks + 1);
+ s:= inttostr(Ammoz[a].Ammo.NumPerTurn - MultiShootAttacks + 1);
AddCaption(format(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate);
end;
- if (Ammo^[CurSlot, CurAmmo].NumPerTurn >= MultiShootAttacks) or
+ if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks) or
((GameFlags and gfMultiWeapon) <> 0) then
begin
isInMultiShoot:= true
end
else
begin
- if ((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_NoRoundEndHint) = 0 then
- begin
- OnUsedAmmo(CurrentHedgehog^);
- TurnTimeLeft:= Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].TimeAfterTurn;
- State:= State or gstAttacked
- end
- else
- begin
- OnUsedAmmo(CurrentHedgehog^);
- ApplyAmmoChanges(CurrentHedgehog^)
- end
+ OnUsedAmmo(CurrentHedgehog^);
+ if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEndHint) = 0) and ((GameFlags and gfInfAttack) = 0) then
+ TurnTimeLeft:= Ammoz[a].TimeAfterTurn;
+ if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEndHint) = 0) then State:= State or gstAttacked;
+ if (Ammoz[a].Ammo.Propz and ammoprop_NoRoundEndHint) <> 0 then ApplyAmmoChanges(CurrentHedgehog^)
end;
end
else
@@ -326,7 +343,7 @@
OnUsedAmmo(CurrentHedgehog^);
ApplyAmmoChanges(CurrentHedgehog^);
end;
- AttackBar:= 0;
+ AttackBar:= 0
end
end;
@@ -397,7 +414,7 @@
i: LongInt;
vga: PVisualGear;
begin
-Gear^.Message:= gm_Destroy;
+Gear^.Message:= gmDestroy;
PlaySound(sndShotgunReload);
case Gear^.Pos of
posCaseUtility,
@@ -444,24 +461,26 @@
procedure HedgehogStep(Gear: PGear);
var PrevdX: LongInt;
+ CurWeapon: PAmmo;
begin
+CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
begin
if isCursorVisible then
with PHedgehog(Gear^.Hedgehog)^ do
- with Ammo^[CurSlot, CurAmmo] do
+ with CurWeapon^ do
begin
- if (Gear^.Message and gm_Left ) <> 0 then
+ if (Gear^.Message and gmLeft ) <> 0 then
Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
else
- if (Gear^.Message and gm_Right ) <> 0 then
+ if (Gear^.Message and gmRight ) <> 0 then
Pos:= (Pos + 1) mod Ammoz[AmmoType].PosCount
else exit;
StepTicks:= 200;
exit
end;
- if ((Gear^.Message and gm_Animate) <> 0) then
+ if ((Gear^.Message and gmAnimate) <> 0) then
begin
Gear^.Message:= 0;
Gear^.State:= Gear^.State or gstAnimation;
@@ -470,9 +489,9 @@
Gear^.Pos:= 0
end;
- if ((Gear^.Message and gm_LJump ) <> 0) then
+ if ((Gear^.Message and gmLJump ) <> 0) then
begin
- Gear^.Message:= Gear^.Message and not gm_LJump;
+ Gear^.Message:= Gear^.Message and not gmLJump;
DeleteCI(Gear);
if not TestCollisionYwithGear(Gear, -1) then
if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - _2 else
@@ -488,10 +507,10 @@
end;
end;
- if ((Gear^.Message and gm_HJump ) <> 0) then
+ if ((Gear^.Message and gmHJump ) <> 0) then
begin
DeleteCI(Gear);
- Gear^.Message:= Gear^.Message and not gm_HJump;
+ Gear^.Message:= Gear^.Message and not gmHJump;
Gear^.dY:= -_0_2;
SetLittle(Gear^.dX);
@@ -501,10 +520,10 @@
end;
PrevdX:= hwSign(Gear^.dX);
- if (Gear^.Message and gm_Left )<>0 then Gear^.dX:= -cLittle else
- if (Gear^.Message and gm_Right )<>0 then Gear^.dX:= cLittle else exit;
+ if (Gear^.Message and gmLeft )<>0 then Gear^.dX:= -cLittle else
+ if (Gear^.Message and gmRight )<>0 then Gear^.dX:= cLittle else exit;
- if (Gear^.Message and (gm_Left or gm_Right)) <> 0 then
+ if (Gear^.Message and (gmLeft or gmRight)) <> 0 then
begin
StepSoundTimer:= cHHStepTicks;
end;
@@ -534,7 +553,7 @@
or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
end;
- if (not cArtillery) and ((Gear^.Message and gm_Precise) = 0) and (not TestCollisionXwithGear(Gear, hwSign(Gear^.dX))) then
+ if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) and (not TestCollisionXwithGear(Gear, hwSign(Gear^.dX))) then
Gear^.X:= Gear^.X + SignAs(_1, Gear^.dX);
SetAllHHToActive;
@@ -578,22 +597,24 @@
var da: LongWord;
begin
with PHedgehog(Gear^.Hedgehog)^ do
- if (Ammo^[CurSlot, CurAmmo].AmmoType = amRope)
+ if (CurAmmoType = amRope)
and ((Gear^.State and (gstMoving or gstHHJumping)) = gstMoving) then da:= 2 else da:= 1;
-if (((Gear^.Message and gm_Precise) = 0) or ((GameTicks mod 5) = 1)) then
- if ((Gear^.Message and gm_Up) <> 0) and (Gear^.Angle >= CurMinAngle + da) then dec(Gear^.Angle, da)
+if (((Gear^.Message and gmPrecise) = 0) or ((GameTicks mod 5) = 1)) then
+ if ((Gear^.Message and gmUp) <> 0) and (Gear^.Angle >= CurMinAngle + da) then dec(Gear^.Angle, da)
else
- if ((Gear^.Message and gm_Down) <> 0) and (Gear^.Angle + da <= CurMaxAngle) then inc(Gear^.Angle, da)
+ if ((Gear^.Message and gmDown) <> 0) and (Gear^.Angle + da <= CurMaxAngle) then inc(Gear^.Angle, da)
end;
procedure doStepHedgehog(Gear: PGear); forward;
////////////////////////////////////////////////////////////////////////////////
procedure doStepHedgehogMoving(Gear: PGear);
-var isFalling: boolean;
+var isFalling, isUnderwater: boolean;
begin
-if Gear^.dX > _0_995 then Gear^.dX:= _0_995;
-if Gear^.dY > _0_995 then Gear^.dY:= _0_995;
+isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
+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
begin
Gear^.dY:= _0;
@@ -606,8 +627,10 @@
begin
if (Gear^.dY.isNegative) and TestCollisionYKick(Gear, -1) then Gear^.dY:= _0;
Gear^.State:= Gear^.State or gstMoving;
- Gear^.dY:= Gear^.dY + cGravity
- end else
+ if isUnderwater then Gear^.dY:= Gear^.dY + cGravity / _2
+ else Gear^.dY:= Gear^.dY + cGravity
+ end
+else
begin
if ((hwAbs(Gear^.dX) + hwAbs(Gear^.dY)) < _0_55)
and ((Gear^.State and gstHHJumping) <> 0) then SetLittle(Gear^.dX);
@@ -628,6 +651,12 @@
if (Gear^.State <> 0) then DeleteCI(Gear);
+if isUnderwater then
+ begin
+ Gear^.dY:= Gear^.dY * _0_999;
+ Gear^.dX:= Gear^.dX * _0_999;
+ end;
+
if (Gear^.State and gstMoving) <> 0 then
if TestCollisionXKick(Gear, hwSign(Gear^.dX)) then
if not isFalling then
@@ -697,7 +726,9 @@
procedure doStepHedgehogDriven(Gear: PGear);
var t: PGear;
wasJumping: boolean;
+ Hedgehog: PHedgehog;
begin
+Hedgehog:= PHedgehog(Gear^.Hedgehog);
if not isInMultiShoot then
AllInactive:= false
else
@@ -717,7 +748,7 @@
if (Gear^.State and gstAnimation) <> 0 then
begin
Gear^.Message:= 0;
- if (Gear^.Pos = Wavez[TWave(Gear^.Tag)].VoiceDelay) and (Gear^.Timer = 0) then PlaySound(Wavez[TWave(Gear^.Tag)].Voice, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+ if (Gear^.Pos = Wavez[TWave(Gear^.Tag)].VoiceDelay) and (Gear^.Timer = 0) then PlaySound(Wavez[TWave(Gear^.Tag)].Voice, Hedgehog^.Team^.voicepack);
inc(Gear^.Timer);
if Gear^.Timer = Wavez[TWave(Gear^.Tag)].Interval then
begin
@@ -733,10 +764,10 @@
or (StepTicks = cHHStepTicks)
or (CurAmmoGear <> nil) then // we are moving
begin
- with PHedgehog(Gear^.Hedgehog)^ do
+ with Hedgehog^ do
if (CurAmmoGear = nil)
and (Gear^.dY > _0_39)
- and (Ammo^[CurSlot, CurAmmo].AmmoType = amParachute) then Gear^.Message:= Gear^.Message or gm_Attack;
+ and (CurAmmoType = amParachute) then Gear^.Message:= Gear^.Message or gmAttack;
// check for case with ammo
t:= CheckGearNear(Gear, gtCase, 36, 36);
if t <> nil then
@@ -744,31 +775,33 @@
end;
if (CurAmmoGear = nil) then
- if (((Gear^.Message and gm_Attack) <> 0)
+ if (((Gear^.Message and gmAttack) <> 0)
or ((Gear^.State and gstAttacking) <> 0)) then
Attack(Gear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
else
-else with PHedgehog(Gear^.Hedgehog)^ do
- if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
- and ((Gear^.Message and gm_LJump) <> 0)
- and (((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_AltUse) <> 0) then
- begin
- Gear^.Message:= Gear^.Message and not gm_LJump;
- Attack(Gear)
- end;
+else
+ with Hedgehog^ do
+ if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
+ and ((Gear^.Message and gmLJump) <> 0)
+ and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+ begin
+ Gear^.Message:= Gear^.Message and not gmLJump;
+ Attack(Gear)
+ end;
if (CurAmmoGear = nil)
- or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) then
+ or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
+ or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_NoRoundEndHint) <> 0) then
begin
- if ((Gear^.Message and gm_Slot) <> 0) then
+ if ((Gear^.Message and gmSlot) <> 0) then
begin
ChangeAmmo(Gear);
- ApplyAmmoChanges(PHedgehog(Gear^.Hedgehog)^)
+ ApplyAmmoChanges(Hedgehog^)
end;
- if ((Gear^.Message and gm_Weapon) <> 0) then HHSetWeapon(Gear);
+ if ((Gear^.Message and gmWeapon) <> 0) then HHSetWeapon(Gear);
- if ((Gear^.Message and gm_Timer) <> 0) then HHSetTimer(Gear);
+ if ((Gear^.Message and gmTimer) <> 0) then HHSetTimer(Gear);
end;
if CurAmmoGear <> nil then
@@ -784,7 +817,7 @@
begin
wasJumping:= ((Gear^.State and gstHHJumping) <> 0);
- if ((Gear^.Message and gm_HJump) <> 0) and
+ if ((Gear^.Message and gmHJump) <> 0) and
wasJumping and
((Gear^.State and gstHHHJump) = 0) then
if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
@@ -792,10 +825,10 @@
Gear^.State:= Gear^.State or gstHHHJump;
Gear^.dY:= -_0_25;
if not cArtillery then Gear^.dX:= -SignAs(_0_02, Gear^.dX);
- PlaySound(sndJump2, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack)
+ PlaySound(sndJump2, Hedgehog^.Team^.voicepack)
end;
- Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
+ Gear^.Message:= Gear^.Message and not (gmLJump or gmHJump);
if (not cArtillery) and wasJumping and
TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
@@ -846,10 +879,14 @@
if not PHedgehog(Gear^.Hedgehog)^.Team^.hasGone then
begin
- Gear^.State:= Gear^.State or gstHHDeath;
- Gear^.doStep:= @doStepHedgehogDead;
- // Death message
- AddCaption(Format(GetEventString(eidDied), PHedgehog(Gear^.Hedgehog)^.Name), cWhiteColor, capgrpMessage);
+ if PHedgehog(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);
+ end;
end
else
begin
@@ -884,7 +921,7 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepHedgehog(Gear: PGear);
begin
-if (Gear^.Message and gm_Destroy) <> 0 then
+if (Gear^.Message and gmDestroy) <> 0 then
begin
DeleteGear(Gear);
exit
--- a/hedgewars/PascalExports.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/PascalExports.pas Wed Oct 27 14:02:20 2010 +0200
@@ -1,25 +1,35 @@
(*
- * PascalExports.pas
- * hwengine
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * 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
*
- * Created by Vittorio on 09/01/10.
- * Copyright 2009 __MyCompanyName__. All rights reserved.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*)
-
{$INCLUDE "options.inc"}
unit PascalExports;
interface
-uses uKeys, GLunit, uWorld, uMisc, uConsole, uTeams, uConsts, uChat, uGears, uSound, hwengine;
+uses uKeys, GLunit, uWorld, uMisc, uConsole, uTeams, uConsts, uChat,
+ uGears, uSound, hwengine, uAmmos, uLocale; // don't change the order!
{$INCLUDE "config.inc"}
+type PPByte = ^PByte;
implementation
-
{$IFDEF HWLIBRARY}
+var cZoomVal: GLfloat;
// retrieve protocol information
procedure HW_versionInfo(netProto: PShortInt; versionStr: PPChar); cdecl; export;
@@ -34,6 +44,17 @@
leftClick:= true;
end;
+procedure HW_ammoMenu; cdecl; export;
+begin
+ rightClick:= true;
+end;
+
+procedure HW_zoomSet(value: GLfloat); cdecl; export;
+begin
+ cZoomVal:= value;
+ ZoomValue:= value;
+end;
+
procedure HW_zoomIn; cdecl; export;
begin
if wheelDown = false then
@@ -48,15 +69,21 @@
procedure HW_zoomReset; cdecl; export;
begin
- middleClick:= true;
+ ZoomValue:= cZoomVal;
+ //middleClick:= true;
// center the camera at current hog
if CurrentHedgehog <> nil then
followGear:= CurrentHedgehog^.Gear;
end;
-procedure HW_ammoMenu; cdecl; export;
+function HW_zoomFactor: GLfloat; cdecl; export;
begin
- rightClick:= true;
+ exit( ZoomValue / cDefaultZoomLevel );
+end;
+
+function HW_zoomLevel: LongInt; cdecl; export;
+begin
+ exit( trunc((ZoomValue - cDefaultZoomLevel) / cZoomDelta) );
end;
procedure HW_walkingKeysUp; cdecl; export;
@@ -148,18 +175,6 @@
if closeFrontend then alsoShutdownFrontend:= true;
end;
-procedure HW_setLandscape(landscape: boolean); cdecl; export;
-begin
- if landscape then
- begin
- cOffsetY:= 0;
- end
- else
- begin
- cOffsetY:= 120;
- end;
-end;
-
procedure HW_setCursor(x,y: LongInt); cdecl; export;
begin
CursorPoint.X:= x;
@@ -172,14 +187,69 @@
y^:= CursorPoint.Y;
end;
-procedure HW_setPianoSound(snd: LongInt); cdecl; export;
-var CurSlot, CurAmmo: LongWord;
+function HW_isAmmoMenuOpen: boolean; cdecl; export;
+begin
+ exit(bShowAmmoMenu);
+end;
+
+function HW_isAmmoMenuNotAllowed: boolean; cdecl; export;
+begin;
+ exit ( (TurnTimeLeft = 0) or (not CurrentTeam^.ExtDriven and (((CurAmmoGear = nil) or ((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 );
+end;
+
+function HW_isWeaponRequiringClick: boolean; cdecl; export;
+begin
+ if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.BotLevel = 0) then
+ exit( (CurrentHedgehog^.Gear^.State and gstHHChooseTarget) <> 0 )
+ else
+ exit(false);
+end;
+
+function HW_isWeaponTimerable: boolean; cdecl; export;
begin
- CurSlot:= CurrentHedgehog^.CurSlot;
- CurAmmo:= CurrentHedgehog^.CurAmmo;
+ if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Ammo <> nil) and (CurrentHedgehog^.BotLevel = 0) then
+ exit( (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Timerable) <> 0)
+ else
+ exit(false);
+end;
+
+function HW_isWeaponSwitch: boolean cdecl; export;
+begin
+ if (CurAmmoGear <> nil) and (CurrentHedgehog^.BotLevel = 0) then
+ exit(CurAmmoGear^.AmmoType = amSwitch)
+ else
+ exit(false)
+end;
+
+function HW_isWeaponRope: boolean cdecl; export;
+begin
+ if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Ammo <> nil) and (CurrentHedgehog^.BotLevel = 0) then
+ exit (CurrentHedgehog^.CurAmmoType = amRope)
+ else
+ exit(false);
+end;
+
+procedure HW_setGrenadeTime(time: LongInt); cdecl; export;
+begin
+ ParseCommand('/timer ' + inttostr(time), true);
+end;
+
+procedure HW_setPianoSound(snd: LongInt); cdecl; export;
+begin
// this most likely won't work in network game
- if (CurrentHedgehog^.Ammo^[CurSlot, CurAmmo].AmmoType = amPiano) then
- case snd of
+ if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Ammo <> nil) and (CurrentHedgehog^.BotLevel = 0)
+ and (CurrentHedgehog^.CurAmmoType = amPiano) then
+ case snd of
0: PlaySound(sndPiano0);
1: PlaySound(sndPiano1);
2: PlaySound(sndPiano2);
@@ -192,46 +262,76 @@
end;
end;
-function HW_isAmmoOpen: boolean; cdecl; export;
+function HW_getWeaponNameByIndex(whichone: LongInt): PChar; cdecl; export;
+begin
+ exit (str2pchar(trammo[Ammoz[TAmmoType(whichone+1)].NameId]));
+end;
+
+function HW_getWeaponCaptionByIndex(whichone: LongInt): PChar; cdecl; export;
begin
- exit(bShowAmmoMenu);
+ exit (str2pchar(trammoc[Ammoz[TAmmoType(whichone+1)].NameId]));
+end;
+
+function HW_getWeaponDescriptionByIndex(whichone: LongInt): PChar; cdecl; export;
+begin
+ exit (str2pchar(trammod[Ammoz[TAmmoType(whichone+1)].NameId]));
end;
-function HW_isWeaponRequiringClick: boolean; cdecl; export;
+function HW_getNumberOfWeapons:LongInt; cdecl; export;
+begin
+ exit(ord(high(TAmmoType)));
+end;
+
+procedure HW_setWeapon(whichone: LongInt); cdecl; export;
begin
- if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) then
- exit( (CurrentHedgehog^.Gear^.State and gstHHChooseTarget) <> 0 )
- else
- exit(false);
+ if (not CurrentTeam^.ExtDriven) and (CurrentTeam^.Hedgehogs[0].BotLevel = 0) then
+ SetWeapon(TAmmoType(whichone+1));
+end;
+
+function HW_isWeaponAnEffect(whichone: LongInt): boolean; cdecl; export;
+begin
+ exit(Ammoz[TAmmoType(whichone+1)].Ammo.Propz and ammoprop_Effect <> 0)
end;
-function HW_isWeaponTimerable: boolean; cdecl; export;
-var CurSlot, CurAmmo: LongWord;
+function HW_getAmmoCounts(counts: PLongInt): LongInt; cdecl; export;
+var a : PHHAmmo;
+ slot, index: LongInt;
begin
- CurSlot:= CurrentHedgehog^.CurSlot;
- CurAmmo:= CurrentHedgehog^.CurAmmo;
- exit( (CurrentHedgehog^.Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Timerable) <> 0)
+ if (CurrentTeam = nil) or
+ (CurrentHedgehog = nil) or
+ (CurrentTeam^.ExtDriven) or
+ (CurrentTeam^.Hedgehogs[0].BotLevel <> 0) then
+ exit(-1);
+
+ a:= CurrentHedgehog^.Ammo;
+ for slot:= 0 to cMaxSlotIndex do
+ for index:= 0 to cMaxSlotAmmoIndex do
+ if a^[slot,index].Count <> 0 then // yes, ammomenu is hell
+ counts[ord(a^[slot,index].AmmoType)-1]:= a^[slot,index].Count;
+ exit(0);
end;
-function HW_isWeaponSwitch: boolean cdecl; export;
+procedure HW_getAmmoDelays (skipTurns: PByte); cdecl; export;
+var a : TAmmoType;
begin
- if CurAmmoGear <> nil then
- exit(CurAmmoGear^.AmmoType = amSwitch)
- else
- exit(false)
+ for a:= Low(TAmmoType) to High(TAmmoType) do
+ skipTurns[ord(a)-1]:= byte(Ammoz[a].SkipTurns);
end;
-function HW_isPaused: boolean; cdecl; export;
+function HW_getTurnsForCurrentTeam: LongInt; cdecl; export;
begin
- exit( isPaused );
+ exit(CurrentTeam^.Clan^.TurnNumber);
end;
-procedure HW_setGrenadeTime(time: LongInt); cdecl; export;
+function HW_getMaxNumberOfHogs: LongInt; cdecl; export;
begin
- ParseCommand('/timer ' + inttostr(time), true);
+ exit(cMaxHHIndex+1);
end;
-//amSwitch
+function HW_getMaxNumberOfTeams: LongInt; cdecl; export;
+begin
+ exit(cMaxTeams);
+end;
{$ENDIF}
end.
--- a/hedgewars/SDLMain.m Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/SDLMain.m Wed Oct 27 14:02:20 2010 +0200
@@ -50,7 +50,7 @@
dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
if (dict)
appName = [dict objectForKey: @"CFBundleName"];
-
+
if (![appName length])
appName = [[NSProcessInfo processInfo] processName];
@@ -131,10 +131,10 @@
NSMenuItem *menuItem;
NSString *title;
NSString *appName;
-
+
appName = getApplicationName();
appleMenu = [[NSMenu alloc] initWithTitle:@""];
-
+
/* Add menu items */
title = [@"About " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
@@ -154,7 +154,7 @@
title = [@"Quit " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
-
+
/* Put menu into the menubar */
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
[menuItem setSubmenu:appleMenu];
@@ -176,17 +176,17 @@
NSMenuItem *menuItem;
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
-
+
/* "Minimize" item */
menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
[windowMenu addItem:menuItem];
[menuItem release];
-
+
/* Put menu into the menubar */
windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
[windowMenuItem setSubmenu:windowMenu];
[[NSApp mainMenu] addItem:windowMenuItem];
-
+
/* Tell the application object that this is now the window menu */
[NSApp setWindowsMenu:windowMenu];
@@ -203,7 +203,7 @@
/* Ensure the application object is initialised */
[SDLApplication sharedApplication];
-
+
#ifdef SDL_USE_CPS
{
CPSProcessSerNum PSN;
@@ -223,10 +223,10 @@
/* Create SDLMain and make it the app delegate */
sdlMain = [[SDLMain alloc] init];
[NSApp setDelegate:sdlMain];
-
+
/* Start the main event loop */
[NSApp run];
-
+
[sdlMain release];
[pool release];
}
@@ -319,27 +319,27 @@
bufferSize = selfLen + aStringLen - aRange.length;
buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar));
-
+
/* Get first part into buffer */
localRange.location = 0;
localRange.length = aRange.location;
[self getCharacters:buffer range:localRange];
-
+
/* Get middle part into buffer */
localRange.location = 0;
localRange.length = aStringLen;
[aString getCharacters:(buffer+aRange.location) range:localRange];
-
+
/* Get last part into buffer */
localRange.location = aRange.location + aRange.length;
localRange.length = selfLen - localRange.location;
[self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
-
+
/* Build output string */
result = [NSString stringWithCharacters:buffer length:bufferSize];
-
+
NSDeallocateMemoryPages(buffer, bufferSize);
-
+
return result;
}
--- a/hedgewars/SDLh.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/SDLh.pas Wed Oct 27 14:02:20 2010 +0200
@@ -96,7 +96,7 @@
SDL_SWSURFACE = $00000000;
SDL_HWSURFACE = $00000001;
SDL_SRCALPHA = $00010000;
-
+
SDL_INIT_TIMER = $00000001;
SDL_INIT_AUDIO = $00000010;
SDL_INIT_VIDEO = $00000020;
@@ -156,7 +156,7 @@
SDL_VIDEORESIZE = 16; // TODO: outdated? no longer in SDL 1.3?
{$ENDIF}
{*end SDL_Event binding*}
-
+
{$IFDEF SDL13}
SDL_ASYNCBLIT = $08000000;
SDL_ANYFORMAT = $10000000;
@@ -209,12 +209,12 @@
SDL_WINDOW_INPUT_FOCUS = $00000200; //*< window has input focus */
SDL_WINDOW_MOUSE_FOCUS = $00000400; //*< window has mouse focus */
SDL_WINDOW_FOREIGN = $00000800; //*< window not created by SDL */
-
+
// SDL_WindowEventID (enum)
SDL_WINDOWEVENT_NONE = 0; //*< Never used
SDL_WINDOWEVENT_SHOWN = 1; //*< Window has been shown
SDL_WINDOWEVENT_HIDDEN = 2; //*< Window has been hidden
- SDL_WINDOWEVENT_EXPOSED = 3; //*< Window has been exposed and should be redrawn
+ SDL_WINDOWEVENT_EXPOSED = 3; //*< Window has been exposed and should be redrawn
SDL_WINDOWEVENT_MOVED = 4; //*< Window has been moved to data1, data2
SDL_WINDOWEVENT_RESIZED = 5; //*< Window size changed to data1xdata2
SDL_WINDOWEVENT_MINIMIZED = 6; //*< Window has been minimized
@@ -233,7 +233,7 @@
MIX_INIT_MOD = $00000002;
MIX_INIT_MP3 = $00000004;
MIX_INIT_OGG = $00000008;
-
+
{* SDL_TTF *}
TTF_STYLE_NORMAL = 0;
TTF_STYLE_BOLD = 1;
@@ -259,7 +259,7 @@
/////////////////////// TYPE DEFINITIONS ///////////////////////
/////////////////////////////////////////////////////////////////
-type
+type
PSDL_Rect = ^TSDL_Rect;
TSDL_Rect = record
{$IFDEF SDL13}
@@ -357,9 +357,9 @@
{* SDL_Event type definition *}
{$IFDEF SDL13}
- PSDL_Window = pointer;
+ PSDL_Window = pointer;
PSDL_Texture = pointer;
-
+
TSDL_WindowEvent = record
type_: LongInt;
windowID: LongInt;
@@ -367,7 +367,7 @@
padding1, padding2, padding3: byte;
data1, data2: LongInt;
end;
-
+
TSDL_KeySym = record
scancode,
sym,
@@ -407,7 +407,7 @@
padding1, padding2: byte;
x, y, z, xrel, yrel : LongInt;
pressure, pressure_max, pressure_min,
- rotation, tilt, cursor: LongInt;
+ rotation, tilt, cursor: LongInt;
{$ELSE}
type_: byte;
x, y, xrel, yrel : word;
@@ -450,7 +450,7 @@
x, y: LongInt;
padding1, padding2, padding3: byte;
end;
-
+
// implement SDL_ProximityEvent
{$ENDIF}
@@ -465,10 +465,10 @@
{$IFDEF SDL13}
value: LongInt;
{$ELSE}
- value: word;
-{$ENDIF}
+ value: Smallint;
+{$ENDIF}
end;
-
+
TSDL_JoyBallEvent = record
which: Byte;
ball: Byte;
@@ -477,7 +477,7 @@
xrel, yrel: LongInt;
{$ELSE}
type_: Byte;
- xrel, yrel: word;
+ xrel, yrel: Smallint;
{$ENDIF}
end;
@@ -491,7 +491,7 @@
hat: Byte;
value: Byte;
end;
-
+
TSDL_JoyButtonEvent = record
{$IFDEF SDL13}
type_: LongInt;
@@ -586,7 +586,7 @@
);
{$IFDEF SDL13}
- TSDL_ArrayByteOrder = ( // array component order, low byte -> high byte
+ TSDL_ArrayByteOrder = ( // array component order, low byte -> high byte
SDL_ARRAYORDER_NONE,
SDL_ARRAYORDER_RGB,
SDL_ARRAYORDER_RGBA,
@@ -702,8 +702,8 @@
function SDL_SaveBMP_RW(surface: PSDL_Surface; dst: PSDL_RWops; freedst: LongInt): LongInt; cdecl; external SDLLibName;
{$IFDEF SDL13}
-function SDL_CreateWindow(title: PChar; x,y,w,h, flags: LongInt): PSDL_Window; cdecl; external SDLLibName;
-function SDL_CreateRenderer(window: PSDL_Window; index, flags: LongInt): LongInt; cdecl; external SDLLibName;
+function SDL_CreateWindow(title: PChar; x,y,w,h, flags: LongInt): PSDL_Window; cdecl; external SDLLibName;
+function SDL_CreateRenderer(window: PSDL_Window; index, flags: LongInt): LongInt; cdecl; external SDLLibName;
function SDL_SetRenderDrawColor(r,g,b,a: byte): LongInt; cdecl; external SDLLibName;
function SDL_DestroyRenderer(window: PSDL_Window): LongInt; cdecl; external SDLLibName;
function SDL_DestroyWindow(window: PSDL_Window): LongInt; cdecl; external SDLLibName;
@@ -718,6 +718,7 @@
function SDL_GetRelativeMouseState(x, y: PLongInt): Byte; cdecl; external SDLLibName;
function SDL_GetNumMice: LongInt; cdecl; external SDLLibName;
function SDL_PixelFormatEnumToMasks(format: TSDL_ArrayByteOrder; bpp: PLongInt; Rmask, Gmask, Bmask, Amask: PLongInt): boolean; cdecl; external SDLLibName;
+function SDL_RenderReadPixels(rect: PSDL_Rect; format: LongInt; pixels: pointer; pitch: LongInt): LongInt; cdecl; external SDLLibName;
{$ENDIF}
function SDL_GetKeyState(numkeys: PLongInt): PByteArray; cdecl; external SDLLibName {$IFDEF SDL13} name 'SDL_GetKeyboardState'{$ENDIF};
@@ -841,13 +842,6 @@
function SDLNet_Read16(buf: pointer): Word;
function SDLNet_Read32(buf: pointer): LongWord;
-{$IFDEF IPHONEOS}
-(* iPhone related calls *)
-procedure clearView; cdecl; external;
-procedure startSpinning; cdecl; external;
-procedure stopSpinning; cdecl; external;
-function isPhone: Boolean; cdecl; external;
-{$ENDIF}
implementation
function SDL_MustLock(Surface: PSDL_Surface): Boolean;
--- a/hedgewars/VGSHandlers.inc Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/VGSHandlers.inc Wed Oct 27 14:02:20 2010 +0200
@@ -34,9 +34,9 @@
Y:= Y + (dY + tdY + cGravityf * vobFallSpeed) * Steps;
Angle:= Angle + dAngle * Steps;
- if (round(X) >= -cScreenWidth - 64) and
- (round(X) <= cScreenWidth + LAND_WIDTH) and
- (round(Y) <= (LAND_HEIGHT + 75)) and
+ if (round(X) >= cLeftScreenBorder) and
+ (round(X) <= cRightScreenBorder) and
+ (round(Y) <= (int64(LAND_HEIGHT) + 75)) and
(Timer > 0) and (Timer-Steps > 0) then
begin
if tdX > 0 then sign := 1
@@ -51,10 +51,10 @@
end
else
begin
- if round(X) < -cScreenWidth - 64 then X:= float(cScreenWidth + LAND_WIDTH) else
- if round(X) > cScreenWidth + LAND_WIDTH then X:= float(-cScreenWidth - 64);
+ 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) > (LAND_HEIGHT + 75) then Y:= Y - float(1024 + 150); // TODO - configure in theme (jellies for example could use limited range)
+ if round(Y) > (int64(LAND_HEIGHT) + 75) then Y:= Y - float(1024 + 150); // TODO - configure in theme (jellies for example could use limited range)
Timer:= 0;
tdX:= 0;
tdY:= 0
@@ -77,17 +77,17 @@
var s: Longword;
t: float;
begin
-Gear^.X:= Gear^.X + (cWindSpeedf * 200 + Gear^.dX) * Steps;
+Gear^.X:= Gear^.X + (cWindSpeedf * 750 * Gear^.dX) * Steps;
// up-and-down-bounce magic
s := (GameTicks + Gear^.Timer) mod 4096;
t := 8 * AngleSin(s mod 2048).QWordValue / 4294967296;
if (s < 2048) then t := -t;
-Gear^.Y := LAND_HEIGHT-1184 + Gear^.Timer mod 8 + t;
+Gear^.Y := int64(LAND_HEIGHT) - 1184 + Gear^.Timer mod 8 + t;
-if round(Gear^.X) < -cScreenWidth - 256 then Gear^.X:= float(cScreenWidth + LAND_WIDTH) else
-if round(Gear^.X) > cScreenWidth + LAND_WIDTH then Gear^.X:= float(-cScreenWidth - 256)
+if round(Gear^.X) < cLeftScreenBorder then Gear^.X:= Gear^.X + cScreenSpace else
+if round(Gear^.X) > cRightScreenBorder then Gear^.X:= Gear^.X - cScreenSpace
end;
////////////////////////////////////////////////////////////////////////////////
@@ -109,6 +109,24 @@
end;
////////////////////////////////////////////////////////////////////////////////
+procedure doStepNote(Gear: PVisualGear; Steps: Longword);
+begin
+Gear^.X:= Gear^.X + Gear^.dX * Steps;
+
+Gear^.Y:= Gear^.Y + Gear^.dY * Steps;
+Gear^.dY:= Gear^.dY + cGravityf * Steps / 2;
+
+Gear^.Angle:= Gear^.Angle + (Gear^.Frame + 1) * Steps / 10;
+while Gear^.Angle > cMaxAngle do
+ Gear^.Angle:= Gear^.Angle - cMaxAngle;
+
+if Gear^.FrameTicks <= Steps then
+ DeleteVisualGear(Gear)
+else
+ dec(Gear^.FrameTicks, Steps)
+end;
+
+////////////////////////////////////////////////////////////////////////////////
procedure doStepEgg(Gear: PVisualGear; Steps: Longword);
begin
Gear^.X:= Gear^.X + Gear^.dX * Steps;
@@ -126,11 +144,27 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepFire(Gear: PVisualGear; Steps: Longword);
+var vgt: PVisualGear;
begin
Gear^.X:= Gear^.X + Gear^.dX * Steps;
Gear^.Y:= Gear^.Y + Gear^.dY * Steps;// + cGravityf * (Steps * Steps);
-Gear^.dY:= Gear^.dY + cGravityf * Steps;
+if (Gear^.State and gstTmpFlag) = 0 then
+ begin
+ Gear^.dY:= Gear^.dY + cGravityf * Steps;
+ if ((GameTicks mod 200) < Steps + 1) then
+ begin
+ vgt:= AddVisualGear(round(Gear^.X), round(Gear^.Y), vgtFire);
+ if vgt <> nil then
+ begin
+ vgt^.dx:= 0;
+ vgt^.dy:= 0;
+ vgt^.State:= gstTmpFlag;
+ end;
+ end
+ end
+else
+ inc(Steps, Steps);
if Gear^.FrameTicks <= Steps then
DeleteVisualGear(Gear)
@@ -167,9 +201,13 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepBubble(Gear: PVisualGear; Steps: Longword);
begin
- Gear^.X:= Gear^.X + (cWindSpeedf * 100 + Gear^.dX) * Steps;
+ Gear^.X:= Gear^.X + Gear^.dX * Steps;
+ Gear^.Y:= Gear^.Y + Gear^.dY * Steps;
Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps;
+ Gear^.dX /= (1.001 * Steps);
+ Gear^.dY /= (1.001 * Steps);
+
if (Gear^.FrameTicks <= Steps) or (round(Gear^.Y) < cWaterLine) then
DeleteVisualGear(Gear)
else
@@ -442,7 +480,7 @@
procedure doStepHealthTagWorkUnderWater(Gear: PVisualGear; Steps: Longword);
begin
-if round(Gear^.Y) < cWaterLine + 10 then
+if round(Gear^.Y) < int64(cWaterLine) + 10 then
DeleteVisualGear(Gear)
else
Gear^.Y:= Gear^.Y - 0.08 * Steps;
@@ -478,12 +516,16 @@
inc(Gear^.Timer, Steps );
if Gear^.Timer > 64 then
begin
+ if Gear^.State = 0 then
+ begin
+ DeleteVisualGear(Gear);
+ exit;
+ end;
dec(Gear^.State, Gear^.Timer div 65);
Gear^.Timer:= Gear^.Timer mod 65;
end;
Gear^.dX:= Gear^.dX + cWindSpeedf * Steps;
Gear^.X:= Gear^.X + Gear^.dX;
-if Gear^.State = 0 then DeleteVisualGear(Gear);
end;
////////////////////////////////////////////////////////////////////////////////
@@ -543,3 +585,19 @@
Gear^.doStep:= @doStepBigExplosionWork;
if Steps > 1 then Gear^.doStep(Gear, Steps-1);
end;
+
+procedure doStepChunk(Gear: PVisualGear; Steps: Longword);
+begin
+Gear^.X:= Gear^.X + Gear^.dX * Steps;
+
+Gear^.Y:= Gear^.Y + Gear^.dY * Steps;
+Gear^.dY:= Gear^.dY + cGravityf * Steps;
+
+Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle;
+
+if round(Gear^.Y) > cWaterLine then
+ begin
+ AddVisualGear(round(Gear^.X), round(Gear^.Y), vgtDroplet);
+ DeleteVisualGear(Gear);
+ end
+end;
--- a/hedgewars/adler32.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/adler32.pas Wed Oct 27 14:02:20 2010 +0200
@@ -75,7 +75,7 @@
procedure Adler32Update(var adler: longint; Msg: pointer; Len: longint);
//-update Adler32 with Msg data
const
- BASE = 65521; // max. prime < 65536
+ BASE = 65521; // max. prime < 65536
NMAX = 5552; // max. n with 255n(n+1)/2 + (n+1)(BASE-1) < 2^32
type
LH = packed record
--- a/hedgewars/hwengine.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/hwengine.pas Wed Oct 27 14:02:20 2010 +0200
@@ -29,10 +29,9 @@
program hwengine;
{$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, sysutils;
-
-type arrayofpchar = array[0..9] of PChar;
+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;
@@ -136,7 +135,7 @@
end;
///////////////////
-procedure MainLoop;
+procedure MainLoop;
var PrevTime, CurrTime: Longword;
event: TSDL_Event;
begin
@@ -176,11 +175,11 @@
if isTerminated = false then
begin
CurrTime:= SDL_GetTicks;
- if PrevTime + cTimerInterval <= CurrTime then
+ if PrevTime + longword(cTimerInterval) <= CurrTime then
begin
DoTimer(CurrTime - PrevTime);
PrevTime:= CurrTime
- end
+ end
else SDL_Delay(1);
IPCCheckSock();
end;
@@ -197,7 +196,7 @@
///////////////
{$IFDEF HWLIBRARY}
-procedure Game(gameArgs: arrayofpchar); cdecl; export;
+procedure Game(gameArgs: PPChar); cdecl; export;
{$ELSE}
procedure Game;
{$ENDIF}
@@ -215,24 +214,23 @@
{$IFDEF DEBUGFILE}
cShowFPS:= true;
{$ELSE}
- cShowFPS:= true; // update me at release time
+ cShowFPS:= false;
{$ENDIF}
- cInitVolume:= 100;
-
- UserNick:= gameArgs[0];
- val(gameArgs[1], ipcPort);
- isSoundEnabled:= gameArgs[2] = '1';
- isMusicEnabled:= gameArgs[3] = '1';
+ val(gameArgs[0], ipcPort);
+ val(gameArgs[1], cScreenWidth);
+ val(gameArgs[2], cScreenHeight);
+ val(gameArgs[3], cReducedQuality);
cLocaleFName:= gameArgs[4];
- cAltDamage:= gameArgs[5] = '1';
- val(gameArgs[6], cScreenHeight);
- val(gameArgs[7], cScreenWidth);
- recordFileName:= gameArgs[8];
-
- val(gameArgs[9], cReducedQuality);
+ UserNick:= gameArgs[5];
+ isSoundEnabled:= gameArgs[6] = '1';
+ isMusicEnabled:= gameArgs[7] = '1';
+ cAltDamage:= gameArgs[8] = '1';
+ val(gameArgs[9], rotationQt);
+ recordFileName:= gameArgs[10];
cStereoMode:= smNone; // TODO: Enable anaglyph rendering on iPhone?
{$ENDIF}
+ cLogfileBase:= 'game';
initEverything(true);
WriteLnToConsole('Hedgewars ' + cVersionString + ' engine (network protocol: ' + inttostr(cNetProtoVersion) + ')');
@@ -244,7 +242,7 @@
for p:= Succ(Low(TPathType)) to High(TPathType) do
if p <> ptMapCurrent then Pathz[p]:= PathPrefix + '/' + Pathz[p];
-
+
WriteToConsole('Init SDL... ');
SDLTry(SDL_Init(SDL_INIT_VIDEO) >= 0, true);
WriteLnToConsole(msgOK);
@@ -269,23 +267,26 @@
ControllerInit(); // has to happen before InitKbdKeyTable to map keys
InitKbdKeyTable();
- if recordFileName = '' then
- InitIPC;
- WriteLnToConsole(msgGettingConfig);
-
LoadLocale(Pathz[ptLocale] + '/en.txt'); // Do an initial load with english
if cLocaleFName <> 'en.txt' then
begin
// Try two letter locale first before trying specific locale overrides
- if (Length(cLocaleFName) > 6) and (Copy(cLocaleFName,1,2)+'.txt' <> 'en.txt') then
+ if (Length(cLocaleFName) > 6) and (Copy(cLocaleFName,1,2)+'.txt' <> 'en.txt') then
LoadLocale(Pathz[ptLocale] + '/' + Copy(cLocaleFName,1,2)+'.txt');
LoadLocale(Pathz[ptLocale] + '/' + cLocaleFName);
end;
+ WriteLnToConsole(msgGettingConfig);
if recordFileName = '' then
- SendIPCAndWaitReply('C') // ask for game config
+ begin
+ InitIPC;
+ SendIPCAndWaitReply('C'); // ask for game config
+ end
else
+ begin
LoadRecordFromFile(recordFileName);
+ perfExt_SaveBeganSynching();
+ end;
ScriptOnGameInit;
@@ -316,13 +317,13 @@
begin
Randomize();
- uConsts.initModule;
+ // uConsts does not need initialization as they are all consts
uMisc.initModule;
uConsole.initModule; // MUST happen after uMisc
uLand.initModule;
uIO.initModule;
-
+
if complete then
begin
uAI.initModule;
@@ -341,7 +342,7 @@
//uLandTemplates does not need initialization
uLandTexture.initModule;
//uLocale does not need initialization
- uRandom.initModule;
+ uRandom.initModule;
uScript.initModule;
uSound.initModule;
uStats.initModule;
@@ -381,19 +382,19 @@
//uAIActions does not need to be freed
uAI.freeModule; //stub
end;
-
+
uIO.freeModule; //stub
uLand.freeModule;
uConsole.freeModule;
uMisc.freeModule; // uMisc closes the debug log.
- uConsts.freeModule; //stub
end;
/////////////////////////
procedure GenLandPreview{$IFDEF HWLIBRARY}(port: LongInt); cdecl; export{$ENDIF};
var Preview: TPreview;
begin
+ cLogfileBase:= 'preview';
initEverything(false);
{$IFDEF HWLIBRARY}
WriteLnToConsole('Preview connecting on port ' + inttostr(port));
@@ -419,134 +420,38 @@
begin
WriteLn('Wrong argument format: correct configurations is');
WriteLn();
- WriteLn(' hwengine <path to data folder> <path to replay file> [option]');
+ WriteLn(' hwengine <path to data folder> <path to replay file> [options]');
WriteLn();
- WriteLn('where [option] must be specified either as');
+ WriteLn('where [options] must be specified either as:');
WriteLn(' --set-video [screen width] [screen height] [color dept]');
WriteLn(' --set-audio [volume] [enable music] [enable sounds]');
WriteLn(' --set-other [language file] [full screen] [show FPS]');
- WriteLn(' --set-multimedia [screen height] [screen width] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]');
- WriteLn(' --set-everything [screen height] [screen width] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]');
+ WriteLn(' --set-multimedia [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]');
+ WriteLn(' --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]');
WriteLn();
- WriteLn('Read documentation online at http://www.hedgewars.org/node/1465 for more information');
- Write('parsed command: ');
+ WriteLn('Read documentation online at http://code.google.com/p/hedgewars/wiki/CommandLineOptions for more information');
+ WriteLn();
+ Write('PARSED COMMAND: ');
for i:=0 to ParamCount do
Write(ParamStr(i) + ' ');
WriteLn();
end;
////////////////////
+{$INCLUDE "ArgParsers.inc"}
+
procedure GetParams;
-var i : LongInt;
begin
- case ParamCount of
- 19: begin
- val(ParamStr(2), cScreenWidth);
- val(ParamStr(3), cScreenHeight);
- cBitsStr:= ParamStr(4);
- val(cBitsStr, cBits);
- val(ParamStr(5), ipcPort);
- cFullScreen:= ParamStr(6) = '1';
- isSoundEnabled:= ParamStr(7) = '1';
- //cVSyncInUse:= ParamStr(8) = '1'; //merged with rqFlags
- //cWeaponTooltips:= ParamStr(9) = '1'; //merged with rqFlags
- cLocaleFName:= ParamStr(10);
- val(ParamStr(11), cInitVolume);
- val(ParamStr(12), cTimerInterval);
- PathPrefix:= ParamStr(13);
- cShowFPS:= ParamStr(14) = '1';
- cAltDamage:= ParamStr(15) = '1';
- UserNick:= DecodeBase64(ParamStr(16));
- isMusicEnabled:= ParamStr(17) = '1';
- val(ParamStr(18), cReducedQuality);
- val(ParamStr(19), i);
- cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), i)));
- end;
- 3: begin
- val(ParamStr(2), ipcPort);
- GameType:= gmtLandPreview;
- if ParamStr(3) <> 'landpreview' then
- OutError(errmsgShouldntRun, true);
- end;
- 2: begin
- PathPrefix:= ParamStr(1);
- recordFileName:= ParamStr(2);
- end;
- 6: begin
- PathPrefix:= ParamStr(1);
- recordFileName:= ParamStr(2);
-
- if ParamStr(3) = '--set-video' then
- begin
- val(ParamStr(4), cScreenWidth);
- val(ParamStr(5), cScreenHeight);
- cBitsStr:= ParamStr(6);
- val(cBitsStr, cBits);
- end
+ if (ParamCount < 2) then
+ GameType:= gmtSyntax
+ else
+ if (ParamCount = 3) then
+ internalSetGameTypeLandPreviewFromParameters()
+ else
+ if (ParamCount = cDefaultParamNum) then
+ internalStartGameWithParameters()
else
- begin
- if ParamStr(3) = '--set-audio' then
- begin
- val(ParamStr(4), cInitVolume);
- isMusicEnabled:= ParamStr(5) = '1';
- isSoundEnabled:= ParamStr(6) = '1';
- end
- else
- begin
- if ParamStr(3) = '--set-other' then
- begin
- cLocaleFName:= ParamStr(4);
- cFullScreen:= ParamStr(5) = '1';
- cShowFPS:= ParamStr(6) = '1';
- end
- else GameType:= gmtSyntax;
- end
- end;
- end;
- 11: begin
- PathPrefix:= ParamStr(1);
- recordFileName:= ParamStr(2);
-
- if ParamStr(3) = '--set-multimedia' then
- begin
- val(ParamStr(4), cScreenWidth);
- val(ParamStr(5), cScreenHeight);
- cBitsStr:= ParamStr(6);
- val(cBitsStr, cBits);
- val(ParamStr(7), cInitVolume);
- isMusicEnabled:= ParamStr(8) = '1';
- isSoundEnabled:= ParamStr(9) = '1';
- cLocaleFName:= ParamStr(10);
- cFullScreen:= ParamStr(11) = '1';
- end
- else GameType:= gmtSyntax;
- end;
- 15: begin
- PathPrefix:= ParamStr(1);
- recordFileName:= ParamStr(2);
- if ParamStr(3) = '--set-everything' then
- begin
- val(ParamStr(4), cScreenWidth);
- val(ParamStr(5), cScreenHeight);
- cBitsStr:= ParamStr(6);
- val(cBitsStr, cBits);
- val(ParamStr(7), cInitVolume);
- isMusicEnabled:= ParamStr(8) = '1';
- isSoundEnabled:= ParamStr(9) = '1';
- cLocaleFName:= ParamStr(10);
- cFullScreen:= ParamStr(11) = '1';
- cAltDamage:= ParamStr(12) = '1';
- cShowFPS:= ParamStr(13) = '1';
- val(ParamStr(14), cTimerInterval);
- if (ParamStr(15) = '1') then //HACK
- cReducedQuality:= $FFFFFFFF xor rqLowRes
- else
- val(ParamStr(15), cReducedQuality);
- end
- else GameType:= gmtSyntax;
- end;
- else GameType:= gmtSyntax;
- end;
+ playReplayFileWithParameters();
end;
////////////////////////////////////////////////////////////////////////////////
@@ -558,7 +463,7 @@
if GameType = gmtLandPreview then GenLandPreview()
else if GameType = gmtSyntax then DisplayUsage()
else Game();
-
+
if GameType = gmtSyntax then
ExitCode:= 1
else
--- a/hedgewars/options.inc Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/options.inc Wed Oct 27 14:02:20 2010 +0200
@@ -25,7 +25,7 @@
{$MODE OBJFPC}
{$MACRO ON}
-{$DEFINE GLunit:=GL,GLext}
+{$DEFINE GLunit:=GL,GLext}
{$IFDEF IPHONEOS}
{$DEFINE SDL13}
--- a/hedgewars/uAI.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uAI.pas Wed Oct 27 14:02:20 2010 +0200
@@ -71,7 +71,7 @@
if (Targets.ar[i].Score >= 0) and (not StopThinking) then
begin
with CurrentHedgehog^ do
- a:= Ammo^[CurSlot, CurAmmo].AmmoType;
+ a:= CurAmmoType;
aa:= a;
repeat
if (CanUseAmmo[a]) and
@@ -212,7 +212,7 @@
Pop(ticks, Actions, Me^);
AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
- if (Me^.Message and gm_Left) <> 0 then AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
+ if (Me^.Message and gmLeft) <> 0 then AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
else AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
steps:= 0;
--- a/hedgewars/uAIAmmoTests.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uAIAmmoTests.pas Wed Oct 27 14:02:20 2010 +0200
@@ -71,7 +71,8 @@
(proc: nil; flags: 0), // amMineStrike
(proc: nil; flags: 0), // amBlowTorch
(proc: nil; flags: 0), // amGirder
- (proc: @TestTeleport; flags: amtest_OnTurn), // amTeleport
+ (proc: nil; flags: 0), // amTeleport
+ //(proc: @TestTeleport; flags: amtest_OnTurn), // amTeleport
(proc: nil; flags: 0), // amSwitch
(proc: @TestMortar; flags: 0), // amMortar
(proc: nil; flags: 0), // amKamikaze
@@ -97,13 +98,16 @@
(proc: nil; flags: 0), // amPiano
(proc: @TestGrenade; flags: 0), // amGasBomb
(proc: @TestShotgun; flags: 0), // amSineGun
- (proc: nil; flags: 0) // amFlamethrower
+ (proc: nil; flags: 0), // amFlamethrower
+ (proc: @TestGrenade; flags: 0), // amSMine
+ (proc: @TestFirePunch; flags: 0), // amHammer
+ (proc: nil; flags: 0) // amResurrector
);
const BadTurn = Low(LongInt) div 4;
implementation
-uses uMisc, uAIMisc, uLand, uTeams;
+uses uMisc, uAIMisc, uLand;
function Metric(x1, y1, x2, y2: LongInt): LongInt;
begin
@@ -121,11 +125,8 @@
t: LongInt;
value: LongInt;
begin
- with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+ x:= Me^.X;
+ y:= Me^.Y;
dX:= Vx;
dY:= -Vy;
t:= rTime;
@@ -179,11 +180,8 @@
var x, y, dY: hwFloat;
t: LongInt;
begin
- with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+ x:= Me^.X;
+ y:= Me^.Y;
dY:= -Vy;
t:= TestTime;
repeat
@@ -234,11 +232,8 @@
var x, y, dY: hwFloat;
t: LongInt;
begin
- with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+ x:= Me^.X;
+ y:= Me^.Y;
dY:= -Vy;
t:= TestTime;
repeat
@@ -289,11 +284,8 @@
var x, y, dY: hwFloat;
t: LongInt;
begin
- with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+ x:= Me^.X;
+ y:= Me^.Y;
dY:= -Vy;
t:= TestTime;
repeat
@@ -348,11 +340,8 @@
var x, y, dY: hwFloat;
t: LongInt;
begin
- with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+ x:= Me^.X;
+ y:= Me^.Y;
dY:= -Vy;
t:= TestTime;
repeat
@@ -381,7 +370,7 @@
if valueResult < Score then
begin
ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
- ap.Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15);
+ ap.Power:= hwRound(r * cMaxPower * _0_9) + AIrndSign(random(Level) * 15);
ap.Time:= TestTime;
ap.ExplR:= 300;
ap.ExplX:= EX;
@@ -403,11 +392,8 @@
var x, y, dY: hwFloat;
value: LongInt;
begin
- with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+ x:= Me^.X;
+ y:= Me^.Y;
dY:= -Vy;
repeat
@@ -491,11 +477,8 @@
ap.ExplR:= 0;
ap.Time:= 0;
ap.Power:= 1;
-with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+x:= Me^.X;
+y:= Me^.Y;
range:= Metric(hwRound(x), hwRound(y), Targ.X, Targ.Y);
if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then exit(BadTurn);
Vx:= (int2hwFloat(Targ.X) - x) * _1div1024;
@@ -528,11 +511,8 @@
ap.ExplR:= 0;
ap.Time:= 0;
ap.Power:= 1;
-with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+x:= Me^.X;
+y:= Me^.Y;
if Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) < 80 then
exit(BadTurn);
t:= _0_5 / Distance(int2hwFloat(Targ.X) - x, int2hwFloat(Targ.Y) - y);
@@ -564,11 +544,8 @@
ap.Time:= 0;
ap.Power:= 1;
-with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+x:= Me^.X;
+y:= Me^.Y;
if (Targ.X) - hwRound(x) >= 0 then ap.Angle:= cMaxAngle div 4
else ap.Angle:= - cMaxAngle div 4;
valueResult:= RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x), hwRound(y), 15, 30);
@@ -585,11 +562,8 @@
ap.Time:= 0;
ap.Power:= 1;
ap.Angle:= 0;
-with PHedgehog(Me^.Hedgehog)^ do
- begin
- x:= Me^.X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(Me^.dX), Me^.Angle)));
- y:= Me^.Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Me^.Angle)))
- end;
+x:= Me^.X;
+y:= Me^.Y;
if (Abs(hwRound(x) - Targ.X) > 25)
or (Abs(hwRound(y) - 50 - Targ.Y) > 50) then
begin
@@ -689,7 +663,7 @@
FillBonuses(true, [gtCase]);
if bonuses.Count = 0 then begin
if Me^.Health <= 100 then begin
- maxTop := Targ.Y - cHHRadius * 2;
+ maxTop := Targ.Y - cHHRadius * 2;
while not TestColl(Targ.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
dec(maxTop, cHHRadius*2);
if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then begin
@@ -701,7 +675,7 @@
end
else begin
failNum := 0;
- repeat
+ repeat
i := random(bonuses.Count);
inc(failNum);
until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius) or (failNum = bonuses.Count*2);
--- a/hedgewars/uAIMisc.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uAIMisc.pas Wed Oct 27 14:02:20 2010 +0200
@@ -76,7 +76,7 @@
var friendlyfactor: LongInt = 300;
KnownExplosion: record
X, Y, Radius: LongInt
- end = (X: 0; Y: 0; Radius: 0);
+ end = (X: 0; Y: 0; Radius: 0);
procedure FillTargets;
var i, t: Longword;
@@ -195,7 +195,7 @@
MeX:= hwRound(Me^.X);
MeY:= hwRound(Me^.Y);
// We are still inside the hog. Skip radius test
- if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and
+ if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and
((Land[y, x] and $FF00) = 0) then exit(false);
end;
exit(TestColl(x, y, r))
@@ -404,8 +404,8 @@
end;
continue
end;
- if (Gear^.Message and gm_Left )<>0 then Gear^.dX:= -cLittle else
- if (Gear^.Message and gm_Right )<>0 then Gear^.dX:= cLittle else exit(bRes);
+ if (Gear^.Message and gmLeft )<>0 then Gear^.dX:= -cLittle else
+ if (Gear^.Message and gmRight )<>0 then Gear^.dX:= cLittle else exit(bRes);
if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
begin
if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
--- a/hedgewars/uAmmos.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uAmmos.pas Wed Oct 27 14:02:20 2010 +0200
@@ -42,16 +42,18 @@
procedure DisableSomeWeapons;
procedure ResetWeapons;
function GetAmmoByNum(num: Longword): PHHAmmo;
+function GetAmmoEntry(var Hedgehog: THedgehog): PAmmo;
var shoppa: boolean;
+ StoreCnt: Longword;
implementation
-uses uMisc, uGears, uWorld, uLocale, uConsole;
+uses uMisc, uGears, uWorld, uLocale, uConsole, uMobile;
type TAmmoCounts = array[TAmmoType] of Longword;
var StoresList: array[0..Pred(cMaxHHs)] of PHHAmmo;
- StoreCnt: Longword;
ammoLoadout, ammoProbability, ammoDelay, ammoReinforcement: shortstring;
+ InitialCounts: array[0..Pred(cMaxHHs)] of TAmmoCounts;
procedure FillAmmoStore(Ammo: PHHAmmo; var cnts: TAmmoCounts);
var mi: array[0..cMaxSlotIndex] of byte;
@@ -67,21 +69,19 @@
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:= cnts[a];
- Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]].InitialCount:= cnts[a];
-
- if ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then
- Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]].Count:= AMMO_INFINITE;
+ 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
+ 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;
- Ammo^[Ammoz[a].Slot, mi[Ammoz[a].Slot]].InitialCount:= 0;
inc(mi[Ammoz[a].Slot])
end
@@ -99,7 +99,7 @@
// FIXME - TEMPORARY hardcoded check on shoppa pending creation of crate *type* probability editor
substr:= Copy(ammoLoadout,1,15);
-if (substr = '000000990000009') or
+if (substr = '000000990000009') or
(substr = '000000990000000') then
shoppa:= true;
@@ -137,16 +137,16 @@
end;
ammos[a]:= cnt;
- if ((GameFlags and gfKing) <> 0) and ((GameFlags and gfPlaceHog) = 0) and (Ammoz[a].SkipTurns = 0) and (a <> amTeleport) and (a <> amSkip) then
+ if ((GameFlags and gfKing) <> 0) and ((GameFlags and gfPlaceHog) = 0) and (Ammoz[a].SkipTurns = 0) and (a <> amTeleport) and (a <> amSkip) then
Ammoz[a].SkipTurns:= 1;
if ((GameFlags and gfPlaceHog) <> 0) and
- (a <> amTeleport) and (a <> amSkip) and
+ (a <> amTeleport) and (a <> amSkip) and
(Ammoz[a].SkipTurns < 10000) then inc(Ammoz[a].SkipTurns,10000)
- end else
- ammos[a]:= AMMO_INFINITE
+ end
+ else ammos[a]:= AMMO_INFINITE;
+ InitialCounts[Pred(StoreCnt)][a]:= ammos[a];
end;
-
FillAmmoStore(StoresList[Pred(StoreCnt)], ammos)
end;
@@ -156,6 +156,18 @@
exit(StoresList[num])
end;
+function GetAmmoEntry(var Hedgehog: THedgehog): PAmmo;
+var ammoidx, slot: LongWord;
+begin
+with Hedgehog do
+ begin
+ slot:= Ammoz[CurAmmoType].Slot;
+ ammoidx:= 0;
+ while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx);
+ GetAmmoEntry:= @Ammo^[slot, ammoidx];
+ end
+end;
+
procedure AssignStores;
var t: LongInt;
i: Longword;
@@ -165,7 +177,10 @@
begin
for i:= 0 to cMaxHHIndex do
if Hedgehogs[i].Gear <> nil then
+ begin
Hedgehogs[i].Ammo:= GetAmmoByNum(Hedgehogs[i].AmmoStore);
+ Hedgehogs[i].CurAmmoType:= amNothing;
+ end
end
end;
@@ -213,21 +228,26 @@
end;
procedure OnUsedAmmo(var Hedgehog: THedgehog);
+var CurWeapon: PAmmo;
begin
+CurWeapon:= GetAmmoEntry(Hedgehog);
with Hedgehog do
begin
+
MultiShootAttacks:= 0;
- with Ammo^[CurSlot, CurAmmo] do
+ with CurWeapon^ do
if Count <> AMMO_INFINITE then
begin
dec(Count);
if Count = 0 then
begin
- PackAmmo(Ammo, CurSlot);
- SwitchNotHeldAmmo(Hedgehog)
+ PackAmmo(Ammo, Ammoz[AmmoType].Slot);
+ //SwitchNotHeldAmmo(Hedgehog);
+ CurAmmoType:= amNothing
end
end
- end
+ end;
+perfExt_AmmoUpdate;
end;
function HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): boolean;
@@ -264,33 +284,37 @@
end;
procedure SwitchToFirstLegalAmmo(var Hedgehog: THedgehog);
+var slot, ammoidx: LongWord;
begin
with Hedgehog do
begin
- CurAmmo:= 0;
- CurSlot:= 0;
- while (CurSlot <= cMaxSlotIndex) and
- ((Ammo^[CurSlot, CurAmmo].Count = 0) or
- (Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber >= 0))
+ CurAmmoType:= amNothing;
+ slot:= 0;
+ ammoidx:= 0;
+ while (slot <= cMaxSlotIndex) and
+ ((Ammo^[slot, ammoidx].Count = 0) or
+ (Ammoz[Ammo^[slot, ammoidx].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber >= 0))
do
begin
- while (CurAmmo <= cMaxSlotAmmoIndex) and
- ((Ammo^[CurSlot, CurAmmo].Count = 0) or
- (Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber >= 0))
- do inc(CurAmmo);
+ while (ammoidx <= cMaxSlotAmmoIndex) and
+ ((Ammo^[slot, ammoidx].Count = 0) or
+ (Ammoz[Ammo^[slot, ammoidx].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber >= 0))
+ do inc(ammoidx);
- if (CurAmmo > cMaxSlotAmmoIndex) then
+ if (ammoidx > cMaxSlotAmmoIndex) then
begin
- CurAmmo:= 0;
- inc(CurSlot)
+ ammoidx:= 0;
+ inc(slot)
end
end;
- TryDo(CurSlot <= cMaxSlotIndex, 'Ammo slot index overflow', true)
+ TryDo(slot <= cMaxSlotIndex, 'Ammo slot index overflow', true);
+ CurAmmoType:= Ammo^[slot, ammoidx].AmmoType;
end
end;
procedure ApplyAmmoChanges(var Hedgehog: THedgehog);
var s: shortstring;
+ CurWeapon: PAmmo;
begin
TargetPoint.X:= NoPointX;
@@ -298,13 +322,16 @@
begin
Timer:= 10;
- if (Ammo^[CurSlot, CurAmmo].Count = 0) then
+ CurWeapon:= GetAmmoEntry(Hedgehog);
+
+ if (CurWeapon^.Count = 0) then
SwitchToFirstLegalAmmo(Hedgehog);
- //bad things could happen here in case CurSlot is overflowing
- ApplyAngleBounds(Hedgehog, Ammo^[CurSlot, CurAmmo].AmmoType);
+ CurWeapon:= GetAmmoEntry(Hedgehog);
- with Ammo^[CurSlot, CurAmmo] do
+ ApplyAngleBounds(Hedgehog, CurWeapon^.AmmoType);
+
+ with CurWeapon^ do
begin
if AmmoType <> amNothing then
begin
@@ -323,19 +350,19 @@
Gear^.State:= Gear^.State and not gstHHChooseTarget;
isCursorVisible:= false
end;
- if (CurAmmoGear <> nil) and ((CurAmmoGear^.Ammo^.Propz and ammoprop_AltAttack) <> 0) then
- ShowCrosshair:= (CurAmmoGear^.Ammo^.Propz and ammoprop_NoCrossHair) = 0
+ if (CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) then
+ ShowCrosshair:= (Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_NoCrossHair) = 0
else
ShowCrosshair:= (Propz and ammoprop_NoCrosshair) = 0;
end
- end
+ end;
end;
procedure SwitchNotHeldAmmo(var Hedgehog: THedgehog);
begin
with Hedgehog do
- if ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_DontHold) <> 0) or
- (Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber >= 0) then
+ if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_DontHold) <> 0) or
+ (Ammoz[CurAmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber >= 0) then
SwitchToFirstLegalAmmo(Hedgehog);
end;
@@ -353,10 +380,10 @@
begin
for a:= 0 to cMaxSlotAmmoIndex do
with StoresList[i]^[slot, a] do
- if (Propz and ammoprop_NotBorder) <> 0 then
+ if (Propz and ammoprop_NotBorder) <> 0 then
begin
Count:= 0;
- InitialCount:= 0
+ InitialCounts[i][AmmoType]:= 0
end;
PackAmmo(StoresList[i], slot)
@@ -388,20 +415,17 @@
// Restore indefinitely disabled weapons and initial weapon counts. Only used for hog placement right now
procedure ResetWeapons;
-var i, slot, a: Longword;
- t: TAmmoType;
+var i, t: Longword;
+ a: TAmmoType;
begin
-for i:= 0 to Pred(StoreCnt) do
- for slot:= 0 to cMaxSlotIndex do
- begin
- for a:= 0 to cMaxSlotAmmoIndex do
- with StoresList[i]^[slot, a] do
- Count:= InitialCount;
+for t:= 0 to Pred(TeamsCount) do
+ with TeamsArray[t]^ do
+ for i:= 0 to cMaxHHIndex do
+ if Hedgehogs[i].Gear <> nil then
+ FillAmmoStore(Hedgehogs[i].Ammo, InitialCounts[Hedgehogs[i].AmmoStore]);
- PackAmmo(StoresList[i], slot)
- end;
-for t:= Low(TAmmoType) to High(TAmmoType) do
- if Ammoz[t].SkipTurns >= 10000 then dec(Ammoz[t].SkipTurns,10000);
+for a:= Low(TAmmoType) to High(TAmmoType) do
+ if Ammoz[a].SkipTurns >= 10000 then dec(Ammoz[a].SkipTurns,10000)
end;
procedure initModule;
@@ -411,7 +435,8 @@
ammoLoadout:= '';
ammoProbability:= '';
ammoDelay:= '';
- ammoReinforcement:= ''
+ ammoReinforcement:= '';
+ FillChar(InitialCounts, sizeof(InitialCounts), 0)
end;
procedure freeModule;
--- a/hedgewars/uChat.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uChat.pas Wed Oct 27 14:02:20 2010 +0200
@@ -29,7 +29,7 @@
procedure DrawChat;
procedure KeyPressChat(Key: Longword);
-var UserNick: shortstring;
+var UserNick: shortstring = '';
ChatReady: boolean;
showAll: boolean;
@@ -253,11 +253,6 @@
ParseCommand('/taunt ' + char(i), true);
exit
end;
- if (s = '/newgrave') then
- begin
- ParseCommand('/newgrave', true);
- exit
- end;
end
else
ParseCommand('/say ' + s, true);
@@ -316,7 +311,6 @@
begin
lastStr:= 0;
visibleCount:= 0;
- UserNick:= '';
showAll:= false;
ChatReady:= false;
missedCount:= 0;
@@ -324,7 +318,7 @@
procedure freeModule;
begin
-
+ UserNick:= '';
end;
end.
--- a/hedgewars/uCollisions.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uCollisions.pas Wed Oct 27 14:02:20 2010 +0200
@@ -387,7 +387,7 @@
for i:= 0 to 8 do
begin
// using mx,my as temporary value buffer here
-
+
jfr:= 8+li+1;
jto:= 8+li-1;
--- a/hedgewars/uConsole.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uConsole.pas Wed Oct 27 14:02:20 2010 +0200
@@ -37,7 +37,7 @@
procedure doPut(putX, putY: LongInt; fromAI: boolean);
implementation
-uses uMisc, uStore, Types, uConsts, uGears, uTeams, uIO, uKeys, uWorld,
+uses uMisc, uStore, Types, uConsts, uGears, uTeams, uIO, uKeys, uWorld, uMobile,
uRandom, uAmmos, uStats, uChat, SDLh, uSound, uVisualGears, uScript;
const cLineWidth: LongInt = 0;
@@ -89,10 +89,11 @@
var Len: LongInt;
done: boolean;
begin
+{$IFNDEF NOCONSOLE}
{$IFDEF DEBUGFILE}AddFileLog('Console write: ' + s);{$ENDIF}
Write(s);
done:= false;
-
+
while not done do
begin
Len:= cLineWidth - Length(ConsoleLines[CurrLine].s);
@@ -106,16 +107,19 @@
end;
done:= (Length(s) = 0);
end;
+{$ENDIF}
end;
procedure WriteLnToConsole(s: shortstring);
begin
+{$IFNDEF NOCONSOLE}
WriteToConsole(s);
WriteLn;
inc(CurrLine);
if CurrLine = cLinesCount then
CurrLine:= 0;
PByte(@ConsoleLines[CurrLine].s)^:= 0
+{$ENDIF}
end;
procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean);
@@ -190,11 +194,11 @@
procedure StopMessages(Message: Longword);
begin
-if (Message and gm_Left) <> 0 then ParseCommand('/-left', true) else
-if (Message and gm_Right) <> 0 then ParseCommand('/-right', true) else
-if (Message and gm_Up) <> 0 then ParseCommand('/-up', true) else
-if (Message and gm_Down) <> 0 then ParseCommand('/-down', true) else
-if (Message and gm_Attack) <> 0 then ParseCommand('/-attack', true)
+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"}
@@ -204,14 +208,17 @@
CurrLine:= 0;
Variables:= nil;
isDeveloperMode:= true;
-
+
// initConsole
cLineWidth:= cScreenWidth div 10;
if cLineWidth > 255 then
cLineWidth:= 255;
- for i:= 0 to Pred(cLinesCount) do
+ 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 );
@@ -225,6 +232,7 @@
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('sd_turns', vtLongInt, @cSuddenDTurns , false);
RegisterVariable('damagepct',vtLongInt, @cDamagePercent , false);
@@ -257,7 +265,6 @@
RegisterVariable('skip' , vtCommand, @chSkip , false);
RegisterVariable('history' , vtCommand, @chHistory , true );
RegisterVariable('chat' , vtCommand, @chChat , true );
- RegisterVariable('newgrave', vtCommand, @chNewGrave , false);
RegisterVariable('say' , vtCommand, @chSay , true );
RegisterVariable('hogsay' , vtCommand, @chHogSay , true );
RegisterVariable('team' , vtCommand, @chTeamSay , true );
@@ -298,8 +305,6 @@
RegisterVariable('-cur_l' , vtCommand, @chCurL_m , true );
RegisterVariable('+cur_r' , vtCommand, @chCurR_p , true );
RegisterVariable('-cur_r' , vtCommand, @chCurR_m , true );
- RegisterVariable('flag' , vtCommand, @chFlag , false);
- RegisterVariable('script' , vtCommand, @chScript , false);
end;
procedure freeModule;
--- a/hedgewars/uConsts.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uConsts.pas Wed Oct 27 14:02:20 2010 +0200
@@ -33,14 +33,14 @@
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);
+ ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps);
TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame,
sprLag, sprArrow, sprGrenade, sprTargetP, sprBee,
@@ -71,11 +71,12 @@
sprAmTeleport, sprSplash, sprDroplet, sprBirdy, sprHandCake, sprHandConstruction,
sprHandGrenade, sprHandMelon, sprHandMortar, sprHandSkip, sprHandCluster,
sprHandDynamite, sprHandHellish, sprHandMine, sprHandSeduction, sprHandVamp,
- sprBigExplosion, sprSmokeRing, sprBeeTrace, sprEgg, sprTargetBee, sprHandBee,
+ sprBigExplosion, sprSmokeRing, sprBeeTrace, sprEgg, sprTargetBee, sprHandBee,
sprFeather, sprPiano, sprHandSineGun, sprPortalGun, sprPortal,
- sprCheese, sprHandCheese, sprHandFlamethrower
+ sprCheese, sprHandCheese, sprHandFlamethrower, sprChunk, sprNote,
+ sprSMineOff, sprSMineOn, sprHandSMine, sprHammer, sprHandResurrector
);
-
+
// Gears that interact with other Gears and/or Land
TGearType = (gtAmmo_Bomb, gtHedgehog, gtAmmo_Grenade, gtGrave, gtBee, // 4
gtShotgunShot, gtPickHammer, gtRope, gtMine, gtCase, // 9
@@ -86,7 +87,8 @@
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
+ gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 51
+ gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector);
// Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
@@ -94,7 +96,7 @@
vgtSteam, vgtAmmo, vgtSmoke, vgtSmokeWhite, vgtHealth, vgtShell,
vgtDust, vgtSplash, vgtDroplet, vgtSmokeRing, vgtBeeTrace, vgtEgg,
vgtFeather, vgtHealthTag, vgtSmokeTrace, vgtEvilTrace, vgtExplosion,
- vgtBigExplosion);
+ vgtBigExplosion, vgtChunk, vgtNote);
TGearsType = set of TGearType;
@@ -120,24 +122,29 @@
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);
+ sndSkip, sndSineGun, sndOoff1, sndOoff2, sndOoff3, sndWhack,
+ sndComeonthen, sndParachute, sndBump, sndResurrector);
- TAmmoType = (amNothing, amGrenade, amClusterBomb, amBazooka, amBee, amShotgun, amPickHammer,
- amSkip, amRope, amMine, amDEagle, amDynamite, amFirePunch, amWhip,
- amBaseballBat, amParachute, amAirAttack, amMineStrike, amBlowTorch,
- amGirder, amTeleport, amSwitch, amMortar, amKamikaze, amCake,
- amSeduction, amWatermelon, amHellishBomb, amNapalm, amDrill, amBallgun,
- amRCPlane, amLowGravity, amExtraDamage, amInvulnerable, amExtraTime,
- amLaserSight, amVampiric, amSniperRifle, amJetpack, amMolotov, amBirdy, amPortalGun,
- amPiano, amGasBomb, amSineGun, amFlamethrower);
+ 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);
- THWFont = (fnt16, fntBig, fntSmall, CJKfnt16, CJKfntBig, CJKfntSmall);
+ 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);
+ siClanHealth, siTeamStats, siPlayerKills, siMaxTeamDamage,
+ siMaxTeamKills, siMaxTurnSkips );
TWave = (waveRollup, waveSad, waveWave, waveHurrah, waveLemonade, waveShrug, waveJuggle);
@@ -157,7 +164,6 @@
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 *)
- InitialCount: LongWord;
NumPerTurn: LongWord;
Timer: LongWord;
Pos: LongWord;
@@ -183,10 +189,12 @@
PrevTexture, NextTexture: PTexture;
end;
- THogEffect = (heInvulnerable, hePoisoned);
+ THogEffect = (heInvulnerable, heResurrectable, hePoisoned);
TScreenFade = (sfNone, sfInit, sfToBlack, sfFromBlack, sfToWhite, sfFromWhite);
-const sfMax = 1000;
+const
+ sfMax = 1000;
+ cDefaultParamNum = 17;
// message constants
errmsgCreateSurface = 'Error creating SDL surface';
@@ -196,7 +204,6 @@
errmsgIncorrectUse = 'Incorrect use';
errmsgShouldntRun = 'This program shouldn''t be run manually';
errmsgWrongNumber = 'Wrong parameters number';
- errmsgSlotsOverflow = 'CurSlot overflowed';
msgLoading = 'Loading ';
msgOK = 'ok';
@@ -223,8 +230,8 @@
rqLowRes = $00000001; // use half land array
rqBlurryLand = $00000002; // downscaled terrain
rqNoBackground= $00000004; // don't draw background
- rqSimpleRope = $00000008; // avoid drawing rope
- rq2DWater = $00000010; // disabe 3D water effect
+ rqSimpleRope = $00000008; // draw rope using lines only
+ rq2DWater = $00000010; // disable 3D water effect
rqFancyBoom = $00000020; // no fancy explosion effects
rqKillFlakes = $00000040; // no flakes
rqSlowMenu = $00000080; // ammomenu appears with no animation
@@ -259,13 +266,13 @@
cPowerDivisor = 1500;
MAXNAMELEN = 192;
-
+
// some opengl headers do not have these macros
GL_BGR = $80E0;
GL_BGRA = $80E1;
GL_CLAMP_TO_EDGE = $812F;
GL_TEXTURE_PRIORITY = $8066;
-
+
cSendCursorPosTime : LongWord = 50;
cVisibleWater : LongInt = 128;
cCursorEdgesDist : LongInt = 100;
@@ -301,7 +308,9 @@
cKeyMaxIndex = 1023;
+ // do not change this value
cDefaultZoomLevel = 2.0;
+
{$IFDEF IPHONEOS}
cMaxZoomLevel = 0.5;
cMinZoomLevel = 3.5;
@@ -313,8 +322,6 @@
{$ENDIF}
cSendEmptyPacketTime = 1000;
-
- // from uTriggers
trigTurns = $80000001;
// Training Flags
@@ -324,28 +331,31 @@
tfSpawnTargets = $00000004;
tfIgnoreDelays = $00000008;
tfTargetRespawn = $00000010;
-
- gfAny = $FFFFFFFF;
- gfForts = $00000001;
- gfMultiWeapon = $00000002;
- gfSolidLand = $00000004;
- gfBorder = $00000008;
- gfDivideTeams = $00000010;
- gfLowGravity = $00000020;
- gfLaserSight = $00000040;
- gfInvulnerable = $00000080;
- gfMines = $00000100;
- gfVampiric = $00000200;
- gfKarma = $00000400;
- gfArtillery = $00000800;
- gfOneClanMode = $00001000;
- gfRandomOrder = $00002000;
- gfKing = $00004000;
- gfPlaceHog = $00008000;
- gfSharedAmmo = $00010000;
- gfDisableGirders = $00020000;
- gfExplosives = $00040000;
- gfDisableLandObjects = $00080000;
+
+ gfAny = $FFFFFFFF;
+ gfOneClanMode = $00000001; // used in trainings
+ gfMultiWeapon = $00000002; // used in trainings
+ gfSolidLand = $00000004;
+ gfBorder = $00000008;
+ gfDivideTeams = $00000010;
+ gfLowGravity = $00000020;
+ gfLaserSight = $00000040;
+ gfInvulnerable = $00000080;
+ gfMines = $00000100; // redundant? same effect as 'landadds 0'
+ gfVampiric = $00000200;
+ gfKarma = $00000400;
+ gfArtillery = $00000800;
+ gfForts = $00001000;
+ gfRandomOrder = $00002000;
+ gfKing = $00004000;
+ gfPlaceHog = $00008000;
+ gfSharedAmmo = $00010000;
+ gfDisableGirders = $00020000;
+ gfDisableLandObjects = $00040000;
+ gfAISurvival = $00080000;
+ gfInfAttack = $00100000;
+ gfResetWeps = $00200000;
+ gfPerHogAmmo = $00400000;
// NOTE: When adding new game flags, ask yourself
// if a "game start notice" would be useful. If so,
// add one in uWorld.pas - look for "AddGoal".
@@ -370,21 +380,21 @@
gstLoser = $00080000;
gstHHGone = $00100000;
- gm_Left = $00000001;
- gm_Right = $00000002;
- gm_Up = $00000004;
- gm_Down = $00000008;
- gm_Switch = $00000010;
- gm_Attack = $00000020;
- gm_LJump = $00000040;
- gm_HJump = $00000080;
- gm_Destroy= $00000100;
- gm_Slot = $00000200; // with param
- gm_Weapon = $00000400; // with param
- gm_Timer = $00000800; // with param
- gm_Animate= $00001000; // with param
- gm_Precise= $00002000;
- gmAllStoppable = gm_Left or gm_Right or gm_Up or gm_Down or gm_Attack or gm_Precise;
+ gmLeft = $00000001;
+ gmRight = $00000002;
+ gmUp = $00000004;
+ gmDown = $00000008;
+ gmSwitch = $00000010;
+ gmAttack = $00000020;
+ gmLJump = $00000040;
+ gmHJump = $00000080;
+ gmDestroy= $00000100;
+ gmSlot = $00000200; // with param
+ gmWeapon = $00000400; // with param
+ gmTimer = $00000800; // with param
+ gmAnimate= $00001000; // with param
+ gmPrecise= $00002000;
+ gmAllStoppable = gmLeft or gmRight or gmUp or gmDown or gmAttack or gmPrecise;
cMaxSlotIndex = 9;
cMaxSlotAmmoIndex = 5;
@@ -403,7 +413,7 @@
ammoprop_Utility = $00001000;
ammoprop_Effect = $00002000;
ammoprop_NoRoundEndHint=$10000000;
-
+
AMMO_INFINITE = 100;
EXPLAllDamageInRadius = $00000001;
@@ -413,6 +423,7 @@
EXPLDontDraw = $00000010;
EXPLNoGfx = $00000020;
EXPLPoisoned = $00000040;
+ EXPLDoNotTouchAny = $00000080;
posCaseAmmo = $00000001;
posCaseHealth = $00000002;
@@ -427,11 +438,11 @@
htName = $02;
htHealth = $04;
htTransparent = $08;
-
+
cHHFileName = 'Hedgehog';
cCHFileName = 'Crosshair';
cThemeCFGFilename = 'theme.cfg';
-
+
FontBorder = 2;
cPathz: array[TPathType] of shortstring = (
'', // ptNone
@@ -452,19 +463,10 @@
'Graphics/Hedgehog', // ptHedgehog
'Sounds/voices', // ptVoices
'Graphics/Hats', // ptHats
- 'Graphics/Flags' // ptFlags
+ 'Graphics/Flags', // ptFlags
+ 'Missions/Maps' // ptMissionMaps
);
-
-var PathPrefix: shortstring = './';
- Pathz: array[TPathType] of shortstring;
- CountTexz: array[1..Pred(AMMO_INFINITE)] of PTexture;
- LAND_WIDTH :longint;
- LAND_HEIGHT :longint;
- LAND_WIDTH_MASK :longWord;
- LAND_HEIGHT_MASK :longWord;
- cMaxCaptions : LongInt;
-const
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);
@@ -480,7 +482,8 @@
(Handle: nil;
Height: 10;
style: TTF_STYLE_NORMAL;
- Name: 'DejaVuSans-Bold.ttf'),
+ Name: 'DejaVuSans-Bold.ttf')
+ {$IFNDEF IPHONEOS}, // remove chinese fonts for now
(Handle: nil;
Height: 12;
style: TTF_STYLE_NORMAL;
@@ -493,6 +496,7 @@
Height: 10;
style: TTF_STYLE_NORMAL;
Name: 'wqy-zenhei.ttc')
+ {$ENDIF}
);
SpritesData: array[TSprite] of record
@@ -725,7 +729,7 @@
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;
+ (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
@@ -800,8 +804,24 @@
(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
- );
+ 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
Wavez: array [TWave] of record
Sprite: TSprite;
@@ -908,7 +928,7 @@
(FileName: 'Droplet2.ogg'; Path: ptSounds),// sndDroplet2
(FileName: 'Droplet3.ogg'; Path: ptSounds),// sndDroplet3
(FileName: 'egg.ogg'; Path: ptSounds),// sndEggBreak
- (FileName: 'pickhammer.ogg'; Path: ptSounds),// sndDrillRocket
+ (FileName: 'drillgun.ogg'; Path: ptSounds),// sndDrillRocket
(FileName: 'PoisonCough.ogg'; Path: ptVoices),// sndPoisonCough
(FileName: 'PoisonMoan.ogg'; Path: ptVoices),// sndPoisonMoan
(FileName: 'BirdyLay.ogg'; Path: ptSounds),// sndBirdyLay
@@ -927,7 +947,12 @@
(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: '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
@@ -950,7 +975,6 @@
NumberInCase: 0;
Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_DontHold or ammoprop_Effect;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -974,7 +998,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 3000;
Pos: 0;
@@ -998,7 +1021,6 @@
NumberInCase: 3;
Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
Count: 5;
- InitialCount: 5;
NumPerTurn: 0;
Timer: 3000;
Pos: 0;
@@ -1022,7 +1044,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1046,7 +1067,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Power or ammoprop_NeedTarget or ammoprop_DontHold;
Count: 2;
- InitialCount: 2;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1070,7 +1090,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_ForwMsgs;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 1;
Timer: 0;
Pos: 0;
@@ -1094,7 +1113,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_AttackInMove or ammoprop_NoCrosshair or ammoprop_DontHold;
Count: 2;
- InitialCount: 2;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1118,7 +1136,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_DontHold;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1146,7 +1163,6 @@
ammoprop_Utility or
ammoprop_AltAttack;
Count: 5;
- InitialCount: 5;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1170,7 +1186,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_AttackInMove or ammoprop_DontHold or ammoprop_AltUse;
Count: 2;
- InitialCount: 2;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1194,7 +1209,6 @@
NumberInCase: 2;
Ammo: (Propz: 0;
Count: 3;
- InitialCount: 3;
NumPerTurn: 3;
Timer: 0;
Pos: 0;
@@ -1218,7 +1232,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_AttackInMove or ammoprop_DontHold or ammoprop_AltUse;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1242,7 +1255,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_ForwMsgs or ammoprop_AttackInMove;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1266,7 +1278,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_NoCrosshair;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1290,7 +1301,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_DontHold;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1320,7 +1330,6 @@
ammoprop_Utility or
ammoprop_AltAttack;
Count: 2;
- InitialCount: 2;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1348,7 +1357,6 @@
ammoprop_DontHold or
ammoprop_NotBorder;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1376,7 +1384,6 @@
ammoprop_DontHold or
ammoprop_NotBorder;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1400,7 +1407,6 @@
NumberInCase: 2;
Ammo: (Propz: ammoprop_ForwMsgs;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1428,7 +1434,6 @@
ammoprop_Utility or
ammoprop_AttackingPut;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1457,7 +1462,6 @@
ammoprop_Utility or
ammoprop_DontHold;
Count: 2;
- InitialCount: 2;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1485,7 +1489,6 @@
ammoprop_Utility or
ammoprop_DontHold;
Count: 3;
- InitialCount: 3;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1509,7 +1512,6 @@
NumberInCase: 4;
Ammo: (Propz: 0;
Count: 4;
- InitialCount: 4;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1533,7 +1535,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold or ammoprop_AttackInMove;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1557,7 +1558,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_NoCrosshair or ammoprop_DontHold;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1581,7 +1581,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1605,7 +1604,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
Count: 0;
- InitialCount: 0;
NumPerTurn: 0;
Timer: 3000;
Pos: 0;
@@ -1629,7 +1627,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
Count: 0;
- InitialCount: 0;
NumPerTurn: 0;
Timer: 5000;
Pos: 0;
@@ -1657,7 +1654,6 @@
ammoprop_DontHold or
ammoprop_NotBorder;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1681,7 +1677,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1705,7 +1700,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 5001;
Pos: 0;
@@ -1731,7 +1725,6 @@
ammoprop_DontHold or
ammoprop_AltAttack};
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1760,7 +1753,6 @@
ammoprop_Utility or
ammoprop_Effect;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1789,7 +1781,6 @@
ammoprop_Utility or
ammoprop_Effect;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1818,7 +1809,6 @@
ammoprop_Utility or
ammoprop_Effect;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1847,7 +1837,6 @@
ammoprop_Utility or
ammoprop_Effect;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1876,7 +1865,6 @@
ammoprop_Utility or
ammoprop_Effect;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1905,7 +1893,6 @@
ammoprop_Utility or
ammoprop_Effect;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1929,7 +1916,6 @@
NumberInCase: 2;
Ammo: (Propz: 0;
Count: 2;
- InitialCount: 2;
NumPerTurn: 1;
Timer: 0;
Pos: 0;
@@ -1959,7 +1945,6 @@
ammoprop_Utility or
ammoprop_AltAttack;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -1983,7 +1968,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 3000;
Pos: 0;
@@ -2009,7 +1993,6 @@
ammoprop_NoCrosshair or
ammoprop_DontHold;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -2036,7 +2019,6 @@
ammoprop_DontHold or
ammoprop_Utility;
Count: 1;
- InitialCount: 1;
NumPerTurn: 3;
Timer: 0;
Pos: 0;
@@ -2064,7 +2046,6 @@
ammoprop_DontHold or
ammoprop_NotBorder;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -2088,7 +2069,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
Count: AMMO_INFINITE;
- InitialCount: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 3000;
Pos: 0;
@@ -2104,7 +2084,7 @@
PosSprite: sprWater;
ejectX: 0;
ejectY: 0),
-
+
// SineGun
(NameId: sidSineGun;
NameTex: nil;
@@ -2112,7 +2092,6 @@
NumberInCase: 2;
Ammo: (Propz: ammoprop_AttackInMove;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 0;
Pos: 0;
@@ -2136,7 +2115,6 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold;
Count: 1;
- InitialCount: 1;
NumPerTurn: 0;
Timer: 5001;
Pos: 0;
@@ -2151,8 +2129,77 @@
PosCount: 1;
PosSprite: sprWater;
ejectX: 0; //20;
- ejectY: -3)
- );
+ ejectY: -3),
+
+// Sticky Mine
+ (NameId: sidSMine;
+ NameTex: nil;
+ Probability: 100;
+ NumberInCase: 1;
+ Ammo: (Propz: ammoprop_Power or 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),
+
+ (NameId: sidResurrector;
+ NameTex: nil;
+ Probability: 0;
+ NumberInCase: 1;
+ Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_NoRoundEndHint;
+ 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)
+ );
+
conversionFormat: TSDL_PixelFormat = (
@@ -2181,48 +2228,7 @@
colorkey: 0;
alpha : 255
);
-
-procedure initModule;
-procedure freeModule;
implementation
-uses uMisc;
-
-procedure initModule;
-begin
- Pathz:= cPathz;
- {* REFERENCE
- 4096 -> $FFFFF000
- 2048 -> $FFFFF800
- 1024 -> $FFFFFC00
- 512 -> $FFFFFE00 *}
- if (cReducedQuality and rqLowRes) <> 0 then
- begin
- LAND_WIDTH:= 2048;
- LAND_HEIGHT:= 1024;
- LAND_WIDTH_MASK:= $FFFFF800;
- LAND_HEIGHT_MASK:= $FFFFFC00;
- end
- else
- begin
- LAND_WIDTH:= 4096;
- LAND_HEIGHT:= 2048;
- LAND_WIDTH_MASK:= $FFFFF000;
- LAND_HEIGHT_MASK:= $FFFFF800
- end;
-
-{$IFDEF IPHONEOS}
- if isPhone() then
- cMaxCaptions:= 3
- else
-{$ENDIF}
- cMaxCaptions:= 4;
-
-end;
-
-procedure freeModule;
-begin
- PathPrefix := './';
-end;
end.
--- a/hedgewars/uFloat.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uFloat.pas Wed Oct 27 14:02:20 2010 +0200
@@ -22,7 +22,6 @@
interface
{$IFDEF FPC}
-{$INLINE ON}
{$IFDEF ENDIAN_LITTLE}
type hwFloat = record
isNegative: boolean;
@@ -43,26 +42,26 @@
operator + (const z1, z2: hwFloat) z : hwFloat; inline;
operator - (const z1, z2: hwFloat) z : hwFloat; inline;
-operator - (const z1: hwFloat) z : hwFloat;
+operator - (const z1: hwFloat) z : hwFloat; inline;
-operator * (const z1, z2: hwFloat) z : hwFloat;
+operator * (const z1, z2: hwFloat) z : hwFloat; inline;
operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
-operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat;
-operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat;
+operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
+operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
-operator < (const z1, z2: hwFloat) b : boolean;
-operator > (const z1, z2: hwFloat) b : boolean;
+operator < (const z1, z2: hwFloat) b : boolean; inline;
+operator > (const z1, z2: hwFloat) b : boolean; inline;
function cstr(const z: hwFloat): shortstring;
-function hwRound(const t: hwFloat): LongInt;
-function hwAbs(const t: hwFloat): hwFloat;
+function hwRound(const t: hwFloat): LongInt; inline;
+function hwAbs(const t: hwFloat): hwFloat; inline;
function hwSqr(const t: hwFloat): hwFloat; inline;
function hwSqrt(const t: hwFloat): hwFloat; inline;
function Distance(const dx, dy: hwFloat): hwFloat;
function DistanceI(const dx, dy: LongInt): hwFloat;
function AngleSin(const Angle: Longword): hwFloat;
function AngleCos(const Angle: Longword): hwFloat;
-function SignAs(const num, signum: hwFloat): hwFloat;
+function SignAs(const num, signum: hwFloat): hwFloat; inline;
{$IFDEF FPC}
{$J-}
@@ -148,7 +147,7 @@
{$ENDIF}
implementation
-uses uMisc;
+//uses uMisc;
{$IFDEF FPC}
@@ -348,7 +347,7 @@
function AngleSin(const Angle: Longword): hwFloat;
begin
{$IFDEF DEBUGFILE}
-TryDo((Angle >= 0) and (Angle <= 2048), 'Sin param exceeds limits', true);
+//TryDo((Angle >= 0) and (Angle <= 2048), 'Sin param exceeds limits', true);
{$ENDIF}
AngleSin.isNegative:= false;
if Angle < 1024 then AngleSin.QWordValue:= SinTable[Angle]
@@ -358,7 +357,7 @@
function AngleCos(const Angle: Longword): hwFloat;
begin
{$IFDEF DEBUGFILE}
-TryDo((Angle >= 0) and (Angle <= 2048), 'Cos param exceeds limits', true);
+//TryDo((Angle >= 0) and (Angle <= 2048), 'Cos param exceeds limits', true);
{$ENDIF}
AngleCos.isNegative:= Angle > 1024;
if Angle < 1024 then AngleCos.QWordValue:= SinTable[1024 - Angle]
--- a/hedgewars/uGame.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uGame.pas Wed Oct 27 14:02:20 2010 +0200
@@ -26,7 +26,7 @@
////////////////////
implementation
////////////////////
-uses uMisc, uConsts, uKeys, uTeams, uIO, uAI, uGears, uScript;
+uses uMisc, uConsts, uKeys, uTeams, uIO, uAI, uGears, uScript, uSound, uMobile;
procedure DoGameTick(Lag: LongInt);
var i: LongInt;
@@ -65,7 +65,10 @@
SetBinds(CurrentTeam^.Binds);
//CurrentHedgehog^.Gear^.Message:= 0; <- produces bugs with further save restoring and demos
isSoundEnabled:= isSEBackup;
- GameType:= gmtLocal
+ if isSoundEnabled then playMusic;
+ GameType:= gmtLocal;
+ InitIPC;
+ perfExt_SaveFinishedSynching();
end;
end
else ProcessGears
--- a/hedgewars/uGears.pas Thu Aug 26 23:59:18 2010 +0200
+++ b/hedgewars/uGears.pas Wed Oct 27 14:02:20 2010 +0200
@@ -22,7 +22,7 @@
interface
uses SDLh, uConsts, uFloat, Math;
-
+
type
PGear = ^TGear;
TGearStepProcedure = procedure (Gear: PGear);
@@ -32,8 +32,7 @@
AdvBounce: Longword;
Invulnerable: Boolean;
RenderTimer: Boolean;
- Ammo : PAmmo;
- AmmoType : TAmmoType; // Used to track AmmoType at time of Gear creation, since Ammo can be reassigned
+ AmmoType : TAmmoType;
State : Longword;
X : hwFloat;
Y : hwFloat;
@@ -63,6 +62,7 @@
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;
@@ -77,10 +77,12 @@
PlacingHogs: boolean; // a convenience flag to indicate placement of hogs is still in progress
StepSoundTimer: LongInt;
StepSoundChannel: LongInt;
-
+
procedure initModule;
procedure freeModule;
function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
+function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content: Longword ): PGear;
+procedure ResurrectHedgehog(gear: PGear);
procedure ProcessGears;
procedure EndTurnCleanup;
procedure ApplyDamage(Gear: PGear; Damage: Longword; Source: TDamageSource);
@@ -113,12 +115,13 @@
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;
//procedure AmmoFlameWork(Ammo: PGear); forward;
+function GearsNear(Gear: PGear; Kind: TGearType; r: LongInt): TPGearArray; forward;
function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear; forward;
procedure SpawnBoxOfSmth; forward;
procedure AfterAttack; forward;
@@ -201,7 +204,12 @@
@doStepPiano,
@doStepBomb,
@doStepSineGunShot,
- @doStepFlamethrower
+ @doStepFlamethrower,
+ @doStepSMine,
+ @doStepPoisonCloud,
+ @doStepHammer,
+ @doStepHammerHit,
+ @doStepResurrector
);
procedure InsertGearToList(Gear: PGear);
@@ -214,7 +222,7 @@
ptmp:= tmp;
tmp:= tmp^.NextGear
end;
-
+
if ptmp <> tmp then
begin
Gear^.NextGear:= ptmp^.NextGear;
@@ -313,6 +321,9 @@
gear^.Friction:= _0_999;
gear^.Angle:= cMaxAngle div 2;
gear^.Z:= cHHZ;
+ if (GameFlags and gfAISurvival) <> 0 then
+ if PHedgehog(gear^.Hedgehog)^.BotLevel > 0 then
+ PHedgehog(gear^.Hedgehog)^.Effects[heResurrectable] := true;
end;
gtAmmo_Grenade: begin // bazooka
gear^.Radius:= 4;
@@ -338,6 +349,10 @@
gear^.Radius:= 10;
gear^.Timer:= 4000
end;
+ gtHammerHit: begin
+ gear^.Radius:= 8;
+ gear^.Timer:= 125
+ end;
gtRope: begin
gear^.Radius:= 3;
gear^.Friction:= _450;
@@ -354,6 +369,14 @@
else
gear^.Timer:= cMinesTime*1;
end;
+ gtSMine: begin
+ gear^.Health:= 10;
+ gear^.State:= gear^.State or gstMoving;
+ gear^.Radius:= 2;
+ gear^.Elasticity:= _0_55;
+ gear^.Friction:= _0_995;
+ gear^.Timer:= 500;
+ end;
gtCase: begin
gear^.ImpactSound:= sndGraveImpact;
gear^.nImpactSounds:= 1;
@@ -424,6 +447,7 @@
gear^.Friction:= _0_08
end;
gtWhip: gear^.Radius:= 20;
+ gtHammer: gear^.Radius:= 20;
gtKamikaze: begin
gear^.Health:= 2048;
gear^.Radius:= 20
@@ -471,7 +495,7 @@
gtJetpack: begin
gear^.Health:= 2000;
end;
- gtMolotov: begin
+ gtMolotov: begin
gear^.Radius:= 6;
end;
gtBirdy: begin
@@ -480,7 +504,7 @@
gear^.Health := 2000;
gear^.FlightTime := 2;
end;
- gtEgg: begin
+ gtEgg: begin
gear^.Radius:= 4;
gear^.Elasticity:= _0_6;
gear^.Friction:= _0_96;
@@ -508,7 +532,15 @@
gear^.Timer:= 10;
gear^.Health:= 500;
end;
- end;
+ gtPoisonCloud: begin
+ gear^.Timer:= 5000;
+ gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000;
+ end;
+ gtResurrector: begin
+ gear^.Radius := 100;
+ end;
+ end;
+
InsertGearToList(gear);
AddGear:= gear;
@@ -541,8 +573,8 @@
else if Gear^.Kind = gtHedgehog then
if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then
begin
- Gear^.Message:= gm_Destroy;
- CurAmmoGear^.Message:= gm_Destroy;
+ Gear^.Message:= gmDestroy;
+ CurAmmoGear^.Message:= gmDestroy;
exit
end
else
@@ -645,20 +677,24 @@
begin
tmp:= 0;
if PHedgehog(Gear^.Hedgehog)^.Effects[hePoisoned] then
- inc(tmp, min(ModifyDamage(5,Gear), max(0,Gear^.Health - 1 - Gear^.Damage)));
- inc(tmp, min(cHealthDecrease, max(0,Gear^.Health - 1 - Gear^.Damage)));
+ inc(tmp, ModifyDamage(5, Gear));
+ inc(tmp, cHealthDecrease);
if PHedgehog(Gear^.Hedgehog)^.King then
begin
flag:= false;
team:= PHedgehog(Gear^.Hedgehog)^.Team;
for i:= 0 to Pred(team^.HedgehogsNumber) do
- if (team^.Hedgehogs[i].Gear <> nil) and
- (not team^.Hedgehogs[i].King) and
- (team^.Hedgehogs[i].Gear^.Health > team^.Hedgehogs[i].Gear^.Damage)
+ if (team^.Hedgehogs[i].Gear <> nil) and
+ (not team^.Hedgehogs[i].King) and
+ (team^.Hedgehogs[i].Gear^.Health > team^.Hedgehogs[i].Gear^.Damage)
then flag:= true;
- if not flag then inc(tmp, min(5, max(0,Gear^.Health - 1 - Gear^.Damage)))
+ if not flag then inc(tmp, 5)
end;
- if tmp > 0 then ApplyDamage(Gear, tmp, dsPoison);
+ if tmp > 0 then
+ begin
+ inc(Gear^.Damage, min(tmp, max(0,Gear^.Health - 1 - Gear^.Damage)));
+ HHHurt(Gear^.Hedgehog, dsPoison);
+ end
end;
Gear:= Gear^.NextGear
@@ -667,6 +703,7 @@
procedure ProcessGears;
const delay: LongWord = 0;