9287
+ − 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.