# HG changeset patch # User Stepan777 # Date 1344199226 -14400 # Node ID deaeac102355ccf00adc3b66af1f453343afd305 # Parent 01111960a48d405a2bc1e12a2201c0803ab69a7a# Parent 86984f6fa1b95df0e49c2218a23d1ee233c67c7d merge diff -r 01111960a48d -r deaeac102355 QTfrontend/ui/page/pageeditteam.cpp --- a/QTfrontend/ui/page/pageeditteam.cpp Thu Jul 26 21:58:25 2012 +0400 +++ b/QTfrontend/ui/page/pageeditteam.cpp Mon Aug 06 00:40:26 2012 +0400 @@ -289,6 +289,9 @@ int idx = list.indexOf("cpu.png"); if (idx >= 0) list.removeAt(idx); + idx = list.indexOf("cpu_plain.png"); + if (idx >= 0) + list.removeAt(idx); idx = list.indexOf("hedgewars.png"); if (idx >= 0) list.removeAt(idx); diff -r 01111960a48d -r deaeac102355 gameServer/Actions.hs --- a/gameServer/Actions.hs Thu Jul 26 21:58:25 2012 +0400 +++ b/gameServer/Actions.hs Mon Aug 06 00:40:26 2012 +0400 @@ -146,9 +146,14 @@ io $ infoM "Clients" (show ci ++ " quits: " ++ B.unpack msg) - processAction $ AnswerClients [chan] ["BYE", msg] when loggedIn $ processAction $ AnswerClients clientsChans ["LOBBY:LEFT", clNick, msg] + mapM processAction + [ + AnswerClients [chan] ["BYE", msg] + , ModifyClient (\c -> c{logonPassed = False}) -- this will effectively hide client from others while he isn't deleted from list + ] + s <- get put $! s{removedClients = ci `Set.insert` removedClients s} @@ -418,11 +423,22 @@ processAction JoinLobby = do chan <- client's sendChan clientNick <- client's nick - (lobbyNicks, clientsChans) <- liftM (unzip . Prelude.map (nick &&& sendChan) . Prelude.filter logonPassed) $! allClientsS - mapM_ processAction $ - AnswerClients clientsChans ["LOBBY:JOINED", clientNick] - : AnswerClients [chan] ("LOBBY:JOINED" : clientNick : lobbyNicks) - : [ModifyClient (\cl -> cl{logonPassed = True}), SendServerMessage] + isAuthenticated <- liftM (not . B.null) $ client's webPassword + isAdmin <- client's isAdministrator + loggedInClients <- liftM (Prelude.filter logonPassed) $! allClientsS + let (lobbyNicks, clientsChans) = unzip . L.map (nick &&& sendChan) $ loggedInClients + let authenticatedNicks = L.map nick . L.filter (not . B.null . webPassword) $ loggedInClients + let adminsNicks = L.map nick . L.filter isAdministrator $ loggedInClients + let clFlags = B.concat . L.concat $ [["u" | isAuthenticated], ["a" | isAdmin]] + mapM_ processAction . concat $ [ + [AnswerClients clientsChans ["LOBBY:JOINED", clientNick]] + , [AnswerClients [chan] ("LOBBY:JOINED" : clientNick : lobbyNicks)] + , [AnswerClients [chan] ("CLIENT_FLAGS" : "+u" : authenticatedNicks) | not $ null authenticatedNicks] + , [AnswerClients [chan] ("CLIENT_FLAGS" : "+a" : adminsNicks) | not $ null adminsNicks] + , [AnswerClients (chan : clientsChans) ["CLIENT_FLAGS", B.concat["+" , clFlags], clientNick] | not $ B.null clFlags] + , [ModifyClient (\cl -> cl{logonPassed = True})] + , [SendServerMessage] + ] processAction (KickClient kickId) = do @@ -522,9 +538,11 @@ where kickTimeouted rnc ci = do pq <- io $ client'sM rnc pingsQueue ci - when (pq > 0) $ + when (pq > 0) $ do withStateT (\as -> as{clientIndex = Just ci}) $ processAction (ByeClient "Ping timeout") + when (pq > 1) $ + processAction $ DeleteClient ci -- smth went wrong with client io threads, issue DeleteClient here processAction StatsAction = do diff -r 01111960a48d -r deaeac102355 hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/GSHandlers.inc Mon Aug 06 00:40:26 2012 +0400 @@ -610,11 +610,10 @@ // move back to cloud layer if yy > cWaterLine then move:= true - else if ((yy and LAND_HEIGHT_MASK) <> 0) - or (xx > LAND_WIDTH + 512) or (xx < -512) then + else if (xx > snowRight) or (xx < snowLeft) then move:=true // Solid pixel encountered - else if ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then + else if ((yy and LAND_HEIGHT_MASK) = 0) and ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then begin lf:= Land[yy, xx] and (lfObject or lfBasic or lfIndestructible); // If there's room below keep falling @@ -724,8 +723,8 @@ exit end; Gear^.Pos:= 0; - Gear^.X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512); - Gear^.Y:= int2hwFloat(750+(GetRandom(50)-25)); + Gear^.X:= int2hwFloat(GetRandom(snowRight-snowLeft)+snowLeft); + Gear^.Y:= int2hwFloat(LAND_HEIGHT-1300+(GetRandom(50)-25)); Gear^.State:= Gear^.State or gstInvisible; end end; @@ -3685,10 +3684,6 @@ Gear^.X := HHGear^.X; Gear^.Y := HHGear^.Y; - // For some reason I need to reapply followgear here, something else grabs it otherwise. - // This is probably not needed anymore - if not CurrentTeam^.ExtDriven then - FollowGear := HHGear; if not isUnderWater and hasBorder and ((HHGear^.X < _0) or (hwRound(HHGear^.X) > LAND_WIDTH)) then diff -r 01111960a48d -r deaeac102355 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/hwengine.pas Mon Aug 06 00:40:26 2012 +0400 @@ -59,6 +59,9 @@ gsLandGen: begin GenMap; + uLandTexture.initModule; + UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false); + uAILandMarks.initModule; ParseCommand('sendlanddigest', true); GameState:= gsStart; end; @@ -462,7 +465,6 @@ uAI.initModule; //uAIActions does not need initialization //uAIAmmoTests does not need initialization - uAILandMarks.initModule; uAIMisc.initModule; uAmmos.initModule; uChat.initModule; @@ -474,7 +476,6 @@ //uLandGraphics does not need initialization //uLandObjects does not need initialization //uLandTemplates does not need initialization - uLandTexture.initModule; //uLocale does not need initialization uRandom.initModule; uScript.initModule; diff -r 01111960a48d -r deaeac102355 hedgewars/uAI.pas --- a/hedgewars/uAI.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uAI.pas Mon Aug 06 00:40:26 2012 +0400 @@ -178,9 +178,12 @@ begin AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0); AddAction(BestActions, aia_attack, aim_release, 1, 0, 0); - - AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0); - AddAction(BestActions, aia_Down, aim_release, 32, 0, 0); + + if abs(ap.Angle) > 32 then + begin + AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0); + AddAction(BestActions, aia_Down, aim_release, 32, 0, 0); + end; AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0); AddAction(BestActions, aia_attack, aim_push, 1, 0, 0); @@ -274,7 +277,8 @@ break; if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support - if Push(ticks, Actions, AltMe, Me^.Message) then + // check if we could go backwards and maybe ljump over a gap after this hjump + if Push(ticks, Actions, AltMe, Me^.Message xor 3) then begin with Stack.States[Pred(Stack.Count)] do begin @@ -291,9 +295,8 @@ else AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0); end; - - // check if we could go backwards and maybe ljump over a gap after this hjump - Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message xor 3) + // but first check walking forward + Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message) end; if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support begin diff -r 01111960a48d -r deaeac102355 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uAIAmmoTests.pas Mon Aug 06 00:40:26 2012 +0400 @@ -47,6 +47,7 @@ function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; @@ -84,7 +85,7 @@ //(proc: @TestTeleport; flags: amtest_OnTurn), // amTeleport (proc: nil; flags: 0), // amSwitch (proc: @TestMortar; flags: 0), // amMortar - (proc: nil; flags: 0), // amKamikaze + (proc: @TestKamikaze; flags: 0), // amKamikaze (proc: @TestCake; flags: amtest_OnTurn or amtest_NoTarget), // amCake (proc: nil; flags: 0), // amSeduction (proc: @TestWatermelon; flags: 0), // amWatermelon @@ -167,7 +168,7 @@ EX:= trunc(x); EY:= trunc(y); - if Me^.Hedgehog^.BotLevel = 1 then + if Level = 1 then value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else value:= RateExplosion(Me, EX, EY, 101); if value = 0 then @@ -330,7 +331,7 @@ EX:= trunc(x); EY:= trunc(y); if t < 50 then - if Me^.Hedgehog^.BotLevel = 1 then + if Level = 1 then Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else Score:= RateExplosion(Me, EX, EY, 101) else @@ -361,12 +362,12 @@ t: LongInt; begin valueResult:= BadTurn; -TestTime:= 0; +TestTime:= 500; ap.ExplR:= 0; meX:= hwFloat2Float(Me^.X); meY:= hwFloat2Float(Me^.Y); repeat - inc(TestTime, 1000); + inc(TestTime, 900); // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster if meX 3 then exit(BadTurn); +if Level > 3 then exit(BadTurn); dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; Level:= Level; // avoid compiler hint ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; + x:= hwFloat2Float(Me^.X); y:= hwFloat2Float(Me^.Y); + if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then begin TestDesertEagle:= BadTurn; exit(BadTurn); end; + t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y)); Vx:= (Targ.X - x) * t; Vy:= (Targ.Y - y) * t; @@ -650,7 +654,7 @@ d: Longword; fallDmg, valueResult: LongInt; begin -if Me^.Hedgehog^.BotLevel > 3 then exit(BadTurn); +if Level > 3 then exit(BadTurn); dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; Level:= Level; // avoid compiler hint ap.ExplR:= 0; @@ -700,9 +704,9 @@ x, y, trackFall: LongInt; dx, dy: real; begin - if Me^.Hedgehog^.BotLevel < 3 then trackFall:= afTrackFall + if Level < 3 then trackFall:= afTrackFall else trackFall:= 0; - Level:= Level; // avoid compiler hint + ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; @@ -749,9 +753,9 @@ var valueResult, v1, v2, i: LongInt; x, y, trackFall: LongInt; begin - if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall + if Level = 1 then trackFall:= afTrackFall else trackFall:= 0; - Level:= Level; // avoid compiler hint + ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; @@ -805,9 +809,9 @@ var valueResult, v1, v2: LongInt; x, y, trackFall: LongInt; begin - if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall + if Level = 1 then trackFall:= afTrackFall else trackFall:= 0; - Level:= Level; // avoid compiler hint + ap.ExplR:= 0; ap.Time:= 0; ap.Power:= 1; @@ -822,7 +826,7 @@ , 30, 30, 25 , -1, -0.8, trackFall or afSetSkip); v1:= v1 + - RateShove(Me, x, y + RateShove(Me, x - 2, y , 30, 30, 25 , -1, -0.8, trackFall); // now try opposite direction @@ -830,7 +834,7 @@ , 30, 30, 25 , 1, -0.8, trackFall or afSetSkip); v2:= v2 + - RateShove(Me, x, y + RateShove(Me, x + 2, y , 30, 30, 25 , 1, -0.8, trackFall); @@ -854,6 +858,90 @@ TestWhip:= valueResult; end; +function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +const step = 8; +var valueResult, i, v, tx: LongInt; + trackFall: LongInt; + t, d, x, y, dx, dy, cx: real; +begin + ap.ExplR:= 0; + ap.Time:= 0; + ap.Power:= 1; + + if Level = 1 then + trackFall:= afTrackFall + else if Level = 2 then + trackFall:= 0 + else + exit(BadTurn); + + valueResult:= 0; + v:= 0; + + x:= hwFloat2Float(Me^.X); + y:= hwFloat2Float(Me^.Y); + d:= sqrt(sqr(Targ.X - x) + sqr(Targ.Y - y)); + if d < 10 then + begin + dx:= 0; + dy:= 8; + ap.Angle:= 2048 + end + else + begin + t:= step / d; + dx:= (Targ.X - x) * t; + dy:= (Targ.Y - y) * t; + + ap.Angle:= DxDy2AttackAnglef(dx, -dy) + end; + + if dx >= 0 then cx:= 0.45 else cx:= -0.45; + + for i:= 0 to 512 div step - 2 do + begin + valueResult:= valueResult + + RateShove(Me, trunc(x), trunc(y) + , 30, 30, 25 + , cx, -0.9, trackFall or afSetSkip); + + x:= x + dx; + y:= y + dy; + end; + if dx = 0 then + begin + x:= hwFloat2Float(Me^.X); + y:= hwFloat2Float(Me^.Y); + tx:= trunc(x); + v:= RateShove(Me, tx, trunc(y) + , 30, 30, 25 + , -cx, -0.9, trackFall); + for i:= 1 to 512 div step - 2 do + begin + y:= y + dy; + v:= v + + RateShove(Me, tx, trunc(y) + , 30, 30, 25 + , -cx, -0.9, trackFall or afSetSkip); + end + end; + if v > valueResult then + begin + ap.Angle:= -2048; + valueResult:= v + end; + + v:= RateShove(Me, trunc(x), trunc(y) + , 30, 30, 25 + , cx, -0.9, trackFall); + valueResult:= valueResult + v - KillScore * friendlyfactor div 100 * 1024; + + if v < 65536 then + inc(valueResult, RateExplosion(Me, trunc(x), trunc(y), 30)); + + TestKamikaze:= valueResult; +end; + function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var rate: LongInt; begin diff -r 01111960a48d -r deaeac102355 hedgewars/uAILandMarks.pas --- a/hedgewars/uAILandMarks.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uAILandMarks.pas Mon Aug 06 00:40:26 2012 +0400 @@ -1,71 +1,71 @@ -unit uAILandMarks; - -interface -const markWasHere = $01; - -procedure addMark(X, Y: LongInt; mark: byte); -function checkMark(X, Y: LongInt; mark: byte) : boolean; -procedure clearAllMarks; -procedure clearMarks(mark: byte); - -procedure initModule; -procedure freeModule; - -implementation -uses uVariables; - -const gr = 2; - -var marks: array of array of byte; - WIDTH, HEIGHT: Longword; - -procedure addMark(X, Y: LongInt; mark: byte); -begin - if((X and LAND_WIDTH_MASK) = 0) and ((Y and LAND_HEIGHT_MASK) = 0) then - begin - X:= X shr gr; - Y:= Y shr gr; - marks[Y, X]:= marks[Y, X] or mark - end -end; - -function checkMark(X, Y: LongInt; mark: byte) : boolean; -begin - checkMark:= ((X and LAND_WIDTH_MASK) = 0) - and ((Y and LAND_HEIGHT_MASK) = 0) - and ((marks[Y shr gr, X shr gr] and mark) <> 0) -end; - -procedure clearAllMarks; -var - Y, X: Longword; -begin - for Y:= 0 to Pred(HEIGHT) do - for X:= 0 to Pred(WIDTH) do - marks[Y, X]:= 0 -end; - -procedure clearMarks(mark: byte); -var - Y, X: Longword; -begin - for Y:= 0 to Pred(HEIGHT) do - for X:= 0 to Pred(WIDTH) do - marks[Y, X]:= marks[Y, X] and (not mark) -end; - - -procedure initModule; -begin - WIDTH:= LAND_WIDTH shr gr; - HEIGHT:= LAND_HEIGHT shr gr; - - SetLength(marks, HEIGHT, WIDTH); -end; - -procedure freeModule; -begin - SetLength(marks, 0, 0); -end; - -end. +unit uAILandMarks; + +interface +const markWasHere = $01; + +procedure addMark(X, Y: LongInt; mark: byte); +function checkMark(X, Y: LongInt; mark: byte) : boolean; +procedure clearAllMarks; +procedure clearMarks(mark: byte); + +procedure initModule; +procedure freeModule; + +implementation +uses uVariables; + +const gr = 2; + +var marks: array of array of byte; + WIDTH, HEIGHT: Longword; + +procedure addMark(X, Y: LongInt; mark: byte); +begin + if((X and LAND_WIDTH_MASK) = 0) and ((Y and LAND_HEIGHT_MASK) = 0) then + begin + X:= X shr gr; + Y:= Y shr gr; + marks[Y, X]:= marks[Y, X] or mark + end +end; + +function checkMark(X, Y: LongInt; mark: byte) : boolean; +begin + checkMark:= ((X and LAND_WIDTH_MASK) = 0) + and ((Y and LAND_HEIGHT_MASK) = 0) + and ((marks[Y shr gr, X shr gr] and mark) <> 0) +end; + +procedure clearAllMarks; +var + Y, X: Longword; +begin + for Y:= 0 to Pred(HEIGHT) do + for X:= 0 to Pred(WIDTH) do + marks[Y, X]:= 0 +end; + +procedure clearMarks(mark: byte); +var + Y, X: Longword; +begin + for Y:= 0 to Pred(HEIGHT) do + for X:= 0 to Pred(WIDTH) do + marks[Y, X]:= marks[Y, X] and (not mark) +end; + + +procedure initModule; +begin + WIDTH:= LAND_WIDTH shr gr; + HEIGHT:= LAND_HEIGHT shr gr; + + SetLength(marks, HEIGHT, WIDTH); +end; + +procedure freeModule; +begin + SetLength(marks, 0, 0); +end; + +end. diff -r 01111960a48d -r deaeac102355 hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uAIMisc.pas Mon Aug 06 00:40:26 2012 +0400 @@ -86,12 +86,13 @@ ar: array[0..Pred(MAXBONUS div 8)] of TBonus; // don't use too many end; +const KillScore = 200; +var friendlyfactor: LongInt = 300; + implementation uses uCollisions, uVariables, uUtils, uDebug, uLandTexture; -const KillScore = 200; - -var friendlyfactor: LongInt = 300; +var KnownExplosion: record X, Y, Radius: LongInt end = (X: 0; Y: 0; Radius: 0); diff -r 01111960a48d -r deaeac102355 hedgewars/uCollisions.pas --- a/hedgewars/uCollisions.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uCollisions.pas Mon Aug 06 00:40:26 2012 +0400 @@ -82,7 +82,7 @@ X:= hwRound(Gear^.X); Y:= hwRound(Gear^.Y); Radius:= Gear^.Radius; - ChangeRoundInLand(X, Y, Radius - 1, true, Gear = CurrentHedgehog^.Gear); + ChangeRoundInLand(X, Y, Radius - 1, true, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase)); cGear:= Gear end; Gear^.CollisionIndex:= Count; @@ -103,7 +103,7 @@ if Gear^.CollisionIndex >= 0 then begin with cinfos[Gear^.CollisionIndex] do - ChangeRoundInLand(X, Y, Radius - 1, false, Gear = CurrentHedgehog^.Gear); + ChangeRoundInLand(X, Y, Radius - 1, false, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase)); cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)]; cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex; Gear^.CollisionIndex:= -1; @@ -138,7 +138,7 @@ var x, y, i: LongInt; begin // Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap -if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and +if (Gear^.CollisionMask = $FF7F) and (Gear^.Kind <> gtHedgehog) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and ((hwRound(Gear^.Hedgehog^.Gear^.X) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.X) - Gear^.Radius) or (hwRound(Gear^.Hedgehog^.Gear^.X) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.X) + Gear^.Radius)) then Gear^.CollisionMask:= $FFFF; @@ -168,7 +168,7 @@ var x, y, i: LongInt; begin // Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap -if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and +if (Gear^.CollisionMask = $FF7F) and (Gear^.Kind <> gtHedgehog) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and ((hwRound(Gear^.Hedgehog^.Gear^.Y) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.Y) - Gear^.Radius) or (hwRound(Gear^.Hedgehog^.Gear^.Y) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.Y) + Gear^.Radius)) then Gear^.CollisionMask:= $FFFF; diff -r 01111960a48d -r deaeac102355 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uCommandHandlers.pas Mon Aug 06 00:40:26 2012 +0400 @@ -626,13 +626,14 @@ if CheckNoTeamOrHH or isPaused then exit; -if FollowGear <> nil then +if autoCameraOn then begin + FollowGear:= nil; AddCaption('Auto Camera Off', $CCCCCC, capgrpVolume); autoCameraOn:= false end - else - begin +else + begin AddCaption('Auto Camera On', $CCCCCC, capgrpVolume); bShowFinger:= true; if not CurrentHedgehog^.Unplaced then diff -r 01111960a48d -r deaeac102355 hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uConsts.pas Mon Aug 06 00:40:26 2012 +0400 @@ -166,7 +166,7 @@ cMinZoomLevel = 3.5; cZoomDelta = 0.20; {$ELSE} - cMaxZoomLevel = 1.0; + cMaxZoomLevel = 0.25; cMinZoomLevel = 3.0; cZoomDelta = 0.25; {$ENDIF} diff -r 01111960a48d -r deaeac102355 hedgewars/uGears.pas --- a/hedgewars/uGears.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uGears.pas Mon Aug 06 00:40:26 2012 +0400 @@ -77,6 +77,7 @@ stAfterDelay, stChWin, stWater, stChWin2, stHealth, stSpawn, stNTurn); upd: Longword; + snowLeft,snowRight: LongInt; //SDMusic: shortstring; // For better maintainability the step handlers of gears are stored in @@ -642,9 +643,12 @@ AddGear(rx, ry, gtGenericFaller, gstInvisible, rdx, rdy, $FFFFFFFF); end; +snowRight:= max(LAND_WIDTH,4096)+512; +snowLeft:= -(snowRight-LAND_WIDTH); + if not hasBorder and ((Theme = 'Snow') or (Theme = 'Christmas')) then - for i:= 0 to Pred(vobCount*2) do - AddGear(GetRandom(LAND_WIDTH+1024)-512, LAND_HEIGHT - GetRandom(LAND_HEIGHT div 2), gtFlake, 0, _0, _0, 0); + for i:= vobCount * max(LAND_WIDTH,4096) div 2048 downto 1 do + AddGear(GetRandom(snowRight-snowLeft)+snowLeft, LAND_HEIGHT-1300+GetRandom(750), gtFlake, 0, _0, _0, 0); end; diff -r 01111960a48d -r deaeac102355 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uGearsHedgehog.pas Mon Aug 06 00:40:26 2012 +0400 @@ -455,11 +455,13 @@ procedure AfterAttack; var s: shortstring; a: TAmmoType; + HHGear: PGear; begin -with CurrentHedgehog^.Gear^, CurrentHedgehog^ do +with CurrentHedgehog^ do begin + HHGear:= Gear; a:= CurAmmoType; - State:= State and (not gstAttacking); + if HHGear <> nil then HHGear^.State:= HHGear^.State and (not gstAttacking); if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then begin Inc(MultiShootAttacks); @@ -484,8 +486,8 @@ TagTurnTimeLeft:= TurnTimeLeft; TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100; end; - if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) then - State:= State or gstAttacked; + if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (HHGear <> nil) then + HHGear^.State:= HHGear^.State or gstAttacked; if (Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0 then ApplyAmmoChanges(CurrentHedgehog^) end; diff -r 01111960a48d -r deaeac102355 hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uGearsUtils.pas Mon Aug 06 00:40:26 2012 +0400 @@ -510,7 +510,7 @@ count: LongInt = 0; begin if (y and LAND_HEIGHT_MASK) = 0 then - for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do + for i:= min(x + r, LAND_WIDTH - 4) downto max(x - r, 0) do if Land[y, i] and mask <> 0 then begin inc(count); diff -r 01111960a48d -r deaeac102355 hedgewars/uLand.pas --- a/hedgewars/uLand.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uLand.pas Mon Aug 06 00:40:26 2012 +0400 @@ -20,7 +20,7 @@ unit uLand; interface -uses SDLh, uLandTemplates, uFloat, uConsts, GLunit, uTypes; +uses SDLh, uLandTemplates, uFloat, uConsts, GLunit, uTypes, uAILandMarks; procedure initModule; procedure freeModule; @@ -35,6 +35,28 @@ var digest: shortstring; +procedure ResizeLand(width, height: LongWord); +var potW, potH: LongWord; +begin +potW:= toPowerOf2(width); +potH:= toPowerOf2(height); +if (potW <> LAND_WIDTH) or (potH <> LAND_HEIGHT) then + begin + LAND_WIDTH:= potW; + LAND_HEIGHT:= potH; + LAND_WIDTH_MASK:= not(LAND_WIDTH-1); + LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); + cWaterLine:= LAND_HEIGHT; + if (cReducedQuality and rqBlurryLand) = 0 then + SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH) + else + SetLength(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2); + + SetLength(Land, LAND_HEIGHT, LAND_WIDTH); + SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); + end; +end; + procedure ColorizeLand(Surface: PSDL_Surface); var tmpsurf: PSDL_Surface; r, rr: TSDL_Rect; @@ -181,6 +203,7 @@ i: Longword; y, x: Longword; begin + ResizeLand(Template.TemplateWidth, Template.TemplateHeight); for y:= 0 to LAND_HEIGHT - 1 do for x:= 0 to LAND_WIDTH - 1 do Land[y, x]:= lfBasic; @@ -237,6 +260,7 @@ procedure GenDrawnMap; begin + ResizeLand(4096, 2048); uLandPainted.Draw; MaxHedgehogs:= 48; @@ -299,7 +323,7 @@ WriteLnToConsole('Generating land...'); case cMapGen of 0: GenBlank(EdgeTemplates[SelectTemplate]); - 1: GenMaze; + 1: begin ResizeLand(4096,2048); GenMaze; end; 2: GenDrawnMap; else OutError('Unknown mapgen', true); @@ -489,7 +513,10 @@ if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptMissionMaps] + '/' + mapName + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); end; -TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true); +// (bare) Sanity check. Considering possible LongInt comparisons as well as just how much system memoery it would take +TryDo((tmpsurf^.w < $40000000) and (tmpsurf^.h < $40000000) and (tmpsurf^.w * tmpsurf^.h < 6*1024*1024*1024), 'Map dimensions too big!', true); + +ResizeLand(tmpsurf^.w, tmpsurf^.h); // unC0Rr - should this be passed from the GUI? I am not sure which layer does what s:= UserPathz[ptMapCurrent] + '/map.cfg'; @@ -676,12 +703,10 @@ LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask) end end; - -UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false); end; procedure GenPreview(out Preview: TPreview); -var x, y, xx, yy, t, bit, cbit, lh, lw: LongInt; +var rh, rw, ox, oy, x, y, xx, yy, t, bit, cbit, lh, lw: LongInt; begin WriteLnToConsole('Generating preview...'); case cMapGen of @@ -692,8 +717,21 @@ OutError('Unknown mapgen', true); end; - lh:= LAND_HEIGHT div 128; - lw:= LAND_WIDTH div 32; + // strict scaling needed here since preview assumes a rectangle + rh:= max(LAND_HEIGHT,2048); + rw:= max(LAND_WIDTH,4096); + ox:= 0; + if rw < rh*2 then + begin + rw:= rh*2; + end; + if rh < rw div 2 then rh:= rw * 2; + + ox:= (rw-LAND_WIDTH) div 2; + oy:= rh-LAND_HEIGHT; + + lh:= rh div 128; + lw:= rw div 32; for y:= 0 to 127 do for x:= 0 to 31 do begin @@ -704,7 +742,8 @@ cbit:= bit * 8; for yy:= y * lh to y * lh + 7 do for xx:= x * lw + cbit to x * lw + cbit + 7 do - if Land[yy, xx] <> 0 then + if ((yy-oy) and LAND_HEIGHT_MASK = 0) and ((xx-ox) and LAND_WIDTH_MASK = 0) + and (Land[yy-oy, xx-ox] <> 0) then inc(t); if t > 8 then Preview[y, x]:= Preview[y, x] or ($80 shr bit); diff -r 01111960a48d -r deaeac102355 hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uLandGraphics.pas Mon Aug 06 00:40:26 2012 +0400 @@ -59,7 +59,7 @@ begin addBgColor:= NewColor; exit - end; + end; // Get colors oRed := (OldColor shr RShift); oGreen := (OldColor shr GShift); @@ -72,7 +72,7 @@ // Mix colors nRed := min(255,((nRed*nAlpha) div 255) + ((oRed*oAlpha*byte(255-nAlpha)) div 65025)); nGreen := min(255,((nGreen*nAlpha) div 255) + ((oGreen*oAlpha*byte(255-nAlpha)) div 65025)); - nBlue := min(255,((nBlue*nAlpha) div 255) + ((oBlue*oAlpha*byte(255-nAlpha)) div 65025)); + nBlue := min(255,((nBlue*nAlpha) div 255) + ((oBlue*oAlpha*byte(255-nAlpha)) div 65025)); nAlpha := min(255, oAlpha + nAlpha); addBgColor := (nAlpha shl AShift) or (nRed shl RShift) or (nGreen shl GShift) or (nBlue shl BShift); @@ -82,19 +82,19 @@ var i: LongInt; begin if ((y + dy) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if (Land[y + dy, i] and lfIndestructible) = 0 then Land[y + dy, i]:= Value; if ((y - dy) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if (Land[y - dy, i] and lfIndestructible) = 0 then Land[y - dy, i]:= Value; if ((y + dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if (Land[y + dx, i] and lfIndestructible) = 0 then Land[y + dx, i]:= Value; if ((y - dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if (Land[y - dx, i] and lfIndestructible) = 0 then Land[y - dx, i]:= Value; end; @@ -105,26 +105,26 @@ if not doSet then begin if ((y + dy) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do + if isCurrent then Land[y + dy, i]:= Land[y + dy, i] and $FF7F else if Land[y + dy, i] and $007F > 0 then Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) - 1); if ((y - dy) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do + if isCurrent then Land[y - dy, i]:= Land[y - dy, i] and $FF7F else if Land[y - dy, i] and $007F > 0 then Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) - 1); if ((y + dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do + if isCurrent then Land[y + dx, i]:= Land[y + dx, i] and $FF7F else if Land[y + dx, i] and $007F > 0 then Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) - 1); if ((y - dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do + if isCurrent then Land[y - dx, i]:= Land[y - dx, i] and $FF7F else if Land[y - dx, i] and $007F > 0 then Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) - 1) @@ -132,28 +132,28 @@ else begin if ((y + dy) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do + if isCurrent then Land[y + dy, i]:= Land[y + dy, i] or $80 else if Land[y + dy, i] and $007F < 127 then Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) + 1); - if ((y - dy) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do - if isCurrent then - Land[y - dy, i]:= Land[y - dy, i] or $80 - else if Land[y - dy, i] and $007F < 127 then + if ((y - dy) and LAND_HEIGHT_MASK) = 0 then + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do + if isCurrent then + Land[y - dy, i]:= Land[y - dy, i] or $80 + else if Land[y - dy, i] and $007F < 127 then Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) + 1); - if ((y + dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then - Land[y + dx, i]:= Land[y + dx, i] or $80 - else if Land[y + dx, i] and $007F < 127 then + if ((y + dx) and LAND_HEIGHT_MASK) = 0 then + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do + if isCurrent then + Land[y + dx, i]:= Land[y + dx, i] or $80 + else if Land[y + dx, i] and $007F < 127 then Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) + 1); - if ((y - dx) and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do - if isCurrent then - Land[y - dx, i]:= Land[y - dx, i] or $80 - else if Land[y - dx, i] and $007F < 127 then + if ((y - dx) and LAND_HEIGHT_MASK) = 0 then + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do + if isCurrent then + Land[y - dx, i]:= Land[y - dx, i] or $80 + else if Land[y - dx, i] and $007F < 127 then Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) + 1) end end; @@ -207,7 +207,7 @@ begin t:= y + dy; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255)) then if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[t, i]:= 0 @@ -216,7 +216,7 @@ t:= y - dy; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255)) then if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[t, i]:= 0 @@ -225,7 +225,7 @@ t:= y + dx; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255)) then if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[t, i]:= 0 @@ -234,7 +234,7 @@ t:= y - dx; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255)) then if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[t, i]:= 0 @@ -250,7 +250,7 @@ cnt:= 0; t:= y + dy; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if (Land[t, i] and lfIndestructible) = 0 then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -266,13 +266,13 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; t:= y - dy; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if (Land[t, i] and lfIndestructible) = 0 then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -288,13 +288,13 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; t:= y + dx; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if (Land[t, i] and lfIndestructible) = 0 then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -310,12 +310,12 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; t:= y - dx; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if (Land[t, i] and lfIndestructible) = 0 then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -331,7 +331,7 @@ inc(cnt); LandPixels[by, bx]:= LandBackPixel(i, t) end - else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end; FillLandCircleLinesBG:= cnt; @@ -342,7 +342,7 @@ begin t:= y + dy; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -357,7 +357,7 @@ t:= y - dy; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do + for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -371,7 +371,7 @@ t:= y + dx; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -386,7 +386,7 @@ t:= y - dx; if (t and LAND_HEIGHT_MASK) = 0 then - for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do + for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -489,8 +489,8 @@ begin for i:= 0 to Pred(Count) do begin - for ty:= Max(y - Radius, 0) to Min(y + Radius, LAND_HEIGHT) do - for tx:= Max(0, ar^[i].Left - Radius) to Min(LAND_WIDTH, ar^[i].Right + Radius) do + for ty:= Min(y + Radius, LAND_HEIGHT) downto Max(y - Radius, 0) do + for tx:= Min(LAND_WIDTH, ar^[i].Right + Radius) downto Max(0, ar^[i].Left - Radius) do begin if (Land[ty, tx] and lfIndestructible) = 0 then begin @@ -504,7 +504,7 @@ end; if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then LandPixels[by, bx]:= LandBackPixel(tx, ty) - else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then + else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then LandPixels[by, bx]:= 0 end end; @@ -516,8 +516,8 @@ for i:= 0 to Pred(Count) do begin - for ty:= Max(y - Radius, 0) to Min(y + Radius, LAND_HEIGHT) do - for tx:= Max(0, ar^[i].Left - Radius) to Min(LAND_WIDTH, ar^[i].Right + Radius) do + for ty:= Min(y + Radius, LAND_HEIGHT) downto Max(y - Radius, 0) do + for tx:= Min(LAND_WIDTH, ar^[i].Right + Radius) downto Max(0, ar^[i].Left - Radius) do if ((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0) then begin if (cReducedQuality and rqBlurryLand) = 0 then @@ -567,7 +567,7 @@ and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - if despeckle then + if despeckle then begin Land[ty, tx]:= Land[ty, tx] or lfDamaged; LandDirty[ty div 32, tx div 32]:= 1 @@ -837,7 +837,7 @@ procedure Smooth(X, Y: LongInt); begin // a bit of AA for explosions -if (Land[Y, X] = 0) and (Y > LongInt(topY) + 1) and +if (Land[Y, X] = 0) and (Y > LongInt(topY) + 1) and (Y < LAND_HEIGHT-2) and (X > LongInt(leftX) + 1) and (X < LongInt(rightX) - 1) then begin if ((((Land[y, x-1] and lfDamaged) <> 0) and (((Land[y+1,x] and lfDamaged) <> 0)) or ((Land[y-1,x] and lfDamaged) <> 0)) diff -r 01111960a48d -r deaeac102355 hedgewars/uLandTemplates.pas --- a/hedgewars/uLandTemplates.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uLandTemplates.pas Mon Aug 06 00:40:26 2012 +0400 @@ -1571,9 +1571,191 @@ ( (X: 512; Y: 0) ); +// Many islands +const Template43Points: array[0..173] of TSDL_Rect = + ( + (x: 95; y: 500; w: 1; h: 1), + (x: 100; y: 275; w: 25; h: 100), + (x: 325; y: 275; w: 25; h: 100), + (x: 330; y: 500; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 725; y: 125; w: 1; h: 1), + (x: 725; y: 25; w: 5; h: 25), + (x: 825; y: 35; w: 5; h: 10), + (x: 825; y: 135; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1150; y: 550; w: 25; h: 50), + (x: 1250; y: 300; w: 25; h: 50), + (x: 1350; y: 300; w: 25; h: 50), + (x: 1400; y: 575; w: 25; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 525; y:1050; w: 50; h: 50), + (x: 700; y: 800; w: 100; h: 150), + (x: 950; y: 900; w: 100; h: 150), + (x: 1100; y:1100; w: 50; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 175; y:1500; w: 1; h: 1), + (x: 210; y:1400; w: 5; h: 25), + (x: 240; y:1400; w: 5; h: 25), + (x: 275; y:1510; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 450; y:1800; w: 100; h: 100), + (x: 600; y:1750; w: 100; h: 100), + (x: 750; y:1750; w: 100; h: 100), + (x: 950; y:1850; w: 100; h: 100), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1075; y:1450; w: 1; h: 1), + (x: 1110; y:1300; w: 5; h: 25), + (x: 1140; y:1300; w: 5; h: 25), + (x: 1175; y:1430; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1600; y:1250; w: 25; h: 100), + (x: 1700; y:1150; w: 25; h: 100), + (x: 1850; y: 500; w: 50; h: 100), + (x: 1950; y: 550; w: 50; h: 150), + (x: 2250; y:1150; w: 25; h: 100), + (x: 2350; y:1250; w: 25; h: 100), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1750; y:2010; w: 1; h: 1), + (x: 1900; y:1870; w: 50; h: 50), + (x: 2050; y:1870; w: 50; h: 50), + (x: 2175; y:2010; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2500; y:1700; w: 1; h: 1), + (x: 2575; y:1500; w: 10; h: 50), + (x: 2650; y:1500; w: 10; h: 50), + (x: 2700; y:1690; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2000; y: 125; w: 1; h: 1), + (x: 2050; y: 50; w: 25; h: 25), + (x: 2100; y: 50; w: 25; h: 25), + (x: 2150; y: 150; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2600; y: 250; w: 25; h: 100), + (x: 2750; y: 400; w: 50; h: 50), + (x: 2900; y: 525; w: 50; h: 50), + (x: 3150; y: 550; w: 50; h: 100), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2800; y:1150; w: 1; h: 1), + (x: 2840; y: 950; w: 25; h: 25), + (x: 2880; y: 950; w: 25; h: 25), + (x: 2900; y:1150; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3075; y:1985; w: 1; h: 1), + (x: 3325; y:1700; w: 50; h: 100), + (x: 3475; y:1700; w: 50; h: 100), + (x: 3625; y:1985; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3200; y:1450; w: 1; h: 1), + (x: 3240; y:1350; w: 25; h: 25), + (x: 3280; y:1350; w: 25; h: 25), + (x: 3300; y:1450; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3500; y:1050; w: 25; h: 50), + (x: 3650; y: 600; w: 50; h: 100), + (x: 3800; y: 600; w: 50; h: 100), + (x: 3900; y:1000; w: 25; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 3800; y: 200; w: 25; h: 50), + (x: 3875; y: 100; w: 50; h: 50), + (x: 3925; y: 50; w: 50; h: 25), + (x: 4050; y: 125; w: 25; h: 50), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 95; y:2548; w: 1; h: 1), + (x: 100; y:2323; w: 25; h: 100), + (x: 325; y:2323; w: 25; h: 100), + (x: 330; y:2548; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 725; y:2173; w: 1; h: 1), + (x: 725; y:2073; w: 5; h: 25), + (x: 825; y:2083; w: 5; h: 10), + (x: 825; y:2183; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1150; y:2598; w: 25; h: 50), + (x: 1250; y:2348; w: 25; h: 50), + (x: 1350; y:2348; w: 25; h: 50), + (x: 1400; y:2623; w: 25; h: 50), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 525; y:3098; w: 50; h: 50), + (x: 700; y:2848; w: 100; h: 150), + (x: 950; y:2948; w: 100; h: 150), + (x: 1100; y:3148; w: 50; h: 50), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 175; y:3548; w: 1; h: 1), + (x: 210; y:3448; w: 5; h: 25), + (x: 240; y:3448; w: 5; h: 25), + (x: 275; y:3558; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 450; y:3848; w: 100; h: 100), + (x: 600; y:3798; w: 100; h: 100), + (x: 750; y:3798; w: 100; h: 100), + (x: 950; y:3898; w: 100; h: 100), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1075; y:3498; w: 1; h: 1), + (x: 1110; y:3348; w: 5; h: 25), + (x: 1140; y:3348; w: 5; h: 25), + (x: 1175; y:3478; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1600; y:3298; w: 25; h: 100), + (x: 1700; y:3198; w: 25; h: 100), + (x: 1850; y:2548; w: 50; h: 100), + (x: 1950; y:2598; w: 50; h: 150), + (x: 2250; y:3198; w: 25; h: 100), + (x: 2350; y:3298; w: 25; h: 100), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 1750; y:4058; w: 1; h: 1), + (x: 1900; y:3918; w: 50; h: 50), + (x: 2050; y:3918; w: 50; h: 50), + (x: 2175; y:4058; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2500; y:3748; w: 1; h: 1), + (x: 2575; y:3548; w: 10; h: 50), + (x: 2650; y:3548; w: 10; h: 50), + (x: 2700; y:3738; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2000; y:2173; w: 1; h: 1), + (x: 2050; y:2098; w: 25; h: 25), + (x: 2100; y:2098; w: 25; h: 25), + (x: 2150; y:2198; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2600; y:2298; w: 25; h: 100), + (x: 2750; y:2448; w: 50; h: 50), + (x: 2900; y:2573; w: 50; h: 50), + (x: 3150; y:2598; w: 50; h: 100), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 2800; y:3198; w: 1; h: 1), + (x: 2840; y:2998; w: 25; h: 25), + (x: 2880; y:2998; w: 25; h: 25), + (x: 2900; y:3198; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3075; y:4033; w: 1; h: 1), + (x: 3325; y:3748; w: 50; h: 100), + (x: 3475; y:3748; w: 50; h: 100), + (x: 3625; y:4033; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3200; y:3498; w: 1; h: 1), + (x: 3240; y:3398; w: 25; h: 25), + (x: 3280; y:3398; w: 25; h: 25), + (x: 3300; y:3498; w: 1; h: 1), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3500; y:3098; w: 25; h: 50), + (x: 3650; y:2648; w: 50; h: 100), + (x: 3800; y:2648; w: 50; h: 100), + (x: 3900; y:3048; w: 25; h: 50), + (x: NTPX; y:2048; w: 1; h: 1), + (x: 3800; y:2248; w: 25; h: 50), + (x: 3875; y:2148; w: 50; h: 50), + (x: 3925; y:2098; w: 50; h: 25), + (x: 4050; y:2173; w: 25; h: 50), + (x: NTPX; y:2048; w: 1; h: 1) + ); + Template43FPoints: array[0..0] of TPoint = + ( + (X: 4095; Y: 0) + ); //////////////////////////////////////////////////////////////////////// -var EdgeTemplates: array[0..42] of TEdgeTemplate = +var EdgeTemplates: array[0..43] of TEdgeTemplate = ( (BasePoints: @Template0Points; BasePointsCount: Succ(High(Template0Points)); @@ -2047,19 +2229,30 @@ canMirror: true; canFlip: false; isNegative: false; canInvert: false; hasGirders: false; MaxHedgeHogs: 8; + ), + (BasePoints: @Template43Points; + BasePointsCount: Succ(High(Template43Points)); + FillPoints: @Template43FPoints; + FillPointsCount: Succ(High(Template43FPoints)); + BezierizeCount: 3; + RandPassesCount: 5; + TemplateHeight: 4096; TemplateWidth: 4096; + canMirror: true; canFlip: true; isNegative: false; canInvert: false; + hasGirders: true; + MaxHedgeHogs: 48; ) ); const SmallTemplates: array[0..2] of Longword = ( 39, 40, 42 ); const MediumTemplates: array[0..17] of Longword = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ); -const LargeTemplates: array[0..19] of Longword = +const LargeTemplates: array[0..20] of Longword = ( 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 37, 38 + 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 43 ); const CavernTemplates: array[0..4] of Longword = (36, 2, 3, 21, 29); //const WackyTemplates: array[0..4] of Longword = (37, 38, 39, 40, 41); -const WackyTemplates: array[0..2] of Longword = (37, 38, 41); +const WackyTemplates: array[0..3] of Longword = (37, 38, 41, 43); implementation diff -r 01111960a48d -r deaeac102355 hedgewars/uStore.pas --- a/hedgewars/uStore.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uStore.pas Mon Aug 06 00:40:26 2012 +0400 @@ -135,10 +135,11 @@ procedure WriteNames(Font: THWFont); var t: LongInt; - i: LongInt; + i, maxLevel: LongInt; r, rr: TSDL_Rect; drY: LongInt; texsurf, flagsurf, iconsurf: PSDL_Surface; + foundBot: boolean; begin r.x:= 0; r.y:= 0; @@ -176,11 +177,28 @@ DrawRoundRect(@r, cWhiteColor, cNearBlackColor, texsurf, true); // overwrite flag for cpu teams and keep players from using it - if (Hedgehogs[0].Gear <> nil) and (Hedgehogs[0].BotLevel > 0) then - if Flag = 'hedgewars' then - Flag:= 'cpu' - else if Flag = 'cpu' then - Flag:= 'hedgewars'; + foundBot:= false; + maxLevel:= -1; + for i:= 0 to cMaxHHIndex do + with Hedgehogs[i] do + if (Gear <> nil) and (BotLevel > 0) then + begin + foundBot:= true; + // initially was going to do the highest botlevel of the team, but for now, just apply if entire team has same bot level + if maxLevel = -1 then maxLevel:= BotLevel + else if (maxLevel > 0) and (maxLevel <> BotLevel) then maxLevel:= 0; + //if (maxLevel > 0) and (BotLevel < maxLevel) then maxLevel:= BotLevel + end + else if Gear <> nil then maxLevel:= 0; + + if foundBot then + begin + // disabled the plain flag - I think it looks ok even w/ full bars obscuring CPU + //if (maxLevel > 0) and (maxLevel < 3) then Flag:= 'cpu_plain' else + Flag:= 'cpu' + end + else if (Flag = 'cpu') or (Flag = 'cpu_plain') then + Flag:= 'hedgewars'; flagsurf:= LoadImage(UserPathz[ptFlags] + '/' + Flag, ifNone); if flagsurf = nil then @@ -190,16 +208,27 @@ if flagsurf = nil then flagsurf:= LoadImage(Pathz[ptFlags] + '/hedgewars', ifNone); TryDo(flagsurf <> nil, 'Failed to load flag "' + Flag + '" as well as the default flag', true); + + case maxLevel of + 1: copyToXY(SpritesData[sprBotlevels].Surface, flagsurf, 0, 0); + 2: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 5, 2, 17, 13, 5, 2); + 3: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 9, 5, 13, 10, 9, 5); + 4: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 13, 9, 9, 6, 13, 9); + 5: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 17, 11, 5, 4, 17, 11) + end; + copyToXY(flagsurf, texsurf, 2, 2); SDL_FreeSurface(flagsurf); flagsurf:= nil; + // restore black border pixels inside the flag PLongwordArray(texsurf^.pixels)^[32 * 2 + 2]:= cNearBlackColor; PLongwordArray(texsurf^.pixels)^[32 * 2 + 23]:= cNearBlackColor; PLongwordArray(texsurf^.pixels)^[32 * 16 + 2]:= cNearBlackColor; PLongwordArray(texsurf^.pixels)^[32 * 16 + 23]:= cNearBlackColor; + FlagTex:= Surface2Tex(texsurf, false); SDL_FreeSurface(texsurf); texsurf:= nil; @@ -208,7 +237,7 @@ dec(drY, r.h + 2); DrawHealthY:= drY; - for i:= 0 to 7 do + for i:= 0 to cMaxHHIndex do with Hedgehogs[i] do if Gear <> nil then begin @@ -298,7 +327,6 @@ WriteLnToConsole(msgOK) end; -WriteNames(fnt16); MakeCrossHairs; LoadGraves; if not reload then @@ -395,6 +423,8 @@ Surface:= nil end; +WriteNames(fnt16); + if not reload then AddProgress; diff -r 01111960a48d -r deaeac102355 hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uTypes.pas Mon Aug 06 00:40:26 2012 +0400 @@ -86,7 +86,7 @@ sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb, sprBulletHit, sprSnowball, sprHandSnowball, sprSnow, sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis, - sprSlider + sprSlider, sprBotlevels ); // Gears that interact with other Gears and/or Land diff -r 01111960a48d -r deaeac102355 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uVariables.pas Mon Aug 06 00:40:26 2012 +0400 @@ -654,7 +654,9 @@ (FileName: 'TARDIS'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; Width: 48; Height: 79; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis (FileName: 'slider'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; - Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprSlider + Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider + (FileName: 'botlevels'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 22; Height: 15; imageWidth: 22; imageHeight: 15; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprBotlevels ); const diff -r 01111960a48d -r deaeac102355 hedgewars/uWorld.pas --- a/hedgewars/uWorld.pas Thu Jul 26 21:58:25 2012 +0400 +++ b/hedgewars/uWorld.pas Mon Aug 06 00:40:26 2012 +0400 @@ -1645,10 +1645,7 @@ uCursor.updatePosition(); {$ENDIF} z:= round(200/zoom); -if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) then - if (not autoCameraOn) then - FollowGear:= nil - else +if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) and autoCameraOn then if ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then begin FollowGear:= nil; diff -r 01111960a48d -r deaeac102355 share/hedgewars/Data/Graphics/Flags/cpu_plain.png Binary file share/hedgewars/Data/Graphics/Flags/cpu_plain.png has changed diff -r 01111960a48d -r deaeac102355 share/hedgewars/Data/Graphics/botlevels.png Binary file share/hedgewars/Data/Graphics/botlevels.png has changed diff -r 01111960a48d -r deaeac102355 share/hedgewars/Data/Locale/en.txt --- a/share/hedgewars/Data/Locale/en.txt Thu Jul 26 21:58:25 2012 +0400 +++ b/share/hedgewars/Data/Locale/en.txt Mon Aug 06 00:40:26 2012 +0400 @@ -492,7 +492,7 @@ 04:36=Well, sometimes you're just too bad in aiming. Get|some assistance using modern day technology.|Attack: Activate 04:37=Don't fear the daylight. It will just last one turn|but will enable you to absorb the damage you do to|other hogs.|Attack: Activate 04:38=The sniper rifle can be the most devastating weapon|in your whole arsenal, however it's very ineffective|at close quarters. The damage dealt increases with|the distance to its target.|Attack: Shoot (twice) -04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility is able to|take you to almost any position on the battlefield.|Attack: Activate|Up/Left/Right: Apply force in one direction|Long Jump: Drop grenades or similar weapons +04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility can|take you to almost any position on the battlefield.|Attack: Activate|Up/Left/Right: Apply force in one direction|Long Jump: Drop grenades or similar weapons 04:40=Set some ground on fire using this bottle filled|with (soon to be) burning liquid.|Attack: Hold to shoot with more power 04:41=The evidence nature might even top the flying|saucer. Birdy can carry your hog around and|drop eggs on your enemies!|Be quick, as using Birdy eats into your turn|time!|Attack: Activate and drop eggs|Up/Left/Right: Flap in one direction 04:42=This portable portal device is capable|of instantly transporting you, your enemies,|or your weaponry between two points on the|terrain.|Use it wisely and your campaign will be a...|HUGE SUCCESS!|Attack: Shoot a portal|Switch: Cycle portal colours @@ -506,7 +506,7 @@ 04:50=Is someone hiding underground?|Dig them out with a drill strike!|Timer controls how far it will dig. 04:51=Get in a free shot by hurling a ball of mud.|Stings a bit, and knocks hogs back. 04:52=UNUSED -04:53=Go on an adventure through time and space,|while leaving your comrades to fight on alone.|Be prepared to return at any time,|or for Sudden Death or if they are all defeated.|Disclaimer. Does not function in Sudden Death,|if you are alone, or if you are a King. +04:53=Take a trip through time and space,|while leaving your comrades to fight on alone.|Be prepared to return at any time,|or for Sudden Death or if they are all defeated.|Disclaimer. Does not function in Sudden Death,|if you are alone, or if you are a King. 04:54=INCOMPLETE 04:55=Spray a stream of sticky flakes.|Build bridges, bury enemies, seal off tunnels.|Be careful you don't get any on you!