hedgewars/uGearsList.pas
branchsdl2transition
changeset 11362 ed5a6478e710
parent 11203 2f4d0a387a02
child 11468 2f6f8baa2a97
equal deleted inserted replaced
11361:31570b766315 11362:ed5a6478e710
     1 (*
     1 (*
     2  * Hedgewars, a free turn based strategy game
     2  * Hedgewars, a free turn based strategy game
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
     3  * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
     4  *
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; version 2 of the License
     7  * the Free Software Foundation; version 2 of the License
     8  *
     8  *
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    12  * GNU General Public License for more details.
    13  *
    13  *
    14  * You should have received a copy of the GNU General Public License
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    17  *)
    17  *)
    18 
    18 
    19 {$INCLUDE "options.inc"}
    19 {$INCLUDE "options.inc"}
    20 unit uGearsList;
    20 unit uGearsList;
    21 
    21 
    22 interface
    22 interface
    23 uses uFloat, uTypes;
    23 uses uFloat, uTypes, SDLh;
    24 
    24 
    25 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
    25 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
       
    26 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer, newUid: LongWord): PGear;
    26 procedure DeleteGear(Gear: PGear);
    27 procedure DeleteGear(Gear: PGear);
    27 procedure InsertGearToList(Gear: PGear);
    28 procedure InsertGearToList(Gear: PGear);
    28 procedure RemoveGearFromList(Gear: PGear);
    29 procedure RemoveGearFromList(Gear: PGear);
    29 
    30 
    30 var curHandledGear: PGear;
    31 var curHandledGear: PGear;
    39     GearKindAmmoTypeMap : array [TGearType] of TAmmoType = (
    40     GearKindAmmoTypeMap : array [TGearType] of TAmmoType = (
    40 (*          gtFlame *)   amNothing
    41 (*          gtFlame *)   amNothing
    41 (*       gtHedgehog *) , amNothing
    42 (*       gtHedgehog *) , amNothing
    42 (*           gtMine *) , amMine
    43 (*           gtMine *) , amMine
    43 (*           gtCase *) , amNothing
    44 (*           gtCase *) , amNothing
       
    45 (*        gtAirMine *) , amAirMine
    44 (*     gtExplosives *) , amNothing
    46 (*     gtExplosives *) , amNothing
    45 (*        gtGrenade *) , amGrenade
    47 (*        gtGrenade *) , amGrenade
    46 (*          gtShell *) , amBazooka
    48 (*          gtShell *) , amBazooka
    47 (*          gtGrave *) , amNothing
    49 (*          gtGrave *) , amNothing
    48 (*            gtBee *) , amBee
    50 (*            gtBee *) , amBee
   141 end;
   143 end;
   142 
   144 
   143 
   145 
   144 procedure RemoveGearFromList(Gear: PGear);
   146 procedure RemoveGearFromList(Gear: PGear);
   145 begin
   147 begin
   146 TryDo((curHandledGear = nil) or (Gear = curHandledGear), 'You''re doing it wrong', true);
   148 if (Gear <> GearsList) and (Gear <> nil) and (Gear^.NextGear = nil) and (Gear^.PrevGear = nil) then
       
   149     begin
       
   150     AddFileLog('Attempted to remove Gear #'+inttostr(Gear^.uid)+' from the list twice.');
       
   151     exit
       
   152     end;
       
   153 TryDo((Gear = nil) or (curHandledGear = nil) or (Gear = curHandledGear), 'You''re doing it wrong', true);
   147 
   154 
   148 if Gear^.NextGear <> nil then
   155 if Gear^.NextGear <> nil then
   149     Gear^.NextGear^.PrevGear:= Gear^.PrevGear;
   156     Gear^.NextGear^.PrevGear:= Gear^.PrevGear;
   150 if Gear^.PrevGear <> nil then
   157 if Gear^.PrevGear <> nil then
   151     Gear^.PrevGear^.NextGear:= Gear^.NextGear
   158     Gear^.PrevGear^.NextGear:= Gear^.NextGear
   152 else
   159 else
   153     GearsList:= Gear^.NextGear
   160     GearsList:= Gear^.NextGear;
       
   161 
       
   162 Gear^.NextGear:= nil;
       
   163 Gear^.PrevGear:= nil
   154 end;
   164 end;
   155 
   165 
   156 
   166 
   157 function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
   167 function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
       
   168 begin
       
   169 AddGear:= AddGear(X, Y, Kind, State, dX, dY, Timer, 0);
       
   170 end;
       
   171 function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer, newUid: LongWord): PGear;
   158 var gear: PGear;
   172 var gear: PGear;
       
   173     //c: byte;
       
   174     cakeData: PCakeData;
   159 begin
   175 begin
   160 inc(GCounter);
   176 if newUid = 0 then
       
   177     inc(GCounter);
       
   178 
   161 AddFileLog('AddGear: #' + inttostr(GCounter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
   179 AddFileLog('AddGear: #' + inttostr(GCounter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
       
   180 
   162 
   181 
   163 New(gear);
   182 New(gear);
   164 FillChar(gear^, sizeof(TGear), 0);
   183 FillChar(gear^, sizeof(TGear), 0);
   165 gear^.X:= int2hwFloat(X);
   184 gear^.X:= int2hwFloat(X);
   166 gear^.Y:= int2hwFloat(Y);
   185 gear^.Y:= int2hwFloat(Y);
   171 gear^.dX:= dX;
   190 gear^.dX:= dX;
   172 gear^.dY:= dY;
   191 gear^.dY:= dY;
   173 gear^.doStep:= doStepHandlers[Kind];
   192 gear^.doStep:= doStepHandlers[Kind];
   174 gear^.CollisionIndex:= -1;
   193 gear^.CollisionIndex:= -1;
   175 gear^.Timer:= Timer;
   194 gear^.Timer:= Timer;
   176 gear^.uid:= GCounter;
   195 if newUid = 0 then
       
   196      gear^.uid:= GCounter
       
   197 else gear^.uid:= newUid;
   177 gear^.SoundChannel:= -1;
   198 gear^.SoundChannel:= -1;
   178 gear^.ImpactSound:= sndNone;
   199 gear^.ImpactSound:= sndNone;
   179 gear^.Density:= _1;
   200 gear^.Density:= _1;
   180 // Define ammo association, if any.
   201 // Define ammo association, if any.
   181 gear^.AmmoType:= GearKindAmmoTypeMap[Kind];
   202 gear^.AmmoType:= GearKindAmmoTypeMap[Kind];
   182 gear^.CollisionMask:= $FFFF;
   203 gear^.CollisionMask:= $FFFF;
       
   204 gear^.Tint:= $FFFFFFFF;
       
   205 gear^.Data:= nil;
   183 
   206 
   184 if CurrentHedgehog <> nil then
   207 if CurrentHedgehog <> nil then
   185     begin
   208     begin
   186     gear^.Hedgehog:= CurrentHedgehog;
   209     gear^.Hedgehog:= CurrentHedgehog;
   187     if (CurrentHedgehog^.Gear <> nil) and (hwRound(CurrentHedgehog^.Gear^.X) = X) and (hwRound(CurrentHedgehog^.Gear^.Y) = Y) then
   210     if (CurrentHedgehog^.Gear <> nil) and (hwRound(CurrentHedgehog^.Gear^.X) = X) and (hwRound(CurrentHedgehog^.Gear^.Y) = Y) then
   219                 gear^.RenderTimer:= true;
   242                 gear^.RenderTimer:= true;
   220                 if gear^.Timer = 0 then
   243                 if gear^.Timer = 0 then
   221                     gear^.Timer:= 3000
   244                     gear^.Timer:= 3000
   222                 end;
   245                 end;
   223   gtMelonPiece: begin
   246   gtMelonPiece: begin
       
   247                 gear^.AdvBounce:= 1;
   224                 gear^.Density:= _2;
   248                 gear^.Density:= _2;
       
   249                 gear^.Elasticity:= _0_8;
       
   250                 gear^.Friction:= _0_995;
       
   251                 gear^.Radius:= 4
   225                 end;
   252                 end;
   226     gtHedgehog: begin
   253     gtHedgehog: begin
   227                 gear^.AdvBounce:= 1;
   254                 gear^.AdvBounce:= 1;
   228                 gear^.Radius:= cHHRadius;
   255                 gear^.Radius:= cHHRadius;
   229                 gear^.Elasticity:= _0_35;
   256                 gear^.Elasticity:= _0_35;
   232                 gear^.Density:= _3;
   259                 gear^.Density:= _3;
   233                 gear^.Z:= cHHZ;
   260                 gear^.Z:= cHHZ;
   234                 if (GameFlags and gfAISurvival) <> 0 then
   261                 if (GameFlags and gfAISurvival) <> 0 then
   235                     if gear^.Hedgehog^.BotLevel > 0 then
   262                     if gear^.Hedgehog^.BotLevel > 0 then
   236                         gear^.Hedgehog^.Effects[heResurrectable] := 1;
   263                         gear^.Hedgehog^.Effects[heResurrectable] := 1;
       
   264                 // this would presumably be set in the frontend
       
   265                 // if we weren't going to do that yet, would need to reinit GetRandom
       
   266                 // oh, and, randomising slightly R and B might be nice too.
       
   267                 //gear^.Tint:= $fa00efff or ((random(80)+128) shl 16)
       
   268                 //gear^.Tint:= $faa4efff
       
   269                 //gear^.Tint:= (($e0+random(32)) shl 24) or
       
   270                 //             ((random(80)+128) shl 16) or
       
   271                 //             (($d5+random(32)) shl 8) or $ff
       
   272                 {c:= GetRandom(32);
       
   273                 gear^.Tint:= (($e0+c) shl 24) or
       
   274                              ((GetRandom(90)+128) shl 16) or
       
   275                              (($d5+c) shl 8) or $ff}
   237                 end;
   276                 end;
   238        gtShell: begin
   277        gtShell: begin
   239                 gear^.Elasticity:= _0_8;
   278                 gear^.Elasticity:= _0_8;
   240                 gear^.Friction:= _0_8;
   279                 gear^.Friction:= _0_8;
   241                 gear^.Radius:= 4;
   280                 gear^.Radius:= 4;
   259                     Radius:= 1;
   298                     Radius:= 1;
   260                     DirAngle:= random(360);
   299                     DirAngle:= random(360);
   261                     if State and gstTmpFlag = 0 then
   300                     if State and gstTmpFlag = 0 then
   262                         begin
   301                         begin
   263                         dx.isNegative:= GetRandom(2) = 0;
   302                         dx.isNegative:= GetRandom(2) = 0;
   264                         dx.QWordValue:= $40DA * GetRandom(10000) * 8;
   303                         dx.QWordValue:= QWord($40DA) * GetRandom(10000) * 8;
   265                         dy.isNegative:= false;
   304                         dy.isNegative:= false;
   266                         dy.QWordValue:= $3AD3 * GetRandom(7000) * 8;
   305                         dy.QWordValue:= QWord($3AD3) * GetRandom(7000) * 8;
   267                         if GetRandom(2) = 0 then
   306                         if GetRandom(2) = 0 then
   268                             dx := -dx
   307                             dx := -dx;
   269                         end;
   308                         Tint:= $FFFFFFFF
       
   309                         end
       
   310                     else
       
   311                         Tint:= (ExplosionBorderColor shr RShift and $FF shl 24) or
       
   312                                (ExplosionBorderColor shr GShift and $FF shl 16) or
       
   313                                (ExplosionBorderColor shr BShift and $FF shl 8) or $FF;
   270                     State:= State or gstInvisible;
   314                     State:= State or gstInvisible;
   271                     Health:= random(vobFrameTicks);
   315                     // use health field to store current frameticks
       
   316                     if vobFrameTicks > 0 then
       
   317                         Health:= random(vobFrameTicks)
       
   318                     else
       
   319                         Health:= 0;
       
   320                     // use timer to store currently displayed frame index
   272                     if gear^.Timer = 0 then Timer:= random(vobFramesCount);
   321                     if gear^.Timer = 0 then Timer:= random(vobFramesCount);
   273                     Damage:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) * 8;
   322                     Damage:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) * 8
   274                     end
   323                     end
   275                 end;
   324                 end;
   276        gtGrave: begin
   325        gtGrave: begin
   277                 gear^.ImpactSound:= sndGraveImpact;
   326                 gear^.ImpactSound:= sndGraveImpact;
   278                 gear^.nImpactSounds:= 1;
   327                 gear^.nImpactSounds:= 1;
   304                 end;
   353                 end;
   305         gtRope: begin
   354         gtRope: begin
   306                 gear^.Radius:= 3;
   355                 gear^.Radius:= 3;
   307                 gear^.Friction:= _450 * _0_01 * cRopePercent;
   356                 gear^.Friction:= _450 * _0_01 * cRopePercent;
   308                 RopePoints.Count:= 0;
   357                 RopePoints.Count:= 0;
       
   358                 gear^.Tint:= $D8D8D8FF;
       
   359                 gear^.Tag:= 0; // normal rope render
   309                 end;
   360                 end;
   310         gtMine: begin
   361         gtMine: begin
   311                 gear^.ImpactSound:= sndMineImpact;
   362                 gear^.ImpactSound:= sndMineImpact;
   312                 gear^.nImpactSounds:= 1;
   363                 gear^.nImpactSounds:= 1;
   313                 gear^.Health:= 10;
   364                 gear^.Health:= 10;
   322                         gear^.Timer:= getrandom(51)*100
   373                         gear^.Timer:= getrandom(51)*100
   323                     else
   374                     else
   324                         gear^.Timer:= cMinesTime
   375                         gear^.Timer:= cMinesTime
   325                     end
   376                     end
   326                 end;
   377                 end;
       
   378      gtAirMine: begin
       
   379                 gear^.ImpactSound:= sndDenied;
       
   380                 gear^.nImpactSounds:= 1;
       
   381                 gear^.Health:= 30;
       
   382                 gear^.State:= gear^.State or gstMoving or gstNoGravity or gstSubmersible;
       
   383                 gear^.Radius:= 8;
       
   384                 gear^.Elasticity:= _0_55;
       
   385                 gear^.Friction:= _0_995;
       
   386                 gear^.Density:= _1;
       
   387                 gear^.Angle:= 175; // Radius at which air bombs will start "seeking". $FFFFFFFF = unlimited. check is skipped.
       
   388                 gear^.Power:= cMaxWindSpeed.QWordValue div 2; // hwFloat converted. 1/2 g default. defines the "seek" speed when a gear is in range.
       
   389                 gear^.Pos:= cMaxWindSpeed.QWordValue * 3 div 2; // air friction. slows it down when not hitting stuff
       
   390                 gear^.Karma:= 30; // damage
       
   391                 if gear^.Timer = 0 then
       
   392                     begin
       
   393                     if cMinesTime < 0 then
       
   394                         gear^.Timer:= getrandom(13)*100
       
   395                     else
       
   396                         gear^.Timer:= cMinesTime div 4
       
   397                     end;
       
   398                 gear^.WDTimer:= gear^.Timer
       
   399                 end;
   327        gtSMine: begin
   400        gtSMine: begin
   328                 gear^.Health:= 10;
   401                 gear^.Health:= 10;
   329                 gear^.State:= gear^.State or gstMoving;
   402                 gear^.State:= gear^.State or gstMoving;
   330                 gear^.Radius:= 2;
   403                 gear^.Radius:= 2;
   331                 gear^.Elasticity:= _0_55;
   404                 gear^.Elasticity:= _0_55;
   386        gtFlame: begin
   459        gtFlame: begin
   387                 gear^.Tag:= GetRandom(32);
   460                 gear^.Tag:= GetRandom(32);
   388                 gear^.Radius:= 1;
   461                 gear^.Radius:= 1;
   389                 gear^.Health:= 5;
   462                 gear^.Health:= 5;
   390                 gear^.Density:= _1;
   463                 gear^.Density:= _1;
       
   464                 gear^.FlightTime:= 9999999; // determines whether in-air flames do damage. disabled by default
   391                 if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then
   465                 if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then
   392                     begin
   466                     begin
   393                     gear^.dY:= (getrandomf - _0_8) * _0_03;
   467                     gear^.dY:= (getrandomf - _0_8) * _0_03;
   394                     gear^.dX:= (getrandomf - _0_5) * _0_4
   468                     gear^.dX:= (getrandomf - _0_5) * _0_4
   395                     end
   469                     end
   396                 end;
   470                 end;
   397    gtFirePunch: begin
   471    gtFirePunch: begin
       
   472                 if gear^.Timer = 0 then gear^.Timer:= 3000;
   398                 gear^.Radius:= 15;
   473                 gear^.Radius:= 15;
   399                 gear^.Tag:= Y
   474                 gear^.Tag:= Y
   400                 end;
   475                 end;
   401    gtAirAttack: gear^.Z:= cHHZ+2;
   476    gtAirAttack: begin
       
   477                 gear^.Health:= 6;
       
   478                 gear^.Damage:= 30;
       
   479                 gear^.Z:= cHHZ+2;
       
   480                 gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF
       
   481                 end;
   402      gtAirBomb: begin
   482      gtAirBomb: begin
       
   483                 gear^.AdvBounce:= 1;
   403                 gear^.Radius:= 5;
   484                 gear^.Radius:= 5;
   404                 gear^.Density:= _2;
   485                 gear^.Density:= _2;
       
   486                 gear^.Elasticity:= _0_55;
       
   487                 gear^.Friction:= _0_995
   405                 end;
   488                 end;
   406    gtBlowTorch: begin
   489    gtBlowTorch: begin
   407                 gear^.Radius:= cHHRadius + cBlowTorchC;
   490                 gear^.Radius:= cHHRadius + cBlowTorchC;
   408                 if gear^.Timer = 0 then gear^.Timer:= 7500
   491                 if gear^.Timer = 0 then gear^.Timer:= 7500
   409                 end;
   492                 end;
   435                 end;
   518                 end;
   436         gtCake: begin
   519         gtCake: begin
   437                 gear^.Health:= 2048;
   520                 gear^.Health:= 2048;
   438                 gear^.Radius:= 7;
   521                 gear^.Radius:= 7;
   439                 gear^.Z:= cOnHHZ;
   522                 gear^.Z:= cOnHHZ;
   440                 gear^.RenderTimer:= true;
   523                 gear^.RenderTimer:= false;
   441                 gear^.DirAngle:= -90 * hwSign(Gear^.dX);
   524                 gear^.DirAngle:= -90 * hwSign(Gear^.dX);
   442                 if not dX.isNegative then
   525                 if not dX.isNegative then
   443                     gear^.Angle:= 1
   526                     gear^.Angle:= 1
   444                 else
   527                 else
   445                     gear^.Angle:= 3
   528                     gear^.Angle:= 3;
       
   529                 New(cakeData);
       
   530                 gear^.Data:= Pointer(cakeData);
   446                 end;
   531                 end;
   447  gtHellishBomb: begin
   532  gtHellishBomb: begin
   448                 gear^.ImpactSound:= sndHellishImpact1;
   533                 gear^.ImpactSound:= sndHellishImpact1;
   449                 gear^.nImpactSounds:= 4;
   534                 gear^.nImpactSounds:= 4;
   450                 gear^.AdvBounce:= 1;
   535                 gear^.AdvBounce:= 1;
   481                 if gear^.Timer = 0 then gear^.Timer:= 5001;
   566                 if gear^.Timer = 0 then gear^.Timer:= 5001;
   482                 end;
   567                 end;
   483      gtRCPlane: begin
   568      gtRCPlane: begin
   484                 if gear^.Timer = 0 then gear^.Timer:= 15000;
   569                 if gear^.Timer = 0 then gear^.Timer:= 15000;
   485                 gear^.Health:= 3;
   570                 gear^.Health:= 3;
   486                 gear^.Radius:= 8
   571                 gear^.Radius:= 8;
       
   572                 gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF
   487                 end;
   573                 end;
   488      gtJetpack: begin
   574      gtJetpack: begin
   489                 gear^.Health:= 2000;
   575                 gear^.Health:= 2000;
   490                 gear^.Damage:= 100;
   576                 gear^.Damage:= 100;
   491                 gear^.State:= Gear^.State or gstSubmersible
   577                 gear^.State:= Gear^.State or gstSubmersible
   492                 end;
   578                 end;
   493      gtMolotov: begin
   579      gtMolotov: begin
       
   580                 gear^.AdvBounce:= 1;
   494                 gear^.Radius:= 6;
   581                 gear^.Radius:= 6;
   495                 gear^.Density:= _2;
   582                 gear^.Density:= _2
   496                 end;
   583                 end;
   497        gtBirdy: begin
   584        gtBirdy: begin
   498                 gear^.Radius:= 16; // todo: check
   585                 gear^.Radius:= 16; // todo: check
   499                 gear^.Health := 2000;
   586                 gear^.Health := 2000;
   500                 gear^.FlightTime := 2;
   587                 gear^.FlightTime := 2
   501                 end;
   588                 end;
   502          gtEgg: begin
   589          gtEgg: begin
   503                 gear^.AdvBounce:= 1;
   590                 gear^.AdvBounce:= 1;
   504                 gear^.Radius:= 4;
   591                 gear^.Radius:= 4;
   505                 gear^.Elasticity:= _0_6;
   592                 gear^.Elasticity:= _0_6;
   509                     gear^.Timer:= 3000
   596                     gear^.Timer:= 3000
   510                 end;
   597                 end;
   511       gtPortal: begin
   598       gtPortal: begin
   512                 gear^.ImpactSound:= sndMelonImpact;
   599                 gear^.ImpactSound:= sndMelonImpact;
   513                 gear^.nImpactSounds:= 1;
   600                 gear^.nImpactSounds:= 1;
   514                 gear^.AdvBounce:= 0;
       
   515                 gear^.Radius:= 17;
   601                 gear^.Radius:= 17;
   516                 // set color
   602                 // set color
   517                 gear^.Tag:= 2 * gear^.Timer;
   603                 gear^.Tag:= 2 * gear^.Timer;
   518                 gear^.Timer:= 15000;
   604                 gear^.Timer:= 15000;
   519                 gear^.RenderTimer:= false;
   605                 gear^.RenderTimer:= false;
   540                 gear^.Damage:= 100;
   626                 gear^.Damage:= 100;
   541                 end;
   627                 end;
   542  gtPoisonCloud: begin
   628  gtPoisonCloud: begin
   543                 if gear^.Timer = 0 then gear^.Timer:= 5000;
   629                 if gear^.Timer = 0 then gear^.Timer:= 5000;
   544                 gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000;
   630                 gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000;
       
   631                 gear^.Tint:= $C0C000C0
   545                 end;
   632                 end;
   546  gtResurrector: begin
   633  gtResurrector: begin
   547                 gear^.Radius := 100;
   634                 gear^.Radius := 100;
   548                 gear^.Tag := 0
   635                 gear^.Tag := 0;
       
   636                 gear^.Tint:= $F5DB35FF
   549                 end;
   637                 end;
   550      gtWaterUp: begin
   638      gtWaterUp: begin
   551                 gear^.Tag := 47;
   639                 gear^.Tag := 47;
   552                 end;
   640                 end;
   553   gtNapalmBomb: begin
   641   gtNapalmBomb: begin
   554                 gear^.AdvBounce:= 1;
       
   555                 gear^.Elasticity:= _0_8;
   642                 gear^.Elasticity:= _0_8;
   556                 gear^.Friction:= _0_8;
   643                 gear^.Friction:= _0_8;
   557                 if gear^.Timer = 0 then gear^.Timer:= 1000;
   644                 if gear^.Timer = 0 then gear^.Timer:= 1000;
   558                 gear^.Radius:= 5;
   645                 gear^.Radius:= 5;
   559                 gear^.Density:= _1_5;
   646                 gear^.Density:= _1_5;
   591 
   678 
   592 procedure DeleteGear(Gear: PGear);
   679 procedure DeleteGear(Gear: PGear);
   593 var team: PTeam;
   680 var team: PTeam;
   594     t,i: Longword;
   681     t,i: Longword;
   595     k: boolean;
   682     k: boolean;
       
   683     cakeData: PCakeData;
       
   684     iterator: PGear;
   596 begin
   685 begin
   597 
   686 
   598 ScriptCall('onGearDelete', gear^.uid);
   687 ScriptCall('onGearDelete', gear^.uid);
   599 
   688 
   600 DeleteCI(Gear);
   689 DeleteCI(Gear);
   601 
   690 
   602 FreeTexture(Gear^.Tex);
   691 FreeAndNilTexture(Gear^.Tex);
   603 Gear^.Tex:= nil;
   692 
       
   693 // remove potential links to this gear
       
   694 // currently relevant to: gears linked by hammer
       
   695 if (Gear^.Kind = gtHedgehog) or (Gear^.Kind = gtMine) or (Gear^.Kind = gtExplosives) then
       
   696     begin
       
   697     // check all gears for stuff to port through
       
   698     iterator := nil;
       
   699     while true do
       
   700         begin
       
   701 
       
   702         // iterate through GearsList
       
   703         if iterator = nil then
       
   704             iterator := GearsList
       
   705         else
       
   706             iterator := iterator^.NextGear;
       
   707 
       
   708         // end of list?
       
   709         if iterator = nil then
       
   710             break;
       
   711 
       
   712         if iterator^.LinkedGear = Gear then
       
   713             iterator^.LinkedGear:= nil;
       
   714         end;
       
   715 
       
   716     end;
   604 
   717 
   605 // make sure that portals have their link removed before deletion
   718 // make sure that portals have their link removed before deletion
   606 if (Gear^.Kind = gtPortal) then
   719 if (Gear^.Kind = gtPortal) then
   607     begin
   720     begin
   608     if (Gear^.LinkedGear <> nil) then
   721     if (Gear^.LinkedGear <> nil) then
   609         if (Gear^.LinkedGear^.LinkedGear = Gear) then
   722         if (Gear^.LinkedGear^.LinkedGear = Gear) then
   610             Gear^.LinkedGear^.LinkedGear:= nil;
   723             Gear^.LinkedGear^.LinkedGear:= nil;
       
   724     end
       
   725 else if Gear^.Kind = gtCake then
       
   726     begin
       
   727         cakeData:= PCakeData(Gear^.Data);
       
   728         Dispose(cakeData);
       
   729         cakeData:= nil;
   611     end
   730     end
   612 else if Gear^.Kind = gtHedgehog then
   731 else if Gear^.Kind = gtHedgehog then
   613     (*
   732     (*
   614     This behaviour dates back to revision 4, and I accidentally encountered it with TARDIS.  I don't think it must apply to any modern weapon, since if it was actually hit, the best the gear could do would be to destroy itself immediately, and you'd still end up with two graves.  I believe it should be removed
   733     This behaviour dates back to revision 4, and I accidentally encountered it with TARDIS.  I don't think it must apply to any modern weapon, since if it was actually hit, the best the gear could do would be to destroy itself immediately, and you'd still end up with two graves.  I believe it should be removed
   615      if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then
   734      if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then
   619         CurAmmoGear^.Message:= gmDestroy;
   738         CurAmmoGear^.Message:= gmDestroy;
   620         exit
   739         exit
   621         end
   740         end
   622     else*)
   741     else*)
   623         begin
   742         begin
   624         if (Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtKamikaze) then
   743         if ((CurrentHedgehog = nil) or (Gear <> CurrentHedgehog^.Gear)) or (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtKamikaze) then
   625             Gear^.Hedgehog^.Team^.Clan^.Flawless:= false;
   744             Gear^.Hedgehog^.Team^.Clan^.Flawless:= false;
   626         if (hwRound(Gear^.Y) >= cWaterLine) then
   745         if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then
   627             begin
   746             begin
   628             t:= max(Gear^.Damage, Gear^.Health);
   747             t:= max(Gear^.Damage, Gear^.Health);
   629             Gear^.Damage:= t;
   748             Gear^.Damage:= t;
   630             if ((not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (WaterOpacity < $FF)))
   749             if (((not SuddenDeathDmg) and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) then
   631             and (hwRound(Gear^.Y) < cWaterLine + 256) then
       
   632                 spawnHealthTagForHH(Gear, t);
   750                 spawnHealthTagForHH(Gear, t);
   633             end;
   751             end;
   634 
   752 
   635         team:= Gear^.Hedgehog^.Team;
   753         team:= Gear^.Hedgehog^.Team;
   636         if CurrentHedgehog^.Gear = Gear then
   754         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear = Gear) then
   637             begin
   755             begin
   638             AttackBar:= 0;
   756             AttackBar:= 0;
   639             FreeActionsList; // to avoid ThinkThread on drawned gear
   757             FreeActionsList; // to avoid ThinkThread on drawned gear
   640             if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0)
   758             if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0)
   641             and (CurrentHedgehog^.MultiShootAttacks > 0) then
   759             and (CurrentHedgehog^.MultiShootAttacks > 0) then
   642                 OnUsedAmmo(CurrentHedgehog^);
   760                 OnUsedAmmo(CurrentHedgehog^);
   643             end;
   761             end;
   644 
   762 
   645         Gear^.Hedgehog^.Gear:= nil;
   763         Gear^.Hedgehog^.Gear:= nil;
       
   764 
   646         if Gear^.Hedgehog^.King then
   765         if Gear^.Hedgehog^.King then
   647             begin
   766             begin
   648             // are there any other kings left? Just doing nil check.  Presumably a mortally wounded king will get reaped soon enough
   767             // are there any other kings left? Just doing nil check.  Presumably a mortally wounded king will get reaped soon enough
   649             k:= false;
   768             k:= false;
   650             for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
   769             for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
   651                 if (team^.Clan^.Teams[i]^.Hedgehogs[0].Gear <> nil) then
   770                 if (team^.Clan^.Teams[i]^.Hedgehogs[0].Gear <> nil) then
   652                     k:= true;
   771                     k:= true;
   653             if not k then
   772             if not k then
   654                 for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
   773                 for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
   655                     begin
   774                     with team^.Clan^.Teams[i]^ do
   656                     team^.Clan^.Teams[i]^.hasGone:= true;
   775                         for t:= 0 to cMaxHHIndex do
   657                     TeamGoneEffect(team^.Clan^.Teams[i]^)
   776                             if Hedgehogs[t].Gear <> nil then
   658                     end
   777                                 Hedgehogs[t].Gear^.Health:= 0
       
   778                             else if (Hedgehogs[t].GearHidden <> nil) then
       
   779                                 Hedgehogs[t].GearHidden^.Health:= 0  // hog is still hidden. if tardis should return though, lua, eh...
   659             end;
   780             end;
   660 
   781 
   661         // should be not CurrentHedgehog, but hedgehog of the last gear which caused damage to this hog
   782         // should be not CurrentHedgehog, but hedgehog of the last gear which caused damage to this hog
   662         // same stand for CheckHHDamage
   783         // same stand for CheckHHDamage
   663         if (Gear^.LastDamage <> nil) then
   784         if (Gear^.LastDamage <> nil) and (CurrentHedgehog <> nil) then
   664             uStats.HedgehogDamaged(Gear, Gear^.LastDamage, 0, true)
   785             uStats.HedgehogDamaged(Gear, Gear^.LastDamage, 0, true)
   665         else
   786         else if CurrentHedgehog <> nil then
   666             uStats.HedgehogDamaged(Gear, CurrentHedgehog, 0, true);
   787             uStats.HedgehogDamaged(Gear, CurrentHedgehog, 0, true);
   667 
   788 
   668         inc(KilledHHs);
   789         inc(KilledHHs);
   669         RecountTeamHealth(team);
   790         RecountTeamHealth(team);
   670         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Effects[heResurrectable] <> 0)  and
   791         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Effects[heResurrectable] <> 0)  and
   671         //(Gear^.Hedgehog^.Effects[heResurrectable] = 0) then
   792         //(Gear^.Hedgehog^.Effects[heResurrectable] = 0) then
   672         (Gear^.Hedgehog^.Team^.Clan <> CurrentHedgehog^.Team^.Clan) then
   793         (Gear^.Hedgehog^.Team^.Clan <> CurrentHedgehog^.Team^.Clan) then
   673             with CurrentHedgehog^ do
   794             with CurrentHedgehog^ do
   674                 begin
   795                 begin
   675                 inc(Team^.stats.AIKills);
   796                 inc(Team^.stats.AIKills);
   676                 FreeTexture(Team^.AIKillsTex);
   797                 FreeAndNilTexture(Team^.AIKillsTex);
   677                 Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
   798                 Team^.AIKillsTex := RenderStringTex(ansistring(inttostr(Team^.stats.AIKills)), Team^.Clan^.Color, fnt16);
   678                 end
   799                 end
   679         end;
   800         end;
   680 with Gear^ do
   801 with Gear^ do
   681     begin
   802     begin
   682     AddFileLog('Delete: #' + inttostr(uid) + ' (' + inttostr(hwRound(x)) + ',' + inttostr(hwRound(y)) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
   803     AddFileLog('Delete: #' + inttostr(uid) + ' (' + inttostr(hwRound(x)) + ',' + inttostr(hwRound(y)) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
   686     CurAmmoGear:= nil;
   807     CurAmmoGear:= nil;
   687 if FollowGear = Gear then
   808 if FollowGear = Gear then
   688     FollowGear:= nil;
   809     FollowGear:= nil;
   689 if lastGearByUID = Gear then
   810 if lastGearByUID = Gear then
   690     lastGearByUID := nil;
   811     lastGearByUID := nil;
   691 RemoveGearFromList(Gear);
   812 if (Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.GearHidden <> Gear) then // hidden hedgehogs shouldn't be in the list
       
   813      RemoveGearFromList(Gear)
       
   814 else Gear^.Hedgehog^.GearHidden:= nil;
       
   815 
   692 Dispose(Gear)
   816 Dispose(Gear)
   693 end;
   817 end;
   694 
   818 
   695 end.
   819 end.