Artillery mode, sniper rifle, speech bubble tweaks, fix of rope bug introduced by enabling hats in jump
authornemo
Sun, 03 May 2009 17:35:10 +0000
changeset 2023 41d3afaa20c7
parent 2022 9bbf8af42ace
child 2024 2985f3bd18b7
Artillery mode, sniper rifle, speech bubble tweaks, fix of rope bug introduced by enabling hats in jump
QTfrontend/ammoSchemeModel.cpp
QTfrontend/gamecfgwidget.cpp
QTfrontend/hedgewars.qrc
QTfrontend/hwconsts.cpp.in
QTfrontend/pages.cpp
QTfrontend/pages.h
QTfrontend/res/btnArtillery.png
QTfrontend/res/btnKarma.png
QTfrontend/res/btnVampiric.png
hedgewars/GSHandlers.inc
hedgewars/HHHandlers.inc
hedgewars/uAIAmmoTests.pas
hedgewars/uConsts.pas
hedgewars/uGears.pas
hedgewars/uLocale.pas
hedgewars/uMisc.pas
hedgewars/uStore.pas
share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png
share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw.png
share/hedgewars/Data/Graphics/Arrow.png
share/hedgewars/Data/Graphics/Hedgehog.png
share/hedgewars/Data/Graphics/Hedgehog/Vampiric.png
share/hedgewars/Data/Graphics/Hedgehog/amSniperRifle.png
share/hedgewars/Data/Graphics/Teleport.png
share/hedgewars/Data/Graphics/WindBar.png
share/hedgewars/Data/Graphics/WindL.png
share/hedgewars/Data/Graphics/WindR.png
share/hedgewars/Data/Locale/bg.txt
share/hedgewars/Data/Locale/cs.txt
share/hedgewars/Data/Locale/de.txt
share/hedgewars/Data/Locale/en.txt
share/hedgewars/Data/Locale/es.txt
share/hedgewars/Data/Locale/fi.txt
share/hedgewars/Data/Locale/fr.txt
share/hedgewars/Data/Locale/it.txt
share/hedgewars/Data/Locale/pl.txt
share/hedgewars/Data/Locale/pt-br.txt
share/hedgewars/Data/Locale/ru.txt
share/hedgewars/Data/Locale/sk.txt
share/hedgewars/Data/Locale/tr.txt
share/hedgewars/Data/Locale/uk.txt
share/hedgewars/Data/Locale/zh_CN.txt
share/hedgewars/Data/Locale/zh_TW.txt
--- a/QTfrontend/ammoSchemeModel.cpp	Fri May 01 11:58:22 2009 +0000
+++ b/QTfrontend/ammoSchemeModel.cpp	Sun May 03 17:35:10 2009 +0000
@@ -34,11 +34,12 @@
 		<< QVariant(true)          // add mines      8
 		<< QVariant(false)         // vampiric       9
 		<< QVariant(false)         // karma          10
-		<< QVariant(100)           // damage modfier 11
-		<< QVariant(45)            // turn time      12
-		<< QVariant(100)           // init health    13
-		<< QVariant(15)            // sudden death   14
-		<< QVariant(5)             // case prob      15
+		<< QVariant(false)         // artillery      11
+		<< QVariant(100)           // damage modfier 12
+		<< QVariant(45)            // turn time      13
+		<< QVariant(100)           // init health    14
+		<< QVariant(15)            // sudden death   15
+		<< QVariant(5)             // case prob      16
 		;
 
 AmmoSchemeModel::AmmoSchemeModel(QObject* parent, const QString & fileName) :
@@ -65,11 +66,12 @@
 		<< "mines"            //  8
 		<< "vampiric"         //  9
 		<< "karma"            // 10
-		<< "damagefactor"     // 11
-		<< "turntime"         // 12
-		<< "health"           // 13
-		<< "suddendeath"      // 14
-		<< "caseprobability"  // 15
+		<< "artillery"        // 11
+		<< "damagefactor"     // 12
+		<< "turntime"         // 13
+		<< "health"           // 14
+		<< "suddendeath"      // 15
+		<< "caseprobability"  // 16
 		;
 
 	QList<QVariant> proMode;
@@ -85,11 +87,12 @@
 		<< QVariant(false)         // add mines      8
 		<< QVariant(false)         // vampiric       9
 		<< QVariant(false)         // karma          10
-		<< QVariant(100)           // damage modfier 11
-		<< QVariant(15)            // turn time      12
-		<< QVariant(100)           // init health    13
-		<< QVariant(15)            // sudden death   14
-		<< QVariant(0)             // case prob      15
+		<< QVariant(false)         // artillery      11
+		<< QVariant(100)           // damage modfier 12
+		<< QVariant(15)            // turn time      13
+		<< QVariant(100)           // init health    14
+		<< QVariant(15)            // sudden death   15
+		<< QVariant(0)             // case prob      16
 		;
 
 	QList<QVariant> shoppa;
