gzdoom/wadsrc/static/zscript/actors/hexen/flies.zs

130 lines
2.9 KiB
Text

// Buzzy fly ----------------------------------------------------------------
class LittleFly : Actor
{
Default
{
+NOBLOCKMAP +NOGRAVITY
+CANPASS
Speed 6;
Radius 5;
Height 5;
Mass 2;
ActiveSound "FlyBuzz";
}
States
{
Spawn:
TNT1 A 20 A_FlySearch; // [RH] Invisible when not flying
Loop;
Buzz:
AFLY ABCD 3 A_FlyBuzz;
Loop;
}
//===========================================================================
//
// FindCorpse
//
// Finds a corpse to buzz around. We can't use a blockmap check because
// corpses generally aren't linked into the blockmap.
//
//===========================================================================
private Actor FindCorpse(sector sec, int recurselimit)
{
Actor fallback = null;
sec.validcount = validcount;
// Search the current sector
for (Actor check = sec.thinglist; check != null; check = check.snext)
{
if (check == self)
continue;
if (!check.bCorpse)
continue;
if (!CheckSight(check))
continue;
fallback = check;
if (random[Fly](0,1)) // 50% chance to try to pick a different corpse
continue;
return check;
}
if (--recurselimit <= 0 || (fallback != null && random[Fly](0,1)))
{
return fallback;
}
// Try neighboring sectors
for (int i = 0; i < sec.lines.Size(); ++i)
{
line ln = sec.lines[i];
sector sec2 = (ln.frontsector == sec) ? ln.backsector : ln.frontsector;
if (sec2 != null && sec2.validcount != validcount)
{
Actor neighbor = FindCorpse(sec2, recurselimit);
if (neighbor != null)
{
return neighbor;
}
}
}
return fallback;
}
void A_FlySearch()
{
// The version from the retail beta is not so great for general use:
// 1. Pick one of the first fifty thinkers at random.
// 2. Starting from that thinker, find one that is an actor, not itself,
// and within sight. Give up after 100 sequential thinkers.
// It's effectively useless if there are more than 150 thinkers on a map.
//
// So search the sectors instead. We can't potentially find something all
// the way on the other side of the map and we can't find invisible corpses,
// but at least we aren't crippled on maps with lots of stuff going on.
validcount++;
Actor other = FindCorpse(CurSector, 5);
if (other != null)
{
target = other;
SetStateLabel("Buzz");
}
}
void A_FlyBuzz()
{
Actor targ = target;
if (targ == null || !targ.bCorpse || random[Fly]() < 5)
{
SetIdle();
return;
}
Angle = AngleTo(targ);
args[0]++;
if (!TryMove(Pos.XY + AngleToVector(angle, 6), true))
{
SetIdle(true);
return;
}
if (args[0] & 2)
{
Vel.X += (random[Fly]() - 128) / 512.;
Vel.Y += (random[Fly]() - 128) / 512.;
}
int zrand = random[Fly]();
if (targ.pos.Z + 5. < pos.z && zrand > 150)
{
zrand = -zrand;
}
Vel.Z = zrand / 512.;
if (random[Fly]() < 40)
{
A_StartSound(ActiveSound, CHAN_VOICE, CHANF_DEFAULT, 0.5f, ATTN_STATIC);
}
}
}