merge
authorunc0rr
Sat, 11 Dec 2010 21:27:43 +0300
changeset 4508 2a14477d1d15
parent 4500 22d06b4be225 (current diff)
parent 4507 0f9b86942c19 (diff)
child 4509 816a0bff5019
merge
--- a/bin/CMakeLists.txt	Sat Dec 11 21:27:15 2010 +0300
+++ b/bin/CMakeLists.txt	Sat Dec 11 21:27:43 2010 +0300
@@ -1,7 +1,9 @@
 if(WIN32 AND NOT UNIX)
 	file(GLOB DLLs *.dll)
+	file(GLOB ICOs *.ico)
 	
 	install(FILES
 		${DLLs}
+		${ICOs}
 		DESTINATION bin)
 endif(WIN32 AND NOT UNIX)
--- a/hedgewars/PascalExports.pas	Sat Dec 11 21:27:15 2010 +0300
+++ b/hedgewars/PascalExports.pas	Sat Dec 11 21:27:43 2010 +0300
@@ -25,7 +25,6 @@
      uCommands;
 
 {$INCLUDE "config.inc"}
-type PPByte = ^PByte;
 var dummy: boolean;  // avoid compiler hint
 
 implementation
--- a/hedgewars/uMobile.pas	Sat Dec 11 21:27:15 2010 +0300
+++ b/hedgewars/uMobile.pas	Sat Dec 11 21:27:43 2010 +0300
@@ -57,7 +57,7 @@
 function isDeviceMute: Boolean; inline;
 begin
 {$IFDEF IPHONEOS}
-    exit(isAppleDeviceMuted());
+//    exit(isAppleDeviceMuted());
 {$ENDIF}
     exit(false);
 end;
--- a/hedgewars/uScript.pas	Sat Dec 11 21:27:15 2010 +0300
+++ b/hedgewars/uScript.pas	Sat Dec 11 21:27:43 2010 +0300
@@ -1028,6 +1028,18 @@
         end;
     lc_setwind:= 0
 end;
+
+function lc_getdatapath(L : Plua_State) : LongInt; Cdecl;
+begin
+    if lua_gettop(L) <> 0 then
+        begin
+        LuaError('Lua: Wrong number of parameters passed to GetDataPath!');
+        lua_pushnil(L);
+        end
+    else
+        lua_pushstring(L, str2pchar(Pathz[ptData]));
+    lc_getdatapath:= 1
+end;
 ///////////////////
 
 procedure ScriptPrintStack;
@@ -1082,7 +1094,6 @@
 end;
 
 procedure ScriptOnGameInit;
-var s, t : ansistring;
 begin
 // not required if there is no script to run
 if not ScriptLoaded then
@@ -1108,12 +1119,6 @@
 ScriptSetString('Map', '');
 ScriptSetString('Theme', '');
 
-// import locale
-s:= cLocaleFName;
-t:= '';
-SplitByChar(s, t, '.');
-ScriptSetString('L', s);
-
 ScriptCall('onGameInit');
 
 // pop game variables
@@ -1295,6 +1300,7 @@
     am : TAmmoType;
     st : TSound;
     he: THogEffect;
+    s, t : ansistring;
 begin
 // initialize lua
 luaState:= lua_open;
@@ -1310,6 +1316,12 @@
 ScriptSetInteger('LAND_WIDTH', LAND_WIDTH);
 ScriptSetInteger('LAND_HEIGHT', LAND_HEIGHT);
 
+// import locale
+s:= cLocaleFName;
+t:= '';
+SplitByChar(s, t, '.');
+ScriptSetString('L', s);
+
 // import game flags
 ScriptSetInteger('gfForts', gfForts);
 ScriptSetInteger('gfMultiWeapon', gfMultiWeapon);
@@ -1434,6 +1446,7 @@
 lua_register(luaState, 'SetGearMessage', @lc_setgearmessage);
 lua_register(luaState, 'GetRandom', @lc_getrandom);
 lua_register(luaState, 'SetWind', @lc_setwind);
+lua_register(luaState, 'GetDataPath', @lc_getdatapath);
 
 
 ScriptClearStack; // just to be sure stack is empty
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/HedgewarsMobile/Classes/Appirater.h	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,105 @@
+/*
+ This file is part of Appirater.
+ 
+ Copyright (c) 2010, Arash Payan
+ All rights reserved.
+ 
+ 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
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ 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
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ 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.
+ */
+/*
+ * Appirater.h
+ * appirater
+ *
+ * Created by Arash Payan on 9/5/09.
+ * http://arashpayan.com
+ * Copyright 2010 Arash Payan. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+extern NSString *const kAppiraterLaunchDate;
+extern NSString *const kAppiraterLaunchCount;
+extern NSString *const kAppiraterCurrentVersion;
+extern NSString *const kAppiraterRatedCurrentVersion;
+extern NSString *const kAppiraterDeclinedToRate;
+
+/*
+ Place your Apple generated software id here.
+ */
+#define APPIRATER_APP_ID                 391234866
+
+/*
+ Your app's name.
+ */
+#define APPIRATER_APP_NAME              [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]
+
+/*
+ This is the message your users will see once they've passed the day+launches
+ threshold.
+ */
+#define APPIRATER_MESSAGE               [NSString stringWithFormat:@"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!", APPIRATER_APP_NAME]
+
+/*
+ This is the title of the message alert that users will see.
+ */
+#define APPIRATER_MESSAGE_TITLE         [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME]
+
+/*
+ The text of the button that rejects reviewing the app.
+ */
+#define APPIRATER_CANCEL_BUTTON         NSLocalizedString(@"No thanks",@"")
+
+/*
+ Text of button that will send user to app review page.
+ */
+#define APPIRATER_RATE_BUTTON           [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME]
+
+/*
+ Text for button to remind the user to review later.
+ */
+#define APPIRATER_RATE_LATER            NSLocalizedString(@"Remind me later",@"")
+
+/*
+ Users will need to have the same version of your app installed for this many
+ days before they will be prompted to rate it.
+ */
+#define DAYS_UNTIL_PROMPT               5       // double
+
+/*
+ Users will need to launch the same version of the app this many times before
+ they will be prompted to rate it.
+ */
+#define LAUNCHES_UNTIL_PROMPT           10      // integer
+
+/*
+ 'YES' will show the Appirater alert everytime. Useful for testing how your message
+ looks and making sure the link to your app's review page works.
+ */
+#define APPIRATER_DEBUG                 NO      // bool
+
+@interface Appirater : NSObject <UIAlertViewDelegate> {
+
+}
+
++(void) appLaunched;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/HedgewarsMobile/Classes/Appirater.m	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,207 @@
+/*
+ This file is part of Appirater.
+ 
+ Copyright (c) 2010, Arash Payan
+ All rights reserved.
+ 
+ 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
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ 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
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ 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.
+ */
+/*
+ * Appirater.m
+ * appirater
+ *
+ * Created by Arash Payan on 9/5/09.
+ * http://arashpayan.com
+ * Copyright 2010 Arash Payan. All rights reserved.
+ */
+
+#import "Appirater.h"
+#import <SystemConfiguration/SCNetworkReachability.h>
+#import <netinet/in.h>
+
+NSString *const kAppiraterLaunchDate            = @"kAppiraterLaunchDate";
+NSString *const kAppiraterLaunchCount           = @"kAppiraterLaunchCount";
+NSString *const kAppiraterCurrentVersion        = @"kAppiraterCurrentVersion";
+NSString *const kAppiraterRatedCurrentVersion   = @"kAppiraterRatedCurrentVersion";
+NSString *const kAppiraterDeclinedToRate        = @"kAppiraterDeclinedToRate";
+
+NSString *templateReviewURL = @"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APP_ID&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software";
+
+@interface Appirater (hidden)
+
+-(BOOL) connectedToNetwork;
+
+@end
+
+@implementation Appirater (hidden)
+
+-(BOOL) connectedToNetwork {
+    // Create zero addy
+    struct sockaddr_in zeroAddress;
+    bzero(&zeroAddress, sizeof(zeroAddress));
+    zeroAddress.sin_len = sizeof(zeroAddress);
+    zeroAddress.sin_family = AF_INET;
+    
+    // Recover reachability flags
+    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
+    SCNetworkReachabilityFlags flags;
+    
+    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
+    CFRelease(defaultRouteReachability);
+    
+    if (!didRetrieveFlags) {
+        NSLog(@"Error. Could not recover network reachability flags");
+        return NO;
+    }
+    
+    BOOL isReachable = flags & kSCNetworkFlagsReachable;
+    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
+    BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;
+    
+    NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"];
+    NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL  cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
+    NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self];
+    
+    return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;
+}
+
+@end
+
+
+@implementation Appirater
+
++(void) appLaunched {
+    Appirater *appirater = [[Appirater alloc] init];
+    [NSThread detachNewThreadSelector:@selector(appLaunchedHandler) toTarget:appirater withObject:nil];
+}
+
+-(void) appLaunchedHandler {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+    if (APPIRATER_DEBUG) {
+        [self performSelectorOnMainThread:@selector(showPrompt) withObject:nil waitUntilDone:NO];
+        return;
+    }
+
+    BOOL willShowPrompt = NO;
+
+    // get the app's version
+    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey];
+
+    // get the version number that we've been tracking
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion];
+    if (trackingVersion == nil) {
+        trackingVersion = version;
+        [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
+    }
+    
+    if (APPIRATER_DEBUG)
+        DLog(@"APPIRATER Tracking version: %@", trackingVersion);
+
+    if ([trackingVersion isEqualToString:version]) {
+        // get the launch date
+        NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterLaunchDate];
+        if (timeInterval == 0) {
+            timeInterval = [[NSDate date] timeIntervalSince1970];
+            [userDefaults setDouble:timeInterval forKey:kAppiraterLaunchDate];
+        }
+
+        NSTimeInterval secondsSinceLaunch = [[NSDate date] timeIntervalSinceDate:[NSDate dateWithTimeIntervalSince1970:timeInterval]];
+        double secondsUntilPrompt = 60 * 60 * 24 * DAYS_UNTIL_PROMPT;
+
+        // get the launch count
+        int launchCount = [userDefaults integerForKey:kAppiraterLaunchCount];
+        launchCount++;
+        [userDefaults setInteger:launchCount forKey:kAppiraterLaunchCount];
+        if (APPIRATER_DEBUG)
+            NSLog(@"APPIRATER Launch count: %d", launchCount);
+
+        // have they previously declined to rate this version of the app?
+        BOOL declinedToRate = [userDefaults boolForKey:kAppiraterDeclinedToRate];
+
+        // have they already rated the app?
+        BOOL ratedApp = [userDefaults boolForKey:kAppiraterRatedCurrentVersion];
+
+        if (secondsSinceLaunch > secondsUntilPrompt &&
+             launchCount > LAUNCHES_UNTIL_PROMPT &&
+             !declinedToRate &&
+             !ratedApp) {
+            if ([self connectedToNetwork]) {	// check if they can reach the app store
+                willShowPrompt = YES;
+                [self performSelectorOnMainThread:@selector(showPrompt) withObject:nil waitUntilDone:NO];
+            }
+        }
+    } else {
+        // it's a new version of the app, so restart tracking
+        [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
+        [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterLaunchDate];
+        [userDefaults setInteger:1 forKey:kAppiraterLaunchCount];
+        [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion];
+        [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate];
+    }
+
+    [userDefaults synchronize];
+    if (!willShowPrompt)
+        [self autorelease];
+
+    [pool release];
+}
+
+-(void) showPrompt {
+    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE
+                                                        message:APPIRATER_MESSAGE
+                                                       delegate:self
+                                              cancelButtonTitle:APPIRATER_CANCEL_BUTTON
+                                              otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil];
+    [alertView show];
+    [alertView release];
+}
+
+-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger) buttonIndex {
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+
+    switch (buttonIndex) {
+        case 0:
+            // they don't want to rate it
+            [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate];
+            break;
+        case 1:
+            // they want to rate it
+            [[UIApplication sharedApplication] openURL:
+             [NSURL URLWithString:[templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%d", APPIRATER_APP_ID]]]];
+            
+            [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion];
+            break;
+        case 2:
+            // remind them later
+            break;
+        default:
+            break;
+    }
+
+    [userDefaults synchronize];
+
+    [self release];
+}
+
+@end
--- a/project_files/HedgewarsMobile/Classes/CommodityFunctions.h	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/CommodityFunctions.h	Sat Dec 11 21:27:43 2010 +0300
@@ -58,6 +58,7 @@
 #define IS_DUALHEAD()           ([[UIScreen class] respondsToSelector:@selector(screens)] && [[UIScreen screens] count] > 1)
 #define IS_IPAD()               (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
 #define IS_NOT_POWERFUL()       ([modelType() hasPrefix:@"iPhone1"] || [modelType() hasPrefix:@"iPod1,1"] || [modelType() hasPrefix:@"iPod2,1"])
+#define IS_NOT_VERY_POWERFUL()  ([modelType() hasPrefix:@"iPad1"]   || [modelType() hasPrefix:@"iPhone2"] || [modelType() hasPrefix:@"iPod3"]  )
 
 #define DEFAULT_NETGAME_PORT    46631
 
--- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.m	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.m	Sat Dec 11 21:27:43 2010 +0300
@@ -226,9 +226,6 @@
                                     [NSNumber numberWithInt:self.interfaceOrientation],@"orientation",
                                     nil];
 
-    // finally launch game and remove this controller
-    DLog(@"sending config %@", gameDictionary);
-
     NSDictionary *allDataNecessary = [NSDictionary dictionaryWithObjectsAndKeys:gameDictionary,@"game_dictionary", @"",@"savefile",
                                       [NSNumber numberWithBool:NO],@"netgame", nil];
     if (IS_IPAD())
--- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Sat Dec 11 21:27:43 2010 +0300
@@ -386,14 +386,15 @@
     [string release];
     // remove a trailing "" element
     [themeArray removeLastObject];
+
+    // remove images that are too big for certain devices without loading the whole image
     NSArray *mapArrayFull = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL];
     NSMutableArray *mapArray = [[NSMutableArray alloc] init];
     for (NSString *str in mapArrayFull) {
         CGSize imgSize = PSPNGSizeFromMetaData([MAPS_DIRECTORY() stringByAppendingFormat:@"%@/map.png",str]);
-        // remove images that are too big for certain devices
         if (IS_NOT_POWERFUL() && imgSize.height > 1024.0f)
             continue;
-        if ([modelType() hasPrefix:@"iPad1"] && imgSize.height > 1280.0f)
+        if (IS_NOT_VERY_POWERFUL() && imgSize.height > 1280.0f)
             continue;
         [mapArray addObject:str];
     }
@@ -402,10 +403,9 @@
     NSMutableArray *missionArray = [[NSMutableArray alloc] init];
     for (NSString *str in missionArrayFull) {
         CGSize imgSize = PSPNGSizeFromMetaData([MISSIONS_DIRECTORY() stringByAppendingFormat:@"%@/map.png",str]);
-        // remove images that are too big for certain devices
         if (IS_NOT_POWERFUL() && imgSize.height > 1024.0f)
             continue;
-        if ([modelType() hasPrefix:@"iPad1"] && imgSize.height > 1280.0f)
+        if (IS_NOT_VERY_POWERFUL() && imgSize.height > 1280.0f)
             continue;
         [missionArray addObject:str];
     }
--- a/project_files/HedgewarsMobile/Classes/ObjcExports.h	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/ObjcExports.h	Sat Dec 11 21:27:43 2010 +0300
@@ -31,5 +31,6 @@
 BOOL isGameRunning();
 void setGameRunning(BOOL value);
 NSInteger cachedGrenadeTime();
+void clearView();
 void setGrenadeTime(NSInteger value);
 void setAmmoMenuInstance(AmmoMenuViewController *instance);
--- a/project_files/HedgewarsMobile/Classes/ObjcExports.m	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/ObjcExports.m	Sat Dec 11 21:27:43 2010 +0300
@@ -96,6 +96,7 @@
 }
 
 void clearView() {
+    // don't use any engine calls here as this function is called every time the ammomenu is opened
     UIWindow *theWindow = (IS_DUALHEAD()) ? [SDLUIKitDelegate sharedAppDelegate].uiwindow : [[UIApplication sharedApplication] keyWindow];
     UIButton *theButton = (UIButton *)[theWindow viewWithTag:CONFIRMATION_TAG];
     UISegmentedControl *theSegment = (UISegmentedControl *)[theWindow viewWithTag:GRENADE_TAG];
@@ -155,33 +156,37 @@
     [amvc_instance updateAmmoVisuals];
 }
 
