still in developement take on adding structures, working hiding of hogs and ejecting them later.
authorHenek
Sat, 29 Jan 2011 18:18:44 +0100
changeset 4881 35e6269227b6
parent 4880 07e9849c6a70
child 4882 b4c84db92d8f
still in developement take on adding structures, working hiding of hogs and ejecting them later. also some refactoring in uGears to evade "ambigous" variable names and, a little tweak to teleportation code that should not affect game but will help in for instance lua
QTfrontend/hwconsts.cpp.in
hedgewars/GSHandlers.inc
hedgewars/HHHandlers.inc
hedgewars/uAIAmmoTests.pas
hedgewars/uGears.pas
hedgewars/uGearsRender.pas
hedgewars/uTeams.pas
hedgewars/uTypes.pas
hedgewars/uVariables.pas
share/hedgewars/Data/Locale/en.txt
--- a/QTfrontend/hwconsts.cpp.in	Sat Jan 29 17:40:45 2011 +0100
+++ b/QTfrontend/hwconsts.cpp.in	Sat Jan 29 18:18:44 2011 +0100
@@ -37,10 +37,10 @@
 int cMaxTeams = 6;
 
 QString * cDefaultAmmoStore = new QString(
-        "939192942219912103223511100120100000021111010101112"
-        "040504054160065554655446477657666666615551010111541"
-        "000000000000020550000004000700400000000020000000060"
-        "131111031211111112311411111111111111121111110111112"
+        "9391929422199121032235111001201000000211110101011129"
+        "0405040541600655546554464776576666666155510101115411"
+        "0000000000000205500000040007004000000000200000000600"
+        "1311110312111111123114111111111111111211111101111121"
         );
 int cAmmoNumber = cDefaultAmmoStore->size() / 4;
 
--- a/hedgewars/GSHandlers.inc	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/GSHandlers.inc	Sat Jan 29 18:18:44 2011 +0100
@@ -2410,6 +2410,7 @@
     Gear^.Hedgehog^.Unplaced := false;
     HHGear := Gear^.Hedgehog^.Gear;
     HHGear^.Y := HHGear^.Y + HHGear^.dY;
+    HHGear^.X := HHGear^.X + HHGear^.dX;
     // hedgehog falling to collect cases
     HHGear^.dY := HHGear^.dY + cGravity;
     if TestCollisionYwithGear(HHGear, 1)
