21 unit uGearsUtils; |
21 unit uGearsUtils; |
22 interface |
22 interface |
23 uses uTypes, uFloat; |
23 uses uTypes, uFloat; |
24 |
24 |
25 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline; |
25 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline; |
26 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord); |
26 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord); |
27 |
27 |
28 function ModifyDamage(dmg: Longword; Gear: PGear): Longword; |
28 function ModifyDamage(dmg: Longword; Gear: PGear): Longword; |
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); |
45 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS; |
45 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS; |
46 procedure SpawnBoxOfSmth; |
46 procedure SpawnBoxOfSmth; |
47 procedure ShotgunShot(Gear: PGear); |
47 procedure ShotgunShot(Gear: PGear); |
48 |
48 |
49 procedure SetAllToActive; |
49 procedure SetAllToActive; |
50 procedure SetAllHHToActive; inline; |
|
51 procedure SetAllHHToActive(Ice: boolean); |
50 procedure SetAllHHToActive(Ice: boolean); |
|
51 procedure SetAllHHToActive(); inline; |
52 |
52 |
53 function GetAmmo(Hedgehog: PHedgehog): TAmmoType; |
53 function GetAmmo(Hedgehog: PHedgehog): TAmmoType; |
54 function GetUtility(Hedgehog: PHedgehog): TAmmoType; |
54 function GetUtility(Hedgehog: PHedgehog): TAmmoType; |
55 |
55 |
56 function WorldWrap(var Gear: PGear): boolean; |
56 function WorldWrap(var Gear: PGear): boolean; |
62 var doStepHandlers: array[TGearType] of TGearStepProcedure; |
62 var doStepHandlers: array[TGearType] of TGearStepProcedure; |
63 |
63 |
64 implementation |
64 implementation |
65 uses uSound, uCollisions, uUtils, uConsts, uVisualGears, uAIMisc, |
65 uses uSound, uCollisions, uUtils, uConsts, uVisualGears, uAIMisc, |
66 uVariables, uLandGraphics, uScript, uStats, uCaptions, uTeams, uStore, |
66 uVariables, uLandGraphics, uScript, uStats, uCaptions, uTeams, uStore, |
67 uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, |
67 uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, |
68 uGearsList, Math, uVisualGearsList, uGearsHandlersMess, |
68 uGearsList, Math, uVisualGearsList, uGearsHandlersMess, |
69 uGearsHedgehog; |
69 uGearsHedgehog; |
70 |
70 |
71 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline; |
71 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline; |
72 begin |
72 begin |
197 King check should be in here instead of ApplyDamage since Tiy wants them kicked less |
197 King check should be in here instead of ApplyDamage since Tiy wants them kicked less |
198 *) |
198 *) |
199 i:= _1; |
199 i:= _1; |
200 if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then |
200 if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then |
201 i:= _1_5; |
201 i:= _1_5; |
202 if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog <> nil) and |
202 if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog <> nil) and |
203 (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then |
203 (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then |
204 ModifyDamage:= hwRound(cDamageModifier * dmg * i * cDamagePercent * _0_5 * _0_01) |
204 ModifyDamage:= hwRound(cDamageModifier * dmg * i * cDamagePercent * _0_5 * _0_01) |
205 else |
205 else |
206 ModifyDamage:= hwRound(cDamageModifier * dmg * i * cDamagePercent * _0_01) |
206 ModifyDamage:= hwRound(cDamageModifier * dmg * i * cDamagePercent * _0_01) |
207 end; |
207 end; |
249 end; |
249 end; |
250 inc(i, 5); |
250 inc(i, 5); |
251 end; |
251 end; |
252 end |
252 end |
253 end; |
253 end; |
254 if (GameFlags and gfKarma <> 0) and (GameFlags and gfInvulnerable = 0) and |
254 if (GameFlags and gfKarma <> 0) and (GameFlags and gfInvulnerable = 0) and |
255 (CurrentHedgehog^.Effects[heInvulnerable] = 0) then |
255 (CurrentHedgehog^.Effects[heInvulnerable] = 0) then |
256 begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid |
256 begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid |
257 inc(CurrentHedgehog^.Gear^.Karma, tmpDmg); |
257 inc(CurrentHedgehog^.Gear^.Karma, tmpDmg); |
258 CurrentHedgehog^.Gear^.LastDamage := CurrentHedgehog; |
258 CurrentHedgehog^.Gear^.LastDamage := CurrentHedgehog; |
259 spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg); |
259 spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg); |
260 end; |
260 end; |
261 uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false); |
261 uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false); |
262 end; |
262 end; |
263 end else |
263 end else |
264 //else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure |
264 //else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure |
265 Gear^.Hedgehog:= AttackerHog; |
265 Gear^.Hedgehog:= AttackerHog; |
266 inc(Gear^.Damage, Damage); |
266 inc(Gear^.Damage, Damage); |
267 |
267 |
268 ScriptCall('onGearDamage', Gear^.UID, Damage); |
268 ScriptCall('onGearDamage', Gear^.UID, Damage); |
269 end; |
269 end; |
270 |
270 |
271 procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword); |
271 procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword); |
272 var tag: PVisualGear; |
272 var tag: PVisualGear; |
275 if (tag <> nil) then |
275 if (tag <> nil) then |
276 tag^.Hedgehog:= HHGear^.Hedgehog; // the tag needs the tag to determine the text color |
276 tag^.Hedgehog:= HHGear^.Hedgehog; // the tag needs the tag to determine the text color |
277 AllInactive:= false; |
277 AllInactive:= false; |
278 HHGear^.Active:= true; |
278 HHGear^.Active:= true; |
279 end; |
279 end; |
280 |
280 |
281 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource); |
281 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource); |
282 begin |
282 begin |
283 if Hedgehog^.Effects[heFrozen] <> 0 then exit; |
283 if Hedgehog^.Effects[heFrozen] <> 0 then exit; |
284 if (Source = dsFall) or (Source = dsExplosion) then |
284 if (Source = dsFall) or (Source = dsExplosion) then |
285 case random(3) of |
285 case random(3) of |
338 end |
338 end |
339 end; |
339 end; |
340 |
340 |
341 |
341 |
342 procedure CalcRotationDirAngle(Gear: PGear); |
342 procedure CalcRotationDirAngle(Gear: PGear); |
343 var |
343 var |
344 dAngle: real; |
344 dAngle: real; |
345 begin |
345 begin |
346 // Frac/Round to be kind to JS as of 2012-08-27 where there is yet no int64/uint64 |
346 // Frac/Round to be kind to JS as of 2012-08-27 where there is yet no int64/uint64 |
347 //dAngle := (Gear^.dX.QWordValue + Gear^.dY.QWordValue) / $80000000; |
347 //dAngle := (Gear^.dX.QWordValue + Gear^.dY.QWordValue) / $80000000; |
348 dAngle := (Gear^.dX.Round + Gear^.dY.Round) / 2 + (Gear^.dX.Frac/$100000000+Gear^.dY.Frac/$100000000); |
348 dAngle := (Gear^.dX.Round + Gear^.dY.Round) / 2 + (Gear^.dX.Frac/$100000000+Gear^.dY.Frac/$100000000); |
356 else if 360 < Gear^.DirAngle then |
356 else if 360 < Gear^.DirAngle then |
357 Gear^.DirAngle := Gear^.DirAngle - 360 |
357 Gear^.DirAngle := Gear^.DirAngle - 360 |
358 end; |
358 end; |
359 |
359 |
360 function CheckGearDrowning(var Gear: PGear): boolean; |
360 function CheckGearDrowning(var Gear: PGear): boolean; |
361 var |
361 var |
362 skipSpeed, skipAngle, skipDecay: hwFloat; |
362 skipSpeed, skipAngle, skipDecay: hwFloat; |
363 i, maxDrops, X, Y: LongInt; |
363 i, maxDrops, X, Y: LongInt; |
364 vdX, vdY: real; |
364 vdX, vdY: real; |
365 particle, splash: PVisualGear; |
365 particle, splash: PVisualGear; |
366 isSubmersible: boolean; |
366 isSubmersible: boolean; |
387 skipDecay := _0_87; |
387 skipDecay := _0_87; |
388 X:= hwRound(Gear^.X); |
388 X:= hwRound(Gear^.X); |
389 vdX:= hwFloat2Float(Gear^.dX); |
389 vdX:= hwFloat2Float(Gear^.dX); |
390 vdY:= hwFloat2Float(Gear^.dY); |
390 vdY:= hwFloat2Float(Gear^.dY); |
391 // this could perhaps be a tiny bit higher. |
391 // this could perhaps be a tiny bit higher. |
392 if (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) |
392 if (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) |
393 and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then |
393 and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then |
394 begin |
394 begin |
395 Gear^.dY.isNegative := true; |
395 Gear^.dY.isNegative := true; |
396 Gear^.dY := Gear^.dY * skipDecay; |
396 Gear^.dY := Gear^.dY * skipDecay; |
397 Gear^.dX := Gear^.dX * skipDecay; |
397 Gear^.dX := Gear^.dX * skipDecay; |
423 end |
423 end |
424 end |
424 end |
425 else |
425 else |
426 Gear^.doStep := @doStepDrowningGear; |
426 Gear^.doStep := @doStepDrowningGear; |
427 if Gear^.Kind = gtFlake then |
427 if Gear^.Kind = gtFlake then |
428 exit // skip splashes |
428 exit // skip splashes |
429 end |
429 end |
430 else if (Y > cWaterLine + cVisibleWater*4) and |
430 else if (Y > cWaterLine + cVisibleWater*4) and |
431 ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then |
431 ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then |
432 Gear^.doStep:= @doStepDrowningGear; |
432 Gear^.doStep:= @doStepDrowningGear; |
433 if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
433 if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
434 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
434 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
435 and (CurAmmoGear^.dY < _0_01))) then |
435 and (CurAmmoGear^.dY < _0_01))) then |
436 if Gear^.Density * Gear^.dY > _1 then |
436 if Gear^.Density * Gear^.dY > _1 then |
437 PlaySound(sndSplash) |
437 PlaySound(sndSplash) |
438 else if Gear^.Density * Gear^.dY > _0_5 then |
438 else if Gear^.Density * Gear^.dY > _0_5 then |
439 PlaySound(sndSkip) |
439 PlaySound(sndSkip) |
440 else |
440 else |
441 PlaySound(sndDroplet2); |
441 PlaySound(sndDroplet2); |
442 end; |
442 end; |
443 |
443 |
445 and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
445 and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
446 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
446 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
447 and (CurAmmoGear^.dY < _0_01)))) then |
447 and (CurAmmoGear^.dY < _0_01)))) then |
448 begin |
448 begin |
449 splash:= AddVisualGear(X, cWaterLine, vgtSplash); |
449 splash:= AddVisualGear(X, cWaterLine, vgtSplash); |
450 if splash <> nil then |
450 if splash <> nil then |
451 with splash^ do |
451 with splash^ do |
452 begin |
452 begin |
453 Scale:= hwFloat2Float(Gear^.Density / _3 * Gear^.dY); |
453 Scale:= hwFloat2Float(Gear^.Density / _3 * Gear^.dY); |
454 if Scale > 1 then Scale:= power(Scale,0.3333) |
454 if Scale > 1 then Scale:= power(Scale,0.3333) |
455 else Scale:= Scale + ((1-Scale) / 2); |
455 else Scale:= Scale + ((1-Scale) / 2); |
468 begin |
468 begin |
469 dX := dX - vdX / 10; |
469 dX := dX - vdX / 10; |
470 dY := dY - vdY / 5; |
470 dY := dY - vdY / 5; |
471 if splash <> nil then |
471 if splash <> nil then |
472 begin |
472 begin |
473 if splash^.Scale > 1 then |
473 if splash^.Scale > 1 then |
474 begin |
474 begin |
475 dX:= dX * power(splash^.Scale,0.3333); // tone down the droplet height further |
475 dX:= dX * power(splash^.Scale,0.3333); // tone down the droplet height further |
476 dY:= dY * power(splash^.Scale, 0.3333) |
476 dY:= dY * power(splash^.Scale, 0.3333) |
477 end |
477 end |
478 else |
478 else |
479 begin |
479 begin |
480 dX:= dX * splash^.Scale; |
480 dX:= dX * splash^.Scale; |
481 dY:= dY * splash^.Scale |
481 dY:= dY * splash^.Scale |
482 end |
482 end |
483 end |
483 end |
487 if isSubmersible and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) then |
487 if isSubmersible and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) then |
488 CurAmmoGear^.Pos := 1000 |
488 CurAmmoGear^.Pos := 1000 |
489 end |
489 end |
490 else |
490 else |
491 begin |
491 begin |
492 if not (Gear^.Kind in [gtJetpack, gtBee]) then Gear^.State:= Gear^.State and not gstSubmersible; // making it temporary for most gears is more attractive I think |
492 if (not ((Gear^.Kind = gtJetpack) or (Gear^.Kind = gtBee))) then |
|
493 Gear^.State:= (Gear^.State and (not gstSubmersible)); // making it temporary for most gears is more attractive I think |
493 CheckGearDrowning := false |
494 CheckGearDrowning := false |
494 end |
495 end |
495 end; |
496 end; |
496 |
497 |
497 |
498 |
510 gear^.Damage := 0; |
511 gear^.Damage := 0; |
511 gear^.Health := gear^.Hedgehog^.InitialHealth; |
512 gear^.Health := gear^.Hedgehog^.InitialHealth; |
512 gear^.Hedgehog^.Effects[hePoisoned] := 0; |
513 gear^.Hedgehog^.Effects[hePoisoned] := 0; |
513 if (CurrentHedgehog^.Effects[heResurrectable] = 0) or ((CurrentHedgehog^.Effects[heResurrectable] <> 0) |
514 if (CurrentHedgehog^.Effects[heResurrectable] = 0) or ((CurrentHedgehog^.Effects[heResurrectable] <> 0) |
514 and (Gear^.Hedgehog^.Team^.Clan <> CurrentHedgehog^.Team^.Clan)) then |
515 and (Gear^.Hedgehog^.Team^.Clan <> CurrentHedgehog^.Team^.Clan)) then |
515 with CurrentHedgehog^ do |
516 with CurrentHedgehog^ do |
516 begin |
517 begin |
517 inc(Team^.stats.AIKills); |
518 inc(Team^.stats.AIKills); |
518 FreeTexture(Team^.AIKillsTex); |
519 FreeTexture(Team^.AIKillsTex); |
519 Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16); |
520 Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16); |
520 end; |
521 end; |
527 if sparkles <> nil then |
528 if sparkles <> nil then |
528 begin |
529 begin |
529 sparkles^.Tint:= tempTeam^.Clan^.Color shl 8 or $FF; |
530 sparkles^.Tint:= tempTeam^.Clan^.Color shl 8 or $FF; |
530 //sparkles^.Angle:= random(360); |
531 //sparkles^.Angle:= random(360); |
531 end; |
532 end; |
532 FindPlace(gear, false, 0, LAND_WIDTH, true); |
533 FindPlace(gear, false, 0, LAND_WIDTH, true); |
533 if gear <> nil then |
534 if gear <> nil then |
534 begin |
535 begin |
535 AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion); |
536 AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion); |
536 PlaySound(sndWarp); |
537 PlaySound(sndWarp); |
537 RenderHealth(gear^.Hedgehog^); |
538 RenderHealth(gear^.Hedgehog^); |
585 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean); |
586 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean); |
586 var x: LongInt; |
587 var x: LongInt; |
587 y, sy: LongInt; |
588 y, sy: LongInt; |
588 ar: array[0..1023] of TPoint; |
589 ar: array[0..1023] of TPoint; |
589 ar2: array[0..2047] of TPoint; |
590 ar2: array[0..2047] of TPoint; |
|
591 temp: TPoint; |
590 cnt, cnt2: Longword; |
592 cnt, cnt2: Longword; |
591 delta: LongInt; |
593 delta: LongInt; |
592 ignoreNearObjects, ignoreOverlap, tryAgain: boolean; |
594 ignoreNearObjects, ignoreOverlap, tryAgain: boolean; |
593 begin |
595 begin |
594 ignoreNearObjects:= false; // try not skipping proximity at first |
596 ignoreNearObjects:= false; // try not skipping proximity at first |
595 ignoreOverlap:= false; // this not only skips proximity, but allows overlapping objects (barrels, mines, hogs, crates). Saving it for a 3rd pass. With this active, winning AI Survival goes back to virtual impossibility |
597 ignoreOverlap:= false; // this not only skips proximity, but allows overlapping objects (barrels, mines, hogs, crates). Saving it for a 3rd pass. With this active, winning AI Survival goes back to virtual impossibility |
596 tryAgain:= true; |
598 tryAgain:= true; |
597 if WorldEdge <> weNone then |
599 if WorldEdge <> weNone then |
598 begin |
600 begin |
599 Left:= max(Left, LongInt(leftX) + Gear^.Radius); |
601 Left:= max(Left, LongInt(leftX) + Gear^.Radius); |
600 Right:= min(Right,rightX-Gear^.Radius) |
602 Right:= min(Right,rightX-Gear^.Radius) |
601 end; |
603 end; |
602 while tryAgain do |
604 while tryAgain do |
612 while y < cWaterLine do |
614 while y < cWaterLine do |
613 begin |
615 begin |
614 repeat |
616 repeat |
615 inc(y, 2); |
617 inc(y, 2); |
616 until (y >= cWaterLine) or |
618 until (y >= cWaterLine) or |
617 (not ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) = 0)) or |
619 ((not ignoreOverlap) and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) = 0)) or |
618 (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) = 0)); |
620 (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) = 0)); |
619 |
621 |
620 sy:= y; |
622 sy:= y; |
621 |
623 |
622 repeat |
624 repeat |
623 inc(y); |
625 inc(y); |
624 until (y >= cWaterLine) or |
626 until (y >= cWaterLine) or |
625 (not ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) <> 0)) or |
627 ((not ignoreOverlap) and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) <> 0)) or |
626 (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) <> 0)); |
628 (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) <> 0)); |
627 |
629 |
628 if (y - sy > Gear^.Radius * 2) |
630 if (y - sy > Gear^.Radius * 2) |
629 and (((Gear^.Kind = gtExplosives) |
631 and (((Gear^.Kind = gtExplosives) |
630 and (y < cWaterLine) |
632 and (y < cWaterLine) |
631 and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60)) |
633 and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60)) |
665 if ignoreNearObjects then ignoreOverlap:= true; |
670 if ignoreNearObjects then ignoreOverlap:= true; |
666 ignoreNearObjects:= true; |
671 ignoreNearObjects:= true; |
667 end; |
672 end; |
668 |
673 |
669 if cnt2 > 0 then |
674 if cnt2 > 0 then |
670 with ar2[GetRandom(cnt2)] do |
675 begin |
|
676 temp := ar2[GetRandom(cnt2)]; |
|
677 with temp do |
671 begin |
678 begin |
672 Gear^.X:= int2hwFloat(x); |
679 Gear^.X:= int2hwFloat(x); |
673 Gear^.Y:= int2hwFloat(y); |
680 Gear^.Y:= int2hwFloat(y); |
674 AddFileLog('Assigned Gear coordinates (' + inttostr(x) + ',' + inttostr(y) + ')'); |
681 AddFileLog('Assigned Gear coordinates (' + inttostr(x) + ',' + inttostr(y) + ')'); |
675 end |
682 end |
|
683 end |
676 else |
684 else |
677 begin |
685 begin |
678 OutError('Can''t find place for Gear', false); |
686 OutError('Can''t find place for Gear', false); |
679 if Gear^.Kind = gtHedgehog then |
687 if Gear^.Kind = gtHedgehog then |
680 Gear^.Hedgehog^.Effects[heResurrectable] := 0; |
688 Gear^.Hedgehog^.Effects[heResurrectable] := 0; |
716 procedure CheckCollisionWithLand(Gear: PGear); inline; |
724 procedure CheckCollisionWithLand(Gear: PGear); inline; |
717 begin |
725 begin |
718 if (TestCollisionX(Gear, hwSign(Gear^.dX)) <> 0) |
726 if (TestCollisionX(Gear, hwSign(Gear^.dX)) <> 0) |
719 or (TestCollisionY(Gear, hwSign(Gear^.dY)) <> 0) then |
727 or (TestCollisionY(Gear, hwSign(Gear^.dY)) <> 0) then |
720 Gear^.State := Gear^.State or gstCollision |
728 Gear^.State := Gear^.State or gstCollision |
721 else |
729 else |
722 Gear^.State := Gear^.State and (not gstCollision) |
730 Gear^.State := Gear^.State and (not gstCollision) |
723 end; |
731 end; |
724 |
732 |
725 function MakeHedgehogsStep(Gear: PGear) : boolean; |
733 function MakeHedgehogsStep(Gear: PGear) : boolean; |
726 begin |
734 begin |
885 Ammo^.Health:= 0; |
893 Ammo^.Health:= 0; |
886 while i > 0 do |
894 while i > 0 do |
887 begin |
895 begin |
888 dec(i); |
896 dec(i); |
889 Gear:= t^.ar[i]; |
897 Gear:= t^.ar[i]; |
890 if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and |
898 if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and |
891 (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then |
899 (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then |
892 Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000); |
900 Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000); |
893 tmpDmg:= ModifyDamage(Damage, Gear); |
901 tmpDmg:= ModifyDamage(Damage, Gear); |
894 if (Gear^.State and gstNoDamage) = 0 then |
902 if (Gear^.State and gstNoDamage) = 0 then |
895 begin |
903 begin |
896 |
904 |
897 if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then |
905 if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then |
898 begin |
906 begin |
899 VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit); |
907 VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit); |
900 if VGear <> nil then |
908 if VGear <> nil then |
901 VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY); |
909 VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY); |
902 end; |
910 end; |
943 end; |
951 end; |
944 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove) |
952 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove) |
945 end |
953 end |
946 else |
954 else |
947 Gear^.State:= Gear^.State or gstWinner; |
955 Gear^.State:= Gear^.State or gstWinner; |
948 if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then |
956 if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then |
949 begin |
957 begin |
950 if (Ammo^.Hedgehog^.Gear <> nil) then |
958 if (Ammo^.Hedgehog^.Gear <> nil) then |
951 Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable); |
959 Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable); |
952 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch |
960 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch |
953 end; |
961 end; |
1239 begin |
1247 begin |
1240 LeftImpactTimer:= 333; |
1248 LeftImpactTimer:= 333; |
1241 Gear^.dX.isNegative:= false; |
1249 Gear^.dX.isNegative:= false; |
1242 Gear^.X:= int2hwfloat(LongInt(leftX) + Gear^.Radius) |
1250 Gear^.X:= int2hwfloat(LongInt(leftX) + Gear^.Radius) |
1243 end |
1251 end |
1244 else |
1252 else |
1245 begin |
1253 begin |
1246 RightImpactTimer:= 333; |
1254 RightImpactTimer:= 333; |
1247 Gear^.dX.isNegative:= true; |
1255 Gear^.dX.isNegative:= true; |
1248 Gear^.X:= int2hwfloat(rightX-Gear^.Radius) |
1256 Gear^.X:= int2hwfloat(rightX-Gear^.Radius) |
1249 end; |
1257 end; |
1251 PlaySound(sndMelonImpact) |
1259 PlaySound(sndMelonImpact) |
1252 end |
1260 end |
1253 else if WorldEdge = weSea then |
1261 else if WorldEdge = weSea then |
1254 begin |
1262 begin |
1255 if (hwRound(Gear^.Y) > cWaterLine) and (Gear^.State and gstSubmersible <> 0) then |
1263 if (hwRound(Gear^.Y) > cWaterLine) and (Gear^.State and gstSubmersible <> 0) then |
1256 Gear^.State:= Gear^.State and not gstSubmersible |
1264 Gear^.State:= Gear^.State and (not gstSubmersible) |
1257 else |
1265 else |
1258 begin |
1266 begin |
1259 Gear^.State:= Gear^.State or gstSubmersible; |
1267 Gear^.State:= Gear^.State or gstSubmersible; |
1260 Gear^.X:= int2hwFloat(PlayWidth)*int2hwFloat(min(max(0,hwRound(Gear^.Y)),PlayHeight))/PlayHeight; |
1268 Gear^.X:= int2hwFloat(PlayWidth)*int2hwFloat(min(max(0,hwRound(Gear^.Y)),PlayHeight))/PlayHeight; |
1261 Gear^.Y:= int2hwFloat(cWaterLine+cVisibleWater+Gear^.Radius*2); |
1269 Gear^.Y:= int2hwFloat(cWaterLine+cVisibleWater+Gear^.Radius*2); |
1267 end; |
1275 end; |
1268 (* |
1276 (* |
1269 * Window in the sky (Gear moved high into the sky, Y is used to determine X) [unfortunately, not a safe thing to do. shame, I thought aerial bombardment would be kinda neat |
1277 * Window in the sky (Gear moved high into the sky, Y is used to determine X) [unfortunately, not a safe thing to do. shame, I thought aerial bombardment would be kinda neat |
1270 This one would be really easy to freeze game unless it was flagged unfortunately. |
1278 This one would be really easy to freeze game unless it was flagged unfortunately. |
1271 |
1279 |
1272 else |
1280 else |
1273 begin |
1281 begin |
1274 Gear^.X:= int2hwFloat(PlayWidth)*int2hwFloat(min(max(0,hwRound(Gear^.Y)),PlayHeight))/PlayHeight; |
1282 Gear^.X:= int2hwFloat(PlayWidth)*int2hwFloat(min(max(0,hwRound(Gear^.Y)),PlayHeight))/PlayHeight; |
1275 Gear^.Y:= -_2048-_256-_256; |
1283 Gear^.Y:= -_2048-_256-_256; |
1276 tdx:= Gear^.dX; |
1284 tdx:= Gear^.dX; |
1277 Gear^.dX:= Gear^.dY; |
1285 Gear^.dX:= Gear^.dY; |