hedgewars/uVisualGearsList.pas
changeset 9287 bb9ad6a5f625
child 9769 5814e0c47c99
equal deleted inserted replaced
9285:8e8b908970c2 9287:bb9ad6a5f625
       
     1 (*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  *)
       
    18 
       
    19 {$INCLUDE "options.inc"}
       
    20 
       
    21 unit uVisualGearsList;
       
    22 interface
       
    23 uses uTypes;
       
    24 
       
    25 function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline;
       
    26 function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord): PVisualGear; inline;
       
    27 function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord; Critical: Boolean): PVisualGear;
       
    28 procedure DeleteVisualGear(Gear: PVisualGear);
       
    29 function  VisualGearByUID(uid : Longword) : PVisualGear;
       
    30 
       
    31 const 
       
    32     cExplFrameTicks = 110;
       
    33 
       
    34 var VGCounter: LongWord;
       
    35     VisualGearLayers: array[0..6] of PVisualGear;
       
    36 
       
    37 implementation
       
    38 uses uFloat, uVariables, uConsts, uTextures, uVisualGearsHandlers;
       
    39 
       
    40 function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline;
       
    41 begin
       
    42     AddVisualGear:= AddVisualGear(X, Y, Kind, 0, false);
       
    43 end;
       
    44 
       
    45 function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord): PVisualGear; inline;
       
    46 begin
       
    47     AddVisualGear:= AddVisualGear(X, Y, Kind, State, false);
       
    48 end;
       
    49 
       
    50 function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord; Critical: Boolean): PVisualGear;
       
    51 var gear: PVisualGear;
       
    52     t: Longword;
       
    53     sp: real;
       
    54 begin
       
    55 AddVisualGear:= nil;
       
    56 if ((GameType = gmtSave) or (fastUntilLag and (GameType = gmtNet)) or fastScrolling) and // we are scrolling now
       
    57    ((Kind <> vgtCloud) and (not Critical)) then
       
    58        exit;
       
    59 
       
    60 if ((cReducedQuality and rqAntiBoom) <> 0) and
       
    61    (not Critical) and
       
    62    (not (Kind in
       
    63    [vgtTeamHealthSorter,
       
    64     vgtSmallDamageTag,
       
    65     vgtSpeechBubble,
       
    66     vgtHealthTag,
       
    67     vgtExplosion,
       
    68     vgtSmokeTrace,
       
    69     vgtEvilTrace,
       
    70     vgtNote,
       
    71     vgtSmoothWindBar])) then
       
    72     
       
    73         exit;
       
    74 
       
    75 inc(VGCounter);
       
    76 New(gear);
       
    77 FillChar(gear^, sizeof(TVisualGear), 0);
       
    78 gear^.X:= real(X);
       
    79 gear^.Y:= real(Y);
       
    80 gear^.Kind := Kind;
       
    81 gear^.doStep:= doStepHandlers[Kind];
       
    82 gear^.State:= 0;
       
    83 gear^.Tint:= $FFFFFFFF;
       
    84 gear^.uid:= VGCounter;
       
    85 gear^.Layer:= 0;
       
    86 
       
    87 with gear^ do
       
    88     case Kind of
       
    89     vgtFlake:
       
    90                 begin
       
    91                 Timer:= 0;
       
    92                 tdX:= 0;
       
    93                 tdY:= 0;
       
    94                 Scale:= 1.0;
       
    95                 if SuddenDeathDmg then
       
    96                     begin
       
    97                     FrameTicks:= random(vobSDFrameTicks);
       
    98                     Frame:= random(vobSDFramesCount);
       
    99                     end
       
   100                 else
       
   101                     begin
       
   102                     FrameTicks:= random(vobFrameTicks);
       
   103                     Frame:= random(vobFramesCount);
       
   104                     end;
       
   105                 Angle:= random(360);
       
   106                 dx:= 0.0000038654705 * random(10000);
       
   107                 dy:= 0.000003506096 * random(7000);
       
   108                 if random(2) = 0 then
       
   109                     dx := -dx;
       
   110                 if SuddenDeathDmg then
       
   111                     dAngle:= (random(2) * 2 - 1) * (vobSDVelocity + random(vobSDVelocity)) / 1000
       
   112                 else
       
   113                     dAngle:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) / 1000
       
   114                 end;
       
   115     vgtCloud:
       
   116                 begin
       
   117                 Frame:= random(4);
       
   118                 dx:= 0.5 + 0.1 * random(5); // how much the cloud will be affected by wind
       
   119                 timer:= random(4096);
       
   120                 Scale:= 1.0
       
   121                 end;
       
   122     vgtExplPart,
       
   123     vgtExplPart2:
       
   124                 begin
       
   125                 t:= random(1024);
       
   126                 sp:= 0.001 * (random(95) + 70);
       
   127                 dx:= hwFloat2Float(AngleSin(t)) * sp;
       
   128                 dy:= hwFloat2Float(AngleCos(t)) * sp;
       
   129                 if random(2) = 0 then
       
   130                     dx := -dx;
       
   131                 if random(2) = 0 then
       
   132                     dy := -dy;
       
   133                 Frame:= 7 - random(3);
       
   134                 FrameTicks:= cExplFrameTicks
       
   135                 end;
       
   136         vgtFire:
       
   137                 begin
       
   138                 t:= random(1024);
       
   139                 sp:= 0.001 * (random(85) + 95);
       
   140                 dx:= hwFloat2Float(AngleSin(t)) * sp;
       
   141                 dy:= hwFloat2Float(AngleCos(t)) * sp;
       
   142                 if random(2) = 0 then
       
   143                     dx := -dx;
       
   144                 if random(2) = 0 then
       
   145                     dy := -dy;
       
   146                 FrameTicks:= 650 + random(250);
       
   147                 Frame:= random(8)
       
   148                 end;
       
   149          vgtEgg:
       
   150                 begin
       
   151                 t:= random(1024);
       
   152                 sp:= 0.001 * (random(85) + 95);
       
   153                 dx:= hwFloat2Float(AngleSin(t)) * sp;
       
   154                 dy:= hwFloat2Float(AngleCos(t)) * sp;
       
   155                 if random(2) = 0 then
       
   156                     dx := -dx;
       
   157                 if random(2) = 0 then
       
   158                     dy := -dy;
       
   159                 FrameTicks:= 650 + random(250);
       
   160                 Frame:= 1
       
   161                 end;
       
   162         vgtShell: FrameTicks:= 500;
       
   163     vgtSmallDamageTag:
       
   164                 begin
       
   165                 gear^.FrameTicks:= 1100
       
   166                 end;
       
   167     vgtBubble:
       
   168                 begin
       
   169                 dx:= 0.0000038654705 * random(10000);
       
   170                 dy:= 0;
       
   171                 if random(2) = 0 then
       
   172                     dx := -dx;
       
   173                 FrameTicks:= 250 + random(1751);
       
   174                 Frame:= random(5)
       
   175                 end;
       
   176     vgtSteam:
       
   177                 begin
       
   178                 dx:= 0.0000038654705 * random(10000);
       
   179                 dy:= 0.001 * (random(85) + 95);
       
   180                 if random(2) = 0 then
       
   181                     dx := -dx;
       
   182                 Frame:= 7 - random(3);
       
   183                 FrameTicks:= cExplFrameTicks * 2;
       
   184                 end;
       
   185     vgtAmmo:
       
   186                 begin
       
   187                 alpha:= 1.0;
       
   188                 scale:= 1.0
       
   189                 end;
       
   190   vgtSmokeWhite,
       
   191   vgtSmoke:
       
   192                 begin
       
   193                 Scale:= 1.0;
       
   194                 dx:= 0.0002 * (random(45) + 10);
       
   195                 dy:= 0.0002 * (random(45) + 10);
       
   196                 if random(2) = 0 then
       
   197                     dx := -dx;
       
   198                 Frame:= 7 - random(2);
       
   199                 FrameTicks:= cExplFrameTicks * 2;
       
   200                 end;
       
   201   vgtDust:
       
   202                 begin
       
   203                 dx:= 0.005 * (random(15) + 10);
       
   204                 dy:= 0.001 * (random(40) + 20);
       
   205                 if random(2) = 0 then dx := -dx;
       
   206                 if random(2) = 0 then Tag:= 1
       
   207                 else Tag:= -1;
       
   208                 Frame:= 7 - random(2);
       
   209                 FrameTicks:= random(20) + 15;
       
   210                 end;
       
   211   vgtSplash:
       
   212                 begin
       
   213                 dx:= 0;
       
   214                 dy:= 0;
       
   215                 FrameTicks:= 740;
       
   216                 Frame:= 19;
       
   217                 Scale:= 0.75;
       
   218                 Timer:= 1;
       
   219                 end;
       
   220     vgtDroplet:
       
   221                 begin
       
   222                 dx:= 0.001 * (random(180) - 90);
       
   223                 dy:= -0.001 * (random(160) + 40);
       
   224                 FrameTicks:= 250 + random(1751);
       
   225                 Frame:= random(3)
       
   226                 end;
       
   227    vgtBeeTrace:
       
   228                 begin
       
   229                 FrameTicks:= 1000;
       
   230                 Frame:= random(16);
       
   231                 end;
       
   232     vgtSmokeRing:
       
   233                 begin
       
   234                 dx:= 0;
       
   235                 dy:= 0;
       
   236                 FrameTicks:= 600;
       
   237                 Timer:= 0;
       
   238                 Frame:= 0;
       
   239                 scale:= 0.6;
       
   240                 alpha:= 1;
       
   241                 angle:= random(360);
       
   242                 end;
       
   243      vgtFeather:
       
   244                 begin
       
   245                 t:= random(1024);
       
   246                 sp:= 0.001 * (random(85) + 95);
       
   247                 dx:= hwFloat2Float(AngleSin(t)) * sp;
       
   248                 dy:= hwFloat2Float(AngleCos(t)) * sp;
       
   249                 if random(2) = 0 then
       
   250                     dx := -dx;
       
   251                 if random(2) = 0 then
       
   252                     dy := -dy;
       
   253                 FrameTicks:= 650 + random(250);
       
   254                 Frame:= 1
       
   255                 end;
       
   256   vgtHealthTag:
       
   257                 begin
       
   258                 Frame:= 0;
       
   259                 Timer:= 1500;
       
   260                 dY:= -0.08;
       
   261                 dX:= 0;
       
   262                 //gear^.Z:= 2002;
       
   263                 end;
       
   264   vgtSmokeTrace,
       
   265   vgtEvilTrace:
       
   266                 begin
       
   267                 gear^.X:= gear^.X - 16;
       
   268                 gear^.Y:= gear^.Y - 16;
       
   269                 gear^.State:= 8;
       
   270                 //gear^.Z:= cSmokeZ
       
   271                 end;
       
   272 vgtBigExplosion:
       
   273                 begin
       
   274                 gear^.Angle:= random(360);
       
   275                 end;
       
   276       vgtChunk:
       
   277                 begin
       
   278                 gear^.Frame:= random(4);
       
   279                 t:= random(1024);
       
   280                 sp:= 0.001 * (random(85) + 47);
       
   281                 dx:= hwFloat2Float(AngleSin(t)) * sp;
       
   282                 dy:= hwFloat2Float(AngleCos(t)) * sp * -2;
       
   283                 if random(2) = 0 then
       
   284                     dx := -dx;
       
   285                 end;
       
   286       vgtNote: 
       
   287                 begin
       
   288                 dx:= 0.005 * (random(15) + 10);
       
   289                 dy:= -0.001 * (random(40) + 20);
       
   290                 if random(2) = 0 then
       
   291                     dx := -dx;
       
   292                 Frame:= random(4);
       
   293                 FrameTicks:= random(2000) + 1500;
       
   294                 end;
       
   295   vgtBulletHit:
       
   296                 begin
       
   297                 dx:= 0;
       
   298                 dy:= 0;
       
   299                 FrameTicks:= 350;
       
   300                 Frame:= 7;
       
   301                 Angle:= 0;
       
   302                 end;
       
   303 vgtSmoothWindBar: 
       
   304                 begin
       
   305                 Angle:= hwFloat2Float(cMaxWindSpeed)*2 / 1440; // seems rate below is supposed to change wind bar at 1px per 10ms. Max time, 1440ms. This tries to match the rate of change
       
   306                 Tag:= hwRound(cWindSpeed * 72 / cMaxWindSpeed);
       
   307                 end;
       
   308  vgtStraightShot:
       
   309                 begin
       
   310                 Angle:= 0;
       
   311                 Scale:= 1.0;
       
   312                 dx:= 0.001 * random(45);
       
   313                 dy:= 0.001 * (random(20) + 25);
       
   314                 State:= ord(sprHealth);
       
   315                 if random(2) = 0 then
       
   316                     dx := -dx;
       
   317                 Frame:= 0;
       
   318                 FrameTicks:= random(750) + 1250;
       
   319                 State:= ord(sprSnowDust);
       
   320                 end;
       
   321         end;
       
   322 
       
   323 if State <> 0 then
       
   324     gear^.State:= State;
       
   325 
       
   326 case Gear^.Kind of
       
   327     vgtFlake: if cFlattenFlakes then
       
   328         gear^.Layer:= 0
       
   329               else if random(3) = 0 then 
       
   330                   begin
       
   331                   gear^.Scale:= 0.5;
       
   332                   gear^.Layer:= 0   // 33% - far back
       
   333                   end
       
   334               else if random(3) = 0 then
       
   335                   begin
       
   336                   gear^.Scale:= 0.8;
       
   337                   gear^.Layer:= 4   // 22% - mid-distance
       
   338                   end
       
   339               else if random(3) <> 0 then
       
   340                   gear^.Layer:= 5  // 30% - just behind land
       
   341               else if random(2) = 0 then
       
   342                   gear^.Layer:= 6   // 7% - just in front of land
       
   343               else
       
   344                   begin
       
   345                   gear^.Scale:= 1.5;
       
   346                   gear^.Layer:= 2;  // 7% - close up
       
   347                   end;
       
   348 
       
   349     vgtCloud: if cFlattenClouds then gear^.Layer:= 5
       
   350               else if random(3) = 0 then
       
   351                   begin
       
   352                   gear^.Scale:= 0.25;
       
   353                   gear^.Layer:= 0
       
   354                   end
       
   355               else if random(2) = 0 then
       
   356                   gear^.Layer:= 5
       
   357               else
       
   358                   begin
       
   359                   gear^.Scale:= 0.4;
       
   360                   gear^.Layer:= 4
       
   361                   end;
       
   362 
       
   363     // 0: this layer is very distant in the background when in stereo
       
   364     vgtTeamHealthSorter,
       
   365     vgtSmoothWindBar: gear^.Layer:= 0;
       
   366 
       
   367 
       
   368     // 1: this layer is on the land level (which is close but behind the screen plane) when stereo
       
   369     vgtSmokeTrace,
       
   370     vgtEvilTrace,
       
   371     vgtLineTrail,
       
   372     vgtSmoke,
       
   373     vgtSmokeWhite,
       
   374     vgtDust,
       
   375     vgtFire,
       
   376     vgtSplash,
       
   377     vgtDroplet,
       
   378     vgtBubble: gear^.Layer:= 1;
       
   379 
       
   380     // 3: this layer is on the screen plane (depth = 0) when stereo
       
   381     vgtSpeechBubble,
       
   382     vgtSmallDamageTag,
       
   383     vgtHealthTag,
       
   384     vgtStraightShot,
       
   385     vgtChunk: gear^.Layer:= 3;
       
   386 
       
   387     // 2: this layer is outside the screen when stereo
       
   388     vgtExplosion,
       
   389     vgtBigExplosion,
       
   390     vgtExplPart,
       
   391     vgtExplPart2,
       
   392     vgtSteam,
       
   393     vgtAmmo,
       
   394     vgtShell,
       
   395     vgtFeather,
       
   396     vgtEgg,
       
   397     vgtBeeTrace,
       
   398     vgtSmokeRing,
       
   399     vgtNote,
       
   400     vgtBulletHit,
       
   401     vgtCircle: gear^.Layer:= 2
       
   402 end;
       
   403 
       
   404 if VisualGearLayers[gear^.Layer] <> nil then
       
   405     begin
       
   406     VisualGearLayers[gear^.Layer]^.PrevGear:= gear;
       
   407     gear^.NextGear:= VisualGearLayers[gear^.Layer]
       
   408     end;
       
   409 VisualGearLayers[gear^.Layer]:= gear;
       
   410 
       
   411 AddVisualGear:= gear;
       
   412 end;
       
   413 
       
   414 procedure DeleteVisualGear(Gear: PVisualGear);
       
   415 begin
       
   416     FreeTexture(Gear^.Tex);
       
   417     Gear^.Tex:= nil;
       
   418 
       
   419     if Gear^.NextGear <> nil then
       
   420         Gear^.NextGear^.PrevGear:= Gear^.PrevGear;
       
   421     if Gear^.PrevGear <> nil then
       
   422         Gear^.PrevGear^.NextGear:= Gear^.NextGear
       
   423     else
       
   424         VisualGearLayers[Gear^.Layer]:= Gear^.NextGear;
       
   425 
       
   426     if lastVisualGearByUID = Gear then
       
   427         lastVisualGearByUID:= nil;
       
   428 
       
   429     Dispose(Gear);
       
   430 end;
       
   431 
       
   432 function  VisualGearByUID(uid : Longword) : PVisualGear;
       
   433 var vg: PVisualGear;
       
   434     i: LongWord;
       
   435 begin
       
   436 VisualGearByUID:= nil;
       
   437 if uid = 0 then
       
   438     exit;
       
   439 if (lastVisualGearByUID <> nil) and (lastVisualGearByUID^.uid = uid) then
       
   440     begin
       
   441     VisualGearByUID:= lastVisualGearByUID;
       
   442     exit
       
   443     end;
       
   444 // search in an order that is more likely to return layers they actually use.  Could perhaps track statistically AddVisualGear in uScript, since that is most likely the ones they want
       
   445 for i:= 2 to 5 do
       
   446     begin
       
   447     vg:= VisualGearLayers[i mod 4];
       
   448     while vg <> nil do
       
   449         begin
       
   450         if vg^.uid = uid then
       
   451             begin
       
   452             lastVisualGearByUID:= vg;
       
   453             VisualGearByUID:= vg;
       
   454             exit
       
   455             end;
       
   456         vg:= vg^.NextGear
       
   457         end
       
   458     end
       
   459 end;
       
   460 
       
   461 
       
   462 end.