133 ((Gear^.Health = 0) and |
134 ((Gear^.Health = 0) and |
134 (Gear^.Damage < 35)) or |
135 (Gear^.Damage < 35)) or |
135 ((Gear^.Health > 0) and |
136 ((Gear^.Health > 0) and |
136 (cMineDudPercent > 95) and |
137 (cMineDudPercent > 95) and |
137 (cMinesTime < 3000)) |
138 (cMinesTime < 3000)) |
138 ) and |
139 )) and |
139 (Targets.Count < 256) then |
140 (Targets.Count < 256) then |
140 begin |
141 begin |
141 with Targets.ar[Targets.Count] do |
142 with Targets.ar[Targets.Count] do |
142 begin |
143 begin |
143 skip:= false; |
144 skip:= false; |
144 dead:= false; |
145 dead:= false; |
145 Kind:= Gear^.Kind; |
146 Kind:= Gear^.Kind; |
|
147 Radius:= Gear^.Radius; |
|
148 Flags:= Gear^.State; |
146 matters:= (Gear^.AIHints and aihDoesntMatter) = 0; |
149 matters:= (Gear^.AIHints and aihDoesntMatter) = 0; |
147 |
150 |
148 Point.X:= hwRound(Gear^.X); |
151 Point.X:= hwRound(Gear^.X); |
149 Point.Y:= hwRound(Gear^.Y); |
152 Point.Y:= hwRound(Gear^.Y); |
150 if (Gear^.Kind = gtHedgehog) then |
153 if (Gear^.Kind = gtHedgehog) then |
364 TestCollExcludingMe:= TestCollWithEverything(x, y, r) |
367 TestCollExcludingMe:= TestCollWithEverything(x, y, r) |
365 end; |
368 end; |
366 |
369 |
367 |
370 |
368 |
371 |
369 function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord; Kind: TGearType): LongInt; |
372 function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord; Target: TTarget): LongInt; |
370 var skipLandCheck: boolean; |
373 var skipLandCheck: boolean; |
371 rCorner, dxdy: real; |
374 rCorner, dxdy, odX, odY: real; |
372 dmg, radius: LongInt; |
375 dmg: LongInt; |
373 begin |
376 begin |
|
377 odX:= dX; |
|
378 odY:= dY; |
374 skipLandCheck:= true; |
379 skipLandCheck:= true; |
375 if x - eX < 0 then dX:= -dX; |
380 if x - eX < 0 then dX:= -dX; |
376 if y - eY < 0 then dY:= -dY; |
381 if y - eY < 0 then dY:= -dY; |
377 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
382 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
378 if Kind = gtHedgehog then |
|
379 radius:= cHHRadius |
|
380 else if Kind = gtExplosives then |
|
381 radius:= 16 |
|
382 else if Kind = gtMine then |
|
383 radius:= 2; |
|
384 rCorner:= r * 0.75; |
383 rCorner:= r * 0.75; |
385 while true do |
384 while true do |
386 begin |
385 begin |
387 x:= x + dX; |
386 x:= x + dX; |
388 y:= y + dY; |
387 y:= y + dY; |
389 dY:= dY + cGravityf; |
388 dY:= dY + cGravityf; |
390 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
389 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
391 if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), radius) then |
390 if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
392 begin |
391 with Target do |
393 if (Kind = gtHedgehog) and (0.4 < dY) then |
392 begin |
394 begin |
393 if (Kind = gtHedgehog) and (0.4 < dY) then |
395 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
394 begin |
396 if dmg >= 1 then exit(dmg) |
395 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
397 end |
396 if dmg >= 1 then exit(dmg) |
398 else |
|
399 begin |
|
400 dxdy:= abs(dX)+abs(dY); |
|
401 // so we don't know at present if a barrel is already rolling. Would need to add that to target info I guess |
|
402 // a barrel oriented vertically only considers dY. however, AI doesn't know to use hammer, and could only bat vertically w/ bat, so probably shouldn't matter |
|
403 if (dxdy > 0.3) then |
|
404 begin |
|
405 dmg := 1 + trunc(dxdy * 25); |
|
406 exit(dmg) |
|
407 end |
397 end |
408 end; |
398 else |
|
399 begin |
|
400 dxdy:= abs(dX)+abs(dY); |
|
401 if ((Kind = gtMine) and (dxdy > 0.35)) or |
|
402 ((Kind = gtExplosives) and |
|
403 (((Flags and gstTmpFlag <> 0) and (dxdy > 0.35)) or |
|
404 ((Flags and gstTmpFlag <> 0) and |
|
405 ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and |
|
406 (abs(odX) > 0.02))) and (dxdy > 0.35)))) then |
|
407 begin |
|
408 dmg := 1 + trunc(dxdy * 25); |
|
409 exit(dmg) |
|
410 end |
|
411 else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then |
|
412 begin |
|
413 dmg := 1 + trunc(dy * 70); |
|
414 exit(dmg) |
|
415 end |
|
416 end; |
409 exit(0) |
417 exit(0) |
410 end; |
418 end; |
411 if (y > cWaterLine) or (x > leftX) or (x < rightX) then exit(-1) |
419 if (y > cWaterLine) or (x > leftX) or (x < rightX) then exit(-1) |
412 end |
420 end |
413 end; |
421 end; |
414 |
422 |
415 function TraceShoveFall(var x, y: Real; dX, dY: Real; Kind: TGearType): LongInt; |
423 function TraceShoveFall(var x, y: Real; dX, dY: Real; Target: TTarget): LongInt; |
416 var dmg, radius: LongInt; |
424 var dmg: LongInt; |
417 dxdy: real; |
425 dxdy, odX, odY: real; |
418 begin |
426 begin |
|
427 odX:= dX; |
|
428 odY:= dY; |
419 //v:= random($FFFFFFFF); |
429 //v:= random($FFFFFFFF); |
420 if Kind = gtHedgehog then |
|
421 radius:= cHHRadius |
|
422 else if Kind = gtExplosives then |
|
423 radius:= 16 |
|
424 else if Kind = gtMine then |
|
425 radius:= 2; |
|
426 while true do |
430 while true do |
427 begin |
431 begin |
428 x:= x + dX; |
432 x:= x + dX; |
429 y:= y + dY; |
433 y:= y + dY; |
430 dY:= dY + cGravityf; |
434 dY:= dY + cGravityf; |
433 begin |
437 begin |
434 LandPixels[trunc(y), trunc(x)]:= v; |
438 LandPixels[trunc(y), trunc(x)]:= v; |
435 UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); |
439 UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); |
436 end;} |
440 end;} |
437 |
441 |
438 |
442 if TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
439 // consider adding dX/dY calc here for fall damage |
443 with Target do |
440 if TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then |
444 begin |
441 begin |
445 if (Kind = gtHedgehog) and (0.4 < dY) then |
442 if (Kind = gtHedgehog) and (0.4 < dY) then |
446 begin |
443 begin |
447 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
444 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
448 if dmg >= 1 then |
445 if dmg >= 1 then |
449 exit(dmg); |
446 exit(dmg); |
|
447 end |
|
448 else |
|
449 begin |
|
450 dxdy:= abs(dX)+abs(dY); |
|
451 // so we don't know at present if a barrel is already rolling. Would need to add that to target info I guess |
|
452 // a barrel oriented vertically only considers dY. however, AI doesn't know to use hammer, and could only bat vertically w/ bat, so probably shouldn't matter |
|
453 if (dxdy > 0.3) then |
|
454 begin |
|
455 dmg := 1 + trunc(dxdy * 25); |
|
456 exit(dmg) |
|
457 end |
450 end |
458 end; |
451 else |
|
452 begin |
|
453 dxdy:= abs(dX)+abs(dY); |
|
454 if ((Kind = gtMine) and (dxdy > 0.35)) or |
|
455 ((Kind = gtExplosives) and |
|
456 (((Flags and gstTmpFlag <> 0) and (dxdy > 0.35)) or |
|
457 ((Flags and gstTmpFlag <> 0) and |
|
458 ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and |
|
459 (abs(odX) > 0.02))) and (dxdy > 0.35)))) then |
|
460 begin |
|
461 dmg := 1 + trunc(dxdy * 25); |
|
462 exit(dmg) |
|
463 end |
|
464 else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then |
|
465 begin |
|
466 dmg := 1 + trunc(dy * 70); |
|
467 exit(dmg) |
|
468 end |
|
469 end; |
459 exit(0) |
470 exit(0) |
460 end; |
471 end; |
461 if (y > cWaterLine) or (x > leftX) or (x < rightX) then |
472 if (y > cWaterLine) or (x > leftX) or (x < rightX) then |
462 // returning -1 for drowning so it can be considered in the Rate routine |
473 // returning -1 for drowning so it can be considered in the Rate routine |
463 exit(-1) |
474 exit(-1) |
513 |
524 |
514 if dmg > 0 then |
525 if dmg > 0 then |
515 begin |
526 begin |
516 pX:= Point.x; |
527 pX:= Point.x; |
517 pY:= Point.y; |
528 pY:= Point.y; |
|
529 fallDmg:= 0; |
518 if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then |
530 if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then |
519 begin |
531 begin |
520 dX:= (0.005 * dmg + 0.01) / Density; |
532 dX:= (0.005 * dmg + 0.01) / Density; |
521 dY:= dX; |
533 dY:= dX; |
522 if (Kind = gtExplosives) and |
534 if (Kind = gtExplosives) and |
523 (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or |
535 (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or |
524 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
536 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
525 dX:= 0; |
537 dX:= 0; |
526 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
538 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
527 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
539 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
528 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Kind) * dmgMod) |
540 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod) |
529 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Kind) * dmgMod) |
541 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod) |
530 end; |
542 end; |
531 if Kind = gtHedgehog then |
543 if Kind = gtHedgehog then |
532 begin |
544 begin |
533 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
545 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
534 begin |
546 begin |
555 if Score > 0 then |
567 if Score > 0 then |
556 inc(rate, (dmg + fallDmg) * 1024) |
568 inc(rate, (dmg + fallDmg) * 1024) |
557 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
569 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
558 end |
570 end |
559 end |
571 end |
560 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly |
572 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
561 else if (Kind <> gtHedgehog) and (FallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
562 begin |
573 begin |
563 dead:= true; |
574 dead:= true; |
564 Targets.reset:= true; |
575 Targets.reset:= true; |
565 if Kind = gtExplosives then |
576 if Kind = gtExplosives then |
566 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
577 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
596 |
607 |
597 if dmg > 0 then |
608 if dmg > 0 then |
598 begin |
609 begin |
599 pX:= Point.x; |
610 pX:= Point.x; |
600 pY:= Point.y-2; |
611 pY:= Point.y-2; |
|
612 fallDmg:= 0; |
601 if (Flags and afSetSkip <> 0) then skip:= true; |
613 if (Flags and afSetSkip <> 0) then skip:= true; |
602 if (Flags and afTrackFall <> 0) and (Score > 0) then |
614 if (Flags and afTrackFall <> 0) and (Score > 0) then |
603 fallDmg:= trunc(TraceShoveFall(pX, pY, dX, dY, Kind) * dmgMod); |
615 fallDmg:= trunc(TraceShoveFall(pX, pY, dX, dY, Targets.ar[i]) * dmgMod); |
604 if Kind = gtHedgehog then |
616 if Kind = gtHedgehog then |
605 begin |
617 begin |
606 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
618 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
607 begin |
619 begin |
608 if Score > 0 then |
620 if Score > 0 then |
630 inc(rate, power+fallDmg) |
642 inc(rate, power+fallDmg) |
631 else |
643 else |
632 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
644 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
633 end |
645 end |
634 end |
646 end |
635 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly |
647 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
636 else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((power+fallDmg) >= Score) then |
|
637 begin |
648 begin |
638 dead:= true; |
649 dead:= true; |
639 Targets.reset:= true; |
650 Targets.reset:= true; |
640 if Kind = gtExplosives then |
651 if Kind = gtExplosives then |
641 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
652 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
694 dY:= gdY * dmg / Density; |
705 dY:= gdY * dmg / Density; |
695 if dX < 0 then dX:= dX - 0.01 |
706 if dX < 0 then dX:= dX - 0.01 |
696 else dX:= dX + 0.01; |
707 else dX:= dX + 0.01; |
697 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
708 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
698 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
709 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
699 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Kind) * dmgMod) |
710 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod) |
700 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Kind) * dmgMod); |
711 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod); |
701 if Kind = gtHedgehog then |
712 if Kind = gtHedgehog then |
702 begin |
713 begin |
703 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
714 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
704 begin |
715 begin |
705 if Score > 0 then |
716 if Score > 0 then |
723 end |
734 end |
724 else if Score > 0 then |
735 else if Score > 0 then |
725 inc(rate, dmg+fallDmg) |
736 inc(rate, dmg+fallDmg) |
726 else dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
737 else dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
727 end |
738 end |
728 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly |
739 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
729 else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
730 begin |
740 begin |
731 dead:= true; |
741 dead:= true; |
732 Targets.reset:= true; |
742 Targets.reset:= true; |
733 if Kind = gtExplosives then |
743 if Kind = gtExplosives then |
734 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or afTrackFall) |
744 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or afTrackFall) |