qzdoom-gpl/wadsrc/static/zscript/hexen/flies.txt
Christoph Oelckers de6969997a - scriptified Hexen's flies.
A few notes:

 * this accesses the lines array in sector_t which effectively is a pointer to an array of pointers - a type the parser can not represent. The compiler has no problems with it, so for now it is defined internally.
 * array sizes were limited to 65536 entries because the 'bound' instruction only existed as an immediate version with no provisions for larger values. For the static map arrays 65536 is not sufficient so now there are alternative instructions for these cases.
 * despite the above, at the moment there is no proper bounds checking for arrays that have no fixed size. To do this, a lot more work is needed. The type system as-is is not prepared for such a scenario.
2016-11-27 18:52:24 +01:00

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.linecount; ++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_PlaySound(ActiveSound, CHAN_VOICE, 0.5f, false, ATTN_STATIC);
}
}
}