hedgewars/GSHandlers.inc
changeset 5594 3ab68a93434b
parent 5564 4f42009237df
child 5606 75916086afa3
equal deleted inserted replaced
5592:662ebb46642f 5594:3ab68a93434b
  3729 end;
  3729 end;
  3730 
  3730 
  3731 procedure doStepPortal(Gear: PGear);
  3731 procedure doStepPortal(Gear: PGear);
  3732 var 
  3732 var 
  3733     iterator, conPortal: PGear;
  3733     iterator, conPortal: PGear;
  3734     s, r, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed: hwFloat;
  3734     s, r, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed,
  3735     o_x,o_y,r_x,r_y,rr_x,rr_y: LongInt;
  3735     resetx, resety, resetdx, resetdy: hwFloat;
  3736     hasdxy, isbullet, iscake: Boolean;
  3736     sx, sy, rh, resetr: LongInt;
       
  3737     hasdxy, isbullet, iscake, isCollision: Boolean;
  3737 begin
  3738 begin
  3738     doPortalColorSwitch();
  3739     doPortalColorSwitch();
  3739 
  3740 
  3740     // destroy portal if ground it was attached too is gone
  3741     // destroy portal if ground it was attached too is gone
  3741     if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0)
  3742     if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0)
  3801         if (iterator^.X < Gear^.X - r)
  3802         if (iterator^.X < Gear^.X - r)
  3802            or (iterator^.X > Gear^.X + r)
  3803            or (iterator^.X > Gear^.X + r)
  3803            or (iterator^.Y < Gear^.Y - r)
  3804            or (iterator^.Y < Gear^.Y - r)
  3804            or (iterator^.Y > Gear^.Y + r) then
  3805            or (iterator^.Y > Gear^.Y + r) then
  3805             continue;
  3806             continue;
  3806 (*
       
  3807 Square check causes fail on many innocent cases. the 3/4s and 1.5 fudge factors... help.
       
  3808 Might still need to remove this section
       
  3809 *)
       
  3810         //Will if fit through?
       
  3811         //set r to be portal distance
       
  3812         r := Int2hwFloat(Gear^.Radius * 3 div 4);
       
  3813         o_x := hwRound(conPortal^.X + (conPortal^.dX*_1_5));
       
  3814         o_y := hwRound(conPortal^.Y + (conPortal^.dY*_1_5));
       
  3815         //r := Int2hwFloat(Gear^.Radius +1);
       
  3816 
       
  3817         //o_x := hwRound(conPortal^.X + conPortal^.dX);
       
  3818         //o_y := hwRound(conPortal^.Y + conPortal^.dY);
       
  3819         r_x := hwRound(conPortal^.X+r*conPortal^.dX);
       
  3820         r_y := hwRound(conPortal^.Y+r*conPortal^.dY);
       
  3821         rr_x := hwRound(conPortal^.X+r*conPortal^.dX*2);
       
  3822         rr_y := hwRound(conPortal^.Y+r*conPortal^.dY*2);
       
  3823 
       
  3824         //check outer edge
       
  3825         if (((rr_y and LAND_HEIGHT_MASK) <> 0) or ((rr_x and LAND_WIDTH_MASK) <> 0)) then
       
  3826             begin
       
  3827             if hasBorder then continue;
       
  3828             end
       
  3829         else
       
  3830             if ((Land[rr_y,rr_x] and $FF00) <> 0) then
       
  3831                 continue;
       
  3832         //check middle bound
       
  3833         if (((r_y and LAND_HEIGHT_MASK) <> 0) or ((r_x and LAND_WIDTH_MASK) <> 0)) then
       
  3834             begin
       
  3835             if hasBorder then continue;
       
  3836             end
       
  3837         else
       
  3838         if ((Land[r_y, r_x] and $FF00) <> 0) then
       
  3839                 continue;
       
  3840         //check inner bound
       
  3841         if (((o_y and LAND_HEIGHT_MASK) <> 0) or ((o_x and LAND_WIDTH_MASK) <> 0)) then
       
  3842             begin
       
  3843             if hasBorder then continue;
       
  3844             end
       
  3845         else
       
  3846         if ((Land[o_y, o_x] and $FF00) <> 0) then
       
  3847                 continue;
       
  3848         //check left bound
       
  3849         if (((rr_y and LAND_HEIGHT_MASK) <> 0) or ((o_x and LAND_WIDTH_MASK) <> 0)) then
       
  3850             begin
       
  3851             if hasBorder then continue;
       
  3852             end
       
  3853         else
       
  3854         if ((Land[rr_y, o_x] and $FF00) <> 0) then
       
  3855                 continue;
       
  3856         //Check Right Bound
       
  3857         if (((o_y and LAND_HEIGHT_MASK) <> 0) or ((rr_x and LAND_WIDTH_MASK) <> 0)) then
       
  3858             begin
       
  3859             if hasBorder then continue;
       
  3860             end
       
  3861         else
       
  3862         if ((Land[o_y, rr_x] and $FF00) <> 0) then
       
  3863                 continue;
       
  3864 
       
  3865         //Okay reset r in case something uses it
       
  3866         r := Int2hwFloat(iterator^.Radius+Gear^.Radius);
       
  3867 
  3807 
  3868         hasdxy := (((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0))
  3808         hasdxy := (((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0))
  3869                     or ((iterator^.State or gstMoving) = 0));
  3809                     or ((iterator^.State or gstMoving) = 0));
  3870 
  3810 
  3871         // in case the object is not moving, let's asume it's falling towards the portal
  3811         // in case the object is not moving, let's asume it's falling towards the portal
  3927             continue;
  3867             continue;
  3928 
  3868 
  3929         //
  3869         //
  3930         // gears that make it till here will definately be ported
  3870         // gears that make it till here will definately be ported
  3931         //
  3871         //
       
  3872         // (but old position/movement vector might be restored in case there's
       
  3873         // not enough space on the other side)
       
  3874         //
       
  3875 
       
  3876         resetr  := iterator^.Radius;
       
  3877         resetx  := iterator^.X;
       
  3878         resety  := iterator^.Y;
       
  3879         resetdx := iterator^.dX;
       
  3880         resetdy := iterator^.dY;
  3932 
  3881 
  3933         // create a normal of the portal vector, but ...
  3882         // create a normal of the portal vector, but ...
  3934         nx := Gear^.dY;
  3883         nx := Gear^.dY;
  3935         ny := Gear^.dX;
  3884         ny := Gear^.dX;
  3936         // ... decide where the top is based on the hog's direction when firing the portal
  3885         // ... decide where the top is based on the hog's direction when firing the portal
  3946         if not iscake and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative)
  3895         if not iscake and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative)
  3947             and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue)
  3896             and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue)
  3948             and (iterator^.PortalCounter > 0) then
  3897             and (iterator^.PortalCounter > 0) then
  3949              continue;
  3898              continue;
  3950 
  3899 
  3951         // Until loops are reliably broken
       
  3952         inc(iterator^.PortalCounter);
       
  3953 
       
  3954         // calc gear speed along to the vector and the normal vector of the portal
  3900         // calc gear speed along to the vector and the normal vector of the portal
  3955         if hasdxy then
  3901         if hasdxy then
  3956         begin
  3902         begin
  3957             pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY);
  3903             pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY);
  3958             nspeed:= (nx * iterator^.dX + ny * iterator^.dY);
  3904             nspeed:= (nx * iterator^.dX + ny * iterator^.dY);
  3986          // determine the distance (in exit vector direction)
  3932          // determine the distance (in exit vector direction)
  3987          // that we want the gear at
  3933          // that we want the gear at
  3988          if iscake then
  3934          if iscake then
  3989              ox:= (r - _0_7)
  3935              ox:= (r - _0_7)
  3990          else
  3936          else
  3991              ox:= (r + _1_9);
  3937              ox:= (r * _1_5);
  3992          s:= ox / poffs;
  3938          s:= ox / poffs;
  3993          poffs:= ox;
  3939          poffs:= ox;
  3994          if (nspeed.QWordValue <> 0) and (pspeed > _0) then
  3940          if (nspeed.QWordValue <> 0) and (pspeed > _0) then
  3995              noffs:= noffs * s * (nspeed / pspeed);
  3941              noffs:= noffs * s * (nspeed / pspeed);
  3996 
  3942 
  4008         if not hasdxy and not (conPortal^.dY.isNegative) then
  3954         if not hasdxy and not (conPortal^.dY.isNegative) then
  4009         begin
  3955         begin
  4010             iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y))
  3956             iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y))
  4011         end;
  3957         end;
  4012 
  3958 
       
  3959         // see if the space on the exit side actually is enough
       
  3960 
       
  3961         if not (isBullet or isCake) then
       
  3962         begin
       
  3963             // TestCollisionXwithXYShift requires a hwFloat for xShift
       
  3964             ox.QWordValue := _1.QWordValue;
       
  3965             ox.isNegative := not iterator^.dX.isNegative;
       
  3966 
       
  3967             sx := hwSign(iterator^.dX);
       
  3968             sy := hwSign(iterator^.dY);
       
  3969 
       
  3970             if iterator^.Radius > 1 then
       
  3971                 iterator^.Radius := iterator^.Radius - 1;
       
  3972 
       
  3973             // check front
       
  3974             isCollision := TestCollisionYwithGear(iterator, sy)
       
  3975                         or TestCollisionXwithGear(iterator, sx);
       
  3976 
       
  3977             if not isCollision then
       
  3978             begin
       
  3979                 // check center area (with half the radius so that the
       
  3980                 // the square check won't check more pixels than we want to)
       
  3981                 iterator^.Radius := 1 + resetr div 2;
       
  3982                 rh := resetr div 4;
       
  3983                 isCollision := TestCollisionYwithXYShift(iterator,       0, -sy * rh, sy)
       
  3984                             or TestCollisionXwithXYShift(iterator, ox * rh,        0, sx);
       
  3985             end;
       
  3986 
       
  3987             iterator^.Radius := resetr;
       
  3988 
       
  3989             if isCollision then
       
  3990             begin
       
  3991                 // collision! oh crap! go back!
       
  3992                 iterator^.X  := resetx;
       
  3993                 iterator^.Y  := resety;
       
  3994                 iterator^.dX := resetdx;
       
  3995                 iterator^.dY := resetdy;
       
  3996                 continue;
       
  3997             end;
       
  3998         end;
       
  3999 
       
  4000         //
       
  4001         // You're now officially portaled!
       
  4002         //
       
  4003 
       
  4004         // Until loops are reliably broken
       
  4005         inc(iterator^.PortalCounter);
       
  4006 
  4013         if not isbullet and (iterator^.Kind <> gtFlake) then
  4007         if not isbullet and (iterator^.Kind <> gtFlake) then
  4014             FollowGear := iterator;
  4008             FollowGear := iterator;
  4015 //AddFileLog('portal''d');
  4009 
  4016 
       
  4017 {
       
  4018         s := _0_2 + _0_008 * Gear^.Health;
       
  4019         iterator^.dX := s * iterator^.dX;
       
  4020         iterator^.dY := s * iterator^.dY;
       
  4021 }
       
  4022         // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
  4010         // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
  4023         iterator:= GearsList;
  4011         iterator:= GearsList;
  4024         while iterator <> nil do
  4012         while iterator <> nil do
  4025             begin
  4013             begin
  4026             if iterator^.Kind <> gtPortal then
  4014             if iterator^.Kind <> gtPortal then
  4033                 end;
  4021                 end;
  4034             iterator:= iterator^.NextGear
  4022             iterator:= iterator^.NextGear
  4035             end;
  4023             end;
  4036 
  4024 
  4037         if Gear^.Health > 1 then dec(Gear^.Health);
  4025         if Gear^.Health > 1 then dec(Gear^.Health);
  4038 
       
  4039 {        // breaks (some) loops
       
  4040         if Distance(iterator^.dX, iterator^.dY) > _0_96 then
       
  4041             begin
       
  4042             iterator^.dX := iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX);
       
  4043             iterator^.dY := iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY);
       
  4044             s := _0_96 / Distance(iterator^.dX, iterator^.dY);
       
  4045             iterator^.dX := s * iterator^.dX;
       
  4046             iterator^.dY := s * iterator^.dX;
       
  4047             end;
       
  4048 }
       
  4049     end;
  4026     end;
  4050 end;
  4027 end;
  4051 
  4028 
  4052 procedure doStepMovingPortal_real(Gear: PGear);
  4029 procedure doStepMovingPortal_real(Gear: PGear);
  4053 var 
  4030 var