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)
--- 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);
--- 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));
--- 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);
--- 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),
--- 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);
--- 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;
Binary file share/hedgewars/Data/Graphics/Hedgehog/amPortalGun.png has changed