Merge
authorunc0rr
Tue, 21 Jan 2014 10:59:52 +0400
changeset 10033 0cdb8bb83ef7
parent 10032 db65298717da (diff)
parent 10027 403b86a1d05f (current diff)
child 10034 fc586f2f8782
Merge
--- a/CMakeLists.txt	Tue Jan 21 00:09:06 2014 +0400
+++ b/CMakeLists.txt	Tue Jan 21 10:59:52 2014 +0400
@@ -215,5 +215,11 @@
 set(LUAAPITESTS "${LUATESTS}/luaAPI")
 set(TESTSDATADIR "${CMAKE_SOURCE_DIR}/share/hedgewars/Data")
 
-add_test("LuaAPI:GetZoom/SetZoom" "bin/hwengine" "--prefix" "${TESTSDATADIR}" "--nosound" "--lua-test" "${LUAAPITESTS}/zoom_get_set.lua")
-add_test("DrillRockets_drill" "bin/hwengine" "--prefix" "${TESTSDATADIR}" "--nosound" "--lua-test" "${LUATESTS}/drillrockets_drill.lua")
+
+add_test("LuaAPI:GetZoom/SetZoom" "bin/hwengine" "--prefix" "${TESTSDATADIR}" "--nosound" "--nomusic" "--lua-test" "${LUAAPITESTS}/zoom_get_set.lua")
+
+# set set this to "" if you want to see what's going on
+set(STATSONLYFLAG "--stats-only")
+add_test("LuaAPI:GetGravity/SetGravity" "bin/hwengine" "--prefix" "${TESTSDATADIR}" "--nosound" "--nomusic" ${STATSONLYFLAG} "--lua-test" "${LUAAPITESTS}/gravity_get_set.lua")
+add_test("DrillRockets_drill" "bin/hwengine" "--prefix" "${TESTSDATADIR}" "--nosound" "--nomusic" ${STATSONLYFLAG} "--lua-test" "${LUATESTS}/drillrockets_drill.lua")
+add_test("DrillRockets_boom" "bin/hwengine" "--prefix" "${TESTSDATADIR}" "--nosound" "--nomusic" ${STATSONLYFLAG} "--lua-test" "${LUATESTS}/drillrockets_boom.lua")
--- a/hedgewars/uGearsList.pas	Tue Jan 21 00:09:06 2014 +0400
+++ b/hedgewars/uGearsList.pas	Tue Jan 21 10:59:52 2014 +0400
@@ -20,7 +20,7 @@
 unit uGearsList;
 
 interface
-uses uFloat, uTypes;
+uses uFloat, uTypes, SDLh;
 
 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
 procedure DeleteGear(Gear: PGear);
@@ -156,6 +156,7 @@
 
 function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
 var gear: PGear;
