hedgewars/GSHandlers.inc
changeset 3422 41ae3c48faa0
parent 3419 b66a1b597f88
child 3423 39e3c8f2e52a
equal deleted inserted replaced
3421:7c72f4d556d1 3422:41ae3c48faa0
  3040     end;
  3040     end;
  3041 end;
  3041 end;
  3042 
  3042 
  3043 ////////////////////////////////////////////////////////////////////////////////
  3043 ////////////////////////////////////////////////////////////////////////////////
  3044 procedure doStepPortal(Gear: PGear);
  3044 procedure doStepPortal(Gear: PGear);
  3045 var iterator: PGear;
  3045 var iterator, conPortal: PGear;
  3046     s: hwFloat;
  3046     s, acptRadius: hwFloat;
  3047 begin
  3047     noTrap, hasdxy: Boolean;
  3048     if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then
  3048 begin
  3049         begin
  3049     // destroy portal if ground it was attached too is gone
  3050         if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= nil;
  3050     if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then deleteGear(Gear);
  3051         DeleteGear(Gear);
  3051 
  3052         EXIT;
  3052     // abort if there is no other portal connected to this one
  3053         end;
  3053     if Gear^.IntersectGear = nil then
       
  3054         exit;
       
  3055 
       
  3056     conPortal:= Gear^.IntersectGear;
       
  3057 
       
  3058     // check all gears for stuff to port through
       
  3059     iterator:= nil;
       
  3060     while true do
       
  3061         begin
       
  3062 
       
  3063         if iterator = nil then
       
  3064             iterator:= GearsList // start
       
  3065         else
       
  3066             iterator:= iterator^.NextGear; // iterate through GearsList
  3054         
  3067         
  3055     if Gear^.IntersectGear <> nil then
  3068         if iterator = nil then
  3056     //if (Gear^.IntersectGear <> nil) then
  3069             break; // end of list
  3057         begin
  3070 
  3058         iterator:= GearsList;
  3071         // don't port portals or other gear that wouldn't make sense
  3059         while iterator <> nil do
  3072         if (iterator^.Kind = gtPortal)
       
  3073         or (iterator^.Kind = gtHealthTag) then
       
  3074             continue;
       
  3075 
       
  3076 {
       
  3077         if (((iterator^.State and gstMoving) = 0) // we don't port non-moving stuff IF the portal entry...
       
  3078             and (iterator^.Active = false)
       
  3079             and ) then //...
       
  3080                 continue;
       
  3081 }
       
  3082 
       
  3083         if (iterator^.Radius > Gear^.Radius) then
       
  3084             continue; // sorry, you're too fat!
       
  3085 
       
  3086         // this is the range we accept incoming gears in
       
  3087         acptRadius:= Int2hwFloat(iterator^.Radius+Gear^.Radius);
       
  3088 
       
  3089         if (iterator^.X < Gear^.X - acptRadius)
       
  3090         or (iterator^.X > Gear^.X + acptRadius)
       
  3091         or (iterator^.Y < Gear^.Y - acptRadius)
       
  3092         or (iterator^.Y > Gear^.Y + acptRadius) then
       
  3093             continue; // too far away!
       
  3094 
       
  3095         hasdxy:= ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0));
       
  3096 
       
  3097         if hasdxy and not (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then
       
  3098             continue; // won't port stuff that moves away from me!
       
  3099 
       
  3100         // wow! good candidate there, let's see if the distance really is small enough!
       
  3101         if (Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y) > acptRadius) then
       
  3102             continue;
       
  3103 
       
  3104         noTrap:= ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) // can't be entered from above
       
  3105             or ((conPortal^.dY.isNegative or (conPortal^.dY.QWordValue = 0)))); // can't be left downwards;
       
  3106  
       
  3107  
       
  3108         // lets see if this one is just stuck in a stuck-loop       
       
  3109         if noTrap and (iterator^.dY.QWordValue < _0_1.QWordValue) then
       
  3110             continue;
       
  3111         
       
  3112         iterator^.Active:= true;
       
  3113         iterator^.State:= iterator^.State or gstMoving;
       
  3114         DeleteCI(iterator);
       
  3115 
       
  3116         s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(conPortal^.dX, conPortal^.dY);
       
  3117         iterator^.X:= conPortal^.X + s * conPortal^.dX;
       
  3118         iterator^.Y:= conPortal^.Y + s * conPortal^.dY;
       
  3119         s:= Distance(iterator^.dX, iterator^.dY) / Distance(conPortal^.dX, conPortal^.dY);
       
  3120         iterator^.dX:= s * conPortal^.dX;
       
  3121         iterator^.dY:= s * conPortal^.dY;
       
  3122         
       
  3123         if iterator^.dY.isNegative and (iterator^.dY.QWordValue <> 0) then
       
  3124             iterator^.dY:= iterator^.dY + hwAbs(Int2hwFloat(iterator^.Radius) / iterator^.dY) * cGravity;
       
  3125 
       
  3126         // breaks (some) loops
       
  3127         if Distance(iterator^.dX, iterator^.dY) > _0_96 then
  3060             begin
  3128             begin
  3061             if (iterator^.Kind <> gtPortal) and (iterator^.PortedCounter < 20) then
  3129             iterator^.dX:= iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX);
  3062                 if (((iterator^.State and gstMoving) <> 0) or (Gear^.IntersectGear^.dY.isNegative and not Gear^.dY.isNegative))
  3130             iterator^.dY:= iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY);
  3063                     and (hwRound(Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y)) < iterator^.Radius+Gear^.Radius) then // Let's check this one more closely
  3131             s:= _0_995 / Distance(iterator^.dX, iterator^.dY);
  3064                         if (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then // make sure object moves towards the portal
  3132             iterator^.dX:= s * iterator^.dX;
  3065                             begin
  3133             iterator^.dY:= s * iterator^.dX;
  3066                             inc(iterator^.PortedCounter);
       
  3067                             s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(Gear^.IntersectGear^.dX, Gear^.IntersectGear^.dY);
       
  3068                             iterator^.X:= Gear^.IntersectGear^.X + s * Gear^.IntersectGear^.dX;
       
  3069                             iterator^.Y:= Gear^.IntersectGear^.Y + s * Gear^.IntersectGear^.dY;
       
  3070                             s:= Distance(iterator^.dX, iterator^.dY) / Distance(Gear^.IntersectGear^.dX, Gear^.IntersectGear^.dY);
       
  3071                             iterator^.dX:= s * Gear^.IntersectGear^.dX;
       
  3072                             iterator^.dY:= s * Gear^.IntersectGear^.dY;
       
  3073                             end;    
       
  3074 
       
  3075             iterator:= iterator^.NextGear;
       
  3076             end;
  3134             end;
  3077 // do portal stuff
  3135 
  3078         end
  3136         iterator:= iterator^.NextGear;
       
  3137         end;
  3079 
  3138 
  3080 (*
  3139 (*
  3081 
  3140 
  3082 2) From then on, if doStepPortal is called and a gear of a radius less than or equal to the portal is within X pixels of the portal (we could also check on moving toward the portal I guess, depends how accurate this needs to be) the portal will then locate the first other portal of the opposite type (there should only be one other one), and move that gear's X/Y to that other portal's location, and modify dX/dY to be relative to that other portal's orientation relative to this portal's orientation.  This might require some tweaking with offsets of a few pixels to avoid getting gears stuck in land.
  3141 2) From then on, if doStepPortal is called and a gear of a radius less than or equal to the portal is within X pixels of the portal (we could also check on moving toward the portal I guess, depends how accurate this needs to be) the portal will then locate the first other portal of the opposite type (there should only be one other one), and move that gear's X/Y to that other portal's location, and modify dX/dY to be relative to that other portal's orientation relative to this portal's orientation.  This might require some tweaking with offsets of a few pixels to avoid getting gears stuck in land.
  3083 
  3142 
  3084 *)
  3143 *)
  3085 end;
  3144 end;
  3086 
  3145 
  3087 procedure doStepMovingPortal(Gear: PGear);
  3146 procedure doStepMovingPortal(Gear: PGear);
  3088 var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt;
  3147 var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt;
  3089     iterator: PGear;
       
  3090     s, dx, dy: hwFloat;
  3148     s, dx, dy: hwFloat;
  3091 begin
  3149 begin
  3092 Gear^.X:= Gear^.X + Gear^.dX;
  3150 Gear^.X:= Gear^.X + Gear^.dX;
  3093 Gear^.Y:= Gear^.Y + Gear^.dY;
  3151 Gear^.Y:= Gear^.Y + Gear^.dY;
  3094 x:= hwRound(Gear^.X);
  3152 x:= hwRound(Gear^.X);
  3097 
  3155 
  3098 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then
  3156 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then
  3099     begin
  3157     begin
  3100     if not calcSlopeTangent(Gear, x, y, tx, ty, 255) then
  3158     if not calcSlopeTangent(Gear, x, y, tx, ty, 255) then
  3101         begin
  3159         begin
  3102         DeleteGear(Gear);
  3160         deleteGear(Gear);
  3103         EXIT;
  3161         EXIT;
  3104         end;
  3162         end;
  3105 
  3163 
  3106     // reject shots at too irregular terrain
  3164     // reject shots at too irregular terrain
  3107     if DistanceI(tx,ty) < _10 then
  3165     if DistanceI(tx,ty) < _12 then
  3108         begin
  3166         begin
  3109         DeleteGear(Gear);
  3167         deleteGear(Gear);
  3110         EXIT;
  3168         EXIT;
  3111     end;
  3169     end;
  3112     
  3170     
  3113     // making a normal, normalized vector
  3171     // making a normal, normalized vector
  3114     s:= _1/DistanceI(tx,ty);
  3172     s:= _1/DistanceI(tx,ty);
  3149         begin
  3207         begin
  3150         if CurrentHedgehog <> nil then
  3208         if CurrentHedgehog <> nil then
  3151             if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
  3209             if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
  3152             else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2
  3210             else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2
  3153             else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1;
  3211             else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1;
  3154         DeleteGear(Gear)
  3212         deleteGear(Gear)
  3155         end
  3213         end
  3156     else
  3214     else
  3157         begin
  3215         begin
  3158         if CurrentHedgehog <> nil then
  3216         if CurrentHedgehog <> nil then
  3159             if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
  3217             if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
  3160             else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2;
  3218             else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2;
  3161         inc(Gear^.Tag);
  3219         inc(Gear^.Tag);
  3162         Gear^.doStep:= @doStepPortal;
  3220         Gear^.doStep:= @doStepPortal;
  3163         if Gear^.IntersectGear <> nil then
  3221         if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= Gear;
  3164             begin
       
  3165             Gear^.IntersectGear^.IntersectGear:= Gear;
       
  3166             AllInactive:= false;
       
  3167             // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
       
  3168             iterator:= GearsList;
       
  3169             while iterator <> nil do
       
  3170                 begin
       
  3171                 if iterator^.Kind <> gtPortal then
       
  3172                     begin
       
  3173                     iterator^.Active:= true;
       
  3174                     if iterator^.dY.QWordValue = _0.QWordValue then iterator^.dY.isNegative:= false;
       
  3175                     iterator^.State:= iterator^.State or gstMoving;
       
  3176                     DeleteCI(iterator);
       
  3177                     inc(iterator^.dY.QWordValue,10);
       
  3178                     end;
       
  3179                 iterator:= iterator^.NextGear
       
  3180                 end;
       
  3181             doStepPortal(Gear);
       
  3182             if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.doStep(Gear^.IntersectGear);
       
  3183             end
       
  3184         end
  3222         end
  3185     end
  3223     end
  3186 else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then
  3224 else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then
  3187     begin
  3225     begin
  3188     if CurrentHedgehog <> nil then
  3226     if CurrentHedgehog <> nil then
  3189         if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
  3227         if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
  3190         else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2
  3228         else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2
  3191         else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1;
  3229         else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1;
  3192     DeleteGear(Gear);
  3230     deleteGear(Gear);
  3193     end;
  3231     end;
  3194 end;
  3232 end;
  3195 
  3233 
  3196 procedure doStepPiano(Gear: PGear);
  3234 procedure doStepPiano(Gear: PGear);
  3197 var r0, r1: LongInt;
  3235 var r0, r1: LongInt;