@@ -4590,4 +4591,79 @@
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
-
+procedure doStepStructure(Gear: PGear);
+var 
+    i, x, y: LongInt;
+    dX, dY: HWFloat;
+    hog: PHedgehog;
+begin
+    if Gear^.Hedgehog <> nil then
+        if Gear^.Tag = 0 then
+        begin
+            hog:= Gear^.Hedgehog;
+            hog^.GearHidden:= hog^.Gear;
+            RemoveGearFromList(hog^.Gear);
+            hog^.Gear:= nil;
+            Gear^.Tag:= TotalRounds + 3;
+        end
+        else if Gear^.Tag = TotalRounds then
+        begin
+            hog:= Gear^.Hedgehog;
+            hog^.Gear:= hog^.GearHidden;
+            hog^.Gear^.X:= Gear^.X;
+            hog^.Gear^.Y:= Gear^.Y - Int2hwFloat(Gear^.Radius);
+            hog^.Gear^.Active:= false;
+            hog^.Gear^.State:= hog^.Gear^.State And not gstHHdriven;
+            InsertGearToList(hog^.Gear);
+            hog^.GearHidden:= nil;
+            Gear^.Hedgehog:= nil;
+        end;
+
+    if (Gear^.dY.QWordValue <> 0) or (not TestCollisionYwithGear(Gear, 1)) then
+    begin
+        AllInactive := false;
+        Gear^.dY := Gear^.dY + cGravity;
+        Gear^.Y := Gear^.Y + Gear^.dY;
+        if (not Gear^.dY.isNegative) and (Gear^.dY > _0_001) then SetAllHHToActive;
+        if (Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, -1) then Gear^.dY := _0;
+        if (not Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, 1) then
+        begin
+            if Gear^.dY > _0_2 then
+                for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
+                    AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
+            Gear^.dY := - Gear^.dY * Gear^.Elasticity;
+            if Gear^.dY > - _0_001 then Gear^.dY := _0
+            else if Gear^.dY < - _0_03 then
+                    PlaySound(Gear^.ImpactSound);
+        end;
+        CheckGearDrowning(Gear);
+    end;
+
+    if (Gear^.dY.QWordValue = 0) then AddGearCI(Gear)
+    else if (Gear^.dY.QWordValue <> 0) then DeleteCI(Gear);
+
+    dec(Gear^.Health, Gear^.Damage);
+    Gear^.Damage := 0;
+
+    if Gear^.Health <= 0 then
+    begin
+        if Gear^.Hedgehog <> nil then
+        begin
+            hog:= Gear^.Hedgehog;
+            hog^.Gear:= hog^.GearHidden;
+            hog^.Gear^.X:= Gear^.X;
+            hog^.Gear^.Y:= Gear^.Y;
+            InsertGearToList(hog^.Gear);
+            hog^.GearHidden:= nil;
+            Gear^.Hedgehog:= nil;
+        end;
+
+        x := hwRound(Gear^.X);
+        y := hwRound(Gear^.Y);
+
+        DeleteGear(Gear);
+
+        doMakeExplosion(x, y, 50, CurrentHedgehog, EXPLAutoSound);
+    end;
+end;
+
--- a/hedgewars/HHHandlers.inc	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/HHHandlers.inc	Sat Jan 29 18:18:44 2011 +0100
@@ -41,29 +41,29 @@
 end;
 
 // Shouldn't more of this ammo switching stuff be moved to uAmmos ?
-function ChangeAmmo(Gear: PGear): boolean;
+function ChangeAmmo(HHGear: PGear): boolean;
 var slot, i: Longword;
     ammoidx: LongInt;
 begin
 ChangeAmmo:= false;
-slot:= Gear^.MsgParam;
+slot:= HHGear^.MsgParam;
 
-with Gear^.Hedgehog^ do
+with HHGear^.Hedgehog^ do
     begin
-    Gear^.Message:= Gear^.Message and not gmSlot;
+    HHGear^.Message:= HHGear^.Message and not gmSlot;
     ammoidx:= 0;
-    if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
+    if ((HHGear^.State and (gstAttacking or gstAttacked)) <> 0) or
        (TargetPoint.X <> NoPointX) or
        ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0)) or
-       ((Gear^.State and gstHHDriven) = 0) then exit;
+       ((HHGear^.State and gstHHDriven) = 0) then exit;
     ChangeAmmo:= true;
 
     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(Gear^.Hedgehog^);
+    if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(HHGear^.Hedgehog^);
 
     MultiShootAttacks:= 0;
-    Gear^.Message:= Gear^.Message and not (gmLJump or gmHJump);
+    HHGear^.Message:= HHGear^.Message and not (gmLJump or gmHJump);
     
     if Ammoz[CurAmmoType].Slot = slot then
         begin
@@ -94,7 +94,7 @@
     end
 end;
 
-procedure HHSetWeapon(Gear: PGear);
+procedure HHSetWeapon(HHGear: PGear);
 var t: LongInt;
     weap: TAmmoType;
     Hedgehog: PHedgehog;
@@ -102,25 +102,25 @@
 begin
 s:= false;
 
-weap:= TAmmoType(Gear^.MsgParam);
-Hedgehog:= Gear^.Hedgehog;
+weap:= TAmmoType(HHGear^.MsgParam);
+Hedgehog:= HHGear^.Hedgehog;
 
 if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
 
-Gear^.MsgParam:= Ammoz[weap].Slot;
+HHGear^.MsgParam:= Ammoz[weap].Slot;
 
 t:= cMaxSlotAmmoIndex;
 