+    c: byte;
 begin
 inc(GCounter);
 AddFileLog('AddGear: #' + inttostr(GCounter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
@@ -180,6 +181,7 @@
 // Define ammo association, if any.
 gear^.AmmoType:= GearKindAmmoTypeMap[Kind];
 gear^.CollisionMask:= $FFFF;
+gear^.Tint:= $FFFFFFFF;
 
 if CurrentHedgehog <> nil then
     begin
@@ -235,6 +237,18 @@
                 if (GameFlags and gfAISurvival) <> 0 then
                     if gear^.Hedgehog^.BotLevel > 0 then
                         gear^.Hedgehog^.Effects[heResurrectable] := 1;
+                // this would presumably be set in the frontend
+                // if we weren't going to do that yet, would need to reinit GetRandom
+                // oh, and, randomising slightly R and B might be nice too. 
+                //gear^.Tint:= $fa00efff or ((random(80)+128) shl 16)
+                //gear^.Tint:= $faa4efff
+                //gear^.Tint:= (($e0+random(32)) shl 24) or 
+                //             ((random(80)+128) shl 16) or
+                //             (($d5+random(32)) shl 8) or $ff
+                c:= random(32);
+                gear^.Tint:= (($e0+c) shl 24) or 
+                             ((random(90)+128) shl 16) or
+                             (($d5+c) shl 8) or $ff
                 end;
        gtShell: begin
                 gear^.Elasticity:= _0_8;
@@ -272,6 +286,9 @@
                     Health:= random(vobFrameTicks);
                     if gear^.Timer = 0 then Timer:= random(vobFramesCount);
                     Damage:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) * 8;
+                    Tint:= (ExplosionBorderColor and RMask shl RShift) or 
+                           (ExplosionBorderColor and GMask shl GShift) or 
+                           (ExplosionBorderColor and BMask shl BShift) or $FF;
                     end
                 end;
        gtGrave: begin
@@ -400,7 +417,10 @@
                 gear^.Radius:= 15;
                 gear^.Tag:= Y
                 end;
-   gtAirAttack: gear^.Z:= cHHZ+2;
+   gtAirAttack: begin
+                gear^.Z:= cHHZ+2;
+                gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF
+                end;
      gtAirBomb: begin
                 gear^.Radius:= 5;
                 gear^.Density:= _2;
@@ -485,7 +505,8 @@
      gtRCPlane: begin
                 if gear^.Timer = 0 then gear^.Timer:= 15000;
                 gear^.Health:= 3;
-                gear^.Radius:= 8
+                gear^.Radius:= 8;
+                gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF
                 end;
      gtJetpack: begin
                 gear^.Health:= 2000;
@@ -544,10 +565,12 @@
  gtPoisonCloud: begin
                 if gear^.Timer = 0 then gear^.Timer:= 5000;
                 gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000;
+                gear^.Tint:= $C0C000C0
                 end;
  gtResurrector: begin
                 gear^.Radius := 100;
-                gear^.Tag := 0
+                gear^.Tag := 0;
+                gear^.Tint:= $F5DB35FF
                 end;
      gtWaterUp: begin
                 gear^.Tag := 47;
--- a/hedgewars/uGearsRender.pas	Tue Jan 21 00:09:06 2014 +0400
+++ b/hedgewars/uGearsRender.pas	Tue Jan 21 10:59:52 2014 +0400
@@ -795,13 +795,24 @@
         begin
         if defaultPos then
             begin
-            if HH^.Team^.hasGone then Tint($FF, $FF, $FF, $80);
+            if HH^.Team^.hasGone then
+                 Tint($FFFFFF80)
+            else if HH^.Effects[hePoisoned] <> 0 then
+                 Tint($B7FFBCFF)
+            else Tint(HH^.Gear^.Tint);
             DrawSpriteRotatedF(sprHHIdle,
                 sx,
                 sy,
                 (RealTicks div 128 + Gear^.Pos) mod 19,
                 sign,
                 0);
+            untint;
+            DrawSpriteRotatedF(sprHHIdle,
+                sx,
+                sy,
+                (RealTicks div 128 + Gear^.Pos) mod 19 + 32,
+                sign,
+                0);
             HatVisible:= true;
             end;
 
@@ -1039,7 +1050,7 @@
        gtRCPlane: begin
                   aangle:= Gear^.Angle * 360 / 4096;
                   if Gear^.Tag < 0 then aangle:= 360-aangle;
-                  Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF);
+                  Tint(Gear^.Tint);
                   DrawSpriteRotatedF(sprPlane, x, y, 0, Gear^.Tag, aangle - 90);
                   untint;
                   DrawSpriteRotatedF(sprPlane, x, y, 1, Gear^.Tag, aangle - 90)
@@ -1161,7 +1172,7 @@
                     DrawAltWeapon(Gear, x + 1, y - 3)
                     end;
        gtAirAttack: begin
-                    Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF);
+                    Tint(Gear^.Tint);
                     DrawSpriteRotatedF(sprAirplane, x, y, 0, Gear^.Tag, 0);
                     untint;
                     DrawSpriteRotatedF(sprAirplane, x, y, 1, Gear^.Tag, 0);
@@ -1237,27 +1248,24 @@
                     end;
      gtPoisonCloud: begin
                     if Gear^.Timer < 1020 then
-                        Tint($C0, $C0, $00, Gear^.Timer div 8)
+                        Tint(Gear^.Tint and $FFFFFF00 or Gear^.Timer div 8)
                     else if Gear^.Timer > 3980 then
-                        Tint($C0, $C0, $00, (5000 - Gear^.Timer) div 8)
+                        Tint(Gear^.Tint and $FFFFFF00 or (5000 - Gear^.Timer) div 8)
                     else