@@ -105,11 +108,12 @@
 		<< QVariant(false)         // add mines      8
 		<< QVariant(false)         // vampiric       9
 		<< QVariant(false)         // karma          10
-		<< QVariant(100)           // damage modfier 11
-		<< QVariant(30)            // turn time      12
-		<< QVariant(100)           // init health    13
-		<< QVariant(50)            // sudden death   14
-		<< QVariant(1)             // case prob      15
+		<< QVariant(false)         // artillery      11
+		<< QVariant(100)           // damage modfier 12
+		<< QVariant(30)            // turn time      13
+		<< QVariant(100)           // init health    14
+		<< QVariant(50)            // sudden death   15
+		<< QVariant(1)             // case prob      16
 		;
 
 	QList<QVariant> basketball;
@@ -125,11 +129,12 @@
 		<< QVariant(false)         // add mines      8
 		<< QVariant(false)         // vampiric       9
 		<< QVariant(false)         // karma          10
-		<< QVariant(100)           // damage modfier 11
-		<< QVariant(30)            // turn time      12
-		<< QVariant(100)           // init health    13
-		<< QVariant(15)            // sudden death   14
-		<< QVariant(0)             // case prob      15
+		<< QVariant(false)         // artillery      11
+		<< QVariant(100)           // damage modfier 12
+		<< QVariant(30)            // turn time      13
+		<< QVariant(100)           // init health    14
+		<< QVariant(15)            // sudden death   15
+		<< QVariant(0)             // case prob      16
 		;
 
 	schemes.append(defaultScheme);
--- a/QTfrontend/gamecfgwidget.cpp	Fri May 01 11:58:22 2009 +0000
+++ b/QTfrontend/gamecfgwidget.cpp	Sun May 03 17:35:10 2009 +0000
@@ -111,13 +111,15 @@
 		result |= 0x200;
 	if (schemeData(10).toBool())
 		result |= 0x400;
+	if (schemeData(11).toBool())
+		result |= 0x800;
 
 	return result;
 }
 
 quint32 GameCFGWidget::getInitHealth() const
 {
-	return schemeData(13).toInt();
+	return schemeData(14).toInt();
 }
 
 QStringList GameCFGWidget::getFullConfig() const
@@ -125,10 +127,10 @@
 	QStringList sl;
 	sl.append("eseed " + pMapContainer->getCurrentSeed());
 	sl.append(QString("e$gmflags %1").arg(getGameFlags()));
-	sl.append(QString("e$damagepct %1").arg(schemeData(11).toInt()));
-	sl.append(QString("e$turntime %1").arg(schemeData(12).toInt() * 1000));
-	sl.append(QString("e$sd_turns %1").arg(schemeData(14).toInt()));
-	sl.append(QString("e$casefreq %1").arg(schemeData(15).toInt()));
+	sl.append(QString("e$damagepct %1").arg(schemeData(12).toInt()));
+	sl.append(QString("e$turntime %1").arg(schemeData(13).toInt() * 1000));
+	sl.append(QString("e$sd_turns %1").arg(schemeData(15).toInt()));
+	sl.append(QString("e$casefreq %1").arg(schemeData(16).toInt()));
 	sl.append(QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()));
 
 	QString currentMap = pMapContainer->getCurrentMap();
--- a/QTfrontend/hedgewars.qrc	Fri May 01 11:58:22 2009 +0000
+++ b/QTfrontend/hedgewars.qrc	Sun May 03 17:35:10 2009 +0000
@@ -55,6 +55,7 @@
     <file>res/btnSolid.png</file>
     <file>res/btnVampiric.png</file>
     <file>res/btnKarma.png</file>
+    <file>res/btnArtillery.png</file>
     <file>res/iconBox.png</file>
     <file>res/iconHealth.png</file>
     <file>res/iconSuddenDeath.png</file>
--- a/QTfrontend/hwconsts.cpp.in	Fri May 01 11:58:22 2009 +0000
+++ b/QTfrontend/hwconsts.cpp.in	Sun May 03 17:35:10 2009 +0000
@@ -29,14 +29,14 @@
 QStringList * Themes;
 QStringList * mapList;
 
-QString * cDefaultAmmoStore = new QString("9391929422199121032235111001201000001");
+QString * cDefaultAmmoStore = new QString("93919294221991210322351110012010000012");
 QList< QPair<QString, QString> > cDefaultAmmos =
 	QList< QPair<QString, QString> >()
 	<< qMakePair(QString("Default"), *cDefaultAmmoStore)