-Gear^.Message:= Gear^.Message and not gmWeapon;
+HHGear^.Message:= HHGear^.Message and not gmWeapon;
 
 with Hedgehog^ do
     while (CurAmmoType <> weap) and (t >= 0) do
         begin
-        s:= ChangeAmmo(Gear);
+        s:= ChangeAmmo(HHGear);
         dec(t)
         end;
 
-if s then ApplyAmmoChanges(Gear^.Hedgehog^)
+if s then ApplyAmmoChanges(HHGear^.Hedgehog^)
 end;
 
 procedure HHSetTimer(Gear: PGear);
@@ -315,6 +315,10 @@
                     end;
                    amDrillStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 3, _0, _0, CurWeapon^.Timer);
                    //amMelonStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 4, _0, _0, 0);
+                     amStructure: begin
+                                  FollowGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, 0, SignAs(_0_03, dX), _0, 0);
+                                  FollowGear^.Hedgehog:= Gear^.Hedgehog;
+                                  end;
                   end;
 
         uStats.AmmoUsed(CurAmmoType);
@@ -635,17 +639,17 @@
    end
 end;
 
-procedure HedgehogChAngle(Gear: PGear);
+procedure HedgehogChAngle(HHGear: PGear);
 var da: LongWord;
 begin
-with Gear^.Hedgehog^ do
+with HHGear^.Hedgehog^ do
     if (CurAmmoType = amRope)
-    and ((Gear^.State and (gstMoving or gstHHJumping)) = gstMoving) then da:= 2 else da:= 1;
+    and ((HHGear^.State and (gstMoving or gstHHJumping)) = gstMoving) then da:= 2 else da:= 1;
 
-if (((Gear^.Message and gmPrecise) = 0) or ((GameTicks mod 5) = 1)) then
-    if ((Gear^.Message and gmUp) <> 0) and (Gear^.Angle >= CurMinAngle + da) then dec(Gear^.Angle, da)
+if (((HHGear^.Message and gmPrecise) = 0) or ((GameTicks mod 5) = 1)) then
+    if ((HHGear^.Message and gmUp) <> 0) and (HHGear^.Angle >= CurMinAngle + da) then dec(HHGear^.Angle, da)
     else
-    if ((Gear^.Message and gmDown) <> 0) and (Gear^.Angle + da <= CurMaxAngle) then inc(Gear^.Angle, da)
+    if ((HHGear^.Message and gmDown) <> 0) and (HHGear^.Angle + da <= CurMaxAngle) then inc(HHGear^.Angle, da)
 end;
 
 procedure doStepHedgehog(Gear: PGear); forward;
@@ -776,118 +780,118 @@
 
 end;
 
-procedure doStepHedgehogDriven(Gear: PGear);
+procedure doStepHedgehogDriven(HHGear: PGear);
 var t: PGear;
     wasJumping: boolean;
     Hedgehog: PHedgehog;
 begin
-Hedgehog:= Gear^.Hedgehog;
+Hedgehog:= HHGear^.Hedgehog;
 if not isInMultiShoot then
    AllInactive:= false
 else
-   Gear^.Message:= 0;
+   HHGear^.Message:= 0;
 
-if (TurnTimeLeft = 0) or (Gear^.Damage > 0) then
+if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) then
     begin
     TurnTimeLeft:= 0;
     isCursorVisible:= false;
-    Gear^.State:= Gear^.State and not (gstHHDriven or gstAnimation or gstAttacking);
+    HHGear^.State:= HHGear^.State and not (gstHHDriven or gstAnimation or gstAttacking);
     AttackBar:= 0;
-    if Gear^.Damage > 0 then
-        Gear^.State:= Gear^.State and not (gstHHJumping or gstHHHJump);
+    if HHGear^.Damage > 0 then
+        HHGear^.State:= HHGear^.State and not (gstHHJumping or gstHHHJump);
     exit
     end;
 
