# HG changeset patch # User sheepluva # Date 1273110067 0 # Node ID 46a2694867bc64c73554a18d3b6883cee8f0468f # Parent b49ed5673727d6efa02c052a2eccac07b78da650 portal: * add/change/move some code * fix graphics (there was a 1 px offset at one frame) * you can use tab key to switch (next) portal color now (for testing purposes, might be removed again) diff -r b49ed5673727 -r 46a2694867bc hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Wed May 05 22:03:10 2010 +0000 +++ b/hedgewars/GSHandlers.inc Thu May 06 01:41:07 2010 +0000 @@ -3044,16 +3044,52 @@ end; //////////////////////////////////////////////////////////////////////////////// +procedure doPortalColorSwitch(); +var flags: LongWord; +begin + if (CurrentHedgehog <> nil) + and (CurrentHedgehog^.Gear <> nil) + and ((CurrentHedgehog^.Gear^.Message and gm_Switch) <> 0) then + With CurrentHedgehog^ do + if (Ammo^[CurSlot, CurAmmo].AmmoType = amPortalGun) then + begin + CurrentHedgehog^.Gear^.Message:= CurrentHedgehog^.Gear^.Message and not gm_Switch; + + flags:= Ammo^[CurSlot, CurAmmo].Timer and not 2; + if (flags and 1) = 0 then + Ammo^[CurSlot, CurAmmo].Timer:= flags or 1 + else + Ammo^[CurSlot, CurAmmo].Timer:= flags and not 1; + end; +end; + procedure doStepPortal(Gear: PGear); var iterator, conPortal: PGear; - s, acptRadius: hwFloat; + s, acptRadius, cdxy: hwFloat; noTrap, hasdxy: Boolean; begin + doPortalColorSwitch(); + // destroy portal if ground it was attached too is gone - if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then deleteGear(Gear); + if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0) + or (Gear^.Timer < 1) + or (hwRound(Gear^.Y) > cWaterLine) then + begin + deleteGear(Gear); + EXIT; + end; + + if (TurnTimeLeft < 1) + or (Gear^.Health < 1) then + dec(Gear^.Timer); + + if Gear^.Timer < 10000 then + gear^.RenderTimer:= true; // abort if there is no other portal connected to this one - if Gear^.IntersectGear = nil then + if (Gear^.IntersectGear = nil) then + exit; + if ((Gear^.IntersectGear^.Tag and 1) = 0) then // or if it's still moving; exit; conPortal:= Gear^.IntersectGear; @@ -3073,15 +3109,14 @@ // don't port portals or other gear that wouldn't make sense if (iterator^.Kind = gtPortal) + or (iterator^.Kind = gtRope) or (iterator^.Kind = gtHealthTag) then continue; - -{ - if (((iterator^.State and gstMoving) = 0) // we don't port non-moving stuff IF the portal entry... - and (iterator^.Active = false) - and ) then //... + + // don't port hogs on rope + if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) + and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtRope) then continue; -} if (iterator^.Radius > Gear^.Radius) then continue; // sorry, you're too fat! @@ -3105,45 +3140,79 @@ continue; noTrap:= ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) // can't be entered from above - or ((conPortal^.dY.isNegative or (conPortal^.dY.QWordValue = 0)))); // can't be left downwards; - + or ((conPortal^.dY.isNegative and not (conPortal^.dY.QWordValue = 0)))); // can't be left downwards; - // lets see if this one is just stuck in a stuck-loop - if noTrap and (iterator^.dY.QWordValue < _0_1.QWordValue) then + // prevent getting stuck in a ground portal loop + if noTrap and (iterator^.dY.QWordValue < _0_08.QWordValue) then continue; - + iterator^.Active:= true; iterator^.State:= iterator^.State or gstMoving; DeleteCI(iterator); - s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(conPortal^.dX, conPortal^.dY); +// TODO: more accurate porting + cdxy:= Distance(conPortal^.dX, conPortal^.dY); + s:= (Int2hwFloat(Gear^.Radius)) / cdxy; + iterator^.X:= conPortal^.X + s * conPortal^.dX; iterator^.Y:= conPortal^.Y + s * conPortal^.dY; - s:= Distance(iterator^.dX, iterator^.dY) / Distance(conPortal^.dX, conPortal^.dY); + + s:= Distance(iterator^.dX, iterator^.dY) / cdxy; + iterator^.dX:= s * conPortal^.dX; iterator^.dY:= s * conPortal^.dY; + + FollowGear:= iterator; + + s:= _0_2 + _0_008 * Gear^.Health; + iterator^.dX:= s * iterator^.dX; + iterator^.dY:= s * iterator^.dY; - if iterator^.dY.isNegative and (iterator^.dY.QWordValue <> 0) then - iterator^.dY:= iterator^.dY + hwAbs(Int2hwFloat(iterator^.Radius) / iterator^.dY) * cGravity; + if Gear^.Health > 1 then + begin + dec(Gear^.Health); + dec(iterator^.Health); + end; // breaks (some) loops if Distance(iterator^.dX, iterator^.dY) > _0_96 then begin iterator^.dX:= iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX); iterator^.dY:= iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY); - s:= _0_995 / Distance(iterator^.dX, iterator^.dY); + s:= _0_96 / Distance(iterator^.dX, iterator^.dY); iterator^.dX:= s * iterator^.dX; iterator^.dY:= s * iterator^.dX; end; - - iterator:= iterator^.NextGear; end; end; procedure doStepMovingPortal(Gear: PGear); var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt; s, dx, dy: hwFloat; + +procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); +var flags: LongWord; begin +if CurrentHedgehog <> nil then + With CurrentHedgehog^ do + if (Ammo^[CurSlot, CurAmmo].AmmoType = amPortalGun) then + begin + flags:= Ammo^[CurSlot, CurAmmo].Timer; + + if destroyGear xor ((oldPortal^.Tag and 2) = 0) then + flags:= flags or 1 + else + flags:= flags and not 1; + + Ammo^[CurSlot, CurAmmo].Timer:= flags and not 2; // make the ball visible + end; + +if destroyGear then deleteGear(oldPortal); +end; + +begin +doPortalColorSwitch(); + Gear^.X:= Gear^.X + Gear^.dX; Gear^.Y:= Gear^.Y + Gear^.dY; x:= hwRound(Gear^.X); @@ -3152,30 +3221,24 @@ if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then begin - if not calcSlopeTangent(Gear, x, y, tx, ty, 255) then - begin - deleteGear(Gear); - EXIT; - end; - - // reject shots at too irregular terrain - if DistanceI(tx,ty) < _12 then - begin - deleteGear(Gear); - EXIT; - end; + if not calcSlopeTangent(Gear, x, y, tx, ty, 255) + or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain + begin + loadNewPortalBall(Gear, true); + EXIT; + end; - // making a normal, normalized vector + // making a normalized normal vector s:= _1/DistanceI(tx,ty); dx:= -s * ty; dy:= s * tx; // make sure the vector is pointing outwards if not (Gear^.dX*dx + Gear^.dY*dy).isNegative then - begin + begin dx:= -dx; dy:= -dy; - end; + end; Gear^.dX:= dx; Gear^.dY:= dy; @@ -3183,33 +3246,60 @@ Gear^.DirAngle:= DxDy2Angle(-dy,dx); if not Gear^.dX.isNegative then Gear^.DirAngle:= 180-Gear^.DirAngle; - if ((Gear^.IntersectGear <> nil) and (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) < Gear^.Radius*2)) + if ((Gear^.IntersectGear = nil) + or (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) >= Gear^.Radius*2)) then begin - if CurrentHedgehog <> nil then - if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 - else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 - else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; - deleteGear(Gear) + loadNewPortalBall(Gear, false); + inc(Gear^.Tag); + Gear^.doStep:= @doStepPortal; end else - begin - if CurrentHedgehog <> nil then - if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 - else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2; - inc(Gear^.Tag); - Gear^.doStep:= @doStepPortal; - if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= Gear; - end + loadNewPortalBall(Gear, true); end -else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then +else if (y > cWaterLine) or (y < -LAND_WIDTH) + or (x > 2*LAND_WIDTH) or (x < -LAND_WIDTH) then + loadNewPortalBall(Gear, true); +end; + +procedure doStepPortalShot(newPortal: PGear); +var iterator: PGear; +begin +newPortal^.IntersectGear:= nil; + +if CurrentHedgehog <> nil then + With CurrentHedgehog^ do begin - if CurrentHedgehog <> nil then - if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 - else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 - else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; - deleteGear(Gear); + // make portal gun look unloaded + Ammo^[CurSlot, CurAmmo].Timer:= Ammo^[CurSlot, CurAmmo].Timer or 2; + + // set portal to the currently chosen color + if ((Ammo^[CurSlot, CurAmmo].Timer and 1) <> 0) then + newPortal^.Tag:= newPortal^.Tag or 2; + + iterator:= GearsList; + while iterator <> nil do + begin + if (iterator^.Kind = gtPortal) then + if (iterator <> newPortal) then + begin + if (iterator^.Tag and 2) = (newPortal^.Tag and 2) then + begin + iterator:= iterator^.PrevGear; + deleteGear(iterator^.NextGear); + continue; + end + else + begin // link portals with each other + newPortal^.IntersectGear:= iterator; + iterator^.IntersectGear:= newPortal; + iterator^.Health:= newPortal^.Health; + end; + end; + iterator:= iterator^.NextGear + end; end; +newPortal^.doStep:= @doStepMovingPortal; end; procedure doStepPiano(Gear: PGear); diff -r b49ed5673727 -r 46a2694867bc hedgewars/GearDrawing.inc --- a/hedgewars/GearDrawing.inc Wed May 05 22:03:10 2010 +0000 +++ b/hedgewars/GearDrawing.inc Thu May 06 01:41:07 2010 +0000 @@ -347,10 +347,10 @@ amShotgun: DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle); amDEagle: DrawRotated(sprHandDEagle, hx, hy, hwSign(Gear^.dX), aangle); amSineGun: DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle); - amPortalGun: if HH^.MultiShootAttacks = 0 then // Add a new Hedgehog value instead of abusing timer? + amPortalGun: if (HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].Timer and 2) <> 0 then // Add a new Hedgehog value instead of abusing timer? DrawRotatedF(sprPortalGun, hx, hy, 0, hwSign(Gear^.dX), aangle) else - DrawRotatedF(sprPortalGun, hx, hy, HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].Timer, hwSign(Gear^.dX), aangle); + DrawRotatedF(sprPortalGun, hx, hy, 1+(HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].Timer and 1), hwSign(Gear^.dX), aangle); amSniperRifle: DrawRotatedF(sprSniperRifle, hx, hy, 0, hwSign(Gear^.dX), aangle); amBlowTorch: DrawRotated(sprHandBlowTorch, hx, hy, hwSign(Gear^.dX), aangle); amCake: DrawRotated(sprHandCake, hx, hy, hwSign(Gear^.dX), aangle); @@ -601,13 +601,12 @@ DrawRotatedf(sprFinger, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, GameTicks div 32 mod 16, 0, DxDy2Angle(Gear^.X - TrainingTargetGear^.X, TrainingTargetGear^.Y - Gear^.Y)); end; gtBall: DrawRotatedf(sprBalls, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tag,0, Gear^.DirAngle); -// Still need portal types and states - gtPortal: begin - if (Gear^.IntersectGear = nil) or (Gear^.IntersectGear^.IntersectGear <> Gear) then // = is portal unlinked? - DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle) - else - DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle) - end; + + gtPortal: if ((Gear^.Tag and 1) = 0) // still moving? + or (Gear^.IntersectGear = nil) or (Gear^.IntersectGear^.IntersectGear <> Gear) // not linked&backlinked? + or ((Gear^.IntersectGear^.Tag and 1) = 0) then // linked portal still moving? + DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle) + else DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle); gtDrill: DrawRotated(sprDrill, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, DxDy2Angle(Gear^.dY, Gear^.dX)); diff -r b49ed5673727 -r 46a2694867bc hedgewars/HHHandlers.inc --- a/hedgewars/HHHandlers.inc Wed May 05 22:03:10 2010 +0000 +++ b/hedgewars/HHHandlers.inc Thu May 06 01:41:07 2010 +0000 @@ -102,7 +102,6 @@ procedure Attack(Gear: PGear); var xx, yy: hwFloat; tmpGear: PVisualGear; - newGear, iterator, portal: PGear; begin bShowFinger:= false; with Gear^, @@ -158,46 +157,7 @@ amMine: AddGear(hwRound(X) + hwSign(dX) * 7, hwRound(Y), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000); amDEagle: CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0); amSineGun: CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtSineGunShot, 0, xx * _0_5, yy * _0_5, 0); - amPortalGun: begin - iterator:= GearsList; - portal:= nil; - while iterator <> nil do - begin - if (iterator^.Kind = gtPortal) then - begin - newGear:= iterator; - iterator:= iterator^.NextGear; - if (portal <> nil) then - begin - if (portal^.uid < newGear^.uid) then - begin - deleteGear(portal); - portal:= newGear - end - else - begin - if newGear^.NextGear = nil then iterator:= nil; - deleteGear(newGear); - end - end - else portal:= newGear - end - else iterator:= iterator^.NextGear - end; - - newGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 0); - if portal <> nil then - begin - newGear^.IntersectGear:= portal; - if portal^.Tag < 2 then newGear^.Tag:= 2 - end - else newGear^.IntersectGear:= nil; - newGear^.Angle:= Angle; - newGear^.DirAngle:= Angle * 180 / cMaxAngle - 90; - if Gear^.DirAngle < 0 then Gear^.DirAngle:= Gear^.DirAngle + 360 - else if 360 < Gear^.DirAngle then Gear^.DirAngle:= Gear^.DirAngle - 360; - Ammo^[CurSlot, CurAmmo].Timer:= 0 - end; + amPortalGun: AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 0); amSniperRifle: begin PlaySound(sndSniperReload); CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0); diff -r b49ed5673727 -r 46a2694867bc hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Wed May 05 22:03:10 2010 +0000 +++ b/hedgewars/uConsts.pas Thu May 06 01:41:07 2010 +0000 @@ -88,9 +88,9 @@ gtParachute, gtAirAttack, gtAirBomb, gtBlowTorch, gtGirder, // 27 gtTeleport, gtSwitcher, gtTarget, gtMortar, // 31 gtWhip, gtKamikaze, gtCake, gtSeduction, gtWatermelon, gtMelonPiece, // 37 - gtHellishBomb, gtEvilTrace, gtWaterUp, gtDrill, gtBallGun, gtBall,gtRCPlane, - gtSniperRifleShot, gtJetpack, gtMolotov, gtExplosives, gtBirdy, - gtBigExplosion, gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot); + gtHellishBomb, gtEvilTrace, gtWaterUp, gtDrill, gtBallGun, gtBall, gtRCPlane, // 44 + gtSniperRifleShot, gtJetpack, gtMolotov, gtExplosives, gtBirdy, // 49 + gtBigExplosion, gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot); // 55 // Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.) TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire, @@ -1918,7 +1918,7 @@ TimeAfterTurn: 0; minAngle: 0; maxAngle: 0; - isDamaging: true; + isDamaging: false; SkipTurns: 0; PosCount: 1; PosSprite: sprWater), diff -r b49ed5673727 -r 46a2694867bc hedgewars/uFloat.pas --- a/hedgewars/uFloat.pas Wed May 05 22:03:10 2010 +0000 +++ b/hedgewars/uFloat.pas Thu May 06 01:41:07 2010 +0000 @@ -80,6 +80,7 @@ _0_003: hwFloat = (isNegative: false; QWordValue: 12884902); _0_004: hwFloat = (isNegative: false; QWordValue: 17179869); _0_005: hwFloat = (isNegative: false; QWordValue: 21474836); + _0_008: hwFloat = (isNegative: false; QWordValue: 34359738); _0_01: hwFloat = (isNegative: false; QWordValue: 42949673); _0_02: hwFloat = (isNegative: false; QWordValue: 85899345); _0_03: hwFloat = (isNegative: false; QWordValue: 128849018); diff -r b49ed5673727 -r 46a2694867bc hedgewars/uGears.pas --- a/hedgewars/uGears.pas Wed May 05 22:03:10 2010 +0000 +++ b/hedgewars/uGears.pas Thu May 06 01:41:07 2010 +0000 @@ -183,7 +183,7 @@ @doStepBirdy, @doStepBigExplosion, @doStepEggWork, - @doStepMovingPortal, + @doStepPortalShot, @doStepPiano, @doStepBomb, @doStepSineGunShot @@ -479,6 +479,9 @@ gear^.AdvBounce:= 0; gear^.Radius:= 16; gear^.Tag:= 0; + gear^.Timer:= 15000; + gear^.RenderTimer:= false; + gear^.Health:= 100; end; gtPiano: begin gear^.Radius:= 32 @@ -511,8 +514,9 @@ end; // make sure that portals have their link removed before deletion -if (Gear^.Kind = gtPortal) and (Gear^.IntersectGear <> nil) then - Gear^.IntersectGear^.IntersectGear:= nil +if (Gear^.Kind = gtPortal) then + if (Gear^.IntersectGear <> nil) then + Gear^.IntersectGear^.IntersectGear:= nil else if Gear^.Kind = gtHedgehog then if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then @@ -678,6 +682,7 @@ if Gear^.Tex <> nil then FreeTexture(Gear^.Tex); Gear^.Tex:= RenderStringTex(inttostr(Gear^.Timer div 1000), cWhiteColor, fntSmall); end; +AddFileLog('doing step for gear '+intToStr(Gear^.uid)+' (type '+EnumToStr(Gear^.Kind)+')'); Gear^.doStep(Gear); end end; diff -r b49ed5673727 -r 46a2694867bc share/hedgewars/Data/Graphics/Hedgehog/amPortalGun.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amPortalGun.png has changed