From 945a00df6e3ac42041d2f69a0e2ef6009c3b13a8 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 21 Apr 2023 15:17:43 +0100 Subject: [PATCH] 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 --- src/deh_tables.c | 1 + src/m_cond.h | 1 + src/objects/audience.c | 25 ++++++++++++++++------- src/p_mobj.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 17f7cc819..5b2fa3f24 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -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}, diff --git a/src/m_cond.h b/src/m_cond.h index a34825bc2..9fdb5bd2e 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -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 diff --git a/src/objects/audience.c b/src/objects/audience.c index 8498426be..aba436013 100644 --- a/src/objects/audience.c +++ b/src/objects/audience.c @@ -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) diff --git a/src/p_mobj.c b/src/p_mobj.c index 3b60dc6bb..49dc1e992 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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; }