-if (Gear^.State and gstAnimation) <> 0 then
+if (HHGear^.State and gstAnimation) <> 0 then
     begin
-    Gear^.Message:= 0;
-    if (Gear^.Pos = Wavez[TWave(Gear^.Tag)].VoiceDelay) and (Gear^.Timer = 0) then PlaySound(Wavez[TWave(Gear^.Tag)].Voice, Hedgehog^.Team^.voicepack);
-    inc(Gear^.Timer);
-    if Gear^.Timer = Wavez[TWave(Gear^.Tag)].Interval then
+    HHGear^.Message:= 0;
+    if (HHGear^.Pos = Wavez[TWave(HHGear^.Tag)].VoiceDelay) and (HHGear^.Timer = 0) then PlaySound(Wavez[TWave(HHGear^.Tag)].Voice, Hedgehog^.Team^.voicepack);
+    inc(HHGear^.Timer);
+    if HHGear^.Timer = Wavez[TWave(HHGear^.Tag)].Interval then
         begin
-        Gear^.Timer:= 0;
-        inc(Gear^.Pos);
-        if Gear^.Pos = Wavez[TWave(Gear^.Tag)].FramesCount then
-            Gear^.State:= Gear^.State and not gstAnimation
+        HHGear^.Timer:= 0;
+        inc(HHGear^.Pos);
+        if HHGear^.Pos = Wavez[TWave(HHGear^.Tag)].FramesCount then
+            HHGear^.State:= HHGear^.State and not gstAnimation
         end;
     exit
     end;
 
-if ((Gear^.State and gstMoving) <> 0)
+if ((HHGear^.State and gstMoving) <> 0)
     or (StepTicks = cHHStepTicks)
     or (CurAmmoGear <> nil) then // we are moving
     begin
     with Hedgehog^ do
         if (CurAmmoGear = nil)
-        and (Gear^.dY > _0_39)
-        and (CurAmmoType = amParachute) then Gear^.Message:= Gear^.Message or gmAttack;
+        and (HHGear^.dY > _0_39)
+        and (CurAmmoType = amParachute) then HHGear^.Message:= HHGear^.Message or gmAttack;
     // check for case with ammo
-    t:= CheckGearNear(Gear, gtCase, 36, 36);
+    t:= CheckGearNear(HHGear, gtCase, 36, 36);
     if t <> nil then
-        PickUp(Gear, t)
+        PickUp(HHGear, t)
     end;
 
 if (CurAmmoGear = nil) then
-    if (((Gear^.Message and gmAttack) <> 0)
-        or ((Gear^.State and gstAttacking) <> 0)) then
-        Attack(Gear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
+    if (((HHGear^.Message and gmAttack) <> 0)
+        or ((HHGear^.State and gstAttacking) <> 0)) then
+        Attack(HHGear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
     else
 else 
     with Hedgehog^ do
         if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
-            and ((Gear^.Message and gmLJump) <> 0)
+            and ((HHGear^.Message and gmLJump) <> 0)
             and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
             begin
-            Attack(Gear);
-            Gear^.Message:= Gear^.Message and not gmLJump
+            Attack(HHGear);
+            HHGear^.Message:= HHGear^.Message and not gmLJump
             end;
 
 if (CurAmmoGear = nil)
     or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) 
     or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) then
     begin
-    if ((Gear^.Message and gmSlot) <> 0) then
-        if ChangeAmmo(Gear) then ApplyAmmoChanges(Hedgehog^);
+    if ((HHGear^.Message and gmSlot) <> 0) then
+        if ChangeAmmo(HHGear) then ApplyAmmoChanges(Hedgehog^);
 
-    if ((Gear^.Message and gmWeapon) <> 0) then HHSetWeapon(Gear);
+    if ((HHGear^.Message and gmWeapon) <> 0) then HHSetWeapon(HHGear);
 
