diff -r 404ddce27b23 -r c13ebed437cb hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Wed Feb 20 02:21:58 2013 +0100 +++ b/hedgewars/uGearsHedgehog.pas Tue Apr 02 21:00:57 2013 +0200 @@ -29,6 +29,7 @@ procedure HedgehogChAngle(HHGear: PGear); procedure PickUp(HH, Gear: PGear); procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord); +procedure CheckIce(Gear: PGear); inline; implementation uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, @@ -53,7 +54,6 @@ prevAmmo:= CurAmmoType; ammoidx:= 0; if ((HHGear^.State and (gstAttacking or gstAttacked)) <> 0) - or ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0)) or ((HHGear^.State and gstHHDriven) = 0) then exit; ChangeAmmo:= true; @@ -61,8 +61,17 @@ while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx); - if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (MultiShootAttacks > 0) then - OnUsedAmmo(HHGear^.Hedgehog^); + if (MultiShootAttacks > 0) then + begin + if (CurAmmoType = amSniperRifle) and ((GameFlags and gfArtillery) = 0) then + cArtillery := false; + if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0 then + begin + MultiShootAttacks:= Ammoz[CurAmmoType].Ammo.NumPerTurn; + AfterAttack + end + else OnUsedAmmo(HHGear^.Hedgehog^) + end; MultiShootAttacks:= 0; HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump)); @@ -211,9 +220,7 @@ and ((TargetPoint.X <> NoPointX) or ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) = 0)) then begin State:= State or gstAttacking; - if Power = cMaxPower then - Message:= Message and (not gmAttack) - else if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) = 0 then + if (Power = cMaxPower) or ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) = 0) then Message:= Message and (not gmAttack) else begin @@ -224,44 +231,44 @@ end; inc(Power) end; - if ((Message and gmAttack) <> 0) then - exit; + if ((Message and gmAttack) <> 0) then + exit; - if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0 then - begin - StopSound(sndThrowPowerUp); - PlaySound(sndThrowRelease); - end; + if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0 then + begin + StopSound(sndThrowPowerUp); + PlaySound(sndThrowRelease); + end; - xx:= SignAs(AngleSin(Angle), dX); - yy:= -AngleCos(Angle); + xx:= SignAs(AngleSin(Angle), dX); + yy:= -AngleCos(Angle); - lx:= X + int2hwfloat(round(GetLaunchX(CurAmmoType, hwSign(dX), Angle))); - ly:= Y + int2hwfloat(round(GetLaunchY(CurAmmoType, Angle))); + lx:= X + int2hwfloat(round(GetLaunchX(CurAmmoType, hwSign(dX), Angle))); + ly:= Y + int2hwfloat(round(GetLaunchY(CurAmmoType, Angle))); - if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then - xx:= - xx; - if Ammoz[CurAmmoType].Ammo.AttackVoice <> sndNone then - AddVoice(Ammoz[CurAmmoType].Ammo.AttackVoice, CurrentTeam^.voicepack); + if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then + xx:= - xx; + if Ammoz[CurAmmoType].Ammo.AttackVoice <> sndNone then + AddVoice(Ammoz[CurAmmoType].Ammo.AttackVoice, CurrentTeam^.voicepack); // Initiating alt attack - if (CurAmmoGear <> nil) - and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) - and ((Gear^.Message and gmLJump) <> 0) - and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then - begin - newDx:= dX; - newDy:= dY; - altUse:= true - end - else - begin - newDx:= xx*Power/cPowerDivisor; - newDy:= yy*Power/cPowerDivisor; - altUse:= false - end; + if (CurAmmoGear <> nil) + and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) + and ((Gear^.Message and gmLJump) <> 0) + and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then + begin + newDx:= dX; + newDy:= dY; + altUse:= true + end + else + begin + newDx:= xx*Power/cPowerDivisor; + newDy:= yy*Power/cPowerDivisor; + altUse:= false + end; - case CurAmmoType of + case CurAmmoType of amGrenade: newGear:= AddGear(hwRound(lx), hwRound(ly), gtGrenade, 0, newDx, newDy, CurWeapon^.Timer); amMolotov: newGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov, 0, newDx, newDy, 0); amClusterBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb, 0, newDx, newDy, CurWeapon^.Timer); @@ -281,7 +288,7 @@ amKnife: begin newGear:= AddGear(hwRound(lx), hwRound(ly), gtKnife, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0); newGear^.State:= newGear^.State or gstMoving; - newGear^.Radius:= 6 // temporarily shrink so it doesn't instantly embed in the ground + newGear^.Radius:= 4 // temporarily shrink so it doesn't instantly embed in the ground end; amDEagle: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0); amSineGun: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSineGunShot, 0, xx * _0_5, yy * _0_5, 0); @@ -377,56 +384,56 @@ //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); amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0); - end; - if altUse and (newGear <> nil) then - begin - newGear^.dX:= newDx / newGear^.Density; - newGear^.dY:= newDY / newGear^.Density - end; + end; + if altUse and (newGear <> nil) then + begin + newGear^.dX:= newDx / newGear^.Density; + newGear^.dY:= newDY / newGear^.Density + end; - case CurAmmoType of - amGrenade, amMolotov, - amClusterBomb, amGasBomb, - amBazooka, amSnowball, - amBee, amSMine, - amMortar, amWatermelon, - amHellishBomb, amDrill: FollowGear:= newGear; + case CurAmmoType of + amGrenade, amMolotov, + amClusterBomb, amGasBomb, + amBazooka, amSnowball, + amBee, amSMine, + amMortar, amWatermelon, + amHellishBomb, amDrill: FollowGear:= newGear; - amShotgun, amPickHammer, - amRope, amDEagle, - amSineGun, amSniperRifle, - amFirePunch, amWhip, - amHammer, amBaseballBat, - amParachute, amBlowTorch, - amGirder, amTeleport, - amSwitch, amRCPlane, - amKamikaze, amCake, - amSeduction, amBallgun, - amJetpack, amBirdy, - amFlamethrower, amLandGun, - amResurrector, //amStructure, - amTardis, amPiano, - amIceGun: CurAmmoGear:= newGear; - end; + amShotgun, amPickHammer, + amRope, amDEagle, + amSineGun, amSniperRifle, + amFirePunch, amWhip, + amHammer, amBaseballBat, + amParachute, amBlowTorch, + amGirder, amTeleport, + amSwitch, amRCPlane, + amKamikaze, amCake, + amSeduction, amBallgun, + amJetpack, amBirdy, + amFlamethrower, amLandGun, + amResurrector, //amStructure, + amTardis, amPiano, + amIceGun: CurAmmoGear:= newGear; + end; if ((CurAmmoType = amMine) or (CurAmmoType = amSMine)) and (GameFlags and gfInfAttack <> 0) then newGear^.FlightTime:= GameTicks + 1000 else if CurAmmoType = amDrill then newGear^.FlightTime:= GameTicks + 250; - if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then - begin - newGear^.Target.X:= TargetPoint.X; - newGear^.Target.Y:= TargetPoint.Y - end; - if (newGear <> nil) and (newGear^.CollisionMask and $80 <> 0) then newGear^.CollisionMask:= newGear^.CollisionMask and (not $80); + if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then + begin + newGear^.Target.X:= TargetPoint.X; + newGear^.Target.Y:= TargetPoint.Y + end; + if (newGear <> nil) and (newGear^.CollisionMask and lfCurrentHog <> 0) then newGear^.CollisionMask:= newGear^.CollisionMask and (not lfCurrentHog); - // Clear FollowGear if using on a rope/parachute/saucer etc so focus stays with the hog's movement - if altUse then - FollowGear:= nil; + // Clear FollowGear if using on a rope/parachute/saucer etc so focus stays with the hog's movement + if altUse then + FollowGear:= nil; - if (newGear <> nil) and ((Ammoz[newGear^.AmmoType].Ammo.Propz and ammoprop_SetBounce) <> 0) then - begin - elastic:= int2hwfloat(CurWeapon^.Bounciness) / _1000; + if (newGear <> nil) and ((Ammoz[newGear^.AmmoType].Ammo.Propz and ammoprop_SetBounce) <> 0) then + begin + elastic:= int2hwfloat(CurWeapon^.Bounciness) / _1000; if elastic < _1 then newGear^.Elasticity:= newGear^.Elasticity * elastic @@ -439,37 +446,36 @@ end; - uStats.AmmoUsed(CurAmmoType); + uStats.AmmoUsed(CurAmmoType); - if not (SpeechText = '') then - begin - speech:= AddVisualGear(0, 0, vgtSpeechBubble); - if speech <> nil then + if not (SpeechText = '') then begin - speech^.Text:= SpeechText; - speech^.Hedgehog:= Gear^.Hedgehog; - speech^.FrameTicks:= SpeechType; + speech:= AddVisualGear(0, 0, vgtSpeechBubble); + if speech <> nil then + begin + speech^.Text:= SpeechText; + speech^.Hedgehog:= Gear^.Hedgehog; + speech^.FrameTicks:= SpeechType; + end; + SpeechText:= '' end; - SpeechText:= '' - end; - Power:= 0; - if (CurAmmoGear <> nil) - and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then - begin - Message:= Message or gmAttack; - CurAmmoGear^.Message:= Message + Power:= 0; + if (CurAmmoGear <> nil) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then + begin + if CurAmmoType in [amRope,amResurrector] then + Message:= Message or gmAttack; + CurAmmoGear^.Message:= Message + end + else + begin + if (not CurrentTeam^.ExtDriven) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then + SendIPC(_S'a'); + AfterAttack; + end end else - begin - if not CurrentTeam^.ExtDriven - and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then - SendIPC(_S'a'); - AfterAttack; - end - end - else - Message:= Message and (not gmAttack); + Message:= Message and (not gmAttack); end; TargetPoint.X := NoPointX; ScriptCall('onHogAttack'); @@ -777,7 +783,7 @@ if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) then MakeHedgehogsStep(Gear); - SetAllHHToActive; + SetAllHHToActive(false); AddGearCI(Gear) end end; @@ -786,7 +792,7 @@ var da: LongWord; begin with HHGear^.Hedgehog^ do - if ((CurAmmoType = amRope) and ((HHGear^.State and (gstMoving or gstHHJumping)) = gstMoving)) + if ((CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amRope) and ((HHGear^.State and (gstMoving or gstHHJumping)) = gstMoving)) or ((CurAmmoType = amPortalGun) and ((HHGear^.State and gstMoving) <> 0)) then da:= 2 else da:= 1; @@ -887,35 +893,40 @@ if TestCollisionXKick(Gear, hwSign(Gear^.dX)) 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)) 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 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)) then + 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 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)) then + 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 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)) then + 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 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)) then + 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 begin Gear^.X:= Gear^.X + Gear^.dX; Gear^.dX:= Gear^.dX * _0_84; @@ -1000,7 +1011,9 @@ Hedgehog: PHedgehog; begin Hedgehog:= HHGear^.Hedgehog; -if isInMultiShoot then +if not isInMultiShoot then + AllInactive:= false +else if Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle] then HHGear^.Message:= 0; if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then @@ -1010,6 +1023,8 @@ if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) then begin + if (Hedgehog^.CurAmmoType = amKnife) then + LoadHedgehogHat(Hedgehog^, Hedgehog^.Hat); if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft; TurnTimeLeft:= 0; @@ -1086,7 +1101,6 @@ exit end; -if not isInMultiShoot then HedgehogChAngle(HHGear); if (HHGear^.State and gstMoving) <> 0 then @@ -1122,7 +1136,7 @@ exit end; - if (not isInMultiShoot) and (Hedgehog^.Gear <> nil) then + if not(isInMultiShoot and (Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle])) and (Hedgehog^.Gear <> nil) then begin if GHStepTicks > 0 then dec(GHStepTicks); @@ -1194,7 +1208,7 @@ if Gear^.Timer = 0 then begin Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstHHChooseTarget)); - Gear^.Active:= false; + if Gear^.Hedgehog^.Effects[heFrozen] = 0 then Gear^.Active:= false; AddGearCI(Gear); exit end @@ -1204,40 +1218,25 @@ AllInactive:= false end; -//////////////////////////////////////////////////////////////////////////////// -procedure doStepHedgehog(Gear: PGear); +procedure CheckIce(Gear: PGear); inline; (* var x,y,tx,ty: LongInt; tdX, tdY, slope: hwFloat; land: Word; *) var slope: hwFloat; begin -CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel; -if (Gear^.Message and gmDestroy) <> 0 then - begin - DeleteGear(Gear); - exit - end; - -if (Gear^.State and gstHHDriven) = 0 then - doStepHedgehogFree(Gear) -else - begin - with Gear^.Hedgehog^ do - if Team^.hasGone then - TeamGoneEffect(Team^) - else - doStepHedgehogDriven(Gear) - end; -if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0) -and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0) -and (not Gear^.dY.isNegative) and (GameTicks mod (100*LongWOrd(hwRound(cMaxWindSpeed*2/cGravity))) = 0) -and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then - begin - slope:= CalcSlopeBelowGear(Gear); - Gear^.dX:=Gear^.dX+slope*_0_07; - if slope.QWordValue <> 0 then - Gear^.State:= Gear^.State or gstMoving; + 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 + begin + slope:= CalcSlopeBelowGear(Gear); + if slope.QWordValue > 730144440 then // ignore mild slopes + begin + Gear^.dX:=Gear^.dX+slope*cGravity*_256; + Gear^.State:= Gear^.State or gstMoving + end + end; (* x:= hwRound(Gear^.X); y:= hwRound(Gear^.Y); @@ -1252,7 +1251,39 @@ AddVisualGear(x + hwRound(_40 * slope), y - hwRound(_40 * slope), vgtSmokeTrace); AddVisualGear(x - hwRound(_50 * slope), y + hwRound(_50 * slope), vgtSmokeTrace); AddVisualGear(x + hwRound(_50 * slope), y - hwRound(_50 * slope), vgtSmokeTrace); *) - end +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepHedgehog(Gear: PGear); +begin +CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel; +if (Gear^.Message and gmDestroy) <> 0 then + begin + DeleteGear(Gear); + exit + end; +if GameTicks mod 100 = 0 then CheckIce(Gear); +(* +if Gear^.Hedgehog^.Effects[heFrozen] > 0 then + begin + if (Gear^.Hedgehog^.Effects[heFrozen] > 256) and (CurrentHedgehog^.Team^.Clan <> Gear^.Hedgehog^.Team^.Clan) then + dec(Gear^.Hedgehog^.Effects[heFrozen]) + else if GameTicks mod 10 = 0 then + dec(Gear^.Hedgehog^.Effects[heFrozen]) + end; +*) +if (GameTicks mod 10 = 0) and (Gear^.Hedgehog^.Effects[heFrozen] > 0) and (Gear^.Hedgehog^.Effects[heFrozen] < 256) then + dec(Gear^.Hedgehog^.Effects[heFrozen]); +if (Gear^.State and gstHHDriven) = 0 then + doStepHedgehogFree(Gear) +else + begin + with Gear^.Hedgehog^ do + if Team^.hasGone then + TeamGoneEffect(Team^) + else + doStepHedgehogDriven(Gear) + end; end; end.