-	<< qMakePair(QString("Crazy"),     QString("9999999999999999992999999999999999299"))
-	<< qMakePair(QString("Pro mode"),  QString("9090009000000000000009000000000000000"))
-	<< qMakePair(QString("Shoppa"),    QString("0000009900000000000000000000000000000"))
-	<< qMakePair(QString("Basketball"),QString("0000009000000900000000000000000000000"))
+	<< qMakePair(QString("Crazy"),     QString("99999999999999999929999999999999992999"))
+	<< qMakePair(QString("Pro mode"),  QString("90900090000000000000090000000000000000"))
+	<< qMakePair(QString("Shoppa"),    QString("00000099000000000000000000000000000000"))
+	<< qMakePair(QString("Basketball"),QString("00000090000009000000000000000000000000"))
 	;
 
 QColor * color1 = new QColor(221,   0,   0);
--- a/QTfrontend/pages.cpp	Fri May 01 11:58:22 2009 +0000
+++ b/QTfrontend/pages.cpp	Sun May 03 17:35:10 2009 +0000
@@ -924,6 +924,10 @@
 	TBW_karma->setText(ToggleButtonWidget::tr("Karma"));
 	glGMLayout->addWidget(TBW_karma,2,1,1,1);
 
+	TBW_artillery = new ToggleButtonWidget(gbGameModes, ":/res/btnArtillery.png");
+	TBW_artillery->setText(ToggleButtonWidget::tr("Artillery"));
+	glGMLayout->addWidget(TBW_artillery,2,2,1,1);
+
 	// Right
 	QLabel * l;
 	
@@ -1041,11 +1045,12 @@
 	mapper->addMapping(TBW_mines->button(), 8);
 	mapper->addMapping(TBW_vampiric->button(), 9);
 	mapper->addMapping(TBW_karma->button(), 10);
-	mapper->addMapping(SB_DamageModifier, 11);
-	mapper->addMapping(SB_TurnTime, 12);
-	mapper->addMapping(SB_InitHealth, 13);
-	mapper->addMapping(SB_SuddenDeath, 14);
-	mapper->addMapping(SB_CaseProb, 15);
+	mapper->addMapping(TBW_artillery->button(), 11);
+	mapper->addMapping(SB_DamageModifier, 12);
+	mapper->addMapping(SB_TurnTime, 13);
+	mapper->addMapping(SB_InitHealth, 14);
+	mapper->addMapping(SB_SuddenDeath, 15);
+	mapper->addMapping(SB_CaseProb, 16);
 
 	mapper->toFirst();
 }
--- a/QTfrontend/pages.h	Fri May 01 11:58:22 2009 +0000
+++ b/QTfrontend/pages.h	Sun May 03 17:35:10 2009 +0000
@@ -426,6 +426,7 @@
 	ToggleButtonWidget * TBW_mines;
 	ToggleButtonWidget * TBW_vampiric;
 	ToggleButtonWidget * TBW_karma;
+	ToggleButtonWidget * TBW_artillery;
 
 	QSpinBox * SB_DamageModifier;
 	QSpinBox * SB_TurnTime;
Binary file QTfrontend/res/btnArtillery.png has changed
Binary file QTfrontend/res/btnKarma.png has changed
Binary file QTfrontend/res/btnVampiric.png has changed
--- a/hedgewars/GSHandlers.inc	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/GSHandlers.inc	Sun May 03 17:35:10 2009 +0000
@@ -451,7 +451,7 @@
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
-procedure doStepDEagleShotWork(Gear: PGear);
+procedure doStepBulletWork(Gear: PGear);
 var i, x, y: LongWord;
     oX, oY: hwFloat;
 begin
@@ -467,7 +467,11 @@
   y:= hwRound(Gear^.Y);
   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 AmmoShove(Gear, 7, 20);
+  if Gear^.Damage > 5 then
+      if Gear^.Ammo^.AmmoType = amDEagle then
+          AmmoShove(Gear, 7, 20)
+      else
+          AmmoShove(Gear, Gear^.Timer*2, 20);
   dec(i)
 until (i = 0) or (Gear^.Damage > Gear^.Health);
 if Gear^.Damage > 0 then
@@ -486,7 +490,27 @@
 procedure doStepDEagleShot(Gear: PGear);
 begin
 PlaySound(sndGun, false, nil);