+/*
 // http://stackoverflow.com/questions/287543/how-to-programatically-sense-the-iphone-mute-switch
 BOOL isAppleDeviceMuted(void) {
     if (!gAudioSessionInited) {
         AudioSessionInterruptionListener inInterruptionListener = NULL;
         OSStatus error;
-        if ((error = AudioSessionInitialize (NULL, NULL, inInterruptionListener, NULL)))
+        if ((error = AudioSessionInitialize(NULL, NULL, inInterruptionListener, NULL)))
             DLog(@"*** Error *** error in AudioSessionInitialize: %d", error);
         else
             gAudioSessionInited = YES;
     }
     UInt32 propertySize = sizeof(CFStringRef);
+    BOOL muteResult = NO;
 
     // this checks if there is volume
     Float32 volume;
     OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputVolume, &propertySize, &volume);
     if (n != 0)
         DLog( @"AudioSessionGetProperty 'volume': %d", n );
-    BOOL volumeResult = (volume == 0.0);
+    BOOL volumeResult = (volume == 0.0f);
     
     // this checks if the device is muted
     CFStringRef state;
     n = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
     if (n != 0)
         DLog( @"AudioSessionGetProperty 'audioRoute': %d", n );
-    NSString *result = (NSString *)state;
-    BOOL muteResult = ([result length] == 0);
-    releaseAndNil(result);
-    
+    else {
+        NSString *result = (NSString *)state;
+        muteResult = ([result length] == 0);
+        releaseAndNil(result);
+    }
     return volumeResult || muteResult;
 }
+*/
--- a/project_files/HedgewarsMobile/Classes/OverlayViewController.m	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/OverlayViewController.m	Sat Dec 11 21:27:43 2010 +0300
@@ -395,6 +395,7 @@
             break;
         case 10:
             playSound(@"clickSound");
+            clearView();
             HW_pause();
             if (self.amvc.isVisible && IS_DUALHEAD() == NO) {
                 doDim();
@@ -405,6 +406,7 @@
             break;
         case 11:
             playSound(@"clickSound");
+            clearView();
             removeConfirmationInput();
             
             if (IS_DUALHEAD() || self.useClassicMenu == NO) {
--- a/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m	Sat Dec 11 21:27:43 2010 +0300
@@ -24,7 +24,6 @@
 #import "SDL_uikitopenglview.h"
 #import "SDL_uikitwindow.h"
 #import "SDL_events_c.h"
-#import "../SDL_sysvideo.h"
 #import "jumphack.h"
 #import "SDL_video.h"
 #import "SDL_mixer.h"
@@ -34,6 +33,8 @@
 #import "GameSetup.h"
 #import "MainMenuViewController.h"
 #import "OverlayViewController.h"
+#import "Appirater.h"
+#include <unistd.h>
 
 #ifdef main
 #undef main
@@ -41,16 +42,15 @@
 
 #define BLACKVIEW_TAG 17935
 #define SECONDBLACKVIEW_TAG 48620
-#define VALGRIND "/opt/valgrind/bin/valgrind"
+#define VALGRIND "/opt/fink/bin/valgrind"
 
 int main (int argc, char *argv[]) {
 #ifdef VALGRIND_REXEC
     // Using the valgrind build config, rexec ourself in valgrind
     // from http://landonf.bikemonkey.org/code/iphone/iPhone_Simulator_Valgrind.20081224.html
     if (argc < 2 || (argc >= 2 && strcmp(argv[1], "-valgrind") != 0))
-        execl(VALGRIND, VALGRIND, "--leak-check=full", argv[0], "-valgrind", NULL);
+        execl(VALGRIND, VALGRIND, "--leak-check=full", "--dsymutil=yes", argv[0], "-valgrind", NULL);
 #endif
-
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     int retVal = UIApplicationMain(argc, argv, nil, @"SDLUIKitDelegate");
     [pool release];
@@ -173,7 +173,7 @@
 }
 
 // override the direct execution of SDL_main to allow us to implement the frontend (or even using a nib)
--(void) applicationDidFinishLaunching:(UIApplication *)application {
+-(BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     [application setStatusBarHidden:YES];
 
     self.uiwindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
@@ -204,6 +204,9 @@
         [titleView release];
         [self.secondWindow makeKeyAndVisible];
     }
+
+    [Appirater appLaunched];
+    return YES;
 }
 
 -(void) applicationWillTerminate:(UIApplication *)application {
@@ -227,15 +230,15 @@
     if ([device respondsToSelector:@selector(isMultitaskingSupported)] &&
          device.multitaskingSupported &&
          self.isInGame) {
-        // there is a bug on iphone that presents a sdl view with a black screen, so it returns to frontend
-        if (IS_IPAD())
+        // multiasking in-game works only for ios >= 4.2, returns a black screen on other verions
+        if (NSClassFromString(@"UIPrintInfo"))
             HW_suspend();
         else {
-            // while screen is loading you can't call HW_terminate() so we close the app
+            // so the game returns to the configuration view
             if (isGameRunning())
                 HW_terminate(NO);
             else {
-                // force app closure
+                // while screen is loading you can't call HW_terminate() so we close the app
                 SDL_SendQuit();
                 HW_terminate(YES);
                 longjmp(*(jump_env()), 1);
--- a/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m	Sat Dec 11 21:27:43 2010 +0300
@@ -236,7 +236,7 @@
     label.textColor = [UIColor whiteColor];
     label.numberOfLines = 1;
     if (section == 0)
-        label.text = NSLocalizedString(@"Tap to add hogs or change color, hold tap to remove team.",@"");
+        label.text = NSLocalizedString(@"Tap to add hogs or change color, touch and hold to remove team.",@"");
     else
         label.text = NSLocalizedString(@"The robot badge indicates an AI-controlled team.",@"");
 
--- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Sat Dec 11 21:27:15 2010 +0300
+++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Sat Dec 11 21:27:43 2010 +0300
@@ -113,6 +113,7 @@
 		6165925511CA9CB400D6E256 /* MapConfigViewController-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6165924D11CA9CB400D6E256 /* MapConfigViewController-iPad.xib */; };
 		6165925811CA9CB400D6E256 /* OverlayViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6165925011CA9CB400D6E256 /* OverlayViewController.xib */; };
 		6165929E11CA9E2F00D6E256 /* SDL_uikitappdelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6165929D11CA9E2F00D6E256 /* SDL_uikitappdelegate.m */; };
+		6172555A12B3DD4A0098D069 /* libLua.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6172555912B3DCEE0098D069 /* libLua.a */; };
 		6172FED91298CF9800D73365 /* background~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = 6172FED71298CF9800D73365 /* background~iphone.png */; };
 		6172FEEF1298D25D00D73365 /* mediumBackground~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 6172FEEB1298D25D00D73365 /* mediumBackground~ipad.png */; };
 		6172FEF11298D25D00D73365 /* smallerBackground~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 6172FEED1298D25D00D73365 /* smallerBackground~ipad.png */; };
