hedgewars/GSHandlers.inc
changeset 1 30f2d1037d5d
child 4 bcbd7adb4e4b
equal deleted inserted replaced
0:475c0f2f9d17 1:30f2d1037d5d
       
     1 (*
       
     2  * Hedgewars, a worms-like game
       
     3  * Copyright (c) 2004, 2005 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * Distributed under the terms of the BSD-modified licence:
       
     6  *
       
     7  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     8  * of this software and associated documentation files (the "Software"), to deal
       
     9  * with the Software without restriction, including without limitation the
       
    10  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
       
    11  * sell copies of the Software, and to permit persons to whom the Software is
       
    12  * furnished to do so, subject to the following conditions:
       
    13  *
       
    14  * 1. Redistributions of source code must retain the above copyright notice,
       
    15  *    this list of conditions and the following disclaimer.
       
    16  * 2. Redistributions in binary form must reproduce the above copyright notice,
       
    17  *    this list of conditions and the following disclaimer in the documentation
       
    18  *    and/or other materials provided with the distribution.
       
    19  * 3. The name of the author may not be used to endorse or promote products
       
    20  *    derived from this software without specific prior written permission.
       
    21  *
       
    22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
       
    23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
       
    24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
       
    25  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
       
    28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
       
    29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
       
    30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
       
    31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    32  *)
       
    33 
       
    34 procedure doStepDrowningGear(Gear: PGear); forward;
       
    35 
       
    36 function CheckGearDrowning(Gear: PGear): boolean;
       
    37 begin
       
    38 Result:= Gear.Y + Gear.HalfHeight >= cWaterLine;
       
    39 if Result then
       
    40    begin
       
    41    Gear.State:= gstDrowning;
       
    42    Gear.doStep:= doStepDrowningGear;
       
    43    PlaySound(sndSplash)
       
    44    end
       
    45 end;
       
    46 
       
    47 procedure CheckCollision(Gear: PGear);
       
    48 begin
       
    49 if TestCollisionXwithGear(Gear, Sign(Gear.X)) or TestCollisionYwithGear(Gear, Sign(Gear.Y))
       
    50    then Gear.State:= Gear.State or      gstCollision
       
    51    else Gear.State:= Gear.State and not gstCollision
       
    52 end;
       
    53 
       
    54 procedure CheckHHDamage(Gear: PGear);
       
    55 begin
       
    56 if Gear.dY > 0.35 then Gear.Damage:= Gear.Damage + round(25 * (abs(Gear.dY) - 0.35));
       
    57 end;
       
    58 
       
    59 ////////////////////////////////////////////////////////////////////////////////
       
    60 ////////////////////////////////////////////////////////////////////////////////
       
    61 procedure CalcRotationDirAngle(Gear: PGear);
       
    62 var dAngle: real;
       
    63 begin
       
    64 dAngle:= (abs(Gear.dX) + abs(Gear.dY))*0.1;
       
    65 if Gear.dX >= 0 then Gear.DirAngle:= Gear.DirAngle + dAngle
       
    66                 else Gear.DirAngle:= Gear.DirAngle - dAngle;
       
    67 if Gear.DirAngle < 0 then Gear.DirAngle:= Gear.DirAngle + 16
       
    68 else if Gear.DirAngle >= 16 then Gear.DirAngle:= Gear.DirAngle - 16
       
    69 end;
       
    70 
       
    71 ////////////////////////////////////////////////////////////////////////////////
       
    72 procedure doStepDrowningGear(Gear: PGear);
       
    73 begin
       
    74 AllInactive:= false;
       
    75 Gear.Y:= Gear.Y + cDrownSpeed;
       
    76 if round(Gear.Y) > Gear.HalfHeight + cWaterLine + 48 + cVisibleWater then DeleteGear(Gear)
       
    77 end;
       
    78 
       
    79 ////////////////////////////////////////////////////////////////////////////////
       
    80 procedure doStepFallingGear(Gear: PGear);
       
    81 var b: boolean;
       
    82 begin
       
    83 if TestCollisionYwithGear(Gear, Sign(Gear.dY)) then
       
    84    begin
       
    85    Gear.dX:=   Gear.dX * Gear.Friction;
       
    86    Gear.dY:= - Gear.dY * Gear.Elasticity;
       
    87    b:= false
       
    88    end else b:= true;
       
    89 if TestCollisionXwithGear(Gear, Sign(Gear.dX)) then
       
    90    begin
       
    91    Gear.dX:= - Gear.dX * Gear.Elasticity;
       
    92 //   Gear.dY:=   Gear.dY;
       
    93    b:= false
       
    94    end;
       
    95 if b then
       
    96    begin
       
    97    Gear.dY:= Gear.dY + cGravity;
       
    98    Gear.State:= Gear.State and not gstCollision
       
    99    end else
       
   100    begin
       
   101    if sqr(Gear.dX) + sqr(Gear.dY) < 0.00001 then
       
   102       if (Gear.Timer = 0) then Gear.Active:= false
       
   103                           else begin
       
   104                           Gear.dX:= 0;
       
   105                           Gear.dY:= 0
       
   106                           end;
       
   107    Gear.State:= Gear.State or gstCollision
       
   108    end;
       
   109 Gear.X:= Gear.X + Gear.dX;
       
   110 Gear.Y:= Gear.Y + Gear.dY;
       
   111 CheckGearDrowning(Gear);
       
   112 if (sqr(Gear.dX) + sqr(Gear.dY) < 0.003) then Gear.State:= Gear.State and not gstMoving
       
   113                                          else Gear.State:= Gear.State or      gstMoving
       
   114 end;
       
   115 
       
   116 ////////////////////////////////////////////////////////////////////////////////
       
   117 procedure doStepCloud(Gear: PGear);
       
   118 begin
       
   119 Gear.X:= Gear.X + cWindSpeed * 200 + Gear.dX;
       
   120 if Gear.X < -cScreenWidth-256 then Gear.X:= cScreenWidth + 2048 else
       
   121 if Gear.X > cScreenWidth + 2048 then Gear.X:= -cScreenWidth - 256
       
   122 end;
       
   123 
       
   124 ////////////////////////////////////////////////////////////////////////////////
       
   125 procedure doStepBomb(Gear: PGear);
       
   126 begin
       
   127 AllInactive:= false;
       
   128 doStepFallingGear(Gear);
       
   129 dec(Gear.Timer);
       
   130 if Gear.Timer = 0 then
       
   131    begin
       
   132    doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
       
   133    DeleteGear(Gear);
       
   134    SetAllToActive;
       
   135    exit
       
   136    end;
       
   137 CalcRotationDirAngle(Gear);
       
   138 if (Gear.State and (gstCollision or gstMoving)) = (gstCollision or gstMoving) then PlaySound(sndGrenadeImpact)
       
   139 end;
       
   140 
       
   141 ////////////////////////////////////////////////////////////////////////////////
       
   142 procedure doStepGrenade(Gear: PGear);
       
   143 begin
       
   144 AllInactive:= false;
       
   145 Gear.dX:= Gear.dX + cWindSpeed;
       
   146 doStepFallingGear(Gear);
       
   147 if (Gear.State and gstCollision) <> 0 then
       
   148    begin
       
   149    doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
       
   150    DeleteGear(Gear);
       
   151    SetAllToActive;
       
   152    exit
       
   153    end;
       
   154 if (GameTicks and $3F) = 0 then
       
   155    AddGear(round(Gear.X), round(Gear.Y), gtSmokeTrace, 0)
       
   156 end;
       
   157 
       
   158 ////////////////////////////////////////////////////////////////////////////////
       
   159 procedure doStepHealthTag(Gear: PGear);
       
   160 begin
       
   161 AllInactive:= false;
       
   162 dec(Gear.Timer);
       
   163 Gear.Y:= Gear.Y - 0.07;
       
   164 if Gear.Timer = 0 then
       
   165    begin
       
   166    PHedgehog(Gear.Hedgehog).Gear.Active:= true;
       
   167    DeleteGear(Gear)
       
   168    end
       
   169 end;
       
   170 
       
   171 ////////////////////////////////////////////////////////////////////////////////
       
   172 procedure doStepGrave(Gear: PGear);
       
   173 begin
       
   174 AllInactive:= false;
       
   175 if Gear.dY < 0 then
       
   176    if TestCollisionY(Gear, -1) then Gear.dY:= 0;
       
   177 
       
   178 if Gear.dY >=0 then
       
   179    if TestCollisionY(Gear, 1) then
       
   180       begin
       
   181       Gear.dY:= - Gear.dY * Gear.Elasticity;
       
   182       if Gear.dY > - 0.001 then
       
   183          begin
       
   184          Gear.Active:= false;
       
   185          exit
       
   186          end else if Gear.dY < - 0.03 then PlaySound(sndGraveImpact)
       
   187       end;
       
   188 Gear.Y:= Gear.Y + Gear.dY;
       
   189 CheckGearDrowning(Gear);
       
   190 Gear.dY:= Gear.dY + cGravity
       
   191 end;
       
   192 
       
   193 ////////////////////////////////////////////////////////////////////////////////
       
   194 procedure doStepUFOWork(Gear: PGear);
       
   195 var t: real;
       
   196 begin
       
   197 AllInactive:= false;
       
   198 t:= sqrt(sqr(Gear.dX) + sqr(Gear.dY));
       
   199 Gear.dX:= Gear.Elasticity * (Gear.dX + 0.000004 * (TargetPoint.X - trunc(Gear.X)));
       
   200 Gear.dY:= Gear.Elasticity * (Gear.dY + 0.000004 * (TargetPoint.Y - trunc(Gear.Y)));
       
   201 t:= t / (sqrt(sqr(Gear.dX) + sqr(Gear.dY)));
       
   202 Gear.dX:= Gear.dX * t;
       
   203 Gear.dY:= Gear.dY * t;
       
   204 Gear.X:= Gear.X + Gear.dX;
       
   205 Gear.Y:= Gear.Y + Gear.dY;
       
   206 CheckCollision(Gear);
       
   207 dec(Gear.Timer);
       
   208 if ((Gear.State and gstCollision) <> 0) or (Gear.Timer = 0) then
       
   209    begin
       
   210    doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
       
   211    DeleteGear(Gear);
       
   212    SetAllToActive
       
   213    end;
       
   214 end;
       
   215 
       
   216 procedure doStepUFO(Gear: PGear);
       
   217 begin
       
   218 AllInactive:= false;
       
   219 Gear.X:= Gear.X + Gear.dX;
       
   220 Gear.Y:= Gear.Y + Gear.dY;
       
   221 Gear.dY:= Gear.dY + cGravity;
       
   222 CheckCollision(Gear);
       
   223 if (Gear.State and gstCollision) <> 0 then
       
   224    begin
       
   225    doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
       
   226    DeleteGear(Gear);
       
   227    SetAllToActive;
       
   228    exit
       
   229    end;
       
   230 dec(Gear.Timer);
       
   231 if Gear.Timer = 0 then
       
   232    begin
       
   233    Gear.Timer:= 5000;
       
   234    Gear.doStep:= doStepUFOWork
       
   235    end;
       
   236 end;
       
   237 
       
   238 ////////////////////////////////////////////////////////////////////////////////
       
   239 procedure doStepShotgunShot(Gear: PGear);
       
   240 var i: LongWord;
       
   241 begin
       
   242 AllInactive:= false;
       
   243 if Gear.Timer > 0 then
       
   244    begin
       
   245    dec(Gear.Timer);
       
   246    if Gear.Timer = 1 then PlaySound(sndShotgunFire);
       
   247    exit
       
   248    end;
       
   249 i:= 200;
       
   250 repeat
       
   251 Gear.X:= Gear.X + Gear.dX;
       
   252 Gear.Y:= Gear.Y + Gear.dY;
       
   253 CheckCollision(Gear);
       
   254 if (Gear.State and gstCollision) <> 0 then
       
   255    begin
       
   256    doMakeExplosion(round(Gear.X), round(Gear.Y), 25, EXPLAllDamageInRadius);
       
   257    DeleteGear(Gear);
       
   258    SetAllToActive;
       
   259    exit
       
   260    end;
       
   261 dec(i)
       
   262 until i = 0;
       
   263 if (Gear.X < 0) or (Gear.Y < 0) or (Gear.X > 2048) or (Gear.Y > 1024) then
       
   264    DeleteGear(Gear)
       
   265 end;
       
   266 
       
   267 ////////////////////////////////////////////////////////////////////////////////
       
   268 procedure doStepActionTimer(Gear: PGear);
       
   269 begin
       
   270 dec(Gear.Timer);
       
   271 case Gear.State of
       
   272      gtsStartGame: begin
       
   273                    AllInactive:= false;
       
   274                    if Gear.Timer > 0 then exit;
       
   275                    AddCaption('Let''s fight!', $FFFFFF, capgrpStartGame);
       
   276                    DeleteGear(Gear)
       
   277                    end;
       
   278      end;
       
   279 end;
       
   280 
       
   281 ////////////////////////////////////////////////////////////////////////////////
       
   282 procedure doStepPickHammerWork(Gear: PGear);
       
   283 var i, ei: integer;
       
   284     HHGear: PGear;
       
   285 begin
       
   286 Allinactive:= false;
       
   287 dec(Gear.Timer);
       
   288 if (Gear.Timer = 0)or((Gear.Message and gm_Destroy) <> 0) then
       
   289    begin
       
   290    DeleteGear(Gear);
       
   291    AfterAttack;
       
   292    SetAllToActive;
       
   293    exit
       
   294    end;
       
   295 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
       
   296 if (Gear.Timer and $3F) = 0 then
       
   297    begin
       
   298    i:= round(Gear.X) - Gear.HalfWidth  - GetRandom(2);
       
   299    ei:= round(Gear.X) + Gear.HalfWidth + GetRandom(2);
       
   300    while i <= ei do
       
   301          begin
       
   302          doMakeExplosion(i, round(Gear.Y) + 3, 3, 0);
       
   303          inc(i, 1)
       
   304          end;
       
   305    SetAllToActive;
       
   306    Gear.X:= Gear.X + Gear.dX;
       
   307    Gear.Y:= Gear.Y + 1.9
       
   308    end;
       
   309 if TestCollisionYwithGear(Gear, 1) then
       
   310    begin
       
   311    Gear.dY:= 0;
       
   312    HHGear.dX:= 0.0000001 * Sign(PGear(Gear.Hedgehog).dX);
       
   313    HHGear.dY:= 0;
       
   314    end else
       
   315    begin
       
   316    Gear.dY:= Gear.dY + cGravity;
       
   317    Gear.Y:= Gear.Y + Gear.dY;
       
   318    if Gear.Y > 1024 then Gear.Timer:= 1
       
   319    end;
       
   320 
       
   321 Gear.X:= Gear.X + HHGear.dX;
       
   322 HHGear.X:= Gear.X;
       
   323 HHGear.Y:= Gear.Y - cHHHalfHeight;
       
   324 
       
   325 if (Gear.Message and gm_Attack) <> 0 then
       
   326    if (Gear.State and gsttmpFlag) <> 0 then Gear.Timer:= 1 else else
       
   327    if (Gear.State and gsttmpFlag) = 0 then Gear.State:= Gear.State or gsttmpFlag;
       
   328 if ((Gear.Message and gm_Left) <> 0) then Gear.dX:= -0.3 else
       
   329    if ((Gear.Message and gm_Right) <> 0) then Gear.dX:= 0.3
       
   330                                          else Gear.dX:= 0;
       
   331 end;
       
   332 
       
   333 procedure doStepPickHammer(Gear: PGear);
       
   334 var i, y: integer;
       
   335     ar: TRangeArray;
       
   336 begin
       
   337 i:= 0;
       
   338 y:= round(Gear.Y) - cHHHalfHeight*2;
       
   339 while y < round(Gear.Y) do
       
   340    begin
       
   341    ar[i].Left := round(Gear.X) - Gear.HalfWidth - GetRandom(2);
       
   342    ar[i].Right:= round(Gear.X) + Gear.HalfWidth + GetRandom(2);
       
   343    inc(y, 2);
       
   344    inc(i)
       
   345    end;
       
   346 DrawLineExplosions(@ar, 3, round(Gear.Y) - cHHHalfHeight*2, 2, Pred(i));
       
   347 Gear.dY:= PHedgehog(Gear.Hedgehog).Gear.dY;
       
   348 doStepPickHammerWork(Gear);
       
   349 Gear.doStep:= doStepPickHammerWork
       
   350 end;
       
   351 
       
   352 ////////////////////////////////////////////////////////////////////////////////
       
   353 procedure doStepRopeWork(Gear: PGear);
       
   354 const pidiv2: real = pi/2;
       
   355       flCheck: boolean = false;
       
   356 var HHGear: PGear;
       
   357     len, cs, cc, tx, ty: real;
       
   358     lx, ly: integer;
       
   359 
       
   360     procedure DeleteMe;
       
   361     begin
       
   362       with HHGear^ do
       
   363            begin
       
   364            Message:= Message and not gm_Attack;
       
   365            State:= State or gstFalling;
       
   366            end;
       
   367       DeleteGear(Gear);
       
   368       OnUsedAmmo(PHedgehog(Gear.Hedgehog)^.Ammo);
       
   369       ApplyAmmoChanges(PHedgehog(Gear.Hedgehog))
       
   370     end;
       
   371 
       
   372 begin
       
   373 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
       
   374 if (HHGear.State and gstHHDriven) = 0 then
       
   375    begin
       
   376    DeleteMe;
       
   377    exit
       
   378    end;
       
   379 Gear.dX:= HHGear.X - Gear.X;
       
   380 Gear.dY:= HHGear.Y - Gear.Y;
       
   381 
       
   382 if (Gear.Message and gm_Left  <> 0) then HHGear.dX:= HHGear.dX - 0.0002 else
       
   383 if (Gear.Message and gm_Right <> 0) then HHGear.dX:= HHGear.dX + 0.0002;
       
   384 
       
   385 if not TestCollisionYwithGear(HHGear, 1) then HHGear.dY:= HHGear.dY + cGravity;
       
   386 
       
   387 HHGear.DirAngle:= arctan(Gear.dY + HHGear.dY, Gear.dX + HHGear.dX);
       
   388 cs:= sin(HHGear.DirAngle);
       
   389 cc:= cos(HHGear.DirAngle);
       
   390 
       
   391 flCheck:= not flCheck;
       
   392 if flCheck then  // check whether rope needs dividing
       
   393    begin
       
   394    len:= Gear.Elasticity - 20;
       
   395    while len > 5 do
       
   396          begin
       
   397          tx:= cc*len;
       
   398          ty:= cs*len;
       
   399 //         if   TestCollisionXwithXYShift(Gear, round(tx), round(ty), Sign(HHGear.dX))
       
   400 ///           or TestCollisionYwithXYShift(Gear, round(tx), round(ty), Sign(HHGear.dY)) then
       
   401          lx:= round(Gear.X + tx) + sign(HHGear.dX);
       
   402          ly:= round(Gear.Y + ty) + sign(HHGear.dY);
       
   403          if ((ly and $FFFFFC00) = 0) and ((lx and $FFFFF800) = 0)and (Land[ly, lx] <> 0) then
       
   404            begin
       
   405            with RopePoints.ar[RopePoints.Count] do
       
   406                 begin
       
   407                 X:= Gear.X;
       
   408                 Y:= Gear.Y;
       
   409                 if RopePoints.Count = 0 then RopePoints.HookAngle:= DxDy2Angle32(Gear.dY, Gear.dX);
       
   410                 b:= (cc * HHGear.dY) > (cs * HHGear.dX);
       
   411                 dLen:= len
       
   412                 end;
       
   413            Gear.X:= Gear.X + tx;
       
   414            Gear.Y:= Gear.Y + ty;
       
   415            inc(RopePoints.Count);
       
   416            Gear.Elasticity:= Gear.Elasticity - len;
       
   417            Gear.Friction:= Gear.Friction - len;
       
   418            break
       
   419            end;
       
   420          len:= len - 3
       
   421          end;
       
   422    end else
       
   423    if RopePoints.Count > 0 then // check whether the last dividing point could be removed
       
   424       begin
       
   425       tx:= RopePoints.ar[Pred(RopePoints.Count)].X;
       
   426       ty:= RopePoints.ar[Pred(RopePoints.Count)].Y;
       
   427       if RopePoints.ar[Pred(RopePoints.Count)].b xor ((tx - Gear.X) * (ty - HHGear.Y) > (tx - HHGear.X) * (ty - Gear.Y)) then
       
   428          begin
       
   429          dec(RopePoints.Count);
       
   430          Gear.X:=RopePoints.ar[RopePoints.Count].X;
       
   431          Gear.Y:=RopePoints.ar[RopePoints.Count].Y;
       
   432          Gear.Elasticity:= Gear.Elasticity + RopePoints.ar[RopePoints.Count].dLen;
       
   433          Gear.Friction:= Gear.Friction + RopePoints.ar[RopePoints.Count].dLen
       
   434          end
       
   435       end;
       
   436 
       
   437 Gear.dX:= HHGear.X - Gear.X;
       
   438 Gear.dY:= HHGear.Y - Gear.Y;
       
   439 HHGear.DirAngle:= arctan(Gear.dY + HHGear.dY, Gear.dX + HHGear.dX);
       
   440 cs:= sin(HHGear.DirAngle);
       
   441 cc:= cos(HHGear.DirAngle);
       
   442 
       
   443 HHGear.dX:= HHGear.X;
       
   444 HHGear.dY:= HHGear.Y;
       
   445 
       
   446 if ((Gear.Message and gm_Down) <> 0) and (Gear.Elasticity < Gear.Friction) then
       
   447    if not (TestCollisionXwithGear(HHGear, Sign(Gear.dX))
       
   448         or TestCollisionYwithGear(HHGear, Sign(Gear.dY))) then Gear.Elasticity:= Gear.Elasticity + 0.3;
       
   449 
       
   450 if ((Gear.Message and gm_Up) <> 0) and (Gear.Elasticity > 30) then
       
   451    if not (TestCollisionXwithGear(HHGear, -Sign(Gear.dX))
       
   452         or TestCollisionYwithGear(HHGear, -Sign(Gear.dY))) then Gear.Elasticity:= Gear.Elasticity - 0.3;
       
   453 
       
   454 HHGear.X:= Gear.X + cc*Gear.Elasticity;
       
   455 HHGear.Y:= Gear.Y + cs*Gear.Elasticity;
       
   456 
       
   457 HHGear.dX:= HHGear.X - HHGear.dX;
       
   458 HHGear.dY:= HHGear.Y - HHGear.dY;
       
   459 
       
   460 if TestCollisionXwithGear(HHGear, Sign(HHGear.dX)) then
       
   461    HHGear.dX:= -0.9 * HHGear.dX;
       
   462 if TestCollisionYwithGear(HHGear, Sign(HHGear.dY)) then
       
   463    HHGear.dY:= -0.9 * HHGear.dY;
       
   464 
       
   465 if (Gear.Message and gm_Attack) <> 0 then
       
   466    if (Gear.State and gsttmpFlag) <> 0 then DeleteMe else
       
   467 else if (Gear.State and gsttmpFlag) = 0 then Gear.State:= Gear.State or gsttmpFlag;
       
   468 end;
       
   469 
       
   470 
       
   471 procedure doStepRopeAttach(Gear: PGear);
       
   472 var HHGear: PGear;
       
   473     tx, ty, tt: real;
       
   474 begin
       
   475 Gear.X:= Gear.X + Gear.dX;
       
   476 Gear.Y:= Gear.Y + Gear.dY;
       
   477 Gear.Elasticity:= Gear.Elasticity + 1.0;
       
   478 HHGear:= PHedgehog(Gear.Hedgehog)^.Gear;
       
   479 if (HHGear.State and gstFalling) <> 0 then
       
   480    if HHTestCollisionYwithGear(HHGear, 1) then
       
   481       begin
       
   482       HHGear.dY:= 0;
       
   483       CheckHHDamage(HHGear);
       
   484       HHGear.State:= HHGear.State and not (gstFalling or gstHHJumping);
       
   485       end else
       
   486       begin
       
   487       if TestCollisionXwithGear(HHGear, Sign(HHGear.dX)) then HHGear.dX:= 0.0000001 * Sign(HHGear.dX);
       
   488       HHGear.X:= HHGear.X + HHGear.dX;
       
   489       HHGear.Y:= HHGear.Y + HHGear.dY;
       
   490       Gear.X:= Gear.X + HHGear.dX;
       
   491       Gear.Y:= Gear.Y + HHGear.dY;
       
   492       HHGear.dY:= HHGear.dY + cGravity;
       
   493       tt:= Gear.Elasticity;
       
   494       tx:= 0;
       
   495       ty:= 0;
       
   496       while tt > 20 do
       
   497             begin
       
   498             if  TestCollisionXwithXYShift(Gear, round(tx), round(ty), Sign(Gear.dX))
       
   499              or TestCollisionYwithXYShift(Gear, round(tx), round(ty), Sign(Gear.dY)) then
       
   500                 begin
       
   501                 Gear.X:= Gear.X + tx;
       
   502                 Gear.Y:= Gear.Y + ty;
       
   503                 Gear.Elasticity:= tt;
       
   504                 Gear.doStep:= doStepRopeWork;
       
   505                 with HHGear^ do State:= State and not gstAttacking;
       
   506                 tt:= 0
       
   507                 end;
       
   508             tx:= tx - Gear.dX - Gear.dX;
       
   509             ty:= ty - Gear.dY - Gear.dY;
       
   510             tt:= tt - 2.0;
       
   511             end;
       
   512       end;
       
   513 CheckCollision(Gear);
       
   514 if (Gear.State and gstCollision) <> 0 then
       
   515    begin
       
   516    Gear.doStep:= doStepRopeWork;
       
   517    with HHGear^ do State:= State and not gstAttacking;
       
   518    if Gear.Elasticity < 10 then
       
   519       Gear.Elasticity:= 10000;
       
   520    end;
       
   521 
       
   522 if (Gear.Elasticity >= Gear.Friction) or ((Gear.Message and gm_Attack) = 0) then
       
   523    begin
       
   524    with PHedgehog(Gear.Hedgehog).Gear^ do
       
   525         begin
       
   526         State:= State and not gstAttacking;
       
   527         Message:= Message and not gm_Attack
       
   528         end;
       
   529    DeleteGear(Gear)
       
   530    end
       
   531 end;
       
   532 
       
   533 procedure doStepRope(Gear: PGear);
       
   534 begin
       
   535 Gear.doStep:= doStepRopeAttach
       
   536 end;
       
   537 
       
   538 ////////////////////////////////////////////////////////////////////////////////
       
   539 procedure doStepSmokeTrace(Gear: PGear);
       
   540 begin
       
   541 inc(Gear.Timer);
       
   542 if Gear.Timer > 64 then
       
   543    begin
       
   544    Gear.Timer:= 0;
       
   545    dec(Gear.Tag)
       
   546    end;
       
   547 Gear.dX:= Gear.dX + cWindSpeed;
       
   548 Gear.X:= Gear.X + Gear.dX;
       
   549 if Gear.Tag = 0 then DeleteGear(Gear)
       
   550 end;