hedgewars/uGears.pas
branchexperimental3D
changeset 4844 20b81fafd236
parent 4837 2ea0a152c319
child 4867 e604ee83e34f
equal deleted inserted replaced
4818:202eef454354 4844:20b81fafd236
    27 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
    27 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
    28 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content: Longword ): PGear;
    28 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content: Longword ): PGear;
    29 procedure ResurrectHedgehog(gear: PGear);
    29 procedure ResurrectHedgehog(gear: PGear);
    30 procedure ProcessGears;
    30 procedure ProcessGears;
    31 procedure EndTurnCleanup;
    31 procedure EndTurnCleanup;
    32 procedure ApplyDamage(Gear: PGear; Damage: Longword; Source: TDamageSource);
    32 procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
    33 procedure SetAllToActive;
    33 procedure SetAllToActive;
    34 procedure SetAllHHToActive;
    34 procedure SetAllHHToActive;
    35 procedure DrawGears;
    35 procedure DrawGears;
    36 procedure FreeGearsList;
    36 procedure FreeGearsList;
    37 procedure AddMiscGears;
    37 procedure AddMiscGears;
    48 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics,
    48 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics,
    49      uAIMisc, uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile, uVariables,
    49      uAIMisc, uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile, uVariables,
    50      uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture;
    50      uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture;
    51 
    51 
    52 
    52 
    53 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask: LongWord); forward;
    53 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord = $FFFFFFFF); forward;
    54 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask, Tint: LongWord); forward;
       
    55 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
    54 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward;
    56 //procedure AmmoFlameWork(Ammo: PGear); forward;
    55 //procedure AmmoFlameWork(Ammo: PGear); forward;
    57 function  GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): TPGearArray; forward;
    56 function  GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): TPGearArray; forward;
    58 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear; forward;
    57 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear; forward;
    59 procedure SpawnBoxOfSmth; forward;
    58 procedure SpawnBoxOfSmth; forward;
   203 gear^.uid:= Counter;
   202 gear^.uid:= Counter;
   204 gear^.SoundChannel:= -1;
   203 gear^.SoundChannel:= -1;
   205 gear^.ImpactSound:= sndNone;
   204 gear^.ImpactSound:= sndNone;
   206 gear^.nImpactSounds:= 0;
   205 gear^.nImpactSounds:= 0;
   207 
   206 
   208 if CurrentTeam <> nil then
   207 if CurrentHedgehog <> nil then
   209     begin
   208     begin
   210     gear^.Hedgehog:= CurrentHedgehog;
   209     gear^.Hedgehog:= CurrentHedgehog;
   211     gear^.IntersectGear:= CurrentHedgehog^.Gear
   210     gear^.IntersectGear:= CurrentHedgehog^.Gear
   212     end;
   211     end;
   213 
   212 
   557             begin
   556             begin
   558             t:= max(Gear^.Damage, Gear^.Health);
   557             t:= max(Gear^.Damage, Gear^.Health);
   559             Gear^.Damage:= t;
   558             Gear^.Damage:= t;
   560             if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cWaterOpacity < $FF))) and (hwRound(Gear^.Y) < cWaterLine + 256) then
   559             if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cWaterOpacity < $FF))) and (hwRound(Gear^.Y) < cWaterLine + 256) then
   561                 spawnHealthTagForHH(Gear, t);
   560                 spawnHealthTagForHH(Gear, t);
   562             uStats.HedgehogDamaged(Gear)
   561 
       
   562             // should be not CurrentHedgehog, but hedgehog of the last gear which caused damage to this hog
       
   563             // same stand for CheckHHDamage
       
   564             uStats.HedgehogDamaged(Gear, CurrentHedgehog)
   563             end;
   565             end;
   564 
   566 
   565         team:= Gear^.Hedgehog^.Team;
   567         team:= Gear^.Hedgehog^.Team;
   566         if CurrentHedgehog^.Gear = Gear then
   568         if CurrentHedgehog^.Gear = Gear then
   567             FreeActionsList; // to avoid ThinkThread on drawned gear
   569             FreeActionsList; // to avoid ThinkThread on drawned gear
   614         if (not isInMultiShoot) then inc(Gear^.Damage, Gear^.Karma);
   616         if (not isInMultiShoot) then inc(Gear^.Damage, Gear^.Karma);
   615         if (Gear^.Damage <> 0) and
   617         if (Gear^.Damage <> 0) and
   616         (not Gear^.Invulnerable) then
   618         (not Gear^.Invulnerable) then
   617             begin
   619             begin
   618             CheckNoDamage:= false;
   620             CheckNoDamage:= false;
   619             uStats.HedgehogDamaged(Gear);
   621 
   620             dmg:= Gear^.Damage;
   622             dmg:= Gear^.Damage;
   621             if Gear^.Health < dmg then
   623             if Gear^.Health < dmg then
   622                 begin
   624                 begin
   623                 Gear^.Active:= true;
   625                 Gear^.Active:= true;
   624                 Gear^.Health:= 0
   626                 Gear^.Health:= 0
   799                     if cHealthDecrease <> 0 then
   801                     if cHealthDecrease <> 0 then
   800                         begin
   802                         begin
   801                         SuddenDeathDmg:= true;
   803                         SuddenDeathDmg:= true;
   802                         ChangeToSDClouds;
   804                         ChangeToSDClouds;
   803                         ChangeToSDFlakes;
   805                         ChangeToSDFlakes;
       
   806                         glClearColor(SDSkyColor.r / 255, SDSkyColor.g / 255, SDSkyColor.b / 255, 0.99);
   804                         end;
   807                         end;
   805                     AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
   808                     AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
   806                     playSound(sndSuddenDeath);
   809                     playSound(sndSuddenDeath);
   807                     MusicFN:= SDMusic;
   810                     MusicFN:= SDMusic;
   808                     ChangeMusic
   811                     ChangeMusic
   984     if (GameFlags and gfResetHealth) <> 0 then
   987     if (GameFlags and gfResetHealth) <> 0 then
   985         for i:= 0 to Pred(TeamsCount) do
   988         for i:= 0 to Pred(TeamsCount) do
   986             RecountTeamHealth(TeamsArray[i])
   989             RecountTeamHealth(TeamsArray[i])
   987 end;
   990 end;
   988 
   991 
   989 procedure ApplyDamage(Gear: PGear; Damage: Longword; Source: TDamageSource);
   992 procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
   990 var s: shortstring;
   993 var s: shortstring;
   991     vampDmg, tmpDmg, i: Longword;
   994     vampDmg, tmpDmg, i: Longword;
   992     vg: PVisualGear;
   995     vg: PVisualGear;
   993 begin
   996 begin
   994     if (Gear^.Kind = gtHedgehog) and (Damage>=1) then
   997     if (Gear^.Kind = gtHedgehog) and (Damage>=1) then
   995     begin
   998     begin
       
   999     uStats.HedgehogDamaged(Gear, AttackerHog);
   996     HHHurt(Gear^.Hedgehog, Source);
  1000     HHHurt(Gear^.Hedgehog, Source);
   997     AddDamageTag(hwRound(Gear^.X), hwRound(Gear^.Y), Damage, Gear^.Hedgehog^.Team^.Clan^.Color);
  1001     AddDamageTag(hwRound(Gear^.X), hwRound(Gear^.Y), Damage, Gear^.Hedgehog^.Team^.Clan^.Color);
   998     tmpDmg:= min(Damage, max(0,Gear^.Health-Gear^.Damage));
  1002     tmpDmg:= min(Damage, max(0,Gear^.Health-Gear^.Damage));
   999     if (Gear <> CurrentHedgehog^.Gear) and (CurrentHedgehog^.Gear <> nil) and (tmpDmg >= 1) then
  1003     if (Gear <> CurrentHedgehog^.Gear) and (CurrentHedgehog^.Gear <> nil) and (tmpDmg >= 1) then
  1000         begin
  1004         begin
  1026            begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid
  1030            begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid
  1027            inc(CurrentHedgehog^.Gear^.Karma, tmpDmg);
  1031            inc(CurrentHedgehog^.Gear^.Karma, tmpDmg);
  1028            spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg);
  1032            spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg);
  1029            end;
  1033            end;
  1030         end;
  1034         end;
  1031     end;
  1035     end else // not gtHedgehog
       
  1036         begin
       
  1037         AddFileLog('Assigning hedgehog ' + inttostr(LongInt(AttackerHog)) + ' to gear ' + inttostr(Gear^.uid));
       
  1038         Gear^.Hedgehog:= AttackerHog;
       
  1039         end;
  1032     inc(Gear^.Damage, Damage);
  1040     inc(Gear^.Damage, Damage);
  1033     ScriptCall('onGearDamage', Gear^.UID, Damage);
  1041     ScriptCall('onGearDamage', Gear^.UID, Damage);
  1034 end;
  1042 end;
  1035 
  1043 
  1036 procedure SetAllToActive;
  1044 procedure SetAllToActive;
  1050 begin
  1058 begin
  1051 AllInactive:= false;
  1059 AllInactive:= false;
  1052 t:= GearsList;
  1060 t:= GearsList;
  1053 while t <> nil do
  1061 while t <> nil do
  1054     begin
  1062     begin
  1055     if t^.Kind = gtHedgehog then t^.Active:= true;
  1063     if (t^.Kind = gtHedgehog) or (t^.Kind = gtExplosives) then t^.Active:= true;
  1056     t:= t^.NextGear
  1064     t:= t^.NextGear
  1057     end
  1065     end
  1058 end;
  1066 end;
  1059 
  1067 
  1060 
  1068 
  1089 var i: LongInt;
  1097 var i: LongInt;
  1090     Gear: PGear;
  1098     Gear: PGear;
  1091 begin
  1099 begin
  1092 AddGear(0, 0, gtATStartGame, 0, _0, _0, 2000);
  1100 AddGear(0, 0, gtATStartGame, 0, _0, _0, 2000);
  1093 
  1101 
  1094 for i:= 0 to Pred(cLandMines) do
  1102 i:= 0;
       
  1103 Gear:= PGear(1);
       
  1104 while (i < cLandMines) {and (Gear <> nil)} do // disable this check until better solution found
  1095     begin
  1105     begin
  1096     Gear:= AddGear(0, 0, gtMine, 0, _0, _0, 0);
  1106     Gear:= AddGear(0, 0, gtMine, 0, _0, _0, 0);
  1097     FindPlace(Gear, false, 0, LAND_WIDTH);
  1107     FindPlace(Gear, false, 0, LAND_WIDTH);
  1098     end;
  1108     inc(i)
  1099 for i:= 0 to Pred(cExplosives) do
  1109     end;
       
  1110 
       
  1111 i:= 0;
       
  1112 Gear:= PGear(1);
       
  1113 while (i < cExplosives){ and (Gear <> nil)} do
  1100     begin
  1114     begin
  1101     Gear:= AddGear(0, 0, gtExplosives, 0, _0, _0, 0);
  1115     Gear:= AddGear(0, 0, gtExplosives, 0, _0, _0, 0);
  1102     FindPlace(Gear, false, 0, LAND_WIDTH);
  1116     FindPlace(Gear, false, 0, LAND_WIDTH);
       
  1117     inc(i)
  1103     end;
  1118     end;
  1104 
  1119 
  1105 if (GameFlags and gfLowGravity) <> 0 then
  1120 if (GameFlags and gfLowGravity) <> 0 then
  1106     begin
  1121     begin
  1107     cGravity:= cMaxWindSpeed;
  1122     cGravity:= cMaxWindSpeed;
  1131         AddGear(GetRandom(LAND_WIDTH+1024)-512, LAND_HEIGHT - GetRandom(LAND_HEIGHT div 2), gtFlake, 0, _0, _0, 0);
  1146         AddGear(GetRandom(LAND_WIDTH+1024)-512, LAND_HEIGHT - GetRandom(LAND_HEIGHT div 2), gtFlake, 0, _0, _0, 0);
  1132     disableLandBack:= true
  1147     disableLandBack:= true
  1133     end
  1148     end
  1134 end;
  1149 end;
  1135 
  1150 
  1136 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask: LongWord);
  1151 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord);
  1137 begin
       
  1138 doMakeExplosion(X, Y, Radius, Mask, $FFFFFFFF);
       
  1139 end;
       
  1140 
       
  1141 procedure doMakeExplosion(X, Y, Radius: LongInt; Mask, Tint: LongWord);
       
  1142 var Gear: PGear;
  1152 var Gear: PGear;
  1143     dmg, dmgRadius, dmgBase: LongInt;
  1153     dmg, dmgRadius, dmgBase: LongInt;
  1144     fX, fY: hwFloat;
  1154     fX, fY: hwFloat;
  1145     vg: PVisualGear;
  1155     vg: PVisualGear;
  1146     i, cnt: LongInt;
  1156     i, cnt: LongInt;
  1190                             dmg:= ModifyDamage(min(dmg div 2, Radius), Gear);
  1200                             dmg:= ModifyDamage(min(dmg div 2, Radius), Gear);
  1191                             //{$IFDEF DEBUGFILE}AddFileLog('Damage: ' + inttostr(dmg));{$ENDIF}
  1201                             //{$IFDEF DEBUGFILE}AddFileLog('Damage: ' + inttostr(dmg));{$ENDIF}
  1192                             if (Mask and EXPLNoDamage) = 0 then
  1202                             if (Mask and EXPLNoDamage) = 0 then
  1193                                 begin
  1203                                 begin
  1194                                 if not Gear^.Invulnerable then
  1204                                 if not Gear^.Invulnerable then
  1195                                     ApplyDamage(Gear, dmg, dsExplosion)
  1205                                     ApplyDamage(Gear, AttackingHog, dmg, dsExplosion)
  1196                                 else
  1206                                 else
  1197                                     Gear^.State:= Gear^.State or gstWinner;
  1207                                     Gear^.State:= Gear^.State or gstWinner;
  1198                                 end;
  1208                                 end;
  1199                             if ((Mask and EXPLDoNotTouchAny) = 0) and (((Mask and EXPLDoNotTouchHH) = 0) or (Gear^.Kind <> gtHedgehog)) then
  1209                             if ((Mask and EXPLDoNotTouchAny) = 0) and (((Mask and EXPLDoNotTouchHH) = 0) or (Gear^.Kind <> gtHedgehog)) then
  1200                                 begin
  1210                                 begin
  1256             gtSMine,
  1266             gtSMine,
  1257             gtCase,
  1267             gtCase,
  1258             gtTarget,
  1268             gtTarget,
  1259             gtExplosives: begin
  1269             gtExplosives: begin
  1260                     if (not t^.Invulnerable) then
  1270                     if (not t^.Invulnerable) then
  1261                         ApplyDamage(t, dmg, dsBullet)
  1271                         ApplyDamage(t, Gear^.Hedgehog, dmg, dsBullet)
  1262                     else
  1272                     else
  1263                         Gear^.State:= Gear^.State or gstWinner;
  1273                         Gear^.State:= Gear^.State or gstWinner;
  1264 
  1274 
  1265                     DeleteCI(t);
  1275                     DeleteCI(t);
  1266                     t^.dX:= t^.dX + Gear^.dX * dmg * _0_01 + SignAs(cHHKick, Gear^.dX);
  1276                     t^.dX:= t^.dX + Gear^.dX * dmg * _0_01 + SignAs(cHHKick, Gear^.dX);
  1303     dec(i);
  1313     dec(i);
  1304     Gear:= t^.ar[i];
  1314     Gear:= t^.ar[i];
  1305     tmpDmg:= ModifyDamage(Damage, Gear);
  1315     tmpDmg:= ModifyDamage(Damage, Gear);
  1306     if (Gear^.State and gstNoDamage) = 0 then
  1316     if (Gear^.State and gstNoDamage) = 0 then
  1307         begin
  1317         begin
  1308         
  1318 
  1309         if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then 
  1319         if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then 
  1310             begin
  1320             begin
  1311             VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
  1321             VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
  1312             if VGear <> nil then VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
  1322             if VGear <> nil then VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
  1313             end;
  1323             end;
  1314         
  1324 
  1315         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1;
  1325         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1;
  1316 
  1326 
  1317         case Gear^.Kind of
  1327         case Gear^.Kind of
  1318             gtHedgehog,
  1328             gtHedgehog,
  1319             gtMine,
  1329             gtMine,
  1321             gtTarget,
  1331             gtTarget,
  1322             gtCase,
  1332             gtCase,
  1323             gtExplosives: begin
  1333             gtExplosives: begin
  1324                     if (Ammo^.Kind = gtDrill) then begin Ammo^.Timer:= 0; exit; end;
  1334                     if (Ammo^.Kind = gtDrill) then begin Ammo^.Timer:= 0; exit; end;
  1325                     if (not Gear^.Invulnerable) then
  1335                     if (not Gear^.Invulnerable) then
  1326                         ApplyDamage(Gear, tmpDmg, dsShove)
  1336                         ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove)
  1327                     else
  1337                     else
  1328                         Gear^.State:= Gear^.State or gstWinner;
  1338                         Gear^.State:= Gear^.State or gstWinner;
  1329                     if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then ApplyDamage(Gear, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch
  1339                     if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch
  1330 
  1340 
  1331                     DeleteCI(Gear);
  1341                     DeleteCI(Gear);
  1332                     if (Gear^.Kind = gtHedgehog) and Gear^.Hedgehog^.King then
  1342                     if (Gear^.Kind = gtHedgehog) and Gear^.Hedgehog^.King then
  1333                         begin
  1343                         begin
  1334                         Gear^.dX:= Ammo^.dX * Power * _0_005;
  1344                         Gear^.dX:= Ammo^.dX * Power * _0_005;
  1426 
  1436 
  1427 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): TPGearArray;
  1437 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): TPGearArray;
  1428 var
  1438 var
  1429     t: PGear;
  1439     t: PGear;
  1430 begin
  1440 begin
       
  1441     r:= r*r;
  1431     GearsNear := nil;
  1442     GearsNear := nil;
  1432     t := GearsList;
  1443     t := GearsList;
  1433     while t <> nil do begin
  1444     while t <> nil do begin
  1434         if (t^.Kind = Kind) then begin
  1445         if (t^.Kind = Kind) then begin
  1435             if (X - t^.X)*(X - t^.X) + (Y - t^.Y)*(Y-t^.Y) <
  1446             if (X - t^.X)*(X - t^.X) + (Y - t^.Y)*(Y-t^.Y) <
  1436                 int2hwFloat(r)*int2hwFloat(r) then
  1447                 int2hwFloat(r) then
  1437             begin
  1448             begin
  1438                 SetLength(GearsNear, Length(GearsNear)+1);
  1449                 SetLength(GearsNear, Length(GearsNear)+1);
  1439                 GearsNear[High(GearsNear)] := t;
  1450                 GearsNear[High(GearsNear)] := t;
  1440             end;
  1451             end;
  1441         end;
  1452         end;
  1515 var tempTeam : PTeam;
  1526 var tempTeam : PTeam;
  1516 begin
  1527 begin
  1517     gear^.dX := _0;
  1528     gear^.dX := _0;
  1518     gear^.dY := _0;
  1529     gear^.dY := _0;
  1519     gear^.State := gstWait;
  1530     gear^.State := gstWait;
  1520     uStats.HedgehogDamaged(gear);
       
  1521     gear^.Damage := 0;
  1531     gear^.Damage := 0;
  1522     gear^.Health := gear^.Hedgehog^.InitialHealth;
  1532     gear^.Health := gear^.Hedgehog^.InitialHealth;
  1523     gear^.Hedgehog^.Effects[hePoisoned] := false;
  1533     gear^.Hedgehog^.Effects[hePoisoned] := false;
  1524     if not CurrentHedgehog^.Effects[heResurrectable] then
  1534     if not CurrentHedgehog^.Effects[heResurrectable] then
  1525         with CurrentHedgehog^ do 
  1535         with CurrentHedgehog^ do