-    if ((Gear^.Message and gmTimer) <> 0) then HHSetTimer(Gear);
+    if ((HHGear^.Message and gmTimer) <> 0) then HHSetTimer(HHGear);
     end;
 
 if CurAmmoGear <> nil then
    begin
-   CurAmmoGear^.Message:= Gear^.Message;
+   CurAmmoGear^.Message:= HHGear^.Message;
    exit
    end;
 
 if not isInMultiShoot then
-   HedgehogChAngle(Gear);
+   HedgehogChAngle(HHGear);
 
-if (Gear^.State and gstMoving) <> 0 then
+if (HHGear^.State and gstMoving) <> 0 then
     begin
-    wasJumping:= ((Gear^.State and gstHHJumping) <> 0);
+    wasJumping:= ((HHGear^.State and gstHHJumping) <> 0);
 
-    if ((Gear^.Message and gmHJump) <> 0) and
+    if ((HHGear^.Message and gmHJump) <> 0) and
         wasJumping and
-        ((Gear^.State and gstHHHJump) = 0) then
-        if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
+        ((HHGear^.State and gstHHHJump) = 0) then
+        if (not (hwAbs(HHGear^.dX) > cLittle)) and (HHGear^.dY < -_0_02) then
             begin
-            Gear^.State:= Gear^.State or gstHHHJump;
-            Gear^.dY:= -_0_25;
-            if not cArtillery then Gear^.dX:= -SignAs(_0_02, Gear^.dX);
+            HHGear^.State:= HHGear^.State or gstHHHJump;
+            HHGear^.dY:= -_0_25;
+            if not cArtillery then HHGear^.dX:= -SignAs(_0_02, HHGear^.dX);
             PlaySound(sndJump2, Hedgehog^.Team^.voicepack)
             end;
 
-    Gear^.Message:= Gear^.Message and not (gmLJump or gmHJump);
+    HHGear^.Message:= HHGear^.Message and not (gmLJump or gmHJump);
 
     if (not cArtillery) and wasJumping and
-        TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
+        TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then SetLittle(HHGear^.dX);
 
-    doStepHedgehogMoving(Gear);
+    if Hedgehog^.Gear <> nil then doStepHedgehogMoving(HHGear);
 
-    if ((Gear^.State and (gstMoving or gstDrowning)) = 0) then
+    if ((HHGear^.State and (gstMoving or gstDrowning)) = 0) then
         begin
-        AddGearCI(Gear);
+        AddGearCI(HHGear);
         if wasJumping then
             StepTicks:= 410
         else
@@ -896,10 +900,10 @@
     exit
     end;
 
-    if not isInMultiShoot then
+    if not isInMultiShoot and (Hedgehog^.Gear <> nil) then
         begin
         if StepTicks > 0 then dec(StepTicks);
-        if (StepTicks = 0) then HedgehogStep(Gear)
+        if (StepTicks = 0) then HedgehogStep(HHGear)
         end
 end;
 
--- a/hedgewars/uAIAmmoTests.pas	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/uAIAmmoTests.pas	Sat Jan 29 18:18:44 2011 +0100
@@ -103,8 +103,9 @@
             (proc: @TestGrenade;     flags: 0), // amSMine
             (proc: @TestFirePunch;   flags: 0), // amHammer
             (proc: nil;              flags: 0), // amResurrector
-            (proc: nil;              flags: 0),// amDrillStrike
-            (proc: @TestSnowball;    flags: 0) // amSnowball
+            (proc: nil;              flags: 0), // amDrillStrike
+            (proc: @TestSnowball;    flags: 0), // amSnowball
+            (proc: nil;              flags: 0) // amStructure
             );
 
 const BadTurn = Low(LongInt) div 4;
--- a/hedgewars/uGears.pas	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/uGears.pas	Sat Jan 29 18:18:44 2011 +0100
@@ -59,10 +59,10 @@
 procedure AfterAttack; forward;
 procedure HedgehogStep(Gear: PGear); forward;
 procedure doStepHedgehogMoving(Gear: PGear); forward;
