hedgewars/uGears.pas
branchwebgl
changeset 9521 8054d9d775fd
parent 9236 ddd675825672
parent 9497 1813b682c6bd
child 9950 2759212a27de
equal deleted inserted replaced
9282:92af50454cf2 9521:8054d9d775fd
    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(Ice: boolean);
       
    49 procedure DrawGears;
    44 procedure DrawGears;
    50 procedure FreeGearsList;
    45 procedure FreeGearsList;
    51 procedure AddMiscGears;
    46 procedure AddMiscGears;
    52 procedure AssignHHCoords;
    47 procedure AssignHHCoords;
    53 function  GearByUID(uid : Longword) : PGear;
    48 function  GearByUID(uid : Longword) : PGear;
    54 procedure doStepDrowningGear(Gear: PGear);
       
    55 
       
    56 implementation
    49 implementation
    57 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF}
    50 uses uStore, uSound, uTeams, uRandom, uIO, uLandGraphics, {$IFDEF SDL2}uTouch,{$ENDIF}
    58     uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables,
    51     uLocale, uAmmos, uStats, uVisualGears, uScript, uVariables,
    59     uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
    52     uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
    60     uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope;
    53     uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlersRope
       
    54     , uVisualGearsList, uGearsHandlersMess, uAI;
    61 
    55 
    62 var skipFlag: boolean;
    56 var skipFlag: boolean;
    63 
       
    64 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
       
    65 //procedure AmmoFlameWork(Ammo: PGear); forward;
       
    66 function  GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS; forward;
       
    67 procedure SpawnBoxOfSmth; forward;
       
    68 procedure ShotgunShot(Gear: PGear); forward;
       
    69 procedure doStepCase(Gear: PGear); forward;
       
    70 
       
    71 
    57 
    72 var delay: LongWord;
    58 var delay: LongWord;
    73     delay2: LongWord;
    59     delay2: LongWord;
    74     step: (stDelay, stChDmg, stSweep, stTurnReact,
    60     step: (stDelay, stChDmg, stSweep, stTurnReact,
    75     stAfterDelay, stChWin, stWater, stChWin2, stHealth,
    61     stAfterDelay, stChWin, stWater, stChWin2, stHealth,
    76     stSpawn, stNTurn);
    62     stSpawn, stNTurn);
    77     upd: Longword;
       
    78     snowLeft,snowRight: LongInt;
       
    79     NewTurnTick: LongWord;
    63     NewTurnTick: LongWord;
    80     //SDMusic: shortstring;
    64     //SDMusic: shortstring;
    81 
       
    82 // For better maintainability the step handlers of gears are stored in
       
    83 // separate files.
       
    84 // Note: step handlers of gears that are hedgehogs are in a different file
       
    85 //       than the handlers for all other gears.
       
    86 {$INCLUDE "GSHandlers.inc"}
       
    87 
    65 
    88 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs
    66 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs
    89 var Gear: PGear;
    67 var Gear: PGear;
    90     dmg: LongInt;
    68     dmg: LongInt;
    91 begin
    69 begin
   191 ScriptCall('onGameTick');
   169 ScriptCall('onGameTick');
   192 if GameTicks mod 20 = 0 then ScriptCall('onGameTick20');
   170 if GameTicks mod 20 = 0 then ScriptCall('onGameTick20');
   193 if GameTicks = NewTurnTick then
   171 if GameTicks = NewTurnTick then
   194     begin
   172     begin
   195     ScriptCall('onNewTurn');
   173     ScriptCall('onNewTurn');
   196 {$IFDEF SDL13}
   174 {$IFDEF SDL2}
   197     uTouch.NewTurnBeginning();
   175     uTouch.NewTurnBeginning();
   198 {$ENDIF}
   176 {$ENDIF}
   199     end;
   177     end;
   200 
   178 
   201 PrvInactive:= AllInactive;
   179 PrvInactive:= AllInactive;
   331                     ScreenFadeValue:= sfMax;
   309                     ScreenFadeValue:= sfMax;
   332                     ScreenFadeSpeed:= 1;
   310                     ScreenFadeSpeed:= 1;
   333 
   311 
   334                     ChangeToSDClouds;
   312                     ChangeToSDClouds;
   335                     ChangeToSDFlakes;
   313                     ChangeToSDFlakes;
   336                     glClearColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255, 0.99);
   314                     SetSkyColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255);
   337                     Ammoz[amTardis].SkipTurns:= 9999;
   315                     Ammoz[amTardis].SkipTurns:= 9999;
   338                     Ammoz[amTardis].Probability:= 0;
   316                     Ammoz[amTardis].Probability:= 0;
   339                     end;
   317                     end;
   340                 AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
   318                 AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
   341                 playSound(sndSuddenDeath);
   319                 playSound(sndSuddenDeath);
   420         if delay2 = 0 then
   398         if delay2 = 0 then
   421             begin
   399             begin
   422             if (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.State and gstAttacked = 0)
   400             if (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.State and gstAttacked = 0)
   423             and (CurAmmoGear = nil) then
   401             and (CurAmmoGear = nil) then
   424                 SweepDirty;
   402                 SweepDirty;
   425             CheckNoDamage;
   403             if (CurrentHedgehog^.Gear = nil) or (CurrentHedgehog^.Gear^.State and gstHHDriven = 0) or (CurrentHedgehog^.Gear^.Damage = 0) then
       
   404                 CheckNoDamage;
   426             AliveCount:= 0; // shorter version of check for win to allow typical step activity to proceed
   405             AliveCount:= 0; // shorter version of check for win to allow typical step activity to proceed
   427             for i:= 0 to Pred(ClansCount) do
   406             for i:= 0 to Pred(ClansCount) do
   428                 if ClansArray[i]^.ClanHealth > 0 then
   407                 if ClansArray[i]^.ClanHealth > 0 then
   429                     inc(AliveCount);
   408                     inc(AliveCount);
   430             if (AliveCount <= 1) and ((GameFlags and gfOneClanMode) = 0) then
   409             if (AliveCount <= 1) and ((GameFlags and gfOneClanMode) = 0) then
   438         end
   417         end
   439     end;
   418     end;
   440 
   419 
   441 if TurnTimeLeft > 0 then
   420 if TurnTimeLeft > 0 then
   442     if CurrentHedgehog^.Gear <> nil then
   421     if CurrentHedgehog^.Gear <> nil then
   443         if ((CurrentHedgehog^.Gear^.State and gstAttacking) = 0) and 
   422         if ((CurrentHedgehog^.Gear^.State and gstAttacking) = 0) and
   444             (not (isInMultiShoot and (CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle]))) then
   423             (not (isInMultiShoot and (CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle]))) then
   445                 begin
   424                 begin
   446                 if (TurnTimeLeft = 5000)
   425                 if (TurnTimeLeft = 5000)
   447                 and (cHedgehogTurnTime >= 10000)
   426                 and (cHedgehogTurnTime >= 10000)
   448                 and (not PlacingHogs)
   427                 and (not PlacingHogs)
   546     if (GameFlags and gfResetHealth) <> 0 then
   525     if (GameFlags and gfResetHealth) <> 0 then
   547         for i:= 0 to Pred(TeamsCount) do
   526         for i:= 0 to Pred(TeamsCount) do
   548             RecountTeamHealth(TeamsArray[i])
   527             RecountTeamHealth(TeamsArray[i])
   549 end;
   528 end;
   550 
   529 
   551 procedure SetAllToActive;
       
   552 var t: PGear;
       
   553 begin
       
   554 AllInactive:= false;
       
   555 t:= GearsList;
       
   556 while t <> nil do
       
   557     begin
       
   558     t^.Active:= true;
       
   559     t:= t^.NextGear
       
   560     end
       
   561 end;
       
   562 
       
   563 procedure SetAllHHToActive(Ice: boolean);
       
   564 var t: PGear;
       
   565 begin
       
   566 AllInactive:= false;
       
   567 t:= GearsList;
       
   568 while t <> nil do
       
   569     begin
       
   570     if (t^.Kind = gtHedgehog) or (t^.Kind = gtExplosives) then
       
   571         begin
       
   572         if (t^.Kind = gtHedgehog) and Ice then CheckIce(t);
       
   573         t^.Active:= true
       
   574         end;
       
   575     t:= t^.NextGear
       
   576     end
       
   577 end;
       
   578 
       
   579 procedure DrawGears;
   530 procedure DrawGears;
   580 var Gear: PGear;
   531 var Gear: PGear;
   581     x, y: LongInt;
   532     x, y: LongInt;
   582 begin
   533 begin
   583 Gear:= GearsList;
   534 Gear:= GearsList;
   667 snowLeft:= -(snowRight-LAND_WIDTH);
   618 snowLeft:= -(snowRight-LAND_WIDTH);
   668 
   619 
   669 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then
   620 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then
   670     for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do
   621     for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do
   671         AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0);
   622         AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0);
   672 end;
       
   673 
       
   674 
       
   675 procedure ShotgunShot(Gear: PGear);
       
   676 var t: PGear;
       
   677     dmg, r, dist: LongInt;
       
   678     dx, dy: hwFloat;
       
   679 begin
       
   680 Gear^.Radius:= cShotgunRadius;
       
   681 t:= GearsList;
       
   682 while t <> nil do
       
   683     begin
       
   684     case t^.Kind of
       
   685         gtHedgehog,
       
   686             gtMine,
       
   687             gtSMine,
       
   688             gtKnife,
       
   689             gtCase,
       
   690             gtTarget,
       
   691             gtExplosives: begin//,
       
   692 //            gtStructure: begin
       
   693 //addFileLog('ShotgunShot radius: ' + inttostr(Gear^.Radius) + ', t^.Radius = ' + inttostr(t^.Radius) + ', distance = ' + inttostr(dist) + ', dmg = ' + inttostr(dmg));
       
   694                     dmg:= 0;
       
   695                     r:= Gear^.Radius + t^.Radius;
       
   696                     dx:= Gear^.X-t^.X;
       
   697                     dx.isNegative:= false;
       
   698                     dy:= Gear^.Y-t^.Y;
       
   699                     dy.isNegative:= false;
       
   700                     if r-hwRound(dx+dy) > 0 then
       
   701                         begin
       
   702                         dist:= hwRound(Distance(dx, dy));
       
   703                         dmg:= ModifyDamage(min(r - dist, 25), t);
       
   704                         end;
       
   705                     if dmg > 0 then
       
   706                         begin
       
   707                         if (not t^.Invulnerable) then
       
   708                             ApplyDamage(t, Gear^.Hedgehog, dmg, dsBullet)
       
   709                         else
       
   710                             Gear^.State:= Gear^.State or gstWinner;
       
   711 
       
   712                         DeleteCI(t);
       
   713                         t^.dX:= t^.dX + Gear^.dX * dmg * _0_01 + SignAs(cHHKick, Gear^.dX);
       
   714                         t^.dY:= t^.dY + Gear^.dY * dmg * _0_01;
       
   715                         t^.State:= t^.State or gstMoving;
       
   716                         if t^.Kind = gtKnife then t^.State:= (t^.State and (not gstCollision));
       
   717                         t^.Active:= true;
       
   718                         FollowGear:= t
       
   719                         end
       
   720                     end;
       
   721             gtGrave: begin
       
   722                     dmg:= 0;
       
   723                     r:= Gear^.Radius + t^.Radius;
       
   724                     dx:= Gear^.X-t^.X;
       
   725                     dx.isNegative:= false;
       
   726                     dy:= Gear^.Y-t^.Y;
       
   727                     dy.isNegative:= false;
       
   728                     if r-hwRound(dx+dy) > 0 then
       
   729                         begin
       
   730                         dist:= hwRound(Distance(dx, dy));
       
   731                         dmg:= ModifyDamage(min(r - dist, 25), t);
       
   732                         end;
       
   733                     if dmg > 0 then
       
   734                         begin
       
   735                         t^.dY:= - _0_1;
       
   736                         t^.Active:= true
       
   737                         end
       
   738                     end;
       
   739         end;
       
   740     t:= t^.NextGear
       
   741     end;
       
   742 if (GameFlags and gfSolidLand) = 0 then
       
   743     DrawExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cShotgunRadius)
       
   744 end;
       
   745 
       
   746 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
       
   747 var t: PGearArray;
       
   748     Gear: PGear;
       
   749     i, j, tmpDmg: LongInt;
       
   750     VGear: PVisualGear;
       
   751 begin
       
   752 t:= CheckGearsCollision(Ammo);
       
   753 // Just to avoid hogs on rope dodging fire.
       
   754 if (CurAmmoGear <> nil) and ((CurAmmoGear^.Kind = gtRope) or (CurAmmoGear^.Kind = gtJetpack) or (CurAmmoGear^.Kind = gtBirdy))
       
   755 and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1)
       
   756 and (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then
       
   757     begin
       
   758     t^.ar[t^.Count]:= CurrentHedgehog^.Gear;
       
   759     inc(t^.Count)
       
   760     end;
       
   761 
       
   762 i:= t^.Count;
       
   763 
       
   764 if (Ammo^.Kind = gtFlame) and (i > 0) then
       
   765     Ammo^.Health:= 0;
       
   766 while i > 0 do
       
   767     begin
       
   768     dec(i);
       
   769     Gear:= t^.ar[i];
       
   770     if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and 
       
   771        (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then
       
   772         Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000);
       
   773     tmpDmg:= ModifyDamage(Damage, Gear);
       
   774     if (Gear^.State and gstNoDamage) = 0 then
       
   775         begin
       
   776 
       
   777         if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then
       
   778             begin
       
   779             VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
       
   780             if VGear <> nil then
       
   781                 VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
       
   782             end;
       
   783 
       
   784         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then
       
   785             Gear^.FlightTime:= 1;
       
   786 
       
   787 
       
   788         case Gear^.Kind of
       
   789             gtHedgehog,
       
   790             gtMine,
       
   791             gtSMine,
       
   792             gtKnife,
       
   793             gtTarget,
       
   794             gtCase,
       
   795             gtExplosives: //,
       
   796             //gtStructure:
       
   797             begin
       
   798             if (Ammo^.Kind = gtDrill) then
       
   799                 begin
       
   800                 Ammo^.Timer:= 0;
       
   801                 exit;
       
   802                 end;
       
   803             if (not Gear^.Invulnerable) then
       
   804                 begin
       
   805                 if (Ammo^.Kind = gtKnife) and (tmpDmg > 0) then
       
   806                     for j:= 1 to max(1,min(3,tmpDmg div 5)) do
       
   807                         begin
       
   808                         VGear:= AddVisualGear(hwRound(Ammo^.X-((Ammo^.X-Gear^.X)/_2)), hwRound(Ammo^.Y-((Ammo^.Y-Gear^.Y)/_2)), vgtStraightShot);
       
   809                         if VGear <> nil then
       
   810                             with VGear^ do
       
   811                                 begin
       
   812                                 Tint:= $FFCC00FF;
       
   813                                 Angle:= random(360);
       
   814                                 dx:= 0.0005 * (random(100));
       
   815                                 dy:= 0.0005 * (random(100));
       
   816                                 if random(2) = 0 then
       
   817                                     dx := -dx;
       
   818                                 if random(2) = 0 then
       
   819                                     dy := -dy;
       
   820                                 FrameTicks:= 600+random(200);
       
   821                                 State:= ord(sprStar)
       
   822                                 end
       
   823                         end;
       
   824                 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove)
       
   825                 end
       
   826             else
       
   827                 Gear^.State:= Gear^.State or gstWinner;
       
   828             if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then
       
   829                 begin
       
   830                 if (Ammo^.Hedgehog^.Gear <> nil) then
       
   831                     Ammo^.Hedgehog^.Gear^.State:= (Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable));
       
   832                 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch
       
   833                 end;
       
   834 
       
   835             if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then
       
   836                 begin
       
   837                 Gear^.dX:= Ammo^.dX * Power * _0_005;
       
   838                 Gear^.dY:= Ammo^.dY * Power * _0_005
       
   839                 end
       
   840             else if ((Ammo^.Kind <> gtFlame) or (Gear^.Kind = gtHedgehog)) and (Power <> 0) then
       
   841                 begin
       
   842                 Gear^.dX:= Ammo^.dX * Power * _0_01;
       
   843                 Gear^.dY:= Ammo^.dY * Power * _0_01
       
   844                 end;
       
   845 
       
   846             if (not isZero(Gear^.dX)) or (not isZero(Gear^.dY)) then
       
   847                 begin
       
   848                 Gear^.Active:= true;
       
   849                 DeleteCI(Gear);
       
   850                 Gear^.State:= Gear^.State or gstMoving;
       
   851                 if Gear^.Kind = gtKnife then Gear^.State:= (Gear^.State and (not gstCollision));
       
   852                 // move the gear upwards a bit to throw it over tiny obstacles at start
       
   853                 if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
       
   854                     begin
       
   855                     if (not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX)))
       
   856                     or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   857                         Gear^.Y:= Gear^.Y - _1;
       
   858                     if (not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)))
       
   859                     or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   860                         Gear^.Y:= Gear^.Y - _1;
       
   861                     if (not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)))
       
   862                     or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   863                         Gear^.Y:= Gear^.Y - _1;
       
   864                     end
       
   865                 end;
       
   866 
       
   867 
       
   868             if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then
       
   869                 FollowGear:= Gear
       
   870             end;
       
   871         end
       
   872         end;
       
   873     end;
       
   874 if i <> 0 then
       
   875     SetAllToActive
       
   876 end;
   623 end;
   877 
   624 
   878 procedure AssignHHCoords;
   625 procedure AssignHHCoords;
   879 var i, t, p, j: LongInt;
   626 var i, t, p, j: LongInt;
   880     ar: array[0..Pred(cMaxHHs)] of PHedgehog;
   627     ar: array[0..Pred(cMaxHHs)] of PHedgehog;
   937         dec(Count)
   684         dec(Count)
   938         end
   685         end
   939     end
   686     end
   940 end;
   687 end;
   941 
   688 
   942 var GearsNearArray : TPGearArray;
       
   943 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS;
       
   944 var
       
   945     t: PGear;
       
   946     s: Longword;
       
   947 begin
       
   948     r:= r*r;
       
   949     s:= 0;
       
   950     SetLength(GearsNearArray, s);
       
   951     t := GearsList;
       
   952     while t <> nil do
       
   953         begin
       
   954         if (t^.Kind = Kind)
       
   955             and ((X - t^.X)*(X - t^.X) + (Y - t^.Y)*(Y-t^.Y) < int2hwFloat(r)) then
       
   956             begin
       
   957             inc(s);
       
   958             SetLength(GearsNearArray, s);
       
   959             GearsNearArray[s - 1] := t;
       
   960             end;
       
   961         t := t^.NextGear;
       
   962     end;
       
   963 
       
   964     GearsNear.size:= s;
       
   965     GearsNear.ar:= @GearsNearArray
       
   966 end;
       
   967 
   689 
   968 {procedure AmmoFlameWork(Ammo: PGear);
   690 {procedure AmmoFlameWork(Ammo: PGear);
   969 var t: PGear;
   691 var t: PGear;
   970 begin
   692 begin
   971 t:= GearsList;
   693 t:= GearsList;
   984     t:= t^.NextGear
   706     t:= t^.NextGear
   985     end;
   707     end;
   986 end;}
   708 end;}
   987 
   709 
   988 
   710 
   989 function CountGears(Kind: TGearType): Longword;
       
   990 var t: PGear;
       
   991     count: Longword = 0;
       
   992 begin
       
   993 
       
   994 t:= GearsList;
       
   995 while t <> nil do
       
   996     begin
       
   997     if t^.Kind = Kind then
       
   998         inc(count);
       
   999     t:= t^.NextGear
       
  1000     end;
       
  1001 CountGears:= count;
       
  1002 end;
       
  1003 
       
  1004 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear;
   711 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear;
  1005 begin
   712 begin
  1006     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
   713     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
  1007     cCaseFactor := 0;
   714     cCaseFactor := 0;
  1008 
   715 
  1069 
   776 
  1070     if ( (x = 0) and (y = 0) ) then
   777     if ( (x = 0) and (y = 0) ) then
  1071         FindPlace(FollowGear, true, 0, LAND_WIDTH);
   778         FindPlace(FollowGear, true, 0, LAND_WIDTH);
  1072 
   779 
  1073     SpawnFakeCrateAt := FollowGear;
   780     SpawnFakeCrateAt := FollowGear;
  1074 end;
       
  1075 
       
  1076 function GetAmmo(Hedgehog: PHedgehog): TAmmoType;
       
  1077 var t, aTot: LongInt;
       
  1078     i: TAmmoType;
       
  1079 begin
       
  1080 Hedgehog:= Hedgehog; // avoid hint
       
  1081 
       
  1082 aTot:= 0;
       
  1083 for i:= Low(TAmmoType) to High(TAmmoType) do
       
  1084     if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
       
  1085         inc(aTot, Ammoz[i].Probability);
       
  1086 
       
  1087 t:= aTot;
       
  1088 i:= Low(TAmmoType);
       
  1089 if (t > 0) then
       
  1090     begin
       
  1091     t:= GetRandom(t);
       
  1092     while t >= 0 do
       
  1093         begin
       
  1094         inc(i);
       
  1095         if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
       
  1096             dec(t, Ammoz[i].Probability)
       
  1097         end
       
  1098     end;
       
  1099 GetAmmo:= i
       
  1100 end;
       
  1101 
       
  1102 function GetUtility(Hedgehog: PHedgehog): TAmmoType;
       
  1103 var t, uTot: LongInt;
       
  1104     i: TAmmoType;
       
  1105 begin
       
  1106 
       
  1107 uTot:= 0;
       
  1108 for i:= Low(TAmmoType) to High(TAmmoType) do
       
  1109     if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0)
       
  1110     and ((Hedgehog^.Team^.HedgehogsNumber > 1) or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
       
  1111         inc(uTot, Ammoz[i].Probability);
       
  1112 
       
  1113 t:= uTot;
       
  1114 i:= Low(TAmmoType);
       
  1115 if (t > 0) then
       
  1116     begin
       
  1117     t:= GetRandom(t);
       
  1118     while t >= 0 do
       
  1119         begin
       
  1120         inc(i);
       
  1121         if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) and ((Hedgehog^.Team^.HedgehogsNumber > 1)
       
  1122         or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
       
  1123             dec(t, Ammoz[i].Probability)
       
  1124         end
       
  1125     end;
       
  1126 GetUtility:= i
       
  1127 end;
       
  1128 
       
  1129 
       
  1130 
       
  1131 procedure SpawnBoxOfSmth;
       
  1132 var t, aTot, uTot, a, h: LongInt;
       
  1133     i: TAmmoType;
       
  1134 begin
       
  1135 if (PlacingHogs) or
       
  1136     (cCaseFactor = 0)
       
  1137     or (CountGears(gtCase) >= 5)
       
  1138     or (GetRandom(cCaseFactor) <> 0) then
       
  1139        exit;
       
  1140 
       
  1141 FollowGear:= nil;
       
  1142 aTot:= 0;
       
  1143 uTot:= 0;
       
  1144 for i:= Low(TAmmoType) to High(TAmmoType) do
       
  1145     if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
       
  1146         inc(aTot, Ammoz[i].Probability)
       
  1147     else
       
  1148         inc(uTot, Ammoz[i].Probability);
       
  1149 
       
  1150 t:=0;
       
  1151 a:=aTot;
       
  1152 h:= 1;
       
  1153 
       
  1154 if (aTot+uTot) <> 0 then
       
  1155     if ((GameFlags and gfInvulnerable) = 0) then
       
  1156         begin
       
  1157         h:= cHealthCaseProb * 100;
       
  1158         t:= GetRandom(10000);
       
  1159         a:= (10000-h)*aTot div (aTot+uTot)
       
  1160         end
       
  1161     else
       
  1162         begin
       
  1163         t:= GetRandom(aTot+uTot);
       
  1164         h:= 0
       
  1165         end;
       
  1166 
       
  1167 
       
  1168 if t<h then
       
  1169     begin
       
  1170     FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
       
  1171     FollowGear^.Health:= cHealthCaseAmount;
       
  1172     FollowGear^.Pos:= posCaseHealth;
       
  1173     AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo);
       
  1174     end
       
  1175 else if (t<a+h) then
       
  1176     begin
       
  1177     t:= aTot;
       
  1178     if (t > 0) then
       
  1179         begin
       
  1180         FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
       
  1181         t:= GetRandom(t);
       
  1182         i:= Low(TAmmoType);
       
  1183         FollowGear^.Pos:= posCaseAmmo;
       
  1184         FollowGear^.AmmoType:= i;
       
  1185         AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo);
       
  1186         end
       
  1187     end
       
  1188 else
       
  1189     begin
       
  1190     t:= uTot;
       
  1191     if (t > 0) then
       
  1192         begin
       
  1193         FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
       
  1194         t:= GetRandom(t);
       
  1195         i:= Low(TAmmoType);
       
  1196         FollowGear^.Pos:= posCaseUtility;
       
  1197         FollowGear^.AmmoType:= i;
       
  1198         AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo);
       
  1199         end
       
  1200     end;
       
  1201 
       
  1202 // handles case of no ammo or utility crates - considered also placing booleans in uAmmos and altering probabilities
       
  1203 if (FollowGear <> nil) then
       
  1204     begin
       
  1205     FindPlace(FollowGear, true, 0, LAND_WIDTH);
       
  1206 
       
  1207     if (FollowGear <> nil) then
       
  1208         AddVoice(sndReinforce, CurrentTeam^.voicepack)
       
  1209     end
       
  1210 end;
   781 end;
  1211 
   782 
  1212 
   783 
  1213 function GearByUID(uid : Longword) : PGear;
   784 function GearByUID(uid : Longword) : PGear;
  1214 var gear: PGear;
   785 var gear: PGear;