-Gear^.doStep:= @doStepDEagleShotWork
+Gear^.doStep:= @doStepBulletWork
+end;
+
+procedure doStepSniperRifleShot(Gear: PGear);
+begin
+if not cLaserSighting then // game doesn't have default laser sight. turn it on and give them a chance to aim
+    begin
+    cLaserSighting:= true;
+    cArtillery:= true;
+	DeleteGear(Gear);
+	AfterAttack;
+    dec(CurrentHedgehog^.AttacksNum);
+    exit 
+    end;
+
+if (PHedgehog(Gear^.Hedgehog)^.Gear^.Message and gm_Attack) <> 0 then
+    begin
+	Gear^.State:= Gear^.State or gstAnimation;
+    PlaySound(sndGun, false, nil);
+    Gear^.doStep:= @doStepBulletWork
+    end
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/hedgewars/HHHandlers.inc	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/HHHandlers.inc	Sun May 03 17:35:10 2009 +0000
@@ -150,6 +150,7 @@
                                  PlaySound(sndLaugh, false, CurrentTeam^.voicepack)
                                  end;
                        amDEagle: CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
+                  amSniperRifle: CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
                      amDynamite: begin
                                  AddGear(hwRound(X) + hwSign(dX) * 7, hwRound(Y), gtDynamite, 0, SignAs(_0_03, dX), _0, 5000);
                                  PlaySound(sndLaugh, false, CurrentTeam^.voicepack)
@@ -185,8 +186,6 @@
                         amBallgun: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtBallgun,  0, xx * _0_5, yy * _0_5, 0);
                       amLowGravity: cGravity:= cMaxWindSpeed / 2;
                       amExtraDamage: cDamageModifier:= _1_5;
-                      //this flag unfortunately gets cleared too often for true invulnerability, although it seemed like the natural choice
-                      //amInvulnerable: State:= State or gstNoDamage;
                       amInvulnerable: Invulnerable:= true;
                       amExtraTime: TurnTimeLeft:= TurnTimeLeft + 30000;
                       amLaserSight: cLaserSighting:= true;
@@ -397,8 +396,7 @@
          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
       end;
 
-   // ARTILLERY HERE
-   if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then Gear^.X:= Gear^.X + SignAs(_1, Gear^.dX);
+   if (not cArtillery) and (not TestCollisionXwithGear(Gear, hwSign(Gear^.dX))) then Gear^.X:= Gear^.X + SignAs(_1, Gear^.dX);
    SetAllHHToActive;
 
    if not TestCollisionYwithGear(Gear, 1) then
@@ -628,7 +626,7 @@
 			begin
 			Gear^.State:= Gear^.State or gstHHHJump or gstMoving;
 			Gear^.dY:= -_0_25;
-			Gear^.dX:= -SignAs(_0_02, Gear^.dX);
+			if not cArtillery then Gear^.dX:= -SignAs(_0_02, Gear^.dX);
 			PlaySound(sndJump2, false, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack)
 			end;
 	
--- a/hedgewars/uAIAmmoTests.pas	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/uAIAmmoTests.pas	Sun May 03 17:35:10 2009 +0000
@@ -81,7 +81,8 @@
 			(proc: nil;              flags: 0), // amInvulnerable
 			(proc: nil;              flags: 0), // amExtraTime
 			(proc: nil;              flags: 0), // amLaserSight
-			(proc: nil;              flags: 0)  // amVampiric
+			(proc: nil;              flags: 0), // amVampiric
+			(proc: nil;              flags: 0)  // amSniperRifle
 			);
 
 const BadTurn = Low(LongInt) div 4;
--- a/hedgewars/uConsts.pas	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/uConsts.pas	Sun May 03 17:35:10 2009 +0000
@@ -62,7 +62,8 @@
 			sprPlane, sprHandPlane, sprUtility, sprInvulnerable, sprVampiric, sprGirder, 
             sprSpeechCorner, sprSpeechEdge, sprSpeechTail, 
             sprThoughtCorner, sprThoughtEdge, sprThoughtTail, 
-            sprShoutCorner, sprShoutEdge, sprShoutTail);
+            sprShoutCorner, sprShoutEdge, sprShoutTail,
+            sprSniperRifle);
 
 	TGearType = (gtAmmo_Bomb, gtHedgehog, gtAmmo_Grenade, gtHealthTag, // 3
 			gtGrave, gtUFO, gtShotgunShot, gtPickHammer, gtRope, // 8
@@ -72,7 +73,7 @@
 			gtParachute, gtAirAttack, gtAirBomb, gtBlowTorch, gtGirder, // 27
 			gtTeleport, gtSwitcher, gtTarget, gtMortar, // 31
 			gtWhip, gtKamikaze, gtCake, gtSeduction, gtWatermelon, gtMelonPiece, // 37
-			gtHellishBomb, gtEvilTrace, gtWaterUp, gtDrill, gtBallGun, gtBall,gtRCPlane, gtSpeechBubble);
+			gtHellishBomb, gtEvilTrace, gtWaterUp, gtDrill, gtBallGun, gtBall,gtRCPlane, gtSpeechBubble, gtSniperRifleShot);
 
 	TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
 			vgtSmallDamageTag, vgtTeamHealthSorter);
