diff --git a/src/dehacked.c b/src/dehacked.c index 946e6f117..dbe0491ef 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2225,6 +2225,7 @@ static actionpointer_t actionpointers[] = {{A_ParentTriesToSleep}, "A_PARENTTRIESTOSLEEP"}, {{A_CryingToMomma}, "A_CRYINGTOMOMMA"}, {{A_CheckFlags2}, "A_CHECKFLAGS2"}, + {{A_Boss5FindWaypoint}, "A_BOSS5FINDWAYPOINT"}, {{A_DoNPCSkid}, "A_DONPCSKID"}, {{A_DoNPCPain}, "A_DONPCPAIN"}, {{A_PrepareRepeat}, "A_PREPAREREPEAT"}, diff --git a/src/info.h b/src/info.h index 948ecef97..f052972e6 100644 --- a/src/info.h +++ b/src/info.h @@ -239,6 +239,7 @@ void A_WhoCaresIfYourSonIsABee(); void A_ParentTriesToSleep(); void A_CryingToMomma(); void A_CheckFlags2(); +void A_Boss5FindWaypoint(); void A_DoNPCSkid(); void A_DoNPCPain(); void A_PrepareRepeat(); diff --git a/src/p_enemy.c b/src/p_enemy.c index 10662ba88..227b8dd47 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -266,6 +266,7 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor); void A_ParentTriesToSleep(mobj_t *actor); void A_CryingToMomma(mobj_t *actor); void A_CheckFlags2(mobj_t *actor); +void A_Boss5FindWaypoint(mobj_t *actor); void A_DoNPCSkid(mobj_t *actor); void A_DoNPCPain(mobj_t *actor); void A_PrepareRepeat(mobj_t *actor); @@ -11863,6 +11864,193 @@ void A_CheckFlags2(mobj_t *actor) P_SetMobjState(actor, (statenum_t)locvar2); } +// Function: A_Boss5FindWaypoint +// +// Description: Finds the next waypoint in sequence and sets it as its tracer. +// +// var1 = if 1, always go to ambush-marked waypoint. if 2, go to MT_BOSSFLYPOINT. +// var2 = unused +// +void A_Boss5FindWaypoint(mobj_t *actor) +{ + INT32 locvar1 = var1; + //INT32 locvar2 = var2; + boolean avoidcenter; + INT32 i; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss5FindWaypoint", actor)) + return; +#endif + + avoidcenter = !actor->tracer || (mobj->health == mobj->info->damage+1); + + if (locvar1 == 2) // look for the boss waypoint + { + for (i = 0; i < nummapthings; i++) + { + if (!mapthings[i].mobj) + continue; + if (mapthings[i].mobj->type != MT_BOSSFLYPOINT) + continue; + P_SetTarget(&actor->tracer, mapthings[i].mobj); + break; + } + if (i == nummapthings) + return; // no boss flypoints found + } + else if (locvar1 == 1) // always go to ambush-marked waypoint + { + if (avoidcenter) + goto nowaypoints; // if we can't go the center, why on earth are we doing this? + + for (i = 0; i < nummapthings; i++) + { + if (!mapthings[i].mobj) + continue; + if (mapthings[i].mobj->type != MT_FANGWAYPOINT) + continue; + if (mapthings[i].options & MTF_AMBUSH) + { + P_SetTarget(&actor->tracer, mapthings[i].mobj); + break; + } + } + + if (i == nummapthings) + goto nowaypoints; + } + else // locvar1 == 0 + { + fixed_t hackoffset = P_MobjFlip(actor)*56*FRACUNIT; + INT32 numwaypoints = 0; + mobj_t **waypoints; + INT32 key; + + actor->z += hackoffset; + + // first, count how many waypoints we have + for (i = 0; i < nummapthings; i++) + { + if (!mapthings[i].mobj) + continue; + if (mapthings[i].mobj->type != MT_FANGWAYPOINT) + continue; + if (actor->tracer == mapthings[i].mobj) // this was your tracer last time + continue; + if (mapthings[i].options & MTF_AMBUSH) + { + if (avoidcenter) + continue; + } + else if (mapthings[i].mobj->reactiontime > 0) + continue; + numwaypoints++; + } + + // players also count as waypoints apparently + if (actor->extravalue2 > 1) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].spectator) + continue; + if (players[i].mo->health <= 0) + continue; + if (players[i].powers[pw_flashing]) + continue; + if (actor->tracer == players[i].mo) // this was your tracer last time + continue; + if (!P_CheckSight(actor, players[i].mo)) + continue; + numwaypoints++; + } + } + + if (!numwaypoints) + { + // restore z position + actor->z -= hackoffset; + goto nowaypoints; // no waypoints :( + } + + // allocate the table and reset count to zero + waypoints = Z_Calloc(sizeof(*waypoints)*numwaypoints, PU_STATIC, NULL); + numwaypoints = 0; + + // now find them again and add them to the table! + for (i = 0; i < nummapthings; i++) + { + if (!mapthings[i].mobj) + continue; + if (mapthings[i].mobj->type != MT_FANGWAYPOINT) + continue; + if (actor->tracer == mapthings[i].mobj) // this was your tracer last time + continue; + if (mapthings[i].options & MTF_AMBUSH) + { + if (avoidcenter) + continue; + waypoints[numwaypoints++] = mapthings[i].mobj; + } + else if (mapthings[i].mobj->reactiontime > 0) + mapthings[i].mobj->reactiontime--; + else + waypoints[numwaypoints++] = mapthings[i].mobj; + } + + if (actor->extravalue2 > 1) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].spectator) + continue; + if (players[i].mo->health <= 0) + continue; + if (players[i].powers[pw_flashing]) + continue; + if (actor->tracer == players[i].mo) // this was your tracer last time + continue; + if (!P_CheckSight(actor, players[i].mo)) + continue; + waypoints[numwaypoints++] = players[i].mo; + } + } + + // restore z position + actor->z -= hackoffset; + + if (!numwaypoints) + goto nowaypoints; // ??? + + key = P_RandomKey(numwaypoints); + + P_SetTarget(&actor->tracer, waypoints[key]); + if (actor->tracer->type == MT_FANGWAYPOINT) + actor->tracer->reactiontime = numwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script + Z_Free(waypoints); // free table + } + + // now face the tracer you just set! + A_FaceTracer(actor); + return; + +nowaypoints: + // no waypoints at all, guess the mobj has to disappear + if (actor->health) + P_KillMobj(actor, NULL, NULL, 0); + else + P_RemoveMobj(actor); + return; +} + // Function: A_DoNPCSkid // // Description: Something that looks like a player is skidding.