231 procedure doStepDrowningGear(Gear: PGear); |
231 procedure doStepDrowningGear(Gear: PGear); |
232 begin |
232 begin |
233 AllInactive := false; |
233 AllInactive := false; |
234 Gear^.Y := Gear^.Y + cDrownSpeed; |
234 Gear^.Y := Gear^.Y + cDrownSpeed; |
235 Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed; |
235 Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed; |
236 if (cWaterOpacity > $FE) or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then |
236 if (not SuddenDeathDmg and (cWaterOpacity > $FE)) or (SuddenDeathDmg and (cSDWaterOpacity > $FE)) or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then |
237 DeleteGear(Gear); |
237 DeleteGear(Gear); |
238 // Create some bubbles (0.5% might be better but causes too few bubbles sometimes) |
238 // Create some bubbles (0.5% might be better but causes too few bubbles sometimes) |
239 if (cWaterOpacity < $FF) and ((GameTicks and $1F) = 0) then |
239 if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then |
240 if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then |
240 if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then |
241 AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, |
241 AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, |
242 vgtBubble) |
242 vgtBubble) |
243 else if Random(12) = 0 then |
243 else if Random(12) = 0 then |
244 AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, |
244 AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, |
588 end; |
589 end; |
589 |
590 |
590 move:= false; |
591 move:= false; |
591 // move back to cloud layer |
592 // move back to cloud layer |
592 if yy > cWaterLine then move:= true |
593 if yy > cWaterLine then move:= true |
593 else if ((yy and LAND_HEIGHT_MASK) = 0) and ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] > 255) then |
594 else if ((yy and LAND_HEIGHT_MASK) <> 0) or ((xx and LAND_WIDTH_MASK) <> 0) then move:=true |
594 begin |
595 // Solid pixel encountered |
595 // we've collided with land. draw some stuff and get back into the clouds |
596 else if (Land[yy, xx] > 255) then |
596 move:= true; |
597 begin |
597 if (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtRope) then |
598 // If there's room below keep falling |
|
599 if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (Land[yy-1, xx] = 0) then |
598 begin |
600 begin |
599 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS //////////////////////////////////// |
601 X:= X - cWindSpeed * 1600 - dX; |
600 if cWindSpeed * 1600 + dX < _0 then i:= -1 |
602 end |
601 else i:= 1; |
603 // If there's room below, on the sides, fill the gaps |
602 if (yy > 0) and ((Land[yy-1, xx] and $FF00) = 0) then dec(yy) |
604 else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx-(1*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx-(1*hwSign(cWindSpeed)))] = 0) then |
603 else dec(xx, i); |
605 begin |
604 dec(yy,2); |
606 X:= X - _0_8 * hwSign(cWindSpeed); |
605 dec(xx,i); |
607 Y:= Y - dY - cGravity * vobFallSpeed * 8; |
606 s:= SpritesData[sprSnow].Surface; |
608 end |
607 p:= s^.pixels; |
609 else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx-(2*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx-(2*hwSign(cWindSpeed)))] = 0) then |
608 allpx:= true; |
610 begin |
609 for py:= 0 to Pred(s^.h) do |
611 X:= X - _0_8 * 2 * hwSign(cWindSpeed); |
|
612 Y:= Y - dY - cGravity * vobFallSpeed * 8; |
|
613 end |
|
614 else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx+(1*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx+(1*hwSign(cWindSpeed)))] = 0) then |
|
615 begin |
|
616 X:= X + _0_8 * hwSign(cWindSpeed); |
|
617 Y:= Y - dY - cGravity * vobFallSpeed * 8; |
|
618 end |
|
619 else if (((yy-1) and LAND_HEIGHT_MASK) = 0) and (((xx+(2*hwSign(cWindSpeed))) and LAND_WIDTH_MASK) = 0) and (Land[yy-1, (xx+(2*hwSign(cWindSpeed)))] = 0) then |
|
620 begin |
|
621 X:= X + _0_8 * 2 * hwSign(cWindSpeed); |
|
622 Y:= Y - dY - cGravity * vobFallSpeed * 8; |
|
623 end |
|
624 else |
|
625 begin |
|
626 // we've collided with land. draw some stuff and get back into the clouds |
|
627 move:= true; |
|
628 if (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtRope) then |
610 begin |
629 begin |
611 for px:= 0 to Pred(s^.w) do |
630 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS //////////////////////////////////// |
612 if (((yy + py) and LAND_HEIGHT_MASK) = 0) and (((xx + px) and LAND_WIDTH_MASK) = 0) and |
631 dec(yy,3); |
613 ((Land[yy + py, xx + px] and $FF00) = 0) then |
632 dec(xx,2); |
|
633 s:= SpritesData[sprSnow].Surface; |
|
634 p:= s^.pixels; |
|
635 allpx:= true; |
|
636 for py:= 0 to Pred(s^.h) do |
|
637 begin |
|
638 for px:= 0 to Pred(s^.w) do |
|
639 if (((yy + py) and LAND_HEIGHT_MASK) = 0) and (((xx + px) and LAND_WIDTH_MASK) = 0) then |
|
640 begin |
|
641 if (cReducedQuality and rqBlurryLand) = 0 then |
|
642 begin |
|
643 LandPixels[yy + py, xx + px]:= addBgColor(LandPixels[yy + py, xx + px], p^[px]); |
|
644 Land[yy + py, xx + px]:= Land[yy + py, xx + px] or lfObject; |
|
645 end |
|
646 else |
|
647 begin |
|
648 LandPixels[(yy + py) div 2, (xx + px) div 2]:= addBgColor(LandPixels[(yy + py) div 2, (xx + px) div 2], p^[px]); |
|
649 Land[(yy + py) div 2, (xx + px) div 2]:= Land[(yy + py) div 2, (xx + px) div 2] or lfObject; |
|
650 end; |
|
651 end |
|
652 else allpx:= false; |
|
653 p:= @(p^[s^.pitch shr 2]) |
|
654 end; |
|
655 |
|
656 for py:= (yy) to (yy+1) do |
|
657 begin |
|
658 for px:= (xx+2) to (xx+3) do |
614 begin |
659 begin |
615 if (cReducedQuality and rqBlurryLand) = 0 then |
660 Land[py, px]:= lfBasic; |
616 LandPixels[yy + py, xx + px]:= p^[px] |
661 end; |
617 else |
662 end; |
618 LandPixels[(yy + py) div 2, (xx + px) div 2]:= p^[px] |
663 |
619 end |
664 if allpx then UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w)) |
620 else allpx:= false; |
665 else |
621 p:= @(p^[s^.pitch shr 2]) |
666 begin |
622 end; |
667 UpdateLandTexture( |
623 if allpx then UpdateLandTexture(xx, 4, yy, 4) |
668 max(0, min(LAND_WIDTH, xx)), |
624 else if ((yy and LAND_HEIGHT_MASK) = 0) and ((xx and LAND_WIDTH_MASK) = 0) then UpdateLandTexture(xx, 1, yy, 1); |
669 min(LAND_WIDTH - xx, Pred(s^.w)), |
625 inc(yy,2); |
670 max(0, min(LAND_WIDTH, yy)), |
626 inc(xx,i); |
671 min(LAND_HEIGHT - yy, Pred(s^.h)) |
627 if ((xx and LAND_WIDTH_MASK) = 0) and ((yy and LAND_HEIGHT_MASK) = 0) then Land[yy, xx]:= Land[yy, xx] or lfObject; |
672 ); |
628 if yy > 0 then |
673 end; |
629 begin |
674 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS //////////////////////////////////// |
630 Land[yy-1, xx]:= Land[yy-1, xx] or lfObject; |
675 end |
631 if ((xx-i and LAND_WIDTH_MASK) = 0) then Land[yy-1, xx-i]:= Land[yy-1, xx-i] or lfObject; |
676 end; |
632 end; |
|
633 if ((xx-i and LAND_WIDTH_MASK) = 0) and ((yy and LAND_HEIGHT_MASK) = 0) then Land[yy, xx-i]:= Land[yy, xx-i] or lfObject |
|
634 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS //////////////////////////////////// |
|
635 end |
|
636 end; |
677 end; |
637 if move then |
678 if move then |
638 begin |
679 begin |
639 X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512); |
680 X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512); |
640 Y:= int2hwFloat(750+(GetRandom(50)-25)) |
681 Y:= int2hwFloat(750+(GetRandom(50)-25)) |
849 begin |
890 begin |
850 DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1); |
891 DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1); |
851 dec(Gear^.Health, Gear^.Damage); |
892 dec(Gear^.Health, Gear^.Damage); |
852 Gear^.Damage := 0 |
893 Gear^.Damage := 0 |
853 end; |
894 end; |
854 if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and (cWaterOpacity < $FF) then |
895 if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) then |
855 begin |
896 begin |
856 for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do |
897 for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do |
857 begin |
898 begin |
858 if Random(6) = 0 then |
899 if Random(6) = 0 then |
859 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); |
900 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); |
2204 isCursorVisible := false; |
2245 isCursorVisible := false; |
2205 ApplyAmmoChanges(HHGear^.Hedgehog^); |
2246 ApplyAmmoChanges(HHGear^.Hedgehog^); |
2206 exit |
2247 exit |
2207 end; |
2248 end; |
2208 |
2249 |
2209 if not TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then |
2250 HHGear^.X := HHGear^.X + cWindSpeed * 200; |
2210 HHGear^.X := HHGear^.X + cWindSpeed * 200; |
|
2211 |
2251 |
2212 if (Gear^.Message and gmLeft) <> 0 then HHGear^.X := HHGear^.X - cMaxWindSpeed * 80 |
2252 if (Gear^.Message and gmLeft) <> 0 then HHGear^.X := HHGear^.X - cMaxWindSpeed * 80 |
2213 else if (Gear^.Message and gmRight) <> 0 then HHGear^.X := HHGear^.X + cMaxWindSpeed * 80; |
2253 else if (Gear^.Message and gmRight) <> 0 then HHGear^.X := HHGear^.X + cMaxWindSpeed * 80; |
2214 if (Gear^.Message and gmUp) <> 0 then HHGear^.Y := HHGear^.Y - cGravity * 40 |
2254 if (Gear^.Message and gmUp) <> 0 then HHGear^.Y := HHGear^.Y - cGravity * 40 |
2215 else if (Gear^.Message and gmDown) <> 0 then HHGear^.Y := HHGear^.Y + cGravity * 40; |
2255 else if (Gear^.Message and gmDown) <> 0 then HHGear^.Y := HHGear^.Y + cGravity * 40; |
2216 |
2256 |
|
2257 // don't drift into obstacles |
|
2258 if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then |
|
2259 HHGear^.X := HHGear^.X - int2hwFloat(hwSign(HHGear^.dX)); |
2217 HHGear^.Y := HHGear^.Y + cGravity * 100; |
2260 HHGear^.Y := HHGear^.Y + cGravity * 100; |
2218 Gear^.X := HHGear^.X; |
2261 Gear^.X := HHGear^.X; |
2219 Gear^.Y := HHGear^.Y |
2262 Gear^.Y := HHGear^.Y |
2220 end; |
2263 end; |
2221 |
2264 |
2911 t := CheckGearsCollision(Gear); |
2961 t := CheckGearsCollision(Gear); |
2912 //fixes drill not exploding when touching HH bug |
2962 //fixes drill not exploding when touching HH bug |
2913 if (Gear^.Timer = 0) |
2963 if (Gear^.Timer = 0) |
2914 or (t^.Count <> 0) |
2964 or (t^.Count <> 0) |
2915 or (not TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) |
2965 or (not TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) |
2916 and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))) |
2966 and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) |
|
2967 and ((Gear^.State and gsttmpFlag) = 0)) |
2917 // CheckLandValue returns true if the type isn't matched |
2968 // CheckLandValue returns true if the type isn't matched |
2918 or not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible) then |
2969 or not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible) then |
2919 begin |
2970 begin |
2920 //out of time or exited ground |
2971 //out of time or exited ground |
2921 StopSound(Gear^.SoundChannel); |
2972 StopSound(Gear^.SoundChannel); |
2922 if (Gear^.State and gsttmpFlag) <> 0 then |
2973 if (Gear^.State and gsttmpFlag) <> 0 then |
2923 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound) |
2974 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound) |
2924 else |
2975 else |
2925 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound); |
2976 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound); |
2926 DeleteGear(Gear); |
2977 DeleteGear(Gear); |
2927 exit |
2978 exit |
2928 end; |
2979 end |
|
2980 else if not TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) then |
|
2981 begin |
|
2982 StopSound(Gear^.SoundChannel); |
|
2983 Gear^.doStep := @doStepDrill |
|
2984 end; |
2929 |
2985 |
2930 dec(Gear^.Timer); |
2986 dec(Gear^.Timer); |
2931 end; |
2987 end; |
2932 |
2988 |
2933 procedure doStepDrill(Gear: PGear); |
2989 procedure doStepDrill(Gear: PGear); |
3547 end; |
3603 end; |
3548 end; |
3604 end; |
3549 |
3605 |
3550 //////////////////////////////////////////////////////////////////////////////// |
3606 //////////////////////////////////////////////////////////////////////////////// |
3551 procedure doPortalColorSwitch(); |
3607 procedure doPortalColorSwitch(); |
3552 var flags: LongWord; |
3608 var CurWeapon: PAmmo; |
3553 CurWeapon: PAmmo; |
|
3554 begin |
3609 begin |
3555 if (CurrentHedgehog <> nil) |
3610 if (CurrentHedgehog <> nil) |
3556 and (CurrentHedgehog^.Gear <> nil) |
3611 and (CurrentHedgehog^.Gear <> nil) |
3557 and ((CurrentHedgehog^.Gear^.Message and gmSwitch) <> 0) then |
3612 and ((CurrentHedgehog^.Gear^.Message and gmSwitch) <> 0) then |
3558 With CurrentHedgehog^ do |
3613 With CurrentHedgehog^ do |
3559 if (CurAmmoType = amPortalGun) then |
3614 if (CurAmmoType = amPortalGun) then |
3560 begin |
3615 begin |
3561 CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and not gmSwitch; |
3616 CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and not gmSwitch; |
3562 |
3617 |
3563 CurWeapon:= GetAmmoEntry(CurrentHedgehog^); |
3618 CurWeapon:= GetAmmoEntry(CurrentHedgehog^); |
3564 flags := CurWeapon^.Timer and not 2; |
3619 if CurWeapon^.Pos <> 0 then |
3565 if (flags and 1) = 0 then |
3620 CurWeapon^.Pos := 0 |
3566 CurWeapon^.Timer := flags or 1 |
|
3567 else |
3621 else |
3568 CurWeapon^.Timer := flags and not 1; |
3622 CurWeapon^.Pos := 1; |
3569 end; |
3623 end; |
3570 end; |
3624 end; |
3571 |
3625 |
3572 procedure doStepPortal(Gear: PGear); |
3626 procedure doStepPortal(Gear: PGear); |
3573 var |
3627 var |
3832 var |
3886 var |
3833 x, y, tx, ty: LongInt; |
3887 x, y, tx, ty: LongInt; |
3834 s: hwFloat; |
3888 s: hwFloat; |
3835 |
3889 |
3836 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); |
3890 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); |
3837 var |
3891 var |
3838 flags: LongWord; |
|
3839 CurWeapon: PAmmo; |
3892 CurWeapon: PAmmo; |
3840 begin |
3893 begin |
3841 if CurrentHedgehog <> nil then |
3894 if CurrentHedgehog <> nil then |
3842 with CurrentHedgehog^ do |
3895 with CurrentHedgehog^ do |
3843 begin |
3896 begin |
3844 CurWeapon:= GetAmmoEntry(CurrentHedgehog^); |
3897 CurWeapon:= GetAmmoEntry(CurrentHedgehog^); |
3845 if (CurAmmoType = amPortalGun) then |
3898 if (CurAmmoType = amPortalGun) then |
3846 begin |
3899 begin |
3847 flags := CurWeapon^.Timer; |
3900 if not destroyGear then |
3848 |
3901 begin |
3849 if destroyGear xor ((oldPortal^.Tag and 2) = 0) then |
3902 // switch color of ball to opposite of oldPortal |
3850 flags := flags or 1 |
3903 if (oldPortal^.Tag and 2) = 0 then |
3851 else |
3904 CurWeapon^.Pos:= 1 |
3852 flags := flags and not 1; |
3905 else |
3853 |
3906 CurWeapon^.Pos:= 0; |
3854 CurWeapon^.Timer := flags and not 2; |
3907 end; |
|
3908 |
3855 // make the ball visible |
3909 // make the ball visible |
|
3910 CurWeapon^.Timer := 0; |
3856 end |
3911 end |
3857 end; |
3912 end; |
3858 |
|
3859 if destroyGear then oldPortal^.Timer:= 0; |
3913 if destroyGear then oldPortal^.Timer:= 0; |
3860 end; |
3914 end; |
3861 |
3915 |
3862 begin |
3916 begin |
3863 x := hwRound(Gear^.X); |
3917 x := hwRound(Gear^.X); |
3938 // when doing a backjump the dx is the opposite of the facing direction |
3992 // when doing a backjump the dx is the opposite of the facing direction |
3939 if ((Gear^.State and gstHHHJump) <> 0) and not cArtillery then |
3993 if ((Gear^.State and gstHHHJump) <> 0) and not cArtillery then |
3940 newPortal^.Elasticity.isNegative := not newPortal^.Elasticity.isNegative; |
3994 newPortal^.Elasticity.isNegative := not newPortal^.Elasticity.isNegative; |
3941 |
3995 |
3942 // make portal gun look unloaded |
3996 // make portal gun look unloaded |
3943 CurWeapon^.Timer := CurWeapon^.Timer or 2; |
3997 if (CurWeapon <> nil) and (CurAmmoType = amPortalGun) then |
3944 |
3998 CurWeapon^.Timer := CurWeapon^.Timer or 2; |
3945 // set portal to the currently chosen color |
|
3946 if ((CurWeapon^.Timer and 1) <> 0) then |
|
3947 newPortal^.Tag := newPortal^.Tag or 2; |
|
3948 |
3999 |
3949 iterator := GearsList; |
4000 iterator := GearsList; |
3950 while iterator <> nil do |
4001 while iterator <> nil do |
3951 begin |
4002 begin |
3952 if (iterator^.Kind = gtPortal) then |
4003 if (iterator^.Kind = gtPortal) then |