-                        Tint($C0, $C0, $00, $C0);
+                        Tint(Gear^.Tint);
                     DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 3, 0, 0, x, y, 0, 1, 22, 22, (RealTicks shr 36 + Gear^.UID * 100) mod 360);
                     untint
                     end;
      gtResurrector: begin
                     DrawSpriteRotated(sprCross, x, y, 0, 0);
-                    Tint($f5, $db, $35, max($00, round($C0 * abs(1 - (GameTicks mod 6000) / 3000))));
+                    Tint(Gear^.Tint and $FFFFFF00 or max($00, round($C0 * abs(1 - (GameTicks mod 6000) / 3000))));
                     DrawTexture(x - 108, y - 108, SpritesData[sprVampiric].Texture, 4.5);
                     untint;
                     end;
       gtNapalmBomb: DrawSpriteRotated(sprNapalmBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
            gtFlake: if Gear^.State and (gstDrowning or gstTmpFlag) <> 0  then
                         begin
-                        Tint((ExplosionBorderColor shr RShift) and $FF,
-                             (ExplosionBorderColor shr GShift) and $FF,
-                             (ExplosionBorderColor shr BShift) and $FF,
-                             $FF);
+                        Tint(Gear^.Tint);
                         // Needs a nicer white texture to tint
                         DrawTextureRotatedF(SpritesData[sprSnowDust].Texture, 1, 0, 0, x, y, 0, 1, 8, 8, Gear^.DirAngle);
                         //DrawSpriteRotated(sprSnowDust, x, y, 0, Gear^.DirAngle);
--- a/hedgewars/uScript.pas	Tue Jan 21 00:09:06 2014 +0400
+++ b/hedgewars/uScript.pas	Tue Jan 21 10:59:52 2014 +0400
@@ -1907,18 +1907,20 @@
 begin
     if lua_gettop(L) <> 0 then
         LuaParameterCountError('GetGravity', '', lua_gettop(L))
+    else if cGravity.isNegative then
+        lua_pushinteger(L, hwRound(-_0_5 + (cGravity * 50 / cMaxWindSpeed)))
     else
-        lua_pushinteger(L, hwRound(cGravity * 50 / cWindSpeed));
+        lua_pushinteger(L, hwRound( _0_5 + (cGravity * 50 / cMaxWindSpeed)));
     lc_getgravity:= 1
 end;
 
 function lc_setgravity(L : Plua_State) : LongInt; Cdecl;
 begin
     if lua_gettop(L) <> 1 then
-        LuaParameterCountError('SetGravity', 'gravity', lua_gettop(L))
+        LuaParameterCountError('SetGravity', 'percent', lua_gettop(L))
     else
         begin
-        cGravity:= cMaxWindSpeed * lua_tointeger(L, 1) * _0_02;
+        cGravity:= _0_02 * lua_tointeger(L, 1) * cMaxWindSpeed;
         cGravityf:= 0.00025 * lua_tointeger(L, 1) * 0.02
         end;
     lc_setgravity:= 0
@@ -1996,6 +1998,7 @@
         end
     else
         begin
+        WriteLnToConsole('Lua test finished');
         halt(lua_tointeger(L, 1));
         lc_endluatest:= 0;
         end;
--- a/hedgewars/uTypes.pas	Tue Jan 21 00:09:06 2014 +0400
+++ b/hedgewars/uTypes.pas	Tue Jan 21 10:59:52 2014 +0400
@@ -270,6 +270,7 @@
             MsgParam: LongWord;      // Initially stored a set of messages. So usually gm values like Message. Frequently overriden
 // These are not used generically, but should probably be used for purpose intended. Definitely shouldn't override pointer type
             Tex: PTexture;          // A texture created by the gear. Shouldn't use for anything but textures
+            Tint: LongWord;         // Used to colour a texture
             LinkedGear: PGear;      // Used to track a related gear. Portal pairs for example.
             Hedgehog: PHedgehog;    // set to CurrentHedgehog on gear creation
             SoundChannel: LongInt;  // Used to track a sound the gear started
--- a/hedgewars/uWorld.pas	Tue Jan 21 00:09:06 2014 +0400
+++ b/hedgewars/uWorld.pas	Tue Jan 21 10:59:52 2014 +0400
@@ -655,7 +655,7 @@
 DrawTexture(AmmoRect.x + AMShiftX, AmmoRect.y + AMShiftY, AmmoMenuTex);
 
 if ((AMState = AMHiding) or (AMState = AMShowingUp)) and ((AMAnimType and AMTypeMaskAlpha) <> 0 )then 
-    Tint($FF, $ff, $ff, $ff);
+    untint;
 
 Pos:= -1;
 Slot:= -1;
@@ -1333,7 +1333,7 @@
     begin
     SetScale(cDefaultZoomLevel);
     if TeamsCount * 20 > Longword(cScreenHeight) div 5 then
-        Tint($FF,$FF,$FF,$FF);
+        untint;
     end;
 end;
 
Binary file share/hedgewars/Data/Graphics/Hedgehog/Idle.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/lua/drillrockets_boom.lua	Tue Jan 21 10:59:52 2014 +0400
@@ -0,0 +1,188 @@
+
+ -- taken from http://code.google.com/p/hedgewars/wiki/LuaDrawing
+ PointsBuffer = ''  -- A string to accumulate points in
+ function AddPoint(x, y, width, erase)
+     PointsBuffer = PointsBuffer .. string.char(band(x,0xff00) / 256 , band(x,0xff) , band(y,0xff00) / 256 , band(y,0xff))
+     if width then
+         width = bor(width,0x80)
+         if erase then
+             width = bor(width,0x40)
+         end
+         PointsBuffer = PointsBuffer .. string.char(width)
+     else
+         PointsBuffer = PointsBuffer .. string.char(0)
+     end
+     if #PointsBuffer > 245 then
+         ParseCommand('draw '..PointsBuffer)
+         PointsBuffer = ''
+     end
+ end
+ function FlushPoints()
+     if #PointsBuffer > 0 then
+         ParseCommand('draw '..PointsBuffer)
+         PointsBuffer = ''
+     end
+ end
+
+
+local ta_pointsize = 63
+local ta_radius = (ta_pointsize * 10 + 6) / 2
+
+local sqrttwo = math.sqrt(2)
+
+-- creates round test area
+function AddTestArea(testarea)
+	step = 100
+	xstep = step * testarea["xdir"]
+	ystep = step * testarea["ydir"]
+	x = testarea["x"]
+	y = testarea["y"]
+	if xstep * ystep ~= 0 then
+		xstep = math.floor(xstep / sqrttwo)
+		ystep = math.floor(ystep / sqrttwo)
+	end
+	AddPoint(x, y, ta_pointsize);
+	AddPoint(x + xstep, y + ystep, ta_pointsize, true);
+end
+
+-- vertical test areas
+local taa_v1 = {x= 350, y= 400, xdir= 0, ydir= 1}
+local taa_v2 = {x= 350, y=1500, xdir= 0, ydir=-1}
+-- horizontal test areas
+local taa_h1 = {x=1150, y= 400, xdir= 1, ydir= 0}
+local taa_h2 = {x=1200, y=1100, xdir=-1, ydir= 0}
+-- diagonal test areas
+local taa_d1 = {x=2200, y= 400, xdir= 1, ydir= 1}
+local taa_d2 = {x=2000, y=1500, xdir= 1, ydir=-1}
+local taa_d3 = {x=3300, y= 400, xdir=-1, ydir= 1}
+local taa_d4 = {x=3300, y=1500, xdir=-1, ydir=-1}
+
+-- fail counter
+local nfailed = 0
+local nspawned = 0
+local ndied = 0
+
+function onGameInit()
+	-- At first we have to overwrite/set some global variables
+	-- that define the map, the game has to load, as well as
+	-- other things such as the game rules to use, etc.
+	-- Things we don't modify here will use their default values.
+
+	-- The base number for the random number generator
+	Seed = 1
+	-- The map to be played
+	MapGen = 2
+	-- The theme to be used
+	Theme = "Bamboo"
+	-- Game settings and rules
+	EnableGameFlags(gfOneClanMode, gfDisableWind, gfDisableLandObjects, gfDisableGirders, gfSolidLand)
+	CaseFreq = 0
+	MinesNum = 0
+	Explosives = 0
+
+	-- No damage please
+	DamagePercent = 1
+
+	-- Draw Map
+	AddPoint(10,30,0) -- hog spawn platform
+	-- test areas
+	AddTestArea(taa_v1)
+	AddTestArea(taa_v2)
+	AddTestArea(taa_h1)
+	AddTestArea(taa_h2)
+	AddTestArea(taa_d1)
+	AddTestArea(taa_d2)
+	AddTestArea(taa_d3)
+	AddTestArea(taa_d4)
+
+	FlushPoints()
+
+	-- Create the player team
+	AddTeam("'Zooka Team", 14483456, "Simple", "Island", "Default")
+	-- And add a hog to it
+	player = AddHog("Hunter", 0, 1, "NoHat")
+	-- place it on how spawn platform
+	SetGearPosition(player, 10, 10)
+end
+
+-- xdir/ydir is direction in which to fire the drills
+function SpawnDrillRocketArray(testarea)
+	xdir = testarea["xdir"]
+	ydir = testarea["ydir"]
+	centerx = testarea["x"]
+	centery = testarea["y"]
+	distance = 23
+	d = distance
+	radius = ta_radius
+	speed = 900000;
+	local xmin, xmax, ymin, ymax
+	if (xdir ~= 0) and (ydir ~= 0) then
+		d = d / sqrttwo
+		radius = radius / sqrttwo
+		speed = math.floor(speed / sqrttwo)
+	end
+	centerx = centerx - (xdir * (radius + 20))
+	centery = centery - (ydir * (radius + 20))
+	radius = radius - 6
+	xn = ydir
+	yn = -xdir
+	startx = centerx - (radius * xn)
+	starty = centery - (radius * yn)
+	endx = centerx + (radius * xn)
+	endy = centery + (radius * yn)
+
+	-- spawn loop
+	x = startx
+	y = starty
+	xd = d * xn
+	yd = d * yn
+	if (xd < 0) and (startx < endx) then x = endx end
+	if (yd < 0) and (starty < endy) then y = endy end
+	nsteps = math.floor(math.max(math.abs(startx - endx),math.abs(starty - endy)) / d)
+	for i = 1, nsteps, 1 do
+		AddGear(math.floor(x), math.floor(y), gtDrill, gsttmpFlag * (i % 2), speed * xdir, speed * ydir, 0)
+		nspawned = nspawned + 1
+		x = x + xd
+		y = y + yd
+	end
+end
+
+function onGearDelete(gear)
+	if GetGearType(gear) == gtDrill then
+		-- the way to check state will change in API at some point
+		if band(GetState(gear), gsttmpFlag) == 0 then
+			-- regular drill rocket
+			if (GetTimer(gear) < 2000) or (GetTimer(gear) > 3000) then
+				nfailed = nfailed + 1
+			end
+		else
+			-- airstrike drill rocket
+			if GetTimer(gear) > 0 then
+				nfailed = nfailed + 1
+			end
+		end
+		ndied = ndied + 1
+		if ndied == nspawned then
+			WriteLnToConsole('TESTRESULT: ' .. nfailed .. ' of ' .. nspawned .. ' drill rockets did not explode as expected')
+			if (nfailed > 0) then
+				EndLuaTest(TEST_FAILED)
+			else
+				EndLuaTest(TEST_SUCCESSFUL)
+			end
+		end
+	end
+end
+
+function onGameStart()
+	SetGravity(1)
+
+	SpawnDrillRocketArray(taa_h1)
+	SpawnDrillRocketArray(taa_h2)
+	SpawnDrillRocketArray(taa_v1)
+	SpawnDrillRocketArray(taa_v2)
+	SpawnDrillRocketArray(taa_d1)
+	SpawnDrillRocketArray(taa_d2)
+	SpawnDrillRocketArray(taa_d3)
+	SpawnDrillRocketArray(taa_d4)
+end
+
--- a/tests/lua/drillrockets_drill.lua	Tue Jan 21 00:09:06 2014 +0400
+++ b/tests/lua/drillrockets_drill.lua	Tue Jan 21 10:59:52 2014 +0400
@@ -109,10 +109,13 @@
 	d = distance
 	radius = ta_radius
 	local xmin, xmax, ymin, ymax
+	speed = 900000;
+	local xmin, xmax, ymin, ymax
 	if (xdir ~= 0) and (ydir ~= 0) then
 		sqrttwo = math.sqrt(2)
 		d = d / sqrttwo
 		radius = radius / sqrttwo
+		speed = math.floor(speed / sqrttwo)
 	end
 	centerx = centerx - (xdir * (radius + 20))
 	centery = centery - (ydir * (radius + 20))
@@ -133,7 +136,7 @@
 	if (yd < 0) and (starty < endy) then y = endy end
 	nsteps = math.floor(math.max(math.abs(startx - endx),math.abs(starty - endy)) / d)
 	for i = 1, nsteps, 1 do
-		AddGear(math.floor(x), math.floor(y), gtDrill, 0, 900000 * xdir, 900000 * ydir, 0)
+		AddGear(math.floor(x), math.floor(y), gtDrill, 0, speed * xdir, speed * ydir, 0)
 		nspawned = nspawned + 1
 		x = x + xd
 		y = y + yd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/lua/luaAPI/gravity_get_set.lua	Tue Jan 21 10:59:52 2014 +0400
@@ -0,0 +1,107 @@
+
+
+-- * let grenade fall
+-- * after a second capture fall distance
+-- * change gravity value every second and see if the fall distance in the
+--   following second is about what we'd expect it to be
+
+local spawnX = 10
+local spawnY = -500
+
+local defaultG = nil
+local currentG = nil
+
+local defaultDY = nil
+local expectedY = nil
+
+local testGs = nil
+
+local nFails = 0
+
+function onGameInit()
+
+
+	-- The base number for the random number generator
+	Seed = 1
+	-- The map to be played
+	Map = "Ruler"
+	-- The theme to be used
+	Theme = "Bamboo"
+	-- Game settings and rules
+	EnableGameFlags(gfOneClanMode, gfInvulnerable)
+	CaseFreq = 0
+	MinesNum = 0
+	Explosives = 0
+
+	-- Create the player team
+	AddTeam("O_o", 14483456, "Simple", "Island", "Default")
+	-- And add a hog to it
+	player = AddHog("o_O", 0, 1, "NoHat")
+	SetGearPosition(player, 100, 100)
+end
+
+local tol = 0
+
+function IsKindaSame(a, b)
+	tol = 1 + math.max(1,math.abs(currentG) / 100)
+	return (a >= b-tol) and (a <= b+tol)
+end
+
+function SpawnGrenade()
+	AddGear(spawnX, spawnY, gtGrenade, 0, 0, 0, 1000)
+end
+
+local gIdx = 1
+
+function onGearDelete(gear)
+	if GetGearType(gear) ~= gtGrenade then
+		return
+	end
+
+	-- catch initial measuring drop
+	if defaultDY == nil then
+		defaultDY = GetY(gear) - spawnY
+	elseif not IsKindaSame(GetY(gear), expectedY) then
+		nFails = nFails + 1
+		WriteLnToConsole("FAIL: Unexpected Y position! " .. GetY(gear) .. " returned, expected " .. expectedY .. ' (max tolerated difference = ' .. tol .. ')')
+	else
+		WriteLnToConsole("Y position OK! " .. GetY(gear) .. " returned, expected " .. expectedY .. ' (max tolerated difference = ' .. tol .. ')')
+	end
+
+	returnedG = GetGravity()
+	if (returnedG ~= currentG) then
+		WriteLnToConsole("GetGravity did not return the value that we used with SetGravity! " .. returnedG .. " returned, expected " .. currentG)
+		nFails = nFails + 1
+	end
+
+	currentG = testGs[gIdx]
+	gIdx = gIdx + 1
+	-- after last test
+	if currentG == nil then
+		if (nFails > 0) then
+			EndLuaTest(TEST_FAILED)
+		else
+			EndLuaTest(TEST_SUCCESSFUL)
+		end
+	end
+
+	WriteLnToConsole("SetGravity(" .. currentG .. ") ...")
+	SetGravity(currentG)
+
+	SpawnGrenade()
+	expectedY = spawnY + math.floor(currentG * defaultDY / 100)
+end
+
+function onGameStart()
+	currentG = 100
+	defaultG = GetGravity()
+	if (defaultG ~= 100) then
+		WriteLnToConsole("GetGravity did not return 100 at game start")
+		nFails = 1
+	end
+
+	SpawnGrenade()
+
+	testGs = {150, 200, 300, 10, 1, 13, 15, 0, 27, -600, -10, nil}
+end
+