hedgewars/uGearsUtils.pas
branchwebgl
changeset 9127 e350500c4edb
parent 8833 c13ebed437cb
parent 9080 9b42757d7e71
child 9160 fc46e75f6b72
equal deleted inserted replaced
8860:bde641cf53c8 9127:e350500c4edb
     1 (*
     1 (*
     2  * Hedgewars, a free turn based strategy game
     2  * Hedgewars, a free turn based strategy game
     3  * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
     3  * Copyright (c) 2004-2013 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  *
    29 procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
    29 procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
    30 procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
    30 procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
    31 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
    31 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
    32 procedure CheckHHDamage(Gear: PGear);
    32 procedure CheckHHDamage(Gear: PGear);
    33 procedure CalcRotationDirAngle(Gear: PGear);
    33 procedure CalcRotationDirAngle(Gear: PGear);
    34 procedure ResurrectHedgehog(gear: PGear);
    34 procedure ResurrectHedgehog(var gear: PGear);
    35 
    35 
    36 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline;
    36 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline;
    37 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
    37 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
    38 
    38 
    39 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
    39 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
    40 function  CheckGearDrowning(Gear: PGear): boolean;
    40 function  CheckGearDrowning(var Gear: PGear): boolean;
    41 procedure CheckCollision(Gear: PGear); inline;
    41 procedure CheckCollision(Gear: PGear); inline;
    42 procedure CheckCollisionWithLand(Gear: PGear); inline;
    42 procedure CheckCollisionWithLand(Gear: PGear); inline;
    43 
    43 
    44 function MakeHedgehogsStep(Gear: PGear) : boolean;
    44 function MakeHedgehogsStep(Gear: PGear) : boolean;
    45 
    45 
   261 HHGear^.Active:= true;
   261 HHGear^.Active:= true;
   262 end;
   262 end;
   263 
   263 
   264 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
   264 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
   265 begin
   265 begin
       
   266 if Hedgehog^.Effects[heFrozen] <> 0 then exit;
   266 if (Source = dsFall) or (Source = dsExplosion) then
   267 if (Source = dsFall) or (Source = dsExplosion) then
   267     case random(3) of
   268     case random(3) of
   268         0: PlaySoundV(sndOoff1, Hedgehog^.Team^.voicepack);
   269         0: PlaySoundV(sndOoff1, Hedgehog^.Team^.voicepack);
   269         1: PlaySoundV(sndOoff2, Hedgehog^.Team^.voicepack);
   270         1: PlaySoundV(sndOoff2, Hedgehog^.Team^.voicepack);
   270         2: PlaySoundV(sndOoff3, Hedgehog^.Team^.voicepack);
   271         2: PlaySoundV(sndOoff3, Hedgehog^.Team^.voicepack);
   287 var
   288 var
   288     dmg: Longword;
   289     dmg: Longword;
   289     i: LongWord;
   290     i: LongWord;
   290     particle: PVisualGear;
   291     particle: PVisualGear;
   291 begin
   292 begin
   292     if _0_4 < Gear^.dY then
   293 if _0_4 < Gear^.dY then
   293         begin
   294     begin
   294         dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear);
   295     dmg := ModifyDamage(1 + hwRound((Gear^.dY - _0_4) * 70), Gear);
   295         PlaySound(sndBump);
   296     if Gear^.Hedgehog^.Effects[heFrozen] = 0 then
   296         if dmg < 1 then
   297          PlaySound(sndBump)
   297             exit;
   298     else PlaySound(sndFrozenHogImpact);
   298 
   299     if dmg < 1 then
   299         for i:= min(12, (3 + dmg div 10)) downto 0 do
   300         exit;
   300             begin
   301 
   301             particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
   302     for i:= min(12, (3 + dmg div 10)) downto 0 do
   302             if particle <> nil then
   303         begin
   303                 particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
   304         particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
   304             end;
   305         if particle <> nil then
   305 
   306             particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
   306         if (Gear^.Invulnerable) then
   307         end;
   307             exit;
   308 
   308 
   309     if (Gear^.Invulnerable) then
   309         //if _0_6 < Gear^.dY then
   310         exit;
   310         //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
   311 
   311         //else
   312     //if _0_6 < Gear^.dY then
   312         //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
   313     //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
   313 
   314     //else
   314         if Gear^.LastDamage <> nil then
   315     //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
   315             ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
   316 
   316         else
   317     if Gear^.LastDamage <> nil then
   317             ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
   318         ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
       
   319     else
       
   320         ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
   318     end
   321     end
   319 end;
   322 end;
   320 
   323 
   321 
   324 
   322 procedure CalcRotationDirAngle(Gear: PGear);
   325 procedure CalcRotationDirAngle(Gear: PGear);
   335         Gear^.DirAngle := Gear^.DirAngle + 360
   338         Gear^.DirAngle := Gear^.DirAngle + 360
   336     else if 360 < Gear^.DirAngle then
   339     else if 360 < Gear^.DirAngle then
   337         Gear^.DirAngle := Gear^.DirAngle - 360
   340         Gear^.DirAngle := Gear^.DirAngle - 360
   338 end;
   341 end;
   339 
   342 
   340 function CheckGearDrowning(Gear: PGear): boolean;
   343 function CheckGearDrowning(var Gear: PGear): boolean;
   341 var
   344 var 
   342     skipSpeed, skipAngle, skipDecay: hwFloat;
   345     skipSpeed, skipAngle, skipDecay: hwFloat;
   343     i, maxDrops, X, Y: LongInt;
   346     i, maxDrops, X, Y: LongInt;
   344     vdX, vdY: real;
   347     vdX, vdY: real;
   345     particle, splash: PVisualGear;
   348     particle, splash: PVisualGear;
   346     isSubmersible: boolean;
   349     isSubmersible: boolean;
   359                 Gear^.dY:= _90-(GetRandomf*_360)
   362                 Gear^.dY:= _90-(GetRandomf*_360)
   360                 end
   363                 end
   361             else DeleteGear(Gear);
   364             else DeleteGear(Gear);
   362             exit
   365             exit
   363             end;
   366             end;
   364         isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
   367         isSubmersible:= ((Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0)) or (Gear^.State and gstSubmersible <> 0);
   365         skipSpeed := _0_25;
   368         skipSpeed := _0_25;
   366         skipAngle := _1_9;
   369         skipAngle := _1_9;
   367         skipDecay := _0_87;
   370         skipDecay := _0_87;
   368         X:= hwRound(Gear^.X);
   371         X:= hwRound(Gear^.X);
   369         vdX:= hwFloat2Float(Gear^.dX);
   372         vdX:= hwFloat2Float(Gear^.dX);
   370         vdY:= hwFloat2Float(Gear^.dY);
   373         vdY:= hwFloat2Float(Gear^.dY);
   371         // this could perhaps be a tiny bit higher.
   374         // this could perhaps be a tiny bit higher.
   372         if  (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed)
   375         if  (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) 
   373         and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
   376         and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
   374             begin
   377             begin
   375             Gear^.dY.isNegative := true;
   378             Gear^.dY.isNegative := true;
   376             Gear^.dY := Gear^.dY * skipDecay;
   379             Gear^.dY := Gear^.dY * skipDecay;
   377             Gear^.dX := Gear^.dX * skipDecay;
   380             Gear^.dX := Gear^.dX * skipDecay;
   388                 if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot)
   391                 if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot)
   389                 and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
   392                 and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
   390                     if Gear^.Kind = gtHedgehog then
   393                     if Gear^.Kind = gtHedgehog then
   391                         begin
   394                         begin
   392                         if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then
   395                         if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then
   393                             ResurrectHedgehog(Gear)
   396                             begin
       
   397                             // Gear could become nil after this, just exit to skip splashes
       
   398                             ResurrectHedgehog(Gear);
       
   399                             exit
       
   400                             end
   394                         else
   401                         else
   395                             begin
   402                             begin
   396                             Gear^.doStep := @doStepDrowningGear;
   403                             Gear^.doStep := @doStepDrowningGear;
   397                             Gear^.State := Gear^.State and (not gstHHDriven);
   404                             Gear^.State := Gear^.State and (not gstHHDriven);
   398                             AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
   405                             AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
   399                             end
   406                             end
   400                         end
   407                         end
   401                     else
   408                     else
   402                         Gear^.doStep := @doStepDrowningGear;
   409                         Gear^.doStep := @doStepDrowningGear;
   403                         if Gear^.Kind = gtFlake then
   410                         if Gear^.Kind = gtFlake then
   404                             exit // skip splashes
   411                             exit // skip splashes 
   405                 end;
   412                 end
       
   413             else if (Y > cWaterLine + cVisibleWater*4) and 
       
   414                     ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then
       
   415                 Gear^.doStep:= @doStepDrowningGear;
   406             if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
   416             if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
   407             or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
   417             or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0)
   408             and (CurAmmoGear^.dY < _0_01))) then
   418             and (CurAmmoGear^.dY < _0_01))) then
   409                 if Gear^.Density * Gear^.dY > _1 then
   419                 if Gear^.Density * Gear^.dY > _1 then
   410                     PlaySound(sndSplash)
   420                     PlaySound(sndSplash)
   411                 else if Gear^.Density * Gear^.dY > _0_5 then
   421                 else if Gear^.Density * Gear^.dY > _0_5 then
   412                     PlaySound(sndSkip)
   422                     PlaySound(sndSkip)
   414                     PlaySound(sndDroplet2);
   424                     PlaySound(sndDroplet2);
   415             end;
   425             end;
   416 
   426 
   417         if ((cReducedQuality and rqPlainSplash) = 0)
   427         if ((cReducedQuality and rqPlainSplash) = 0)
   418         and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
   428         and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
   419         or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
   429         or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0)
   420         and (CurAmmoGear^.dY < _0_01)))) then
   430         and (CurAmmoGear^.dY < _0_01)))) then
   421             begin
   431             begin
   422             splash:= AddVisualGear(X, cWaterLine, vgtSplash);
   432             splash:= AddVisualGear(X, cWaterLine, vgtSplash);
   423             if splash <> nil then
   433             if splash <> nil then
   424                 with splash^ do
   434                 with splash^ do
   455                                 end
   465                                 end
   456                             end
   466                             end
   457                         end
   467                         end
   458                 end
   468                 end
   459             end;
   469             end;
   460         if isSubmersible and (CurAmmoGear^.Pos = 0) then
   470         if isSubmersible and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) then
   461             CurAmmoGear^.Pos := 1000
   471             CurAmmoGear^.Pos := 1000
   462         end
   472         end
   463     else
   473     else
   464         CheckGearDrowning := false;
   474         CheckGearDrowning := false;
   465 end;
   475 end;
   466 
   476 
   467 
   477 
   468 procedure ResurrectHedgehog(gear: PGear);
   478 procedure ResurrectHedgehog(var gear: PGear);
   469 var tempTeam : PTeam;
   479 var tempTeam : PTeam;
   470     sparkles: PVisualGear;
   480     sparkles: PVisualGear;
   471     gX, gY: LongInt;
   481     gX, gY: LongInt;
   472 begin
   482 begin
   473     if (Gear^.LastDamage <> nil) then
   483     if (Gear^.LastDamage <> nil) then
   505         AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion);
   515         AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion);
   506         PlaySound(sndWarp);
   516         PlaySound(sndWarp);
   507         RenderHealth(gear^.Hedgehog^);
   517         RenderHealth(gear^.Hedgehog^);
   508         ScriptCall('onGearResurrect', gear^.uid);
   518         ScriptCall('onGearResurrect', gear^.uid);
   509         gear^.State := gstWait;
   519         gear^.State := gstWait;
   510     end;
   520         end;
   511     RecountTeamHealth(tempTeam);
   521     RecountTeamHealth(tempTeam);
   512 end;
   522 end;
   513 
   523 
   514 function CountNonZeroz(x, y, r, c: LongInt; mask: LongWord): LongInt;
   524 function CountNonZeroz(x, y, r, c: LongInt; mask: LongWord): LongInt;
   515 var i: LongInt;
   525 var i: LongInt;