-procedure HedgehogChAngle(Gear: PGear); forward;
+procedure HedgehogChAngle(HHGear: PGear); forward;
 procedure ShotgunShot(Gear: PGear); forward;
 procedure PickUp(HH, Gear: PGear); forward;
-procedure HHSetWeapon(Gear: PGear); forward;
+procedure HHSetWeapon(HHGear: PGear); forward;
 procedure doStepCase(Gear: PGear); forward;
 
 {$INCLUDE "GSHandlers.inc"}
@@ -128,7 +128,8 @@
             @doStepResurrector,
             @doStepNapalmBomb,
             @doStepSnowball,
-            @doStepSnowflake
+            @doStepSnowflake,
+            @doStepStructure
             );
 
 procedure InsertGearToList(Gear: PGear);
@@ -514,6 +515,14 @@
                 gear^.Radius:= 5;
                 gear^.Density:= _1_5;
                 end;
+   gtStructure: begin
+                gear^.ImpactSound:= sndGrenadeImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Radius:= 13;
+                gear^.Elasticity:= _0_3;
+                gear^.Timer:= 5000;
+                gear^.Health:= 50;
+                end;
     end;
 
 InsertGearToList(gear);
@@ -1034,7 +1043,7 @@
            spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg);
            end;
         end;
-    end else // not gtHedgehog
+    end else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure
         begin
         AddFileLog('Assigning hedgehog ' + inttostr(LongInt(AttackerHog)) + ' to gear ' + inttostr(Gear^.uid));
         Gear^.Hedgehog:= AttackerHog;
@@ -1193,7 +1202,8 @@
                 gtCase,
                 gtTarget,
                 gtFlame,
-                gtExplosives: begin
+                gtExplosives,
+                gtStructure: begin
 // Run the calcs only once we know we have a type that will need damage
                         if hwRound(hwAbs(Gear^.X-fX)+hwAbs(Gear^.Y-fY)) < dmgBase then
                             dmg:= dmgBase - hwRound(Distance(Gear^.X - fX, Gear^.Y - fY));
@@ -1268,7 +1278,8 @@
             gtSMine,
             gtCase,
             gtTarget,
-            gtExplosives: begin
+            gtExplosives,
+            gtStructure: begin
                     if (not t^.Invulnerable) then
                         ApplyDamage(t, Gear^.Hedgehog, dmg, dsBullet)
                     else
@@ -1332,7 +1343,8 @@
             gtSMine,
             gtTarget,
             gtCase,
-            gtExplosives: begin
+            gtExplosives,
+            gtStructure: begin
                     if (Ammo^.Kind = gtDrill) then begin Ammo^.Timer:= 0; exit; end;
                     if (not Gear^.Invulnerable) then
                         ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove)
--- a/hedgewars/uGearsRender.pas	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/uGearsRender.pas	Sat Jan 29 18:18:44 2011 +0100
@@ -944,6 +944,7 @@
                     DrawRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0);
                     end;
         gtSwitcher: DrawSprite(sprSwitch, x - 16, y - 56, (GameTicks shr 6) mod 12);
+       gtStructure,
           gtTarget: begin
                     Tint($FF, $FF, $FF, round($FF * Gear^.Timer / 1000));
                     DrawSprite(sprTarget, x - 16, y - 16, 0);
--- a/hedgewars/uTeams.pas	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/uTeams.pas	Sat Jan 29 18:18:44 2011 +0100
@@ -529,11 +529,17 @@
 end;
 
 procedure freeModule;
-var i: LongWord;
+var i, h: LongWord;
 begin
    if TeamsCount > 0 then
      begin