@@ -96,7 +97,8 @@
 			amBaseballBat, amParachute, amAirAttack, amMineStrike, amBlowTorch,
 			amGirder, amTeleport, amSwitch, amMortar, amKamikaze, amCake,
 			amSeduction, amWatermelon, amHellishBomb, amNapalm, amDrill, amBallgun, 
-            amRCPlane, amLowGravity, amExtraDamage, amInvulnerable, amExtraTime, amLaserSight, amVampiric);
+            amRCPlane, amLowGravity, amExtraDamage, amInvulnerable, amExtraTime,
+            amLaserSight, amVampiric, amSniperRifle);
 
 	THWFont = (fnt16, fntBig, fntSmall);
 
@@ -208,6 +210,7 @@
 	gfMines        = $00000100;
 	gfVampiric     = $00000200;
 	gfKarma        = $00000400;
+	gfArtillery    = $00000800;
 	gfOneClanMode  = $10000000;
 
 	gstDrowning       = $00000001;
@@ -523,7 +526,9 @@
 			(FileName:'ShoutEdge';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
 			Width:  30; Height: 20; saveSurf: true), // sprShoutEdge
 			(FileName:'ShoutTail';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
-			Width:  30; Height: 37; saveSurf: true) // sprShoutTail
+			Width:  30; Height: 37; saveSurf: true), // sprShoutTail
+			(FileName:'amSniperRifle';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
+			Width:  128; Height: 32; saveSurf: false) // sprSniperRifle
 			);
 
 	Wavez: array [TWave] of record
@@ -1346,6 +1351,24 @@
 			isDamaging: false;
 			SkipTurns: 0;
 			PosCount: 1;
+			PosSprite: sprWater),
+			(NameId: sidSniperRifle;
+			NameTex: nil;
+			Probability: 20;
+			NumberInCase: 2;
+			Ammo: (Propz: 0;
+					Count: 2;
+					NumPerTurn: 1;
+					Timer: 0;
+					Pos: 0;
+					AmmoType: amSniperRifle);
+			Slot: 2;
+			TimeAfterTurn: 3000;
+			minAngle: 0;
+			maxAngle: 0;
+			isDamaging: true;
+			SkipTurns: 0;
+			PosCount: 1;
 			PosSprite: sprWater)
 			);
 
--- a/hedgewars/uGears.pas	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/uGears.pas	Sun May 03 17:35:10 2009 +0000
@@ -163,7 +163,8 @@
 			@doStepBallgun,
 			@doStepBomb,
 			@doStepRCPlane,
-			@doStepSpeechBubble
+			@doStepSpeechBubble,
+			@doStepSniperRifleShot
 			);
 
 procedure InsertGearToList(Gear: PGear);
@@ -307,6 +308,10 @@
                 Result^.Radius:= 1;
                 Result^.Health:= 50
                 end;
+  gtSniperRifleShot: begin
+                Result^.Radius:= 1;
+                Result^.Health:= 50
+                end;
     gtDynamite: begin
                 Result^.Radius:= 3;
                 Result^.Elasticity:= _0_55;
@@ -636,15 +641,21 @@
 
     if (GameFlags and gfLaserSight) = 0 then
         cLaserSighting:= false;
-    // have to sweep *all* current team hedgehogs since it is theoretically possible if you have enough invulnerabilities and switch turns to make your entire team invulnerable
+
+    if (GameFlags and gfArtillery) = 0 then
+        cArtillery:= false;
 
-   if (GameFlags and gfInvulnerable) = 0 then
-       if (CurrentTeam <> nil) then
-          with CurrentTeam^ do
-             for i:= 0 to cMaxHHIndex do
-                 with Hedgehogs[i] do
-                     if (Gear <> nil) then
-                         Gear^.Invulnerable:= false;
+    // have to sweep *all* current team hedgehogs since it is theoretically possible if you have enough invulnerabilities and switch turns to make your entire team invulnerable
+    if (CurrentTeam <> nil) then
+       with CurrentTeam^ do
+          for i:= 0 to cMaxHHIndex do
+              with Hedgehogs[i] do
+                  begin
+                  if (SpeechGear <> nil) then DeleteGear(SpeechGear);  // remove to restore persisting beyond end of turn. Tiy says was too much of a gameplay issue
+                  if (Gear <> nil) then
+                     if (GameFlags and gfInvulnerable) = 0 then
+                        Gear^.Invulnerable:= false;
+                  end;
 end;
 procedure ApplyDamage(Gear: PGear; Damage: Longword);
 var s: shortstring;
@@ -716,7 +727,7 @@
 end;
 
 procedure DrawHH(Gear: PGear);
