hedgewars/GSHandlers.inc
changeset 7439 0a494f951dcf
parent 7426 55b49cc1f33a
child 7468 1333ca7554dc
equal deleted inserted replaced
7358:57a508884052 7439:0a494f951dcf
   114     if FollowGear = HH^.Gear then
   114     if FollowGear = HH^.Gear then
   115         FollowGear:= nil;
   115         FollowGear:= nil;
   116         
   116         
   117     if lastGearByUID = HH^.Gear then
   117     if lastGearByUID = HH^.Gear then
   118         lastGearByUID := nil;
   118         lastGearByUID := nil;
   119         
   119     
   120     RemoveGearFromList(HH^.Gear);
   120     HH^.Gear^.Message:= HH^.Gear^.Message or gmRemoveFromList;
   121     with HH^.Gear^ do
   121     with HH^.Gear^ do
   122         begin
   122         begin
   123         Z := cHHZ;
   123         Z := cHHZ;
   124         Active := false;
   124         HH^.Gear^.Active:= false;
   125         State:= State and (not (gstHHDriven or gstAttacking or gstAttacked));
   125         State:= State and (not (gstHHDriven or gstAttacking or gstAttacked));
   126         Message := Message and (not gmAttack);
   126         Message := Message and (not gmAttack);
   127     end;
   127     end;
   128     HH^.GearHidden:= HH^.Gear;
   128     HH^.GearHidden:= HH^.Gear;
   129     HH^.Gear:= nil
   129     HH^.Gear:= nil
   731 end;
   731 end;
   732 
   732 
   733 ////////////////////////////////////////////////////////////////////////////////
   733 ////////////////////////////////////////////////////////////////////////////////
   734 procedure doStepGrave(Gear: PGear);
   734 procedure doStepGrave(Gear: PGear);
   735 begin
   735 begin
       
   736     if (Gear^.Message and gmDestroy) <> 0 then
       
   737         begin
       
   738         DeleteGear(Gear);
       
   739         exit
       
   740         end;
       
   741 
   736     AllInactive := false;
   742     AllInactive := false;
       
   743 
   737     if Gear^.dY.isNegative then
   744     if Gear^.dY.isNegative then
   738         if TestCollisionY(Gear, -1) then
   745         if TestCollisionY(Gear, -1) then
   739             Gear^.dY := _0;
   746             Gear^.dY := _0;
   740 
   747 
   741     if not Gear^.dY.isNegative then
   748     if not Gear^.dY.isNegative then
  2078     k: TGearType;
  2085     k: TGearType;
  2079     exBoom: boolean;
  2086     exBoom: boolean;
  2080     dX, dY: HWFloat;
  2087     dX, dY: HWFloat;
  2081     hog: PHedgehog;
  2088     hog: PHedgehog;
  2082     sparkles: PVisualGear;
  2089     sparkles: PVisualGear;
       
  2090     gi: PGear;
  2083 begin
  2091 begin
  2084     k := Gear^.Kind;
  2092     k := Gear^.Kind;
  2085     exBoom := false;
  2093     exBoom := false;
  2086 
  2094 
  2087     if (Gear^.Message and gmDestroy) > 0 then
  2095     if (Gear^.Message and gmDestroy) > 0 then
  2112         if Gear^.Health <= 0 then
  2120         if Gear^.Health <= 0 then
  2113             exBoom := true;
  2121             exBoom := true;
  2114         end
  2122         end
  2115     else
  2123     else
  2116         begin 
  2124         begin 
       
  2125         if (Gear^.Pos <> posCaseHealth) and (GameTicks and $3FF = 0) then // stir it up every second or so
       
  2126             begin
       
  2127             gi := GearsList;
       
  2128             while gi <> nil do
       
  2129                 begin
       
  2130                 if gi^.Kind = gtGenericFaller then
       
  2131                     begin
       
  2132                     gi^.Active:= true;
       
  2133                     gi^.X:=  int2hwFloat(GetRandom(rightX-leftX)+leftX);
       
  2134                     gi^.Y:=  int2hwFloat(GetRandom(LAND_HEIGHT-topY)+topY);
       
  2135                     gi^.dX:= _90-(GetRandomf*_360);
       
  2136                     gi^.dY:= _90-(GetRandomf*_360)
       
  2137                     end;
       
  2138                 gi := gi^.NextGear
       
  2139                 end
       
  2140             end;
       
  2141 
  2117         if Gear^.Timer = 500 then
  2142         if Gear^.Timer = 500 then
  2118             begin
  2143             begin
  2119 (* Can't make sparkles team coloured without working out what the next team is going to be. This should be solved, really, since it also screws up
  2144 (* Can't make sparkles team coloured without working out what the next team is going to be. This should be solved, really, since it also screws up
  2120    voices. Reinforcements voices is heard for active team, not team-to-be.  Either that or change crate spawn from end of turn to start, although that
  2145    voices. Reinforcements voices is heard for active team, not team-to-be.  Either that or change crate spawn from end of turn to start, although that
  2121    has its own complexities. *)
  2146    has its own complexities. *)
  2122             // Abuse a couple of gear values to track origin
  2147             // Abuse a couple of gear values to track origin
  2123             Gear^.Angle:= hwRound(Gear^.X);
  2148             Gear^.Angle:= hwRound(Gear^.Y);
  2124             Gear^.Power:= hwRound(Gear^.Y);
       
  2125             Gear^.Tag:= random(2);
  2149             Gear^.Tag:= random(2);
  2126             inc(Gear^.Timer)
  2150             inc(Gear^.Timer)
  2127             end;
  2151             end;
  2128         if Gear^.Timer < 1833 then inc(Gear^.Timer);
  2152         if Gear^.Timer < 1833 then inc(Gear^.Timer);
  2129         if Gear^.Timer = 1000 then
  2153         if Gear^.Timer = 1000 then
  2130             begin
  2154             begin
  2131             sparkles:= AddVisualGear(Gear^.Angle, Gear^.Power, vgtDust, 1);
  2155             sparkles:= AddVisualGear(hwRound(Gear^.X), Gear^.Angle, vgtDust, 1);
  2132             if sparkles <> nil then
  2156             if sparkles <> nil then
  2133                 begin
  2157                 begin
  2134                 sparkles^.dX:= 0;
  2158                 sparkles^.dX:= 0;
  2135                 sparkles^.dY:= 0;
  2159                 sparkles^.dY:= 0;
  2136                 sparkles^.Angle:= 270;
  2160                 sparkles^.Angle:= 270;
  2380                 else if ((GameTicks and $3) = 3) then
  2404                 else if ((GameTicks and $3) = 3) then
  2381                     doMakeExplosion(gX, gY, 8, Gear^.Hedgehog, 0);//, EXPLNoDamage); 
  2405                     doMakeExplosion(gX, gY, 8, Gear^.Hedgehog, 0);//, EXPLNoDamage); 
  2382                 //DrawExplosion(gX, gY, 4);
  2406                 //DrawExplosion(gX, gY, 4);
  2383                 
  2407                 
  2384                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2408                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2385                     for i:= 1 to Random(2)+1 do
  2409                     for i:= Random(2) downto 0 do
  2386                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2410                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2387                         
  2411                         
  2388                 if Gear^.Health > 0 then
  2412                 if Gear^.Health > 0 then
  2389                     dec(Gear^.Health);
  2413                     dec(Gear^.Health);
  2390                 Gear^.Timer := 450 - Gear^.Tag * 8
  2414                 Gear^.Timer := 450 - Gear^.Tag * 8
  2394                 // Modified fire
  2418                 // Modified fire
  2395                 if ((GameTicks and $7FF) = 0) and ((GameFlags and gfSolidLand) = 0) then
  2419                 if ((GameTicks and $7FF) = 0) and ((GameFlags and gfSolidLand) = 0) then
  2396                     begin
  2420                     begin
  2397                     DrawExplosion(gX, gY, 4);
  2421                     DrawExplosion(gX, gY, 4);
  2398 
  2422 
  2399                     for i:= 0 to Random(3) do
  2423                     for i:= Random(3) downto 0 do
  2400                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2424                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2401                     end;
  2425                     end;
  2402 
  2426 
  2403 // This one is interesting.  I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom.
  2427 // This one is interesting.  I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom.
  2404                 Gear^.Timer := 100 - Gear^.Tag * 3;
  2428                 Gear^.Timer := 100 - Gear^.Tag * 3;
  2412         gX := hwRound(Gear^.X);
  2436         gX := hwRound(Gear^.X);
  2413         gY := hwRound(Gear^.Y);
  2437         gY := hwRound(Gear^.Y);
  2414         if not sticky then
  2438         if not sticky then
  2415             begin
  2439             begin
  2416             if ((GameTicks and $3) = 0) and (Random(1) = 0) then
  2440             if ((GameTicks and $3) = 0) and (Random(1) = 0) then
  2417                 begin
  2441                 for i:= Random(2) downto 0 do
  2418                 for i:= 1 to Random(2)+1 do
       
  2419                     begin
       
  2420                     AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2442                     AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2421                     end;
       
  2422                 end;
       
  2423             end
  2443             end
  2424         else
  2444         else
  2425             begin
  2445             for i:= Random(3) downto 0 do
  2426             for i:= 0 to Random(3) do
       
  2427                 begin
       
  2428                 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2446                 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2429                 end;
       
  2430             end;
       
  2431 
  2447 
  2432         DeleteGear(Gear)
  2448         DeleteGear(Gear)
  2433         end;
  2449         end;
  2434 end;
  2450 end;
  2435 
  2451 
  2749 
  2765 
  2750 ////////////////////////////////////////////////////////////////////////////////
  2766 ////////////////////////////////////////////////////////////////////////////////
  2751 procedure doStepSwitcherWork(Gear: PGear);
  2767 procedure doStepSwitcherWork(Gear: PGear);
  2752 var 
  2768 var 
  2753     HHGear: PGear;
  2769     HHGear: PGear;
       
  2770     hedgehog: PHedgehog;
  2754     State: Longword;
  2771     State: Longword;
  2755 begin
  2772 begin
  2756     AllInactive := false;
  2773     AllInactive := false;
  2757 
  2774 
  2758     if ((Gear^.Message and (not gmSwitch)) <> 0) or (TurnTimeLeft = 0) then
  2775     if ((Gear^.Message and (not gmSwitch)) <> 0) or (TurnTimeLeft = 0) then
  2759         begin
  2776         begin
  2760         HHGear := Gear^.Hedgehog^.Gear;
  2777         hedgehog := Gear^.Hedgehog;
  2761         //Msg := Gear^.Message and (not gmSwitch);
  2778         //Msg := Gear^.Message and (not gmSwitch);
  2762         DeleteGear(Gear);
  2779         DeleteGear(Gear);
  2763         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2780         ApplyAmmoChanges(hedgehog^);
  2764 
  2781 
  2765         HHGear := CurrentHedgehog^.Gear;
  2782         HHGear := CurrentHedgehog^.Gear;
  2766         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2783         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2767         //HHGear^.Message := Msg;
  2784         //HHGear^.Message := Msg;
  2768         exit
  2785         exit
  2773         HHGear := CurrentHedgehog^.Gear;
  2790         HHGear := CurrentHedgehog^.Gear;
  2774         HHGear^.Message := HHGear^.Message and (not gmSwitch);
  2791         HHGear^.Message := HHGear^.Message and (not gmSwitch);
  2775         Gear^.Message := Gear^.Message and (not gmSwitch);
  2792         Gear^.Message := Gear^.Message and (not gmSwitch);
  2776         State := HHGear^.State;
  2793         State := HHGear^.State;
  2777         HHGear^.State := 0;
  2794         HHGear^.State := 0;
       
  2795         HHGear^.Z := cHHZ;
  2778         HHGear^.Active := false;
  2796         HHGear^.Active := false;
  2779         HHGear^.Z := cHHZ;
  2797         HHGear^.Message:= HHGear^.Message or gmRemoveFromList or gmAddToList;
  2780         RemoveGearFromList(HHGear);
       
  2781         InsertGearToList(HHGear);
       
  2782 
  2798 
  2783         PlaySound(sndSwitchHog);
  2799         PlaySound(sndSwitchHog);
  2784 
  2800 
  2785         repeat
  2801         repeat
  2786             CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.HedgehogsNumber);
  2802             CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.HedgehogsNumber);
  2792         HHGear := CurrentHedgehog^.Gear;
  2808         HHGear := CurrentHedgehog^.Gear;
  2793         HHGear^.State := State;
  2809         HHGear^.State := State;
  2794         HHGear^.Active := true;
  2810         HHGear^.Active := true;
  2795         FollowGear := HHGear;
  2811         FollowGear := HHGear;
  2796         HHGear^.Z := cCurrHHZ;
  2812         HHGear^.Z := cCurrHHZ;
  2797         RemoveGearFromList(HHGear);
  2813         HHGear^.Message:= HHGear^.Message or gmRemoveFromList or gmAddToList;
  2798         InsertGearToList(HHGear);
       
  2799         Gear^.X := HHGear^.X;
  2814         Gear^.X := HHGear^.X;
  2800         Gear^.Y := HHGear^.Y
  2815         Gear^.Y := HHGear^.Y
  2801         end;
  2816         end;
  2802 end;
  2817 end;
  2803 
  2818 
  2938                             dy := -dy;
  2953                             dy := -dy;
  2939                         FrameTicks:= random(400) + 250
  2954                         FrameTicks:= random(400) + 250
  2940                         end
  2955                         end
  2941                 end;
  2956                 end;
  2942         AfterAttack;
  2957         AfterAttack;
  2943         DeleteGear(HHGear);
  2958         HHGear^.Message:= HHGear^.Message or gmDestroy;
  2944         DeleteGear(Gear);
  2959         DeleteGear(Gear);
  2945     end
  2960     end
  2946     else
  2961     else
  2947         begin
  2962         begin
  2948         dec(Gear^.Health, Gear^.Damage);
  2963         dec(Gear^.Health, Gear^.Damage);
  2982 end;
  2997 end;
  2983 
  2998 
  2984 ////////////////////////////////////////////////////////////////////////////////
  2999 ////////////////////////////////////////////////////////////////////////////////
  2985 
  3000 
  2986 const cakeh =   27;
  3001 const cakeh =   27;
  2987     cakeDmg =   75;
       
  2988 var 
  3002 var 
  2989     CakePoints: array[0..Pred(cakeh)] of record
  3003     CakePoints: array[0..Pred(cakeh)] of record
  2990         x, y: hwFloat;
  3004         x, y: hwFloat;
  2991     end;
  3005     end;
  2992     CakeI: Longword;
  3006     CakeI: Longword;
  3052         end
  3066         end
  3053     else dec(Gear^.Pos)
  3067     else dec(Gear^.Pos)
  3054 end;
  3068 end;
  3055 
  3069 
  3056 
  3070 
  3057 procedure PrevAngle(Gear: PGear; dA: LongInt);
       
  3058 begin
       
  3059     Gear^.Angle := (LongInt(Gear^.Angle) + 4 - dA) mod 4
       
  3060 end;
       
  3061 
       
  3062 procedure NextAngle(Gear: PGear; dA: LongInt);
       
  3063 begin
       
  3064     Gear^.Angle := (LongInt(Gear^.Angle) + 4 + dA) mod 4
       
  3065 end;
       
  3066 
       
  3067 procedure doStepCakeWork(Gear: PGear);
  3071 procedure doStepCakeWork(Gear: PGear);
  3068 
  3072 
  3069 const dirs: array[0..3] of TPoint =   ((X: 0; Y: -1), (X: 1; Y: 0),(X: 0; Y: 1),(X: -1; Y: 0));
  3073 const dirs: array[0..3] of TPoint =   ((X: 0; Y: -1), (X: 1; Y: 0),(X: 0; Y: 1),(X: -1; Y: 0));
  3070 var 
  3074 var
  3071     xx, yy, xxn, yyn: LongInt;
  3075     xx, yy, xxn, yyn: LongInt;
  3072     dA: LongInt;
  3076     dA: LongInt;
  3073     tdx, tdy: hwFloat;
  3077     tdx, tdy: hwFloat;
  3074 begin
  3078 begin
  3075     AllInactive := false;
  3079     AllInactive := false;
  3076 
  3080 
  3077     inc(Gear^.Tag);
  3081     inc(Gear^.Tag);
  3078     if Gear^.Tag < 7 then
  3082     if Gear^.Tag < 7 then
  3079         exit;
  3083         exit;
  3080 
  3084 
  3081     dA := hwSign(Gear^.dX);
  3085     dec(Gear^.Health);
  3082     xx := dirs[Gear^.Angle].x;
  3086     Gear^.Timer := Gear^.Health*10;
  3083     yy := dirs[Gear^.Angle].y;
  3087     if Gear^.Health mod 100 = 0 then
  3084     xxn := dirs[(LongInt(Gear^.Angle) + 4 + dA) mod 4].x;
  3088         Gear^.PortalCounter:= 0;
  3085     yyn := dirs[(LongInt(Gear^.Angle) + 4 + dA) mod 4].y;
  3089     // This is not seconds, but at least it is *some* feedback
  3086 
  3090     if (Gear^.Health = 0) or ((Gear^.Message and gmAttack) <> 0) then
  3087     if (xx = 0) then
  3091         begin
  3088         if TestCollisionYwithGear(Gear, yy) <> 0 then
  3092         FollowGear := Gear;
  3089             PrevAngle(Gear, dA)
  3093         Gear^.RenderTimer := false;
  3090     else
  3094         Gear^.doStep := @doStepCakeDown;
  3091         begin
  3095         exit
  3092         Gear^.Tag := 0;
  3096         end;
  3093         Gear^.Y := Gear^.Y + int2hwFloat(yy);
  3097 
  3094         if not TestCollisionXwithGear(Gear, xxn) then
  3098     cakeStep(Gear);
  3095             begin
       
  3096             Gear^.X := Gear^.X + int2hwFloat(xxn);
       
  3097             NextAngle(Gear, dA)
       
  3098             end;
       
  3099         end;
       
  3100 
       
  3101     if (yy = 0) then
       
  3102         if TestCollisionXwithGear(Gear, xx) then
       
  3103             PrevAngle(Gear, dA)
       
  3104     else
       
  3105         begin
       
  3106         Gear^.Tag := 0;
       
  3107         Gear^.X := Gear^.X + int2hwFloat(xx);
       
  3108         if TestCollisionYwithGear(Gear, yyn) = 0 then
       
  3109             begin
       
  3110             Gear^.Y := Gear^.Y + int2hwFloat(yyn);
       
  3111             NextAngle(Gear, dA)
       
  3112             end;
       
  3113         end;
       
  3114 
  3099 
  3115     if Gear^.Tag = 0 then
  3100     if Gear^.Tag = 0 then
  3116         begin
  3101         begin
  3117         CakeI := (CakeI + 1) mod cakeh;
  3102         CakeI := (CakeI + 1) mod cakeh;
  3118         tdx := CakePoints[CakeI].x - Gear^.X;
  3103         tdx := CakePoints[CakeI].x - Gear^.X;
  3119         tdy := - CakePoints[CakeI].y + Gear^.Y;
  3104         tdy := - CakePoints[CakeI].y + Gear^.Y;
  3120         CakePoints[CakeI].x := Gear^.X;
  3105         CakePoints[CakeI].x := Gear^.X;
  3121         CakePoints[CakeI].y := Gear^.Y;
  3106         CakePoints[CakeI].y := Gear^.Y;
  3122         Gear^.DirAngle := DxDy2Angle(tdx, tdy);
  3107         Gear^.DirAngle := DxDy2Angle(tdx, tdy);
  3123         end;
  3108         end;
  3124 
       
  3125     dec(Gear^.Health);
       
  3126     Gear^.Timer := Gear^.Health*10;
       
  3127     if Gear^.Health mod 100 = 0 then
       
  3128         Gear^.PortalCounter:= 0;
       
  3129     // This is not seconds, but at least it is *some* feedback
       
  3130     if (Gear^.Health = 0) or ((Gear^.Message and gmAttack) <> 0) then
       
  3131         begin
       
  3132         FollowGear := Gear;
       
  3133         Gear^.RenderTimer := false;
       
  3134         Gear^.doStep := @doStepCakeDown
       
  3135         end
       
  3136 end;
  3109 end;
  3137 
  3110 
  3138 procedure doStepCakeUp(Gear: PGear);
  3111 procedure doStepCakeUp(Gear: PGear);
  3139 var 
  3112 var 
  3140     i: Longword;
  3113     i: Longword;
  3191 end;
  3164 end;
  3192 
  3165 
  3193 ////////////////////////////////////////////////////////////////////////////////
  3166 ////////////////////////////////////////////////////////////////////////////////
  3194 procedure doStepSeductionWork(Gear: PGear);
  3167 procedure doStepSeductionWork(Gear: PGear);
  3195 var i: LongInt;
  3168 var i: LongInt;
  3196     hogs: TPGearArray;
  3169     hogs: PGearArrayS;
  3197 begin
  3170 begin
  3198     AllInactive := false;
  3171     AllInactive := false;
  3199     hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius);
  3172     hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius);
  3200     if Length(hogs) > 0 then
  3173     if hogs.size > 0 then
  3201         begin
  3174         begin
  3202         for i:= 0 to Length(hogs) - 1 do
  3175         for i:= 0 to hogs.size - 1 do
  3203             begin
  3176             with hogs.ar^[i]^ do
  3204             if hogs[i] <> CurrentHedgehog^.Gear then
  3177                 begin
  3205                 begin
  3178                 if hogs.ar^[i] <> CurrentHedgehog^.Gear then
  3206                 //d:= Distance(Gear^.X - hogs[i]^.X, Gear^.Y - hogs[i]^.Y);
  3179                     begin
  3207                 hogs[i]^.dX:= _50 * cGravity * (Gear^.X - hogs[i]^.X) / _25;
  3180                     dX:= _50 * cGravity * (Gear^.X - X) / _25;
  3208                 //if Gear^.X < hogs[i]^.X then hogs[i]^.dX.isNegative:= true;
  3181                     dY:= -_450 * cGravity;
  3209                 hogs[i]^.dY:= -_450 * cGravity;
  3182                     Active:= true;
  3210                 hogs[i]^.Active:= true;
  3183                     end
  3211                 end
  3184                 end;
  3212             end;
       
  3213         end ;
  3185         end ;
  3214         AfterAttack;
  3186         AfterAttack;
  3215         DeleteGear(Gear);
  3187         DeleteGear(Gear);
  3216 (*
  3188 (*
  3217     Gear^.X := Gear^.X + Gear^.dX;
  3189     Gear^.X := Gear^.X + Gear^.dX;
  3329         Gear^.Y := Gear^.Y + Gear^.dY;
  3301         Gear^.Y := Gear^.Y + Gear^.dY;
  3330         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 2, 6);
  3302         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 2, 6);
  3331         if (Gear^.Timer mod 30) = 0 then
  3303         if (Gear^.Timer mod 30) = 0 then
  3332             AddVisualGear(hwRound(Gear^.X + _20 * Gear^.dX), hwRound(Gear^.Y + _20 * Gear^.dY), vgtDust);
  3304             AddVisualGear(hwRound(Gear^.X + _20 * Gear^.dX), hwRound(Gear^.Y + _20 * Gear^.dY), vgtDust);
  3333         if (CheckGearDrowning(Gear)) then
  3305         if (CheckGearDrowning(Gear)) then
  3334            begin
  3306             begin
  3335             StopSoundChan(Gear^.SoundChannel);
  3307             StopSoundChan(Gear^.SoundChannel);
  3336             exit
  3308             exit
  3337     end
  3309         end
  3338     end;
  3310     end;
  3339 
  3311 
  3340     if GameTicks > Gear^.FlightTime then
  3312     if GameTicks > Gear^.FlightTime then
  3341         t := CheckGearsCollision(Gear)
  3313         t := CheckGearsCollision(Gear)
  3342         
  3314         
  3423             gear^.RenderTimer:= true;
  3395             gear^.RenderTimer:= true;
  3424         if Gear^.Timer > 0 then dec(Gear^.Timer)
  3396         if Gear^.Timer > 0 then dec(Gear^.Timer)
  3425         end
  3397         end
  3426     else if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Tag <> 0) then
  3398     else if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Tag <> 0) then
  3427         begin
  3399         begin
  3428         if Gear^.Timer > 0 then dec(Gear^.Timer);
  3400         if Gear^.Timer > 0 then 
  3429         if Gear^.Timer = 0 then
  3401             dec(Gear^.Timer)
       
  3402         else
  3430             begin
  3403             begin
  3431             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  3404             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  3432             DeleteGear(Gear);
  3405             DeleteGear(Gear);
  3433             end
  3406             end
  3434         end;
  3407         end;
  4336         and (iterator = CurrentHedgehog^.Gear)
  4309         and (iterator = CurrentHedgehog^.Gear)
  4337         and (CurAmmoGear <> nil)
  4310         and (CurAmmoGear <> nil)
  4338         and (CurAmmoGear^.Kind =gtRope) then
  4311         and (CurAmmoGear^.Kind =gtRope) then
  4339                CurAmmoGear^.PortalCounter:= 1;
  4312                CurAmmoGear^.PortalCounter:= 1;
  4340 
  4313 
  4341         if not isbullet
  4314         if not isbullet and (iterator^.State and gstInvisible = 0) 
  4342         and (iterator^.Kind <> gtFlake) then
  4315         and (iterator^.Kind <> gtFlake) then
  4343             FollowGear := iterator;
  4316             FollowGear := iterator;
  4344 
  4317 
  4345         // store X/Y values of exit for net bullet trail
  4318         // store X/Y values of exit for net bullet trail
  4346         if isbullet then
  4319         if isbullet then
  4415         begin
  4388         begin
  4416         Gear^.State := Gear^.State or gstCollision;
  4389         Gear^.State := Gear^.State or gstCollision;
  4417         Gear^.State := Gear^.State and (not gstMoving);
  4390         Gear^.State := Gear^.State and (not gstMoving);
  4418         
  4391         
  4419         if (Land[y, x] and lfBouncy <> 0)
  4392         if (Land[y, x] and lfBouncy <> 0)
  4420         or not CalcSlopeTangent(Gear, x, y, tx, ty, 255)
  4393         or (not CalcSlopeTangent(Gear, x, y, tx, ty, 255))
  4421         or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain
  4394         or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain
  4422             begin
  4395             begin
  4423             loadNewPortalBall(Gear, true);
  4396             loadNewPortalBall(Gear, true);
  4424             EXIT;
  4397             EXIT;
  4425             end;
  4398             end;
  4695                     dec(Gear^.Health, Gear^.Damage);
  4668                     dec(Gear^.Health, Gear^.Damage);
  4696                     Gear^.Damage := 0;
  4669                     Gear^.Damage := 0;
  4697 
  4670 
  4698                     // add some fire to the tunnel
  4671                     // add some fire to the tunnel
  4699                     if getRandom(6) = 0 then
  4672                     if getRandom(6) = 0 then
  4700                         AddGear(x - Gear^.Radius + LongInt(getRandom(2 * Gear^.Radius)), y -
  4673                         begin
  4701                         getRandom(Gear^.Radius + 1), gtFlame, gsttmpFlag, _0, _0, 0);
  4674                         tmp:= GetRandom(2 * Gear^.Radius);
       
  4675                         AddGear(x - Gear^.Radius + tmp, y - GetRandom(Gear^.Radius + 1), gtFlame, gsttmpFlag, _0, _0, 0)
       
  4676                         end
  4702                     end;
  4677                     end;
  4703 
  4678 
  4704                 if getRandom(100) = 0 then
  4679                 if random(100) = 0 then
  4705                     AddVisualGear(x, y, vgtSmokeTrace); 
  4680                     AddVisualGear(x, y, vgtSmokeTrace); 
  4706                 end
  4681                 end
  4707                 else dec(Gear^.Health, 5); // if underwater get additional damage
  4682                 else dec(Gear^.Health, 5); // if underwater get additional damage
  4708             end;
  4683             end;
  4709 
  4684 
  5059 end;
  5034 end;
  5060 
  5035 
  5061 ////////////////////////////////////////////////////////////////////////////////
  5036 ////////////////////////////////////////////////////////////////////////////////
  5062 procedure doStepResurrectorWork(Gear: PGear);
  5037 procedure doStepResurrectorWork(Gear: PGear);
  5063 var
  5038 var
  5064     graves: TPGearArray;
  5039     graves: PGearArrayS;
  5065     resgear: PGear;
  5040     resgear: PGear;
  5066     hh: PHedgehog;
  5041     hh: PHedgehog;
  5067     i: LongInt;
  5042     i: LongInt;
  5068 begin
  5043 begin
  5069     if (TurnTimeLeft > 0) then
  5044     if (TurnTimeLeft > 0) then
  5094             hh^.Gear^.Y := hh^.Gear^.Y - _1;
  5069             hh^.Gear^.Y := hh^.Gear^.Y - _1;
  5095         end;
  5070         end;
  5096 
  5071 
  5097     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
  5072     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
  5098 
  5073 
  5099     if Length(graves) = 0 then
  5074     if graves.size = 0 then
  5100         begin
  5075         begin
  5101         StopSoundChan(Gear^.SoundChannel);
  5076         StopSoundChan(Gear^.SoundChannel);
  5102         Gear^.Timer := 250;
  5077         Gear^.Timer := 250;
  5103         Gear^.doStep := @doStepIdle;
  5078         Gear^.doStep := @doStepIdle;
  5104         exit;
  5079         exit;
  5105         end;
  5080         end;
  5106 
  5081 
  5107     if ((Gear^.Message and gmAttack) <> 0) and (hh^.Gear^.Health > 0) and (TurnTimeLeft > 0) then
  5082     if ((Gear^.Message and gmAttack) <> 0) and (hh^.Gear^.Health > 0) and (TurnTimeLeft > 0) then
  5108         begin
  5083         begin
  5109         if Length(graves) <= Gear^.Tag then Gear^.Tag:= 0;
  5084         if graves.size <= Gear^.Tag then Gear^.Tag:= 0;
  5110         dec(hh^.Gear^.Health);
  5085         dec(hh^.Gear^.Health);
  5111         if (hh^.Gear^.Health = 0) and (hh^.Gear^.Damage = 0) then
  5086         if (hh^.Gear^.Health = 0) and (hh^.Gear^.Damage = 0) then
  5112             hh^.Gear^.Damage:= 1;
  5087             hh^.Gear^.Damage:= 1;
  5113         RenderHealth(hh^);
  5088         RenderHealth(hh^);
  5114         inc(graves[Gear^.Tag]^.Health);
  5089         RecountTeamHealth(hh^.Team);
       
  5090         inc(graves.ar^[Gear^.Tag]^.Health);
  5115         inc(Gear^.Tag)
  5091         inc(Gear^.Tag)
  5116 {-for i:= 0 to High(graves) do begin
  5092 {-for i:= 0 to High(graves) do begin
  5117             if hh^.Gear^.Health > 0 then begin
  5093             if hh^.Gear^.Health > 0 then begin
  5118                 dec(hh^.Gear^.Health);
  5094                 dec(hh^.Gear^.Health);
  5119                 inc(graves[i]^.Health);
  5095                 inc(graves[i]^.Health);
  5121         end; -}
  5097         end; -}
  5122         end 
  5098         end 
  5123     else 
  5099     else 
  5124         begin
  5100         begin
  5125         // now really resurrect the hogs with the hp saved in the graves
  5101         // now really resurrect the hogs with the hp saved in the graves
  5126         for i:= 0 to Length(graves) - 1 do
  5102         for i:= 0 to graves.size - 1 do
  5127             if graves[i]^.Health > 0 then
  5103             if graves.ar^[i]^.Health > 0 then
  5128                 begin
  5104                 begin
  5129                 resgear := AddGear(hwRound(graves[i]^.X), hwRound(graves[i]^.Y), gtHedgehog, gstWait, _0, _0, 0);
  5105                 resgear := AddGear(hwRound(graves.ar^[i]^.X), hwRound(graves.ar^[i]^.Y), gtHedgehog, gstWait, _0, _0, 0);
  5130                 resgear^.Hedgehog := graves[i]^.Hedgehog;
  5106                 resgear^.Hedgehog := graves.ar^[i]^.Hedgehog;
  5131                 resgear^.Health := graves[i]^.Health;
  5107                 resgear^.Health := graves.ar^[i]^.Health;
  5132                 PHedgehog(graves[i]^.Hedgehog)^.Gear := resgear;
  5108                 PHedgehog(graves.ar^[i]^.Hedgehog)^.Gear := resgear;
  5133                 DeleteGear(graves[i]);
  5109                 graves.ar^[i]^.Message:= graves.ar^[i]^.Message or gmDestroy;
       
  5110                 graves.ar^[i]^.Active:= true;
  5134                 RenderHealth(resgear^.Hedgehog^);
  5111                 RenderHealth(resgear^.Hedgehog^);
  5135                 RecountTeamHealth(resgear^.Hedgehog^.Team);
  5112                 RecountTeamHealth(resgear^.Hedgehog^.Team);
  5136                 resgear^.Hedgehog^.Effects[heResurrected]:= 1;
  5113                 resgear^.Hedgehog^.Effects[heResurrected]:= 1;
  5137                 // only make hat-less hedgehogs look like zombies, preserve existing hats
  5114                 // only make hat-less hedgehogs look like zombies, preserve existing hats
  5138                 
  5115 
  5139                 if resgear^.Hedgehog^.Hat = 'NoHat' then
  5116                 if resgear^.Hedgehog^.Hat = 'NoHat' then
  5140                     LoadHedgehogHat(resgear, 'Reserved/Zombie');
  5117                     LoadHedgehogHat(resgear, 'Reserved/Zombie');
  5141                 end;
  5118                 end;
  5142 
  5119 
  5143         hh^.Gear^.dY := _0;
  5120         hh^.Gear^.dY := _0;
  5150     //if hh^.Gear^.Health = 0 then doStepHedgehogFree(hh^.Gear);
  5127     //if hh^.Gear^.Health = 0 then doStepHedgehogFree(hh^.Gear);
  5151 end;
  5128 end;
  5152 
  5129 
  5153 procedure doStepResurrector(Gear: PGear);
  5130 procedure doStepResurrector(Gear: PGear);
  5154 var
  5131 var
  5155     graves: TPGearArray;
  5132     graves: PGearArrayS;
  5156     i: LongInt;
  5133     i: LongInt;
  5157 begin
  5134 begin
  5158     AllInactive := false;
  5135     AllInactive := false;
  5159     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
  5136     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
  5160 
  5137 
  5161     if Length(graves) > 0 then
  5138     if graves.size > 0 then
  5162         begin
  5139         begin
  5163         for i:= 0 to Length(graves) - 1 do
  5140         for i:= 0 to graves.size - 1 do
  5164             begin
  5141             begin
  5165             PHedgehog(graves[i]^.Hedgehog)^.Gear := nil;
  5142             PHedgehog(graves.ar^[i]^.Hedgehog)^.Gear := nil;
  5166             graves[i]^.Health := 0;
  5143             graves.ar^[i]^.Health := 0;
  5167             end;
  5144             end;
  5168         Gear^.doStep := @doStepResurrectorWork;
  5145         Gear^.doStep := @doStepResurrectorWork;
  5169         end 
  5146         end 
  5170     else 
  5147     else 
  5171         begin
  5148         begin
  5480 procedure doStepIceGun(Gear: PGear);
  5457 procedure doStepIceGun(Gear: PGear);
  5481 var 
  5458 var 
  5482     HHGear, iter: PGear;
  5459     HHGear, iter: PGear;
  5483     ndX, ndY: hwFloat;
  5460     ndX, ndY: hwFloat;
  5484     i, t, gX, gY: LongInt;
  5461     i, t, gX, gY: LongInt;
  5485     hogs: TPGearArray;
  5462     hogs: PGearArrayS;
  5486 begin
  5463 begin
  5487     HHGear := Gear^.Hedgehog^.Gear;
  5464     HHGear := Gear^.Hedgehog^.Gear;
  5488     if (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) then
  5465     if (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) then
  5489         begin
  5466         begin
  5490         DeleteGear(Gear);
  5467         DeleteGear(Gear);
  5544                     Y:= HHGear^.Y
  5521                     Y:= HHGear^.Y
  5545                     end;
  5522                     end;
  5546 // freeze nearby hogs
  5523 // freeze nearby hogs
  5547                 if GameTicks mod 10 = 0 then dec(Gear^.Health);
  5524                 if GameTicks mod 10 = 0 then dec(Gear^.Health);
  5548                 hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius);
  5525                 hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius);
  5549                 if Length(hogs) > 0 then
  5526                 if hogs.size > 0 then
  5550                     for i:= 0 to Length(hogs) - 1 do
  5527                     for i:= 0 to hogs.size - 1 do
  5551                         if hogs[i] <> HHGear then
  5528                         if hogs.ar^[i] <> HHGear then
  5552                             begin
  5529                             begin
  5553                             //if Gear^.Hedgehog^.Effects[heFrozen]:= 0;
  5530                             //if Gear^.Hedgehog^.Effects[heFrozen]:= 0;
  5554                             end;
  5531                             end;
  5555                 inc(Pos)
  5532                 inc(Pos)
  5556                 end
  5533                 end
  5572                 Y:= HHGear^.Y
  5549                 Y:= HHGear^.Y
  5573                 end
  5550                 end
  5574         end
  5551         end
  5575     end;
  5552     end;
  5576 end;
  5553 end;
       
  5554 
       
  5555 procedure doStepAddAmmo(Gear: PGear);
       
  5556 var a: TAmmoType;
       
  5557     gi: PGear;
       
  5558 begin
       
  5559 if Gear^.Timer > 0 then dec(Gear^.Timer)
       
  5560 else
       
  5561     begin
       
  5562     if Gear^.Pos = posCaseUtility then
       
  5563         a:= GetUtility(Gear^.Hedgehog)
       
  5564     else
       
  5565         a:= GetAmmo(Gear^.Hedgehog);
       
  5566     CheckSum:= CheckSum xor GameTicks;
       
  5567     gi := GearsList;
       
  5568     while gi <> nil do
       
  5569         begin
       
  5570         with gi^ do CheckSum:= CheckSum xor X.round xor X.frac xor dX.round xor dX.frac xor Y.round xor Y.frac xor dY.round xor dY.frac;
       
  5571         AddRandomness(CheckSum);
       
  5572         gi := gi^.NextGear
       
  5573         end;
       
  5574     AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
       
  5575     DeleteGear(Gear)
       
  5576     end;
       
  5577 end;
       
  5578 
       
  5579 procedure doStepGenericFaller(Gear: PGear);
       
  5580 begin
       
  5581 if Gear^.Timer < $FFFFFFFF then
       
  5582     if Gear^.Timer > 0 then
       
  5583         dec(Gear^.Timer)
       
  5584     else
       
  5585         begin
       
  5586         DeleteGear(Gear);
       
  5587         exit
       
  5588         end;
       
  5589     
       
  5590 doStepFallingGear(Gear);
       
  5591 end;