--- a/hedgewars/uGearsUtils.pas Sun Jun 10 18:56:51 2018 +0200
+++ b/hedgewars/uGearsUtils.pas Sun Jun 10 19:12:26 2018 +0200
@@ -31,6 +31,8 @@
procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
+procedure HHHeal(Hedgehog: PHedgehog; healthBoost: Longword; showMessage: boolean; vgTint: Longword);
+procedure HHHeal(Hedgehog: PHedgehog; healthBoost: Longword; showMessage: boolean);
procedure CheckHHDamage(Gear: PGear);
procedure CalcRotationDirAngle(Gear: PGear);
procedure ResurrectHedgehog(var gear: PGear);
@@ -38,12 +40,14 @@
procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline;
procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
+function CheckGearNear(Kind: TGearType; X, Y: hwFloat; rX, rY: LongInt): PGear;
function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
function CheckGearDrowning(var Gear: PGear): boolean;
procedure CheckCollision(Gear: PGear); inline;
procedure CheckCollisionWithLand(Gear: PGear); inline;
procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
+procedure AmmoShoveLine(Ammo: PGear; Damage, Power: LongInt; oX, oY, tX, tY: hwFloat);
function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS;
procedure SpawnBoxOfSmth;
procedure ShotgunShot(Gear: PGear);
@@ -262,8 +266,7 @@
end;
procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
-var s: ansistring;
- vampDmg, tmpDmg, i: Longword;
+var vampDmg, tmpDmg, i: Longword;
vg: PVisualGear;
begin
if Damage = 0 then
@@ -287,22 +290,9 @@
// was considering pulsing on attack, Tiy thinks it should be permanent while in play
//CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstVampiric;
inc(CurrentHedgehog^.Gear^.Health,vampDmg);
- s:= IntToStr(vampDmg);
- AddCaption(FormatA(trmsg[sidHealthGain], s), CurrentHedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
RenderHealth(CurrentHedgehog^);
RecountTeamHealth(CurrentHedgehog^.Team);
- i:= 0;
- while (i < vampDmg) and (i < 1000) do
- begin
- vg:= AddVisualGear(hwRound(CurrentHedgehog^.Gear^.X), hwRound(CurrentHedgehog^.Gear^.Y), vgtStraightShot);
- if vg <> nil then
- with vg^ do
- begin
- Tint:= $FF0000FF;
- State:= ord(sprHealth)
- end;
- inc(i, 5);
- end;
+ HHHeal(CurrentHedgehog, vampDmg, true, $FF0000FF);
end
end;
if (GameFlags and gfKarma <> 0) and (GameFlags and gfInvulnerable = 0) and
@@ -354,6 +344,7 @@
HHGear^.Active:= true;
end;
+// Play effects for hurt hedgehog
procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
begin
if Hedgehog^.Effects[heFrozen] <> 0 then exit;
@@ -378,6 +369,48 @@
end
end;
+{-
+Show heal particles and message at hog gear.
+Hedgehog: Hedgehog which gets the health boost
+healthBoost: Amount of added health added
+showMessage: Whether to show announcer message
+vgTint: Tint of heal particle
+-}
+procedure HHHeal(Hedgehog: PHedgehog; healthBoost: Longword; showMessage: boolean; vgTint: Longword);
+var i: LongInt;
+ vg: PVisualGear;
+ s: ansistring;
+begin
+ if healthBoost < 1 then
+ exit;
+
+ if showMessage then
+ begin
+ s:= IntToStr(healthBoost);
+ AddCaption(FormatA(trmsg[sidHealthGain], s), Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo)
+ end;
+
+ i:= 0;
+ // One particle for every 5 HP. Max. 200 particles
+ while (i < healthBoost) and (i < 1000) do
+ begin
+ vg:= AddVisualGear(hwRound(Hedgehog^.Gear^.X), hwRound(Hedgehog^.Gear^.Y), vgtStraightShot);
+ if vg <> nil then
+ with vg^ do
+ begin
+ Tint:= vgTint;
+ State:= ord(sprHealth)
+ end;
+ inc(i, 5)
+ end;
+end;
+
+// Shorthand for the same above, but with tint implied
+procedure HHHeal(Hedgehog: PHedgehog; healthBoost: Longword; showMessage: boolean);
+begin
+ HHHeal(Hedgehog, healthBoost, showMessage, $00FF00FF);
+end;
+
procedure CheckHHDamage(Gear: PGear);
var
dmg: LongInt;
@@ -663,7 +696,8 @@
TurnTimeLeft := 0;
Gear^.RenderTimer := false;
if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot)
- and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
+ and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot)
+ and (Gear^.Kind <> gtMinigunBullet) then
if Gear^.Kind = gtHedgehog then
begin
if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then
@@ -992,20 +1026,48 @@
end
end;
-function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
+function CheckGearNear(Kind: TGearType; X, Y: hwFloat; rX, rY: LongInt): PGear;
var t: PGear;
+ width: hwFloat;
begin
t:= GearsList;
rX:= sqr(rX);
rY:= sqr(rY);
+width:= int2hwFloat(RightX-LeftX);
+
+while t <> nil do
+ begin
+ if (t^.Kind = Kind) then
+ if (not ((hwSqr(X - t^.X) / rX + hwSqr(Y - t^.Y) / rY) > _1)) or
+ ((WorldEdge = weWrap) and (
+ (not ((hwSqr(X - width - t^.X) / rX + hwSqr(Y - t^.Y) / rY) > _1)) or
+ (not ((hwSqr(X + width - t^.X) / rX + hwSqr(Y - t^.Y) / rY) > _1)))) then
+ begin
+ CheckGearNear:= t;
+ exit;
+ end;
+ t:= t^.NextGear
+ end;
+
+CheckGearNear:= nil
+end;
+
+function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
+var t: PGear;
+ width: hwFloat;
+begin
+t:= GearsList;
+rX:= sqr(rX);
+rY:= sqr(rY);
+width:= int2hwFloat(RightX-LeftX);
while t <> nil do
begin
if (t <> Gear) and (t^.Kind = Kind) then
if (not ((hwSqr(Gear^.X - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)) or
((WorldEdge = weWrap) and (
- (not ((hwSqr(Gear^.X - int2hwFloat(RightX-LeftX) - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)) or
- (not ((hwSqr(Gear^.X + int2hwFloat(RightX-LeftX) - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)))) then
+ (not ((hwSqr(Gear^.X - width - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)) or
+ (not ((hwSqr(Gear^.X + width - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)))) then
begin
CheckGearNear:= t;
exit;
@@ -1117,6 +1179,7 @@
gtHedgehog,
gtMine,
gtSMine,
+ gtAirMine,
gtKnife,
gtCase,
gtTarget,
@@ -1190,7 +1253,7 @@
usable:= true;
HH:= HHGear^.Hedgehog;
if HHGear <> nil then
- if (HHGear = nil) or (HH^.King) or (SuddenDeathDmg) then
+ if (HHGear = nil) or (HH^.King) or (SuddenDeathActive) then
usable:= false;
cnt:= 0;
for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do
@@ -1204,13 +1267,14 @@
CanUseTardis:= usable;
end;
-procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
+procedure AmmoShoveImpl(Ammo: PGear; Damage, Power: LongInt; collisions: PGearArray);
var t: PGearArray;
Gear: PGear;
i, j, tmpDmg: LongInt;
VGear: PVisualGear;
begin
-t:= CheckGearsCollision(Ammo);
+t:= collisions;
+
// Just to avoid hogs on rope dodging fire.
if (CurAmmoGear <> nil) and ((CurAmmoGear^.Kind = gtRope) or (CurAmmoGear^.Kind = gtJetpack) or (CurAmmoGear^.Kind = gtBirdy))
and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1)
@@ -1228,18 +1292,22 @@
begin
dec(i);
Gear:= t^.ar[i];
- if (Ammo^.Data <> nil) and (Ammo^.Kind in [gtDEagleShot, gtSniperRifleShot]) and (PGear(Ammo^.Data) = Gear) then
+ if (Ammo^.Kind in [gtDEagleShot, gtSniperRifleShot, gtMinigunBullet])
+ and (((Ammo^.Data <> nil) and (PGear(Ammo^.Data) = Gear))
+ or (not UpdateHitOrder(Gear, Ammo^.WDTimer))) then
continue;
+
if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and
- (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then
+ (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then
Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000);
tmpDmg:= ModifyDamage(Damage, Gear);
if (Gear^.State and gstNoDamage) = 0 then
begin
- if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then
+ if (not (Gear^.Kind in [gtMinigun, gtPortal])) and
+ (Ammo^.Kind in [gtDEagleShot, gtSniperRifleShot, gtMinigunBullet]) then
begin
- VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
+ VGear := AddVisualGear(t^.cX[i], t^.cY[i], vgtBulletHit);
if VGear <> nil then
VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
end;
@@ -1251,6 +1319,7 @@
case Gear^.Kind of
gtHedgehog,
gtMine,
+ gtAirMine,
gtSMine,
gtKnife,
gtTarget,
@@ -1268,7 +1337,10 @@
if (Ammo^.Kind = gtKnife) and (tmpDmg > 0) then
for j:= 1 to max(1,min(3,tmpDmg div 5)) do
begin
- VGear:= AddVisualGear(hwRound(Ammo^.X-((Ammo^.X-Gear^.X)/_2)), hwRound(Ammo^.Y-((Ammo^.Y-Gear^.Y)/_2)), vgtStraightShot);
+ VGear:= AddVisualGear(
+ t^.cX[i] - ((t^.cX[i] - hwround(Gear^.X)) div 2),
+ t^.cY[i] - ((t^.cY[i] - hwround(Gear^.Y)) div 2),
+ vgtStraightShot);
if VGear <> nil then
with VGear^ do
begin
@@ -1297,13 +1369,13 @@
if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then
begin
- Gear^.dX:= Ammo^.dX * Power * _0_005;
- Gear^.dY:= Ammo^.dY * Power * _0_005
+ Gear^.dX:= Gear^.dX + Ammo^.dX * Power * _0_005;
+ Gear^.dY:= Gear^.dY + Ammo^.dY * Power * _0_005
end
else if ((Ammo^.Kind <> gtFlame) or (Gear^.Kind = gtHedgehog)) and (Power <> 0) then
begin
- Gear^.dX:= Ammo^.dX * Power * _0_01;
- Gear^.dY:= Ammo^.dY * Power * _0_01
+ Gear^.dX:= Gear^.dX + Ammo^.dX * Power * _0_01;
+ Gear^.dY:= Gear^.dY + Ammo^.dY * Power * _0_01
end;
if (not isZero(Gear^.dX)) or (not isZero(Gear^.dY)) then
@@ -1338,6 +1410,19 @@
SetAllToActive
end;
+procedure AmmoShoveLine(Ammo: PGear; Damage, Power: LongInt; oX, oY, tX, tY: hwFloat);
+var t: PGearArray;
+begin
+ t:= CheckAllGearsLineCollision(Ammo, oX, oY, tX, tY);
+ AmmoShoveImpl(Ammo, Damage, Power, t);
+end;
+
+procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
+begin
+ AmmoShoveImpl(Ammo, Damage, Power,
+ CheckGearsCollision(Ammo));
+end;
+
function CountGears(Kind: TGearType): Longword;
var t: PGear;
@@ -1423,7 +1508,6 @@
GearsNear.ar:= @GearsNearArray
end;
-
procedure SpawnBoxOfSmth;
var t, aTot, uTot, a, h: LongInt;
i: TAmmoType;
@@ -1578,9 +1662,6 @@
if (hwRound(Gear^.X) < LongInt(leftX)) or
(hwRound(Gear^.X) > LongInt(rightX)) then
begin
- // bullets can now hurt the hog that fired them
- if (WorldEdge <> weSea) and (Gear^.Kind in [gtDEagleShot, gtSniperRifleShot]) then
- Gear^.Data:= nil;
if WorldEdge = weWrap then
begin
if (hwRound(Gear^.X) < LongInt(leftX)) then