@@ -163,7 +164,6 @@
 		6199E81A12463EC400DADF8C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6199E81912463EC400DADF8C /* SystemConfiguration.framework */; };
 		6199E839124647DE00DADF8C /* SupportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6199E837124647DE00DADF8C /* SupportViewController.m */; };
 		6199E86D12464A8E00DADF8C /* surprise.png in Resources */ = {isa = PBXBuildFile; fileRef = 6199E86C12464A8E00DADF8C /* surprise.png */; };
-		619C5ACF124F7DE200D041AE /* libLua.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 619C5ACE124F7DDF00D041AE /* libLua.a */; };
 		619C5AF4124F7E3100D041AE /* LuaPas.pas in Sources */ = {isa = PBXBuildFile; fileRef = 619C5AF3124F7E3100D041AE /* LuaPas.pas */; };
 		619C5BA2124FA59000D041AE /* MapPreviewButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 619C5BA1124FA59000D041AE /* MapPreviewButtonView.m */; };
 		61A1188511683A8C00359010 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61A117FE1168322700359010 /* CoreGraphics.framework */; settings = {ATTRIBUTES = (Required, ); }; };
@@ -182,6 +182,7 @@
 		61A670C012747D9B00B06CE7 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 6183D83D11E2BCE200A88903 /* Default.png */; };
 		61A670C112747DB900B06CE7 /* MainMenuViewController-iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6165924C11CA9CB400D6E256 /* MainMenuViewController-iPhone.xib */; };
 		61A670C212747DBD00B06CE7 /* MapConfigViewController-iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6165924E11CA9CB400D6E256 /* MapConfigViewController-iPhone.xib */; };
+		61AC067412B2E32D000B52A2 /* Appirater.m in Sources */ = {isa = PBXBuildFile; fileRef = 61AC067312B2E32D000B52A2 /* Appirater.m */; };
 		61B3D71C11EA6F2700EC7420 /* uKeys.pas in Sources */ = {isa = PBXBuildFile; fileRef = 617987FE114AA34C00BA94A9 /* uKeys.pas */; };
 		61C079E411F35A300072BF46 /* EditableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 61C079E311F35A300072BF46 /* EditableCellView.m */; };
 		61D205A1127CDD1100ABD83E /* ObjcExports.m in Sources */ = {isa = PBXBuildFile; fileRef = 61D205A0127CDD1100ABD83E /* ObjcExports.m */; };
@@ -692,6 +693,27 @@
 			remoteGlobalIDString = BE1FA74107AF4C45004B6283;
 			remoteInfo = "Static Library";
 		};
+		6172555412B3DCEE0098D069 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 6172554E12B3DCEE0098D069 /* Lua.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 1D6058910D05DD3D006BFB54 /* Lua.app */;
+			remoteInfo = "Test Lua";
+		};
+		6172555612B3DCEE0098D069 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 6172554E12B3DCEE0098D069 /* Lua.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 506EE05E10304ED200A389B3 /* libcocos2d libraries.a */;
+			remoteInfo = "cocos2d libraries";
+		};
+		6172555812B3DCEE0098D069 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 6172554E12B3DCEE0098D069 /* Lua.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = E14CF7C110ABC177005470B6 /* libLua.a */;
+			remoteInfo = Lua;
+		};
 		617988D9114AAA3900BA94A9 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 617988D3114AAA3900BA94A9 /* SDLiPhoneOS.xcodeproj */;
@@ -727,27 +749,6 @@
 			remoteGlobalIDString = BE48FF6F07AFA9A900BB41DA;
 			remoteInfo = "Static Library";
 		};
-		619C5AC9124F7DDF00D041AE /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 1D6058910D05DD3D006BFB54;
-			remoteInfo = "Test Lua";
-		};
-		619C5ACB124F7DDF00D041AE /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 506EE05E10304ED200A389B3;
-			remoteInfo = "cocos2d libraries";
-		};
-		619C5ACD124F7DDF00D041AE /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = E14CF7C110ABC177005470B6;
-			remoteInfo = Lua;
-		};
 		928301590F10E41300CC5A3C /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
@@ -876,6 +877,7 @@
 		6165925011CA9CB400D6E256 /* OverlayViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = OverlayViewController.xib; path = Resources/OverlayViewController.xib; sourceTree = SOURCE_ROOT; };
 		6165929C11CA9E2F00D6E256 /* SDL_uikitappdelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_uikitappdelegate.h; path = Classes/SDL_uikitappdelegate.h; sourceTree = "<group>"; };
 		6165929D11CA9E2F00D6E256 /* SDL_uikitappdelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDL_uikitappdelegate.m; path = Classes/SDL_uikitappdelegate.m; sourceTree = "<group>"; };
+		6172554E12B3DCEE0098D069 /* Lua.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Lua.xcodeproj; path = ../../../Library/Lua/Lua.xcodeproj; sourceTree = SOURCE_ROOT; };
 		6172FEA21298C7F900D73365 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/Icons/Default@2x.png"; sourceTree = "<group>"; };
 		6172FEC81298CE4800D73365 /* savesButton@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "savesButton@2x.png"; path = "Resources/Frontend/savesButton@2x.png"; sourceTree = "<group>"; };
 		6172FECA1298CE4E00D73365 /* settingsButton@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "settingsButton@2x.png"; path = "Resources/Frontend/settingsButton@2x.png"; sourceTree = "<group>"; };
@@ -941,7 +943,6 @@
 		6199E836124647DE00DADF8C /* SupportViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SupportViewController.h; sourceTree = "<group>"; };
 		6199E837124647DE00DADF8C /* SupportViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SupportViewController.m; sourceTree = "<group>"; };
 		6199E86C12464A8E00DADF8C /* surprise.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = surprise.png; path = Resources/surprise.png; sourceTree = "<group>"; };
-		619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Lua.xcodeproj; path = ../../../Library/Lua/Lua.xcodeproj; sourceTree = SOURCE_ROOT; };
 		619C5AF3124F7E3100D041AE /* LuaPas.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = LuaPas.pas; path = ../../hedgewars/LuaPas.pas; sourceTree = SOURCE_ROOT; };
 		619C5BA0124FA59000D041AE /* MapPreviewButtonView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapPreviewButtonView.h; path = Classes/MapPreviewButtonView.h; sourceTree = "<group>"; };
 		619C5BA1124FA59000D041AE /* MapPreviewButtonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MapPreviewButtonView.m; path = Classes/MapPreviewButtonView.m; sourceTree = "<group>"; };
@@ -958,6 +959,8 @@
 		61A4A39212A5CCC2004D81E6 /* uUtils.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uUtils.pas; path = ../../hedgewars/uUtils.pas; sourceTree = SOURCE_ROOT; };
 		61A4A39312A5CCC2004D81E6 /* uVariables.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uVariables.pas; path = ../../hedgewars/uVariables.pas; sourceTree = SOURCE_ROOT; };
 		61A4A3A112A5CD56004D81E6 /* uCaptions.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uCaptions.pas; path = ../../hedgewars/uCaptions.pas; sourceTree = SOURCE_ROOT; };
+		61AC067212B2E32D000B52A2 /* Appirater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Appirater.h; path = Classes/Appirater.h; sourceTree = "<group>"; };
+		61AC067312B2E32D000B52A2 /* Appirater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Appirater.m; path = Classes/Appirater.m; sourceTree = "<group>"; };
 		61C079E211F35A300072BF46 /* EditableCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EditableCellView.h; path = Classes/EditableCellView.h; sourceTree = "<group>"; };
 		61C079E311F35A300072BF46 /* EditableCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EditableCellView.m; path = Classes/EditableCellView.m; sourceTree = "<group>"; };
 		61D2059F127CDD1100ABD83E /* ObjcExports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjcExports.h; path = Classes/ObjcExports.h; sourceTree = "<group>"; };
@@ -1011,10 +1014,10 @@
 				61272334117DF764005B90CF /* libSDL_image.a in Frameworks */,
 				61798996114AB3FF00BA94A9 /* libSDL_mixer.a in Frameworks */,
 				617988DB114AAA4200BA94A9 /* libSDLiPhoneOS.a in Frameworks */,
+				6172555A12B3DD4A0098D069 /* libLua.a in Frameworks */,
 				922F64900F10F53100DC6EC0 /* libfpc.a in Frameworks */,
 				611E03E711FA747C0077A41E /* libvorbis.a in Frameworks */,
 				611E0E5111FA92170077A41E /* libfreetype.a in Frameworks */,
-				619C5ACF124F7DE200D041AE /* libLua.a in Frameworks */,
 				1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
 				61A1188511683A8C00359010 /* CoreGraphics.framework in Frameworks */,
 				1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
@@ -1076,6 +1079,8 @@
 			children = (
 				6165929C11CA9E2F00D6E256 /* SDL_uikitappdelegate.h */,
 				6165929D11CA9E2F00D6E256 /* SDL_uikitappdelegate.m */,
+				61AC067212B2E32D000B52A2 /* Appirater.h */,
+				61AC067312B2E32D000B52A2 /* Appirater.m */,
 				61DE91561258B76800B80214 /* Custom UIs */,
 				32CA4F630368D1EE00C91783 /* Hedgewars_Prefix.pch */,
 				6165922911CA9BD500D6E256 /* PascalImports.h */,
@@ -1120,7 +1125,7 @@
 		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
-				619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */,
+				6172554E12B3DCEE0098D069 /* Lua.xcodeproj */,
 				611E02EC11FA74580077A41E /* cocos2d-iphone.xcodeproj */,
 				611E0E4B11FA92130077A41E /* freetype.xcodeproj */,
 				617988D3114AAA3900BA94A9 /* SDLiPhoneOS.xcodeproj */,
@@ -1342,6 +1347,16 @@
 			name = Overlay;
 			sourceTree = "<group>";
 		};
