diff -r 00a3e2452e79 -r ef0a76e154cb hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Sat Sep 10 11:40:37 2011 -0400 +++ b/hedgewars/GSHandlers.inc Sun Sep 11 00:36:47 2011 +0200 @@ -959,6 +959,44 @@ end; //////////////////////////////////////////////////////////////////////////////// +procedure spawnBulletTrail(Bullet: PGear); +var oX, oY: hwFloat; + VGear: PVisualGear; +begin + if Bullet^.PortalCounter = 0 then + begin + ox:= CurrentHedgehog^.Gear^.X + Int2hwFloat(GetLaunchX(CurrentHedgehog^.CurAmmoType, hwSign(CurrentHedgehog^.Gear^.dX), CurrentHedgehog^.Gear^.Angle)); + oy:= CurrentHedgehog^.Gear^.Y + Int2hwFloat(GetLaunchY(CurrentHedgehog^.CurAmmoType, CurrentHedgehog^.Gear^.Angle)); + end + else + begin + ox:= Bullet^.Elasticity; + oy:= Bullet^.Friction; + end; + + // Bullet trail + VGear := AddVisualGear(hwRound(ox), hwRound(oy), vgtLineTrail); + if VGear <> nil then + begin + VGear^.X:= hwFloat2Float(ox); + VGear^.Y:= hwFloat2Float(oy); + VGear^.dX:= hwFloat2Float(Bullet^.X); + VGear^.dY:= hwFloat2Float(Bullet^.Y); + + // reached edge of land. assume infinite beam. Extend it way out past camera + 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 + begin + VGear^.dX := VGear^.dX + LAND_WIDTH * (VGear^.dX - VGear^.X); + VGear^.dY := VGear^.dY + LAND_WIDTH * (VGear^.dY - VGear^.Y); + end; + + VGear^.Timer := 200; + end; +end; + procedure doStepBulletWork(Gear: PGear); var i, x, y: LongWord; @@ -977,6 +1015,19 @@ y := hwRound(Gear^.Y); if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then inc(Gear^.Damage); + // let's interrupt before a collision to give portals a chance to catch the bullet + if (Gear^.Damage = 1) and (Gear^.Tag = 0) and (Land[y, x] > 255) then + begin + Gear^.Tag := 1; + Gear^.Damage := 0; + Gear^.X := Gear^.X - Gear^.dX; + Gear^.Y := Gear^.Y - Gear^.dY; + CheckGearDrowning(Gear); + break; + end + else + Gear^.Tag := 0; + if Gear^.Damage > 5 then if Gear^.AmmoType = amDEagle then AmmoShove(Gear, 7, 20) @@ -1022,36 +1073,7 @@ end; end; - if Gear^.PortalCounter = 0 then - begin - // Bullet trail - VGear := AddVisualGear( - hwround(CurrentHedgehog^.Gear^.X) + GetLaunchX(CurrentHedgehog^.CurAmmoType, hwSign(CurrentHedgehog^.Gear^.dX), CurrentHedgehog^.Gear^.Angle), - hwround(CurrentHedgehog^.Gear^.Y) + GetLaunchY(CurrentHedgehog^.CurAmmoType, CurrentHedgehog^.Gear^.Angle), - vgtLineTrail - ); - if VGear <> nil then - begin - // http://mantis.freepascal.org/view.php?id=17714 hits again - VGear^.dX := Gear^.X.QWordValue / SignAs(_1,_1).QWordValue; - VGear^.dY := Gear^.Y.QWordValue / SignAs(_1,_1).QWordValue; - - if (Gear^.X.isNegative) then VGear^.dX:= -VGear^.dX; - if (Gear^.Y.isNegative) then VGear^.dY:= -VGear^.dY; - - // reached edge of land. assume infinite beam. Extend it way out past camera - if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) - or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then - // only extend if not under water - if hwRound(Gear^.Y) < cWaterLine then - begin - VGear^.dX := VGear^.dX + LAND_WIDTH * (VGear^.dX - VGear^.X); - VGear^.dY := VGear^.dY + LAND_WIDTH * (VGear^.dY - VGear^.Y); - end; - - VGear^.Timer := 200; - end - end; + spawnBulletTrail(Gear); Gear^.doStep := @doStepShotIdle end; end; @@ -3931,12 +3953,20 @@ continue; end; + // draw bullet trail + if isbullet then + spawnBulletTrail(iterator); + // calc gear offset in portal vector direction ox := (iterator^.X - Gear^.X); oy := (iterator^.Y - Gear^.Y); poffs:= (Gear^.dX * ox + Gear^.dY * oy); - if poffs < _0 then + if not isBullet and poffs.isNegative then + continue; + + // only port bullets close to the portal + if isBullet and not (hwAbs(poffs) < _3) then continue; // @@ -3964,8 +3994,11 @@ // calc gear offset in portal normal vector direction noffs:= (nx * ox + ny * oy); + if isBullet and (hwRound(hwAbs(noffs)) >= Gear^.Radius) then + continue; + // avoid gravity related loops of not really moving gear - if not iscake and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative) + if not (iscake or isbullet) and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative) and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue) and (iterator^.PortalCounter > 0) then continue; @@ -4080,6 +4113,13 @@ if not isbullet and (iterator^.Kind <> gtFlake) then FollowGear := iterator; + // store X/Y values of exit for net bullet trail + if isbullet then + begin + iterator^.Elasticity:= iterator^.X; + iterator^.Friction := iterator^.Y; + end; + // This jiggles gears, to ensure a portal connection just placed under a gear takes effect. iterator:= GearsList; while iterator <> nil do