Permit emblem pickups that take on the visage of a Follower

- If Global-type map emblem has GE_FOLLOWER, attempt to take on the appearance of the follower specified by var2.
    - Unlike MT_RANDOMAUDIENCE, this picks whether the object should be floating or hopping based on the specified mode of the source Follower.
    - Always chooses to face the nearest player.
- Rearrange some properties affected by Obj_Audience/audience.c to not conflict with MT_EMBLEM
This commit is contained in:
toaster 2023-04-21 15:17:43 +01:00
parent 8878bf8465
commit 945a00df6e
4 changed files with 66 additions and 7 deletions

View file

@ -6395,6 +6395,7 @@ struct int_const_s const INT_CONST[] = {
// Global emblem var flags
{"GE_NOTMEDAL", GE_NOTMEDAL},
{"GE_TIMED", GE_TIMED},
{"GE_FOLLOWER", GE_FOLLOWER},
// Map emblem var flags
{"ME_ENCORE",ME_ENCORE},

View file

@ -132,6 +132,7 @@ struct conditionset_t
// Global emblem flags
#define GE_NOTMEDAL 1 // Doesn't count towards number of medals
#define GE_TIMED 2 // Disappears after var time
#define GE_FOLLOWER 4 // Takes on the appearance of a Follower in (string)var2
// Map emblem flags
#define ME_ENCORE 1 // Achieve in Encore

View file

@ -10,10 +10,13 @@
#include "../r_main.h" // R_PointToAngle2, R_PointToDist2
#include "../z_zone.h" // Z_StrDup/Z_Free
// The following cannot be used due to conflicts with MT_EMBLEM.
//#define audience_emblem_reserved_1(o) ((o)->reactiontime)
#define audience_mainstate(o) ((o)->cvmem)
#define audience_bobamp(o) ((o)->cusval)
#define audience_bobspeed(o) ((o)->reactiontime)
#define audience_bobamp(o) ((o)->movefactor)
#define audience_bobspeed(o) ((o)->cusval)
#define audience_animoffset(o) ((o)->threshold)
@ -231,17 +234,25 @@ Obj_AudienceThink
if (mobj->flags & MF_NOGRAVITY)
{
// This horrible calculation was inherited from k_follower.c, with only newlines (and a FRACUNIT offset) added
// This horrible calculation was inherited from k_follower.c
mobj->sprzoff = FixedMul(audience_bobamp(mobj),
FRACUNIT + FINESINE(((
FINESINE(((
FixedMul(4 * M_TAU_FIXED, audience_bobspeed(mobj))
* (leveltime + audience_animoffset(mobj))
) >> ANGLETOFINESHIFT) & FINEMASK));
// Gravity
if (mobj->flags2 & MF2_OBJECTFLIP)
// Offset to not go through floor...
if (mobj->type == MT_EMBLEM)
{
mobj->sprzoff = -mobj->sprzoff;
; // ...unless it's important to keep a centered hitbox
}
else if (mobj->flags2 & MF2_OBJECTFLIP)
{
mobj->sprzoff -= audience_bobamp(mobj);
}
else
{
mobj->sprzoff += audience_bobamp(mobj);
}
}
else if (audience_animoffset(mobj) > 0)

View file

@ -40,6 +40,7 @@
#include "k_kart.h"
#include "k_battle.h"
#include "k_color.h"
#include "k_follower.h"
#include "k_respawn.h"
#include "k_bot.h"
#include "k_terrain.h"
@ -7102,6 +7103,13 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
{
INT32 trans = 0;
if (mobj->flags2 & MF2_STRONGBOX)
{
Obj_AudienceThink(mobj, true);
if (P_MobjWasRemoved(mobj))
return false;
}
mobj->frame &= ~FF_TRANSMASK;
mobj->renderflags &= ~RF_TRANSMASK;
@ -12276,6 +12284,44 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
mobj->reactiontime = emblemlocations[j].var;
}
if (emblemlocations[j].flags & GE_FOLLOWER)
{
INT32 followerpick;
char testname[SKINNAMESIZE+1];
size_t i;
// match deh_soc readfollower()
for (i = 0; emblemlocations[j].stringVar2[i]; i++)
{
testname[i] = emblemlocations[j].stringVar2[i];
if (emblemlocations[j].stringVar2[i] == '_')
testname[i] = ' ';
}
testname[i] = '\0';
followerpick = K_FollowerAvailable(testname);
if (followerpick == -1)
{
CONS_Alert(CONS_WARNING, "P_SetupEmblem: Follower \"%s\" on emblem for map %d with tag %d not found!\n", emblemlocations[j].stringVar2, gamemap, tagnum);
return false;
}
// Set up data
Obj_AudienceInit(mobj, NULL, followerpick);
if (P_MobjWasRemoved(mobj))
{
CONS_Alert(CONS_WARNING, "P_SetupEmblem: Follower \"%s\" causes emblem for map %d with tag %d to be removed immediately!\n", emblemlocations[j].stringVar2, gamemap, tagnum);
return false;
}
// Signal that you are to behave like a follower
mobj->flags2 |= MF2_STRONGBOX;
if (followers[followerpick].mode == FOLLOWERMODE_GROUND)
{
mobj->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
}
}
return true;
}