-     for i:= 0 to Pred(TeamsCount) do Dispose(TeamsArray[i]);
+     for i:= 0 to Pred(TeamsCount) do
+        begin
+            for h:= 0 to cMaxHHIndex do
+                if TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil then
+                    Dispose(TeamsArray[i]^.Hedgehogs[h].GearHidden);
+            Dispose(TeamsArray[i]);
+        end;
      for i:= 0 to Pred(ClansCount) do Dispose(ClansArray[i]);
      end;
    TeamsCount:= 0;
--- a/hedgewars/uTypes.pas	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/uTypes.pas	Sat Jan 29 18:18:44 2011 +0100
@@ -71,7 +71,7 @@
             gtSniperRifleShot, gtJetpack, gtMolotov, gtExplosives, gtBirdy, // 45
             gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 51
             gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 56
-            gtNapalmBomb, gtSnowball, gtFlake); // 58
+            gtNapalmBomb, gtSnowball, gtFlake, gtStructure); // 60
 
     // Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
     TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
@@ -116,7 +116,7 @@
             amRCPlane, amLowGravity, amExtraDamage, amInvulnerable, amExtraTime, // 35
             amLaserSight, amVampiric, amSniperRifle, amJetpack, amMolotov, amBirdy, amPortalGun, // 42
             amPiano, amGasBomb, amSineGun, amFlamethrower, amSMine, amHammer, // 48
-            amResurrector, amDrillStrike, amSnowball);
+            amResurrector, amDrillStrike, amSnowball, amStructure);
 
     TCrateType = (HealthCrate, AmmoCrate, UtilityCrate);
 
@@ -281,6 +281,7 @@
     THedgehog = record
             Name: string[MAXNAMELEN];
             Gear: PGear;
+            GearHidden: PGear;
             SpeechGear: PVisualGear;
             NameTagTex,
             HealthTagTex,
@@ -350,7 +351,7 @@
             sidLowGravity, sidExtraDamage, sidInvulnerable, sidExtraTime,
             sidLaserSight, sidVampiric, sidSniperRifle, sidJetpack,
             sidMolotov, sidBirdy, sidPortalGun, sidPiano, sidGasBomb, sidSineGun, sidFlamethrower,
-            sidSMine, sidHammer, sidResurrector, sidDrillStrike, sidSnowball, sidNothing);
+            sidSMine, sidHammer, sidResurrector, sidDrillStrike, sidSnowball, sidNothing, sidStructure);
 
     TMsgStrId = (sidStartFight, sidDraw, sidWinner, sidVolume, sidPaused,
             sidConfirm, sidSuddenDeath, sidRemaining, sidFuel, sidSync,
--- a/hedgewars/uVariables.pas	Sat Jan 29 17:40:45 2011 +0100
+++ b/hedgewars/uVariables.pas	Sat Jan 29 18:18:44 2011 +0100
@@ -2000,6 +2000,29 @@
             PosCount: 1;
             PosSprite: sprWater;
             ejectX: 0; 
+            ejectY: 0),
+
+// Structure
+            (NameId: sidStructure;
+            NameTex: nil;
+            Probability: 0;
+            NumberInCase: 1;
+            Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_DontHold or ammoprop_Utility;
+                Count: 1;
+                NumPerTurn: 0;
+                Timer: 0;
+                Pos: 0;
+                AmmoType: amStructure;
+                AttackVoice: sndNone);
+            Slot: 6;
+            TimeAfterTurn: 0;
+            minAngle: 0;
+            maxAngle: 0;
+            isDamaging: false;
+            SkipTurns: 0;
+            PosCount: 1;
+            PosSprite: sprWater;
+            ejectX: 0;
             ejectY: 0)
         );
 
--- a/share/hedgewars/Data/Locale/en.txt	Sat Jan 29 17:40:45 2011 +0100
+++ b/share/hedgewars/Data/Locale/en.txt	Sat Jan 29 18:18:44 2011 +0100
@@ -53,6 +53,7 @@
 00:50=Drill Strike
 00:51=Mudball
 00:52=No weapon selected
+00:53=Structure
 
 01:00=Let's fight!
 01:01=Round draw