# HG changeset patch # User sheepluva # Date 1404593698 -7200 # Node ID 86a823dd1d23d96a3815711b28caac7f1df84fa3 # Parent 25f325b48a6c640d5d96231e794f1e60d7cf0b4c# Parent 7d1044267b8395fd65f2d0086ca0e421bdfe5c0e merge (even although I rebased... ok) diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uAIMisc.pas Sat Jul 05 22:54:58 2014 +0200 @@ -445,7 +445,7 @@ end; exit(0) end; - if (y > cWaterLine) or (x > rightX) or (x < leftX) then exit(-1) + if CheckCoordInWater(round(x), round(y)) then exit(-1) end end; @@ -497,7 +497,7 @@ end; exit(0) end; - if (y > cWaterLine) or (x > rightX) or (x < leftX) then + if CheckCoordInWater(round(x), round(y)) then // returning -1 for drowning so it can be considered in the Rate routine exit(-1) end; @@ -876,7 +876,7 @@ UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true); end;} - if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then + if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + cHHRadius) then exit(false); if (Gear^.State and gstMoving) <> 0 then begin @@ -941,7 +941,7 @@ pX:= hwRound(Gear^.X); pY:= hwRound(Gear^.Y); - if pY + cHHRadius >= cWaterLine then + if CheckCoordInWater(pX, pY + cHHRadius) then begin if AltGear^.Hedgehog^.BotLevel < 4 then AddWalkBonus(pX, tY, 250, -40); diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uCollisions.pas --- a/hedgewars/uCollisions.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uCollisions.pas Sat Jul 05 22:54:58 2014 +0200 @@ -54,6 +54,8 @@ function TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; +function CheckCoordInWater(X, Y: LongInt): boolean; inline; + // returns: negative sign if going downhill to left, value is steepness (noslope/error = _0, 45 = _0_5) function CalcSlopeBelowGear(Gear: PGear): hwFloat; function CalcSlopeNearGear(Gear: PGear; dirX, dirY: LongInt): hwFloat; @@ -112,6 +114,12 @@ end; end; +function CheckCoordInWater(X, Y: LongInt): boolean; inline; +begin + CheckCoordInWater:= (Y > cWaterLine) + or ((WorldEdge = weSea) and ((X < leftX) or (X > rightX))); +end; + function CheckGearsCollision(Gear: PGear): PGearArray; var mx, my, tr: LongInt; i: Longword; diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uConsts.pas Sat Jul 05 22:54:58 2014 +0200 @@ -314,6 +314,8 @@ kSystemSoundID_Vibrate = $00000FFF; + cMinPlayWidth = 200; + implementation end. diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uGearsHandlersMess.pas --- a/hedgewars/uGearsHandlersMess.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uGearsHandlersMess.pas Sat Jul 05 22:54:58 2014 +0200 @@ -259,9 +259,29 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepDrowningGear(Gear: PGear); begin - AllInactive := false; + if Gear^.Timer = 0 then + begin + if (FollowGear = Gear) and (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) then + FollowGear:= CurrentHedgehog^.Gear; + end + else if Gear^.Timer > 0 then + begin + AllInactive := false; + dec(Gear^.Timer); + end; + Gear^.Y := Gear^.Y + cDrownSpeed; - Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed; + + if cWaterLine > hwRound(Gear^.Y) + Gear^.Radius then + begin + if leftX > hwRound(Gear^.X) - Gear^.Radius then + Gear^.X := Gear^.X - cDrownSpeed + else + Gear^.X := Gear^.X + cDrownSpeed; + end + else + Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed; + // Create some bubbles (0.5% might be better but causes too few bubbles sometimes) if ((not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then @@ -301,7 +321,7 @@ if Gear^.dY.Round > 1 then Gear^.dY.QWordValue:= 8589934592; - if (Gear^.State and gstSubmersible <> 0) and (gY > cWaterLine) then + if (Gear^.State and gstSubmersible <> 0) and CheckCoordInWater(gX, gY) then begin Gear^.dX:= Gear^.dX * _0_999; Gear^.dY:= Gear^.dY * _0_999 @@ -787,7 +807,7 @@ end; *) // move back to cloud layer - if yy > cWaterLine then + if CheckCoordInWater(xx, yy) then move:= true else if (xx > snowRight) or (xx < snowLeft) then move:=true @@ -956,16 +976,19 @@ gX := hwRound(Gear^.X); gY := hwRound(Gear^.Y); uw := (Gear^.Tag <> 0); // was bee underwater last tick? - nuw := (cWaterLine < gy + Gear^.Radius); // is bee underwater now? + nuw := CheckCoordInWater(gx, gy + Gear^.Radius); // is bee underwater now? // if water entered or left if nuw <> uw then begin - AddVisualGear(gX, cWaterLine, vgtSplash); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); + if (gX > leftX) and (gY < rightX) then + begin + AddVisualGear(gX, cWaterLine, vgtSplash); + AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); + AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); + AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); + AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); + end; StopSoundChan(Gear^.SoundChannel); if nuw then begin @@ -1178,7 +1201,7 @@ if (hwRound(Bullet^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Bullet^.Y) and LAND_HEIGHT_MASK <> 0) then // only extend if not under water - if hwRound(Bullet^.Y) < cWaterLine then + if not CheckCoordInWater(hwRound(Bullet^.X), hwRound(Bullet^.Y)) then begin VGear^.dX := VGear^.dX + max(LAND_WIDTH,4096) * (VGear^.dX - VGear^.X); VGear^.dY := VGear^.dY + max(LAND_WIDTH,4096) * (VGear^.dY - VGear^.Y); @@ -2153,11 +2176,13 @@ Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640; Gear^.Y := Gear^.Y + Gear^.dY; - if (hwRound(Gear^.Y) > cWaterLine) then + gX := hwRound(Gear^.X); + gY := hwRound(Gear^.Y); + + if CheckCoordInWater(gX, gY) then begin - gX := hwRound(Gear^.X); for i:= 0 to 3 do - AddVisualGear(gX - 16 + Random(32), cWaterLine - 16 + Random(16), vgtSteam); + AddVisualGear(gX - 8 + Random(16), gY - 8 + Random(16), vgtSteam); PlaySound(sndVaporize); DeleteGear(Gear); exit @@ -2170,8 +2195,7 @@ Gear^.Y:= Gear^.Y+_6; if (landPixel and lfIce <> 0) or (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then begin - gX := hwRound(Gear^.X); - gY := hwRound(Gear^.Y)-6; + gY := gy-6; DrawExplosion(gX, gY, 4); PlaySound(sndVaporize); AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSteam); @@ -2201,8 +2225,6 @@ end else begin - gX := hwRound(Gear^.X); - gY := hwRound(Gear^.Y); // Standard fire if not sticky then begin @@ -2252,8 +2274,6 @@ end; if Gear^.Health = 0 then begin - gX := hwRound(Gear^.X); - gY := hwRound(Gear^.Y); if not sticky then begin if ((GameTicks and $3) = 0) and (Random(1) = 0) then @@ -2799,6 +2819,14 @@ HHGear^.X := Gear^.X; HHGear^.Y := Gear^.Y; + // check for drowning + if CheckGearDrowning(HHGear) then + begin + AfterAttack; + DeleteGear(Gear); + exit; + end; + inc(Gear^.Damage, 2); // if TestCollisionXwithGear(HHGear, hwSign(Gear^.dX)) @@ -3167,6 +3195,18 @@ else exit; + if playWidth > cMinPlayWidth then + begin + inc(leftX); + dec(rightX); + dec(playWidth, 2); + for i:= 0 to LAND_HEIGHT - 1 do + begin + Land[i, leftX] := 0; + Land[i, rightX] := 0; + end; + end; + if cWaterLine > 0 then begin dec(cWaterLine); @@ -3508,7 +3548,7 @@ isUnderwater: Boolean; bubble: PVisualGear; begin - isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius; + isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); if Gear^.Pos > 0 then dec(Gear^.Pos); AllInactive := false; @@ -3614,6 +3654,7 @@ if // (Gear^.Health = 0) (HHGear^.Damage <> 0) //or CheckGearDrowning(HHGear) + // drown if too deep under water or (cWaterLine + cVisibleWater * 4 < hwRound(HHGear^.Y)) or (TurnTimeLeft = 0) // allow brief ground touches - to be fair on this, might need another counter @@ -3929,7 +3970,7 @@ if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] <= lfAllObjMask) or (Gear^.Timer < 1) or (Gear^.Hedgehog^.Team <> CurrentHedgehog^.Team) - or (hwRound(Gear^.Y) > cWaterLine) then + or CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then begin deleteGear(Gear); EXIT; @@ -4318,7 +4359,7 @@ loadNewPortalBall(Gear, true); end - else if (y > cWaterLine) + else if CheckCoordInWater(x, y) or (y < -max(LAND_WIDTH,4096)) or (x > 2*max(LAND_WIDTH,4096)) or (x < -max(LAND_WIDTH,4096)) then @@ -4558,7 +4599,7 @@ end else begin - if (rY <= cWaterLine) or (y <= cWaterLine) then + if CheckCoordInWater(rX, rY) or CheckCoordInWater(x, y) then begin if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then @@ -4945,7 +4986,7 @@ begin //Gear^.dY := Gear^.dY + cGravity; //Gear^.Y := Gear^.Y + Gear^.dY; - if hwRound(Gear^.Y) > cWaterLine then + if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then Gear^.Timer := 1 end; diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uGearsHedgehog.pas Sat Jul 05 22:54:58 2014 +0200 @@ -423,7 +423,7 @@ newGear^.dY:= newDY / newGear^.Density end; if (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack) and - (Gear^.Message and gmPrecise <> 0) and (hwRound(Y) > cWaterLine) then + (Gear^.Message and gmPrecise <> 0) and CheckCoordInWater(hwRound(X), hwRound(Y)) then newGear^.State:= newGear^.State or gstSubmersible; case CurAmmoType of @@ -548,7 +548,7 @@ begin if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft; - if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and (hwRound(CurAmmoGear^.Y) > cWaterLine) then + if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and CheckCoordInWater(hwRound(CurAmmoGear^.X), hwRound(CurAmmoGear^.Y)) then TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 25 else TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100; end; @@ -864,7 +864,7 @@ land: Word; begin land:= 0; -isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius; +isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); if Gear^.dX.QWordValue > 8160437862 then Gear^.dX.QWordValue:= 8160437862; if Gear^.dY.QWordValue > 8160437862 then diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uGearsList.pas --- a/hedgewars/uGearsList.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uGearsList.pas Sat Jul 05 22:54:58 2014 +0200 @@ -649,12 +649,11 @@ begin if (Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtKamikaze) then Gear^.Hedgehog^.Team^.Clan^.Flawless:= false; - if (hwRound(Gear^.Y) >= cWaterLine) then + if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then begin t:= max(Gear^.Damage, Gear^.Health); Gear^.Damage:= t; - if (((not SuddenDeathDmg) and (WaterOpacity < $FF)) or (SuddenDeathDmg and (WaterOpacity < $FF))) - and (hwRound(Gear^.Y) < cWaterLine + 256) then + if (((not SuddenDeathDmg) and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) then spawnHealthTagForHH(Gear, t); end; diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uGearsUtils.pas Sat Jul 05 22:54:58 2014 +0200 @@ -357,19 +357,40 @@ Gear^.DirAngle := Gear^.DirAngle - 360 end; +procedure DrownGear(Gear: PGear); +begin +Gear^.doStep := @doStepDrowningGear; + +Gear^.Timer := 5000; // how long game should wait +end; + function CheckGearDrowning(var Gear: PGear): boolean; var - skipSpeed, skipAngle, skipDecay: hwFloat; - i, maxDrops, X, Y: LongInt; - vdX, vdY: real; + skipSpeed, skipAngle, skipDecay, hwTmp: hwFloat; + i, maxDrops, X, Y, dist2Water: LongInt; + vdX, vdY, tmp: real; particle, splash: PVisualGear; - isSubmersible: boolean; + isSubmersible, isImpactH, isImpactRight, isLeaving: boolean; s: ansistring; begin // probably needs tweaking. might need to be in a case statement based upon gear type + X:= hwRound(Gear^.X); Y:= hwRound(Gear^.Y); - if cWaterLine < Y + Gear^.Radius then + + dist2Water:= cWaterLine - (Y + Gear^.Radius); + isImpactH:= false; + + if WorldEdge = weSea then begin + i:= dist2Water; + dist2Water:= min(dist2Water, min(X - Gear^.Radius - leftX, rightX - (X + Gear^.Radius))); + isImpactH:= i <> dist2Water; + end; + + if dist2Water < 0 then + begin + // invisible gears will just be deleted + // unless they are generic fallers, then they will be "respawned" if Gear^.State and gstInvisible <> 0 then begin if Gear^.Kind = gtGenericFaller then @@ -386,20 +407,33 @@ skipSpeed := _0_25; skipAngle := _1_9; skipDecay := _0_87; - X:= hwRound(Gear^.X); - vdX:= hwFloat2Float(Gear^.dX); - vdY:= hwFloat2Float(Gear^.dY); - // this could perhaps be a tiny bit higher. - if (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) - and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then + vdX:= abs(hwFloat2Float(Gear^.dX)); + vdY:= abs(hwFloat2Float(Gear^.dY)); + + // skipping + + // check for -1 depth because if deeper, then it already had its chance of skipping + if (dist2Water = -1) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) + and ( ((not isImpactH) and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY))) + or (isImpactH and (hwAbs(Gear^.dY) > skipAngle * hwAbs(Gear^.dX))) ) then begin - Gear^.dY.isNegative := true; + // if skipping we move the gear out of water + if isImpactH then + begin + Gear^.dX.isNegative := (not Gear^.dX.isNegative); + Gear^.X:= Gear^.X + Gear^.dX; + end + else + begin + Gear^.dY.isNegative := (not Gear^.dY.isNegative); + Gear^.Y:= Gear^.Y + Gear^.dY; + end; Gear^.dY := Gear^.dY * skipDecay; Gear^.dX := Gear^.dX * skipDecay; CheckGearDrowning := false; PlaySound(sndSkip) end - else + else // not skipping begin if not isSubmersible then begin @@ -418,58 +452,110 @@ end else begin - Gear^.doStep := @doStepDrowningGear; + DrownGear(Gear); Gear^.State := Gear^.State and (not gstHHDriven); s:= ansistring(Gear^.Hedgehog^.Name); AddCaption(FormatA(GetEventString(eidDrowned), s), cWhiteColor, capgrpMessage); end end else - Gear^.doStep := @doStepDrowningGear; - if Gear^.Kind = gtFlake then - exit(true) // skip splashes + DrownGear(Gear); + if Gear^.Kind = gtFlake then + exit(true); // skip splashes end + // drown submersible grears if far below map else if (Y > cWaterLine + cVisibleWater*4) and ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then - Gear^.doStep:= @doStepDrowningGear; - if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) - or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) - and (CurAmmoGear^.dY < _0_01))) then - if Gear^.Density * Gear^.dY > _1 then + DrownGear(Gear); + + isImpactRight:= isImpactH and (abs(X - LongInt(leftX)) > abs(LongInt(rightX) - X)); + isLeaving:= (isSubmersible and (dist2Water = -2 * Gear^.Radius) and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) + and (((not isImpactH) and CurAmmoGear^.dY.isNegative) or (isImpactH and (isImpactRight = CurAmmoGear^.dX.isNegative)))); + + // splash sound + + if ((not isSubmersible) and (dist2Water = -1)) + or isLeaving then + begin + // adjust water impact sound on gear speed and density + if isImpactH then + hwTmp:= hwAbs(Gear^.Density * Gear^.dX) + else + hwTmp:= hwAbs(Gear^.Density * Gear^.dY); + + if hwTmp > _1 then PlaySound(sndSplash) - else if Gear^.Density * Gear^.dY > _0_5 then + else if hwTmp > _0_5 then PlaySound(sndSkip) else PlaySound(sndDroplet2); + end; end; + // splash animation + if ((cReducedQuality and rqPlainSplash) = 0) - and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) - or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) - and (CurAmmoGear^.dY < _0_01)))) then + and (((not isSubmersible) and (dist2Water = -1)) + or isLeaving) then begin - splash:= AddVisualGear(X, cWaterLine, vgtSplash); + splash:= AddVisualGear(X, Y, vgtSplash); if splash <> nil then - with splash^ do begin - Scale:= hwFloat2Float(Gear^.Density / _3 * Gear^.dY); - if Scale > 1 then Scale:= power(Scale,0.3333) - else Scale:= Scale + ((1-Scale) / 2); - if Scale > 1 then Timer:= round(min(Scale*0.0005/cGravityf,4)) - else Timer:= 1; - // Low Gravity - FrameTicks:= FrameTicks*Timer; + if isImpactH then + begin + splash^.Scale:= abs(hwFloat2Float((Gear^.Density / _3) * Gear^.dX)); + if isImpactRight then + splash^.Angle:= -90 + else + splash^.Angle:= 90; + end + else + splash^.Scale:= abs(hwFloat2Float(Gear^.Density / _3 * Gear^.dY)); + with splash^ do + begin + if Scale > 1 then Scale:= power(Scale,0.3333) + else Scale:= Scale + ((1-Scale) / 2); + if Scale > 1 then Timer:= round(min(Scale*0.0005/cGravityf,4)) + else Timer:= 1; + // Low Gravity + FrameTicks:= FrameTicks*Timer; + end; end; + // eject water drops + maxDrops := (hwRound(Gear^.Density) * 3) div 2 + round(vdX * hwRound(Gear^.Density) * 6) + round(vdY * hwRound(Gear^.Density) * 6); for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do begin - particle := AddVisualGear(X - 3 + Random(7), cWaterLine, vgtDroplet); + if isImpactH then + begin + if isImpactRight then + particle := AddVisualGear(RightX, Y - 3 + Random(7), vgtDroplet) + else + particle := AddVisualGear(LeftX, Y - 3 + Random(7), vgtDroplet) + end + else + particle := AddVisualGear(X - 3 + Random(7), cWaterLine, vgtDroplet); + if particle <> nil then with particle^ do begin - dX := dX - vdX / 10; - dY := dY - vdY / 5; + // dX and dY were initialized to have a random value on creation (see uVisualGearsList) + if isImpactH then + begin + tmp:= dX; + if isImpactRight then + dX:= dY - vdX / 5 + else + dX:= -dy + vdX / 5; + dY:= tmp * (1 + vdY / 10); + end + else + begin + dX:= dX * (1 + vdX / 10); + dY:= dY - vdY / 5; + end; + if splash <> nil then begin if splash^.Scale > 1 then @@ -482,7 +568,7 @@ dX:= dX * splash^.Scale; dY:= dY * splash^.Scale end - end + end; end end end; @@ -1250,7 +1336,7 @@ Trying to make the checks a little broader than on first pass to catch things that don't move normally. *) function WorldWrap(var Gear: PGear): boolean; -var tdx: hwFloat; +//var tdx: hwFloat; begin WorldWrap:= false; if WorldEdge = weNone then exit(false); @@ -1281,7 +1367,7 @@ end; if (Gear^.Radius > 2) and (Gear^.dX.QWordValue > _0_001.QWordValue) then PlaySound(sndMelonImpact) - end + end{ else if WorldEdge = weSea then begin if (hwRound(Gear^.Y) > cWaterLine) and (Gear^.State and gstSubmersible <> 0) then @@ -1296,7 +1382,7 @@ Gear^.dY:= tdx; Gear^.dY.isNegative:= true end - end; + end}; (* * Window in the sky (Gear moved high into the sky, Y is used to determine X) [unfortunately, not a safe thing to do. shame, I thought aerial bombardment would be kinda neat This one would be really easy to freeze game unless it was flagged unfortunately. diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uRender.pas --- a/hedgewars/uRender.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uRender.pas Sat Jul 05 22:54:58 2014 +0200 @@ -847,7 +847,6 @@ procedure DrawTextureRotatedF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real); var ft, fb, fl, fr: GLfloat; hw, hh, nx, ny: LongInt; - VertexBuffer, TextureBuffer: array [0..3] of TVertex2f; begin // note: not taking scale into account @@ -1520,7 +1519,6 @@ lw, nWaves, shift: GLfloat; sprite: TSprite; begin - // note: spriteHeight is the Height of the wave sprite while // cWaveHeight describes how many pixels of it will be above waterline diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uVisualGears.pas --- a/hedgewars/uVisualGears.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uVisualGears.pas Sat Jul 05 22:54:58 2014 +0200 @@ -205,11 +205,25 @@ else DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16); vgtSplash: if SuddenDeathDmg then + begin + if Gear^.Angle <> 0 then + begin + DrawTextureRotatedF(SpritesData[sprSDSplash].Texture, Gear^.scale, 0, 0, round(Gear^.X + WorldDx + (((SpritesData[sprSDSplash].Height+8)*Gear^.Scale)/2) * (Gear^.Angle / abs(Gear^.Angle))), round(Gear^.Y + WorldDy), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSDSplash].Width, SpritesData[sprSDSplash].Height, Gear^.Angle); + end + else //DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)) - DrawTextureF(SpritesData[sprSDSplash].Texture, Gear^.scale, round(Gear^.X + WorldDx), round(Gear^.Y + WorldDy - ((SpritesData[sprSDSplash].Height+8)*Gear^.Scale)/2), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSDSplash].Width, SpritesData[sprSDSplash].Height) + DrawTextureF(SpritesData[sprSDSplash].Texture, Gear^.scale, round(Gear^.X + WorldDx), round(Gear^.Y + WorldDy - ((SpritesData[sprSDSplash].Height+8)*Gear^.Scale)/2), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSDSplash].Width, SpritesData[sprSDSplash].Height); + end else + begin + if Gear^.Angle <> 0 then + begin + DrawTextureRotatedF(SpritesData[sprSplash].Texture, Gear^.scale, 0, 0, round(Gear^.X + WorldDx + (((SpritesData[sprSplash].Height+8)*Gear^.Scale)/2) * (Gear^.Angle / abs(Gear^.Angle))), round(Gear^.Y + WorldDy), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSplash].Width, SpritesData[sprSplash].Height, Gear^.Angle); + end + else //DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)); - DrawTextureF(SpritesData[sprSplash].Texture, Gear^.scale, round(Gear^.X + WorldDx), round(Gear^.Y + WorldDy - ((SpritesData[sprSplash].Height+8)*Gear^.Scale)/2), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSplash].Width, SpritesData[sprSplash].Height); + DrawTextureF(SpritesData[sprSplash].Texture, Gear^.scale, round(Gear^.X + WorldDx), round(Gear^.Y + WorldDy - ((SpritesData[sprSplash].Height+8)*Gear^.Scale)/2), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSplash].Width, SpritesData[sprSplash].Height); + end; vgtDroplet: if SuddenDeathDmg then DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame) else diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uVisualGearsHandlers.pas --- a/hedgewars/uVisualGearsHandlers.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uVisualGearsHandlers.pas Sat Jul 05 22:54:58 2014 +0200 @@ -75,7 +75,7 @@ procedure initModule; implementation -uses uVariables, Math, uConsts, uVisualGearsList, uFloat, uSound, uRenderUtils, uWorld; +uses uCollisions, uVariables, Math, uConsts, uVisualGearsList, uFloat, uSound, uRenderUtils, uWorld; procedure doStepFlake(Gear: PVisualGear; Steps: Longword); var sign: real; @@ -345,7 +345,7 @@ Gear^.dX := Gear^.dX / (1.001 * Steps); Gear^.dY := Gear^.dY / (1.001 * Steps); -if (Gear^.FrameTicks <= Steps) or (round(Gear^.Y) < cWaterLine) then +if (Gear^.FrameTicks <= Steps) or (not CheckCoordInWater(round(Gear^.X), round(Gear^.Y))) then DeleteVisualGear(Gear) else dec(Gear^.FrameTicks, Steps) @@ -354,7 +354,9 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepSteam(Gear: PVisualGear; Steps: Longword); begin -Gear^.X:= Gear^.X + (cWindSpeedf * 100 + Gear^.dX) * Steps; +if ((cWindSpeedf > 0) and ( leftX > Gear^.X)) +or ((cWindSpeedf < 0) and (rightX < Gear^.X)) then + Gear^.X:= Gear^.X + (cWindSpeedf * 100 + Gear^.dX) * Steps; Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; if Gear^.FrameTicks <= Steps then diff -r 25f325b48a6c -r 86a823dd1d23 hedgewars/uVisualGearsList.pas --- a/hedgewars/uVisualGearsList.pas Sun Jul 06 00:26:55 2014 +0400 +++ b/hedgewars/uVisualGearsList.pas Sat Jul 05 22:54:58 2014 +0200 @@ -36,12 +36,12 @@ VisualGearLayers: array[0..6] of PVisualGear; implementation -uses uFloat, uVariables, uConsts, uTextures, uVisualGearsHandlers; +uses uCollisions, uFloat, uVariables, uConsts, uTextures, uVisualGearsHandlers; function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline; begin // adjust some visual gear types if underwater - if (Y > cWaterLine) and ((Kind = vgtBeeTrace) or (Kind = vgtSmokeTrace) or (Kind = vgtEvilTrace)) then + if CheckCoordInWater(X, Y) and ((Kind = vgtBeeTrace) or (Kind = vgtSmokeTrace) or (Kind = vgtEvilTrace)) then Kind:= vgtBubble; AddVisualGear:= AddVisualGear(X, Y, Kind, 0, false, -1);