hedgewars/uGears.pas
changeset 3697 d5b30d6373fc
parent 3689 e2be39ee19f0
child 3710 411f5c2b5292
equal deleted inserted replaced
3695:c11abf387a7d 3697:d5b30d6373fc
    20 
    20 
    21 unit uGears;
    21 unit uGears;
    22 interface
    22 interface
    23 uses SDLh, uConsts, uFloat, Math;
    23 uses SDLh, uConsts, uFloat, Math;
    24 
    24 
    25     
    25 
    26 type
    26 type
    27     PGear = ^TGear;
    27     PGear = ^TGear;
    28     TGearStepProcedure = procedure (Gear: PGear);
    28     TGearStepProcedure = procedure (Gear: PGear);
    29     TGear = record
    29     TGear = record
    30             NextGear, PrevGear: PGear;
    30             NextGear, PrevGear: PGear;
    75     TrainingTargetGear: PGear;
    75     TrainingTargetGear: PGear;
    76     skipFlag: boolean;
    76     skipFlag: boolean;
    77     PlacingHogs: boolean; // a convenience flag to indicate placement of hogs is still in progress
    77     PlacingHogs: boolean; // a convenience flag to indicate placement of hogs is still in progress
    78     StepSoundTimer: LongInt;
    78     StepSoundTimer: LongInt;
    79     StepSoundChannel: LongInt;
    79     StepSoundChannel: LongInt;
    80     
    80 
    81 procedure initModule;
    81 procedure initModule;
    82 procedure freeModule;
    82 procedure freeModule;
    83 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
    83 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
    84 procedure ProcessGears;
    84 procedure ProcessGears;
    85 procedure EndTurnCleanup;
    85 procedure EndTurnCleanup;
   111                                   dLen: hwFloat;
   111                                   dLen: hwFloat;
   112                                   b: boolean;
   112                                   b: boolean;
   113                                   end;
   113                                   end;
   114                 rounded: array[0..MAXROPEPOINTS + 2] of TVertex2f;
   114                 rounded: array[0..MAXROPEPOINTS + 2] of TVertex2f;
   115                 end;
   115                 end;
   116  
   116 
   117 procedure DeleteGear(Gear: PGear); forward;
   117 procedure DeleteGear(Gear: PGear); forward;
   118 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask: LongWord); forward;
   118 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask: LongWord); forward;
   119 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask, Tint: LongWord); forward;
   119 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask, Tint: LongWord); forward;
   120 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
   120 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
   121 //procedure AmmoFlameWork(Ammo: PGear); forward;
   121 //procedure AmmoFlameWork(Ammo: PGear); forward;
   212     while (tmp <> nil) and (tmp^.Z <= Gear^.Z) do
   212     while (tmp <> nil) and (tmp^.Z <= Gear^.Z) do
   213         begin
   213         begin
   214         ptmp:= tmp;
   214         ptmp:= tmp;
   215         tmp:= tmp^.NextGear
   215         tmp:= tmp^.NextGear
   216         end;
   216         end;
   217     
   217 
   218     if ptmp <> tmp then
   218     if ptmp <> tmp then
   219         begin
   219         begin
   220         Gear^.NextGear:= ptmp^.NextGear;
   220         Gear^.NextGear:= ptmp^.NextGear;
   221         Gear^.PrevGear:= ptmp;
   221         Gear^.PrevGear:= ptmp;
   222         if ptmp^.NextGear <> nil then ptmp^.NextGear^.PrevGear:= Gear;
   222         if ptmp^.NextGear <> nil then ptmp^.NextGear^.PrevGear:= Gear;
   469                 gear^.Radius:= 8
   469                 gear^.Radius:= 8
   470                 end;
   470                 end;
   471      gtJetpack: begin
   471      gtJetpack: begin
   472                 gear^.Health:= 2000;
   472                 gear^.Health:= 2000;
   473                 end;
   473                 end;
   474      gtMolotov: begin 
   474      gtMolotov: begin
   475                 gear^.Radius:= 6;
   475                 gear^.Radius:= 6;
   476                 end;
   476                 end;
   477        gtBirdy: begin
   477        gtBirdy: begin
   478                 gear^.Radius:= 16; // todo: check
   478                 gear^.Radius:= 16; // todo: check
   479                 gear^.Timer:= 0;
   479                 gear^.Timer:= 0;
   480                 gear^.Health := 2000;
   480                 gear^.Health := 2000;
   481                 gear^.FlightTime := 2;
   481                 gear^.FlightTime := 2;
   482                 end;
   482                 end;
   483          gtEgg: begin 
   483          gtEgg: begin
   484                 gear^.Radius:= 4;
   484                 gear^.Radius:= 4;
   485                 gear^.Elasticity:= _0_6;
   485                 gear^.Elasticity:= _0_6;
   486                 gear^.Friction:= _0_96;
   486                 gear^.Friction:= _0_96;
   487                 if gear^.Timer = 0 then gear^.Timer:= 3000
   487                 if gear^.Timer = 0 then gear^.Timer:= 3000
   488                 end;
   488                 end;
   650             if PHedgehog(Gear^.Hedgehog)^.King then
   650             if PHedgehog(Gear^.Hedgehog)^.King then
   651                 begin
   651                 begin
   652                 flag:= false;
   652                 flag:= false;
   653                 team:= PHedgehog(Gear^.Hedgehog)^.Team;
   653                 team:= PHedgehog(Gear^.Hedgehog)^.Team;
   654                 for i:= 0 to Pred(team^.HedgehogsNumber) do
   654                 for i:= 0 to Pred(team^.HedgehogsNumber) do
   655                     if (team^.Hedgehogs[i].Gear <> nil) and 
   655                     if (team^.Hedgehogs[i].Gear <> nil) and
   656                         (not team^.Hedgehogs[i].King) and 
   656                         (not team^.Hedgehogs[i].King) and
   657                         (team^.Hedgehogs[i].Gear^.Health > team^.Hedgehogs[i].Gear^.Damage) 
   657                         (team^.Hedgehogs[i].Gear^.Health > team^.Hedgehogs[i].Gear^.Damage)
   658                     then flag:= true;
   658                     then flag:= true;
   659                 if not flag then inc(tmp, min(5, max(0,Gear^.Health - 1 - Gear^.Damage)))
   659                 if not flag then inc(tmp, min(5, max(0,Gear^.Health - 1 - Gear^.Damage)))
   660                 end;
   660                 end;
   661             if tmp > 0 then ApplyDamage(Gear, tmp, dsPoison);
   661             if tmp > 0 then ApplyDamage(Gear, tmp, dsPoison);
   662             end;
   662             end;
   792             else begin
   792             else begin
   793                 // delayed till after 0.9.12
   793                 // delayed till after 0.9.12
   794                 // reset to default zoom
   794                 // reset to default zoom
   795                 //ZoomValue:= ZoomDefault;
   795                 //ZoomValue:= ZoomDefault;
   796                 with CurrentHedgehog^ do
   796                 with CurrentHedgehog^ do
   797                     if (Gear <> nil) 
   797                     if (Gear <> nil)
   798                         and ((Gear^.State and gstAttacked) = 0)
   798                         and ((Gear^.State and gstAttacked) = 0)
   799                         and (MultiShootAttacks > 0) then OnUsedAmmo(CurrentHedgehog^);
   799                         and (MultiShootAttacks > 0) then OnUsedAmmo(CurrentHedgehog^);
   800                 
   800 
   801                 EndTurnCleanup;
   801                 EndTurnCleanup;
   802 
   802 
   803                 FreeActionsList; // could send -left, -right and similar commands, so should be called before /nextturn
   803                 FreeActionsList; // could send -left, -right and similar commands, so should be called before /nextturn
   804 
   804 
   805                 ParseCommand('/nextturn', true);
   805                 ParseCommand('/nextturn', true);
  1316     Gear: PGear;
  1316     Gear: PGear;
  1317     i, tmpDmg: LongInt;
  1317     i, tmpDmg: LongInt;
  1318 begin
  1318 begin
  1319 t:= CheckGearsCollision(Ammo);
  1319 t:= CheckGearsCollision(Ammo);
  1320 // Just to avoid hogs on rope dodging fire.
  1320 // Just to avoid hogs on rope dodging fire.
  1321 if (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtRope) and 
  1321 if (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtRope) and
  1322    (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1) and 
  1322    (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1) and
  1323    (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then 
  1323    (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then
  1324     begin
  1324     begin
  1325     t^.ar[t^.Count]:= CurrentHedgehog^.Gear;
  1325     t^.ar[t^.Count]:= CurrentHedgehog^.Gear;
  1326     inc(t^.Count)
  1326     inc(t^.Count)
  1327     end;
  1327     end;
  1328 i:= t^.Count;
  1328 i:= t^.Count;
  1334     Gear:= t^.ar[i];
  1334     Gear:= t^.ar[i];
  1335     tmpDmg:= ModifyDamage(Damage, Gear);
  1335     tmpDmg:= ModifyDamage(Damage, Gear);
  1336     if (Gear^.State and gstNoDamage) = 0 then
  1336     if (Gear^.State and gstNoDamage) = 0 then
  1337         begin
  1337         begin
  1338         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1;
  1338         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1;
  1339         
  1339 
  1340         case Gear^.Kind of
  1340         case Gear^.Kind of
  1341             gtHedgehog,
  1341             gtHedgehog,
  1342             gtMine,
  1342             gtMine,
  1343             gtTarget,
  1343             gtTarget,
  1344             gtCase,
  1344             gtCase,
  1372                         if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
  1372                         if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
  1373                             or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
  1373                             or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
  1374                         if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
  1374                         if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
  1375                             or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
  1375                             or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
  1376                         end;
  1376                         end;
  1377                     
  1377 
  1378                     if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then FollowGear:= Gear
  1378                     if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then FollowGear:= Gear
  1379                     end;
  1379                     end;
  1380         end
  1380         end
  1381         end;
  1381         end;
  1382     end;
  1382     end;
  1536 a:=aTot;
  1536 a:=aTot;
  1537 h:= 1;
  1537 h:= 1;
  1538 // FIXME - shoppa is TEMPORARY REMOVE WHEN CRATE PROBABILITY ALLOWS DISABLING OF HEALTH CRATES
  1538 // FIXME - shoppa is TEMPORARY REMOVE WHEN CRATE PROBABILITY ALLOWS DISABLING OF HEALTH CRATES
  1539 // Preserving health crate distribution of 35% until that happens
  1539 // Preserving health crate distribution of 35% until that happens
  1540 if (aTot+uTot) <> 0 then
  1540 if (aTot+uTot) <> 0 then
  1541     if not shoppa and ((GameFlags and gfInvulnerable) = 0) then 
  1541     if not shoppa and ((GameFlags and gfInvulnerable) = 0) then
  1542         begin
  1542         begin
  1543         h:= 3500;
  1543         h:= 3500;
  1544         t:= GetRandom(10000);
  1544         t:= GetRandom(10000);
  1545         a:= 6500*aTot div (aTot+uTot)
  1545         a:= 6500*aTot div (aTot+uTot)
  1546         end
  1546         end
  1547     else 
  1547     else
  1548         begin
  1548         begin
  1549         t:= GetRandom(aTot+uTot);
  1549         t:= GetRandom(aTot+uTot);
  1550         h:= 0
  1550         h:= 0
  1551         end;
  1551         end;
  1552 
  1552 
  1553     
  1553 
  1554 if t<h then
  1554 if t<h then
  1555     begin
  1555     begin
  1556     FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
  1556     FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0);
  1557     FollowGear^.Health:= 25;
  1557     FollowGear^.Health:= 25;
  1558     FollowGear^.Pos:= posCaseHealth;
  1558     FollowGear^.Pos:= posCaseHealth;
  1651             sy:= y;
  1651             sy:= y;
  1652 
  1652 
  1653             repeat
  1653             repeat
  1654                 inc(y);
  1654                 inc(y);
  1655             until (y >= LAND_HEIGHT) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0);
  1655             until (y >= LAND_HEIGHT) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0);
  1656             
  1656 
  1657             if (y - sy > Gear^.Radius * 2) and
  1657             if (y - sy > Gear^.Radius * 2) and
  1658                (((Gear^.Kind = gtExplosives)
  1658                (((Gear^.Kind = gtExplosives)
  1659                    and (y < LAND_HEIGHT-1)
  1659                    and (y < LAND_HEIGHT-1)
  1660                    and (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 60, 60) = nil)
  1660                    and (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 60, 60) = nil)
  1661                    and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius)) 
  1661                    and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius))
  1662                or
  1662                or
  1663                  ((Gear^.Kind <> gtExplosives)
  1663                  ((Gear^.Kind <> gtExplosives)
  1664                    and (y < LAND_HEIGHT)
  1664                    and (y < LAND_HEIGHT)
  1665                    and (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 110, 110) = nil))) then
  1665                    and (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 110, 110) = nil))) then
  1666                 begin
  1666                 begin
  1740     KilledHHs:= 0;
  1740     KilledHHs:= 0;
  1741     SuddenDeathDmg:= false;
  1741     SuddenDeathDmg:= false;
  1742     SpeechType:= 1;
  1742     SpeechType:= 1;
  1743     TrainingTargetGear:= nil;
  1743     TrainingTargetGear:= nil;
  1744     skipFlag:= false;
  1744     skipFlag:= false;
  1745     
  1745 
  1746     AllInactive:= false;
  1746     AllInactive:= false;
  1747     PrvInactive:= false;
  1747     PrvInactive:= false;
  1748 end;
  1748 end;
  1749 
  1749 
  1750 procedure freeModule;
  1750 procedure freeModule;