hedgewars/uGears.pas
changeset 6580 6155187bf599
parent 6543 697e9b730189
child 6596 4c06ea12de1c
equal deleted inserted replaced
6579:fc52f7c22c9b 6580:6155187bf599
    55 procedure doStepDrowningGear(Gear: PGear);
    55 procedure doStepDrowningGear(Gear: PGear);
    56 
    56 
    57 
    57 
    58 implementation
    58 implementation
    59 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics,
    59 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics,
    60      uAIMisc, uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile, uVariables,
    60     uAIMisc, uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile, uVariables,
    61      uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
    61     uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
    62      uGearsHedgehog, uGearsUtils, uGearsList;
    62     uGearsHedgehog, uGearsUtils, uGearsList;
    63 
    63 
    64 
    64 
    65 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
    65 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
    66 //procedure AmmoFlameWork(Ammo: PGear); forward;
    66 //procedure AmmoFlameWork(Ammo: PGear); forward;
    67 function  GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): TPGearArray; forward;
    67 function  GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): TPGearArray; forward;
    81 begin
    81 begin
    82 CheckNoDamage:= true;
    82 CheckNoDamage:= true;
    83 Gear:= GearsList;
    83 Gear:= GearsList;
    84 while Gear <> nil do
    84 while Gear <> nil do
    85     begin
    85     begin
    86     if (Gear^.Kind = gtHedgehog) and (((GameFlags and gfInfAttack) = 0) or ((Gear^.dX.QWordValue < _0_000004.QWordValue) and (Gear^.dY.QWordValue < _0_000004.QWordValue))) then
    86     if (Gear^.Kind = gtHedgehog) and (((GameFlags and gfInfAttack) = 0) or ((Gear^.dX.QWordValue < _0_000004.QWordValue)
    87         begin
    87     and (Gear^.dY.QWordValue < _0_000004.QWordValue))) then
    88         if (not isInMultiShoot) then inc(Gear^.Damage, Gear^.Karma);
    88         begin
    89         if (Gear^.Damage <> 0) and
    89         if (not isInMultiShoot) then
    90         (not Gear^.Invulnerable) then
    90             inc(Gear^.Damage, Gear^.Karma);
       
    91         if (Gear^.Damage <> 0) and (not Gear^.Invulnerable) then
    91             begin
    92             begin
    92             CheckNoDamage:= false;
    93             CheckNoDamage:= false;
    93 
    94 
    94             dmg:= Gear^.Damage;
    95             dmg:= Gear^.Damage;
    95             if Gear^.Health < dmg then
    96             if Gear^.Health < dmg then
    98                 Gear^.Health:= 0
    99                 Gear^.Health:= 0
    99                 end
   100                 end
   100             else
   101             else
   101                 dec(Gear^.Health, dmg);
   102                 dec(Gear^.Health, dmg);
   102 
   103 
   103             if (Gear^.Hedgehog^.Team = CurrentTeam) and
   104             if (Gear^.Hedgehog^.Team = CurrentTeam) and (Gear^.Damage <> Gear^.Karma)
   104                (Gear^.Damage <> Gear^.Karma) and
   105             and (not Gear^.Hedgehog^.King) and (not Gear^.Hedgehog^.Effects[hePoisoned]) and (not SuddenDeathDmg) then
   105                 (not Gear^.Hedgehog^.King) and
       
   106                 (not Gear^.Hedgehog^.Effects[hePoisoned]) and
       
   107                 (not SuddenDeathDmg) then
       
   108                 Gear^.State:= Gear^.State or gstLoser;
   106                 Gear^.State:= Gear^.State or gstLoser;
   109 
   107 
   110             spawnHealthTagForHH(Gear, dmg);
   108             spawnHealthTagForHH(Gear, dmg);
   111 
   109 
   112             RenderHealth(Gear^.Hedgehog^);
   110             RenderHealth(Gear^.Hedgehog^);
   113             RecountTeamHealth(Gear^.Hedgehog^.Team);
   111             RecountTeamHealth(Gear^.Hedgehog^.Team);
   114 
   112 
   115             end;
   113             end;
   116         if (not isInMultiShoot) then Gear^.Karma:= 0;
   114         if (not isInMultiShoot) then
       
   115             Gear^.Karma:= 0;
   117         Gear^.Damage:= 0
   116         Gear^.Damage:= 0
   118         end;
   117         end;
   119     Gear:= Gear^.NextGear
   118     Gear:= Gear^.NextGear
   120     end;
   119     end;
   121 end;
   120 end;
   122 
   121 
   123 procedure HealthMachine;
   122 procedure HealthMachine;
   124 var Gear: PGear;
   123 var Gear: PGear;
   125     team: PTeam;
   124     team: PTeam;
   126        i: LongWord;
   125     i: LongWord;
   127     flag: Boolean;
   126     flag: Boolean;
   128      tmp: LongWord;
   127     tmp: LongWord;
   129 begin
   128 begin
   130     Gear:= GearsList;
   129     Gear:= GearsList;
   131 
   130 
   132     while Gear <> nil do
   131     while Gear <> nil do
   133     begin
   132     begin
   135             begin
   134             begin
   136             tmp:= 0;
   135             tmp:= 0;
   137             if Gear^.Hedgehog^.Effects[hePoisoned] then
   136             if Gear^.Hedgehog^.Effects[hePoisoned] then
   138                 begin
   137                 begin
   139                 inc(tmp, ModifyDamage(5, Gear));
   138                 inc(tmp, ModifyDamage(5, Gear));
   140                 if (GameFlags and gfResetHealth) <> 0 then dec(Gear^.Hedgehog^.InitialHealth)  // does not need a minimum check since <= 1 basically disables it
   139                 if (GameFlags and gfResetHealth) <> 0 then
       
   140                     dec(Gear^.Hedgehog^.InitialHealth)  // does not need a minimum check since <= 1 basically disables it
   141                 end;
   141                 end;
   142             if (TotalRounds > cSuddenDTurns - 1) then
   142             if (TotalRounds > cSuddenDTurns - 1) then
   143                 begin
   143                 begin
   144                 inc(tmp, cHealthDecrease);
   144                 inc(tmp, cHealthDecrease);
   145                 if (GameFlags and gfResetHealth) <> 0 then dec(Gear^.Hedgehog^.InitialHealth, cHealthDecrease)
   145                 if (GameFlags and gfResetHealth) <> 0 then
       
   146                     dec(Gear^.Hedgehog^.InitialHealth, cHealthDecrease)
   146                 end;
   147                 end;
   147             if Gear^.Hedgehog^.King then
   148             if Gear^.Hedgehog^.King then
   148                 begin
   149                 begin
   149                 flag:= false;
   150                 flag:= false;
   150                 team:= Gear^.Hedgehog^.Team;
   151                 team:= Gear^.Hedgehog^.Team;
   151                 for i:= 0 to Pred(team^.HedgehogsNumber) do
   152                 for i:= 0 to Pred(team^.HedgehogsNumber) do
   152                     if (team^.Hedgehogs[i].Gear <> nil) and
   153                     if (team^.Hedgehogs[i].Gear <> nil) and (not team^.Hedgehogs[i].King)
   153                         (not team^.Hedgehogs[i].King) and
   154                     and (team^.Hedgehogs[i].Gear^.Health > team^.Hedgehogs[i].Gear^.Damage) then
   154                         (team^.Hedgehogs[i].Gear^.Health > team^.Hedgehogs[i].Gear^.Damage)
   155                         flag:= true;
   155                     then flag:= true;
       
   156                 if not flag then
   156                 if not flag then
   157                     begin
   157                     begin
   158                     inc(tmp, 5);
   158                     inc(tmp, 5);
   159                     if (GameFlags and gfResetHealth) <> 0 then dec(Gear^.Hedgehog^.InitialHealth, 5)
   159                     if (GameFlags and gfResetHealth) <> 0 then
       
   160                         dec(Gear^.Hedgehog^.InitialHealth, 5)
   160                     end
   161                     end
   161                 end;
   162                 end;
   162             if tmp > 0 then 
   163             if tmp > 0 then 
   163                 begin
   164                 begin
   164                 inc(Gear^.Damage, min(tmp, max(0,Gear^.Health - 1 - Gear^.Damage)));
   165                 inc(Gear^.Damage, min(tmp, max(0,Gear^.Health - 1 - Gear^.Damage)));
   170     end;
   171     end;
   171 end;
   172 end;
   172 
   173 
   173 procedure ProcessGears;
   174 procedure ProcessGears;
   174 const delay: LongWord = 0;
   175 const delay: LongWord = 0;
   175       delay2: LongWord = 0;
   176     delay2: LongWord = 0;
   176     step: (stDelay, stChDmg, stSweep, stTurnReact,
   177     step: (stDelay, stChDmg, stSweep, stTurnReact,
   177             stAfterDelay, stChWin, stWater, stChWin2, stHealth,
   178     stAfterDelay, stChWin, stWater, stChWin2, stHealth,
   178             stSpawn, stNTurn) = stDelay;
   179     stSpawn, stNTurn) = stDelay;
   179 var Gear, t: PGear;
   180 var Gear, t: PGear;
   180     i, AliveCount: LongInt;
   181     i, AliveCount: LongInt;
   181     s: shortstring;
   182     s: shortstring;
   182 begin
   183 begin
   183 PrvInactive:= AllInactive;
   184 PrvInactive:= AllInactive;
   213         end
   214         end
   214     end;
   215     end;
   215 
   216 
   216 if AllInactive then
   217 if AllInactive then
   217 case step of
   218 case step of
   218     stDelay: begin
   219     stDelay:
       
   220         begin
   219         if delay = 0 then
   221         if delay = 0 then
   220             delay:= cInactDelay
   222             delay:= cInactDelay
   221         else
   223         else
   222             dec(delay);
   224             dec(delay);
   223 
   225 
   224         if delay = 0 then
   226         if delay = 0 then
   225             inc(step)
   227             inc(step)
   226         end;
   228         end;
   227     stChDmg: if CheckNoDamage then inc(step) else step:= stDelay;
   229         
   228     stSweep: if SweepDirty then
   230     stChDmg:
   229                 begin
   231     if CheckNoDamage then
   230                 SetAllToActive;
   232         inc(step)
   231                 step:= stChDmg
   233     else
   232                 end else inc(step);
   234         step:= stDelay;
   233     stTurnReact: begin
   235         
       
   236     stSweep:
       
   237     if SweepDirty then
       
   238         begin
       
   239         SetAllToActive;
       
   240         step:= stChDmg
       
   241         end
       
   242     else
       
   243         inc(step);
       
   244         
       
   245     stTurnReact:
       
   246         begin
   234         if (not bBetweenTurns) and (not isInMultiShoot) then
   247         if (not bBetweenTurns) and (not isInMultiShoot) then
   235             begin
   248             begin
   236             uStats.TurnReaction;
   249             uStats.TurnReaction;
   237             inc(step)
   250             inc(step)
   238         end else
   251             end
       
   252         else
   239             inc(step, 2);
   253             inc(step, 2);
   240         end;
   254         end;
   241     stAfterDelay: begin
   255         
       
   256     stAfterDelay:
       
   257         begin
   242         if delay = 0 then
   258         if delay = 0 then
   243             delay:= cInactDelay
   259             delay:= cInactDelay
   244         else
   260         else
   245             dec(delay);
   261             dec(delay);
   246 
   262 
   247         if delay = 0 then
   263         if delay = 0 then
       
   264             inc(step)
       
   265             end;
       
   266     stChWin:
       
   267         begin
       
   268         CheckForWin;
   248         inc(step)
   269         inc(step)
   249         end;
   270         end;
   250     stChWin: begin
   271     stWater:
   251             CheckForWin;
   272     if (not bBetweenTurns) and (not isInMultiShoot) then
   252             inc(step)
   273         begin
   253             end;
   274         if TotalRounds = cSuddenDTurns + 1 then
   254     stWater: if (not bBetweenTurns) and (not isInMultiShoot) then
   275             bWaterRising:= true;
   255                 begin
   276         if bWaterRising and (cWaterRise > 0) then
   256                 if TotalRounds = cSuddenDTurns + 1 then bWaterRising:= true;
   277             AddGear(0, 0, gtWaterUp, 0, _0, _0, 0)^.Tag:= cWaterRise;
   257 
   278         inc(step)
   258                 if bWaterRising and (cWaterRise > 0) then
   279         end
   259                     AddGear(0, 0, gtWaterUp, 0, _0, _0, 0)^.Tag:= cWaterRise;
   280     else
   260 
   281         inc(step);
   261                 inc(step)
   282     stChWin2:
   262                 end else inc(step);
   283         begin
   263     stChWin2: begin
   284         CheckForWin;
   264             CheckForWin;
   285         inc(step)
   265             inc(step)
   286         end;
   266             end;
   287 
   267     stHealth: begin
   288     stHealth:
   268             if (cWaterRise <> 0) or (cHealthDecrease <> 0) then
   289         begin
   269                 begin
   290         if (cWaterRise <> 0) or (cHealthDecrease <> 0) then
   270                 if (TotalRounds = cSuddenDTurns) and (not SuddenDeath) and (not isInMultiShoot) then
   291              begin
       
   292             if (TotalRounds = cSuddenDTurns) and (not SuddenDeath) and (not isInMultiShoot) then
       
   293                 begin
       
   294                 SuddenDeath:= true;
       
   295                 if cHealthDecrease <> 0 then
   271                     begin
   296                     begin
   272                     SuddenDeath:= true;
   297                     SuddenDeathDmg:= true;
   273                     if cHealthDecrease <> 0 then
       
   274                         begin
       
   275                         SuddenDeathDmg:= true;
       
   276                         
   298                         
   277                         // flash
   299                     // flash
   278                         ScreenFade:= sfFromWhite;
   300                     ScreenFade:= sfFromWhite;
   279                         ScreenFadeValue:= sfMax;
   301                     ScreenFadeValue:= sfMax;
   280                         ScreenFadeSpeed:= 1;
   302                     ScreenFadeSpeed:= 1;
   281                         
   303                     
   282                         ChangeToSDClouds;
   304                     ChangeToSDClouds;
   283                         ChangeToSDFlakes;
   305                     ChangeToSDFlakes;
   284                         glClearColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255, 0.99);
   306                     glClearColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255, 0.99);
   285                         Ammoz[amTardis].SkipTurns:= 9999;
   307                     Ammoz[amTardis].SkipTurns:= 9999;
   286                         Ammoz[amTardis].Probability:= 0;
   308                     Ammoz[amTardis].Probability:= 0;
   287                         end;
   309                     end;
   288                     AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
   310                 AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
   289                     playSound(sndSuddenDeath);
   311                 playSound(sndSuddenDeath);
   290                     StopMusic //No SDMusic for now
   312                 StopMusic //No SDMusic for now
   291                     //MusicFN:= SDMusic;
   313                     //MusicFN:= SDMusic;
   292                     //ChangeMusic
   314                     //ChangeMusic
   293                     end
   315                     end
   294                 else if (TotalRounds < cSuddenDTurns) and (not isInMultiShoot) then
   316                 else if (TotalRounds < cSuddenDTurns) and (not isInMultiShoot) then
   295                     begin
   317                     begin
   300                     else if (i = 2) or ((i > 0) and ((i mod 50 = 0) or ((i <= 25) and (i mod 5 = 0)))) then
   322                     else if (i = 2) or ((i > 0) and ((i mod 50 = 0) or ((i <= 25) and (i mod 5 = 0)))) then
   301                         AddCaption(Format(trmsg[sidRoundsSD], s), cWhiteColor, capgrpGameState);
   323                         AddCaption(Format(trmsg[sidRoundsSD], s), cWhiteColor, capgrpGameState);
   302                     end;
   324                     end;
   303                 end;
   325                 end;
   304             if bBetweenTurns
   326             if bBetweenTurns
   305                 or isInMultiShoot
   327             or isInMultiShoot
   306                 or (TotalRounds = -1) then inc(step)
   328             or (TotalRounds = -1) then
   307             else begin
   329                 inc(step)
       
   330             else
       
   331                 begin
   308                 bBetweenTurns:= true;
   332                 bBetweenTurns:= true;
   309                 HealthMachine;
   333                 HealthMachine;
   310                 step:= stChDmg
   334                 step:= stChDmg
   311                 end
   335                 end
   312             end;
   336             end;
   313     stSpawn: begin
   337     stSpawn:
   314             if not isInMultiShoot then SpawnBoxOfSmth;
   338         begin
   315             inc(step)
   339         if not isInMultiShoot then
   316             end;
   340             SpawnBoxOfSmth;
   317     stNTurn: begin
   341         inc(step)
   318             if isInMultiShoot then
   342         end;
   319                 isInMultiShoot:= false
   343     stNTurn:
   320             else begin
   344         begin
   321                 // delayed till after 0.9.12
   345         if isInMultiShoot then
   322                 // reset to default zoom
   346             isInMultiShoot:= false
   323                 //ZoomValue:= ZoomDefault;
   347         else
   324                 with CurrentHedgehog^ do
   348             begin
   325                     if (Gear <> nil)
   349             // delayed till after 0.9.12
   326                         and ((Gear^.State and gstAttacked) = 0)
   350             // reset to default zoom
   327                         and (MultiShootAttacks > 0) then OnUsedAmmo(CurrentHedgehog^);
   351             //ZoomValue:= ZoomDefault;
       
   352             with CurrentHedgehog^ do
       
   353                 if (Gear <> nil)
       
   354                 and ((Gear^.State and gstAttacked) = 0)
       
   355                 and (MultiShootAttacks > 0) then
       
   356                     OnUsedAmmo(CurrentHedgehog^);
   328 
   357 
   329                 EndTurnCleanup;
   358                 EndTurnCleanup;
   330 
   359 
   331                 FreeActionsList; // could send -left, -right and similar commands, so should be called before /nextturn
   360                 FreeActionsList; // could send -left, -right and similar commands, so should be called before /nextturn
   332 
   361 
   345         delay2:= cInactDelay * 50
   374         delay2:= cInactDelay * 50
   346     else
   375     else
   347         begin
   376         begin
   348         dec(delay2);
   377         dec(delay2);
   349 
   378 
   350         if ((delay2 mod cInactDelay) = 0) and (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and (not CurrentHedgehog^.Unplaced) then
   379         if ((delay2 mod cInactDelay) = 0) and (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil)
   351             begin
   380         and (not CurrentHedgehog^.Unplaced) then
   352             if (CurrentHedgehog^.Gear^.State and gstAttacked <> 0) and (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0) then
   381             begin
       
   382             if (CurrentHedgehog^.Gear^.State and gstAttacked <> 0)
       
   383             and (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0) then
   353                 begin
   384                 begin
   354                 CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstHHChooseTarget;
   385                 CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstHHChooseTarget;
   355                 isCursorVisible := true
   386                 isCursorVisible := true
   356                 end;
   387                 end;
   357             CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State and (not gstAttacked);
   388             CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State and (not gstAttacked);
   358             end;
   389             end;
   359         if delay2 = 0 then
   390         if delay2 = 0 then
   360             begin
   391             begin
   361             if (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.State and gstAttacked = 0) and (CurAmmoGear = nil) then SweepDirty;
   392             if (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.State and gstAttacked = 0)
       
   393             and (CurAmmoGear = nil) then
       
   394                 SweepDirty;
   362             CheckNoDamage;
   395             CheckNoDamage;
   363             AliveCount:= 0; // shorter version of check for win to allow typical step activity to proceed
   396             AliveCount:= 0; // shorter version of check for win to allow typical step activity to proceed
   364             for i:= 0 to Pred(ClansCount) do
   397             for i:= 0 to Pred(ClansCount) do
   365                 if ClansArray[i]^.ClanHealth > 0 then inc(AliveCount);
   398                 if ClansArray[i]^.ClanHealth > 0 then
       
   399                     inc(AliveCount);
   366             if (AliveCount <= 1) and ((GameFlags and gfOneClanMode) = 0) then
   400             if (AliveCount <= 1) and ((GameFlags and gfOneClanMode) = 0) then
   367                 begin
   401                 begin
   368                 step:= stChDmg;
   402                 step:= stChDmg;
   369                 if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft;
   403                 if TagTurnTimeLeft = 0 then
       
   404                     TagTurnTimeLeft:= TurnTimeLeft;
   370                 TurnTimeLeft:= 0
   405                 TurnTimeLeft:= 0
   371                 end
   406                 end
   372             end
   407             end
   373         end
   408         end
   374     end;
   409     end;
   375 
   410 
   376 if TurnTimeLeft > 0 then
   411 if TurnTimeLeft > 0 then
   377         if CurrentHedgehog^.Gear <> nil then
   412     if CurrentHedgehog^.Gear <> nil then
   378             if ((CurrentHedgehog^.Gear^.State and gstAttacking) = 0)
   413         if ((CurrentHedgehog^.Gear^.State and gstAttacking) = 0)
   379                 and (not isInMultiShoot) then
   414             and (not isInMultiShoot) then
   380                 begin
   415                 begin
   381                 if (TurnTimeLeft = 5000)
   416                 if (TurnTimeLeft = 5000)
   382                     and (cHedgehogTurnTime >= 10000)
   417                 and (cHedgehogTurnTime >= 10000)
   383                     and (not PlacingHogs)
   418                 and (not PlacingHogs)
   384                     and (CurrentHedgehog^.Gear <> nil)
   419                 and (CurrentHedgehog^.Gear <> nil)
   385                     and ((CurrentHedgehog^.Gear^.State and gstAttacked) = 0) then
   420                 and ((CurrentHedgehog^.Gear^.State and gstAttacked) = 0) then
   386                         AddVoice(sndHurry, CurrentTeam^.voicepack);
   421                     AddVoice(sndHurry, CurrentTeam^.voicepack);
   387                 if ReadyTimeLeft > 0 then
   422             if ReadyTimeLeft > 0 then
   388                     begin
   423                 begin
   389                     if ReadyTimeLeft = 2000 then
   424                 if ReadyTimeLeft = 2000 then
   390                         AddVoice(sndComeonthen, CurrentTeam^.voicepack);
   425                     AddVoice(sndComeonthen, CurrentTeam^.voicepack);
   391                     dec(ReadyTimeLeft)
   426                 dec(ReadyTimeLeft)
   392                     end
   427                 end
   393                 else
   428             else
   394                     dec(TurnTimeLeft)
   429                 dec(TurnTimeLeft)
   395                 end;
   430             end;
   396 
   431 
   397 if skipFlag then
   432 if skipFlag then
   398     begin
   433     begin
   399     if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft;
   434     if TagTurnTimeLeft = 0 then
       
   435         TagTurnTimeLeft:= TurnTimeLeft;
   400     TurnTimeLeft:= 0;
   436     TurnTimeLeft:= 0;
   401     skipFlag:= false;
   437     skipFlag:= false;
   402     inc(CurrentHedgehog^.Team^.stats.TurnSkips);
   438     inc(CurrentHedgehog^.Team^.stats.TurnSkips);
   403     end;
   439     end;
   404 
   440 
   499 begin
   535 begin
   500 AllInactive:= false;
   536 AllInactive:= false;
   501 t:= GearsList;
   537 t:= GearsList;
   502 while t <> nil do
   538 while t <> nil do
   503     begin
   539     begin
   504     if (t^.Kind = gtHedgehog) or (t^.Kind = gtExplosives) then t^.Active:= true;
   540     if (t^.Kind = gtHedgehog) or (t^.Kind = gtExplosives) then
       
   541         t^.Active:= true;
   505     t:= t^.NextGear
   542     t:= t^.NextGear
   506     end
   543     end
   507 end;
   544 end;
   508 
   545 
   509 
   546 
   570 if (GameFlags and gfVampiric) <> 0 then
   607 if (GameFlags and gfVampiric) <> 0 then
   571     cVampiric:= true;
   608     cVampiric:= true;
   572 
   609 
   573 Gear:= GearsList;
   610 Gear:= GearsList;
   574 if (GameFlags and gfInvulnerable) <> 0 then
   611 if (GameFlags and gfInvulnerable) <> 0 then
   575    while Gear <> nil do
   612     while Gear <> nil do
   576        begin
   613         begin
   577        Gear^.Invulnerable:= true;  // this is only checked on hogs right now, so no need for gear type check
   614         Gear^.Invulnerable:= true;  // this is only checked on hogs right now, so no need for gear type check
   578        Gear:= Gear^.NextGear
   615         Gear:= Gear^.NextGear
   579        end;
   616         end;
   580 
   617 
   581 if (GameFlags and gfLaserSight) <> 0 then
   618 if (GameFlags and gfLaserSight) <> 0 then
   582     cLaserSighting:= true;
   619     cLaserSighting:= true;
   583 
   620 
   584 if (GameFlags and gfArtillery) <> 0 then
   621 if (GameFlags and gfArtillery) <> 0 then
   653                         end
   690                         end
   654                     end;
   691                     end;
   655         end;
   692         end;
   656     t:= t^.NextGear
   693     t:= t^.NextGear
   657     end;
   694     end;
   658 if (GameFlags and gfSolidLand) = 0 then DrawExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cShotgunRadius)
   695 if (GameFlags and gfSolidLand) = 0 then
       
   696     DrawExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cShotgunRadius)
   659 end;
   697 end;
   660 
   698 
   661 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
   699 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
   662 var t: PGearArray;
   700 var t: PGearArray;
   663     Gear: PGear;
   701     Gear: PGear;
   664     i, tmpDmg: LongInt;
   702     i, tmpDmg: LongInt;
   665     VGear: PVisualGear;
   703     VGear: PVisualGear;
   666 begin
   704 begin
   667 t:= CheckGearsCollision(Ammo);
   705 t:= CheckGearsCollision(Ammo);
   668 // Just to avoid hogs on rope dodging fire.
   706 // Just to avoid hogs on rope dodging fire.
   669 if (CurAmmoGear <> nil) and ((CurAmmoGear^.Kind = gtRope) or (CurAmmoGear^.Kind = gtJetpack) or (CurAmmoGear^.Kind = gtBirdy)) and
   707 if (CurAmmoGear <> nil) and ((CurAmmoGear^.Kind = gtRope) or (CurAmmoGear^.Kind = gtJetpack) or (CurAmmoGear^.Kind = gtBirdy))
   670    (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1) and
   708 and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1)
   671    (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then
   709 and (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then
   672     begin
   710     begin
   673     t^.ar[t^.Count]:= CurrentHedgehog^.Gear;
   711     t^.ar[t^.Count]:= CurrentHedgehog^.Gear;
   674     inc(t^.Count)
   712     inc(t^.Count)
   675     end;
   713     end;
   676 
   714 
   677 i:= t^.Count;
   715 i:= t^.Count;
   678 
   716 
   679 if (Ammo^.Kind = gtFlame) and (i > 0) then Ammo^.Health:= 0;
   717 if (Ammo^.Kind = gtFlame) and (i > 0) then
       
   718     Ammo^.Health:= 0;
   680 while i > 0 do
   719 while i > 0 do
   681     begin
   720     begin
   682     dec(i);
   721     dec(i);
   683     Gear:= t^.ar[i];
   722     Gear:= t^.ar[i];
   684     tmpDmg:= ModifyDamage(Damage, Gear);
   723     tmpDmg:= ModifyDamage(Damage, Gear);
   686         begin
   725         begin
   687 
   726 
   688         if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then 
   727         if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then 
   689             begin
   728             begin
   690             VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
   729             VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
   691             if VGear <> nil then VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
   730             if VGear <> nil then
   692             end;
   731                 VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
   693 
   732             end;
   694         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1;
   733 
       
   734         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then
       
   735             Gear^.FlightTime:= 1;
   695 
   736 
   696         case Gear^.Kind of
   737         case Gear^.Kind of
   697             gtHedgehog,
   738             gtHedgehog,
   698             gtMine,
   739             gtMine,
   699             gtSMine,
   740             gtSMine,
   700             gtTarget,
   741             gtTarget,
   701             gtCase,
   742             gtCase,
   702             gtExplosives,
   743             gtExplosives,
   703             gtStructure: begin
   744             gtStructure:
   704                     if (Ammo^.Kind = gtDrill) then begin Ammo^.Timer:= 0; exit; end;
   745             begin
   705                     if (not Gear^.Invulnerable) then
   746             if (Ammo^.Kind = gtDrill) then
   706                         ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove)
   747                 begin
   707                     else
   748                 Ammo^.Timer:= 0;
   708                         Gear^.State:= Gear^.State or gstWinner;
   749                 exit;
   709                     if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then 
   750                 end;
   710                         begin
   751             if (not Gear^.Invulnerable) then
   711                         if (Ammo^.Hedgehog^.Gear <> nil) then Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable);
   752                 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove)
   712                         ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch
   753             else
   713                         end;
   754                 Gear^.State:= Gear^.State or gstWinner;
   714 
   755             if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then 
   715                     DeleteCI(Gear);
   756                 begin
   716                     if (Gear^.Kind = gtHedgehog) and Gear^.Hedgehog^.King then
   757                 if (Ammo^.Hedgehog^.Gear <> nil) then
   717                         begin
   758                     Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable);
   718                         Gear^.dX:= Ammo^.dX * Power * _0_005;
   759                 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch
   719                         Gear^.dY:= Ammo^.dY * Power * _0_005
   760                 end;
   720                         end
   761 
   721                     else
   762             DeleteCI(Gear);
   722                         begin
   763             if (Gear^.Kind = gtHedgehog) and Gear^.Hedgehog^.King then
   723                         Gear^.dX:= Ammo^.dX * Power * _0_01;
   764                 begin
   724                         Gear^.dY:= Ammo^.dY * Power * _0_01
   765                 Gear^.dX:= Ammo^.dX * Power * _0_005;
   725                         end;
   766                 Gear^.dY:= Ammo^.dY * Power * _0_005
   726 
   767                 end
   727                     Gear^.Active:= true;
   768             else
   728                     Gear^.State:= Gear^.State or gstMoving;
   769                 begin
   729 
   770                 Gear^.dX:= Ammo^.dX * Power * _0_01;
   730                     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   771                 Gear^.dY:= Ammo^.dY * Power * _0_01
   731                         begin
   772                 end;
   732                         if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
   773 
   733                             or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   774             Gear^.Active:= true;
   734                         if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
   775             Gear^.State:= Gear^.State or gstMoving;
   735                             or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   776 
   736                         if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
   777             if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   737                             or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   778                 begin
   738                         end;
   779                 if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
   739 
   780                 or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   740                     if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then FollowGear:= Gear
   781                     Gear^.Y:= Gear^.Y - _1;
   741                     end;
   782                 if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
       
   783                 or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   784                     Gear^.Y:= Gear^.Y - _1;
       
   785                 if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
       
   786                 or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   787                     Gear^.Y:= Gear^.Y - _1;
       
   788                 end;
       
   789 
       
   790             if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then
       
   791                 FollowGear:= Gear
       
   792             end;
   742         end
   793         end
   743         end;
   794         end;
   744     end;
   795     end;
   745 if i <> 0 then SetAllToActive
   796 if i <> 0 then
       
   797     SetAllToActive
   746 end;
   798 end;
   747 
   799 
   748 procedure AssignHHCoords;
   800 procedure AssignHHCoords;
   749 var i, t, p, j: LongInt;
   801 var i, t, p, j: LongInt;
   750     ar: array[0..Pred(cMaxHHs)] of PHedgehog;
   802     ar: array[0..Pred(cMaxHHs)] of PHedgehog;
   751     Count: Longword;
   803     Count: Longword;
   752 begin
   804 begin
   753 if (GameFlags and gfPlaceHog) <> 0 then PlacingHogs:= true;
   805 if (GameFlags and gfPlaceHog) <> 0 then
       
   806     PlacingHogs:= true;
   754 if (GameFlags and gfDivideTeams) <> 0 then
   807 if (GameFlags and gfDivideTeams) <> 0 then
   755     begin
   808     begin
   756     t:= 0;
   809     t:= 0;
   757     TryDo(ClansCount = 2, 'More or less than 2 clans on map in divided teams mode!', true);
   810     TryDo(ClansCount = 2, 'More or less than 2 clans on map in divided teams mode!', true);
   758     for p:= 0 to 1 do
   811     for p:= 0 to 1 do
   762                 with Teams[j]^ do
   815                 with Teams[j]^ do
   763                     for i:= 0 to cMaxHHIndex do
   816                     for i:= 0 to cMaxHHIndex do
   764                         with Hedgehogs[i] do
   817                         with Hedgehogs[i] do
   765                             if (Gear <> nil) and (Gear^.X.QWordValue = 0) then
   818                             if (Gear <> nil) and (Gear^.X.QWordValue = 0) then
   766                                 begin
   819                                 begin
   767                                 if PlacingHogs then Unplaced:= true
   820                                 if PlacingHogs then
   768                                 else FindPlace(Gear, false, t, t + LAND_WIDTH div 2);// could make Gear == nil;
   821                                     Unplaced:= true
       
   822                                 else
       
   823                                     FindPlace(Gear, false, t, t + LAND_WIDTH div 2);// could make Gear == nil;
   769                                 if Gear <> nil then
   824                                 if Gear <> nil then
   770                                     begin
   825                                     begin
   771                                     Gear^.Pos:= GetRandom(49);
   826                                     Gear^.Pos:= GetRandom(49);
   772                                     Gear^.dX.isNegative:= p = 1;
   827                                     Gear^.dX.isNegative:= p = 1;
   773                                     end
   828                                     end
   793     //it would be nice if divide teams, forts mode and hh per map could all be checked by the team widget, or maybe disable start button
   848     //it would be nice if divide teams, forts mode and hh per map could all be checked by the team widget, or maybe disable start button
   794     TryDo(Count <= MaxHedgehogs, 'Too many hedgehogs for this map! (max # is ' + inttostr(MaxHedgehogs) + ')', true);
   849     TryDo(Count <= MaxHedgehogs, 'Too many hedgehogs for this map! (max # is ' + inttostr(MaxHedgehogs) + ')', true);
   795     while (Count > 0) do
   850     while (Count > 0) do
   796         begin
   851         begin
   797         i:= GetRandom(Count);
   852         i:= GetRandom(Count);
   798         if PlacingHogs then ar[i]^.Unplaced:= true
   853         if PlacingHogs then
   799         else FindPlace(ar[i]^.Gear, false, 0, LAND_WIDTH);
   854             ar[i]^.Unplaced:= true
       
   855         else
       
   856             FindPlace(ar[i]^.Gear, false, 0, LAND_WIDTH);
   800         if ar[i]^.Gear <> nil then
   857         if ar[i]^.Gear <> nil then
   801             begin
   858             begin
   802             ar[i]^.Gear^.dX.isNegative:= hwRound(ar[i]^.Gear^.X) > LAND_WIDTH div 2;
   859             ar[i]^.Gear^.dX.isNegative:= hwRound(ar[i]^.Gear^.X) > LAND_WIDTH div 2;
   803             ar[i]^.Gear^.Pos:= GetRandom(19)
   860             ar[i]^.Gear^.Pos:= GetRandom(19)
   804             end;
   861             end;
   856 begin
   913 begin
   857 
   914 
   858 t:= GearsList;
   915 t:= GearsList;
   859 while t <> nil do
   916 while t <> nil do
   860     begin
   917     begin
   861     if t^.Kind = Kind then inc(count);
   918     if t^.Kind = Kind then
       
   919         inc(count);
   862     t:= t^.NextGear
   920     t:= t^.NextGear
   863     end;
   921     end;
   864 CountGears:= count;
   922 CountGears:= count;
   865 end;
   923 end;
   866 
   924 
   867 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content: Longword): PGear;
   925 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content: Longword): PGear;
   868 begin
   926 begin
   869     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
   927     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
   870     cCaseFactor := 0;
   928     cCaseFactor := 0;
   871 
   929 
   872     if (crate <> HealthCrate) and (content > ord(High(TAmmoType))) then content := ord(High(TAmmoType));
   930     if (crate <> HealthCrate) and (content > ord(High(TAmmoType))) then
       
   931         content := ord(High(TAmmoType));
   873 
   932 
   874     case crate of
   933     case crate of
   875         HealthCrate: begin
   934         HealthCrate:
       
   935             begin
   876             FollowGear^.Pos := posCaseHealth;
   936             FollowGear^.Pos := posCaseHealth;
   877             FollowGear^.Health := content;
   937             FollowGear^.Health := content;
   878             AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo);
   938             AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo);
   879             end;
   939             end;
   880         AmmoCrate: begin
   940         AmmoCrate:
       
   941             begin
   881             FollowGear^.Pos := posCaseAmmo;
   942             FollowGear^.Pos := posCaseAmmo;
   882             FollowGear^.AmmoType := TAmmoType(content);
   943             FollowGear^.AmmoType := TAmmoType(content);
   883             AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo);
   944             AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo);
   884             end;
   945             end;
   885         UtilityCrate: begin
   946         UtilityCrate:
       
   947             begin
   886             FollowGear^.Pos := posCaseUtility;
   948             FollowGear^.Pos := posCaseUtility;
   887             FollowGear^.AmmoType := TAmmoType(content);
   949             FollowGear^.AmmoType := TAmmoType(content);
   888             AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo);
   950             AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo);
   889             end;
   951             end;
   890     end;
   952     end;
   891 
   953 
   892     if ( (x = 0) and (y = 0) ) then FindPlace(FollowGear, true, 0, LAND_WIDTH);
   954     if ( (x = 0) and (y = 0) ) then
       
   955         FindPlace(FollowGear, true, 0, LAND_WIDTH);
   893 
   956 
   894     SpawnCustomCrateAt := FollowGear;
   957     SpawnCustomCrateAt := FollowGear;
   895 end;
   958 end;
   896 
   959 
   897 function SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean): PGear;
   960 function SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean): PGear;
   898 begin
   961 begin
   899     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
   962     FollowGear := AddGear(x, y, gtCase, 0, _0, _0, 0);
   900     cCaseFactor := 0;
   963     cCaseFactor := 0;
   901     FollowGear^.Pos := posCaseDummy;
   964     FollowGear^.Pos := posCaseDummy;
   902     
   965     
   903     if explode then FollowGear^.Pos := FollowGear^.Pos + posCaseExplode;
   966     if explode then
   904     if poison then FollowGear^.Pos := FollowGear^.Pos + posCasePoison;
   967         FollowGear^.Pos := FollowGear^.Pos + posCaseExplode;
       
   968     if poison then
       
   969         FollowGear^.Pos := FollowGear^.Pos + posCasePoison;
   905 
   970 
   906     case crate of
   971     case crate of
   907         HealthCrate: begin
   972         HealthCrate:
       
   973             begin
   908             FollowGear^.Pos := FollowGear^.Pos + posCaseHealth;
   974             FollowGear^.Pos := FollowGear^.Pos + posCaseHealth;
   909             AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo);
   975             AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo);
   910             end;
   976             end;
   911         AmmoCrate: begin
   977         AmmoCrate:
       
   978             begin
   912             FollowGear^.Pos := FollowGear^.Pos + posCaseAmmo;
   979             FollowGear^.Pos := FollowGear^.Pos + posCaseAmmo;
   913             AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo);
   980             AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo);
   914             end;
   981             end;
   915         UtilityCrate: begin
   982         UtilityCrate:
       
   983             begin
   916             FollowGear^.Pos := FollowGear^.Pos + posCaseUtility;
   984             FollowGear^.Pos := FollowGear^.Pos + posCaseUtility;
   917             AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo);
   985             AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo);
   918             end;
   986             end;
   919     end;
   987     end;
   920 
   988 
   921     if ( (x = 0) and (y = 0) ) then FindPlace(FollowGear, true, 0, LAND_WIDTH);
   989     if ( (x = 0) and (y = 0) ) then
       
   990         FindPlace(FollowGear, true, 0, LAND_WIDTH);
   922 
   991 
   923     SpawnFakeCrateAt := FollowGear;
   992     SpawnFakeCrateAt := FollowGear;
   924 end;
   993 end;
   925 
   994 
   926 function GetAmmo(Hedgehog: PHedgehog): TAmmoType;
   995 function GetAmmo(Hedgehog: PHedgehog): TAmmoType;
   937 i:= Low(TAmmoType);
  1006 i:= Low(TAmmoType);
   938 if (t > 0) then
  1007 if (t > 0) then
   939     begin
  1008     begin
   940     t:= GetRandom(t);
  1009     t:= GetRandom(t);
   941     while t >= 0 do
  1010     while t >= 0 do
   942       begin
  1011         begin
   943       inc(i);
  1012         inc(i);
   944       if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
  1013         if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then
   945           dec(t, Ammoz[i].Probability)
  1014             dec(t, Ammoz[i].Probability)
   946       end
  1015         end
   947     end;
  1016     end;
   948 GetAmmo:= i
  1017 GetAmmo:= i
   949 end;
  1018 end;
   950 
  1019 
   951 function GetUtility(Hedgehog: PHedgehog): TAmmoType;
  1020 function GetUtility(Hedgehog: PHedgehog): TAmmoType;
   953     i: TAmmoType;
  1022     i: TAmmoType;
   954 begin
  1023 begin
   955 
  1024 
   956 uTot:= 0;
  1025 uTot:= 0;
   957 for i:= Low(TAmmoType) to High(TAmmoType) do
  1026 for i:= Low(TAmmoType) to High(TAmmoType) do
   958     if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) and ((Hedgehog^.Team^.HedgehogsNumber > 1) or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
  1027     if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0)
       
  1028     and ((Hedgehog^.Team^.HedgehogsNumber > 1) or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
   959         inc(uTot, Ammoz[i].Probability);
  1029         inc(uTot, Ammoz[i].Probability);
   960 
  1030 
   961 t:= uTot;
  1031 t:= uTot;
   962 i:= Low(TAmmoType);
  1032 i:= Low(TAmmoType);
   963 if (t > 0) then
  1033 if (t > 0) then
   964     begin
  1034     begin
   965     t:= GetRandom(t);
  1035     t:= GetRandom(t);
   966     while t >= 0 do
  1036     while t >= 0 do
   967       begin
  1037         begin
   968       inc(i);
  1038         inc(i);
   969       if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) and ((Hedgehog^.Team^.HedgehogsNumber > 1) or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
  1039         if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) and ((Hedgehog^.Team^.HedgehogsNumber > 1)
   970           dec(t, Ammoz[i].Probability)
  1040         or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then
   971       end
  1041             dec(t, Ammoz[i].Probability)
       
  1042         end
   972     end;
  1043     end;
   973 GetUtility:= i
  1044 GetUtility:= i
   974 end;
  1045 end;
   975 
  1046 
   976 
  1047 
   978 procedure SpawnBoxOfSmth;
  1049 procedure SpawnBoxOfSmth;
   979 var t, aTot, uTot, a, h: LongInt;
  1050 var t, aTot, uTot, a, h: LongInt;
   980     i: TAmmoType;
  1051     i: TAmmoType;
   981 begin
  1052 begin
   982 if (PlacingHogs) or
  1053 if (PlacingHogs) or
   983    (cCaseFactor = 0) or
  1054     (cCaseFactor = 0)
   984    (CountGears(gtCase) >= 5) or
  1055     or (CountGears(gtCase) >= 5)
   985    (GetRandom(cCaseFactor) <> 0) then exit;
  1056     or (GetRandom(cCaseFactor) <> 0) then
       
  1057        exit;
   986 
  1058 
   987 FollowGear:= nil;
  1059 FollowGear:= nil;
   988 aTot:= 0;
  1060 aTot:= 0;
   989 uTot:= 0;
  1061 uTot:= 0;
   990 for i:= Low(TAmmoType) to High(TAmmoType) do
  1062 for i:= Low(TAmmoType) to High(TAmmoType) do
  1081 
  1153 
  1082 
  1154 
  1083 procedure chSkip(var s: shortstring);
  1155 procedure chSkip(var s: shortstring);
  1084 begin
  1156 begin
  1085 s:= s; // avoid compiler hint
  1157 s:= s; // avoid compiler hint
  1086 if not CurrentTeam^.ExtDriven then SendIPC(',');
  1158 if not CurrentTeam^.ExtDriven then
       
  1159     SendIPC(',');
  1087 uStats.Skipped;
  1160 uStats.Skipped;
  1088 skipFlag:= true
  1161 skipFlag:= true
  1089 end;
  1162 end;
  1090 
  1163 
  1091 procedure chHogSay(var s: shortstring);
  1164 procedure chHogSay(var s: shortstring);
  1100     t:= 0;
  1173     t:= 0;
  1101     x:= byte(s[1]);  // speech type
  1174     x:= byte(s[1]);  // speech type
  1102     if x < 4 then
  1175     if x < 4 then
  1103         begin
  1176         begin
  1104         t:= byte(s[2]);  // team
  1177         t:= byte(s[2]);  // team
  1105         if Length(s) > 2 then h:= byte(s[3])  // target hog
  1178         if Length(s) > 2 then
       
  1179             h:= byte(s[3])  // target hog
  1106         end;
  1180         end;
  1107     // allow targetting a hog by specifying a number as the first portion of the text
  1181     // allow targetting a hog by specifying a number as the first portion of the text
  1108     if (x < 4) and (h > byte('0')) and (h < byte('9')) then i:= h - 48;
  1182     if (x < 4) and (h > byte('0')) and (h < byte('9')) then
  1109     if i <> 0 then text:= copy(s, 4, Length(s) - 1)
  1183         i:= h - 48;
  1110     else if x < 4 then text:= copy(s, 3, Length(s) - 1)
  1184     if i <> 0 then
       
  1185         text:= copy(s, 4, Length(s) - 1)
       
  1186     else if x < 4 then
       
  1187         text:= copy(s, 3, Length(s) - 1)
  1111     else text:= copy(s, 2, Length(s) - 1);
  1188     else text:= copy(s, 2, Length(s) - 1);
  1112 
  1189 
  1113     (*
  1190     (*
  1114     if CheckNoTeamOrHH then
  1191     if CheckNoTeamOrHH then
  1115         begin
  1192         begin
  1119     *)
  1196     *)
  1120 
  1197 
  1121     if (x < 4) and (TeamsArray[t] <> nil) then
  1198     if (x < 4) and (TeamsArray[t] <> nil) then
  1122         begin
  1199         begin
  1123             // if team matches current hedgehog team, default to current hedgehog
  1200             // if team matches current hedgehog team, default to current hedgehog
  1124             if (i = 0) and (CurrentHedgehog <> nil) and (CurrentHedgehog^.Team = TeamsArray[t]) then hh:= CurrentHedgehog
  1201             if (i = 0) and (CurrentHedgehog <> nil) and (CurrentHedgehog^.Team = TeamsArray[t]) then
       
  1202                 hh:= CurrentHedgehog
  1125             else 
  1203             else 
  1126                 begin
  1204                 begin
  1127             // otherwise use the first living hog or the hog amongs the remaining ones indicated by i
  1205             // otherwise use the first living hog or the hog amongs the remaining ones indicated by i
  1128                 j:= 0;
  1206                 j:= 0;
  1129                 c:= 0;
  1207                 c:= 0;