-var t: LongInt;
+var i, t: LongInt;
 	amt: TAmmoType;
 	hx, hy, cx, cy, tx, ty, sx, sy, m: LongInt;  // hedgehog, crosshair, temp, sprite, direction
 	lx, ly, dx, dy, ax, ay, aAngle, dAngle: real;  // laser, change
@@ -782,6 +793,12 @@
 						DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle);
 				end;
 			gtDEagleShot: DrawRotated(sprDEagle, hx, hy, hwSign(Gear^.dX), aangle);
+			gtSniperRifleShot: begin
+					if (CurAmmoGear^.State and gstAnimation <> 0) then
+			            DrawRotatedF(sprSniperRifle, hx, hy, 1, hwSign(Gear^.dX), aangle)
+					else
+			            DrawRotatedF(sprSniperRifle, hx, hy, 0, hwSign(Gear^.dX), aangle)
+				end;
 			gtBallgun: DrawRotated(sprHandBallgun, hx, hy, hwSign(Gear^.dX), aangle);
 			gtRCPlane: begin
 				DrawRotated(sprHandPlane, hx, hy, hwSign(Gear^.dX), 0);
@@ -791,16 +808,16 @@
 				if Gear^.X < CurAmmoGear^.X then
 					begin
 					dAngle:= 0;
-					m:= 1
+					i:= 1
 					end else
 					begin
 					dAngle:= 180;
-					m:= -1
+					i:= -1
 					end;
                 sx:= hwRound(Gear^.X) + WorldDx;
                 sy:= hwRound(Gear^.Y) + WorldDy;
 				DrawHedgehog(sx, sy,
-						m,
+						i,
 						1,
 						0,
 						DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + dAngle);
@@ -878,6 +895,7 @@
 		case CurAmmoGear^.Kind of
 			gtShotgunShot,
 			gtDEagleShot,
+			gtSniperRifleShot,
 			gtShover: begin
 				DrawHedgehog(sx, sy,
 						hwSign(Gear^.dX),
@@ -936,6 +954,7 @@
 			amRope: DrawRotated(sprHandRope, hx, hy, hwSign(Gear^.dX), aangle);
 			amShotgun: DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle);
 			amDEagle: DrawRotated(sprHandDEagle, hx, hy, hwSign(Gear^.dX), aangle);
+			amSniperRifle: DrawRotatedF(sprSniperRifle, hx, hy, 0, hwSign(Gear^.dX), aangle);
 			amBlowTorch: DrawRotated(sprHandBlowTorch, hx, hy, hwSign(Gear^.dX), aangle);
 			amRCPlane: begin
 				DrawRotated(sprHandPlane, hx, hy, hwSign(Gear^.dX), 0);
@@ -1401,7 +1420,10 @@
        end;
 
 if (GameFlags and gfLaserSight) <> 0 then
-    cLaserSighting:= true
+    cLaserSighting:= true;
+
+if (GameFlags and gfArtillery) <> 0 then
+    cArtillery:= true
 end;
 
 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask: LongWord);
--- a/hedgewars/uLocale.pas	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/uLocale.pas	Sun May 03 17:35:10 2009 +0000
@@ -25,7 +25,8 @@
 			sidGirder, sidTeleport, sidSwitch, sidMortar, sidWhip,
 			sidKamikaze, sidCake, sidSeduction, sidWatermelon,
 			sidHellishBomb, sidDrill, sidBallgun, sidNapalm, sidRCPlane, 
-            sidLowGravity, sidExtraDamage, sidInvulnerable, sidExtraTime, sidLaserSight, sidVampiric);
+            sidLowGravity, sidExtraDamage, sidInvulnerable, sidExtraTime, 
+            sidLaserSight, sidVampiric, sidSniperRifle);
 
 	TMsgStrId = (sidStartFight, sidDraw, sidWinner, sidVolume, sidPaused,
 			sidConfirm, sidSuddenDeath);
--- a/hedgewars/uMisc.pas	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/uMisc.pas	Sun May 03 17:35:10 2009 +0000
@@ -106,6 +106,7 @@
 	cDamageModifier: hwFloat;
 	cLaserSighting: boolean;
 	cVampiric: boolean;
+	cArtillery: boolean;
 
 	flagMakeCapture: boolean = false;
 
@@ -550,6 +551,7 @@
 cDamageModifier:= _1;
 cLaserSighting:= false;
 cVampiric:= false;
+cArtillery:= false;
 
 {$IFDEF DEBUGFILE}
 {$I-}
--- a/hedgewars/uStore.pas	Fri May 01 11:58:22 2009 +0000
+++ b/hedgewars/uStore.pas	Sun May 03 17:35:10 2009 +0000
@@ -451,8 +451,11 @@
 begin
 glPushMatrix;
 glTranslatef(X, Y, 0);
