--- a/hedgewars/uGearsHedgehog.pas Fri Oct 11 17:43:13 2013 +0200
+++ b/hedgewars/uGearsHedgehog.pas Sat Jan 04 23:55:54 2014 +0400
@@ -20,7 +20,7 @@
unit uGearsHedgehog;
interface
-uses uTypes;
+uses uTypes, uGearsHandlersMess;
procedure doStepHedgehog(Gear: PGear);
procedure AfterAttack;
@@ -35,10 +35,22 @@
uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions,
uCommands, uLocale, uUtils, uStats, uIO, uScript,
uGearsList, uCollisions, uRandom, uStore, uTeams,
- uGearsUtils, uVisualGearsList;
+ uGearsUtils, uVisualGearsList, uChat;
var GHStepTicks: LongWord = 0;
+procedure AFKSkip;
+var
+ t: byte;
+begin
+ t:= 0;
+ while (TeamsArray[t] <> CurrentTeam) do inc(t);
+
+ SendHogSpeech(#1 + char(t) + 'AFK');
+
+ ParseCommand('/skip', true)
+end;
+
// Shouldn't more of this ammo switching stuff be moved to uAmmos ?
function ChangeAmmo(HHGear: PGear): boolean;
var slot, i: Longword;
@@ -53,7 +65,7 @@
HHGear^.Message:= HHGear^.Message and (not gmSlot);
prevAmmo:= CurAmmoType;
ammoidx:= 0;
- if ((HHGear^.State and (gstAttacking or gstAttacked)) <> 0)
+ if (((HHGear^.State and (gstAttacking or gstAttacked)) <> 0) and (GameFlags and gfInfAttack = 0))
or ((HHGear^.State and gstHHDriven) = 0) then
exit;
ChangeAmmo:= true;
@@ -114,9 +126,9 @@
LoadHedgehogHat(HHGear^.Hedgehog^, Hat);
end;
// Try again in the next slot
- if CurAmmoType = prevAmmo then
+ if (CurAmmoType = prevAmmo) and (slot < cMaxSlotIndex) then
begin
- if slot >= cMaxSlotIndex then slot:= 0 else inc(slot);
+ inc(slot);
HHGear^.MsgParam:= slot;
ChangeAmmo(HHGear)
end
@@ -128,6 +140,7 @@
weap: TAmmoType;
Hedgehog: PHedgehog;
s: boolean;
+ prevState, newState: LongWord;
begin
s:= false;
@@ -143,12 +156,18 @@
HHGear^.Message:= HHGear^.Message and (not gmWeapon);
+prevState:= HHGear^.State;
+newState:= prevState;
with Hedgehog^ do
while (CurAmmoType <> weap) and (t >= 0) do
begin
s:= ChangeAmmo(HHGear);
+ if HHGear^.State <> prevState then // so we can keep gstAttacked out of consideration when looping
+ newState:= HHGear^.State;
+ HHGear^.State:= prevState;
dec(t)
end;
+HHGear^.State:= newState;
if s then
ApplyAmmoChanges(HHGear^.Hedgehog^)
@@ -334,6 +353,10 @@
amNapalm: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 2, _0, _0, 0);
amBlowTorch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
amGirder: newGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
+ amRubber: begin
+ newGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
+ newGear^.AmmoType:= amRubber
+ end;
amTeleport: newGear:= AddGear(CurWeapon^.Pos, 0, gtTeleport, 0, _0, _0, 0);
amSwitch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
amMortar: begin
@@ -365,7 +388,7 @@
PlaySound(sndHellishImpact4);
cDamageModifier:= _1_5
end;
- amInvulnerable: Invulnerable:= true;
+ amInvulnerable: Effects[heInvulnerable]:= 1;
amExtraTime: begin
PlaySound(sndSwitchHog);
TurnTimeLeft:= TurnTimeLeft + 30000
@@ -390,7 +413,7 @@
newGear^.SoundChannel := LoopSound(sndResurrector);
end;
//amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
- amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000);
+ amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 0);
amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0);
end;
if altUse and (newGear <> nil) and
@@ -425,7 +448,7 @@
amFlamethrower, amLandGun,
amResurrector, //amStructure,
amTardis, amPiano,
- amIceGun: CurAmmoGear:= newGear;
+ amIceGun, amRubber: CurAmmoGear:= newGear;
end;
if ((CurAmmoType = amMine) or (CurAmmoType = amSMine)) and (GameFlags and gfInfAttack <> 0) then
@@ -747,13 +770,13 @@
Gear^.Message:= Gear^.Message and (not gmLJump);
DeleteCI(Gear);
if TestCollisionYwithGear(Gear, -1) = 0 then
- if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
+ if TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) = 0 then
Gear^.Y:= Gear^.Y - _2
else
- if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then
+ if TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) = 0 then
Gear^.Y:= Gear^.Y - _1;
- if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
- or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+ if (TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) = 0) and
+ (TestCollisionYwithGear(Gear, -1) = 0) then
begin
Gear^.dY:= -_0_15;
if not cArtillery then
@@ -841,11 +864,21 @@
Gear^.State:= Gear^.State and (not gstMoving);
exit
end;
-isFalling:= (Gear^.dY.isNegative) or (not TestCollisionYKick(Gear, 1));
+isFalling:= (Gear^.dY.isNegative) or (TestCollisionYKick(Gear, 1) = 0);
if isFalling then
begin
- if (Gear^.dY.isNegative) and TestCollisionYKick(Gear, -1) then
- Gear^.dY:= _0;
+ land:= TestCollisionYKick(Gear, -1);
+ if (Gear^.dY.isNegative) and (land <> 0) then
+ begin
+ if land and lfBouncy <> 0 then
+ begin
+ doStepFallingGear(Gear);
+ Gear^.dX:= Gear^.dX * _0_8
+ end;
+ if (land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0) then
+ Gear^.dY:= _0;
+ Gear^.State:= Gear^.State and not gstCollision
+ end;
Gear^.State:= Gear^.State or gstMoving;
if (CurrentHedgehog^.Gear = Gear) and (CurrentHedgehog^.Gear^.State and gstHHDriven <> 0) and
(not CurrentTeam^.ExtDriven) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then
@@ -870,19 +903,36 @@
else
begin
land:= TestCollisionYwithGear(Gear, 1);
- if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0)
+ if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0)
+ and ((land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0))
and ((Gear^.State and gstHHJumping) <> 0) then
SetLittle(Gear^.dX);
if not Gear^.dY.isNegative then
begin
+ if land and lfBouncy <> 0 then
+ begin
+ doStepFallingGear(Gear);
+ // hogs for some reason have very low friction. slippery little buggers
+ Gear^.dX:= Gear^.dX * _0_8
+ end;
+
CheckHHDamage(Gear);
- if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery)
- and (Gear^.dX.QWordValue < _0_02.QWordValue) then
- Gear^.dX.isNegative:= not Gear^.dX.isNegative; // landing after high jump
- Gear^.State:= Gear^.State and (not (gstHHJumping or gstHHHJump));
- Gear^.dY:= _0;
+ if (land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0) then
+ begin
+ if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery)
+ and (Gear^.dX.QWordValue < _0_02.QWordValue) then
+ begin
+ if land and lfBouncy <> 0 then
+ Gear^.dY:= _0;
+ Gear^.dX.isNegative:= not Gear^.dX.isNegative // landing after high jump
+ end;
+ Gear^.State:= Gear^.State and (not (gstHHJumping or gstHHHJump));
+ if (land and lfBouncy = 0) or (Gear^.dX.QWordValue < _0_02.QWordValue) then
+ Gear^.dY:= _0
+ end;
+ Gear^.State:= Gear^.State and not gstCollision
end
else
Gear^.dY:= Gear^.dY + cGravity;
@@ -908,43 +958,43 @@
end;
if (Gear^.State and gstMoving) <> 0 then
- if TestCollisionXKick(Gear, hwSign(Gear^.dX)) then
+ if TestCollisionXKick(Gear, hwSign(Gear^.dX)) <> 0 then
if not isFalling then
if hwAbs(Gear^.dX) > _0_01 then
- if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -1, hwSign(Gear^.dX)) or
- (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+ if (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -1, hwSign(Gear^.dX)) = 0) and
+ (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
begin
Gear^.X:= Gear^.X + Gear^.dX;
Gear^.dX:= Gear^.dX * _0_96;
Gear^.Y:= Gear^.Y - _1
end
else
- if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -2, hwSign(Gear^.dX)) or
- (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+ if (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -2, hwSign(Gear^.dX)) = 0) and
+ (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
begin
Gear^.X:= Gear^.X + Gear^.dX;
Gear^.dX:= Gear^.dX * _0_93;
Gear^.Y:= Gear^.Y - _2
end
else
- if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -3, hwSign(Gear^.dX)) or
- (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+ if (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -3, hwSign(Gear^.dX)) = 0) and
+ (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
begin
Gear^.X:= Gear^.X + Gear^.dX;
Gear^.dX:= Gear^.dX * _0_9 ;
Gear^.Y:= Gear^.Y - _3
end
else
- if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -4, hwSign(Gear^.dX)) or
- (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+ if (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -4, hwSign(Gear^.dX)) = 0) and
+ (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
begin
Gear^.X:= Gear^.X + Gear^.dX;
Gear^.dX:= Gear^.dX * _0_87;
Gear^.Y:= Gear^.Y - _4
end
else
- if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -5, hwSign(Gear^.dX)) or
- (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+ if (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -5, hwSign(Gear^.dX)) = 0) and
+ (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
begin
Gear^.X:= Gear^.X + Gear^.dX;
Gear^.dX:= Gear^.dX * _0_84;
@@ -978,7 +1028,7 @@
begin
Gear^.State:= Gear^.State and (not gstWinner);
Gear^.State:= Gear^.State and (not gstMoving);
- while (TestCollisionYWithGear(Gear,1) = 0) and (not CheckGearDrowning(Gear)) and (Gear <> nil) do
+ while (not CheckGearDrowning(Gear)) and (Gear <> nil) and (TestCollisionYWithGear(Gear,1) = 0) do
Gear^.Y:= Gear^.Y + _1;
// could become nil in CheckGearDrowning if ai's hog fails to respawn in ai survival
@@ -995,15 +1045,21 @@
// ARTILLERY but not being moved by explosions
Gear^.X:= Gear^.X + Gear^.dX;
Gear^.Y:= Gear^.Y + Gear^.dY;
- if (not Gear^.dY.isNegative) and (not TestCollisionYKick(Gear, 1))
- and TestCollisionYwithXYShift(Gear, 0, 1, 1) then
+ if (not Gear^.dY.isNegative) and (TestCollisionYKick(Gear, 1) = 0) then
begin
- CheckHHDamage(Gear);
- Gear^.dY:= _0;
- Gear^.Y:= Gear^.Y + _1
+ land:= TestCollisionYwithXYShift(Gear, 0, 1, 1);
+ if land and lfBouncy <> 0 then
+ doStepFallingGear(Gear);
+
+ if (land <> 0) and ((land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0)) then
+ begin
+ CheckHHDamage(Gear);
+ Gear^.dY:= _0;
+ Gear^.Y:= Gear^.Y + _1
+ end;
+ Gear^.State:= Gear^.State and not gstCollision
end;
- CheckGearDrowning(Gear);
// could become nil if ai's hog fails to respawn in ai survival
if Gear = nil then exit;
// hide target cursor if current hog is drowning
@@ -1060,6 +1116,12 @@
exit
end;
+if isAFK and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0) then
+ begin
+ AFKSkip;
+ exit
+ end;
+
if (HHGear^.State and gstAnimation) <> 0 then
begin
HHGear^.Message:= 0;
@@ -1143,7 +1205,7 @@
HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump));
- if (not cArtillery) and wasJumping and TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+ if (not cArtillery) and wasJumping and (TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) <> 0) then
SetLittle(HHGear^.dX);
if Hedgehog^.Gear <> nil then
@@ -1252,7 +1314,7 @@
if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0)
and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0)
and ((Gear^.Hedgehog = nil) or ((Gear^.Hedgehog^.Effects[heFrozen] = 0) or (Gear^.Hedgehog^.Effects[heFrozen] > 255)))
- and (not Gear^.dY.isNegative) and (TurnTimeLeft > 0) and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
+ and (not Gear^.dY.isNegative) and TurnClockActive and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
begin
slope:= CalcSlopeBelowGear(Gear);
if slope.QWordValue > 730144440 then // ignore mild slopes
@@ -1279,10 +1341,22 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepHedgehog(Gear: PGear);
+var tX: hwFloat;
begin
-if WorldWrap(Gear) and (WorldEdge <> weBounce) and
- (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) then
- CurAmmoGear^.PortalCounter:= 1;
+CheckGearDrowning(Gear);
+if Gear = nil then exit;
+tX:= Gear^.X;
+if WorldWrap(Gear) then
+ begin
+ if (WorldEdge <> weBounce) and (Gear = CurrentHedgehog^.Gear) and
+ (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) and (CurAmmoGear^.Elasticity <> _0) then
+ CurAmmoGear^.PortalCounter:= 1;
+ if (WorldEdge = weWrap) and ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0)) then
+ begin
+ Gear^.X:= tX;
+ Gear^.dX.isNegative:= (hwRound(tX) > LongInt(leftX) + Gear^.Radius * 2)
+ end
+ end;
CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel;
if (Gear^.Message and gmDestroy) <> 0 then
@@ -1290,7 +1364,7 @@
DeleteGear(Gear);
exit
end;
-if GameTicks mod 100 = 0 then CheckIce(Gear);
+if GameTicks mod 128 = 0 then CheckIce(Gear);
(*
if Gear^.Hedgehog^.Effects[heFrozen] > 0 then
begin