hedgewars/uGearsHandlersMess.pas
changeset 14572 34e810295d08
parent 14570 0da43a3d5500
child 14574 6e5cda26f676
equal deleted inserted replaced
14571:1d3dc553829c 14572:34e810295d08
   356 
   356 
   357 ////////////////////////////////////////////////////////////////////////////////
   357 ////////////////////////////////////////////////////////////////////////////////
   358 procedure doStepFallingGear(Gear: PGear);
   358 procedure doStepFallingGear(Gear: PGear);
   359 var
   359 var
   360     isFalling: boolean;
   360     isFalling: boolean;
   361     //tmp: QWord;
       
   362     tX, tdX, tdY: hwFloat;
   361     tX, tdX, tdY: hwFloat;
   363     collV, collH, gX, gY: LongInt;
   362     collV, collH, gX, gY: LongInt;
   364     land, xland: word;
   363     land, xland: word;
   365 begin
   364 begin
   366     tX:= Gear^.X;
   365     tX:= Gear^.X;
   477     else if Gear^.AdvBounce = 1 then
   476     else if Gear^.AdvBounce = 1 then
   478         begin
   477         begin
   479         xland:= TestCollisionXwithGear(Gear, -hwSign(Gear^.dX));
   478         xland:= TestCollisionXwithGear(Gear, -hwSign(Gear^.dX));
   480         if xland <> 0 then collH := -hwSign(Gear^.dX)
   479         if xland <> 0 then collH := -hwSign(Gear^.dX)
   481         end;
   480         end;
   482     //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then
       
   483     if (collV <> 0) and (collH <> 0) and
   481     if (collV <> 0) and (collH <> 0) and
   484        (((Gear^.AdvBounce=1) and ((collV=-1) or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)))) then
   482        (((Gear^.AdvBounce=1) and ((collV=-1) or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)))) then
   485  //or ((xland or land) and lfBouncy <> 0)) then
       
   486         begin
   483         begin
   487         if (xland or land) and lfBouncy = 0 then
   484         if (xland or land) and lfBouncy = 0 then
   488             begin
   485             begin
   489             Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
   486             Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
   490             Gear^.dY := tdX*Gear^.Elasticity;
   487             Gear^.dY := tdX*Gear^.Elasticity;
   533         end;
   530         end;
   534 
   531 
   535     Gear^.X := Gear^.X + Gear^.dX;
   532     Gear^.X := Gear^.X + Gear^.dX;
   536     Gear^.Y := Gear^.Y + Gear^.dY;
   533     Gear^.Y := Gear^.Y + Gear^.dY;
   537     CheckGearDrowning(Gear);
   534     CheckGearDrowning(Gear);
   538     //if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _0_0002) and
       
   539     if (not isFalling) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_02.QWordValue) then
   535     if (not isFalling) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_02.QWordValue) then
   540         Gear^.State := Gear^.State and (not gstMoving)
   536         Gear^.State := Gear^.State and (not gstMoving)
   541     else
   537     else
   542         Gear^.State := Gear^.State or gstMoving;
   538         Gear^.State := Gear^.State or gstMoving;
   543 
   539 
   711         PlaySound(sndMolotov);
   707         PlaySound(sndMolotov);
   712         gX := hwRound(Gear^.X);
   708         gX := hwRound(Gear^.X);
   713         gY := hwRound(Gear^.Y);
   709         gY := hwRound(Gear^.Y);
   714         for i:= 0 to 4 do
   710         for i:= 0 to 4 do
   715             begin
   711             begin
   716             (*glass:= AddVisualGear(gx+random(7)-3, gy+random(5)-2, vgtEgg);
       
   717             if glass <> nil then
       
   718                 begin
       
   719                 glass^.Frame:= 2;
       
   720                 glass^.Tint:= $41B83ED0 - i * $10081000;
       
   721                 glass^.dX:= 1/(10*(random(11)-5));
       
   722                 glass^.dY:= -1/(random(4)+5);
       
   723                 end;*)
       
   724             glass:= AddVisualGear(gx+random(7)-3, gy+random(7)-3, vgtStraightShot);
   712             glass:= AddVisualGear(gx+random(7)-3, gy+random(7)-3, vgtStraightShot);
   725             if glass <> nil then
   713             if glass <> nil then
   726                 with glass^ do
   714                 with glass^ do
   727                     begin
   715                     begin
   728                     Frame:= 2;
   716                     Frame:= 2;
   866             if DirAngle < 0 then
   854             if DirAngle < 0 then
   867                 DirAngle := DirAngle + 360
   855                 DirAngle := DirAngle + 360
   868             else if 360 < DirAngle then
   856             else if 360 < DirAngle then
   869                 DirAngle := DirAngle - 360;
   857                 DirAngle := DirAngle - 360;
   870             end;
   858             end;
   871 (*
       
   872 We aren't using frametick right now, so just a waste of cycles.
       
   873         inc(Health, 8);
       
   874         if longword(Health) > vobFrameTicks then
       
   875             begin
       
   876             dec(Health, vobFrameTicks);
       
   877             inc(Timer);
       
   878             if Timer = vobFramesCount then
       
   879                 Timer:= 0
       
   880             end;
       
   881 *)
       
   882     // move back to cloud layer
   859     // move back to cloud layer
   883         if CheckCoordInWater(xx, yy) then
   860         if CheckCoordInWater(xx, yy) then
   884             move:= true
   861             move:= true
   885         else if (xx > snowRight) or (xx < snowLeft) then
   862         else if (xx > snowRight) or (xx < snowLeft) then
   886             move:=true
   863             move:=true
  2394             dmg:= hwRound(dxdy * _50);
  2371             dmg:= hwRound(dxdy * _50);
  2395             inc(Gear^.Damage, dmg);
  2372             inc(Gear^.Damage, dmg);
  2396             ScriptCall('onGearDamage', Gear^.UID, dmg)
  2373             ScriptCall('onGearDamage', Gear^.UID, dmg)
  2397             end;
  2374             end;
  2398         CalcRotationDirAngle(Gear);
  2375         CalcRotationDirAngle(Gear);
  2399         //CheckGearDrowning(Gear)
       
  2400         end
  2376         end
  2401     else
  2377     else
  2402         begin
  2378         begin
  2403         Gear^.State := Gear^.State or gsttmpFlag;
  2379         Gear^.State := Gear^.State or gsttmpFlag;
  2404         AddCI(Gear)
  2380         AddCI(Gear)
  2405         end;
  2381         end;
  2406 
       
  2407 (*
       
  2408 Attempt to make a barrel knock itself over an edge.  Would need more checks to avoid issues like burn damage
       
  2409     begin
       
  2410     x:= hwRound(Gear^.X);
       
  2411     y:= hwRound(Gear^.Y);
       
  2412     if (((y+1) and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) then
       
  2413         if (Land[y+1, x] = 0) then
       
  2414             begin
       
  2415             if (((y+1) and LAND_HEIGHT_MASK) = 0) and (((x+Gear^.Radius-2) and LAND_WIDTH_MASK) = 0) and (Land[y+1, x+Gear^.Radius-2] = 0) then
       
  2416                 Gear^.dX:= -_0_08
       
  2417             else if (((y+1 and LAND_HEIGHT_MASK)) = 0) and (((x-(Gear^.Radius-2)) and LAND_WIDTH_MASK) = 0) and (Land[y+1, x-(Gear^.Radius-2)] = 0) then
       
  2418                 Gear^.dX:= _0_08;
       
  2419             end;
       
  2420     if Gear^.dX.QWordValue = 0 then AddCI(Gear)
       
  2421     end; *)
       
  2422 
  2382 
  2423     if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  2383     if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  2424         Gear^.dY := _0;
  2384         Gear^.dY := _0;
  2425     if hwAbs(Gear^.dX) < _0_001 then
  2385     if hwAbs(Gear^.dX) < _0_001 then
  2426         Gear^.dX := _0;
  2386         Gear^.dX := _0;
  2488         exit
  2448         exit
  2489         end;
  2449         end;
  2490 
  2450 
  2491     if k = gtExplosives then
  2451     if k = gtExplosives then
  2492         begin
  2452         begin
  2493         //if V > _0_03 then Gear^.State:= Gear^.State or gstAnimation;
       
  2494         if (hwAbs(Gear^.dX) > _0_15) or ((hwAbs(Gear^.dY) > _0_15) and (hwAbs(Gear^.dX) > _0_02)) then
  2453         if (hwAbs(Gear^.dX) > _0_15) or ((hwAbs(Gear^.dY) > _0_15) and (hwAbs(Gear^.dX) > _0_02)) then
  2495             begin
  2454             begin
  2496             Gear^.doStep := @doStepRollingBarrel;
  2455             Gear^.doStep := @doStepRollingBarrel;
  2497             exit;
  2456             exit;
  2498             end
  2457             end
  2568             if Gear^.dY > - _0_001 then
  2527             if Gear^.dY > - _0_001 then
  2569                 Gear^.dY := _0
  2528                 Gear^.dY := _0
  2570             else if Gear^.dY < - _0_03 then
  2529             else if Gear^.dY < - _0_03 then
  2571                 PlaySound(Gear^.ImpactSound);
  2530                 PlaySound(Gear^.ImpactSound);
  2572             end;
  2531             end;
  2573         //if Gear^.dY > - _0_001 then Gear^.dY:= _0
       
  2574         CheckGearDrowning(Gear);
  2532         CheckGearDrowning(Gear);
  2575         end;
  2533         end;
  2576 
  2534 
  2577     if (Gear^.dY.QWordValue = 0) then
  2535     if (Gear^.dY.QWordValue = 0) then
  2578         AddCI(Gear)
  2536         AddCI(Gear)
  2739         else begin
  2697         else begin
  2740             if Gear^.dX.QWordValue > _0_01.QWordValue then
  2698             if Gear^.dX.QWordValue > _0_01.QWordValue then
  2741                     Gear^.dX := Gear^.dX * _0_995;
  2699                     Gear^.dX := Gear^.dX * _0_995;
  2742 
  2700 
  2743             Gear^.dY := Gear^.dY + cGravity;
  2701             Gear^.dY := Gear^.dY + cGravity;
  2744             // if sticky then Gear^.dY := Gear^.dY + cGravity;
       
  2745 
  2702 
  2746             if Gear^.dY.QWordValue > _0_2.QWordValue then
  2703             if Gear^.dY.QWordValue > _0_2.QWordValue then
  2747                 Gear^.dY := Gear^.dY * _0_995;
  2704                 Gear^.dY := Gear^.dY * _0_995;
  2748 
  2705 
  2749             //if sticky then Gear^.X := Gear^.X + Gear^.dX else
       
  2750             Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640;
  2706             Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640;
  2751             Gear^.Y := Gear^.Y + Gear^.dY;
  2707             Gear^.Y := Gear^.Y + Gear^.dY;
  2752         end;
  2708         end;
  2753 
  2709 
  2754         gX := hwRound(Gear^.X);
  2710         gX := hwRound(Gear^.X);
  2819                     Gear^.dX:= tdX;
  2775                     Gear^.dX:= tdX;
  2820                     Gear^.dY:= tdY;
  2776                     Gear^.dY:= tdY;
  2821                     Gear^.Radius := 1;
  2777                     Gear^.Radius := 1;
  2822                     end
  2778                     end
  2823                 else if ((GameTicks and $3) = 3) then
  2779                 else if ((GameTicks and $3) = 3) then
  2824                     doMakeExplosion(gX, gY, Gear^.Boom * 4, Gear^.Hedgehog, 0);//, EXPLNoDamage);
  2780                     doMakeExplosion(gX, gY, Gear^.Boom * 4, Gear^.Hedgehog, 0);
  2825 
  2781 
  2826                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2782                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2827                     for i:= Random(2) downto 0 do
  2783                     for i:= Random(2) downto 0 do
  2828                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2784                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2829 
  2785 
  2916     HHGear: PGear;
  2872     HHGear: PGear;
  2917 begin
  2873 begin
  2918     AllInactive := false;
  2874     AllInactive := false;
  2919     HHGear := Gear^.Hedgehog^.Gear;
  2875     HHGear := Gear^.Hedgehog^.Gear;
  2920     DeleteCI(HHGear);
  2876     DeleteCI(HHGear);
  2921     //HHGear^.X := int2hwFloat(hwRound(HHGear^.X)) - _0_5; WTF?
       
  2922     HHGear^.dX := SignAs(cLittle, Gear^.dX);
  2877     HHGear^.dX := SignAs(cLittle, Gear^.dX);
  2923 
  2878 
  2924     HHGear^.dY := - _0_3;
  2879     HHGear^.dY := - _0_3;
  2925 
  2880 
  2926     ClearHitOrder();
  2881     ClearHitOrder();
  3031             case Gear^.State of
  2986             case Gear^.State of
  3032                 0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  2987                 0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  3033                 1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, cBombsSpeed * Gear^.Tag, _0, 0);
  2988                 1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, cBombsSpeed * Gear^.Tag, _0, 0);
  3034                 2: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtNapalmBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  2989                 2: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtNapalmBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  3035                 3: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtDrill, gsttmpFlag, cBombsSpeed * Gear^.Tag, _0, Gear^.Timer + 1);
  2990                 3: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtDrill, gsttmpFlag, cBombsSpeed * Gear^.Tag, _0, Gear^.Timer + 1);
  3036             //4: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtWaterMelon, 0, cBombsSpeed *
       
  3037             //                 Gear^.Tag, _0, 5000);
       
  3038             end;
  2991             end;
  3039             Gear^.dX := Gear^.dX + int2hwFloat(Gear^.Damage * Gear^.Tag);
  2992             Gear^.dX := Gear^.dX + int2hwFloat(Gear^.Damage * Gear^.Tag);
  3040             if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then
  2993             if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then
  3041                 FollowGear^.State:= FollowGear^.State or gstSubmersible;
  2994                 FollowGear^.State:= FollowGear^.State or gstSubmersible;
  3042             end;
  2995             end;
  3324     AllInactive := false;
  3277     AllInactive := false;
  3325 
  3278 
  3326     if ((Gear^.Message and (not (gmSwitch or gmPrecise))) <> 0) or (TurnTimeLeft = 0) then
  3279     if ((Gear^.Message and (not (gmSwitch or gmPrecise))) <> 0) or (TurnTimeLeft = 0) then
  3327         begin
  3280         begin
  3328         hedgehog := Gear^.Hedgehog;
  3281         hedgehog := Gear^.Hedgehog;
  3329         //Msg := Gear^.Message and (not gmSwitch);
       
  3330         ApplyAmmoChanges(hedgehog^);
  3282         ApplyAmmoChanges(hedgehog^);
  3331 
  3283 
  3332         HHGear := CurrentHedgehog^.Gear;
  3284         HHGear := CurrentHedgehog^.Gear;
  3333         ApplyAmmoChanges(HHGear^.Hedgehog^);
  3285         ApplyAmmoChanges(HHGear^.Hedgehog^);
  3334         //HHGear^.Message := Msg;
       
  3335         DeleteGear(Gear);
  3286         DeleteGear(Gear);
  3336         exit
  3287         exit
  3337         end;
  3288         end;
  3338 
  3289 
  3339     if (Gear^.Message and gmSwitch) <> 0 then
  3290     if (Gear^.Message and gmSwitch) <> 0 then
  3488             DeleteGear(Gear);
  3439             DeleteGear(Gear);
  3489             exit;
  3440             exit;
  3490             end;
  3441             end;
  3491 
  3442 
  3492         inc(Gear^.Damage, 2);
  3443         inc(Gear^.Damage, 2);
  3493 
       
  3494         //  if TestCollisionXwithGear(HHGear, hwSign(Gear^.dX))
       
  3495         //      or TestCollisionYwithGear(HHGear, hwSign(Gear^.dY)) then inc(Gear^.Damage, 3);
       
  3496 
  3444 
  3497         dec(i)
  3445         dec(i)
  3498     until (i = 0)
  3446     until (i = 0)
  3499     or (Gear^.Damage > Gear^.Health);
  3447     or (Gear^.Damage > Gear^.Health);
  3500 
  3448 
  3635     Gear^.Tag := 0;
  3583     Gear^.Tag := 0;
  3636 
  3584 
  3637     if Gear^.Pos = 0 then
  3585     if Gear^.Pos = 0 then
  3638         begin
  3586         begin
  3639 ///////////// adapted from doMakeExplosion ///////////////////////////
  3587 ///////////// adapted from doMakeExplosion ///////////////////////////
  3640         //fX:= Gear^.X;
       
  3641         //fY:= Gear^.Y;
       
  3642         //fX.QWordValue:= fX.QWordValue and $FFFFFFFF00000000;
       
  3643         //fY.QWordValue:= fY.QWordValue and $FFFFFFFF00000000;
       
  3644         fX:= int2hwFloat(hwRound(Gear^.X));
  3588         fX:= int2hwFloat(hwRound(Gear^.X));
  3645         fY:= int2hwFloat(hwRound(Gear^.Y));
  3589         fY:= int2hwFloat(hwRound(Gear^.Y));
  3646         dmgBase:= Gear^.Boom shl 1 + cHHRadius div 2;
  3590         dmgBase:= Gear^.Boom shl 1 + cHHRadius div 2;
  3647         partyEpicness:= 0;
  3591         partyEpicness:= 0;
  3648         gi := GearsList;
  3592         gi := GearsList;
  3910                 else if Hedgehog^.Effects[heFrozen] > 255 then
  3854                 else if Hedgehog^.Effects[heFrozen] > 255 then
  3911                     Hedgehog^.Effects[heFrozen]:= 255
  3855                     Hedgehog^.Effects[heFrozen]:= 255
  3912         end ;
  3856         end ;
  3913     AfterAttack;
  3857     AfterAttack;
  3914     DeleteGear(Gear);
  3858     DeleteGear(Gear);
  3915 
       
  3916 (*
       
  3917     Gear^.X := Gear^.X + Gear^.dX;
       
  3918     Gear^.Y := Gear^.Y + Gear^.dY;
       
  3919     x := hwRound(Gear^.X);
       
  3920     y := hwRound(Gear^.Y);
       
  3921 
       
  3922     if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) then
       
  3923         if (Land[y, x] <> 0) then
       
  3924             begin
       
  3925             Gear^.dX.isNegative := not Gear^.dX.isNegative;
       
  3926             Gear^.dY.isNegative := not Gear^.dY.isNegative;
       
  3927             Gear^.dX := Gear^.dX * _1_5;
       
  3928             Gear^.dY := Gear^.dY * _1_5 - _0_3;
       
  3929             AmmoShove(Gear, 0, 40);
       
  3930             AfterAttack;
       
  3931             DeleteGear(Gear)
       
  3932             end
       
  3933         else
       
  3934     else
       
  3935         begin
       
  3936         AfterAttack;
       
  3937         DeleteGear(Gear)
       
  3938         end*)
       
  3939 end;
  3859 end;
  3940 
  3860 
  3941 procedure doStepSeductionWear(Gear: PGear);
  3861 procedure doStepSeductionWear(Gear: PGear);
  3942 var heart: PVisualGear;
  3862 var heart: PVisualGear;
  3943     HHGear: PGear;
  3863     HHGear: PGear;
  3968         begin
  3888         begin
  3969         heart:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot);
  3889         heart:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot);
  3970         if heart <> nil then
  3890         if heart <> nil then
  3971             with heart^ do
  3891             with heart^ do
  3972                 begin
  3892                 begin
  3973                 { // old calcs
       
  3974                 dx:= 0.001 * (random(200));
       
  3975                 dy:= 0.001 * (random(200));
       
  3976                 if random(2) = 0 then
       
  3977                     dx := -dx;
       
  3978                 if random(2) = 0 then
       
  3979                     dy := -dy;
       
  3980                 }
       
  3981 
  3893 
  3982                 // randomize speed in both directions
  3894                 // randomize speed in both directions
  3983                 dx:= 0.001 * (random(201));
  3895                 dx:= 0.001 * (random(201));
  3984                 dy:= 0.001 * (random(201));
  3896                 dy:= 0.001 * (random(201));
  3985 
  3897 
  4013 end;
  3925 end;
  4014 
  3926 
  4015 procedure doStepSeduction(Gear: PGear);
  3927 procedure doStepSeduction(Gear: PGear);
  4016 begin
  3928 begin
  4017     AllInactive := false;
  3929     AllInactive := false;
  4018     //DeleteCI(Gear^.Hedgehog^.Gear);
       
  4019     Gear^.doStep := @doStepSeductionWear
  3930     Gear^.doStep := @doStepSeductionWear
  4020 end;
  3931 end;
  4021 
  3932 
  4022 ////////////////////////////////////////////////////////////////////////////////
  3933 ////////////////////////////////////////////////////////////////////////////////
  4023 procedure doStepWaterUp(Gear: PGear);
  3934 procedure doStepWaterUp(Gear: PGear);
  4413     isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius);
  4324     isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius);
  4414     if Gear^.Pos > 0 then
  4325     if Gear^.Pos > 0 then
  4415         dec(Gear^.Pos);
  4326         dec(Gear^.Pos);
  4416     AllInactive := false;
  4327     AllInactive := false;
  4417     HHGear := Gear^.Hedgehog^.Gear;
  4328     HHGear := Gear^.Hedgehog^.Gear;
  4418     //dec(Gear^.Timer);
       
  4419     move := _0_2;
  4329     move := _0_2;
  4420     fuel := 50;
  4330     fuel := 50;
  4421 (*if (HHGear^.Message and gmPrecise) <> 0 then
       
  4422     begin
       
  4423     move:= _0_02;
       
  4424     fuel:= 5;
       
  4425     end;*)
       
  4426     if HHGear^.Message and gmPrecise <> 0 then
  4331     if HHGear^.Message and gmPrecise <> 0 then
  4427         HedgehogChAngle(HHGear)
  4332         HedgehogChAngle(HHGear)
  4428     else if (Gear^.Health > 0) or (Gear^.Health = JETPACK_FUEL_INFINITE) then
  4333     else if (Gear^.Health > 0) or (Gear^.Health = JETPACK_FUEL_INFINITE) then
  4429         begin
  4334         begin
  4430         if HHGear^.Message and gmUp <> 0 then
  4335         if HHGear^.Message and gmUp <> 0 then
  4518 
  4423 
  4519     if ((Gear^.State and gsttmpFlag) = 0)
  4424     if ((Gear^.State and gsttmpFlag) = 0)
  4520     or (HHGear^.dY < _0) then
  4425     or (HHGear^.dY < _0) then
  4521         doStepHedgehogMoving(HHGear);
  4426         doStepHedgehogMoving(HHGear);
  4522 
  4427 
  4523     if // (Gear^.Health = 0)
  4428     if
  4524         (HHGear^.Damage <> 0)
  4429         (HHGear^.Damage <> 0)
  4525         //or CheckGearDrowning(HHGear)
       
  4526         // drown if too deep under water
  4430         // drown if too deep under water
  4527         or (cWaterLine + cVisibleWater * 4 < hwRound(HHGear^.Y))
  4431         or (cWaterLine + cVisibleWater * 4 < hwRound(HHGear^.Y))
  4528         or (TurnTimeLeft = 0)
  4432         or (TurnTimeLeft = 0)
  4529         // allow brief ground touches - to be fair on this, might need another counter
  4433         // allow brief ground touches - to be fair on this, might need another counter
  4530         or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
  4434         or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
  4538                 end;
  4442                 end;
  4539             if (GetAmmoEntry(HHGear^.Hedgehog^, amJetpack)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) and (HHGear^.Hedgehog^.MultiShootAttacks = 0) then
  4443             if (GetAmmoEntry(HHGear^.Hedgehog^, amJetpack)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) and (HHGear^.Hedgehog^.MultiShootAttacks = 0) then
  4540                 HHGear^.Hedgehog^.CurAmmoType:= amJetpack;
  4444                 HHGear^.Hedgehog^.CurAmmoType:= amJetpack;
  4541             isCursorVisible := false;
  4445             isCursorVisible := false;
  4542             ApplyAmmoChanges(HHGear^.Hedgehog^);
  4446             ApplyAmmoChanges(HHGear^.Hedgehog^);
  4543         //    if Gear^.Tex <> nil then FreeTexture(Gear^.Tex);
       
  4544 
       
  4545 //    Gear^.Tex:= RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(round(Gear^.Health / 20)) + '%', cWhiteColor, fntSmall)
       
  4546 
       
  4547 //AddCaption(trmsg[sidFuel]+': '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate);
       
  4548             DeleteGear(Gear);
  4447             DeleteGear(Gear);
  4549             end
  4448             end
  4550 end;
  4449 end;
  4551 
  4450 
  4552 procedure doStepJetpack(Gear: PGear);
  4451 procedure doStepJetpack(Gear: PGear);
  4787     i: LongInt;
  4686     i: LongInt;
  4788 begin
  4687 begin
  4789     AllInactive := false;
  4688     AllInactive := false;
  4790     Gear^.dX := Gear^.dX;
  4689     Gear^.dX := Gear^.dX;
  4791     doStepFallingGear(Gear);
  4690     doStepFallingGear(Gear);
  4792     //    CheckGearDrowning(Gear); // already checked for in doStepFallingGear
       
  4793     CalcRotationDirAngle(Gear);
  4691     CalcRotationDirAngle(Gear);
  4794 
  4692 
  4795     if (Gear^.State and gstCollision) <> 0 then
  4693     if (Gear^.State and gstCollision) <> 0 then
  4796         begin
  4694         begin
  4797         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLPoisoned, $C0E0FFE0);
  4695         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLPoisoned, $C0E0FFE0);
  5413         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote);
  5311         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote);
  5414         CurrentHedgehog^.Gear^.MsgParam := 0;
  5312         CurrentHedgehog^.Gear^.MsgParam := 0;
  5415         CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSlot);
  5313         CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSlot);
  5416         end;
  5314         end;
  5417 
  5315 
  5418     if (*((Gear^.Pos = 3) and ((GameFlags and gfSolidLand) <> 0)) or*) (Gear^.Pos = 5) then
  5316     if (Gear^.Pos = 5) then
  5419         begin
  5317         begin
  5420         Gear^.dY := Gear^.dY + cGravity * 2;
  5318         Gear^.dY := Gear^.dY + cGravity * 2;
  5421         Gear^.Y := Gear^.Y + Gear^.dY;
  5319         Gear^.Y := Gear^.Y + Gear^.dY;
  5422         if CheckGearDrowning(Gear) then
  5320         if CheckGearDrowning(Gear) then
  5423             begin
  5321             begin
  5741 
  5639 
  5742             flame:= AddGear(gx, gy, gtFlame, gstTmpFlag,
  5640             flame:= AddGear(gx, gy, gtFlame, gstTmpFlag,
  5743                     SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx,
  5641                     SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx,
  5744                     AngleCos(HHGear^.Angle) * ( - speed) + ry, 0);
  5642                     AngleCos(HHGear^.Angle) * ( - speed) + ry, 0);
  5745             flame^.CollisionMask:= lfNotCurHogCrate;
  5643             flame^.CollisionMask:= lfNotCurHogCrate;
  5746             //flame^.FlightTime:= 500;  use the default huge value to avoid sticky flame suddenly being damaging as opposed to other flames
       
  5747 
  5644 
  5748             if (Gear^.Health mod 30) = 0 then
  5645             if (Gear^.Health mod 30) = 0 then
  5749                 begin
  5646                 begin
  5750                 flame:= AddGear(gx, gy, gtFlame, 0,
  5647                 flame:= AddGear(gx, gy, gtFlame, 0,
  5751                         SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx,
  5648                         SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx,
  5752                         AngleCos(HHGear^.Angle) * ( - speed) + ry, 0);
  5649                         AngleCos(HHGear^.Angle) * ( - speed) + ry, 0);
  5753                 flame^.CollisionMask:= lfNotCurHogCrate;
  5650                 flame^.CollisionMask:= lfNotCurHogCrate;
  5754         //flame^.FlightTime:= 500;
       
  5755                 end
  5651                 end
  5756             end;
  5652             end;
  5757         Gear^.Timer:= Gear^.Tag
  5653         Gear^.Timer:= Gear^.Tag
  5758         end;
  5654         end;
  5759 
  5655 
  5922     tmp:= t^.ar[i];
  5818     tmp:= t^.ar[i];
  5923     if (tmp^.State and gstNoDamage) = 0 then
  5819     if (tmp^.State and gstNoDamage) = 0 then
  5924         if (tmp^.Kind = gtHedgehog) or (tmp^.Kind = gtMine) or (tmp^.Kind = gtExplosives) then
  5820         if (tmp^.Kind = gtHedgehog) or (tmp^.Kind = gtMine) or (tmp^.Kind = gtExplosives) then
  5925             begin
  5821             begin
  5926             dmg:= 0;
  5822             dmg:= 0;
  5927             //tmp^.State:= tmp^.State or gstFlatened;
       
  5928             if (tmp^.Kind <> gtHedgehog) or (tmp^.Hedgehog^.Effects[heInvulnerable] = 0) then
  5823             if (tmp^.Kind <> gtHedgehog) or (tmp^.Hedgehog^.Effects[heInvulnerable] = 0) then
  5929                 begin
  5824                 begin
  5930                 // base damage on remaining health
  5825                 // base damage on remaining health
  5931                 dmg:= (tmp^.Health - tmp^.Damage);
  5826                 dmg:= (tmp^.Health - tmp^.Damage);
  5932                 if dmg > 0 then
  5827                 if dmg > 0 then
  5940         tmp^.dY:= _0_03 * Gear^.Boom
  5835         tmp^.dY:= _0_03 * Gear^.Boom
  5941                 end;
  5836                 end;
  5942 
  5837 
  5943             if (tmp^.Kind <> gtHedgehog) or (dmg > 0) or (tmp^.Health > tmp^.Damage) then
  5838             if (tmp^.Kind <> gtHedgehog) or (dmg > 0) or (tmp^.Health > tmp^.Damage) then
  5944                 begin
  5839                 begin
  5945                 //DrawTunnel(tmp^.X, tmp^.Y - _1, _0, _0_5, cHHRadius * 6, cHHRadius * 3);
       
  5946                 tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0);
  5840                 tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0);
  5947                 tmp2^.LinkedGear:= tmp;
  5841                 tmp2^.LinkedGear:= tmp;
  5948                 SetAllToActive
  5842                 SetAllToActive
  5949                 end;
  5843                 end;
  5950             end;
  5844             end;
  5984             end;
  5878             end;
  5985 
  5879 
  5986         if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9)
  5880         if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9)
  5987            , lfIndestructible) then
  5881            , lfIndestructible) then
  5988             begin
  5882             begin
  5989             //Gear^.X := Gear^.X + Gear^.dX;
       
  5990             Gear^.Y := Gear^.Y + _1_9
  5883             Gear^.Y := Gear^.Y + _1_9
  5991             end;
  5884             end;
  5992         end;
  5885         end;
  5993     if TestCollisionYwithGear(Gear, 1) <> 0 then
  5886     if TestCollisionYwithGear(Gear, 1) <> 0 then
  5994         begin
  5887         begin
  5996         SetLittle(HitGear^.dX);
  5889         SetLittle(HitGear^.dX);
  5997         HitGear^.dY := _0;
  5890         HitGear^.dY := _0;
  5998         end
  5891         end
  5999     else
  5892     else
  6000         begin
  5893         begin
  6001         //Gear^.dY := Gear^.dY + cGravity;
       
  6002         //Gear^.Y := Gear^.Y + Gear^.dY;
       
  6003         if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then
  5894         if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then
  6004             Gear^.Timer := 1
  5895             Gear^.Timer := 1
  6005         end;
  5896         end;
  6006 
  5897 
  6007     //Gear^.X := Gear^.X + HitGear^.dX;
       
  6008     HitGear^.X := Gear^.X;
  5898     HitGear^.X := Gear^.X;
  6009     HitGear^.Y := Gear^.Y;
  5899     HitGear^.Y := Gear^.Y;
  6010     SetLittle(HitGear^.dY);
  5900     SetLittle(HitGear^.dY);
  6011     HitGear^.Active:= true;
  5901     HitGear^.Active:= true;
  6012 end;
  5902 end;
  6047     s: ansistring;
  5937     s: ansistring;
  6048 begin
  5938 begin
  6049     AllInactive := false;
  5939     AllInactive := false;
  6050     hh := Gear^.Hedgehog;
  5940     hh := Gear^.Hedgehog;
  6051 
  5941 
  6052     // no, you can't do that here
       
  6053     {DrawCentered(hwRound(hh^.Gear^.X) + WorldDx, hwRound(hh^.Gear^.Y) + WorldDy -
       
  6054             cHHRadius - 14 - hh^.HealthTagTex^.h, hh^.HealthTagTex);
       
  6055     }
       
  6056     (*DrawCircle(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, 1.5, 0, 0, $FF,
       
  6057             $FF);*)
       
  6058 
       
  6059     if ((Gear^.Message and gmUp) <> 0) then
  5942     if ((Gear^.Message and gmUp) <> 0) then
  6060         begin
  5943         begin
  6061         if (GameTicks and $F) <> 0 then
  5944         if (GameTicks and $F) <> 0 then
  6062         exit;
  5945         exit;
  6063         end
  5946         end
  6089             hh^.Gear^.Damage:= 1;
  5972             hh^.Gear^.Damage:= 1;
  6090         RenderHealth(hh^);
  5973         RenderHealth(hh^);
  6091         RecountTeamHealth(hh^.Team);
  5974         RecountTeamHealth(hh^.Team);
  6092         inc(graves.ar^[Gear^.Tag]^.Health);
  5975         inc(graves.ar^[Gear^.Tag]^.Health);
  6093         inc(Gear^.Tag)
  5976         inc(Gear^.Tag)
  6094 {-for i:= 0 to High(graves) do begin
       
  6095             if hh^.Gear^.Health > 0 then begin
       
  6096                 dec(hh^.Gear^.Health);
       
  6097                 inc(graves[i]^.Health);
       
  6098             end;
       
  6099         end; -}
       
  6100         end
  5977         end
  6101     else
  5978     else
  6102         begin
  5979         begin
  6103         // now really resurrect the hogs with the hp saved in the graves
  5980         // now really resurrect the hogs with the hp saved in the graves
  6104         for i:= 0 to graves.size - 1 do
  5981         for i:= 0 to graves.size - 1 do
  6130         doStepHedgehogMoving(hh^.Gear);
  6007         doStepHedgehogMoving(hh^.Gear);
  6131         StopSoundChan(Gear^.SoundChannel);
  6008         StopSoundChan(Gear^.SoundChannel);
  6132         Gear^.Timer := 250;
  6009         Gear^.Timer := 250;
  6133         Gear^.doStep := @doStepIdle;
  6010         Gear^.doStep := @doStepIdle;
  6134         end
  6011         end
  6135     //if hh^.Gear^.Health = 0 then doStepHedgehogFree(hh^.Gear);
       
  6136 end;
  6012 end;
  6137 
  6013 
  6138 procedure doStepResurrector(Gear: PGear);
  6014 procedure doStepResurrector(Gear: PGear);
  6139 var
  6015 var
  6140     graves: PGearArrayS;
  6016     graves: PGearArrayS;
  6243             if Gear = CurAmmoGear then CurAmmoGear := nil;
  6119             if Gear = CurAmmoGear then CurAmmoGear := nil;
  6244             if (HH^.Gear^.Damage = 0) and  (HH^.Gear^.Health > 0) and
  6120             if (HH^.Gear^.Damage = 0) and  (HH^.Gear^.Health > 0) and
  6245             ((Gear^.State and (gstMoving or gstHHDeath or gstHHGone)) = 0) then
  6121             ((Gear^.State and (gstMoving or gstHHDeath or gstHHGone)) = 0) then
  6246                 HideHog(HH)
  6122                 HideHog(HH)
  6247             end
  6123             end
  6248         //else if (HH^.Gear <> nil) and (HH^.Gear^.State and gstInvisible <> 0) then
  6124         else if (HH^.GearHidden <> nil) then
  6249         else if (HH^.GearHidden <> nil) then// and (HH^.Gear^.State and gstInvisible <> 0) then
       
  6250             begin
  6125             begin
  6251             RestoreHog(HH);
  6126             RestoreHog(HH);
  6252             s:= ansistring(HH^.Name);
  6127             s:= ansistring(HH^.Name);
  6253             AddCaption(FormatA(GetEventString(eidTimeTravelEnd), s), capcolDefault, capgrpMessage)
  6128             AddCaption(FormatA(GetEventString(eidTimeTravelEnd), s), capcolDefault, capgrpMessage)
  6254             end
  6129             end
  6350 end;
  6225 end;
  6351 
  6226 
  6352 ////////////////////////////////////////////////////////////////////////////////
  6227 ////////////////////////////////////////////////////////////////////////////////
  6353 
  6228 
  6354 (*
  6229 (*
  6355 WIP. The ice gun will have the following effects.  It has been proposed by sheepluva that it take the appearance of a large freezer
  6230 The ice gun has the following effects:
  6356 spewing ice cubes.  The cubes will be visual gears only.  The scatter from them and the impact snow dust should help hide imprecisions in things like the GearsNear effect.
  6231 A "ray" like a deagle is projected out from the gun.
  6357 For now we assume a "ray" like a deagle projected out from the gun.
       
  6358 All these effects assume the ray's angle is not changed and that the target type was unchanged over a number of ticks.  This is a simplifying assumption for "gun was applying freezing effect to the same target".
  6232 All these effects assume the ray's angle is not changed and that the target type was unchanged over a number of ticks.  This is a simplifying assumption for "gun was applying freezing effect to the same target".
  6359   * When fired at water a layer of ice textured land is added above the water.
  6233   * When fired at water a layer of ice textured land is added above the water.
  6360   * When fired at non-ice land (land and lfLandMask and not lfIce) the land is overlaid with a thin layer of ice textured land around that point (say, 1 or 2px into land, 1px above). For attractiveness, a slope would probably be needed.
  6234   * When fired at non-ice land (land and lfLandMask and not lfIce) the land is overlaid with a thin layer of ice textured land around that point (say, 1 or 2px into land, 1px above). For attractiveness, a slope would probably be needed.
  6361   * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen.
  6235   * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen.
  6362     As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head.
  6236     As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head.
  6363     If the effect is interrupted before reaching the top, the freezing state is cleared.
  6237     If the effect is interrupted before reaching the top, the freezing state is cleared.
  6364 A frozen hog will animate differently.
  6238 A frozen hog will animate differently.
  6365     To be decided, but possibly in a similar fashion to a grave when it comes to explosions.
  6239     Frozen hogs take less damage and are harder to push.
  6366     The hog might (possibly) not be damaged by explosions.
       
  6367     This might make freezing potentially useful for friendlies in a bad position.
  6240     This might make freezing potentially useful for friendlies in a bad position.
  6368     It might be better to allow damage though.
       
  6369 A frozen hog stays frozen for a certain number of turns.
  6241 A frozen hog stays frozen for a certain number of turns.
  6370     Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again.
  6242     Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again.
  6371 *)
  6243 *)
  6372 
  6244 
  6373 
  6245 
  6405         end
  6277         end
  6406 end;
  6278 end;
  6407 
  6279 
  6408 
  6280 
  6409 procedure updateTarget(Gear:PGear; newX, newY:HWFloat);
  6281 procedure updateTarget(Gear:PGear; newX, newY:HWFloat);
  6410 //    var
       
  6411 //    iter:PGear;
       
  6412 begin
  6282 begin
  6413   with Gear^ do
  6283   with Gear^ do
  6414   begin
  6284   begin
  6415     dX:= newX;
  6285     dX:= newX;
  6416     dY:= newY;
  6286     dY:= newY;
  6423 end;
  6293 end;
  6424 
  6294 
  6425 procedure doStepIceGun(Gear: PGear);
  6295 procedure doStepIceGun(Gear: PGear);
  6426 const iceWaitCollision = 0;
  6296 const iceWaitCollision = 0;
  6427 const iceCollideWithGround = 1;
  6297 const iceCollideWithGround = 1;
  6428 //const iceWaitNextTarget:Longint = 2;
       
  6429 //const iceCollideWithHog:Longint = 4;
       
  6430 const iceCollideWithWater = 5;
  6298 const iceCollideWithWater = 5;
  6431 //const waterFreezingTime:Longint = 500;
       
  6432 const groundFreezingTime = 1000;
  6299 const groundFreezingTime = 1000;
  6433 const iceRadius = 32;
  6300 const iceRadius = 32;
  6434 const iceHeight = 40;
  6301 const iceHeight = 40;
  6435 var
  6302 var
  6436     HHGear, iter: PGear;
  6303     HHGear, iter: PGear;
  6602                                 end
  6469                                 end
  6603                             end;
  6470                             end;
  6604                         iter:= iter^.NextGear
  6471                         iter:= iter^.NextGear
  6605                         end;
  6472                         end;
  6606 
  6473 
  6607                     // FillRoundInLandWithIce(Target.X, Target.Y, iceRadius);
       
  6608                     SetAllHHToActive;
  6474                     SetAllHHToActive;
  6609                     Timer := iceWaitCollision;
  6475                     Timer := iceWaitCollision;
  6610                     Power:= GameTicks
  6476                     Power:= GameTicks
  6611                     end;
  6477                     end;
  6612 
  6478 
  6622                     else
  6488                     else
  6623                         DrawIceBreak(Target.X-iceHeight-5, Target.Y, iceRadius, iceHeight);
  6489                         DrawIceBreak(Target.X-iceHeight-5, Target.Y, iceRadius, iceHeight);
  6624                     SetAllHHToActive;
  6490                     SetAllHHToActive;
  6625                     Timer := iceWaitCollision;
  6491                     Timer := iceWaitCollision;
  6626                     end;
  6492                     end;
  6627 (*
       
  6628  Any ideas for something that would look good here?
       
  6629                 if (Target.X <> NoPointX) and ((Timer = iceCollideWithGround) or (Timer = iceCollideWithWater)) and (GameTicks mod max((groundFreezingTime-((GameTicks - Power)*2)),2) = 0) then //and CheckLandValue(Target.X, Target.Y, lfIce) then
       
  6630                     begin
       
  6631                         vg:= AddVisualGear(Target.X+random(20)-10, Target.Y+random(40)-10, vgtDust, 1);
       
  6632                         if vg <> nil then
       
  6633                             begin
       
  6634                             i:= random(100) + 155;
       
  6635                             vg^.Tint:= IceColor or $FF;
       
  6636                             vg^.Angle:= random(360);
       
  6637                             vg^.dx:= 0.001 * random(80);
       
  6638                             vg^.dy:= 0.001 * random(80)
       
  6639                             end
       
  6640                     end;
       
  6641 *)
       
  6642 
       
  6643 // freeze nearby hogs
  6493 // freeze nearby hogs
  6644                 hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2);
  6494                 hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2);
  6645                 if hogs.size > 0 then
  6495                 if hogs.size > 0 then
  6646                     for i:= 0 to hogs.size - 1 do
  6496                     for i:= 0 to hogs.size - 1 do
  6647                         if hogs.ar^[i] <> HHGear then
  6497                         if hogs.ar^[i] <> HHGear then
  6905         end
  6755         end
  6906 end;
  6756 end;
  6907 
  6757 
  6908 ////////////////////////////////////////////////////////////////////////////////
  6758 ////////////////////////////////////////////////////////////////////////////////
  6909 procedure doStepKnife(Gear: PGear);
  6759 procedure doStepKnife(Gear: PGear);
  6910 //var ox, oy: LongInt;
       
  6911 //    la: hwFloat;
       
  6912 var   a: real;
  6760 var   a: real;
  6913 begin
  6761 begin
  6914     // Gear is shrunk so it can actually escape the hog without carving into the terrain
  6762     // Gear is shrunk so it can actually escape the hog without carving into the terrain
  6915     if (Gear^.Radius = 4) and (Gear^.CollisionMask = lfAll) then Gear^.Radius:= 7;
  6763     if (Gear^.Radius = 4) and (Gear^.CollisionMask = lfAll) then Gear^.Radius:= 7;
  6916     if Gear^.Damage > 100 then Gear^.CollisionMask:= 0
  6764     if Gear^.Damage > 100 then Gear^.CollisionMask:= 0
  6930         CalcRotationDirAngle(Gear);
  6778         CalcRotationDirAngle(Gear);
  6931         Gear^.DirAngle:= a+(Gear^.DirAngle-a)*2*hwSign(Gear^.dX) // double rotation
  6779         Gear^.DirAngle:= a+(Gear^.DirAngle-a)*2*hwSign(Gear^.dX) // double rotation
  6932         end
  6780         end
  6933     else if (Gear^.CollisionIndex = -1) and (Gear^.Timer = 0) then
  6781     else if (Gear^.CollisionIndex = -1) and (Gear^.Timer = 0) then
  6934         begin
  6782         begin
  6935         (*ox:= 0; oy:= 0;
       
  6936         if TestCollisionYwithGear(Gear, -1) <> 0 then oy:= -1;
       
  6937         if TestCollisionXwithGear(Gear, 1)  <> 0 then ox:=  1;
       
  6938         if TestCollisionXwithGear(Gear, -1) <> 0 then ox:= -1;
       
  6939         if TestCollisionYwithGear(Gear, 1)  <> 0 then oy:=  1;
       
  6940 
       
  6941         la:= _10000;
       
  6942         if (ox <> 0) or (oy <> 0) then
       
  6943             la:= CalcSlopeNearGear(Gear, ox, oy);
       
  6944         if la = _10000 then
       
  6945             begin
       
  6946             // debug for when we couldn't get an angle
       
  6947             //AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeWhite);
       
  6948 *)
       
  6949         if Gear^.Health > 0 then
  6783         if Gear^.Health > 0 then
  6950             PlaySound(Gear^.ImpactSound);
  6784             PlaySound(Gear^.ImpactSound);
  6951 
  6785 
  6952             Gear^.DirAngle:= DxDy2Angle(Gear^.dX, Gear^.dY) + (random(30)-15);
  6786             Gear^.DirAngle:= DxDy2Angle(Gear^.dX, Gear^.dY) + (random(30)-15);
  6953             if (Gear^.dX.isNegative and Gear^.dY.isNegative) or
  6787             if (Gear^.dX.isNegative and Gear^.dY.isNegative) or
  6954              ((not Gear^.dX.isNegative) and (not Gear^.dY.isNegative)) then Gear^.DirAngle:= Gear^.DirAngle-90;
  6788              ((not Gear^.dX.isNegative) and (not Gear^.dY.isNegative)) then Gear^.DirAngle:= Gear^.DirAngle-90;
  6955  //           end
       
  6956  //       else Gear^.DirAngle:= hwFloat2Float(la)*90; // sheepluva's comment claims 45deg = 0.5 - yet orientation doesn't seem consistent?
       
  6957  //       AddFileLog('la: '+floattostr(la)+' DirAngle: '+inttostr(round(Gear^.DirAngle)));
       
  6958         Gear^.dX:= _0;
  6789         Gear^.dX:= _0;
  6959         Gear^.dY:= _0;
  6790         Gear^.dY:= _0;
  6960         Gear^.State:= Gear^.State and (not gstMoving) or gstCollision;
  6791         Gear^.State:= Gear^.State and (not gstMoving) or gstCollision;
  6961         Gear^.Radius:= 16;
  6792         Gear^.Radius:= 16;
  6962         if Gear^.Health > 0 then AmmoShove(Gear, Gear^.Health, 0);
  6793         if Gear^.Health > 0 then AmmoShove(Gear, Gear^.Health, 0);
  7054     Gear^.Y := Gear^.Y + Gear^.dY * 2;
  6885     Gear^.Y := Gear^.Y + Gear^.dY * 2;
  7055     Gear^.FlightTime := 0;
  6886     Gear^.FlightTime := 0;
  7056     Gear^.doStep := @doStepBulletWork
  6887     Gear^.doStep := @doStepBulletWork
  7057 end;
  6888 end;
  7058 
  6889 
  7059 (*
       
  7060  This didn't end up getting used, but, who knows, might be reasonable for javellin or something
       
  7061 // Make the knife initial angle based on the hog attack angle, or is that too hard?
       
  7062 procedure doStepKnife(Gear: PGear);
       
  7063 var t,
       
  7064     gx, gy, ga,  // gear x,y,angle
       
  7065     lx, ly, la, // land x,y,angle
       
  7066     ox, oy, // x,y offset
       
  7067     w, h,   // wXh of clip area
       
  7068     tx, ty  // tip position in sprite
       
  7069     : LongInt;
       
  7070     surf: PSDL_Surface;
       
  7071     s: hwFloat;
       
  7072 
       
  7073 begin
       
  7074     Gear^.dY := Gear^.dY + cGravity;
       
  7075     if (GameFlags and gfMoreWind) <> 0 then
       
  7076         Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density;
       
  7077     Gear^.X := Gear^.X + Gear^.dX;
       
  7078     Gear^.Y := Gear^.Y + Gear^.dY;
       
  7079     CheckGearDrowning(Gear);
       
  7080     gx:= hwRound(Gear^.X);
       
  7081     gy:= hwRound(Gear^.Y);
       
  7082     if Gear^.State and gstDrowning <> 0 then exit;
       
  7083     with Gear^ do
       
  7084         begin
       
  7085         if CheckLandValue(gx, gy, lfLandMask) then
       
  7086             begin
       
  7087             t:= Angle + hwRound((hwAbs(dX)+hwAbs(dY)) * _10);
       
  7088 
       
  7089             if t < 0 then inc(t, 4096)
       
  7090             else if 4095 < t then dec(t, 4096);
       
  7091             Angle:= t;
       
  7092 
       
  7093             DirAngle:= Angle / 4096 * 360
       
  7094             end
       
  7095         else
       
  7096             begin
       
  7097 //This is the set of postions for the knife.
       
  7098 //Using FlipSurface and copyToXY the knife can be written to the LandPixels at 32 positions, and an appropriate line drawn in Land.
       
  7099             t:= Angle mod 1024;
       
  7100             case t div 128 of
       
  7101                 0:  begin
       
  7102                     ox:=   2; oy:= 5;
       
  7103                     w :=  25;  h:= 5;
       
  7104                     tx:=   0; ty:= 2
       
  7105                     end;
       
  7106                 1:  begin
       
  7107                     ox:=   2; oy:= 15;
       
  7108                      w:=  24;  h:=  8;
       
  7109                     tx:=   0; ty:=  7
       
  7110                     end;
       
  7111                 2:  begin
       
  7112                     ox:=   2; oy:= 27;
       
  7113                      w:=  23;  h:= 12;
       
  7114                     tx:= -12; ty:= -5
       
  7115                     end;
       
  7116                 3:  begin
       
  7117                     ox:=   2; oy:= 43;
       
  7118                      w:=  21;  h:= 15;
       
  7119                     tx:=   0; ty:= 14
       
  7120                     end;
       
  7121                 4:  begin
       
  7122                     ox:= 29; oy:=  8;
       
  7123                      w:= 19;  h:= 19;
       
  7124                     tx:=  0; ty:= 17
       
  7125                     end;
       
  7126                 5:  begin
       
  7127                     ox:= 29; oy:=  32;
       
  7128                      w:= 15;  h:=  21;
       
  7129                     tx:=  0; ty:=  20
       
  7130                     end;
       
  7131                 6:  begin
       
  7132                     ox:= 51; oy:=   3;
       
  7133                      w:= 11;  h:=  23;
       
  7134                     tx:=  0; ty:=  22
       
  7135                     end;
       
  7136                 7:  begin
       
  7137                     ox:= 51; oy:=  34;
       
  7138                      w:=  7;  h:=  24;
       
  7139                     tx:=  0; ty:=  23
       
  7140                     end
       
  7141                 end;
       
  7142 
       
  7143             surf:= SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RMask, GMask, BMask, AMask);
       
  7144             copyToXYFromRect(SpritesData[sprKnife].Surface, surf, ox, oy, w, h, 0, 0);
       
  7145             // try to make the knife hit point first
       
  7146             lx := 0;
       
  7147             ly := 0;
       
  7148             if CalcSlopeTangent(Gear, gx, gy, lx, ly, 255) then
       
  7149                 begin
       
  7150                 la:= vector2Angle(int2hwFloat(lx), int2hwFloat(ly));
       
  7151                 ga:= vector2Angle(dX, dY);
       
  7152                 AddFileLog('la: '+inttostr(la)+' ga: '+inttostr(ga)+' Angle: '+inttostr(Angle));
       
  7153                 // change  to 0 to 4096 forced by LongWord in Gear
       
  7154                 if la < 0 then la:= 4096+la;
       
  7155                 if ga < 0 then ga:= 4096+ga;
       
  7156                 if ((Angle > ga) and (Angle < la)) or ((Angle < ga) and (Angle > la)) then
       
  7157                     begin
       
  7158                     if Angle >= 2048 then dec(Angle, 2048)
       
  7159                     else if Angle < 2048 then inc(Angle, 2048)
       
  7160                     end;
       
  7161                 AddFileLog('la: '+inttostr(la)+' ga: '+inttostr(ga)+' Angle: '+inttostr(Angle))
       
  7162                 end;
       
  7163             case Angle div 1024 of
       
  7164                 0:  begin
       
  7165                     flipSurface(surf, true);
       
  7166                     flipSurface(surf, true);
       
  7167                     BlitImageAndGenerateCollisionInfo(gx-(w-tx), gy-(h-ty), w, surf)
       
  7168                     end;
       
  7169                 1:  begin
       
  7170                     flipSurface(surf, false);
       
  7171                     BlitImageAndGenerateCollisionInfo(gx-(w-tx), gy-ty, w, surf)
       
  7172                     end;
       
  7173                 2:  begin // knife was actually drawn facing this way...
       
  7174                     BlitImageAndGenerateCollisionInfo(gx-tx, gy-ty, w, surf)
       
  7175                     end;
       
  7176                 3:  begin
       
  7177                     flipSurface(surf, true);
       
  7178                     BlitImageAndGenerateCollisionInfo(gx-tx, gy-(h-ty), w, surf)
       
  7179                     end
       
  7180                 end;
       
  7181             SDL_FreeSurface(surf);
       
  7182             // this needs to calculate actual width/height + land clipping since update texture doesn't.
       
  7183             // i.e. this will crash if you fire near sides of map, but until I get the blit right, not going to put real values
       
  7184             UpdateLandTexture(hwRound(X)-32, 64, hwRound(Y)-32, 64, true);
       
  7185             DeleteGear(Gear);
       
  7186             exit
       
  7187             end
       
  7188         end;
       
  7189 end;
       
  7190 *)
       
  7191 
       
  7192 end.
  6890 end.