-glRotatef(Angle, 0, 0, 1);
 
+if Dir < 0 then
+   glRotatef(Angle, 0, 0, -1)
+else
+   glRotatef(Angle, 0, 0,  1);
 if Dir < 0 then glScalef(-1.0, 1.0, 1.0);
 
 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
@@ -678,7 +681,7 @@
 end;
 
 function RenderSpeechBubbleTex(s: string; SpeechType: Longword; font: THWFont): PTexture;
-var textWidth, textHeight, x, y, w, h, i, pos, prevpos, line, numLines, edgeWidth, edgeHeight, cornerWidth, cornerHeight: LongInt;
+var textWidth, textHeight, x, y, w, h, i, j, pos, prevpos, line, numLines, edgeWidth, edgeHeight, cornerWidth, cornerHeight: LongInt;
     Result, tmpsurf, rotatedEdge: PSDL_Surface;
     rect: TSDL_Rect;
     chars: TSysCharSet = [#9,' ','.',';',':','?','!',','];
@@ -707,33 +710,42 @@
 edgeWidth:= SpritesData[edge].Width;
 cornerWidth:= SpritesData[corner].Width;
 cornerHeight:= SpritesData[corner].Height;
-// This one screws it up
+// This one screws up WrapText
 //s:= 'This is the song that never ends.  ''cause it goes on and on my friends. Some people, started singing it not knowing what it was. And they''ll just go on singing it forever just because... This is the song that never ends...';
 // This one doesn't
-//s:= 'This is the song that never ends.  cause it goes on and on my friends. Some people, started singing it not knowing what it was. And theyll just go on singing it forever just because... This is the song that never ends... ';
-// Also screws up, but only action
-//s:= 'This is the song that never ends.  cause it goes on and on .';
-// ok in all
-// s:= 'This is the song that never ends.  cause it goes on .';
+//s:= 'This is the song that never ends.  cause it goes on and on my friends. Some people, started singing it not knowing what it was. And they will go on singing it forever just because... This is the song that never ends... ';
+
 numLines:= 0;
 
 if length(s) = 0 then s:= '...';
-
 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(s), w, h);
-textWidth:= w;
-textHeight:= h;
+j:= 0;
 if (length(s) > 20) then
     begin
+    w:= 0;
     i:= round(Sqrt(length(s)) * 2);
     s:= WrapText(s, #1, chars, i);
-    for pos:= 1 to length(s) do
+    pos:= 1; prevpos:= 0; line:= 0;
+// Find the longest line for the purposes of centring the text.  Font dependant.
+    while pos <= length(s) do
+        begin
         if (s[pos] = #1) or (pos = length(s)) then
-            inc(numLines);
+            begin
+            inc(numlines);
+            if s[pos] <> #1 then inc(pos);
+            while s[prevpos+1] = ' ' do inc(prevpos);
+            substr:= copy(s, prevpos+1, pos-prevpos-1);
+            i:= 0; j:= 0;
+            TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(substr), i, j);
+            if i > w then w:= i;
+            prevpos:= pos;
+            end;
+        inc(pos);
+        end;
+    end
+else numLines := 1;
 
-    textWidth:= round(w/(numLines)) + 12;
-    end;
-
-textWidth:=((textWidth-(cornerWidth-edgeWidth)*2) div edgeWidth)*edgeWidth+edgeWidth;
+textWidth:=((w-(cornerWidth-edgeWidth)*2) div edgeWidth)*edgeWidth+edgeWidth;
 textHeight:=(((numlines * h + 2)-((cornerHeight-edgeWidth)*2)) div edgeWidth)*edgeWidth;
 
 textHeight:=max(textHeight,edgeWidth);
@@ -742,7 +754,7 @@
 rect.y:= 0;
 rect.w:= textWidth + (cornerWidth * 2);
 rect.h:= textHeight + cornerHeight*2 - edgeHeight + SpritesData[tail].Height;
-//s:= inttostr(h) + ' ' + inttostr(numlines) + ' ' + inttostr(rect.x) + ' '+inttostr(rect.y) + ' ' + inttostr(rect.w) + ' ' + inttostr(rect.h) + ' ' + s;
+//s:= inttostr(w) + ' ' + inttostr(numlines) + ' ' + inttostr(rect.x) + ' '+inttostr(rect.y) + ' ' + inttostr(rect.w) + ' ' + inttostr(rect.h);
 
 Result:= SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, rect.h, 32, RMask, GMask, BMask, AMask);
 
@@ -814,6 +826,8 @@
 rect.y:= edgeHeight;
 rect.w:= rect.w - edgeHeight * 2;
 rect.h:= textHeight + cornerHeight * 2 - edgeHeight * 2;
