diff -r 8054d9d775fd -r 2759212a27de hedgewars/uGearsHedgehog.pas --- 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