hedgewars/uGears.pas
changeset 351 29bc9c36ad5f
parent 307 96b428ac11f2
child 355 40c68869899e
equal deleted inserted replaced
350:c3ccec3834e8 351:29bc9c36ad5f
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    17  *)
    17  *)
    18 
    18 
    19 unit uGears;
    19 unit uGears;
    20 interface
    20 interface
    21 uses SDLh, uConsts;
    21 uses SDLh, uConsts, uFloat;
    22 {$INCLUDE options.inc}
    22 {$INCLUDE options.inc}
    23 const AllInactive: boolean = false;
    23 const AllInactive: boolean = false;
    24 
    24 
    25 type PGear = ^TGear;
    25 type PGear = ^TGear;
    26      TGearStepProcedure = procedure (Gear: PGear);
    26      TGearStepProcedure = procedure (Gear: PGear);
    27      TGear = record
    27      TGear = record
    28              NextGear, PrevGear: PGear;
    28              NextGear, PrevGear: PGear;
    29              Active: Boolean;
    29              Active: Boolean;
    30              State : Longword;
    30              State : Longword;
    31              X : Double;
    31              X : hwFloat;
    32              Y : Double;
    32              Y : hwFloat;
    33              dX: Double;
    33              dX: hwFloat;
    34              dY: Double;
    34              dY: hwFloat;
    35              Kind: TGearType;
    35              Kind: TGearType;
    36              Pos: Longword;
    36              Pos: Longword;
    37              doStep: TGearStepProcedure;
    37              doStep: TGearStepProcedure;
    38              Radius: integer;
    38              Radius: integer;
    39              Angle, Power : Longword;
    39              Angle, Power : Longword;
    40              DirAngle: Double;
    40              DirAngle: hwFloat;
    41              Timer : LongWord;
    41              Timer : LongWord;
    42              Elasticity: Double;
    42              Elasticity: hwFloat;
    43              Friction  : Double;
    43              Friction  : hwFloat;
    44              Message : Longword;
    44              Message : Longword;
    45              Hedgehog: pointer;
    45              Hedgehog: pointer;
    46              Health, Damage: integer;
    46              Health, Damage: integer;
    47              CollIndex: Longword;
    47              CollIndex: Longword;
    48              Tag: integer;
    48              Tag: integer;
    49              Surf: PSDL_Surface;
    49              Surf: PSDL_Surface;
    50              Z: Longword;
    50              Z: Longword;
    51              end;
    51              end;
    52 
    52 
    53 function  AddGear(X, Y: integer; Kind: TGearType; State: Longword; const dX: Double=0.0; dY: Double=0.0; Timer: LongWord=0): PGear;
    53 function  AddGear(X, Y: integer; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
    54 procedure ProcessGears;
    54 procedure ProcessGears;
    55 procedure SetAllToActive;
    55 procedure SetAllToActive;
    56 procedure SetAllHHToActive;
    56 procedure SetAllHHToActive;
    57 procedure DrawGears(Surface: PSDL_Surface);
    57 procedure DrawGears(Surface: PSDL_Surface);
    58 procedure FreeGearsList;
    58 procedure FreeGearsList;
    71      uLand, uIO, uLandGraphics, uAIMisc, uLocale, uAI, uAmmos;
    71      uLand, uIO, uLandGraphics, uAIMisc, uLocale, uAI, uAmmos;
    72 var RopePoints: record
    72 var RopePoints: record
    73                 Count: Longword;
    73                 Count: Longword;
    74                 HookAngle: integer;
    74                 HookAngle: integer;
    75                 ar: array[0..300] of record
    75                 ar: array[0..300] of record
    76                                   X, Y: Double;
    76                                   X, Y: hwFloat;
    77                                   dLen: Double;
    77                                   dLen: hwFloat;
    78                                   b: boolean;
    78                                   b: boolean;
    79                                   end;
    79                                   end;
    80                  end;
    80                  end;
    81     StepDamage: Longword = 0;
    81     StepDamage: Longword = 0;
    82 
    82 
    93 
    93 
    94 {$INCLUDE GSHandlers.inc}
    94 {$INCLUDE GSHandlers.inc}
    95 {$INCLUDE HHHandlers.inc}
    95 {$INCLUDE HHHandlers.inc}
    96 
    96 
    97 const doStepHandlers: array[TGearType] of TGearStepProcedure = (
    97 const doStepHandlers: array[TGearType] of TGearStepProcedure = (
    98                                                                doStepCloud,
    98                                                                @doStepCloud,
    99                                                                doStepBomb,
    99                                                                @doStepBomb,
   100                                                                doStepHedgehog,
   100                                                                @doStepHedgehog,
   101                                                                doStepGrenade,
   101                                                                @doStepGrenade,
   102                                                                doStepHealthTag,
   102                                                                @doStepHealthTag,
   103                                                                doStepGrave,
   103                                                                @doStepGrave,
   104                                                                doStepUFO,
   104                                                                @doStepUFO,
   105                                                                doStepShotgunShot,
   105                                                                @doStepShotgunShot,
   106                                                                doStepPickHammer,
   106                                                                @doStepPickHammer,
   107                                                                doStepRope,
   107                                                                @doStepRope,
   108                                                                doStepSmokeTrace,
   108                                                                @doStepSmokeTrace,
   109                                                                doStepExplosion,
   109                                                                @doStepExplosion,
   110                                                                doStepMine,
   110                                                                @doStepMine,
   111                                                                doStepCase,
   111                                                                @doStepCase,
   112                                                                doStepDEagleShot,
   112                                                                @doStepDEagleShot,
   113                                                                doStepDynamite,
   113                                                                @doStepDynamite,
   114                                                                doStepTeamHealthSorter,
   114                                                                @doStepTeamHealthSorter,
   115                                                                doStepBomb,
   115                                                                @doStepBomb,
   116                                                                doStepCluster,
   116                                                                @doStepCluster,
   117                                                                doStepShover,
   117                                                                @doStepShover,
   118                                                                doStepFlame,
   118                                                                @doStepFlame,
   119                                                                doStepFirePunch,
   119                                                                @doStepFirePunch,
   120                                                                doStepActionTimer,
   120                                                                @doStepActionTimer,
   121                                                                doStepActionTimer,
   121                                                                @doStepActionTimer,
   122                                                                doStepActionTimer,
   122                                                                @doStepActionTimer,
   123                                                                doStepParachute,
   123                                                                @doStepParachute,
   124                                                                doStepAirAttack,
   124                                                                @doStepAirAttack,
   125                                                                doStepAirBomb,
   125                                                                @doStepAirBomb,
   126                                                                doStepBlowTorch
   126                                                                @doStepBlowTorch
   127                                                                );
   127                                                                );
   128 
   128 
   129 procedure InsertGearToList(Gear: PGear);
   129 procedure InsertGearToList(Gear: PGear);
   130 var tmp: PGear;
   130 var tmp: PGear;
   131 begin
   131 begin
   132 if GearsList = nil then
   132 if GearsList = nil then
   133    GearsList:= Gear
   133    GearsList:= Gear
   134    else begin
   134    else begin
   135    // WARNING: this code assumes that the first gears added to the list are clouds (have maximal Z)
   135    // WARNING: this code assumes that the first gears added to the list are clouds (have maximal Z)
   136    tmp:= GearsList;
   136    tmp:= GearsList;
   137    while (tmp <> nil) and (tmp.Z < Gear.Z) do
   137    while (tmp <> nil) and (tmp^.Z < Gear^.Z) do
   138           tmp:= tmp.NextGear;
   138           tmp:= tmp^.NextGear;
   139 
   139 
   140    if tmp.PrevGear <> nil then tmp.PrevGear.NextGear:= Gear;
   140    if tmp^.PrevGear <> nil then tmp^.PrevGear^.NextGear:= Gear;
   141    Gear.PrevGear:= tmp.PrevGear;
   141    Gear^.PrevGear:= tmp^.PrevGear;
   142    tmp.PrevGear:= Gear;
   142    tmp^.PrevGear:= Gear;
   143    Gear.NextGear:= tmp;
   143    Gear^.NextGear:= tmp;
   144    if GearsList = tmp then GearsList:= Gear
   144    if GearsList = tmp then GearsList:= Gear
   145    end
   145    end
   146 end;
   146 end;
   147 
   147 
   148 procedure RemoveGearFromList(Gear: PGear);
   148 procedure RemoveGearFromList(Gear: PGear);
   149 begin
   149 begin
   150 if Gear.NextGear <> nil then Gear.NextGear.PrevGear:= Gear.PrevGear;
   150 if Gear^.NextGear <> nil then Gear^.NextGear^.PrevGear:= Gear^.PrevGear;
   151 if Gear.PrevGear <> nil then Gear.PrevGear.NextGear:= Gear.NextGear
   151 if Gear^.PrevGear <> nil then Gear^.PrevGear^.NextGear:= Gear^.NextGear
   152    else begin
   152    else begin
   153    GearsList:= Gear.NextGear;
   153    GearsList:= Gear^.NextGear;
   154    if GearsList <> nil then GearsList.PrevGear:= nil
   154    if GearsList <> nil then GearsList^.PrevGear:= nil
   155    end;
   155    end;
   156 end;
   156 end;
   157 
   157 
   158 function AddGear(X, Y: integer; Kind: TGearType; State: Longword; const dX: Double=0.0; dY: Double=0.0; Timer: LongWord=0): PGear;
   158 function AddGear(X, Y: integer; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
   159 const Counter: Longword = 0;
   159 const Counter: Longword = 0;
       
   160 var Result: PGear;
   160 begin
   161 begin
   161 inc(Counter);
   162 inc(Counter);
   162 {$IFDEF DEBUGFILE}AddFileLog('AddGear: ('+inttostr(x)+','+inttostr(y)+'), d('+floattostr(dX)+','+floattostr(dY)+')');{$ENDIF}
   163 {$IFDEF DEBUGFILE}AddFileLog('AddGear: ('+inttostr(x)+','+inttostr(y)+'), d('+floattostr(dX)+','+floattostr(dY)+')');{$ENDIF}
   163 New(Result);
   164 New(Result);
   164 {$IFDEF DEBUGFILE}AddFileLog('AddGear: type = '+inttostr(ord(Kind))+'; handle = '+inttostr(integer(Result)));{$ENDIF}
   165 {$IFDEF DEBUGFILE}AddFileLog('AddGear: type = '+inttostr(ord(Kind))+'; handle = '+inttostr(integer(Result)));{$ENDIF}
   165 FillChar(Result^, sizeof(TGear), 0);
   166 FillChar(Result^, sizeof(TGear), 0);
   166 Result.X:= X;
   167 Result^.X:= X;
   167 Result.Y:= Y;
   168 Result^.Y:= Y;
   168 Result.Kind := Kind;
   169 Result^.Kind := Kind;
   169 Result.State:= State;
   170 Result^.State:= State;
   170 Result.Active:= true;
   171 Result^.Active:= true;
   171 Result.dX:= dX;
   172 Result^.dX:= dX;
   172 Result.dY:= dY;
   173 Result^.dY:= dY;
   173 Result.doStep:= doStepHandlers[Kind];
   174 Result^.doStep:= doStepHandlers[Kind];
   174 Result.CollIndex:= High(Longword);
   175 Result^.CollIndex:= High(Longword);
   175 Result.Timer:= Timer;
   176 Result^.Timer:= Timer;
   176 if CurrentTeam <> nil then
   177 if CurrentTeam <> nil then
   177    Result.Hedgehog:= @CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog];
   178    Result^.Hedgehog:= @(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]);
   178 case Kind of
   179 case Kind of
   179        gtCloud: Result.Z:= High(Result.Z);  
   180        gtCloud: Result^.Z:= High(Result^.Z);
   180    gtAmmo_Bomb: begin
   181    gtAmmo_Bomb: begin
   181                 Result.Radius:= 4;
   182                 Result^.Radius:= 4;
   182                 Result.Elasticity:= 0.6;
   183                 Result^.Elasticity:= _0_6;
   183                 Result.Friction:= 0.995;
   184                 Result^.Friction:= _0_995;
   184                 end;
   185                 end;
   185     gtHedgehog: begin
   186     gtHedgehog: begin
   186                 Result.Radius:= cHHRadius;
   187                 Result^.Radius:= cHHRadius;
   187                 Result.Elasticity:= 0.35;
   188                 Result^.Elasticity:= _0_35;
   188                 Result.Friction:= 0.999;
   189                 Result^.Friction:= _0_999;
   189                 Result.Angle:= cMaxAngle div 2;
   190                 Result^.Angle:= cMaxAngle div 2;
   190                 Result.Z:= cHHZ;
   191                 Result^.Z:= cHHZ;
   191                 end;
   192                 end;
   192 gtAmmo_Grenade: begin
   193 gtAmmo_Grenade: begin
   193                 Result.Radius:= 4;
   194                 Result^.Radius:= 4;
   194                 end;
   195                 end;
   195    gtHealthTag: begin
   196    gtHealthTag: begin
   196                 Result.Timer:= 1500;
   197                 Result^.Timer:= 1500;
   197                 Result.Z:= 2000;
   198                 Result^.Z:= 2000;
   198                 end;
   199                 end;
   199        gtGrave: begin
   200        gtGrave: begin
   200                 Result.Radius:= 10;
   201                 Result^.Radius:= 10;
   201                 Result.Elasticity:= 0.6;
   202                 Result^.Elasticity:= _0_6;
   202                 end;
   203                 end;
   203          gtUFO: begin
   204          gtUFO: begin
   204                 Result.Radius:= 5;
   205                 Result^.Radius:= 5;
   205                 Result.Timer:= 500;
   206                 Result^.Timer:= 500;
   206                 Result.Elasticity:= 0.9
   207                 Result^.Elasticity:= _0_9
   207                 end;
   208                 end;
   208  gtShotgunShot: begin
   209  gtShotgunShot: begin
   209                 Result.Timer:= 900;
   210                 Result^.Timer:= 900;
   210                 Result.Radius:= 2
   211                 Result^.Radius:= 2
   211                 end;
   212                 end;
   212   gtPickHammer: begin
   213   gtPickHammer: begin
   213                 Result.Radius:= 10;
   214                 Result^.Radius:= 10;
   214                 Result.Timer:= 4000
   215                 Result^.Timer:= 4000
   215                 end;
   216                 end;
   216   gtSmokeTrace: begin
   217   gtSmokeTrace: begin
   217                 Result.X:= Result.X - 16;
   218                 Result^.X:= Result^.X - 16;
   218                 Result.Y:= Result.Y - 16;
   219                 Result^.Y:= Result^.Y - 16;
   219                 Result.State:= 8
   220                 Result^.State:= 8
   220                 end;
   221                 end;
   221         gtRope: begin
   222         gtRope: begin
   222                 Result.Radius:= 3;
   223                 Result^.Radius:= 3;
   223                 Result.Friction:= 500;
   224                 Result^.Friction:= 500;
   224                 RopePoints.Count:= 0;
   225                 RopePoints.Count:= 0;
   225                 end;
   226                 end;
   226    gtExplosion: begin
   227    gtExplosion: begin
   227                 Result.X:= Result.X - 25;
   228                 Result^.X:= Result^.X - 25;
   228                 Result.Y:= Result.Y - 25;
   229                 Result^.Y:= Result^.Y - 25;
   229                 end;
   230                 end;
   230         gtMine: begin
   231         gtMine: begin
   231                 Result.Radius:= 3;
   232                 Result^.Radius:= 3;
   232                 Result.Elasticity:= 0.55;
   233                 Result^.Elasticity:= _0_55;
   233                 Result.Friction:= 0.995;
   234                 Result^.Friction:= _0_995;
   234                 Result.Timer:= 3000;
   235                 Result^.Timer:= 3000;
   235                 end;
   236                 end;
   236         gtCase: begin
   237         gtCase: begin
   237                 Result.Radius:= 16;
   238                 Result^.Radius:= 16;
   238                 Result.Elasticity:= 0.4
   239                 Result^.Elasticity:= _0_4
   239                 end;
   240                 end;
   240   gtDEagleShot: begin
   241   gtDEagleShot: begin
   241                 Result.Radius:= 1;
   242                 Result^.Radius:= 1;
   242                 Result.Radius:= 1;
   243                 Result^.Radius:= 1;
   243                 Result.Health:= 50
   244                 Result^.Health:= 50
   244                 end;
   245                 end;
   245     gtDynamite: begin
   246     gtDynamite: begin
   246                 Result.Radius:= 3;
   247                 Result^.Radius:= 3;
   247                 Result.Elasticity:= 0.55;
   248                 Result^.Elasticity:= _0_55;
   248                 Result.Friction:= 0.03;
   249                 Result^.Friction:= _0_03;
   249                 Result.Timer:= 5000;
   250                 Result^.Timer:= 5000;
   250                 end;
   251                 end;
   251  gtClusterBomb: begin
   252  gtClusterBomb: begin
   252                 Result.Radius:= 4;
   253                 Result^.Radius:= 4;
   253                 Result.Elasticity:= 0.6;
   254                 Result^.Elasticity:= _0_6;
   254                 Result.Friction:= 0.995;
   255                 Result^.Friction:= _0_995;
   255                 end;
   256                 end;
   256        gtFlame: begin
   257        gtFlame: begin
   257                 Result.Angle:= Counter mod 64;
   258                 Result^.Angle:= Counter mod 64;
   258                 Result.Radius:= 1;
   259                 Result^.Radius:= 1;
   259                 Result.Health:= 2;
   260                 Result^.Health:= 2;
   260                 Result.dY:= (getrandom - 0.8) * 0.03;
   261                 Result^.dY:= (getrandom - _0_8) * _0_03;
   261                 Result.dX:= (getrandom - 0.5) * 0.4
   262                 Result^.dX:= (getrandom - _0_5) * _0_4
   262                 end;
   263                 end;
   263    gtFirePunch: begin
   264    gtFirePunch: begin
   264                 Result.Radius:= 15;
   265                 Result^.Radius:= 15;
   265                 Result.Tag:= Y
   266                 Result^.Tag:= Y
   266                 end;
   267                 end;
   267      gtAirBomb: begin
   268      gtAirBomb: begin
   268                 Result.Radius:= 10;
   269                 Result^.Radius:= 10;
   269                 end;
   270                 end;
   270    gtBlowTorch: begin
   271    gtBlowTorch: begin
   271                 Result.Radius:= cHHRadius;
   272                 Result^.Radius:= cHHRadius;
   272                 Result.Timer:= 7500;
   273                 Result^.Timer:= 7500;
   273                 end;
   274                 end;
   274      end;
   275      end;
   275 InsertGearToList(Result)
   276 InsertGearToList(Result);
       
   277 AddGear:= Result
   276 end;
   278 end;
   277 
   279 
   278 procedure DeleteGear(Gear: PGear);
   280 procedure DeleteGear(Gear: PGear);
   279 var team: PTeam;
   281 var team: PTeam;
   280     t: Longword;
   282     t: Longword;
   281 begin
   283 begin
   282 if Gear.CollIndex < High(Longword) then DeleteCI(Gear);
   284 if Gear^.CollIndex < High(Longword) then DeleteCI(Gear);
   283 if Gear.Surf <> nil then SDL_FreeSurface(Gear.Surf);
   285 if Gear^.Surf <> nil then SDL_FreeSurface(Gear^.Surf);
   284 if Gear.Kind = gtHedgehog then
   286 if Gear^.Kind = gtHedgehog then
   285    if CurAmmoGear <> nil then
   287    if CurAmmoGear <> nil then
   286       begin
   288       begin
   287       {$IFDEF DEBUGFILE}AddFileLog('DeleteGear: Sending gm_Destroy, hh handle = '+inttostr(integer(Gear)));{$ENDIF}
   289       {$IFDEF DEBUGFILE}AddFileLog('DeleteGear: Sending gm_Destroy, hh handle = '+inttostr(integer(Gear)));{$ENDIF}
   288       Gear.Message:= gm_Destroy;
   290       Gear^.Message:= gm_Destroy;
   289       CurAmmoGear.Message:= gm_Destroy;
   291       CurAmmoGear^.Message:= gm_Destroy;
   290       exit
   292       exit
   291       end else
   293       end else
   292       begin
   294       begin
   293       if Gear.Y >= cWaterLine then
   295       if not (Gear^.Y < cWaterLine) then
   294          begin
   296          begin
   295          t:= max(Gear.Damage, Gear.Health);
   297          t:= max(Gear^.Damage, Gear^.Health);
   296          AddGear(Round(Gear.X), Round(Gear.Y), gtHealthTag, t).Hedgehog:= Gear.Hedgehog;
   298          AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtHealthTag, t, 0, 0, 0)^.Hedgehog:= Gear^.Hedgehog;
   297          inc(StepDamage, t)
   299          inc(StepDamage, t)
   298          end;
   300          end;
   299       team:= PHedgehog(Gear.Hedgehog).Team;
   301       team:= PHedgehog(Gear^.Hedgehog)^.Team;
   300       if CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].Gear = Gear then
   302       if CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear = Gear then
   301          FreeActionsList; // to avoid ThinkThread on drawned gear
   303          FreeActionsList; // to avoid ThinkThread on drawned gear
   302       PHedgehog(Gear.Hedgehog).Gear:= nil;
   304       PHedgehog(Gear^.Hedgehog)^.Gear:= nil;
   303       inc(KilledHHs);
   305       inc(KilledHHs);
   304       RecountTeamHealth(team);
   306       RecountTeamHealth(team);
   305       end;
   307       end;
   306 {$IFDEF DEBUGFILE}AddFileLog('DeleteGear: handle = '+inttostr(integer(Gear)));{$ENDIF}
   308 {$IFDEF DEBUGFILE}AddFileLog('DeleteGear: handle = '+inttostr(integer(Gear)));{$ENDIF}
   307 if CurAmmoGear = Gear then CurAmmoGear:= nil;
   309 if CurAmmoGear = Gear then CurAmmoGear:= nil;
   311 end;
   313 end;
   312 
   314 
   313 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs
   315 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs
   314 var Gear: PGear;
   316 var Gear: PGear;
   315 begin
   317 begin
   316 Result:= true;
   318 CheckNoDamage:= true;
   317 Gear:= GearsList;
   319 Gear:= GearsList;
   318 while Gear <> nil do
   320 while Gear <> nil do
   319       begin
   321       begin
   320       if Gear.Kind = gtHedgehog then
   322       if Gear^.Kind = gtHedgehog then
   321          if Gear.Damage <> 0 then
   323          if Gear^.Damage <> 0 then
   322             begin
   324             begin
   323             Result:= false;
   325             CheckNoDamage:= false;
   324             inc(StepDamage, Gear.Damage);
   326             inc(StepDamage, Gear^.Damage);
   325             if Gear.Health < Gear.Damage then Gear.Health:= 0
   327             if Gear^.Health < Gear^.Damage then Gear^.Health:= 0
   326                                          else dec(Gear.Health, Gear.Damage);
   328                                          else dec(Gear^.Health, Gear^.Damage);
   327             AddGear(Round(Gear.X), round(Gear.Y) - cHHRadius - 12 - PHedgehog(Gear.Hedgehog)^.HealthTag.h,
   329             AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) - cHHRadius - 12 - PHedgehog(Gear^.Hedgehog)^.HealthTag^.h,
   328                     gtHealthTag, Gear.Damage).Hedgehog:= Gear.Hedgehog;
   330                     gtHealthTag, Gear^.Damage, 0, 0, 0)^.Hedgehog:= Gear^.Hedgehog;
   329             RenderHealth(PHedgehog(Gear.Hedgehog)^);
   331             RenderHealth(PHedgehog(Gear^.Hedgehog)^);
   330             RecountTeamHealth(PHedgehog(Gear.Hedgehog)^.Team);
   332             RecountTeamHealth(PHedgehog(Gear^.Hedgehog)^.Team);
   331             
   333 
   332             Gear.Damage:= 0
   334             Gear^.Damage:= 0
   333             end;
   335             end;
   334       Gear:= Gear.NextGear
   336       Gear:= Gear^.NextGear
   335       end;
   337       end;
   336 end;
   338 end;
   337 
   339 
   338 procedure ProcessGears;
   340 procedure ProcessGears;
   339 const delay: integer = cInactDelay;
   341 const delay: integer = cInactDelay;
   358 AllInactive:= true;
   360 AllInactive:= true;
   359 t:= GearsList;
   361 t:= GearsList;
   360 while t<>nil do
   362 while t<>nil do
   361       begin
   363       begin
   362       Gear:= t;
   364       Gear:= t;
   363       t:= Gear.NextGear;
   365       t:= Gear^.NextGear;
   364       if Gear.Active then Gear.doStep(Gear);
   366       if Gear^.Active then Gear^.doStep(Gear);
   365       end;
   367       end;
   366 
   368 
   367 if AllInactive then
   369 if AllInactive then
   368    case step of
   370    case step of
   369         stDelay: begin
   371         stDelay: begin
   373                     inc(step);
   375                     inc(step);
   374                     delay:= cInactDelay
   376                     delay:= cInactDelay
   375                     end
   377                     end
   376                  end;
   378                  end;
   377         stChDmg: if CheckNoDamage then inc(step) else step:= stDelay;
   379         stChDmg: if CheckNoDamage then inc(step) else step:= stDelay;
   378         stChWin: if not CheckForWin then inc(step) else step:= stDelay; 
   380         stChWin: if not CheckForWin then inc(step) else step:= stDelay;
   379         stSpawn: begin
   381         stSpawn: begin
   380                  if not isInMultiShoot then SpawnBoxOfSmth;
   382                  if not isInMultiShoot then SpawnBoxOfSmth;
   381                  inc(step)
   383                  inc(step)
   382                  end;
   384                  end;
   383         stNTurn: begin
   385         stNTurn: begin
   384                  AwareOfExplosion(0, 0, 0);
   386                  //AwareOfExplosion(0, 0, 0);
   385                  if isInMultiShoot then isInMultiShoot:= false
   387                  if isInMultiShoot then isInMultiShoot:= false
   386                     else begin
   388                     else begin
   387                     with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
   389                     with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do
   388                          if MaxStepDamage < StepDamage then MaxStepDamage:= StepDamage;
   390                          if MaxStepDamage < StepDamage then MaxStepDamage:= StepDamage;
   389                     StepDamage:= 0;
   391                     StepDamage:= 0;
   390                     ParseCommand('/nextturn');
   392                     ParseCommand('/nextturn', true);
   391                     end;
   393                     end;
   392                  step:= Low(step)
   394                  step:= Low(step)
   393                  end;
   395                  end;
   394         end;
   396         end;
   395 
   397 
   396 if TurnTimeLeft > 0 then
   398 if TurnTimeLeft > 0 then
   397    if CurrentTeam <> nil then
   399    if CurrentTeam <> nil then
   398       if CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].Gear <> nil then
   400       if CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil then
   399          if ((CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].Gear.State and gstAttacking) = 0)
   401          if ((CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.State and gstAttacking) = 0)
   400             and not isInMultiShoot then dec(TurnTimeLeft);
   402             and not isInMultiShoot then dec(TurnTimeLeft);
   401             
   403 
   402 inc(GameTicks);
   404 inc(GameTicks);
   403 {$IFDEF COUNTTICKS}
   405 {$IFDEF COUNTTICKS}
   404 asm
   406 asm
   405         push    eax
   407         push    eax
   406         push    edx
   408         push    edx
   425 procedure SetAllToActive;
   427 procedure SetAllToActive;
   426 var t: PGear;
   428 var t: PGear;
   427 begin
   429 begin
   428 AllInactive:= false;
   430 AllInactive:= false;
   429 t:= GearsList;
   431 t:= GearsList;
   430 while t<>nil do
   432 while t <> nil do
   431       begin
   433       begin
   432       t.Active:= true;
   434       t^.Active:= true;
   433       t:= t.NextGear
   435       t:= t^.NextGear
   434       end
   436       end
   435 end;
   437 end;
   436 
   438 
   437 procedure SetAllHHToActive;
   439 procedure SetAllHHToActive;
   438 var t: PGear;
   440 var t: PGear;
   439 begin
   441 begin
   440 AllInactive:= false;
   442 AllInactive:= false;
   441 t:= GearsList;
   443 t:= GearsList;
   442 while t<>nil do
   444 while t <> nil do
   443       begin
   445       begin
   444       if t.Kind = gtHedgehog then t.Active:= true;
   446       if t^.Kind = gtHedgehog then t^.Active:= true;
   445       t:= t.NextGear
   447       t:= t^.NextGear
   446       end
   448       end
   447 end;
   449 end;
   448 
   450 
   449 procedure DrawHH(Gear: PGear; Surface: PSDL_Surface);
   451 procedure DrawHH(Gear: PGear; Surface: PSDL_Surface);
   450 var t: integer;
   452 var t: integer;
   451 begin
   453 begin
   452 DrawHedgehog(Round(Gear.X) - 14 + WorldDx, Round(Gear.Y) - 18 + WorldDy,
   454 DrawHedgehog(hwRound(Gear^.X) - 14 + WorldDx, hwRound(Gear^.Y) - 18 + WorldDy,
   453              hwSign(Gear.dX), 0,
   455              hwSign(Gear^.dX), 0,
   454              PHedgehog(Gear.Hedgehog).visStepPos div 2,
   456              PHedgehog(Gear^.Hedgehog)^.visStepPos div 2,
   455              Surface);
   457              Surface);
   456 
   458 
   457 with PHedgehog(Gear.Hedgehog)^ do
   459 with PHedgehog(Gear^.Hedgehog)^ do
   458      if Gear.State = 0 then
   460      if Gear^.State = 0 then
   459         begin
   461         begin
   460         t:= round(Gear.Y) - cHHRadius - 10 + WorldDy;
   462         t:= hwRound(Gear^.Y) - cHHRadius - 10 + WorldDy;
   461         dec(t, HealthTag.h + 2);
   463         dec(t, HealthTag^.h + 2);
   462         DrawCentered(round(Gear.X) + WorldDx, t, HealthTag, Surface);
   464         DrawCentered(hwRound(Gear^.X) + WorldDx, t, HealthTag, Surface);
   463         dec(t, NameTag.h + 2);
   465         dec(t, NameTag^.h + 2);
   464         DrawCentered(round(Gear.X) + WorldDx, t, NameTag, Surface);
   466         DrawCentered(hwRound(Gear^.X) + WorldDx, t, NameTag, Surface);
   465         dec(t, Team.NameTag.h + 2);
   467         dec(t, Team^.NameTag^.h + 2);
   466         DrawCentered(round(Gear.X) + WorldDx, t, Team.NameTag, Surface)
   468         DrawCentered(hwRound(Gear^.X) + WorldDx, t, Team^.NameTag, Surface)
   467         end else // Current hedgehog
   469         end else // Current hedgehog
   468         begin
   470         begin
   469         if bShowFinger and ((Gear.State and gstHHDriven) <> 0) then
   471         if bShowFinger and ((Gear^.State and gstHHDriven) <> 0) then
   470            DrawSprite(sprFinger, round(Gear.X) - 16 + WorldDx, round(Gear.Y) - 64 + WorldDy,
   472            DrawSprite(sprFinger, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 64 + WorldDy,
   471                       GameTicks div 32 mod 16, Surface);
   473                       GameTicks div 32 mod 16, Surface);
   472         if (Gear.State and (gstMoving or gstDrowning or gstFalling)) = 0 then
   474         if (Gear^.State and (gstMoving or gstDrowning or gstFalling)) = 0 then
   473            if (Gear.State and gstHHThinking) <> 0 then
   475            if (Gear^.State and gstHHThinking) <> 0 then
   474               DrawGear(sQuestion, Round(Gear.X) - 10 + WorldDx, Round(Gear.Y) - cHHRadius - 34 + WorldDy, Surface)
   476               DrawGear(sQuestion, hwRound(Gear^.X) - 10 + WorldDx, hwRound(Gear^.Y) - cHHRadius - 34 + WorldDy, Surface)
   475               else
   477               else
   476               if ShowCrosshair and ((Gear.State and gstAttacked) = 0) then
   478               if ShowCrosshair and ((Gear^.State and gstAttacked) = 0) then
   477                  DrawSurfSprite(Round(Gear.X + hwSign(Gear.dX) * Sin(Gear.Angle*pi/cMaxAngle)*60) + WorldDx - 11,
   479                  DrawSurfSprite(Round(hwRound(Gear^.X) + hwSign(Gear^.dX) * Sin(Gear^.Angle*pi/cMaxAngle)*60) + WorldDx - 11,
   478                            Round(Gear.Y - Cos(Gear.Angle*pi/cMaxAngle)*60) + WorldDy - 12,
   480                            Round(hwRound(Gear^.Y) - Cos(Gear^.Angle*pi/cMaxAngle)*60) + WorldDy - 12,
   479                            24, (18 + hwSign(Gear.dX) * integer(((Gear.Angle * 72 div cMaxAngle) + 1) div 2) mod 18) mod 18,
   481                            24, (18 + hwSign(Gear^.dX) * integer(((Gear^.Angle * 72 div cMaxAngle) + 1) div 2) mod 18) mod 18,
   480                            Team.CrosshairSurf, Surface);
   482                            Team^.CrosshairSurf, Surface);
   481         end;
   483         end;
   482 end;
   484 end;
   483 
   485 
   484 procedure DrawGears(Surface: PSDL_Surface);
   486 procedure DrawGears(Surface: PSDL_Surface);
   485 var Gear: PGear;
   487 var Gear: PGear;
   486     i: Longword;
   488     i: Longword;
   487     roplen: Double;
   489     roplen: hwFloat;
   488 
   490 
   489     procedure DrawRopeLine(X1, Y1, X2, Y2: integer);
   491     procedure DrawRopeLine(X1, Y1, X2, Y2: integer);
   490     const nodlen = 5;
   492     const nodlen = 5;
   491     var i, x, y: integer;
   493     var i, x, y: integer;
   492         t, k, ladd: Double;
   494         t, k, ladd: hwFloat;
   493     begin
   495     begin
   494     if (X1 = X2) and (Y1 = Y2) then
   496     if (X1 = X2) and (Y1 = Y2) then
   495        begin
   497        begin
   496        OutError('WARNING: zero length rope line!');
   498        OutError('WARNING: zero length rope line!', false);
   497        exit
   499        exit
   498        end;
   500        end;
   499     if abs(X1 - X2) > abs(Y1 - Y2) then
   501 {    if abs(X1 - X2) > abs(Y1 - Y2) then
   500        begin
   502        begin
   501        if X1 > X2 then
   503        if X1 > X2 then
   502           begin
   504           begin
   503           i:= X1;
   505           i:= X1;
   504           X1:= X2;
   506           X1:= X2;
   553               roplen:= roplen - nodlen;
   555               roplen:= roplen - nodlen;
   554               end;
   556               end;
   555            t:= t + k;
   557            t:= t + k;
   556            end;
   558            end;
   557        end
   559        end
   558     end;
   560 }    end;
   559 
   561 
   560 begin
   562 begin
   561 Gear:= GearsList;
   563 Gear:= GearsList;
   562 while Gear<>nil do
   564 while Gear<>nil do
   563       begin
   565       begin
   564       case Gear.Kind of
   566       case Gear^.Kind of
   565            gtCloud: DrawSprite(sprCloud   , Round(Gear.X) + WorldDx, Round(Gear.Y) + WorldDy, Gear.State, Surface);
   567            gtCloud: DrawSprite(sprCloud   , hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.State, Surface);
   566        gtAmmo_Bomb: DrawSprite(sprBomb , Round(Gear.X) - 8 + WorldDx, Round(Gear.Y) - 8 + WorldDy, trunc(Gear.DirAngle), Surface);
   568        gtAmmo_Bomb: DrawSprite(sprBomb , hwRound(Gear^.X) - 8 + WorldDx, hwRound(Gear^.Y) - 8 + WorldDy, hwRound(Gear^.DirAngle), Surface);
   567         gtHedgehog: DrawHH(Gear, Surface);
   569         gtHedgehog: DrawHH(Gear, Surface);
   568     gtAmmo_Grenade: DrawSprite(sprGrenade , Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 16 + WorldDy, DxDy2Angle32(Gear.dY, Gear.dX), Surface);
   570     gtAmmo_Grenade: DrawSprite(sprGrenade , hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 16 + WorldDy, DxDy2Angle32(Gear^.dY.QWordValue, Gear^.dX.QWordValue), Surface);
   569        gtHealthTag: if Gear.Surf <> nil then DrawCentered(Round(Gear.X) + WorldDx, Round(Gear.Y) + WorldDy, Gear.Surf, Surface);
   571        gtHealthTag: if Gear^.Surf <> nil then DrawCentered(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Surf, Surface);
   570            gtGrave: DrawSpriteFromRect(PHedgehog(Gear.Hedgehog).Team.GraveRect, Round(Gear.X) + WorldDx - 16, Round(Gear.Y) + WorldDy - 16, 32, (GameTicks shr 7) and 7, Surface);
   572            gtGrave: DrawSpriteFromRect(PHedgehog(Gear^.Hedgehog)^.Team^.GraveRect, hwRound(Gear^.X) + WorldDx - 16, hwRound(Gear^.Y) + WorldDy - 16, 32, (GameTicks shr 7) and 7, Surface);
   571              gtUFO: DrawSprite(sprUFO, Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 16 + WorldDy, (GameTicks shr 7) mod 4, Surface);
   573              gtUFO: DrawSprite(sprUFO, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 16 + WorldDy, (GameTicks shr 7) mod 4, Surface);
   572       gtSmokeTrace: if Gear.State < 8 then DrawSprite(sprSmokeTrace, Round(Gear.X) + WorldDx, Round(Gear.Y) + WorldDy, Gear.State, Surface);
   574       gtSmokeTrace: if Gear^.State < 8 then DrawSprite(sprSmokeTrace, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.State, Surface);
   573             gtRope: begin
   575             gtRope: begin
   574                     roplen:= 0;
   576                     roplen:= 0;
   575                     if RopePoints.Count > 0 then
   577                     if RopePoints.Count > 0 then
   576                        begin
   578                        begin
   577                        i:= 0;
   579                        i:= 0;
   578                        while i < Pred(RopePoints.Count) do
   580                        while i < Pred(RopePoints.Count) do
   579                              begin
   581                              begin
   580                              DrawRopeLine(Round(RopePoints.ar[i].X) + WorldDx, Round(RopePoints.ar[i].Y) + WorldDy,
   582                              DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy,
   581                                           Round(RopePoints.ar[Succ(i)].X) + WorldDx, Round(RopePoints.ar[Succ(i)].Y) + WorldDy);
   583                                           hwRound(RopePoints.ar[Succ(i)].X) + WorldDx, hwRound(RopePoints.ar[Succ(i)].Y) + WorldDy);
   582                              inc(i)
   584                              inc(i)
   583                              end;
   585                              end;
   584                        DrawRopeLine(Round(RopePoints.ar[i].X) + WorldDx, Round(RopePoints.ar[i].Y) + WorldDy,
   586                        DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy,
   585                                     Round(Gear.X) + WorldDx, Round(Gear.Y) + WorldDy);
   587                                     hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy);
   586                        DrawRopeLine(Round(Gear.X) + WorldDx, Round(Gear.Y) + WorldDy,
   588                        DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy,
   587                                     Round(PHedgehog(Gear.Hedgehog).Gear.X) + WorldDx, Round(PHedgehog(Gear.Hedgehog).Gear.Y) + WorldDy);
   589                                     hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.X) + WorldDx, hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.Y) + WorldDy);
   588                        DrawSprite(sprRopeHook, Round(RopePoints.ar[0].X) + WorldDx - 16, Round(RopePoints.ar[0].Y) + WorldDy - 16, RopePoints.HookAngle, Surface);
   590                        DrawSprite(sprRopeHook, hwRound(RopePoints.ar[0].X) + WorldDx - 16, hwRound(RopePoints.ar[0].Y) + WorldDy - 16, RopePoints.HookAngle, Surface);
   589                        end else
   591                        end else
   590                        begin
   592                        begin
   591                        DrawRopeLine(Round(Gear.X) + WorldDx, Round(Gear.Y) + WorldDy,
   593                        DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy,
   592                                     Round(PHedgehog(Gear.Hedgehog).Gear.X) + WorldDx, Round(PHedgehog(Gear.Hedgehog).Gear.Y) + WorldDy);
   594                                     hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.X) + WorldDx, hwRound(PHedgehog(Gear^.Hedgehog)^.Gear^.Y) + WorldDy);
   593                        DrawSprite(sprRopeHook, Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 16 + WorldDy, DxDy2Angle32(Gear.dY, Gear.dX), Surface);
   595                        DrawSprite(sprRopeHook, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 16 + WorldDy, DxDy2Angle32(Gear^.dY.QWordValue, Gear^.dX.QWordValue), Surface);
   594                        end;
   596                        end;
   595                     end;
   597                     end;
   596        gtExplosion: DrawSprite(sprExplosion50, Round(Gear.X) + WorldDx, Round(Gear.Y) + WorldDy, Gear.State, Surface);
   598        gtExplosion: DrawSprite(sprExplosion50, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.State, Surface);
   597             gtMine: if ((Gear.State and gstAttacking) = 0)or((Gear.Timer and $3FF) < 420)
   599             gtMine: if ((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)
   598                        then DrawSprite(sprMineOff , Round(Gear.X) - 8 + WorldDx, Round(Gear.Y) - 8 + WorldDy, trunc(Gear.DirAngle), Surface)
   600                        then DrawSprite(sprMineOff , hwRound(Gear^.X) - 8 + WorldDx, hwRound(Gear^.Y) - 8 + WorldDy, hwRound(Gear^.DirAngle), Surface)
   599                        else DrawSprite(sprMineOn  , Round(Gear.X) - 8 + WorldDx, Round(Gear.Y) - 8 + WorldDy, trunc(Gear.DirAngle), Surface);
   601                        else DrawSprite(sprMineOn  , hwRound(Gear^.X) - 8 + WorldDx, hwRound(Gear^.Y) - 8 + WorldDy, hwRound(Gear^.DirAngle), Surface);
   600         gtDynamite: DrawSprite2(sprDynamite, Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 25 + WorldDy, Gear.Tag and 1, Gear.Tag shr 1, Surface);
   602         gtDynamite: DrawSprite2(sprDynamite, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 25 + WorldDy, Gear^.Tag and 1, Gear^.Tag shr 1, Surface);
   601             gtCase: case Gear.Pos of
   603             gtCase: case Gear^.Pos of
   602                          posCaseAmmo  : DrawSprite(sprCase, Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 16 + WorldDy, 0, Surface);
   604                          posCaseAmmo  : DrawSprite(sprCase, hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 16 + WorldDy, 0, Surface);
   603                          posCaseHealth: DrawSprite(sprFAid, Round(Gear.X) - 24 + WorldDx, Round(Gear.Y) - 24 + WorldDy, (GameTicks shr 6) mod 13, Surface);
   605                          posCaseHealth: DrawSprite(sprFAid, hwRound(Gear^.X) - 24 + WorldDx, hwRound(Gear^.Y) - 24 + WorldDy, (GameTicks shr 6) mod 13, Surface);
   604                          end;
   606                          end;
   605      gtClusterBomb: DrawSprite(sprClusterBomb, Round(Gear.X) - 8 + WorldDx, Round(Gear.Y) - 8 + WorldDy, trunc(Gear.DirAngle), Surface);
   607      gtClusterBomb: DrawSprite(sprClusterBomb, hwRound(Gear^.X) - 8 + WorldDx, hwRound(Gear^.Y) - 8 + WorldDy, hwRound(Gear^.DirAngle), Surface);
   606          gtCluster: DrawSprite(sprClusterParticle, Round(Gear.X) - 8 + WorldDx, Round(Gear.Y) - 8 + WorldDy, 0, Surface);
   608          gtCluster: DrawSprite(sprClusterParticle, hwRound(Gear^.X) - 8 + WorldDx, hwRound(Gear^.Y) - 8 + WorldDy, 0, Surface);
   607            gtFlame: DrawSprite(sprFlame, Round(Gear.X) - 8 + WorldDx, Round(Gear.Y) - 8 + WorldDy,(GameTicks div 128 + Gear.Angle) mod 8, Surface);
   609            gtFlame: DrawSprite(sprFlame, hwRound(Gear^.X) - 8 + WorldDx, hwRound(Gear^.Y) - 8 + WorldDy,(GameTicks div 128 + Gear^.Angle) mod 8, Surface);
   608          gtAirBomb: DrawSprite(sprAirBomb , Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 16 + WorldDy, DxDy2Angle32(Gear.dY, Gear.dX), Surface);
   610          gtAirBomb: DrawSprite(sprAirBomb , hwRound(Gear^.X) - 16 + WorldDx, hwRound(Gear^.Y) - 16 + WorldDy, DxDy2Angle32(Gear^.dY.QWordValue, Gear^.dX.QWordValue), Surface);
   609        gtAirAttack: DrawSprite(sprAirplane, Round(Gear.X) - 60 + WorldDx, Round(Gear.Y) - 25 + WorldDy, 0, Surface);
   611        gtAirAttack: DrawSprite(sprAirplane, hwRound(Gear^.X) - 60 + WorldDx, hwRound(Gear^.Y) - 25 + WorldDy, 0, Surface);
   610               end;
   612               end;
   611       Gear:= Gear.NextGear
   613       Gear:= Gear^.NextGear
   612       end;
   614       end;
   613 end;
   615 end;
   614 
   616 
   615 procedure FreeGearsList;
   617 procedure FreeGearsList;
   616 var t, tt: PGear;
   618 var t, tt: PGear;
   618 tt:= GearsList;
   620 tt:= GearsList;
   619 GearsList:= nil;
   621 GearsList:= nil;
   620 while tt<>nil do
   622 while tt<>nil do
   621       begin
   623       begin
   622       t:= tt;
   624       t:= tt;
   623       tt:= tt.NextGear;
   625       tt:= tt^.NextGear;
   624       Dispose(t)
   626       Dispose(t)
   625       end;
   627       end;
   626 end;
   628 end;
   627 
   629 
   628 procedure AddMiscGears;
   630 procedure AddMiscGears;
   629 var i: integer;
   631 var i: integer;
   630 begin
   632 begin
   631 AddGear(0, 0, gtATStartGame, 0, 0, 0, 2000);
   633 AddGear(0, 0, gtATStartGame, 0, 0, 0, 2000);
   632 if (GameFlags and gfForts) = 0 then
   634 if (GameFlags and gfForts) = 0 then
   633    for i:= 0 to 3 do
   635    for i:= 0 to 3 do
   634        FindPlace(AddGear(0, 0, gtMine, 0), false, 0, 2048);
   636        FindPlace(AddGear(0, 0, gtMine, 0, 0, 0, 0), false, 0, 2048);
   635 end;
   637 end;
   636 
   638 
   637 procedure AddClouds;
   639 procedure AddClouds;
   638 var i: integer;
   640 var i: integer;
   639 begin
   641 begin
   640 for i:= 0 to cCloudsNumber do
   642 for i:= 0 to cCloudsNumber do
   641     AddGear( - cScreenWidth + i * ((cScreenWidth * 2 + 2304) div cCloudsNumber), -140, gtCloud, random(4),
   643     AddGear( - cScreenWidth + i * ((cScreenWidth * 2 + 2304) div cCloudsNumber), -140, gtCloud, random(4),
   642              (0.5-random)*0.1, ((i mod 2) * 2 - 1) * (0.005 + 0.015*random))
   644 //             (0.5-random)*0.1, ((i mod 2) * 2 - 1) * (0.005 + 0.015*random), 0)
       
   645              0, 0, 0)
   643 end;
   646 end;
   644 
   647 
   645 procedure doMakeExplosion(X, Y, Radius: integer; Mask: LongWord);
   648 procedure doMakeExplosion(X, Y, Radius: integer; Mask: LongWord);
   646 var Gear: PGear;
   649 var Gear: PGear;
   647     dmg: integer;
   650     dmg: integer;
   648 begin
   651 begin
   649 TargetPoint.X:= NoPointX;
   652 TargetPoint.X:= NoPointX;
   650 {$IFDEF DEBUGFILE}if Radius > 3 then AddFileLog('Explosion: at (' + inttostr(x) + ',' + inttostr(y) + ')');{$ENDIF}
   653 {$IFDEF DEBUGFILE}if Radius > 3 then AddFileLog('Explosion: at (' + inttostr(x) + ',' + inttostr(y) + ')');{$ENDIF}
   651 if (Mask and EXPLDontDraw) = 0 then DrawExplosion(X, Y, Radius);
   654 if (Mask and EXPLDontDraw) = 0 then DrawExplosion(X, Y, Radius);
   652 if Radius = 50 then AddGear(X, Y, gtExplosion, 0);
   655 if Radius = 50 then AddGear(X, Y, gtExplosion, 0, 0, 0, 0);
   653 if (Mask and EXPLAutoSound)<>0 then PlaySound(sndExplosion);
   656 if (Mask and EXPLAutoSound)<>0 then PlaySound(sndExplosion, false);
   654 if (Mask and EXPLAllDamageInRadius)=0 then Radius:= Radius shl 1;
   657 if (Mask and EXPLAllDamageInRadius)=0 then Radius:= Radius shl 1;
   655 Gear:= GearsList;
   658 Gear:= GearsList;
   656 while Gear <> nil do
   659 while Gear <> nil do
   657       begin
   660       begin
   658       dmg:= Radius - Round(sqrt(sqr(Gear.X - X) + sqr(Gear.Y - Y)));
   661       dmg:= Radius - hwRound(Distance(Gear^.X - X, Gear^.Y - Y));
   659       if dmg > 0 then
   662       if dmg > 0 then
   660          begin
   663          begin
   661          dmg:= dmg shr 1;
   664          dmg:= dmg shr 1;
   662          case Gear.Kind of
   665          case Gear^.Kind of
   663               gtHedgehog,
   666               gtHedgehog,
   664                   gtMine,
   667                   gtMine,
   665                   gtCase,
   668                   gtCase,
   666                  gtFlame: begin
   669                  gtFlame: begin
   667                           if (Mask and EXPLNoDamage) = 0 then inc(Gear.Damage, dmg);
   670                           if (Mask and EXPLNoDamage) = 0 then inc(Gear^.Damage, dmg);
   668                           if ((Mask and EXPLDoNotTouchHH) = 0) or (Gear.Kind <> gtHedgehog) then
   671                           if ((Mask and EXPLDoNotTouchHH) = 0) or (Gear^.Kind <> gtHedgehog) then
   669                              begin
   672                              begin
   670                              Gear.dX:= Gear.dX + (dmg / 200 + cHHKick)* hwSign(Gear.X - X);
   673                              Gear^.dX:= Gear^.dX + (_0_005 * dmg + cHHKick)* hwSign(Gear^.X - X);
   671                              Gear.dY:= Gear.dY + (dmg / 200 + cHHKick)* hwSign(Gear.Y - Y);
   674                              Gear^.dY:= Gear^.dY + (_0_005 * dmg + cHHKick)* hwSign(Gear^.Y - Y);
   672                              Gear.Active:= true;
   675                              Gear^.Active:= true;
   673                              FollowGear:= Gear
   676                              FollowGear:= Gear
   674                              end;
   677                              end;
   675                           end;
   678                           end;
   676                  gtGrave: begin
   679                  gtGrave: begin
   677                           Gear.dY:= - dmg / 250;
   680                           Gear^.dY:= - _0_004 * dmg;
   678                           Gear.Active:= true;
   681                           Gear^.Active:= true;
   679                           end;
   682                           end;
   680               end;
   683               end;
   681          end;
   684          end;
   682       Gear:= Gear.NextGear
   685       Gear:= Gear^.NextGear
   683       end;
   686       end;
   684 uAIMisc.AwareOfExplosion(0, 0, 0)
   687 //uAIMisc.AwareOfExplosion(0, 0, 0)
   685 end;
   688 end;
   686 
   689 
   687 procedure AmmoShove(Ammo: PGear; Damage, Power: integer);
   690 procedure AmmoShove(Ammo: PGear; Damage, Power: integer);
   688 var t: PGearArray;
   691 var t: PGearArray;
   689     i: integer;
   692     i: integer;
   690     hh: PHedgehog;
   693     hh: PHedgehog;
   691 begin
   694 begin
   692 t:= CheckGearsCollision(Ammo);
   695 t:= CheckGearsCollision(Ammo);
   693 i:= t.Count;
   696 i:= t^.Count;
   694 hh:= Ammo.Hedgehog;
   697 hh:= Ammo^.Hedgehog;
   695 while i > 0 do
   698 while i > 0 do
   696     begin
   699     begin
   697     dec(i);
   700     dec(i);
   698     if (t.ar[i].State and gstNoDamage) = 0 then
   701     if (t^.ar[i]^.State and gstNoDamage) = 0 then
   699        case t.ar[i].Kind of
   702        case t^.ar[i]^.Kind of
   700            gtHedgehog,
   703            gtHedgehog,
   701                gtMine,
   704                gtMine,
   702                gtCase: begin
   705                gtCase: begin
   703                        inc(t.ar[i].Damage, Damage);
   706                        inc(t^.ar[i]^.Damage, Damage);
   704                        inc(hh.DamageGiven, Damage);
   707                        inc(hh^.DamageGiven, Damage);
   705                        t.ar[i].dX:= Ammo.dX * Power * 0.01;
   708                        t^.ar[i]^.dX:= Ammo^.dX * Power * _0_01;
   706                        t.ar[i].dY:= Ammo.dY * Power * 0.01;
   709                        t^.ar[i]^.dY:= Ammo^.dY * Power * _0_01;
   707                        t.ar[i].Active:= true;
   710                        t^.ar[i]^.Active:= true;
   708                        DeleteCI(t.ar[i]);
   711                        DeleteCI(t^.ar[i]);
   709                        FollowGear:= t.ar[i]
   712                        FollowGear:= t^.ar[i]
   710                        end;
   713                        end;
   711            end
   714            end
   712     end;
   715     end;
   713 SetAllToActive
   716 SetAllToActive
   714 end;
   717 end;
   720 Team:= TeamsList;
   723 Team:= TeamsList;
   721 t:= 0;
   724 t:= 0;
   722 while Team <> nil do
   725 while Team <> nil do
   723       begin
   726       begin
   724       for i:= 0 to cMaxHHIndex do
   727       for i:= 0 to cMaxHHIndex do
   725           with Team.Hedgehogs[i] do
   728           with Team^.Hedgehogs[i] do
   726                if Gear <> nil then
   729                if Gear <> nil then
   727                   if (GameFlags and gfForts) = 0 then FindPlace(Gear, false, 0, 2048)
   730                   if (GameFlags and gfForts) = 0 then FindPlace(Gear, false, 0, 2048)
   728                                                  else FindPlace(Gear, false, t, t + 1024);
   731                                                  else FindPlace(Gear, false, t, t + 1024);
   729       inc(t, 1024);
   732       inc(t, 1024);
   730       Team:= Team.Next
   733       Team:= Team^.Next
   731       end
   734       end
   732 end;
   735 end;
   733 
   736 
   734 function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: integer): PGear;
   737 function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: integer): PGear;
   735 var t: PGear;
   738 var t: PGear;
   737 t:= GearsList;
   740 t:= GearsList;
   738 rX:= sqr(rX);
   741 rX:= sqr(rX);
   739 rY:= sqr(rY);
   742 rY:= sqr(rY);
   740 while t <> nil do
   743 while t <> nil do
   741       begin
   744       begin
   742       if (t <> Gear) and (t.Kind = Kind) then
   745       if (t <> Gear) and (t^.Kind = Kind) then
   743          if sqr(Gear.X - t.X) / rX + sqr(Gear.Y - t.Y) / rY <= 1 then
   746          if not((hwSqr(Gear^.X - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > 1) then
   744             begin
   747             exit(t);
   745             Result:= t;
   748       t:= t^.NextGear
   746             exit
   749       end;
   747             end;
   750 CheckGearNear:= nil
   748       t:= t.NextGear
       
   749       end;
       
   750 Result:= nil
       
   751 end;
   751 end;
   752 
   752 
   753 procedure AmmoFlameWork(Ammo: PGear);
   753 procedure AmmoFlameWork(Ammo: PGear);
   754 var t: PGear;
   754 var t: PGear;
   755 begin
   755 begin
   756 t:= GearsList;
   756 t:= GearsList;
   757 while t <> nil do
   757 while t <> nil do
   758       begin
   758       begin
   759       if (t.Kind = gtHedgehog) and (t.Y < Ammo.Y) then
   759       if (t^.Kind = gtHedgehog) and (t^.Y < Ammo^.Y) then
   760          if sqr(Ammo.X - t.X) + sqr(Ammo.Y - t.Y - cHHRadius) * 2 <= sqr(4) then
   760          if not (hwSqr(Ammo^.X - t^.X) + hwSqr(Ammo^.Y - t^.Y - cHHRadius) * 2 > 2) then
   761             begin
   761             begin
   762             inc(t.Damage, 5);
   762             inc(t^.Damage, 5);
   763             t.dX:= t.dX + (t.X - Ammo.X) * 0.02;
   763             t^.dX:= t^.dX + (t^.X - Ammo^.X) * _0_02;
   764             t.dY:= - 0.25;
   764             t^.dY:= - _0_25;
   765             t.Active:= true;
   765             t^.Active:= true;
   766             DeleteCI(t);
   766             DeleteCI(t);
   767             FollowGear:= t
   767             FollowGear:= t
   768             end;
   768             end;
   769       t:= t.NextGear
   769       t:= t^.NextGear
   770       end;
   770       end;
   771 end;
   771 end;
   772 
   772 
   773 function CheckGearsNear(mX, mY: integer; Kind: TGearsType; rX, rY: integer): PGear;
   773 function CheckGearsNear(mX, mY: integer; Kind: TGearsType; rX, rY: integer): PGear;
   774 var t: PGear;
   774 var t: PGear;
   776 t:= GearsList;
   776 t:= GearsList;
   777 rX:= sqr(rX);
   777 rX:= sqr(rX);
   778 rY:= sqr(rY);
   778 rY:= sqr(rY);
   779 while t <> nil do
   779 while t <> nil do
   780       begin
   780       begin
   781       if t.Kind in Kind then
   781       if t^.Kind in Kind then
   782          if sqr(mX - t.X) / rX + sqr(mY - t.Y) / rY <= 1 then
   782          if not (hwSqr(mX - t^.X) / rX + hwSqr(mY - t^.Y) / rY > 1) then
   783             begin
   783             exit(t);
   784             Result:= t;
   784       t:= t^.NextGear
   785             exit
   785       end;
   786             end;
   786 CheckGearsNear:= nil
   787       t:= t.NextGear
       
   788       end;
       
   789 Result:= nil
       
   790 end;
   787 end;
   791 
   788 
   792 function CountGears(Kind: TGearType): Longword;
   789 function CountGears(Kind: TGearType): Longword;
   793 var t: PGear;
   790 var t: PGear;
       
   791     Result: Longword;
   794 begin
   792 begin
   795 Result:= 0;
   793 Result:= 0;
   796 t:= GearsList;
   794 t:= GearsList;
   797 while t <> nil do
   795 while t <> nil do
   798       begin
   796       begin
   799       if t.Kind = Kind then inc(Result);
   797       if t^.Kind = Kind then inc(Result);
   800       t:= t.NextGear
   798       t:= t^.NextGear
   801       end;
   799       end;
       
   800 CountGears:= Result
   802 end;
   801 end;
   803 
   802 
   804 procedure SpawnBoxOfSmth;
   803 procedure SpawnBoxOfSmth;
   805 begin
   804 begin
   806 if (CountGears(gtCase) >= 5) or (getrandom(cCaseFactor) <> 0) then exit;
   805 if (CountGears(gtCase) >= 5) or (getrandom(cCaseFactor) <> 0) then exit;
   807 FollowGear:= AddGear(0, 0, gtCase, 0);
   806 FollowGear:= AddGear(0, 0, gtCase, 0, 0, 0, 0);
   808 case getrandom(2) of
   807 case getrandom(2) of
   809      0: begin
   808      0: begin
   810         FollowGear.Health:= 25;
   809         FollowGear^.Health:= 25;
   811         FollowGear.Pos:= posCaseHealth
   810         FollowGear^.Pos:= posCaseHealth
   812         end;
   811         end;
   813      1: begin
   812      1: begin
   814         FollowGear.Pos:= posCaseAmmo;
   813         FollowGear^.Pos:= posCaseAmmo;
   815         FollowGear.State:= Longword(amMineStrike)
   814         FollowGear^.State:= Longword(amMineStrike)
   816         end;
   815         end;
   817      end;
   816      end;
   818 FindPlace(FollowGear, true, 0, 2048)
   817 FindPlace(FollowGear, true, 0, 2048)
   819 end;
   818 end;
   820 
   819 
   821 procedure FindPlace(Gear: PGear; withFall: boolean; Left, Right: integer);
   820 procedure FindPlace(Gear: PGear; withFall: boolean; Left, Right: integer);
   822 
   821 
   823     function CountNonZeroz(x, y, r: integer): integer;
   822     function CountNonZeroz(x, y, r: integer): integer;
   824     var i: integer;
   823     var i: integer;
       
   824         Result: integer;
   825     begin
   825     begin
   826     Result:= 0;
   826     Result:= 0;
   827     if (y and $FFFFFC00) <> 0 then exit;
   827     if (y and $FFFFFC00) <> 0 then exit;
   828     for i:= max(x - r, 0) to min(x + r, 2043) do
   828     for i:= max(x - r, 0) to min(x + r, 2043) do
   829         if Land[y, i] <> 0 then inc(Result)
   829         if Land[y, i] <> 0 then inc(Result);
       
   830     CountNonZeroz:= Result
   830     end;
   831     end;
   831 
   832 
   832 var fx, x: integer;
   833 var fx, x: integer;
   833     y, sy: integer;
   834     y, sy: integer;
   834     ar: array[0..512] of TPoint;
   835     ar: array[0..512] of TPoint;
   837 fx:= Left + integer(GetRandom(Right - Left));
   838 fx:= Left + integer(GetRandom(Right - Left));
   838 x:= fx;
   839 x:= fx;
   839 delta:= 130;
   840 delta:= 130;
   840 repeat
   841 repeat
   841   repeat
   842   repeat
   842      inc(x, Gear.Radius);
   843      inc(x, Gear^.Radius);
   843      if x > Right then x:= Left + (x mod (Right - left));
   844      if x > Right then x:= Left + (x mod (Right - left));
   844      cnt:= 0;
   845      cnt:= 0;
   845      y:= -Gear.Radius * 2;
   846      y:= -Gear^.Radius * 2;
   846      while y < 1023 do
   847      while y < 1023 do
   847         begin
   848         begin
   848         repeat
   849         repeat
   849           inc(y, 2);
   850           inc(y, 2);
   850         until (y > 1023) or (CountNonZeroz(x, y, Gear.Radius - 1) = 0);
   851         until (y > 1023) or (CountNonZeroz(x, y, Gear^.Radius - 1) = 0);
   851         sy:= y;
   852         sy:= y;
   852         repeat
   853         repeat
   853           inc(y);
   854           inc(y);
   854         until (y > 1023) or (CountNonZeroz(x, y, Gear.Radius - 1) <> 0);
   855         until (y > 1023) or (CountNonZeroz(x, y, Gear^.Radius - 1) <> 0);
   855         if (y - sy > Gear.Radius * 2)
   856         if (y - sy > Gear^.Radius * 2)
   856         and (y < 1023)
   857         and (y < 1023)
   857         and (CheckGearsNear(x, y - Gear.Radius, [gtHedgehog, gtMine, gtCase], 110, 110) = nil) then
   858         and (CheckGearsNear(x, y - Gear^.Radius, [gtHedgehog, gtMine, gtCase], 110, 110) = nil) then
   858            begin
   859            begin
   859            ar[cnt].X:= x;
   860            ar[cnt].X:= x;
   860            if withFall then ar[cnt].Y:= sy + Gear.Radius
   861            if withFall then ar[cnt].Y:= sy + Gear^.Radius
   861                        else ar[cnt].Y:= y - Gear.Radius;
   862                        else ar[cnt].Y:= y - Gear^.Radius;
   862            inc(cnt)
   863            inc(cnt)
   863            end;
   864            end;
   864         inc(y, 80)
   865         inc(y, 80)
   865         end;
   866         end;
   866      if cnt > 0 then
   867      if cnt > 0 then
   867         with ar[GetRandom(cnt)] do
   868         with ar[GetRandom(cnt)] do
   868           begin
   869           begin
   869           Gear.X:= x;
   870           Gear^.X:= x;
   870           Gear.Y:= y;
   871           Gear^.Y:= y;
   871          {$IFDEF DEBUGFILE}
   872          {$IFDEF DEBUGFILE}
   872          AddFileLog('Assigned Gear ' + inttostr(integer(Gear)) +
   873          AddFileLog('Assigned Gear ' + inttostr(integer(Gear)) +
   873                     ' coordinates (' + inttostr(x) +
   874                     ' coordinates (' + inttostr(x) +
   874                     ',' + inttostr(y) + ')');
   875                     ',' + inttostr(y) + ')');
   875          {$ENDIF}
   876          {$ENDIF}
   876           exit
   877           exit
   877           end
   878           end
   878   until (x - Gear.Radius < fx) and (x + Gear.Radius > fx);
   879   until (x - Gear^.Radius < fx) and (x + Gear^.Radius > fx);
   879 dec(Delta, 20)
   880 dec(Delta, 20)
   880 until (Delta < 70);
   881 until (Delta < 70);
   881 OutError('Couldn''t find place for Gear ' + inttostr(integer(Gear)), false);
   882 OutError('Couldn''t find place for Gear ' + inttostr(integer(Gear)), false);
   882 DeleteGear(Gear)
   883 DeleteGear(Gear)
   883 end;
   884 end;