+i:= rect.w;
+j:= rect.h;
 SDL_FillRect(Result, @rect, cWhiteColor);
 
 pos:= 1; prevpos:= 0; line:= 0;
@@ -827,9 +841,9 @@
         if Length(substr) <> 0 then
            begin
            tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(substr), cColorNearBlack);
-           rect.x:= edgeHeight+4;
+           rect.x:= edgeHeight + 1 + ((i - w) div 2);
            // trying to more evenly position the text, vertically
-           rect.y:= max(edgeHeight,3+(rect.h-(numLines*h)) div 2) + line * h;
+           rect.y:= edgeHeight + ((j-(numLines*h)) div 2) + line * h;
            SDLTry(tmpsurf <> nil, true);
            SDL_UpperBlit(tmpsurf, nil, Result, @rect);
            SDL_FreeSurface(tmpsurf);
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png has changed
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw.png has changed
Binary file share/hedgewars/Data/Graphics/Arrow.png has changed
Binary file share/hedgewars/Data/Graphics/Hedgehog.png has changed
Binary file share/hedgewars/Data/Graphics/Hedgehog/Vampiric.png has changed
Binary file share/hedgewars/Data/Graphics/Hedgehog/amSniperRifle.png has changed
Binary file share/hedgewars/Data/Graphics/Teleport.png has changed
Binary file share/hedgewars/Data/Graphics/WindBar.png has changed
Binary file share/hedgewars/Data/Graphics/WindL.png has changed
Binary file share/hedgewars/Data/Graphics/WindR.png has changed
--- a/share/hedgewars/Data/Locale/bg.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/bg.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra Time
 00:36=Laser Sight
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Бой!
 01:01=Равен рунд
--- a/share/hedgewars/Data/Locale/cs.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/cs.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra Time
 00:36=Laser Sight
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Do boje!
 01:01=Kolo nerozhodně
--- a/share/hedgewars/Data/Locale/de.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/de.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Zusatzzeit
 00:36=Laservisier
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Auf in die Schlacht!
 01:01=Unentschieden
--- a/share/hedgewars/Data/Locale/en.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/en.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra Time
 00:36=Laser Sight
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Let's fight!
 01:01=Round draw
--- a/share/hedgewars/Data/Locale/es.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/es.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Tiempo extra
 00:36=Mira láser
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Luchad!
 01:01=Empate
--- a/share/hedgewars/Data/Locale/fi.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/fi.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra Time
 00:36=Laser Sight
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Taistelu alkakoon!
 01:01=Tasapeli
--- a/share/hedgewars/Data/Locale/fr.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/fr.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra Time
 00:36=Laser Sight
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=C'est parti!
 01:01=Round ex aequo
--- a/share/hedgewars/Data/Locale/it.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/it.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Tempo Extra
 00:36=Mirino Laser
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Combattiamo!
 01:01=Round in parità
--- a/share/hedgewars/Data/Locale/pl.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/pl.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Dodatkowy czas
 00:36=Celownik laserowy
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Walczmy!
 01:01=Remis
--- a/share/hedgewars/Data/Locale/pt-br.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/pt-br.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra Time
 00:36=Laser Sight
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Hora de lutar!
 01:01=Partida empatou
--- a/share/hedgewars/Data/Locale/ru.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/ru.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=30 секунд
 00:36=Лазерный прицел
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Вперёд к победе!
 01:01=Ничья
--- a/share/hedgewars/Data/Locale/sk.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/sk.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra čas
 00:36=Laserové zameriavanie
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Do boja!
 01:01=Remíza
--- a/share/hedgewars/Data/Locale/tr.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/tr.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Arttırılmış Zaman
 00:36=Lazer Görüşü
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Savaş başlasın!
 01:01=Beraberlik
--- a/share/hedgewars/Data/Locale/uk.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/uk.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=Extra Time
 00:36=Laser Sight
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=Уперед до перемоги!
 01:01=Нічия
--- a/share/hedgewars/Data/Locale/zh_CN.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/zh_CN.txt	Sun May 03 17:35:10 2009 +0000
@@ -38,6 +38,7 @@
 00:35=加时
 00:36=激光瞄准
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=战斗啦!
 01:01=平手
--- a/share/hedgewars/Data/Locale/zh_TW.txt	Fri May 01 11:58:22 2009 +0000
+++ b/share/hedgewars/Data/Locale/zh_TW.txt	Sun May 03 17:35:10 2009 +0000
@@ -36,6 +36,7 @@
 00:35=附加時間
 00:36=雷射瞄准
 00:37=Vampirism
+00:38=Sniper Rifle
 
 01:00=戰鬥開始!
 01:01=平手