+		6172554F12B3DCEE0098D069 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				6172555512B3DCEE0098D069 /* Lua.app */,
+				6172555712B3DCEE0098D069 /* libcocos2d libraries.a */,
+				6172555912B3DCEE0098D069 /* libLua.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
 		61798892114AA56300BA94A9 /* inc */ = {
 			isa = PBXGroup;
 			children = (
@@ -1412,16 +1427,6 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
-		619C5AC1124F7DDF00D041AE /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				619C5ACA124F7DDF00D041AE /* Lua.app */,
-				619C5ACC124F7DDF00D041AE /* libcocos2d libraries.a */,
-				619C5ACE124F7DDF00D041AE /* libLua.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
 		61DE91561258B76800B80214 /* Custom UIs */ = {
 			isa = PBXGroup;
 			children = (
@@ -1620,8 +1625,8 @@
 					ProjectRef = 611E0E4B11FA92130077A41E /* freetype.xcodeproj */;
 				},
 				{
-					ProductGroup = 619C5AC1124F7DDF00D041AE /* Products */;
-					ProjectRef = 619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */;
+					ProductGroup = 6172554F12B3DCEE0098D069 /* Products */;
+					ProjectRef = 6172554E12B3DCEE0098D069 /* Lua.xcodeproj */;
 				},
 				{
 					ProductGroup = 6127232F117DF752005B90CF /* Products */;
@@ -2116,6 +2121,27 @@
 			remoteRef = 61272332117DF752005B90CF /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
+		6172555512B3DCEE0098D069 /* Lua.app */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.application;
+			path = Lua.app;
+			remoteRef = 6172555412B3DCEE0098D069 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		6172555712B3DCEE0098D069 /* libcocos2d libraries.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libcocos2d libraries.a";
+			remoteRef = 6172555612B3DCEE0098D069 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		6172555912B3DCEE0098D069 /* libLua.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libLua.a;
+			remoteRef = 6172555812B3DCEE0098D069 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
 		617988DA114AAA3900BA94A9 /* libSDLiPhoneOS.a */ = {
 			isa = PBXReferenceProxy;
 			fileType = archive.ar;
@@ -2151,27 +2177,6 @@
 			remoteRef = 618E27BA12A2C30700C20EF0 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
-		619C5ACA124F7DDF00D041AE /* Lua.app */ = {
-			isa = PBXReferenceProxy;
-			fileType = wrapper.application;
-			path = Lua.app;
-			remoteRef = 619C5AC9124F7DDF00D041AE /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		619C5ACC124F7DDF00D041AE /* libcocos2d libraries.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libcocos2d libraries.a";
-			remoteRef = 619C5ACB124F7DDF00D041AE /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		619C5ACE124F7DDF00D041AE /* libLua.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libLua.a;
-			remoteRef = 619C5ACD124F7DDF00D041AE /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
 /* End PBXReferenceProxy section */
 
 /* Begin PBXResourcesBuildPhase section */
@@ -2412,6 +2417,7 @@
 				61A4A3A212A5CD56004D81E6 /* uCaptions.pas in Sources */,
 				61E5D68D12AB006F00566F29 /* uLandPainted.pas in Sources */,
 				61F544C712AF1748007FD913 /* HoldTableViewCell.m in Sources */,
+				61AC067412B2E32D000B52A2 /* Appirater.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
--- a/share/hedgewars/Data/CMakeLists.txt	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/CMakeLists.txt	Sat Dec 11 21:27:43 2010 +0300
@@ -1,3 +1,3 @@
-foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc")
+foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc" "Scripts")
   add_subdirectory(${dir})
 endforeach(dir)
--- a/share/hedgewars/Data/Locale/CMakeLists.txt	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Locale/CMakeLists.txt	Sat Dec 11 21:27:43 2010 +0300
@@ -1,6 +1,7 @@
 file(GLOB txttrans2 ??.txt)
 file(GLOB txttrans5 ?????.txt)
 file(GLOB tsfiles *.ts)
+file(GLOB luafiles *.lua)
 
 QT4_ADD_TRANSLATION(QM ${tsfiles})
 
@@ -13,6 +14,7 @@
 	${txttrans2}
 	${txttrans5}
 	${QM}
+	${luafiles}
 	DESTINATION ${SHAREPATH}Data/Locale
 )
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Locale/de.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,27 @@
+locale = {
+	["Aiming Practice"] = "Zielübung", --Bazooka, Shotgun, SniperRifle
+	["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Eliminiere alle Ziele bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.", --Bazooka, Shotgun, SniperRifle
+	["Oh no! Time's up! Just try again."] = "Oh nein! Die Zeit ist um! Versuche es nochmal.", --Bazooka, Shotgun, SniperRifle
+	["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.", --Bazooka, Shotgun, SniperRifle
+	["Hunter"] = "Jäger", --Bazooka, Shotgun, SniperRifle
+	["Bazooka Training"] = "Bazooka-Training",
+	["'Zooka Team"] = "Die Knalltüten",
+	["Shotgun Training"] = "Schrotflinten-Training",
+	["Shotgun Team"] = "Entrenamiento con escopeta",
+	["Sniper Training"] = "Scharfschützen-Training",
+	["Sniperz"] = "Heckenschützen",
+	["Not So Friendly Match"] = "Kein-so-Freundschaftsspiel", -- Basketball, Knockball
+	["%s is out and Team %d|scored a point!| |Score:"] = "%s ist draußen und Team %d|erhält einen Punkt!| |Punktestand:", -- Basketball, Knockball
+	["%s is out and Team %d|scored a penalty!| |Score:"] = "%s ist draußen und Team %d|erhält eine Strafe!| |Punktestand:", -- Basketball, Knockball
+	["Hedgewars-Basketball"] = "Hedgewars-Basketball",
+	["Bat your opponents through the|baskets and out of the map!"] = "Schlage deine Widersacher durch|die Körbe und aus der Karte hinaus!",
+	["Hedgewars-Knockball"] = "Hedgewars-Knockball",
+	["Bat balls at your enemies and|push them into the sea!"] = "Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!",
+--	["TrophyRace"] = 
+--	["Use your rope to get from start to finish as fast as you can!"] = 
+--	["You've reached the goal!| |Time: "] = 
+--	["NEW fastest lap: "] = 
+--	["Fastest lap: "] = 
+--	["Best laps per team: "] = 
+--	["Team %d: "] = 
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Locale/es.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,27 @@
+locale = {
+	["Aiming Practice"] = "Practica tu puntería", --Bazooka, Shotgun, SniperRifle
+	["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Destruye todos los objetivos antes de que se agote el tiempo.|La munición en esta misión es ilimitada.", --Bazooka, Shotgun, SniperRifle
+	["Oh no! Time's up! Just try again."] = "¡Oh, no, se te acabó el tiempo! ¿Por qué no lo intentas de nuevo?", --Bazooka, Shotgun, SniperRifle
+	["Congratulations! You've eliminated all targets|within the allowed time frame."] = "¡Felicidades! Has destruido todos los objectivos|dentro del tiempo establecido.", --Bazooka, Shotgun, SniperRifle
+	["Hunter"] = "Artillero", --Bazooka, Shotgun, SniperRifle
+	["Bazooka Training"] = "Entrenamiento con bazuca",
+	["'Zooka Team"] = "Bazuqueros",
+	["Shotgun Training"] = "Entrenamiento con escopeta",
+	["Shotgun Team"] = "Escopeteros",
+	["Sniper Training"] = "Entrenamiento con rifle francotirador",
+	["Sniperz"] = "Fusileros",
+	["Not So Friendly Match"] = "Partido no-tan-amistoso", -- Basketball, Knockball
+	["%s is out and Team %d|scored a point!| |Score:"] = "¡%s cayó y Equipo %d|anotó un tanto!| |Puntuación:", -- Basketball, Knockball
+	["%s is out and Team %d|scored a penalty!| |Score:"] = "¡%s cayó y Equipo %d|anotó una falta!| |Puntuación:", -- Basketball, Knockball
+	["Hedgewars-Basketball"] = "Hedgewars-Baloncesto",
+	["Bat your opponents through the|baskets and out of the map!"] = "¡Batea pelotas hacia tus enemigos|y hazlos caer al agua!",
+	["Hedgewars-Knockball"] = "Hedgewars-Knockball",
+	["Bat balls at your enemies and|push them into the sea!"] = "Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!",
+	["TrophyRace"] = "TrophyRace",
+	["Use your rope to get from start to finish as fast as you can!"] = "¡Usa tu cuerda para llegar a la salida lo más rápido que puedas!",
+	["You've reached the goal!| |Time: "] = "¡Has llegado a la meta!| |Tiempo: ",
+	["NEW fastest lap: "] = "NUEVA vuelta rápida: ",
+	["Fastest lap: "] = "Vuelta rápida: ",
+	["Best laps per team: "] = "Mejores tiempos por equipo: ",
+	["Team %d: "] = "Equipo %d",
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Locale/pl.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,27 @@
+locale = {
+	["Aiming Practice"] = "Potrenuj celność", --Bazooka, Shotgun, SniperRifle
+	["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Zniszcz wszystkie cele zanim upłynie czas.|W tej misji masz nieskończoną ilość amunicji.", --Bazooka, Shotgun, SniperRifle
+	["Oh no! Time's up! Just try again."] = "Ajajaj! Koniec czasu! Spróbuj jeszcze raz.", --Bazooka, Shotgun, SniperRifle
+	["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulacje! Zniszczyłeś wszystkie cele przed upłynięciem czasu.", --Bazooka, Shotgun, SniperRifle
+	["Hunter"] = "Strzelec", --Bazooka, Shotgun, SniperRifle
+	["Bazooka Training"] = "Trening bazooki",
+	["'Zooka Team"] = "Bazookinierzy",
+	["Shotgun Training"] = "Trening strzelecki",
+--	["Shotgun Team"] = 
+	["Sniper Training"] = "Trening Snajperski",
+	["Sniperz"] = "Snajperzy",
+	["Not So Friendly Match"] = "Mecz Nie-Do-Końca Towarzyski", -- Basketball, Knockball
+	["%s is out and Team %d|scored a point!| |Score:"] = "%s utonął i drużyna %d|zdobyła punkt!| |Punktacja:", -- Basketball, Knockball
+	["%s is out and Team %d|scored a penalty!| |Score:"] = "%s utonął i drużyna %d|dostała punkt karny!| |Punktacja:", -- Basketball, Knockball
+	["Hedgewars-Basketball"] = "Hedgewars-Koszykówka",
+	["Bat your opponents through the|baskets and out of the map!"] = "Uderzaj swoich przekiwników|wyrzucając przez kosz, poza mapę!",
+	["Hedgewars-Knockball"] = "Hedgewars-Knockball",
+	["Bat balls at your enemies and|push them into the sea!"] = "Uderzaj piłkami w swoich przeciwników|i strącaj ich do wody!",
+	["TrophyRace"] = "TrophyRace",
+	["Use your rope to get from start to finish as fast as you can!"] = "Użyj liny by jak najszybciej dotrzec od startu do mety",
+	["You've reached the goal!| |Time: "] = "Dotarłeś do celu!| |Czas: ",
+	["NEW fastest lap: "] = "NOWE najszybsze okrążenie: ",
+	["Fastest lap: "] = "Najszybsze okrążenie: ",
+	["Best laps per team: "] = "Najszybsze okrążenie drużyny: ",
+	["Team %d: "] = "Drużyna %d: ",
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Locale/pt_BR.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,27 @@
+locale = {
+	["Aiming Practice"] = "Pratique a sua pontaria", --Bazooka, Shotgun, SniperRifle
+	["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Destrua todos os alvos antes que o tempo acabe.|Você tem munição infinita para esta missão.", --Bazooka, Shotgun, SniperRifle
+	["Oh no! Time's up! Just try again."] = "Oh não! O tempo acabou! Tente novamente.", --Bazooka, Shotgun, SniperRifle
+	["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Parabéns! Você eliminou todos os alvos|dentro do tempo limite.", --Bazooka, Shotgun, SniperRifle
+	["Hunter"] = "Artilheiro", --Bazooka, Shotgun, SniperRifle
+	["Bazooka Training"] = "Treino com a Bazuca",
+	["'Zooka Team"] = "Bazuqueiros",
+	["Shotgun Training"] = "Treino com a Escopeta",
+	["Shotgun Team"] = "Carabineiros",
+	["Sniper Training"] = "Treino com o Rifle Sniper",
+	["Sniperz"] = "Franco-Atiradores",
+	["Not So Friendly Match"] = "Partida não muito amigável", -- Basketball, Knockball
+	["%s is out and Team %d|scored a point!| |Score:"] = "%s está fora e a Equipe %d|marcou um ponto!| |Pontuação:", -- Basketball, Knockball
+	["%s is out and Team %d|scored a penalty!| |Score:"] = "%s está fora e a Equipe %d|sofreu uma penalidade!| |Pontuação:", -- Basketball, Knockball
+	["Hedgewars-Basketball"] = "Hedgewars-Basketball",
+	["Bat your opponents through the|baskets and out of the map!"] = "Rebata seus oponentes para|fora do mapa através dos cestos!",
+	["Hedgewars-Knockball"] = "Hedgewars-Knockball",
+	["Bat balls at your enemies and|push them into the sea!"] = "Rebata as bolas em direção ao seus|e derrube-os no mar!",
+	["TrophyRace"] = "TrophyRace",
+	["Use your rope to get from start to finish as fast as you can!"] = "Use sua corda para ir do início ao fim o mais rápido que você puder!",
+	["You've reached the goal!| |Time: "] = "Você alcançou o objetivo!| |Tempo: ",
+	["NEW fastest lap: "] = "NOVA volta mais rápida: ",
+	["Fastest lap: "] = "Volta mais rápida: ",
+	["Best laps per team: "] = "Melhor volta por equipe: ",
+	["Team %d: "] = "Equipe %d: ",
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Locale/pt_PT.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,27 @@
+locale = {
+	["Aiming Practice"] = "Pratica a tua pontaria", --Bazooka, Shotgun, SniperRifle
+	["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Destrói todos os alvos antes do tempo terminar.|Tens munições infinitas para esta missão.", --Bazooka, Shotgun, SniperRifle
+	["Oh no! Time's up! Just try again."] = "Oh não! Acabou o tempo! Tenta novamente.", --Bazooka, Shotgun, SniperRifle
+	["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Parabéns! Eliminaste todos os alvos|dentro do tempo limite.", --Bazooka, Shotgun, SniperRifle
+	["Hunter"] = "Comando", --Bazooka, Shotgun, SniperRifle
+	["Bazooka Training"] = "Treino com Bazuca",
+	["'Zooka Team"] = "Bazuqueiros",
+	["Shotgun Training"] = "Treino com Caçadeira",
+	["Shotgun Team"] = "Caçadores",
+	["Sniper Training"] = "Treino com Sniper",
+--	["Sniperz"] = 
+	["Not So Friendly Match"] = "Partida não muito amigável", -- Basketball, Knockball
+	["%s is out and Team %d|scored a point!| |Score:"] = "%s está fora e a equipa %d|soma um ponto!| |Pontuação:", -- Basketball, Knockball
+	["%s is out and Team %d|scored a penalty!| |Score:"] = "%s está fora e a equipa %d|perde um ponto!| |Pontuação:", -- Basketball, Knockball
+	["Hedgewars-Basketball"] = "Hedgewars-Basketball",
+	["Bat your opponents through the|baskets and out of the map!"] = "Bate os teus adversarios|fora do mapa acertando com eles no cesto!",
+	["Hedgewars-Knockball"] = "Hedgewars-Knockball",
+	["Bat balls at your enemies and|push them into the sea!"] = "Bate bolas contra os teus|enimigos e empurra-os ao mar!",
+	["TrophyRace"] = "TrophyRace",
+	["Use your rope to get from start to finish as fast as you can!"] = "Utilizando a corda, percorre o percurso do inicio ao fim o mais rápido que conseguires!",
+	["You've reached the goal!| |Time: "] = "Chegaste ao fim!| |Tempo: ",
+	["NEW fastest lap: "] = "NOVA volta recorde: ",
+	["Fastest lap: "] = "Volta mais rápida: ",
+	["Best laps per team: "] = "Melhores voltas por equipa: ",
+	["Team %d: "] = "Equipa %d: ",
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Locale/sk.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,27 @@
+locale = {
+	["Aiming Practice"] = "Tréning presnosti", --Bazooka, Shotgun, SniperRifle
+	["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Zneškodnite všetky ciele pred vypršaním času.|Na túto misiu máte neobmedzené množstvo streliva.", --Bazooka, Shotgun, SniperRifle
+	["Oh no! Time's up! Just try again."] = "Ale nie! Čas vypršal! Tak to skúste znovu.", --Bazooka, Shotgun, SniperRifle
+	["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulujem! Zneškodnili ste všetky ciele|v stanovenom čase.", --Bazooka, Shotgun, SniperRifle
+	["Hunter"] = "Lovec", --Bazooka, Shotgun, SniperRifle
+	["Bazooka Training"] = "Tréning s bazukou",
+	["'Zooka Team"] = "Bazuka tím",
+	["Shotgun Training"] = "Tréning s brokovnicou",
+	["Shotgun Team"] = "Shotgun tím",
+	["Sniper Training"] = "Tréning pre ostreľovačov",
+	["Sniperz"] = "Ostreľovači",
+	["Not So Friendly Match"] = "Nie tak celkom priateľský zápas", -- Basketball, Knockball
+	["%s is out and Team %d|scored a point!| |Score:"] = "%s je mimo hru a tím %d|získal bod!| |Skóre:", -- Basketball, Knockball
+	["%s is out and Team %d|scored a penalty!| |Score:"] = "%s je mimo hru a tím %d|dostal trestný bod!| |Skóre:", -- Basketball, Knockball
+	["Hedgewars-Basketball"] = "Hedgewars-Basketbal",
+	["Bat your opponents through the|baskets and out of the map!"] = "Odpálkujte vašich súperov do koša|a von z mapy!",
+	["Hedgewars-Knockball"] = "Hedgewars-Knockball",
+	["Bat balls at your enemies and|push them into the sea!"] = "Loptami triafajte vašich nepriateľov|a zhoďte ich tak do mora!",
+	["TrophyRace"] = "Preteky o trofej",
+	["Use your rope to get from start to finish as fast as you can!"] = "Použite lano na presun zo štartovnej pozície do cieľa tak rýchlo, ako to len viete!",
+	["You've reached the goal!| |Time: "] = "Dosiahli ste cieľ!| |Čas: ",
+	["NEW fastest lap: "] = "NOVÉ najrýchlejšie kolo: ",
+	["Fastest lap: "] = "Najrýchlejšie kolo: ",
+	["Best laps per team: "] = "Najrýchlejšie kolá podľa tímov: ",
+	["Team %d: "] = "Tím %d: ",
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Locale/sv.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,27 @@
+locale = {
+	["Aiming Practice"] = "Siktesövning", --Bazooka, Shotgun, SniperRifle
+	["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Förstör alla målen innan din tid tar slut.|Du har obegränsad ammunition för deta uppdrag", --Bazooka, Shotgun, SniperRifle
+	["Oh no! Time's up! Just try again."] = "Åh nej! Tiden är ute! Pröva igen.", --Bazooka, Shotgun, SniperRifle
+	["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Grattis! Du har förstört alla målen inom den|tillåtna tidsramen.", --Bazooka, Shotgun, SniperRifle
+	["Hunter"] = "Jägare", --Bazooka, Shotgun, SniperRifle
+	["Bazooka Training"] = "Bazookaträning",
+	["'Zooka Team"] = "Bazookalaget",
+	["Shotgun Training"] = "Hagelgevärsträning",
+	["Shotgun Team"] = "Hagelgevärslaget",
+	["Sniper Training"] = "Prickskyttesträning",
+	["Sniperz"] = "Prickskyttarna",
+	["Not So Friendly Match"] = "En inte så vänlig match", -- Basketball, Knockball
+	["%s is out and Team %d|scored a point!| |Score:"] = "%s är ute och lag %d|fick ett poäng!| |Poängställning:", -- Basketball, Knockball
+	["%s is out and Team %d|scored a penalty!| |Score:"] = "%s är ute och lag %d|fick ett straff!| |Poängställning:", -- Basketball, Knockball
+	["Hedgewars-Basketball"] = "Hedgewars-Basket",
+	["Bat your opponents through the|baskets and out of the map!"] = "Slå ner dina motståndare i|korgarna och ut ur kartan!",
+	["Hedgewars-Knockball"] = "Hedgewars-Knockball",
+	["Bat balls at your enemies and|push them into the sea!"] = "Slå bollar mot dina fiender|och slå ner dem i havet",
+	["TrophyRace"] = "TrophyRace",
+	["Use your rope to get from start to finish as fast as you can!"] = "Använd ditt rep för att ta dig från start till mål så fort som möjligt!",
+	["You've reached the goal!| |Time: "] = "Du har nått målet!| |Tid: ",
+	["NEW fastest lap: "] = "NYTT snabbast varv: ",
+	["Fastest lap: "] = "Snabbast varv: ",
+	["Best laps per team: "] = "Bästa varv per lag: ",
+	["Team %d: "] = "Lag %d: ",
+    }
--- a/share/hedgewars/Data/Maps/Basketball/map.lua	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Maps/Basketball/map.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -1,100 +1,6 @@
 -- Hedgewars - Basketball for 2+ Players
 
-local caption = {
-	["en"] = "Hedgewars-Basketball",
-	["de"] = "Hedgewars-Basketball",
-	["es"] = "Hedgewars-Baloncesto",
-	["pl"] = "Hedgewars-Koszykówka",
-	["pt_PT"] = "Hedgewars-Basketball",
-	["sk"] = "Hedgewars-Basketbal",
-	["sv"] = "Hedgewars-Basket",
-	["pt_BR"] = "Hedgewars-Basketball"
-	}
-
-local subcaption = {
-	["en"] = "Not So Friendly Match",
-	["de"] = "Kein-so-Freundschaftsspiel",
-	["es"] = "Partido no-tan-amistoso",
-	["pl"] = "Mecz Nie-Do-Końca Towarzyski",
-	["pt_PT"] = "Partida não muito amigável",
-	["sk"] = "Nie tak celkom priateľský zápas",
-	["sv"] = "En inte så vänlig match",
-	["pt_BR"] = "Partida não muito amigável"
-	}
-
-local goal = {
-	["en"] = "Bat your opponents through the|baskets and out of the map!",
-	["de"] = "Schlage deine Widersacher durch|die Körbe und aus der Karte hinaus!",
-	["es"] = "¡Batea a tus oponentes fuera del mapa a través de la canasta!",
-	["pl"] = "Uderzaj swoich przekiwników|wyrzucając przez kosz, poza mapę!",
-	["pt_PT"] = "Bate os teus adversarios|fora do mapa acertando com eles no cesto!",
-	["sk"] = "Odpálkujte vašich súperov do koša|a von z mapy!",
-	["sv"] = "Slå ner dina motståndare i|korgarna och ut ur kartan!",
-	["pt_BR"] = "Rebata seus oponentes para|fora do mapa através dos cestos!"
-	}
-
-local scored = {
-	["en"] = " scored a point!",
-	["de"] = " erhält einen Punkt!",
-	["es"] = " anotó un tanto!",
-	["pl"] = " zdobyła punkt!",
-	["pt_PT"] = " marca um cesto!",
-	["sk"] = " skóruje!",
-	["sv"] = " fick ett poäng",
-	["pt_BR"] = " fez uma cesta"
-	}
-
-local failed = {
-	["en"] = " scored a penalty!",
-	["de"] = " erhält eine Strafe!",
-	["es"] = " anotó una falta!",
-	["pl"] = " zdobyła punkt karny!",
-	["pt_PT"] = " perde um ponto!",
-	["sk"] = " dostáva trestný bod!",
-	["sv"] = " fick ett straff",
-	["pt_BR"] = " sofre uma penalidade"
-	}
-
-	local sscore = {
-	["en"] = "Score",
-	["de"] = "Punktestand",
-	["es"] = "Puntuación",
-	["pl"] = "Punktacja",
-	["pt_PT"] = "Pontuação",
-	["sk"] = "Skóre",
-	["sv"] = "Poängställning",
-	["pt_BR"] = "Pontuação"
-	}
-
-local team = {
-	["en"] = "Team",
-	["es"] = "Equipo",
-	["pl"] = "Drużyna",
-	["pt_PT"] = "Equipa",
-	["sk"] = "Tím",
-	["sv"] = "Lag",
-	["pt_BR"] = "Equipe"
-	}
-
-local drowning = {
-	["en"] = "is out and",
-	["de"] = "ist draußen und",
-	["es"] = "cayó y",
-	["pl"] = "jest wyautowany i",
-	["pt_PT"] = "está fora e",
-	["sk"] = "je mimo hru a",
-	["sv"] = "är ute och",
-	["pt_BR"] = "está fora e"
-	}
-
-local function loc(text)
-	if text == nil then return "**missing**"
-	elseif text[L] == nil then return text["en"]
-	else return text[L]
-	end
-end
-
----------------------------------------------------------------
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
 
 local score = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0}
 
@@ -111,7 +17,7 @@
 end
 
 function onGameStart()
-	ShowMission(loc(caption), loc(subcaption), loc(goal), -amBaseballBat, 0)
+	ShowMission(loc("Hedgewars-Basketball"), loc("Not So Friendly Match"), loc("Bat your opponents through the|baskets and out of the map!"), -amBaseballBat, 0)
 	started = true
 end
 
@@ -132,16 +38,18 @@
 	end
 	if (GetGearType(gear) == gtHedgehog) and CurrentHedgehog ~= nil then
 		local clan = GetHogClan(CurrentHedgehog)
-		local s = GetHogName(gear) .. " " .. loc(drowning) .. "|" .. loc(team) .. " " .. (clan + 1) .. " "
-		if GetHogClan(CurrentHedgehog) ~= GetHogClan(gear) then
-			score[clan] = score[clan] + 1
-			s = s .. loc(scored)
-		else
-			score[clan] = score[clan] - 1
-			s = s .. loc(failed)
+		local s
+		if clan ~= nil then
+			if GetHogClan(CurrentHedgehog) ~= GetHogClan(gear) then
+				score[clan] = score[clan] + 1
+				s = string.format(loc("%s is out and Team %d|scored a point!| |Score:"), GetHogName(gear), clan + 1)
+			else
+				score[clan] = score[clan] - 1
+				s = string.format(loc("%s is out and Team %d|scored a penalty!| |Score:"), GetHogName(gear), clan + 1)
+			end
+			s = s .. " " .. score[0]
+			for i = 1, ClansCount - 1 do s = s .. " - " .. score[i] end
+			ShowMission(loc("Hedgewars-Basketball"), loc("Not So Friendly Match"), s, -amBaseballBat, 0)
 		end
-		s = s .. "| |" .. loc(sscore) .. ": " .. score[0]
-		for i = 1, ClansCount - 1 do s = s .. " - " .. score[i] end
-		ShowMission(loc(caption), loc(subcaption), s, -amBaseballBat, 0)
 	end
 end
--- a/share/hedgewars/Data/Maps/Knockball/map.lua	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Maps/Knockball/map.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -1,68 +1,6 @@
 -- Hedgewars - Knockball for 2+ Players
 
-local caption = {
-	["en"] = "Hedgewars-Knockball",
-	["de"] = "Hedgewars-Knockball",
-	["es"] = "Hedgewars-Knockball",
-	["pl"] = "Hedgewars-Knockball",
-	["pt_PT"] = "Hedgewars-Knockball",
-	["sk"] = "Hedgewars-Knockball",
-	["sv"] = "Hedgewars-Knockball",
-	["pt_BR"] = "Hedgewars-Knockball"
-	}
-
-local subcaption = {
-	["en"] = "Not So Friendly Match",
-	["de"] = "Kein-so-Freundschaftsspiel",
-	["es"] = "Partido no-tan-amistoso",
-	["pl"] = "Mecz Nie-Do-Końca Towarzyski",
-	["pt_PT"] = "Partida não muito amigável",
-	["sk"] = "Nie tak celkom priateľský zápas",
-	["sv"] = "En inte så vänlig match",
-	["pt_BR"] = "Partida não muito amigável"
-	}
-
-local goal = {
-	["en"] = "Bat balls at your enemies and|push them into the sea!",
-	["de"] = "Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!",
-	["es"] = "¡Batea pelotas hacia tus enemigos|y hazlos caer al agua!",
-	["pl"] = "Uderzaj piłkami w swoich przeciwników|i strącaj ich do wody!",
-	["pt_PT"] = "Bate bolas contra os teus|enimigos e empurra-os ao mar!",
-	["sk"] = "Loptami triafajte vašich nepriateľov|a zhoďte ich tak do mora!",
-	["sv"] = "Slå bollar mot dina fiender|och slå ner dem i havet",
-	["pt_BR"] = "Rebata as bolas em direção ao seus|e derrube-os no mar!"
-	}
-
-local scored = {
-	["en"] = "%s is out and Team %d|scored a point!| |Score:",
-	["de"] = "%s ist draußen und Team %d|erhält einen Punkt!| |Punktestand:",
-	["es"] = "¡%s cayó y Equipo %d|anotó un tanto!| |Puntuación:",
-	["pl"] = "%s utonął i drużyna %d|zdobyła punkt!| |Punktacja:",
-	["pt_PT"] = "%s está fora e a equipa %d|soma um ponto!| |Pontuação:",
-	["sk"] = "%s je mimo hru a tím %d|získal bod!| |Skóre:",
-	["sv"] = "%s är ute och lag %d|fick ett poäng!| |Poängställning:",
-	["pt_BR"] = "%s está fora e a Equipe %d|marcou um ponto!| |Pontuação:"
-	}
-
-local failed = {
-	["en"] = "%s is out and Team %d|scored a penalty!| |Score:",
-	["de"] = "%s ist draußen und Team %d|erhält eine Strafe!| |Punktestand:",
-	["es"] = "¡%s cayó y Equipo %d|anotó una falta!| |Puntuación:",
-	["pl"] = "%s utonął i drużyna %d|dostała punkt karny!| |Punktacja:",
-	["pt_PT"] = "%s está fora e a equipa %d|perde um ponto!| |Pontuação:",
-	["sk"] = "%s je mimo hru a tím %d|dostal trestný bod!| |Skóre:",
-	["sv"] = "%s är ute och lag %d|fick ett straff!| |Poängställning:",
-	["pt_BR"] = "%s está fora e a Equipe %d|sofreu uma penalidade!| |Pontuação:"
-	}
-
-local function loc(text)
-	if text == nil then return "**missing**"
-	elseif text[L] == nil then return text["en"]
-	else return text[L]
-	end
-end
-
----------------------------------------------------------------
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
 
 local score = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0}
 
@@ -81,7 +19,7 @@
 end
 
 function onGameStart()
-	ShowMission(loc(caption), loc(subcaption), loc(goal), -amBaseballBat, 0)
+	ShowMission(loc("Hedgewars-Knockball"), loc("Not So Friendly Match"), loc("Bat balls at your enemies and|push them into the sea!"), -amBaseballBat, 0)
 	started = true
 end
 
@@ -118,14 +56,14 @@
 		if clan ~= nil then
 			if GetHogClan(CurrentHedgehog) ~= GetHogClan(gear) then
 				score[clan] = score[clan] + 1
-				s = string.format(loc(scored), GetHogName(gear), clan + 1)
+				s = string.format(loc("%s is out and Team %d|scored a point!| |Score:"), GetHogName(gear), clan + 1)
 			else
 				score[clan] = score[clan] - 1
-				s = string.format(loc(failed), GetHogName(gear), clan + 1)
+				s = string.format(loc("%s is out and Team %d|scored a penalty!| |Score:"), GetHogName(gear), clan + 1)
 			end
 			s = s .. " " .. score[0]
 			for i = 1, ClansCount - 1 do s = s .. " - " .. score[i] end
-			ShowMission(loc(caption), loc(subcaption), s, -amBaseballBat, 0)
+			ShowMission(loc("Hedgewars-Knockball"), loc("Not So Friendly Match"), s, -amBaseballBat, 0)
 		end
 	end
 end
--- a/share/hedgewars/Data/Maps/TrophyRace/map.lua	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Maps/TrophyRace/map.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -1,93 +1,6 @@
 -- Hedgewars - Roperace for 2+ Players
 
-local caption = {
-	["en"] = "TrophyRace",
-	["sv"] = "TrophyRace",
-	["pt_PT"] = "TrophyRace",
-	["pl"] = "TrophyRace",
-	["es"] = "TrophyRace",
-	["pt_BR"] = "TrophyRace",
-	["sk"] = "Preteky o trofej"
-	}
-
-local goal = {
-	["en"] = "Use your rope to get from start to finish as fast as you can!",
-	["sv"] = "Använd ditt rep för att ta dig från start till mål så fort som möjligt!",
-	["pt_PT"] = "Utilizando a corda, percorre o percurso do inicio ao fim o mais rápido que conseguires!",
-	["pl"] = "Użyj liny by jak najszybciej dotrzec od startu do mety",
-	["es"] = "¡Usa tu cuerda para llegar a la salida lo más rápido que puedas!",
-	["pt_BR"] = "Use sua corda para ir do início ao fim o mais rápido que você puder!",
-	["sk"] = "Použite lano na presun zo štartovnej pozície do cieľa tak rýchlo, ako to len viete!"
-	}
-
-local done = {
-	["en"] = "You've reached the goal!| |Time: ",
-	["sv"] = "Du har nått målet!| |Tid: ",
-	["pt_PT"] = "Chegaste ao fim!| |Tempo: ",
-	["pl"] = "Dotarłeś do celu!| |Czas: ",
-	["es"] = "¡Has llegado a la meta!| |Tiempo: ",
-	["pt_BR"] = "Você alcançou o objetivo!| |Tempo: ",
-	["sk"] = "Dosiahli ste cieľ!| |Čas: "
-	}
-
-local eliminated = {
-	["en"] = "Eliminating worst hedgehog this round...| |%s is OUT!",
-	["sv"] = "Eliminerar sämsta igelkott den här rundan...| |%s är UTE!",
-	["pt_PT"] = "A eliminar o pior ouriço da ronda...| |% está FORA!",
-	["pl"] = "Eliminujemy najgorszego jeża tej rundy...| |%s ODPADŁ!",
-	["es"] = "Eliminando al peor erizo de esta ronda...| |¡%s está FUERA!",
-	["pt_BR"] = "Eliminando o ouriço mais lento...| |%s vai para o chuveiro!",
-	["sk"] = "Eliminujem najhoršieho ježka tohto kola...| |%s je mimo hru!"
-	}
-
-local newbesttime = {
-	["en"] = "NEW fastest lap: ",
-	["sv"] = "NYTT snabbast varv: ",
-	["pt_PT"] = "NOVA volta recorde: ",
-	["pl"] = "NOWE najszybsze okrążenie: ",
-	["es"] = "NUEVA vuelta rápida: ",
-	["pt_BR"] = "NOVA volta mais rápida: ",
-	["sk"] = "NOVÉ najrýchlejšie kolo: "
-	}
-
-local oldbesttime = {
-	["en"] = "Fastest lap: ",
-	["sv"] = "Snabbast varv: ",
-	["pt_PT"] = "Volta mais rápida: ",
-	["pl"] = "Najszybsze okrążenie: ",
-	["es"] = "Vuelta rápida: ",
-	["pt_BR"] = "Volta mais rápida: ",
-	["sk"] = "Najrýchlejšie kolo: "
-	}
-
-local bestclantimes = {
-	["en"] = "Best laps per team: ",
-	["sv"] = "Bästa varv per lag: ",
-	["pt_PT"] = "Melhores voltas por equipa: ",
-	["pl"] = "Najszybsze okrążenie drużyny: ",
-	["es"] = "Mejores tiempos por equipo: ",
-	["pt_BR"] = "Melhor volta por equipe: ",
-	["sk"] = "Najrýchlejšie kolá podľa tímov: "
-	}
-
-local clantime = {
-	["en"] = "Team %d: ",
-	["sv"] = "Lag %d: ",
-	["pt_PT"] = "Equipa %d: ",
-	["pl"] = "Drużyna %d: ",
-	["es"] = "Equipo %d",
-	["pt_BR"] = "Equipe %d: ",
-	["sk"] = "Tím %d: "
-	}
-
-local function loc(text)
-	if text == nil then return "**missing**"
-	elseif text[L] == nil then return text["en"]
-	else return text[L]
-	end
-end
-
----------------------------------------------------------------
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
 
 -- store number of hedgehogs
 local numhhs = 0
@@ -140,7 +53,7 @@
 end
 
 function onGameStart()
-	ShowMission(loc(caption), "", loc(goal), -amRope, 0)
+	ShowMission(loc("TrophyRace"), "", loc("Use your rope to get from start to finish as fast as you can!"), -amRope, 0)
 	started = true
 	p=1820
 	for i = 0, numhhs - 1 do
@@ -196,15 +109,15 @@
 			if ttime < besttime then
 				besttime = ttime
 				besthog = CurrentHedgehog
-				hscore = hscore .. loc(newbesttime)
+				hscore = hscore .. loc("NEW fastest lap: ")
 			else
-				hscore = hscore .. loc(oldbesttime)
+				hscore = hscore .. loc("Fastest lap: ")
 			end
 			if ttime > worsttime then
 				worsttime = ttime
 				worsthog = CurrentHedgehog
 			end
-			hscore = hscore .. GetHogName(besthog) .. " - " .. (besttime / 1000) .. " s | |" .. loc(bestclantimes)
+			hscore = hscore .. GetHogName(besthog) .. " - " .. (besttime / 1000) .. " s | |" .. loc("Best laps per team: ")
 			
 			if clan == ClansCount -1 then
 				-- Time for elimination - worst hog is out and the worst hog vars are reset.
@@ -221,10 +134,10 @@
 				if clantimes[i] == 0 then
 					tt = "--"
 				end
-				hscore = hscore .. "|" .. string.format(loc(clantime), i+1) .. tt
+				hscore = hscore .. "|" .. string.format(loc("Team %d: "), i+1) .. tt
 			end
 			
-			ShowMission(loc(caption), "", loc(done) .. (ttime / 1000) .. " s" .. hscore, 0, 0)
+			ShowMission(loc("TrophyRace"), "", loc("You've reached the goal!| |Time: ") .. (ttime / 1000) .. " s" .. hscore, 0, 0)
 			TurnTimeLeft = 0
 		end
 	end
--- a/share/hedgewars/Data/Missions/Campaign/01#Boot Camp.lua	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/01#Boot Camp.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -1,5 +1,5 @@
 -- IMPORTANT -- THIS IS WORK IN PROGRESS AND VERY LIKELY TO BE CHANGED AGAIN
--- IMPORTANT -- SAVE YOURSELF THE WORK AND DON'T TRANSLATE THE TEXTS IF YOU FEAR STARTING OVER LATER!
+-- IMPORTANT -- DO NOT TRANSLATE THIS AS IT USES THE OLD SYSTEM AND WILL BE UPDATED LATER!
 
 local teamnames = {}
 local hognames = {}
--- a/share/hedgewars/Data/Missions/Training/Bazooka.lua	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Missions/Training/Bazooka.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -8,102 +8,12 @@
 -- following "--" is ignored.
 
 ---------------------------------------------------------------
--- At first we put all text we'd like to use in some arrays.
--- This way we're able to localize the text to be shown without
--- modifying other files.
--- The language to be used is stored in the global variable
--- 'L' that is set by the game (string).
--- Text may then be accessed using "arrayname[L]".
-
-local caption = {
-	["en"] = "Bazooka Training",
-	["de"] = "Bazooka-Training",
-	["es"] = "Entrenamiento con bazuca",
-	["pl"] = "Trening bazooki",
-	["pt_PT"] = "Treino com Bazuca",
-	["pt_BR"] = "Treino com a Bazuca",
-	["sv"] = "Bazookaträning",
-	["sk"] = "Tréning s bazukou"
-	-- To add other languages, just add lines similar to the
-	-- existing ones - don't forget the trailing ","!
-	}
-
-local subcaption = {
-	["en"] = "Aiming Practice",
-	["de"] = "Zielübung",
-	["es"] = "Practica tu puntería",
-	["pl"] = "Potrenuj celność",
-	["pt_PT"] = "Pratica a tua pontaria",
-	["pt_BR"] = "Pratique a sua pontaria",
-	["sv"] = "Siktesövning",
-	["sk"] = "Tréning presnosti"
-	}
-
-local goal = {
-	["en"] = "Eliminate all targets before your time runs out.|You have unlimited ammo for this mission.",
-	["de"] = "Eliminiere alle Ziele bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.",
-	["es"] = "Destruye todos los objetivos antes de que se agote el tiempo.|La munición en esta misión es ilimitada.",
-	["pl"] = "Zniszcz wszystkie cele zanim upłynie czas.|W tej misji masz nieskończoną ilość amunicji.",
-	["pt_PT"] = "Destrói todos os alvos antes do tempo terminar.|Tens munições infinitas para esta missão.",
-	["pt_BR"] = "Destrua todos os alvos antes que o tempo acabe.|Você tem munição infinita para esta missão.",
-	["sv"] = "Förstör alla målen innan din tid tar slut.|Du har obegränsad ammunition för deta uppdrag",
-	["sk"] = "Zneškodnite všetky ciele pred vypršaním času.|Na túto misiu máte neobmedzené množstvo streliva."
-	}
+-- At first we implement the localization library using loadfile.
+-- This allows us to localize strings without needing to think
+-- about translations.
+-- We can use the function loc(text) to localize a string.
 
-local timeout = {
-	["en"] = "Oh no! Time's up! Just try again.",
-	["de"] = "Oh nein! Die Zeit ist um! Versuche es nochmal.",
-	["es"] = "¡Oh, no, se te acabó el tiempo! ¿Por qué no lo intentas de nuevo?",
-	["pl"] = "Ajajaj! Koniec czasu! Spróbuj jeszcze raz.",
-	["pt_PT"] = "Oh não! Acabou o tempo! Tenta novamente.",
-	["pt_BR"] = "Oh não! O tempo acabou! Tente novamente.",
-	["sv"] = "Åh nej! Tiden är ute! Pröva igen.",
-	["sk"] = "Ale nie! Čas vypršal! Tak to skúste znovu."
-	}
-
-local success = {
-	["en"] = "Congratulations! You've eliminated all targets|within the allowed time frame.",
-	["de"] = "Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.",
-	["es"] = "¡Felicidades! Has destruido todos los objectivos|dentro del tiempo establecido.",
-	["pl"] = "Gratulacje! Zniszczyłeś wszystkie cele przed upłynięciem czasu.",
-	["pt_PT"] = "Parabéns! Eliminaste todos os alvos|dentro do tempo limite.",
-	["pt_BR"] = "Parabéns! Você eliminou todos os alvos|dentro do tempo limite.",
-	["sv"] = "Grattis! Du har förstört alla målen inom den|tillåtna tidsramen.",
-	["sk"] = "Gratulujem! Zneškodnili ste všetky ciele|v stanovenom čase."
-	}
-
-local teamname = {
-	["en"] = "'Zooka Team",
-	["de"] = "Die Knalltüten",
-	["es"] = "Bazuqueros",
-	["pl"] = "Bazookinierzy",
-	["pt_PT"] = "Bazuqueiros",
-	["pt_BR"] = "Bazuqueiros",
-	["sv"] = "Bazookalaget",
-	["sk"] = "Bazuka tím"
-	}
-
-local hogname = {
-	["en"] = "Hunter",
-	["de"] = "Jäger",
-	["es"] = "Artillero",
-	["pl"] = "Strzelec",
-	["pt_PT"] = "Comando",
-	["pt_BR"] = "Artilheiro",
-	["sv"] = "Jägare",
-	["sk"] = "Lovec"
-	}
-
--- To handle missing texts we define a small wrapper function that
--- we'll use to retrieve text.
-local function loc(text)
-	if text == nil then return "**missing**"
-	elseif text[L] == nil then return text["en"]
-	else return text[L]
-	end
-end
-
----------------------------------------------------------------
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
 
 -- This variable will hold the number of destroyed targets.
 local score = 0
@@ -171,9 +81,9 @@
 	Theme = "Bamboo"
 
 	-- Create the player team
-	AddTeam(loc(teamname), 14483456, "Simple", "Island", "Default")
+	AddTeam(loc("'Zooka Team"), 14483456, "Simple", "Island", "Default")
 	-- And add a hog to it
-	player = AddHog(loc(hogname), 0, 1, "NoHat")
+	player = AddHog(loc("Hunter"), 0, 1, "NoHat")
 	SetGearPosition(player, 1960, 1160)
 end
 
@@ -190,7 +100,7 @@
 	-- A negative icon parameter (-n) represents the n-th weapon icon
 	-- A positive icon paramter (n) represents the (n+1)-th mission icon
 	-- A timeframe of 0 is replaced with the default time to show.
-	ShowMission(loc(caption), loc(subcaption), loc(goal), -amBazooka, 0)
+	ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amBazooka, 0)
 end
 
 -- This function is called every game tick.
@@ -204,7 +114,7 @@
 	if TurnTimeLeft == 1 and score < score_goal then
 		game_lost = true
 		-- ... and show a short message.
-		ShowMission(loc(caption), loc(subcaption), loc(timeout), -amSkip, 0)
+		ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0)
 		-- How about killing our poor hog due to his poor performance?
 		SetHealth(player, 0)
 		-- Just to be sure set the goal time to 1 ms
@@ -253,7 +163,7 @@
 		else
 			if not game_lost then
 			-- Otherwise show that the goal was accomplished
-			ShowMission(loc(caption), loc(subcaption), loc(success), 0, 0)
+			ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0)
 			-- Also let the hogs shout "victory!"
 			PlaySound(sndVictory)
 			-- Save the time left so we may keep it.
--- a/share/hedgewars/Data/Missions/Training/Shotgun.lua	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Missions/Training/Shotgun.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -8,102 +8,12 @@
 -- following "--" is ignored.
 
 ---------------------------------------------------------------
--- At first we put all text we'd like to use in some arrays.
--- This way we're able to localize the text to be shown without
--- modifying other files.
--- The language to be used is stored in the global variable
--- 'L' that is set by the game (string).
--- Text may then be accessed using "arrayname[L]".
-
-local caption = {
-	["en"] = "Shotgun Training",
-	["de"] = "Schrotflinten-Training",
-	["es"] = "Entrenamiento con escopeta",
-	["pl"] = "Trening strzelecki",
-	["pt_PT"] = "Treino com Caçadeira",
-	["pt_BR"] = "Treino com a Escopeta",
-	["sv"] = "Hagelgevärsträning",
-	["sk"] = "Tréning s brokovnicou"
-	-- To add other languages, just add lines similar to the
-	-- existing ones - don't forget the trailing ","!
-	}
-
-local subcaption = {
-	["en"] = "Aiming Practice",
-	["de"] = "Zielübung",
-	["es"] = "Practica tu puntería",
-	["pl"] = "Potrenuj celność",
-	["pt_PT"] = "Pratica a tua pontaria",
-	["pt_BR"] = "Pratique a sua pontaria",
-	["sv"] = "Siktesövning",
-	["sk"] = "Tréning presnosti"
-	}
-
-local goal = {
-	["en"] = "Eliminate all targets before your time runs out.|You have unlimited ammo for this mission.",
-	["de"] = "Eliminiere alle Ziele bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.",
-	["es"] = "Destruye todos los objetivos antes de que se agote el tiempo.|La munición en esta misión es ilimitada.",
-	["pl"] = "Zniszcz wszystkie cele zanim upłynie czas.|W tej misji masz nieskończoną ilość amunicji.",
-	["pt_PT"] = "Destrói todos os alvos antes do tempo terminar.|Tens munições infinitas para esta missão.",
-	["pt_BR"] = "Destrua todos os alvos antes que o tempo acabe.|Você tem munição infinita para esta missão.",
-	["sv"] = "Förstör alla målen innan din tid tar slut.|Du har obegränsad ammunition för deta uppdrag",
-	["sk"] = "Zneškodnite všetky ciele pred vypršaním času.|Na túto misiu máte neobmedzené množstvo streliva."
-	}
+-- At first we implement the localization library using loadfile.
+-- This allows us to localize strings without needing to think
+-- about translations.
+-- We can use the function loc(text) to localize a string.
 
-local timeout = {
-	["en"] = "Oh no! Time's up! Just try again.",
-	["de"] = "Oh nein! Die Zeit ist um! Versuche es nochmal.",
-	["es"] = "¡Oh, no, se te acabó el tiempo! ¿Por qué no lo intentas de nuevo?",
-	["pl"] = "Ajajaj! Koniec czasu! Spróbuj jeszcze raz.",
-	["pt_PT"] = "Oh não! Acabou o tempo! Tenta novamente.",
-	["pt_BR"] = "Oh não! O tempo acabou! Tente novamente.",
-	["sv"] = "Åh nej! Tiden är ute! Pröva igen.",
-	["sk"] = "Ale nie! Čas vypršal! Tak to skúste znovu."
-	}
-
-local success = {
-	["en"] = "Congratulations! You've eliminated all targets|within the allowed time frame.",
-	["de"] = "Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.",
-	["es"] = "¡Felicidades! Has destruido todos los objectivos|dentro del tiempo establecido.",
-	["pl"] = "Gratulacje! Zniszczyłeś wszystkie cele przed upłynięciem czasu.",
-	["pt_PT"] = "Parabéns! Eliminaste todos os alvos|dentro do tempo limite.",
-	["pt_BR"] = "Parabéns! Você eliminou todos os alvos|dentro do tempo limite.",
-	["sv"] = "Grattis! Du har förstört alla målen inom den|tillåtna tidsramen.",
-	["sk"] = "Gratulujem! Zneškodnili ste všetky ciele|v stanovenom čase."
-	}
-
-local teamname = {
-	["en"] = "Shotgun Team",
-	["de"] = "Die Knalltüten",
-	["es"] = "Escopeteros",
-	["pl"] = "Shotgun Team",
-	["pt_PT"] = "Caçadores",
-	["pt_PT"] = "Carabineiros",
-	["sv"] = "Hagelgevärslaget",
-	["sk"] = "Shotgun tím"
-	}
-
-local hogname = {
-	["en"] = "Hunter",
-	["de"] = "Jäger",
-	["es"] = "Cazador",
-	["pl"] = "Strzelec",
-	["pt_PT"] = "Comando",
-	["pt_BR"] = "Caçador",
-	["sv"] = "Jägare",
-	["sk"] = "Lovec"
-	}
-
--- To handle missing texts we define a small wrapper function that
--- we'll use to retrieve text.
-local function loc(text)
-	if text == nil then return "**missing**"
-	elseif text[L] == nil then return text["en"]
-	else return text[L]
-	end
-end
-
----------------------------------------------------------------
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
 
 -- This variable will hold the number of destroyed targets.
 local score = 0
@@ -171,9 +81,9 @@
 	Theme = "Nature"
 
 	-- Create the player team
-	AddTeam(loc(teamname), 14483456, "Simple", "Island", "Default")
+	AddTeam(loc("Shotgun Team"), 14483456, "Simple", "Island", "Default")
 	-- And add a hog to it
-	player = AddHog(loc(hogname), 0, 1, "NoHat")
+	player = AddHog(loc("Hunter"), 0, 1, "NoHat")
 	SetGearPosition(player, 2334, 1254)
 end
 
@@ -190,7 +100,7 @@
 	-- A negative icon parameter (-n) represents the n-th weapon icon
 	-- A positive icon paramter (n) represents the (n+1)-th mission icon
 	-- A timeframe of 0 is replaced with the default time to show.
-	ShowMission(loc(caption), loc(subcaption), loc(goal), -amShotgun, 0)
+	ShowMission(loc("Shotgun Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amShotgun, 0)
 end
 
 -- This function is called every game tick.
@@ -204,7 +114,7 @@
 	if TurnTimeLeft == 1 and score < score_goal then
 		game_lost = true
 		-- ... and show a short message.
-		ShowMission(loc(caption), loc(subcaption), loc(timeout), -amSkip, 0)
+		ShowMission(loc("Shotgun Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0)
 		-- How about killing our poor hog due to his poor performance?
 		SetHealth(player, 0)
 		-- Just to be sure set the goal time to 1 ms
@@ -253,7 +163,7 @@
 		else
 			if not game_lost then
 			-- Otherwise show that the goal was accomplished
-			ShowMission(loc(caption), loc(subcaption), loc(success), 0, 0)
+			ShowMission(loc("Shotgun Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0)
 			-- Also let the hogs shout "victory!"
 			PlaySound(sndVictory)
 			-- Save the time left so we may keep it.
--- a/share/hedgewars/Data/Missions/Training/SniperRifle.lua	Sat Dec 11 21:27:15 2010 +0300
+++ b/share/hedgewars/Data/Missions/Training/SniperRifle.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -8,101 +8,12 @@
 -- following "--" is ignored.
 
 ---------------------------------------------------------------
--- At first we put all text we'd like to use in some arrays.
--- This way we're able to localize the text to be shown without
--- modifying other files.
--- The language to be used is stored in the global variable
--- 'L' that is set by the game (string).
--- Text may then be accessed using "arrayname[L]".
-
-local caption = {
-	["en"] = "Sniper Training",
-	["de"] = "Scharfschützen-Training",
-	["es"] = "Entrenamiento con rifle francotirador",
-	["pl"] = "Trening Snajperski",
-	["pt_PT"] = "Treino com Sniper",
-	["pt_BR"] = "Treino com o Rifle Sniper",
-	["sv"] = "Prickskyttesträning",
-	["sk"] = "Tréning pre ostreľovačov"
-	-- To add other languages, just add lines similar to the
-	-- existing ones - don't forget the trailing ","!
-	}
-
-local subcaption = {
-	["en"] = "Aiming Practice",
-	["de"] = "Zielübung",
-	["es"] = "Practica tu puntería",
-	["pl"] = "Potrenuj celność",
-	["pt_PT"] = "Pratica a tua pontaria",
-	["pt_BR"] = "Pratique a sua pontaria",
-	["sv"] = "Siktesövning",
-	["sk"] = "Tréning presnosti"
-	}
-
-local goal = {
-	["en"] = "Eliminate all targets before your time runs out.|You have unlimited ammo for this mission.",
-	["de"] = "Eliminiere alle Ziele bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.",
-	["es"] = "Destruye todos los objetivos antes de que se agote el tiempo.|La munición en esta misión es ilimitada.",
-	["pl"] = "Zniszcz wszystkie cele zanim upłynie czas.|W tej misji masz nieskończoną ilość amunicji.",
-	["pt_PT"] = "Destrói todos os alvos antes do tempo terminar.|Tens munições infinitas para esta missão.",
-	["pt_BR"] = "Destrua todos os alvos antes que o tempo acabe.|Você tem munição infinita para esta missão.",
-	["sv"] = "Förstör alla målen innan din tid tar slut.|Du har obegränsad ammunition för deta uppdrag",
-	["sk"] = "Zneškodnite všetky ciele pred vypršaním času.|Na túto misiu máte neobmedzené množstvo streliva."
-	}
+-- At first we implement the localization library using loadfile.
+-- This allows us to localize strings without needing to think
+-- about translations.
+-- We can use the function loc(text) to localize a string.
 
-local timeout = {
-	["en"] = "Oh no! Time's up! Just try again.",
-	["de"] = "Oh nein! Die Zeit ist um! Versuche es nochmal.",
-	["es"] = "¡Oh, no, se te acabó el tiempo! ¿Por qué no lo intentas de nuevo?",
-	["pl"] = "Ajajaj! Koniec czasu! Spróbuj jeszcze raz.",
-	["pt_PT"] = "Oh não! Acabou o tempo! Tenta novamente.",
-	["pt_BR"] = "Oh não! O tempo acabou! Tente novamente.",
-	["sv"] = "Åh nej! Tiden är ute! Pröva igen.",
-	["sk"] = "Ale nie! Čas vypršal! Tak to skúste znovu."
-	}
-
-local success = {
-	["en"] = "Congratulations! You've eliminated all targets|within the allowed time frame.",
-	["de"] = "Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.",
-	["es"] = "¡Felicidades! Has destruido todos los objectivos|dentro del tiempo establecido.",
-	["pl"] = "Gratulacje! Zniszczyłeś wszystkie cele przed upłynięciem czasu.",
-	["pt_PT"] = "Parabéns! Eliminaste todos os alvos|dentro do tempo limite.",
-	["pt_BR"] = "Parabéns! Você eliminou todos os alvos|dentro do tempo limite.",
-	["sv"] = "Grattis! Du har förstört alla målen inom den|tillåtna tidsramen.",
-	["sk"] = "Gratulujem! Zneškodnili ste všetky ciele|v stanovenom čase."
-	}
-
-local teamname = {
-	["en"] = "Sniperz",
-	["de"] = "Heckenschützen",
-	["es"] = "Fusileros",
-	["pl"] = "Snajperzy",
-	["pt_BR"] = "Franco-Atiradores",
-	["sv"] = "Prickskyttarna",
-	["sk"] = "Ostreľovači"
-	}
-
-local hogname = {
-	["en"] = "Hunter",
-	["de"] = "Jäger",
-	["es"] = "Francotirador",
-	["pl"] = "Strzelec",
-	["pt_PT"] = "Comando",
-	["pt_BR"] = "Caçador",
-	["sv"] = "Jägare",
-	["sk"] = "Lovec"
-	}
-
--- To handle missing texts we define a small wrapper function that
--- we'll use to retrieve text.
-local function loc(text)
-	if text == nil then return "**missing**"
-	elseif text[L] == nil then return text["en"]
-	else return text[L]
-	end
-end
-
----------------------------------------------------------------
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
 
 -- This variable will hold the number of destroyed targets.
 local score = 0
@@ -171,9 +82,9 @@
 	Theme = "City"
 
 	-- Create the player team
-	AddTeam(loc(teamname), 14483456, "Simple", "Island", "Default")
+	AddTeam(loc("Sniperz"), 14483456, "Simple", "Island", "Default")
 	-- And add a hog to it
-	player = AddHog(loc(hogname), 0, 1, "Sniper")
+	player = AddHog(loc("Hunter"), 0, 1, "Sniper")
 	SetGearPosition(player, 602, 1465)
 end
 
@@ -190,7 +101,7 @@
 	-- A negative icon parameter (-n) represents the n-th weapon icon
 	-- A positive icon paramter (n) represents the (n+1)-th mission icon
 	-- A timeframe of 0 is replaced with the default time to show.
-	ShowMission(loc(caption), loc(subcaption), loc(goal), -amSniperRifle, 0)
+	ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amSniperRifle, 0)
 end
 
 -- This function is called every game tick.
@@ -215,7 +126,7 @@
 	if TurnTimeLeft == 1 and score < score_goal then
 		game_lost = true
 		-- ... and show a short message.
-		ShowMission(loc(caption), loc(subcaption), loc(timeout), -amSkip, 0)
+		ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0)
 		-- How about killing our poor hog due to his poor performance?
 		SetHealth(player, 0)
 		-- Just to be sure set the goal time to 1 ms
@@ -381,7 +292,7 @@
 		else
 			if not game_lost then
 			-- Otherwise show that the goal was accomplished
-			ShowMission(loc(caption), loc(subcaption), loc(success), 0, 0)
+			ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0)
 			-- Also let the hogs shout "victory!"
 			PlaySound(sndVictory)
 			-- Save the time left so we may keep it.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/CMakeLists.txt	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,6 @@
+file(GLOB luafiles *.lua)
+
+install(FILES
+	${luafiles}
+	DESTINATION ${SHAREPATH}Data/Scripts)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Locale.lua	Sat Dec 11 21:27:43 2010 +0300
@@ -0,0 +1,10 @@
+local lang = loadfile(GetDataPath() .. "Locale/" .. tostring(L) .. ".lua")
+if lang ~= nil then
+    lang()
+end
+
+function loc(text)
+    if lang ~= nil and locale ~= nil and locale[text] ~= nil then return locale[text]
+    else return text
+    end
+end