statenum_t frogstate = (mobj->state-states);
// FROG ATTACK VALUES:
// threshold: distance
// movecount: time
// lastlook: direction
// extravalue1: x step
// extravalue2: y step
// cusval: z step
if (frogstate == S_FROGGER)
{
mobj->threshold = mobj->movecount = mobj->lastlook = 0; // clear tongue attack
mobj->extravalue1 = mobj->extravalue2 = mobj->cusval = 0;
if (mobj->hnext) // Clean hnext list
{
mobj_t *cur = mobj->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
mobj_t *next = cur->hnext;
P_RemoveMobj(cur);
cur = next;
}
}
if (mobj->reactiontime)
mobj->reactiontime--;
else
{
if (mobj->flags2 & MF2_AMBUSH)
{
mobj->momz = P_RandomRange(12, 16)<<FRACBITS;
S_StartSound(mobj, sfx_s3kb1);
P_SetMobjState(mobj, S_FROGGER_JUMP);
}
else
{
mobj_t *tongue = P_SpawnMobj(mobj->x, mobj->y, mobj->z + (mobj->height/2), MT_FROGTONGUE);
P_SetTarget(&mobj->tracer, tongue);
P_SetMobjState(mobj, S_FROGGER_ATTACK);
}
}
}
else if (frogstate == S_FROGGER_ATTACK)
{
if (!mobj->tracer || P_MobjWasRemoved(mobj->tracer))
{
mobj->reactiontime = mobj->info->reactiontime;
P_SetMobjState(mobj, S_FROGGER);
break;
}
if (mobj->threshold == 0)
{
fixed_t targetz = mobj->tracer->z; //mobj->z + (mobj->height/2)
mobj->threshold = 256;
mobj->movecount = 1;
mobj->lastlook = 1;
mobj->tracer->angle = mobj->angle;
mobj->extravalue1 = FixedMul(FixedMul((mobj->threshold/16)<<FRACBITS,
FINECOSINE(((angle_t)targetz)>>ANGLETOFINESHIFT)),
FINECOSINE(mobj->angle>>ANGLETOFINESHIFT)) >> FRACBITS;
mobj->extravalue2 = FixedMul(FixedMul((mobj->threshold/16)<<FRACBITS,
FINECOSINE(((angle_t)targetz)>>ANGLETOFINESHIFT)),
FINESINE(mobj->angle>>ANGLETOFINESHIFT)) >> FRACBITS;
mobj->cusval = FixedMul((mobj->threshold/16)<<FRACBITS,
FINESINE(((angle_t)targetz)>>ANGLETOFINESHIFT)) >> FRACBITS;
S_StartSound(mobj, sfx_s3k8c); // Play that tongue-y sound.
}
mobj->movecount += mobj->lastlook;
if (!(P_TryMove(mobj->tracer, mobj->x + ((mobj->extravalue1<<FRACBITS) * mobj->movecount), mobj->y + ((mobj->extravalue2<<FRACBITS) * mobj->movecount), true))
|| (mobj->movecount >= 16) // maximum travel time
|| (mobj->tracer->z <= mobj->tracer->floorz) // Through the floor
|| ((mobj->tracer->z + mobj->tracer->height) >= mobj->tracer->ceilingz)) // Through the ceiling
{
mobj->lastlook = -1; // Reverse direction.
}
if (mobj->movecount == 0) // It's back to its source, time to reset.
{
mobj->threshold = mobj->lastlook = 0;
P_RemoveMobj(mobj->tracer);
if (mobj->hnext) // Clean hnext list
{
mobj_t *cur = mobj->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
mobj_t *next = cur->hnext;
P_RemoveMobj(cur);
cur = next;
}
}
mobj->reactiontime = mobj->info->reactiontime;
P_SetMobjState(mobj, S_FROGGER);
}
else
{
const UINT8 numjoints = 11;
UINT8 joint = numjoints;
mobj_t *cur = mobj->hnext, *prev = mobj;
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y);
for (; joint > 0; joint--)
{
fixed_t wx = mobj->tracer->x + (joint * (mobj->x - mobj->tracer->x) / (numjoints+1));
fixed_t wy = mobj->tracer->y + (joint * (mobj->y - mobj->tracer->y) / (numjoints+1));
fixed_t wz = mobj->tracer->z + (joint * ((mobj->z + (mobj->height/2)) - mobj->tracer->z) / (numjoints+1));
if (cur && !P_MobjWasRemoved(cur))
P_TeleportMove(cur, wx, wy, wz);
else
cur = P_SpawnMobj(wx, wy, wz, MT_FROGTONGUE_JOINT);
P_SetTarget(&cur->target, mobj);
P_SetTarget(&prev->hnext, cur);
P_SetTarget(&cur->hprev, prev);
prev = cur;
cur = cur->hnext;
}
}
}
else if (frogstate == S_FROGGER_JUMP)
{
if (P_IsObjectOnGround(mobj))
{
mobj->reactiontime = mobj->info->reactiontime;
P_SetMobjState(mobj, S_FROGGER);
}
}
}
break;