hedgewars/uGears.pas
changeset 9289 6bc1df062f04
parent 9285 8e8b908970c2
child 9291 15f7bb217b66
equal deleted inserted replaced
9261:6e4feb4191a0 9289:6bc1df062f04
    31  *
    31  *
    32  * Note: Gears that do not have an effect on the game but are just visual
    32  * Note: Gears that do not have an effect on the game but are just visual
    33  *       effects are called "Visual Gears" and defined in the respective unit!
    33  *       effects are called "Visual Gears" and defined in the respective unit!
    34  *)
    34  *)
    35 interface
    35 interface
    36 uses SDLh, uConsts, uFloat, uTypes;
    36 uses uConsts, uFloat, uTypes;
    37 
    37 
    38 procedure initModule;
    38 procedure initModule;
    39 procedure freeModule;
    39 procedure freeModule;
    40 function  SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear;
    40 function  SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear;
    41 function  SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean ): PGear;
    41 function  SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean ): PGear;
    42 function  GetAmmo(Hedgehog: PHedgehog): TAmmoType;
       
    43 function  GetUtility(Hedgehog: PHedgehog): TAmmoType;
       
    44 procedure HideHog(HH: PHedgehog);
       
    45 procedure ProcessGears;
    42 procedure ProcessGears;
    46 procedure EndTurnCleanup;
    43 procedure EndTurnCleanup;
    47 procedure SetAllToActive;
       
    48 procedure SetAllHHToActive; inline;
       
    49 procedure SetAllHHToActive(Ice: boolean);
       
    50 procedure DrawGears;
    44 procedure DrawGears;
    51 procedure FreeGearsList;
    45 procedure FreeGearsList;
    52 procedure AddMiscGears;
    46 procedure AddMiscGears;
    53 procedure AssignHHCoords;
    47 procedure AssignHHCoords;
    54 function  GearByUID(uid : Longword) : PGear;
    48 function  GearByUID(uid : Longword) : PGear;
    55 procedure doStepDrowningGear(Gear: PGear);
       
    56 
       
    57 
    49 
    58 implementation
    50 implementation
    59 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF}
    51 uses uStore, uSound, uTeams, uRandom, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF}
    60     uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables,
    52     uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables,
    61     uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
    53     uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
    62     uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope;
    54     uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlersRope
       
    55     , uVisualGearsList, uGearsHandlersMess;
    63 
    56 
    64 var skipFlag: boolean;
    57 var skipFlag: boolean;
    65 
       
    66 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
       
    67 //procedure AmmoFlameWork(Ammo: PGear); forward;
       
    68 function  GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS; forward;
       
    69 procedure SpawnBoxOfSmth; forward;
       
    70 procedure ShotgunShot(Gear: PGear); forward;
       
    71 procedure doStepCase(Gear: PGear); forward;
       
    72 
       
    73 
    58 
    74 var delay: LongWord;
    59 var delay: LongWord;
    75     delay2: LongWord;
    60     delay2: LongWord;
    76     step: (stDelay, stChDmg, stSweep, stTurnReact,
    61     step: (stDelay, stChDmg, stSweep, stTurnReact,
    77     stAfterDelay, stChWin, stWater, stChWin2, stHealth,
    62     stAfterDelay, stChWin, stWater, stChWin2, stHealth,
    78     stSpawn, stNTurn);
    63     stSpawn, stNTurn);
    79     upd: Longword;
       
    80     snowLeft,snowRight: LongInt;
       
    81     NewTurnTick: LongWord;
    64     NewTurnTick: LongWord;
    82     //SDMusic: shortstring;
    65     //SDMusic: shortstring;
    83 
       
    84 // For better maintainability the step handlers of gears are stored in
       
    85 // separate files.
       
    86 // Note: step handlers of gears that are hedgehogs are in a different file
       
    87 //       than the handlers for all other gears.
       
    88 {$INCLUDE "GSHandlers.inc"}
       
    89 
    66 
    90 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs
    67 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs
    91 var Gear: PGear;
    68 var Gear: PGear;
    92     dmg: LongInt;
    69     dmg: LongInt;
    93 begin
    70 begin
   548     if (GameFlags and gfResetHealth) <> 0 then
   525     if (GameFlags and gfResetHealth) <> 0 then
   549         for i:= 0 to Pred(TeamsCount) do
   526         for i:= 0 to Pred(TeamsCount) do
   550             RecountTeamHealth(TeamsArray[i])
   527             RecountTeamHealth(TeamsArray[i])
   551 end;
   528 end;
   552 
   529 
   553 procedure SetAllToActive;
       
   554 var t: PGear;
       
   555 begin
       
   556 AllInactive:= false;
       
   557 t:= GearsList;
       
   558 while t <> nil do
       
   559     begin
       
   560     t^.Active:= true;
       
   561     t:= t^.NextGear
       
   562     end
       
   563 end;
       
   564 
       
   565 procedure SetAllHHToActive; inline;
       
   566 begin
       
   567 SetAllHHToActive(true)
       
   568 end;
       
   569 
       
   570 procedure SetAllHHToActive(Ice: boolean);
       
   571 var t: PGear;
       
   572 begin
       
   573 AllInactive:= false;
       
   574 t:= GearsList;
       
   575 while t <> nil do
       
   576     begin
       
   577     if (t^.Kind = gtHedgehog) or (t^.Kind = gtExplosives) then
       
   578         begin
       
   579         if (t^.Kind = gtHedgehog) and Ice then CheckIce(t);
       
   580         t^.Active:= true
       
   581         end;
       
   582     t:= t^.NextGear
       
   583     end
       
   584 end;
       
   585 
       
   586 procedure DrawGears;
   530 procedure DrawGears;
   587 var Gear: PGear;
   531 var Gear: PGear;
   588     x, y: LongInt;
   532     x, y: LongInt;
   589 begin
   533 begin
   590 Gear:= GearsList;
   534 Gear:= GearsList;
   673 snowLeft:= -(snowRight-LAND_WIDTH);
   617 snowLeft:= -(snowRight-LAND_WIDTH);
   674 
   618 
   675 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then
   619 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then
   676     for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do
   620     for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do
   677         AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0);
   621         AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0);
   678 end;
       
   679 
       
   680 
       
   681 procedure ShotgunShot(Gear: PGear);
       
   682 var t: PGear;
       
   683     dmg, r, dist: LongInt;
       
   684     dx, dy: hwFloat;
       
   685 begin
       
   686 Gear^.Radius:= cShotgunRadius;
       
   687 t:= GearsList;
       
   688 while t <> nil do
       
   689     begin
       
   690     case t^.Kind of
       
   691         gtHedgehog,
       
   692             gtMine,
       
   693             gtSMine,
       
   694             gtKnife,
       
   695             gtCase,
       
   696             gtTarget,
       
   697             gtExplosives: begin//,
       
   698 //            gtStructure: begin
       
   699 //addFileLog('ShotgunShot radius: ' + inttostr(Gear^.Radius) + ', t^.Radius = ' + inttostr(t^.Radius) + ', distance = ' + inttostr(dist) + ', dmg = ' + inttostr(dmg));
       
   700                     dmg:= 0;
       
   701                     r:= Gear^.Radius + t^.Radius;
       
   702                     dx:= Gear^.X-t^.X;
       
   703                     dx.isNegative:= false;
       
   704                     dy:= Gear^.Y-t^.Y;
       
   705                     dy.isNegative:= false;
       
   706                     if r-hwRound(dx+dy) > 0 then
       
   707                         begin
       
   708                         dist:= hwRound(Distance(dx, dy));
       
   709                         dmg:= ModifyDamage(min(r - dist, 25), t);
       
   710                         end;
       
   711                     if dmg > 0 then
       
   712                         begin
       
   713                         if (not t^.Invulnerable) then
       
   714                             ApplyDamage(t, Gear^.Hedgehog, dmg, dsBullet)
       
   715                         else
       
   716                             Gear^.State:= Gear^.State or gstWinner;
       
   717 
       
   718                         DeleteCI(t);
       
   719                         t^.dX:= t^.dX + Gear^.dX * dmg * _0_01 + SignAs(cHHKick, Gear^.dX);
       
   720                         t^.dY:= t^.dY + Gear^.dY * dmg * _0_01;
       
   721                         t^.State:= t^.State or gstMoving;
       
   722                         if t^.Kind = gtKnife then t^.State:= t^.State and (not gstCollision);
       
   723                         t^.Active:= true;
       
   724                         FollowGear:= t
       
   725                         end
       
   726                     end;
       
   727             gtGrave: begin
       
   728                     dmg:= 0;
       
   729                     r:= Gear^.Radius + t^.Radius;
       
   730                     dx:= Gear^.X-t^.X;
       
   731                     dx.isNegative:= false;
       
   732                     dy:= Gear^.Y-t^.Y;
       
   733                     dy.isNegative:= false;
       
   734                     if r-hwRound(dx+dy) > 0 then
       
   735                         begin
       
   736                         dist:= hwRound(Distance(dx, dy));
       
   737                         dmg:= ModifyDamage(min(r - dist, 25), t);
       
   738                         end;
       
   739                     if dmg > 0 then
       
   740                         begin
       
   741                         t^.dY:= - _0_1;
       
   742                         t^.Active:= true
       
   743                         end
       
   744                     end;
       
   745         end;
       
   746     t:= t^.NextGear
       
   747     end;
       
   748 if (GameFlags and gfSolidLand) = 0 then
       
   749     DrawExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cShotgunRadius)
       
   750 end;
       
   751 
       
   752 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
       
   753 var t: PGearArray;
       
   754     Gear: PGear;
       
   755     i, j, tmpDmg: LongInt;
       
   756     VGear: PVisualGear;
       
   757 begin
       
   758 t:= CheckGearsCollision(Ammo);
       
   759 // Just to avoid hogs on rope dodging fire.
       
   760 if (CurAmmoGear <> nil) and ((CurAmmoGear^.Kind = gtRope) or (CurAmmoGear^.Kind = gtJetpack) or (CurAmmoGear^.Kind = gtBirdy))
       
   761 and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1)
       
   762 and (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then
       
   763     begin
       
   764     t^.ar[t^.Count]:= CurrentHedgehog^.Gear;
       
   765     inc(t^.Count)
       
   766     end;
       
   767 
       
   768 i:= t^.Count;
       
   769 
       
   770 if (Ammo^.Kind = gtFlame) and (i > 0) then
       
   771     Ammo^.Health:= 0;
       
   772 while i > 0 do
       
   773     begin
       
   774     dec(i);
       
   775     Gear:= t^.ar[i];
       
   776     if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and 
       
   777        (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then
       
   778         Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000);
       
   779     tmpDmg:= ModifyDamage(Damage, Gear);
       
   780     if (Gear^.State and gstNoDamage) = 0 then
       
   781         begin
       
   782 
       
   783         if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then 
       
   784             begin
       
   785             VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
       
   786             if VGear <> nil then
       
   787                 VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
       
   788             end;
       
   789 
       
   790         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then
       
   791             Gear^.FlightTime:= 1;
       
   792 
       
   793 
       
   794         case Gear^.Kind of
       
   795             gtHedgehog,
       
   796             gtMine,
       
   797             gtSMine,
       
   798             gtKnife,
       
   799             gtTarget,
       
   800             gtCase,
       
   801             gtExplosives: //,
       
   802             //gtStructure:
       
   803             begin
       
   804             if (Ammo^.Kind = gtDrill) then
       
   805                 begin
       
   806                 Ammo^.Timer:= 0;
       
   807                 exit;
       
   808                 end;
       
   809             if (not Gear^.Invulnerable) then
       
   810                 begin
       
   811                 if (Ammo^.Kind = gtKnife) and (tmpDmg > 0) then
       
   812                     for j:= 1 to max(1,min(3,tmpDmg div 5)) do
       
   813                         begin
       
   814                         VGear:= AddVisualGear(hwRound(Ammo^.X-((Ammo^.X-Gear^.X)/_2)), hwRound(Ammo^.Y-((Ammo^.Y-Gear^.Y)/_2)), vgtStraightShot);
       
   815                         if VGear <> nil then
       
   816                             with VGear^ do
       
   817                                 begin
       
   818                                 Tint:= $FFCC00FF;
       
   819                                 Angle:= random(360);
       
   820                                 dx:= 0.0005 * (random(100));
       
   821                                 dy:= 0.0005 * (random(100));
       
   822                                 if random(2) = 0 then
       
   823                                     dx := -dx;
       
   824                                 if random(2) = 0 then
       
   825                                     dy := -dy;
       
   826                                 FrameTicks:= 600+random(200);
       
   827                                 State:= ord(sprStar)
       
   828                                 end
       
   829                         end;
       
   830                 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove)
       
   831                 end
       
   832             else
       
   833                 Gear^.State:= Gear^.State or gstWinner;
       
   834             if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then 
       
   835                 begin
       
   836                 if (Ammo^.Hedgehog^.Gear <> nil) then
       
   837                     Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable);
       
   838                 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch
       
   839                 end;
       
   840 
       
   841             if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then
       
   842                 begin
       
   843                 Gear^.dX:= Ammo^.dX * Power * _0_005;
       
   844                 Gear^.dY:= Ammo^.dY * Power * _0_005
       
   845                 end
       
   846             else if ((Ammo^.Kind <> gtFlame) or (Gear^.Kind = gtHedgehog)) and (Power <> 0) then
       
   847                 begin
       
   848                 Gear^.dX:= Ammo^.dX * Power * _0_01;
       
   849                 Gear^.dY:= Ammo^.dY * Power * _0_01
       
   850                 end;
       
   851 
       
   852             if (not isZero(Gear^.dX)) or (not isZero(Gear^.dY)) then
       
   853                 begin
       
   854                 Gear^.Active:= true;
       
   855                 DeleteCI(Gear);
       
   856                 Gear^.State:= Gear^.State or gstMoving;
       
   857                 if Gear^.Kind = gtKnife then Gear^.State:= Gear^.State and (not gstCollision);
       
   858                 // move the gear upwards a bit to throw it over tiny obstacles at start
       
   859                 if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
       
   860                     begin
       
   861                     if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
       
   862                     or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   863                         Gear^.Y:= Gear^.Y - _1;
       
   864                     if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
       
   865                     or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   866                         Gear^.Y:= Gear^.Y - _1;
       
   867                     if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
       
   868                     or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   869                         Gear^.Y:= Gear^.Y - _1;
       
   870                     end
       
   871                 end;
       
   872 
       
   873 
       
   874             if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then
       
   875                 FollowGear:= Gear
       
   876             end;
       
   877         end
       
   878         end;
       
   879     end;
       
   880 if i <> 0 then
       
   881     SetAllToActive
       
   882 end;
   622 end;
   883 
   623 
   884 procedure AssignHHCoords;
   624 procedure AssignHHCoords;
   885 var i, t, p, j: LongInt;
   625 var i, t, p, j: LongInt;
   886     ar: array[0..Pred(cMaxHHs)] of PHedgehog;
   626     ar: array[0..Pred(cMaxHHs)] of PHedgehog;
   943         dec(Count)
   683         dec(Count)
   944         end
   684         end
   945     end
   685     end
   946 end;
   686 end;
   947 
   687 
   948 var GearsNearArray : TPGearArray;
       
   949 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS;
       
   950 var
       
   951     t: PGear;
       
   952     s: Longword;
       
   953 begin
       
   954     r:= r*r;
       
   955     s:= 0;
       
   956     SetLength(GearsNearArray, s);
       
   957     t := GearsList;
       
   958     while t <> nil do 
       
   959         begin
       
   960         if (t^.Kind = Kind) 
       
   961             and ((X - t^.X)*(X - t^.X) + (Y - t^.Y)*(Y-t^.Y) < int2hwFloat(r)) then
       
   962             begin
       
   963             inc(s);
       
   964             SetLength(GearsNearArray, s);
       
   965             GearsNearArray[s - 1] := t;
       
   966             end;
       
   967         t := t^.NextGear;
       
   968     end;
       
   969 
       
   970     GearsNear.size:= s;
       
   971     GearsNear.ar:= @GearsNearArray
       
   972 end;
       
   973 
   688 
   974 {procedure AmmoFlameWork(Ammo: PGear);
   689 {procedure AmmoFlameWork(Ammo: PGear);
   975 var t: PGear;
   690 var t: PGear;
   976 begin
   691 begin
   977 t:= GearsList;
   692 t:= GearsList;
   989             end;
   704             end;
   990     t:= t^.NextGear
   705     t:= t^.NextGear
   991     end;
   706     end;
   992 end;}
   707 end;}
   993 
   708 
   994 
       
   995 function CountGears(Kind: TGearType): Longword;
       
   996 var t: PGear;
       
   997     count: Longword = 0;
       
   998 begin
       
   999 
       
  1000 t:= GearsList;
       
  1001 while t <> nil do
       
  1002     begin
       
  1003     if t^.Kind = Kind then
       
  1004         inc(count);
       
  1005     t:= t^.NextGear
       
  1006     end;
       
  1007 CountGears:= count;
       
  1008 end;
       
  1009 
   709 
  1010 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear;
   710 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear;
  1011 begin
   711 begin
  1012     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
   712     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
  1013     cCaseFactor := 0;
   713     cCaseFactor := 0;
  1075 
   775 
  1076     if ( (x = 0) and (y = 0) ) then
   776     if ( (x = 0) and (y = 0) ) then
  1077         FindPlace(FollowGear, true, 0, LAND_WIDTH);
   777         FindPlace(FollowGear, true, 0, LAND_WIDTH);
  1078 
   778 
  1079     SpawnFakeCrateAt := FollowGear;
   779     SpawnFakeCrateAt := FollowGear;
  1080 end;
       
  1081 
       
  1082 function GetAmmo(Hedgehog: PHedgehog): TAmmoType;
       
  1083 var t, aTot: LongInt;
       
  1084     i: TAmmoType;
       
  1085 begin
       
  1086 Hedgehog:= Hedgehog; // avoid hint
       
  1087 
       
  1088 aTot:= 0;
       
  1089 for i:= Low(TAmmoType) to High(TAmmoType) do
       
  1090     if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
       
  1091         inc(aTot, Ammoz[i].Probability);
       
  1092 
       
  1093 t:= aTot;
       
  1094 i:= Low(TAmmoType);
       
  1095 if (t > 0) then
       
  1096     begin
       
  1097     t:= GetRandom(t);
       
  1098     while t >= 0 do
       
  1099         begin
       
  1100         inc(i);
       
  1101         if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
       
  1102             dec(t, Ammoz[i].Probability)
       
  1103         end
       
  1104     end;
       
  1105 GetAmmo:= i
       
  1106 end;
       
  1107 
       
  1108 function GetUtility(Hedgehog: PHedgehog): TAmmoType;
       
  1109 var t, uTot: LongInt;
       
  1110     i: TAmmoType;
       
  1111 begin
       
  1112 
       
  1113 uTot:= 0;
       
  1114 for i:= Low(TAmmoType) to High(TAmmoType) do
       
  1115     if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0)
       
  1116     and ((Hedgehog^.Team^.HedgehogsNumber > 1) or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
       
  1117         inc(uTot, Ammoz[i].Probability);
       
  1118 
       
  1119 t:= uTot;
       
  1120 i:= Low(TAmmoType);
       
  1121 if (t > 0) then
       
  1122     begin
       
  1123     t:= GetRandom(t);
       
  1124     while t >= 0 do
       
  1125         begin
       
  1126         inc(i);
       
  1127         if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) and ((Hedgehog^.Team^.HedgehogsNumber > 1)
       
  1128         or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
       
  1129             dec(t, Ammoz[i].Probability)
       
  1130         end
       
  1131     end;
       
  1132 GetUtility:= i
       
  1133 end;
       
  1134 
       
  1135 
       
  1136 
       
  1137 procedure SpawnBoxOfSmth;
       
  1138 var t, aTot, uTot, a, h: LongInt;
       
  1139     i: TAmmoType;
       
  1140 begin
       
  1141 if (PlacingHogs) or
       
  1142     (cCaseFactor = 0)
       
  1143     or (CountGears(gtCase) >= 5)
       
  1144     or (GetRandom(cCaseFactor) <> 0) then
       
  1145        exit;
       
  1146 
       
  1147 FollowGear:= nil;
       
  1148 aTot:= 0;
       
  1149 uTot:= 0;
       
  1150 for i:= Low(TAmmoType) to High(TAmmoType) do
       
  1151     if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
       
  1152         inc(aTot, Ammoz[i].Probability)
       
  1153     else
       
  1154         inc(uTot, Ammoz[i].Probability);
       
  1155 
       
  1156 t:=0;
       
  1157 a:=aTot;
       
  1158 h:= 1;
       
  1159 
       
  1160 if (aTot+uTot) <> 0 then
       
  1161     if ((GameFlags and gfInvulnerable) = 0) then
       
  1162         begin
       
  1163         h:= cHealthCaseProb * 100;
       
  1164         t:= GetRandom(10000);
       
  1165         a:= (10000-h)*aTot div (aTot+uTot)
       
  1166         end
       
  1167     else
       
  1168         begin
       
  1169         t:= GetRandom(aTot+uTot);
       
  1170         h:= 0
       
  1171         end;
       
  1172 
       
  1173 
       
  1174 if t<h then
       
  1175     begin
       
  1176     FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
       
  1177     FollowGear^.Health:= cHealthCaseAmount;
       
  1178     FollowGear^.Pos:= posCaseHealth;
       
  1179     AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo);
       
  1180     end
       
  1181 else if (t<a+h) then
       
  1182     begin
       
  1183     t:= aTot;
       
  1184     if (t > 0) then
       
  1185         begin
       
  1186         FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
       
  1187         t:= GetRandom(t);
       
  1188         i:= Low(TAmmoType);
       
  1189         FollowGear^.Pos:= posCaseAmmo;
       
  1190         FollowGear^.AmmoType:= i;
       
  1191         AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo);
       
  1192         end
       
  1193     end
       
  1194 else
       
  1195     begin
       
  1196     t:= uTot;
       
  1197     if (t > 0) then
       
  1198         begin
       
  1199         FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
       
  1200         t:= GetRandom(t);
       
  1201         i:= Low(TAmmoType);
       
  1202         FollowGear^.Pos:= posCaseUtility;
       
  1203         FollowGear^.AmmoType:= i;
       
  1204         AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo);
       
  1205         end
       
  1206     end;
       
  1207 
       
  1208 // handles case of no ammo or utility crates - considered also placing booleans in uAmmos and altering probabilities
       
  1209 if (FollowGear <> nil) then
       
  1210     begin
       
  1211     FindPlace(FollowGear, true, 0, LAND_WIDTH);
       
  1212 
       
  1213     if (FollowGear <> nil) then
       
  1214         AddVoice(sndReinforce, CurrentTeam^.voicepack)
       
  1215     end
       
  1216 end;
   780 end;
  1217 
   781 
  1218 
   782 
  1219 function GearByUID(uid : Longword) : PGear;
   783 function GearByUID(uid : Longword) : PGear;
  1220 var gear: PGear;
   784 var gear: PGear;