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