1 (* |
1 (* |
2 * Hedgewars, a free turn based strategy game |
2 * Hedgewars, a free turn based strategy game |
3 * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com> |
3 * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com> |
4 * |
4 * |
5 * This program is free software; you can redistribute it and/or modify |
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 |
6 * it under the terms of the GNU General Public License as published by |
7 * the Free Software Foundation; version 2 of the License |
7 * the Free Software Foundation; version 2 of the License |
8 * |
8 * |
29 procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource); |
29 procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource); |
30 procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword); |
30 procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword); |
31 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource); |
31 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource); |
32 procedure CheckHHDamage(Gear: PGear); |
32 procedure CheckHHDamage(Gear: PGear); |
33 procedure CalcRotationDirAngle(Gear: PGear); |
33 procedure CalcRotationDirAngle(Gear: PGear); |
34 procedure ResurrectHedgehog(gear: PGear); |
34 procedure ResurrectHedgehog(var gear: PGear); |
35 |
35 |
36 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline; |
36 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline; |
37 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean); |
37 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean); |
38 |
38 |
39 function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear; |
39 function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear; |
40 function CheckGearDrowning(Gear: PGear): boolean; |
40 function CheckGearDrowning(var Gear: PGear): boolean; |
41 procedure CheckCollision(Gear: PGear); inline; |
41 procedure CheckCollision(Gear: PGear); inline; |
42 procedure CheckCollisionWithLand(Gear: PGear); inline; |
42 procedure CheckCollisionWithLand(Gear: PGear); inline; |
43 |
43 |
44 function MakeHedgehogsStep(Gear: PGear) : boolean; |
44 function MakeHedgehogsStep(Gear: PGear) : boolean; |
45 |
45 |
261 HHGear^.Active:= true; |
261 HHGear^.Active:= true; |
262 end; |
262 end; |
263 |
263 |
264 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource); |
264 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource); |
265 begin |
265 begin |
|
266 if Hedgehog^.Effects[heFrozen] <> 0 then exit; |
266 if (Source = dsFall) or (Source = dsExplosion) then |
267 if (Source = dsFall) or (Source = dsExplosion) then |
267 case random(3) of |
268 case random(3) of |
268 0: PlaySoundV(sndOoff1, Hedgehog^.Team^.voicepack); |
269 0: PlaySoundV(sndOoff1, Hedgehog^.Team^.voicepack); |
269 1: PlaySoundV(sndOoff2, Hedgehog^.Team^.voicepack); |
270 1: PlaySoundV(sndOoff2, Hedgehog^.Team^.voicepack); |
270 2: PlaySoundV(sndOoff3, Hedgehog^.Team^.voicepack); |
271 2: PlaySoundV(sndOoff3, Hedgehog^.Team^.voicepack); |
287 var |
288 var |
288 dmg: Longword; |
289 dmg: Longword; |
289 i: LongWord; |
290 i: LongWord; |
290 particle: PVisualGear; |
291 particle: PVisualGear; |
291 begin |
292 begin |
292 if _0_4 < Gear^.dY then |
293 if _0_4 < Gear^.dY then |
293 begin |
294 begin |
294 dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear); |
295 dmg := ModifyDamage(1 + hwRound((Gear^.dY - _0_4) * 70), Gear); |
295 PlaySound(sndBump); |
296 if Gear^.Hedgehog^.Effects[heFrozen] = 0 then |
296 if dmg < 1 then |
297 PlaySound(sndBump) |
297 exit; |
298 else PlaySound(sndFrozenHogImpact); |
298 |
299 if dmg < 1 then |
299 for i:= min(12, (3 + dmg div 10)) downto 0 do |
300 exit; |
300 begin |
301 |
301 particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust); |
302 for i:= min(12, (3 + dmg div 10)) downto 0 do |
302 if particle <> nil then |
303 begin |
303 particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480); |
304 particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust); |
304 end; |
305 if particle <> nil then |
305 |
306 particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480); |
306 if (Gear^.Invulnerable) then |
307 end; |
307 exit; |
308 |
308 |
309 if (Gear^.Invulnerable) then |
309 //if _0_6 < Gear^.dY then |
310 exit; |
310 // PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack) |
311 |
311 //else |
312 //if _0_6 < Gear^.dY then |
312 // PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack); |
313 // PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack) |
313 |
314 //else |
314 if Gear^.LastDamage <> nil then |
315 // PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack); |
315 ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall) |
316 |
316 else |
317 if Gear^.LastDamage <> nil then |
317 ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall); |
318 ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall) |
|
319 else |
|
320 ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall); |
318 end |
321 end |
319 end; |
322 end; |
320 |
323 |
321 |
324 |
322 procedure CalcRotationDirAngle(Gear: PGear); |
325 procedure CalcRotationDirAngle(Gear: PGear); |
335 Gear^.DirAngle := Gear^.DirAngle + 360 |
338 Gear^.DirAngle := Gear^.DirAngle + 360 |
336 else if 360 < Gear^.DirAngle then |
339 else if 360 < Gear^.DirAngle then |
337 Gear^.DirAngle := Gear^.DirAngle - 360 |
340 Gear^.DirAngle := Gear^.DirAngle - 360 |
338 end; |
341 end; |
339 |
342 |
340 function CheckGearDrowning(Gear: PGear): boolean; |
343 function CheckGearDrowning(var Gear: PGear): boolean; |
341 var |
344 var |
342 skipSpeed, skipAngle, skipDecay: hwFloat; |
345 skipSpeed, skipAngle, skipDecay: hwFloat; |
343 i, maxDrops, X, Y: LongInt; |
346 i, maxDrops, X, Y: LongInt; |
344 vdX, vdY: real; |
347 vdX, vdY: real; |
345 particle, splash: PVisualGear; |
348 particle, splash: PVisualGear; |
346 isSubmersible: boolean; |
349 isSubmersible: boolean; |
359 Gear^.dY:= _90-(GetRandomf*_360) |
362 Gear^.dY:= _90-(GetRandomf*_360) |
360 end |
363 end |
361 else DeleteGear(Gear); |
364 else DeleteGear(Gear); |
362 exit |
365 exit |
363 end; |
366 end; |
364 isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack); |
367 isSubmersible:= ((Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0)) or (Gear^.State and gstSubmersible <> 0); |
365 skipSpeed := _0_25; |
368 skipSpeed := _0_25; |
366 skipAngle := _1_9; |
369 skipAngle := _1_9; |
367 skipDecay := _0_87; |
370 skipDecay := _0_87; |
368 X:= hwRound(Gear^.X); |
371 X:= hwRound(Gear^.X); |
369 vdX:= hwFloat2Float(Gear^.dX); |
372 vdX:= hwFloat2Float(Gear^.dX); |
370 vdY:= hwFloat2Float(Gear^.dY); |
373 vdY:= hwFloat2Float(Gear^.dY); |
371 // this could perhaps be a tiny bit higher. |
374 // this could perhaps be a tiny bit higher. |
372 if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) |
375 if (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) |
373 and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then |
376 and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then |
374 begin |
377 begin |
375 Gear^.dY.isNegative := true; |
378 Gear^.dY.isNegative := true; |
376 Gear^.dY := Gear^.dY * skipDecay; |
379 Gear^.dY := Gear^.dY * skipDecay; |
377 Gear^.dX := Gear^.dX * skipDecay; |
380 Gear^.dX := Gear^.dX * skipDecay; |
388 if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot) |
391 if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot) |
389 and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then |
392 and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then |
390 if Gear^.Kind = gtHedgehog then |
393 if Gear^.Kind = gtHedgehog then |
391 begin |
394 begin |
392 if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then |
395 if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then |
393 ResurrectHedgehog(Gear) |
396 begin |
|
397 // Gear could become nil after this, just exit to skip splashes |
|
398 ResurrectHedgehog(Gear); |
|
399 exit |
|
400 end |
394 else |
401 else |
395 begin |
402 begin |
396 Gear^.doStep := @doStepDrowningGear; |
403 Gear^.doStep := @doStepDrowningGear; |
397 Gear^.State := Gear^.State and (not gstHHDriven); |
404 Gear^.State := Gear^.State and (not gstHHDriven); |
398 AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage); |
405 AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage); |
399 end |
406 end |
400 end |
407 end |
401 else |
408 else |
402 Gear^.doStep := @doStepDrowningGear; |
409 Gear^.doStep := @doStepDrowningGear; |
403 if Gear^.Kind = gtFlake then |
410 if Gear^.Kind = gtFlake then |
404 exit // skip splashes |
411 exit // skip splashes |
405 end; |
412 end |
|
413 else if (Y > cWaterLine + cVisibleWater*4) and |
|
414 ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then |
|
415 Gear^.doStep:= @doStepDrowningGear; |
406 if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
416 if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
407 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0) |
417 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
408 and (CurAmmoGear^.dY < _0_01))) then |
418 and (CurAmmoGear^.dY < _0_01))) then |
409 if Gear^.Density * Gear^.dY > _1 then |
419 if Gear^.Density * Gear^.dY > _1 then |
410 PlaySound(sndSplash) |
420 PlaySound(sndSplash) |
411 else if Gear^.Density * Gear^.dY > _0_5 then |
421 else if Gear^.Density * Gear^.dY > _0_5 then |
412 PlaySound(sndSkip) |
422 PlaySound(sndSkip) |
414 PlaySound(sndDroplet2); |
424 PlaySound(sndDroplet2); |
415 end; |
425 end; |
416 |
426 |
417 if ((cReducedQuality and rqPlainSplash) = 0) |
427 if ((cReducedQuality and rqPlainSplash) = 0) |
418 and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
428 and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
419 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0) |
429 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
420 and (CurAmmoGear^.dY < _0_01)))) then |
430 and (CurAmmoGear^.dY < _0_01)))) then |
421 begin |
431 begin |
422 splash:= AddVisualGear(X, cWaterLine, vgtSplash); |
432 splash:= AddVisualGear(X, cWaterLine, vgtSplash); |
423 if splash <> nil then |
433 if splash <> nil then |
424 with splash^ do |
434 with splash^ do |
455 end |
465 end |
456 end |
466 end |
457 end |
467 end |
458 end |
468 end |
459 end; |
469 end; |
460 if isSubmersible and (CurAmmoGear^.Pos = 0) then |
470 if isSubmersible and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) then |
461 CurAmmoGear^.Pos := 1000 |
471 CurAmmoGear^.Pos := 1000 |
462 end |
472 end |
463 else |
473 else |
464 CheckGearDrowning := false; |
474 CheckGearDrowning := false; |
465 end; |
475 end; |
466 |
476 |
467 |
477 |
468 procedure ResurrectHedgehog(gear: PGear); |
478 procedure ResurrectHedgehog(var gear: PGear); |
469 var tempTeam : PTeam; |
479 var tempTeam : PTeam; |
470 sparkles: PVisualGear; |
480 sparkles: PVisualGear; |
471 gX, gY: LongInt; |
481 gX, gY: LongInt; |
472 begin |
482 begin |
473 if (Gear^.LastDamage <> nil) then |
483 if (Gear^.LastDamage <> nil) then |
505 AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion); |
515 AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion); |
506 PlaySound(sndWarp); |
516 PlaySound(sndWarp); |
507 RenderHealth(gear^.Hedgehog^); |
517 RenderHealth(gear^.Hedgehog^); |
508 ScriptCall('onGearResurrect', gear^.uid); |
518 ScriptCall('onGearResurrect', gear^.uid); |
509 gear^.State := gstWait; |
519 gear^.State := gstWait; |
510 end; |
520 end; |
511 RecountTeamHealth(tempTeam); |
521 RecountTeamHealth(tempTeam); |
512 end; |
522 end; |
513 |
523 |
514 function CountNonZeroz(x, y, r, c: LongInt; mask: LongWord): LongInt; |
524 function CountNonZeroz(x, y, r, c: LongInt; mask: LongWord): LongInt; |
515 var i: LongInt; |
525 var i: LongInt; |