hedgewars/uGearsHedgehog.pas
branchui-scaling
changeset 15288 c4fd2813b127
parent 15151 6b7d92fa4912
child 15399 b7e40129dbdb
equal deleted inserted replaced
13395:0135e64c6c66 15288:c4fd2813b127
    29 procedure HedgehogChAngle(HHGear: PGear);
    29 procedure HedgehogChAngle(HHGear: PGear);
    30 procedure PickUp(HH, Gear: PGear);
    30 procedure PickUp(HH, Gear: PGear);
    31 procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord);
    31 procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord);
    32 procedure CheckIce(Gear: PGear); inline;
    32 procedure CheckIce(Gear: PGear); inline;
    33 procedure PlayTaunt(taunt: Longword);
    33 procedure PlayTaunt(taunt: Longword);
       
    34 function HHGetTimer(Gear: PGear): LongWord;
       
    35 function HHGetTimerMsg(Gear: PGear): LongWord;
       
    36 function HHGetBounciness(Gear: PGear): LongWord;
       
    37 function HHGetBouncinessMsg(Gear: PGear): LongWord;
    34 
    38 
    35 implementation
    39 implementation
    36 uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions,
    40 uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions,
    37     uCommands, uLocale, uUtils, uStats, uIO, uScript,
    41     uCommands, uLocale, uUtils, uStats, uIO, uScript,
    38     uGearsList, uCollisions, uRandom, uStore, uTeams,
    42     uGearsList, uCollisions, uRandom, uStore, uTeams,
    45     t: byte;
    49     t: byte;
    46 begin
    50 begin
    47     t:= 0;
    51     t:= 0;
    48     while (TeamsArray[t] <> CurrentTeam) do inc(t);
    52     while (TeamsArray[t] <> CurrentTeam) do inc(t);
    49 
    53 
    50     AddChatString(#2 + FormatA(trmsg[sidAutoSkip], CurrentTeam^.TeamName));
    54     AddChatString(#2 + Format(shortstring(trmsg[sidAutoSkip]), CurrentTeam^.TeamName));
    51 
    55 
    52     ParseCommand('/skip', true)
    56     ParseCommand('/skip', true)
    53 end;
    57 end;
    54 
    58 
    55 // Shouldn't more of this ammo switching stuff be moved to uAmmos ?
    59 // Shouldn't more of this ammo switching stuff be moved to uAmmos ?
   141 weap:= TAmmoType(HHGear^.MsgParam);
   145 weap:= TAmmoType(HHGear^.MsgParam);
   142 Hedgehog:= HHGear^.Hedgehog;
   146 Hedgehog:= HHGear^.Hedgehog;
   143 
   147 
   144 HHGear^.Message:= HHGear^.Message and (not gmWeapon);
   148 HHGear^.Message:= HHGear^.Message and (not gmWeapon);
   145 
   149 
   146 // Special case: amNothing unselects weapon
       
   147 if weap = amNothing then
       
   148     begin
       
   149     HHGear^.Hedgehog^.CurAmmoType:= amNothing;
       
   150     ApplyAmmoChanges(HHGear^.Hedgehog^);
       
   151     exit
       
   152     end;
       
   153 
       
   154 if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then
   150 if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then
   155     exit; // weapon is not activated yet
   151     exit; // weapon is not activated yet
   156 
   152 
   157 HHGear^.MsgParam:= Ammoz[weap].Slot;
   153 HHGear^.MsgParam:= Ammoz[weap].Slot;
   158 
   154 
   180     color: LongWord;
   176     color: LongWord;
   181 begin
   177 begin
   182 Gear^.Message:= Gear^.Message and (not gmTimer);
   178 Gear^.Message:= Gear^.Message and (not gmTimer);
   183 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
   179 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
   184 with Gear^.Hedgehog^ do
   180 with Gear^.Hedgehog^ do
       
   181     if (((Gear^.State and gstAttacked) <> 0) and (GameFlags and gfInfAttack = 0))
       
   182     or ((Gear^.State and gstHHDriven) = 0) then
       
   183         exit;
   185     if ((Gear^.Message and gmPrecise) <> 0) and ((CurWeapon^.Propz and ammoprop_SetBounce) <> 0) then
   184     if ((Gear^.Message and gmPrecise) <> 0) and ((CurWeapon^.Propz and ammoprop_SetBounce) <> 0) then
   186         begin
   185         begin
   187         color:= Gear^.Hedgehog^.Team^.Clan^.Color;
   186         color:= Gear^.Hedgehog^.Team^.Clan^.Color;
       
   187 
   188         case Gear^.MsgParam of
   188         case Gear^.MsgParam of
   189             1: begin
   189             1: begin
   190                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce1]), color, capgrpAmmostate);
   190                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce1]), color, capgrpAmmostate);
   191                CurWeapon^.Bounciness:= 350;
       
   192                end;
   191                end;
   193             2: begin
   192             2: begin
   194                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce2]), color, capgrpAmmostate);
   193                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce2]), color, capgrpAmmostate);
   195                CurWeapon^.Bounciness:= 700;
       
   196                end;
   194                end;
   197             3: begin
   195             3: begin
   198                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce3]), color, capgrpAmmostate);
   196                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce3]), color, capgrpAmmostate);
   199                CurWeapon^.Bounciness:= 1000;
       
   200                end;
   197                end;
   201             4: begin
   198             4: begin
   202                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce4]), color, capgrpAmmostate);
   199                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce4]), color, capgrpAmmostate);
   203                CurWeapon^.Bounciness:= 2000;
       
   204                end;
   200                end;
   205             5: begin
   201             5: begin
   206                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce5]), color, capgrpAmmostate);
   202                AddCaption(FormatA(trmsg[sidBounce], trmsg[sidBounce5]), color, capgrpAmmostate);
   207                CurWeapon^.Bounciness:= 4000;
       
   208                end
   203                end
   209             end
   204             end;
       
   205         CurWeapon^.Bounciness:= bouncinessLevels[Gear^.MsgParam - 1];
   210         end
   206         end
   211     else if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
   207     else if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
   212         begin
   208         begin
   213         CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
   209         CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
   214         with CurrentTeam^ do
   210         with CurrentTeam^ do
   215             ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
   211             ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
   216         end;
   212         end;
   217 end;
   213 end;
   218 
   214 
       
   215 // Return timer (in ticks) of hogs current ammo or MSGPARAM_INVALID
       
   216 // if not timerable
       
   217 function HHGetTimer(Gear: PGear): LongWord;
       
   218 var CurWeapon: PAmmo;
       
   219 begin
       
   220 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
       
   221 with Gear^.Hedgehog^ do
       
   222     if ((CurWeapon^.Propz and ammoprop_Timerable) <> 0) then
       
   223         HHGetTimer:= CurWeapon^.Timer
       
   224     else
       
   225         HHGetTimer:= MSGPARAM_INVALID;
       
   226 end;
       
   227 
       
   228 // Returns timer as a corresponding msgParam for /timer command
       
   229 function HHGetTimerMsg(Gear: PGear): LongWord;
       
   230 var timer: LongInt;
       
   231 begin
       
   232 timer:= HHGetTimer(Gear);
       
   233 if timer > -1 then
       
   234     HHGetTimerMsg:= timer div 1000
       
   235 else
       
   236     HHGetTimerMsg:= MSGPARAM_INVALID
       
   237 end;
       
   238 
       
   239 // Returns the selected bounciness value for the hog gear's current ammo
       
   240 // or MSGPARAM_INVALID if current ammo has no settable bounciness
       
   241 function HHGetBounciness(Gear: PGear): LongWord;
       
   242 var CurWeapon: PAmmo;
       
   243 begin
       
   244 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
       
   245 with Gear^.Hedgehog^ do
       
   246     if ((CurWeapon^.Propz and ammoprop_SetBounce) <> 0) then
       
   247         HHGetBounciness:= CurWeapon^.Bounciness
       
   248     else
       
   249         HHGetBounciness:= MSGPARAM_INVALID
       
   250 end;
       
   251 
       
   252 // Returns bounciness as a corresponding msgParam for /timer command
       
   253 function HHGetBouncinessMsg(Gear: PGear): LongWord;
       
   254 var bounciness, i: LongInt;
       
   255 begin
       
   256     bounciness:= HHGetBounciness(Gear);
       
   257     if bounciness > -1 then
       
   258         for i:=0 to High(bouncinessLevels) do
       
   259             if bounciness = bouncinessLevels[i] then
       
   260                 begin
       
   261                 HHGetBouncinessMsg:= i+1;
       
   262                 exit
       
   263                 end;
       
   264     HHGetBouncinessMsg:= MSGPARAM_INVALID
       
   265 end;
   219 
   266 
   220 procedure Attack(Gear: PGear);
   267 procedure Attack(Gear: PGear);
   221 var xx, yy, newDx, newDy, lx, ly: hwFloat;
   268 var xx, yy, newDx, newDy, lx, ly: hwFloat;
   222     speech: PVisualGear;
   269     speech: PVisualGear;
   223     newGear:  PGear;
   270     newGear:  PGear;
   224     CurWeapon: PAmmo;
   271     CurWeapon: PAmmo;
   225     usedAmmoType: TAmmoType;
   272     usedAmmoType: TAmmoType;
   226     altUse: boolean;
   273     altUse, faceLeft: boolean;
   227     elastic: hwFloat;
   274     elastic: hwFloat;
   228 begin
   275 begin
   229 newGear:= nil;
   276 newGear:= nil;
   230 bShowFinger:= false;
   277 bShowFinger:= false;
   231 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
   278 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
   336                   amSniperRifle: begin
   383                   amSniperRifle: begin
   337                                  PlaySound(sndSniperReload);
   384                                  PlaySound(sndSniperReload);
   338                                  newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
   385                                  newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
   339                                  end;
   386                                  end;
   340                      amDynamite: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtDynamite, 0, SignAs(_0_03, dX), _0, 5000);
   387                      amDynamite: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtDynamite, 0, SignAs(_0_03, dX), _0, 5000);
   341                          amDuck: begin
   388                       amCreeper: begin
   342                                  // Does duck spawn inside water?
   389                                  // TODO: Implement proper creeper spawning code. This is still the old rubber duck code.
       
   390 
       
   391                                  // Does it spawn inside water?
   343                                  if (LeftX > hwRound(Gear^.X) - Gear^.Karma) or (RightX < hwRound(Gear^.X) + Gear^.Karma) or (cWaterLine < hwRound(Gear^.Y) + Gear^.Karma) then
   392                                  if (LeftX > hwRound(Gear^.X) - Gear^.Karma) or (RightX < hwRound(Gear^.X) + Gear^.Karma) or (cWaterLine < hwRound(Gear^.Y) + Gear^.Karma) then
   344                                      PlaySound(sndDroplet2)
   393                                      PlaySound(sndDroplet2)
   345                                  else
   394                                  else
   346                                      // Duck spawned in air, normal drop sound
   395                                      // spawned in air, normal drop sound
   347                                      PlaySound(sndDuckDrop);
   396                                      PlaySound(sndCreeperDrop);
   348                                  newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtDuck, 0, SignAs(_0_03, dX), _0, 0);
   397                                  newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtCreeper, 0, SignAs(_0_03, dX), _0, 0);
   349                                  if not ((not dX.isNegative) xor ((State and gstHHHJump) <> 0)) then
   398                                  if not ((not dX.isNegative) xor ((State and gstHHHJump) <> 0)) then
   350                                      newGear^.Tag:= -1
   399                                      newGear^.Tag:= -1
   351                                  else
   400                                  else
   352                                      newGear^.Tag:= 1;
   401                                      newGear^.Tag:= 1;
   353                                  end;
   402                                  end;
   363                   amBaseballBat: begin
   412                   amBaseballBat: begin
   364                                  newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtShover, gsttmpFlag, xx * _0_5, yy * _0_5, 0);
   413                                  newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtShover, gsttmpFlag, xx * _0_5, yy * _0_5, 0);
   365                                  PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
   414                                  PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
   366                                  end;
   415                                  end;
   367                     amParachute: begin
   416                     amParachute: begin
       
   417                                  faceLeft:= IsHogFacingLeft(Gear);
   368                                  newGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
   418                                  newGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
       
   419                                  if faceLeft then
       
   420                                      newGear^.Tag:= -1;
   369                                  PlaySound(sndParachute)
   421                                  PlaySound(sndParachute)
   370                                  end;
   422                                  end;
   371                     // we save CurWeapon^.Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
   423                     // we save CurWeapon^.Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
   372                     amAirAttack: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 0, _0, _0, 0);
   424                     amAirAttack: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 0, _0, _0, 0);
   373                    amMineStrike: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 1, _0, _0, 0);
   425                    amMineStrike: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 1, _0, _0, 0);
   406                                  cGravity:= cMaxWindSpeed;
   458                                  cGravity:= cMaxWindSpeed;
   407                                  cGravityf:= 0.00025;
   459                                  cGravityf:= 0.00025;
   408                                  cLowGravity := true
   460                                  cLowGravity := true
   409                                  end;
   461                                  end;
   410                   amExtraDamage: begin
   462                   amExtraDamage: begin
   411                                  PlaySound(sndHellishImpact4);
   463                                  PlaySound(sndExtraDamage);
   412                                  cDamageModifier:= _1_5
   464                                  cDamageModifier:= _1_5
   413                                  end;
   465                                  end;
   414                  amInvulnerable: begin
   466                  amInvulnerable: begin
   415                                  PlaySound(sndInvulnerable);
   467                                  PlaySound(sndInvulnerable);
   416                                  Effects[heInvulnerable]:= 1
   468                                  Effects[heInvulnerable]:= 1
   417                                  end;
   469                                  end;
   418                     amExtraTime: begin
   470                     amExtraTime: begin
   419                                  PlaySound(sndExtraTime);
   471                                  PlaySound(sndExtraTime);
   420                                  TurnTimeLeft:= TurnTimeLeft + 30000
   472                                  if TurnTimeLeft <= (cMaxTurnTime - ExtraTime) then
       
   473                                      TurnTimeLeft:= TurnTimeLeft + ExtraTime
       
   474                                  else
       
   475                                      TurnTimeLeft:= cMaxTurnTime;
   421                                  end;
   476                                  end;
   422                    amLaserSight: begin
   477                    amLaserSight: begin
   423                                  PlaySound(sndLaserSight);
   478                                  PlaySound(sndLaserSight);
   424                                  cLaserSighting:= true
   479                                  cLaserSighting:= true
   425                                  end;
   480                                  end;
   426                      amVampiric: begin
   481                      amVampiric: begin
   427                                  PlaySoundV(sndOw1, Team^.voicepack);
   482                                  PlaySoundV(sndOw1, Team^.voicepack);
   428                                  cVampiric:= true;
   483                                  cVampiric:= true;
   429                                  end;
   484                                  end;
   430                         amPiano: begin
   485                         amPiano: newGear:= AddGear(TargetPoint.X, -1024, gtPiano, 0, _0, _0, 0);
   431                                  // Tuck the hedgehog away until the piano attack is completed
       
   432                                  Unplaced:= true;
       
   433                                  X:= _0;
       
   434                                  Y:= _0;
       
   435                                  newGear:= AddGear(TargetPoint.X, -1024, gtPiano, 0, _0, _0, 0);
       
   436                                  PauseMusic
       
   437                                  end;
       
   438                  amFlamethrower: newGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower,  0, xx * _0_5, yy * _0_5, 0);
   486                  amFlamethrower: newGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower,  0, xx * _0_5, yy * _0_5, 0);
   439                       amLandGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtLandGun,  0, xx * _0_5, yy * _0_5, 0);
   487                       amLandGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtLandGun,  0, xx * _0_5, yy * _0_5, 0);
   440                   amResurrector: begin
   488                   amResurrector: begin
   441                                  newGear:= AddGear(hwRound(lx), hwRound(ly), gtResurrector, 0, _0, _0, 0);
   489                                  newGear:= AddGear(hwRound(lx), hwRound(ly), gtResurrector, 0, _0, _0, 0);
   442                                  newGear^.SoundChannel := LoopSound(sndResurrector);
   490                                  newGear^.SoundChannel := LoopSound(sndResurrector);
   443                                  end;
   491                                  end;
   444                     //amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
       
   445                        amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 0);
   492                        amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 0);
   446                        amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0);
   493                        amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0);
   447             end;
   494             end;
   448             if altUse and (newGear <> nil) and
   495             if altUse and (newGear <> nil) and
   449                ((CurAmmoGear = nil) or (CurAmmoGear^.AmmoType <> amJetpack) or (Gear^.Message and gmPrecise = 0)) then
   496                ((CurAmmoGear = nil) or (CurAmmoGear^.AmmoType <> amJetpack) or (Gear^.Message and gmPrecise = 0)) then
   474                       amSwitch, amRCPlane,
   521                       amSwitch, amRCPlane,
   475                     amKamikaze, amCake,
   522                     amKamikaze, amCake,
   476                    amSeduction, amBallgun,
   523                    amSeduction, amBallgun,
   477                      amJetpack, amBirdy,
   524                      amJetpack, amBirdy,
   478                 amFlamethrower, amLandGun,
   525                 amFlamethrower, amLandGun,
   479                  amResurrector, //amStructure,
   526                  amResurrector, amTardis,
   480                       amTardis, amPiano,
   527                        amPiano, amIceGun,
   481                       amIceGun, amRubber,
   528                    amAirAttack, amNapalm,
   482                       amMinigun: CurAmmoGear:= newGear;
   529                   amMineStrike, amDrillStrike,
       
   530                       amRubber, amMinigun: CurAmmoGear:= newGear;
   483             end;
   531             end;
   484             if CurAmmoType = amCake then FollowGear:= newGear;
   532             if CurAmmoType = amCake then FollowGear:= newGear;
   485             if CurAmmoType = amAirMine then newGear^.Hedgehog:= nil;
       
   486 
   533 
   487             if ((CurAmmoType = amMine) or (CurAmmoType = amSMine) or (CurAmmoType = amAirMine)) and (GameFlags and gfInfAttack <> 0) then
   534             if ((CurAmmoType = amMine) or (CurAmmoType = amSMine) or (CurAmmoType = amAirMine)) and (GameFlags and gfInfAttack <> 0) then
   488                 newGear^.FlightTime:= GameTicks + min(TurnTimeLeft,1000)
   535                 newGear^.FlightTime:= GameTicks + min(TurnTimeLeft,1000)
   489             else if CurAmmoType = amDrill then
   536             else if CurAmmoType = amDrill then
   490                 newGear^.FlightTime:= GameTicks + 250;
   537                 newGear^.FlightTime:= GameTicks + 250;
   491             if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
   538             if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
   492                 begin
   539                 begin
   493                 newGear^.Target.X:= TargetPoint.X;
   540                 newGear^.Target.X:= TargetPoint.X;
   494                 newGear^.Target.Y:= TargetPoint.Y
   541                 newGear^.Target.Y:= TargetPoint.Y
   495                 end;
   542                 end;
   496             if (newGear <> nil) and (newGear^.CollisionMask and lfCurrentHog <> 0) then newGear^.CollisionMask:= newGear^.CollisionMask and (not lfCurrentHog);
   543             if (newGear <> nil) and (newGear^.CollisionMask and lfCurHogCrate <> 0) then newGear^.CollisionMask:= newGear^.CollisionMask and (not lfCurHogCrate);
   497 
   544 
   498             // Clear FollowGear if using on a rope/parachute/saucer etc so focus stays with the hog's movement
   545             // Clear FollowGear if using on a rope/parachute/saucer etc so focus stays with the hog's movement
   499             if altUse then
   546             if altUse then
   500                 FollowGear:= nil;
   547                 FollowGear:= nil;
   501 
   548 
   522                 if speech <> nil then
   569                 if speech <> nil then
   523                     begin
   570                     begin
   524                     speech^.Text:= SpeechText;
   571                     speech^.Text:= SpeechText;
   525                     speech^.Hedgehog:= Gear^.Hedgehog;
   572                     speech^.Hedgehog:= Gear^.Hedgehog;
   526                     speech^.FrameTicks:= SpeechType;
   573                     speech^.FrameTicks:= SpeechType;
       
   574                     AddChatString(#9+Format(shortstring(trmsg[sidChatHog]), Gear^.Hedgehog^.Name, SpeechText));
   527                     end;
   575                     end;
   528                 SpeechText:= ''
   576                 SpeechText:= ''
   529                 end;
   577                 end;
   530 
   578 
   531             Power:= 0;
   579             Power:= 0;
   538             else
   586             else
   539                 begin
   587                 begin
   540                 if (not CurrentTeam^.ExtDriven) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then
   588                 if (not CurrentTeam^.ExtDriven) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then
   541                     SendIPC(_S'a');
   589                     SendIPC(_S'a');
   542                 AfterAttack;
   590                 AfterAttack;
   543                 end
   591                 end;
       
   592             TargetPoint.X := NoPointX;
   544             end
   593             end
   545         else
   594         else
   546             Message:= Message and (not gmAttack);
   595             Message:= Message and (not gmAttack);
   547 
   596 
   548     ScriptCall('onHogAttack', ord(usedAmmoType));
   597     ScriptCall('onHogAttack', ord(usedAmmoType));
   549     end; // of with Gear^, Gear^.Hedgehog^ do
   598     end; // of with Gear^, Gear^.Hedgehog^ do
   550 
       
   551     TargetPoint.X := NoPointX;
       
   552 end;
   599 end;
   553 
   600 
   554 procedure AfterAttack;
   601 procedure AfterAttack;
   555 var s: ansistring;
   602 var s: ansistring;
   556     a: TAmmoType;
   603     a: TAmmoType;
   563     if HHGear <> nil then HHGear^.State:= HHGear^.State and (not gstAttacking);
   610     if HHGear <> nil then HHGear^.State:= HHGear^.State and (not gstAttacking);
   564     if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then
   611     if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then
   565         begin
   612         begin
   566         Inc(MultiShootAttacks);
   613         Inc(MultiShootAttacks);
   567 
   614 
   568         if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks) then
   615         if (Ammoz[a].Ammo.NumPerTurn > 0) and ((GameFlags and gfMultiWeapon) = 0) then
   569             begin
   616             begin
   570             s:= ansistring(inttostr(Ammoz[a].Ammo.NumPerTurn - MultiShootAttacks + 1));
   617             s:= ansistring(inttostr(Ammoz[a].Ammo.NumPerTurn - MultiShootAttacks + 1));
   571             AddCaption(formatA(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate);
   618             AddCaption(formatA(trmsg[sidRemaining], s), capcolDefault, capgrpAmmostate);
   572             end;
   619             end;
   573 
   620 
   574         if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks)
   621         if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks)
   575         or ((GameFlags and gfMultiWeapon) <> 0) then
   622         or ((GameFlags and gfMultiWeapon) <> 0) then
   576             begin
   623             begin
   581             OnUsedAmmo(CurrentHedgehog^);
   628             OnUsedAmmo(CurrentHedgehog^);
   582             if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (((GameFlags and gfInfAttack) = 0) or PlacingHogs) then
   629             if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (((GameFlags and gfInfAttack) = 0) or PlacingHogs) then
   583                 begin
   630                 begin
   584                 if TagTurnTimeLeft = 0 then
   631                 if TagTurnTimeLeft = 0 then
   585                     TagTurnTimeLeft:= TurnTimeLeft;
   632                     TagTurnTimeLeft:= TurnTimeLeft;
   586                 if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and CheckCoordInWater(hwRound(CurAmmoGear^.X), hwRound(CurAmmoGear^.Y)) then
   633                 if (HHGear <> nil) and ((HHGear^.State and gstHHDriven) <> 0) then
   587                      TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 25
   634                     begin
   588                 else TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
   635                     if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and CheckCoordInWater(hwRound(CurAmmoGear^.X), hwRound(CurAmmoGear^.Y)) then
   589                 IsGetAwayTime := true;
   636                          TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 25
       
   637                     else TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
       
   638                     IsGetAwayTime := true;
       
   639                     end;
   590                 end;
   640                 end;
   591             if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (HHGear <> nil) then
   641             if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (HHGear <> nil) then
   592                 HHGear^.State:= HHGear^.State or gstAttacked;
   642                 HHGear^.State:= HHGear^.State or gstAttacked;
   593             if (a = amNothing) or ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) or
   643             if (a = amNothing) or ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) or
   594                (((GameFlags and gfInfAttack) <> 0) and ((Ammoz[a].Ammo.Propz and ammoprop_ForceTurnEnd) = 0)) then
   644                (((GameFlags and gfInfAttack) <> 0) and ((Ammoz[a].Ammo.Propz and ammoprop_ForceTurnEnd) = 0)) then
   635     begin
   685     begin
   636     AllInactive:= false;
   686     AllInactive:= false;
   637     Gear^.Z:= cCurrHHZ;
   687     Gear^.Z:= cCurrHHZ;
   638     RemoveGearFromList(Gear);
   688     RemoveGearFromList(Gear);
   639     InsertGearToList(Gear);
   689     InsertGearToList(Gear);
   640     PlaySoundV(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
   690     case random(3) of
       
   691     0: PlaySoundV(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
       
   692     1: PlaySoundV(sndSoLong, Gear^.Hedgehog^.Team^.voicepack);
       
   693     2: PlaySoundV(sndOhDear, Gear^.Hedgehog^.Team^.voicepack);
       
   694     end;
   641     Gear^.Pos:= 0;
   695     Gear^.Pos:= 0;
   642     Gear^.Timer:= timertime
   696     Gear^.Timer:= timertime
   643     end
   697     end
   644 end;
   698 end;
   645 
   699 
   708             cnt:= Ammoz[ammo].NumberInCase;
   762             cnt:= Ammoz[ammo].NumberInCase;
   709 
   763 
   710         if (ammo = amNothing) or (cnt = 0) then
   764         if (ammo = amNothing) or (cnt = 0) then
   711             s:= trmsg[sidEmptyCrate]
   765             s:= trmsg[sidEmptyCrate]
   712         else if cnt >= AMMO_INFINITE then
   766         else if cnt >= AMMO_INFINITE then
   713             s:= name + ansistring(' (+∞)')
   767             // infinity symbol
       
   768             s:= name + ansistring(' (+' + char($E2) + char($88) + char($9E) +')')
   714         else
   769         else
   715             s:= name + ansistring(' (+' + IntToStr(cnt) + ')');
   770             s:= name + ansistring(' (+' + IntToStr(cnt) + ')');
   716 
   771 
   717         AddCaption(s, HH.Team^.Clan^.Color, capgrpAmmoinfo);
   772         AddCaption(s, HH.Team^.Clan^.Color, capgrpAmmoinfo);
   718 
   773 
   728 end;
   783 end;
   729 
   784 
   730 ////////////////////////////////////////////////////////////////////////////////
   785 ////////////////////////////////////////////////////////////////////////////////
   731 procedure PickUp(HH, Gear: PGear);
   786 procedure PickUp(HH, Gear: PGear);
   732 var ag, gi: PGear;
   787 var ag, gi: PGear;
       
   788     healthBoost: LongInt;
   733 begin
   789 begin
   734 if Gear^.State and gstFrozen <> 0 then exit;
   790 if Gear^.State and gstFrozen <> 0 then exit;
       
   791 if Gear^.Message and gmDestroy <> 0 then exit;
   735 
   792 
   736 Gear^.Message:= gmDestroy;
   793 Gear^.Message:= gmDestroy;
   737 if (Gear^.Pos and posCaseExplode) <> 0 then
   794 if (Gear^.Pos and posCaseExplode) <> 0 then
   738     if (Gear^.Pos and posCasePoison) <> 0 then
   795     if (Gear^.Pos and posCasePoison) <> 0 then
   739         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound + EXPLPoisoned)
   796         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound + EXPLPoisoned)
   774                         ag^.Power:= Gear^.Power
   831                         ag^.Power:= Gear^.Power
   775                         end;
   832                         end;
   776                     end;
   833                     end;
   777      posCaseHealth: begin
   834      posCaseHealth: begin
   778                     PlaySound(sndShotgunReload);
   835                     PlaySound(sndShotgunReload);
   779                     inc(HH^.Health, Gear^.Health);
   836                     healthBoost:= IncHogHealth(HH^.Hedgehog, Gear^.Health);
   780                     HH^.Hedgehog^.Effects[hePoisoned] := 0;
   837                     HH^.Hedgehog^.Effects[hePoisoned] := 0;
   781                     RenderHealth(HH^.Hedgehog^);
   838                     RenderHealth(HH^.Hedgehog^);
   782                     RecountTeamHealth(HH^.Hedgehog^.Team);
   839                     RecountTeamHealth(HH^.Hedgehog^.Team);
   783                     HHHeal(HH^.Hedgehog, Gear^.Health, true);
   840                     HHHeal(HH^.Hedgehog, healthBoost, true);
   784                     end;
   841                     end;
   785      end
   842      end
   786 end;
   843 end;
   787 
   844 
   788 procedure HedgehogStep(Gear: PGear);
   845 procedure HedgehogStep(Gear: PGear);
   789 var PrevdX: LongInt;
   846 var PrevdX: LongInt;
   790     CurWeapon: PAmmo;
   847     CurWeapon: PAmmo;
   791     portals: PGearArrayS;
       
   792 begin
   848 begin
   793 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
   849 CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
   794 if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
   850 if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
   795     begin
   851     begin
   796     if isCursorVisible then
   852     if isCursorVisible then
   797         with Gear^.Hedgehog^ do
   853         with Gear^.Hedgehog^ do
   798             with CurWeapon^ do
   854             with CurWeapon^ do
   799                 begin
   855                 begin
   800                 if (Gear^.Message and gmLeft  ) <> 0 then
   856                 if Ammoz[AmmoType].PosCount < 2 then
       
   857                     exit
       
   858                 else if (Gear^.Message and gmLeft  ) <> 0 then
   801                     Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
   859                     Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
       
   860                 else if (Gear^.Message and gmRight ) <> 0 then
       
   861                     Pos:= (Pos + 1) mod Ammoz[AmmoType].PosCount
   802                 else
   862                 else
   803                     if (Gear^.Message and gmRight ) <> 0 then
   863                     exit;
   804                         Pos:= (Pos + 1) mod Ammoz[AmmoType].PosCount
   864                 GHStepTicks:= 200;
   805     else
   865                 exit
       
   866                 end;
       
   867 
       
   868     if (Gear^.Hedgehog^.Unplaced) then
   806         exit;
   869         exit;
   807     GHStepTicks:= 200;
       
   808     exit
       
   809     end;
       
   810 
   870 
   811     if ((Gear^.Message and gmAnimate) <> 0) then
   871     if ((Gear^.Message and gmAnimate) <> 0) then
   812         begin
   872         begin
   813         Gear^.Message:= 0;
   873         Gear^.Message:= 0;
   814         Gear^.State:= Gear^.State or gstAnimation;
   874         Gear^.State:= Gear^.State or gstAnimation;
   849         Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   909         Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   850         PlaySoundV(sndJump3, Gear^.Hedgehog^.Team^.voicepack);
   910         PlaySoundV(sndJump3, Gear^.Hedgehog^.Team^.voicepack);
   851         exit
   911         exit
   852         end;
   912         end;
   853 
   913 
   854     if (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.State and gstMoving = 0) then
   914     if (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.State and gstMoving = 0) and 
   855         begin
   915 		(CheckGearNear(Gear, gtPortal, 26, 26) = nil) then
   856         // slightly inefficient since it doesn't halt after one portal, maybe could add a param to GearsNear for number desired.
   916 		Gear^.PortalCounter:= 0;
   857         portals:= GearsNear(Gear^.X, Gear^.Y, gtPortal, 26);
       
   858         if portals.size = 0 then Gear^.PortalCounter:= 0
       
   859         end;
       
   860     PrevdX:= hwSign(Gear^.dX);
   917     PrevdX:= hwSign(Gear^.dX);
   861     if (Gear^.Message and gmLeft  )<>0 then
   918     if (Gear^.Message and gmLeft  )<>0 then
   862         Gear^.dX:= -cLittle else
   919         Gear^.dX:= -cLittle else
   863     if (Gear^.Message and gmRight )<>0 then
   920     if (Gear^.Message and gmRight )<>0 then
   864         Gear^.dX:=  cLittle
   921         Gear^.dX:=  cLittle
  1157             SetLittle(Gear^.dX);
  1214             SetLittle(Gear^.dX);
  1158 
  1215 
  1159 if (not isFalling)
  1216 if (not isFalling)
  1160   and (hwAbs(Gear^.dX) + hwAbs(Gear^.dY) < _0_03) then
  1217   and (hwAbs(Gear^.dX) + hwAbs(Gear^.dY) < _0_03) then
  1161     begin
  1218     begin
  1162     Gear^.State:= Gear^.State and (not gstWinner);
  1219     if (not GameOver) then
       
  1220         Gear^.State:= Gear^.State and (not gstWinner);
  1163     Gear^.State:= Gear^.State and (not gstMoving);
  1221     Gear^.State:= Gear^.State and (not gstMoving);
  1164     cnt:= 0;
  1222     cnt:= 0;
  1165     while (cnt < 6) and (not CheckGearDrowning(Gear)) and (Gear <> nil) and (TestCollisionYWithGear(Gear,1) = 0) do
  1223     while (cnt < 6) and (not CheckGearDrowning(Gear)) and (Gear <> nil) and (TestCollisionYWithGear(Gear,1) = 0) do
  1166         begin
  1224         begin
  1167         Gear^.Y:= Gear^.Y + _1;
  1225         Gear^.Y:= Gear^.Y + _1;
  1206             isCursorVisible:= false
  1264             isCursorVisible:= false
  1207     end;
  1265     end;
  1208 if (not isZero(Gear^.dY)) and (Gear^.FlightTime > 0) and ((GameFlags and gfLowGravity) = 0) then
  1266 if (not isZero(Gear^.dY)) and (Gear^.FlightTime > 0) and ((GameFlags and gfLowGravity) = 0) then
  1209     begin
  1267     begin
  1210     inc(Gear^.FlightTime);
  1268     inc(Gear^.FlightTime);
  1211     if (Gear^.FlightTime > 1500) and ((hwRound(Gear^.X) < LongInt(leftX)-250) or (hwRound(Gear^.X) > LongInt(rightX)+250))  then
  1269     if (Gear^.FlightTime > 1500) and ((hwRound(Gear^.X) < leftX-250) or (hwRound(Gear^.X) > rightX+250))  then
  1212         begin
  1270         begin
  1213         Gear^.FlightTime:= 0;
  1271         Gear^.FlightTime:= 0;
  1214         s:= ansistring(CurrentHedgehog^.Name);
  1272         s:= ansistring(CurrentHedgehog^.Name);
  1215         AddCaption(FormatA(GetEventString(eidHomerun), s), cWhiteColor, capgrpMessage);
  1273         AddCaption(FormatA(GetEventString(eidHomerun), s), capcolDefault, capgrpMessage2);
  1216         PlaySound(sndHomerun)
  1274         PlaySound(sndHomerun)
  1217         end;
  1275         end;
  1218     end
  1276     end
  1219 else
  1277 else
  1220     begin
  1278     begin
  1221     uStats.hedgehogFlight(Gear, Gear^.FlightTime);
  1279     uStats.hedgehogFlight(Gear, Gear^.FlightTime);
  1222     Gear^.FlightTime:= 0;
  1280     Gear^.FlightTime:= 0;
       
  1281     end;
       
  1282 if (WorldEdge = weNone) and (not Gear^.Hedgehog^.FlownOffMap) and (not isZero(Gear^.dX)) and (not isUnderwater) and ((Gear^.State and gstHHDriven) = 0) and (hwRound(Gear^.Y) < cWaterLine-300) and ((hwRound(Gear^.X) < leftX-2048) or (hwRound(Gear^.X) > rightX+2048)) then
       
  1283     begin
       
  1284     PlaySoundV(sndFlyAway, Gear^.Hedgehog^.Team^.voicepack);
       
  1285     Gear^.Hedgehog^.FlownOffMap:= true;
  1223     end;
  1286     end;
  1224 
  1287 
  1225 end;
  1288 end;
  1226 
  1289 
  1227 procedure doStepHedgehogDriven(HHGear: PGear);
  1290 procedure doStepHedgehogDriven(HHGear: PGear);
  1239 if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then
  1302 if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then
  1240     AllInactive:= true
  1303     AllInactive:= true
  1241 else if not isInMultiShoot then
  1304 else if not isInMultiShoot then
  1242     AllInactive:= false;
  1305     AllInactive:= false;
  1243 
  1306 
  1244 if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) or (LuaEndTurnRequested = true) then
  1307 if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) or (HHGear^.Health = 0) or (((GameFlags and gfKing) <> 0) and (not Hedgehog^.Team^.hasKing)) or (LuaEndTurnRequested = true) then
  1245     begin
  1308     begin
  1246     if (Hedgehog^.CurAmmoType = amKnife) then
  1309     if (Hedgehog^.CurAmmoType = amKnife) then
  1247        LoadHedgehogHat(Hedgehog^, Hedgehog^.Hat);
  1310        LoadHedgehogHat(Hedgehog^, Hedgehog^.Hat);
  1248     if TagTurnTimeLeft = 0 then
  1311     if TagTurnTimeLeft = 0 then
  1249         TagTurnTimeLeft:= TurnTimeLeft;
  1312         TagTurnTimeLeft:= TurnTimeLeft;
  1250     TurnTimeLeft:= 0;
  1313     TurnTimeLeft:= 0;
  1251     if (GameOver = false) and ((GameFlags and gfInfAttack) = 0) and ((HHGear^.State and gstAttacked) = 0) and (HHGear^.Damage = 0) and (LuaNoEndTurnTaunts = false) then
  1314     if (GameOver = false) and ((GameFlags and gfInfAttack) = 0) and ((HHGear^.State and gstAttacked) = 0) and (HHGear^.Damage = 0) and (HHGear^.Health > 0) and (LuaNoEndTurnTaunts = false) and (uStats.getIsTurnSkipped() = false) then
  1252         begin
  1315         begin
  1253         AddVoice(sndBoring, Hedgehog^.Team^.voicepack);
  1316         AddVoice(sndBoring, Hedgehog^.Team^.voicepack);
  1254         if (GameFlags and gfInfAttack = 0) then
  1317         if (GameFlags and gfInfAttack = 0) then
  1255             begin
  1318             begin
  1256             s:= Hedgehog^.Name;
  1319             s:= Hedgehog^.Name;
  1257             AddCaption(FormatA(GetEventString(eidTimeout), s), cWhiteColor, capgrpMessage);
  1320             AddCaption(FormatA(GetEventString(eidTimeout), s), capcolDefault, capgrpMessage);
  1258             end;
  1321             end;
  1259         end;
  1322         end;
  1260     isCursorVisible:= false;
  1323     isCursorVisible:= false;
  1261     HHGear^.State:= HHGear^.State and (not (gstHHDriven or gstAnimation or gstAttacking));
  1324     HHGear^.State:= HHGear^.State and (not (gstHHDriven or gstAnimation or gstAttacking));
  1262     AttackBar:= 0;
  1325     AttackBar:= 0;
  1263     StopSound(sndThrowPowerUp);
  1326     StopSound(sndThrowPowerUp);
  1264     LuaEndTurnRequested:= false;
  1327     LuaEndTurnRequested:= false;
  1265     LuaNoEndTurnTaunts:= false;
  1328     LuaNoEndTurnTaunts:= false;
  1266     if HHGear^.Damage > 0 then
  1329     if (HHGear^.Damage > 0) or (HHGear^.Health = 0) then
  1267         HHGear^.State:= HHGear^.State and (not (gstHHJumping or gstHHHJump));
  1330         HHGear^.State:= HHGear^.State and (not (gstHHJumping or gstHHHJump));
  1268     exit
  1331     exit
  1269     end;
  1332     end;
  1270 
  1333 
  1271 if isAFK and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0) then
  1334 if isAFK and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0) then
  1421                 Gear^.State:= (Gear^.State or gstHHDeath) and (not gstAnimation);
  1484                 Gear^.State:= (Gear^.State or gstHHDeath) and (not gstAnimation);
  1422                 Gear^.doStep:= @doStepHedgehogDead;
  1485                 Gear^.doStep:= @doStepHedgehogDead;
  1423                 // Death message
  1486                 // Death message
  1424                 s:= ansistring(Gear^.Hedgehog^.Name);
  1487                 s:= ansistring(Gear^.Hedgehog^.Name);
  1425                 if Gear^.Hedgehog^.King then
  1488                 if Gear^.Hedgehog^.King then
  1426                     AddCaption(FormatA(GetEventString(eidKingDied), s), cWhiteColor, capgrpMessage)
  1489                     AddCaption(FormatA(GetEventString(eidKingDied), s), capcolDefault, capgrpMessage)
  1427                 else
  1490                 else
  1428                     AddCaption(FormatA(GetEventString(eidDied), s), cWhiteColor, capgrpMessage);
  1491                     AddCaption(FormatA(GetEventString(eidDied), s), capcolDefault, capgrpMessage);
  1429                 end;
  1492                 end;
  1430             end
  1493             end
  1431         else
  1494         else
  1432             begin
  1495             begin
  1433             Gear^.State:= Gear^.State and (not gstAnimation);
  1496             Gear^.State:= Gear^.State and (not gstAnimation);
  1434             Gear^.doStep:= @doStepHedgehogGone;
  1497             Gear^.doStep:= @doStepHedgehogGone;
  1435 
  1498 
  1436             // Gone message
  1499             // Gone message
  1437             s:= ansistring(Gear^.Hedgehog^.Name);
  1500             s:= ansistring(Gear^.Hedgehog^.Name);
  1438             AddCaption(FormatA(GetEventString(eidGone), s), cWhiteColor, capgrpMessage);
  1501             AddCaption(FormatA(GetEventString(eidGone), s), capcolDefault, capgrpMessage);
  1439             end
  1502             end
  1440         end;
  1503         end;
  1441     exit
  1504     exit
  1442     end;
  1505     end;
  1443 
  1506 
  1449     end
  1512     end
  1450 else
  1513 else
  1451     begin
  1514     begin
  1452     if Gear^.Timer = 0 then
  1515     if Gear^.Timer = 0 then
  1453         begin
  1516         begin
  1454         Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstChooseTarget));
  1517         Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstAttacked or gstNotKickable or gstChooseTarget));
       
  1518         if (not GameOver) then
       
  1519             Gear^.State:= Gear^.State and (not gstWinner);
  1455         if Gear^.Hedgehog^.Effects[heFrozen] = 0 then Gear^.Active:= false;
  1520         if Gear^.Hedgehog^.Effects[heFrozen] = 0 then Gear^.Active:= false;
  1456         AddCI(Gear);
  1521         AddCI(Gear);
  1457         exit
  1522         exit
  1458         end
  1523         end
  1459     else dec(Gear^.Timer)
  1524     else dec(Gear^.Timer)
  1510     begin
  1575     begin
  1511     if (WorldEdge <> weBounce) and (Gear = CurrentHedgehog^.Gear) and
  1576     if (WorldEdge <> weBounce) and (Gear = CurrentHedgehog^.Gear) and
  1512        (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) and (CurAmmoGear^.Elasticity <> _0) then
  1577        (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) and (CurAmmoGear^.Elasticity <> _0) then
  1513        CurAmmoGear^.PortalCounter:= 1;
  1578        CurAmmoGear^.PortalCounter:= 1;
  1514     if (WorldEdge = weWrap) and ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0))  then
  1579     if (WorldEdge = weWrap) and ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0))  then
  1515         begin
  1580         // Stop hedgehog if it collides with land *just* behind other side of world wrap edge
  1516         Gear^.X:= tX;
  1581         if ((Gear^.State and gstNotKickable) = 0) then
  1517         Gear^.dX.isNegative:= (hwRound(tX) > LongInt(leftX) + Gear^.Radius * 2)
  1582             begin
  1518         end
  1583             if (hwRound(tX) > leftX + Gear^.Radius * 2) then
       
  1584                 Gear^.X:= int2HwFloat(RightX)
       
  1585             else
       
  1586                 Gear^.X:= int2HwFloat(LeftX);
       
  1587             Gear^.dX.QWordValue:= 0;
       
  1588             Gear^.State := Gear^.State or gstCollision;
       
  1589             end;
  1519     end;
  1590     end;
  1520 
  1591 
  1521 CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel;
  1592 CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel;
  1522 if (Gear^.Message and gmDestroy) <> 0 then
  1593 if (Gear^.Message and gmDestroy) <> 0 then
  1523     begin
  1594     begin