New end-of-level signpost logic

This commit is contained in:
lachwright 2019-11-04 16:28:44 +08:00
parent 96aa11c825
commit 5e03d40b33
6 changed files with 193 additions and 204 deletions

View File

@ -2308,6 +2308,7 @@ static actionpointer_t actionpointers[] =
{{A_ThrownRing}, "A_THROWNRING"},
{{A_SetSolidSteam}, "A_SETSOLIDSTEAM"},
{{A_UnsetSolidSteam}, "A_UNSETSOLIDSTEAM"},
{{A_SignSpin}, "S_SIGNSPIN"},
{{A_SignPlayer}, "A_SIGNPLAYER"},
{{A_OverlayThink}, "A_OVERLAYTHINK"},
{{A_JetChase}, "A_JETCHASE"},
@ -5385,59 +5386,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BUBBLES4",
// Level End Sign
"S_SIGN1",
"S_SIGN2",
"S_SIGN3",
"S_SIGN4",
"S_SIGN5",
"S_SIGN6",
"S_SIGN7",
"S_SIGN8",
"S_SIGN9",
"S_SIGN10",
"S_SIGN11",
"S_SIGN12",
"S_SIGN13",
"S_SIGN14",
"S_SIGN15",
"S_SIGN16",
"S_SIGN17",
"S_SIGN18",
"S_SIGN19",
"S_SIGN20",
"S_SIGN21",
"S_SIGN22",
"S_SIGN23",
"S_SIGN24",
"S_SIGN25",
"S_SIGN26",
"S_SIGN27",
"S_SIGN28",
"S_SIGN29",
"S_SIGN30",
"S_SIGN31",
"S_SIGN32",
"S_SIGN33",
"S_SIGN34",
"S_SIGN35",
"S_SIGN36",
"S_SIGN37",
"S_SIGN38",
"S_SIGN39",
"S_SIGN40",
"S_SIGN41",
"S_SIGN42",
"S_SIGN43",
"S_SIGN44",
"S_SIGN45",
"S_SIGN46",
"S_SIGN47",
"S_SIGN48",
"S_SIGN49",
"S_SIGN50",
"S_SIGN51",
"S_SIGN52", // Eggman
"S_SIGN53",
"S_SIGN",
"S_SIGNSPIN",
"S_SIGNSPINLOOP",
"S_SIGNROULETTE",
"S_SIGNPLAYER",
"S_SIGNBOARD",
"S_EGGMANSIGN",
// Spike Ball
"S_SPIKEBALL1",

View File

@ -808,7 +808,7 @@ state_t states[NUMSTATES] =
{SPR_PLAY, SPR2_LIFE, 20, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3
// Level end sign (uses player sprite)
{SPR_PLAY, SPR2_SIGN, 1, {NULL}, 0, 24, S_PLAY_SIGN}, // S_PLAY_SIGN
{SPR_PLAY, SPR2_SIGN|FF_PAPERSPRITE, -1, {NULL}, 0, 29, S_PLAY_SIGN}, // S_PLAY_SIGN
// NiGHTS Player, transforming
{SPR_PLAY, SPR2_TRNS|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS1
@ -1925,59 +1925,13 @@ state_t states[NUMSTATES] =
{SPR_BBLS, 3, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES1}, // S_BUBBLES4
// Level End Sign
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN2}, // S_SIGN1
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN3}, // S_SIGN2
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN4}, // S_SIGN3
{SPR_SIGN, 5, 1, {NULL}, 0, 0, S_SIGN5}, // S_SIGN4
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN6}, // S_SIGN5
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN7}, // S_SIGN6
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN8}, // S_SIGN7
{SPR_SIGN, 3, 1, {NULL}, 0, 0, S_SIGN9}, // S_SIGN8
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN10}, // S_SIGN9
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN11}, // S_SIGN10
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN12}, // S_SIGN11
{SPR_SIGN, 4, 1, {NULL}, 0, 0, S_SIGN13}, // S_SIGN12
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN14}, // S_SIGN13
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN15}, // S_SIGN14
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN16}, // S_SIGN15
{SPR_SIGN, 3, 1, {NULL}, 0, 0, S_SIGN17}, // S_SIGN16
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN18}, // S_SIGN17
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN19}, // S_SIGN18
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN20}, // S_SIGN19
{SPR_SIGN, 6, 1, {NULL}, 0, 0, S_SIGN21}, // S_SIGN20
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN22}, // S_SIGN21
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN23}, // S_SIGN22
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN24}, // S_SIGN23
{SPR_SIGN, 3, 1, {NULL}, 0, 0, S_SIGN25}, // S_SIGN24
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN26}, // S_SIGN25
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN27}, // S_SIGN26
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN28}, // S_SIGN27
{SPR_SIGN, 5, 1, {NULL}, 0, 0, S_SIGN29}, // S_SIGN28
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN30}, // S_SIGN29
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN31}, // S_SIGN30
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN32}, // S_SIGN31
{SPR_SIGN, 3, 1, {NULL}, 0, 0, S_SIGN33}, // S_SIGN32
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN34}, // S_SIGN33
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN35}, // S_SIGN34
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN36}, // S_SIGN35
{SPR_SIGN, 4, 1, {NULL}, 0, 0, S_SIGN37}, // S_SIGN36
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN38}, // S_SIGN37
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN39}, // S_SIGN38
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN40}, // S_SIGN39
{SPR_SIGN, 3, 1, {NULL}, 0, 0, S_SIGN41}, // S_SIGN40
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN42}, // S_SIGN41
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN43}, // S_SIGN42
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN44}, // S_SIGN43
{SPR_SIGN, 6, 1, {NULL}, 0, 0, S_SIGN45}, // S_SIGN44
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN46}, // S_SIGN45
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN47}, // S_SIGN46
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN48}, // S_SIGN47
{SPR_SIGN, 3, 1, {NULL}, 0, 0, S_SIGN49}, // S_SIGN48
{SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN50}, // S_SIGN49
{SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN51}, // S_SIGN50
{SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN53}, // S_SIGN51
{SPR_SIGN, 3, -1, {NULL}, 0, 0, S_NULL}, // S_SIGN52 Eggman
{SPR_SIGN, 7, -1, {A_SignPlayer}, 0, 0, S_NULL}, // S_SIGN53 Blank
{SPR_SIGN, 0, -1, {A_SignPlayer}, -3, 0, S_NULL}, // S_SIGN
{SPR_SIGN, 0, 1, {A_SignSpin}, 30, S_SIGNPLAYER, S_SIGNSPINLOOP}, // S_SIGNSPIN
{SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN, S_SIGNROULETTE}, // S_SIGNSPINLOOP
{SPR_SIGN, 0, 0, {A_SignPlayer}, -2, 0, S_SIGNSPIN}, // S_SIGNROULETTE
{SPR_SIGN, 0, -1, {A_SignPlayer}, -1, 0, S_NULL}, // S_SIGNPLAYER
{SPR_SIGN, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNBOARD
{SPR_SIGN, FF_PAPERSPRITE|1, -1, {NULL}, 0, 29, S_NULL}, // S_EGGMANSIGN
// Spike Ball
{SPR_SPIK, 0, 1, {NULL}, 0, 0, S_SPIKEBALL2}, // S_SPIKEBALL1
@ -7832,29 +7786,29 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_SIGN
501, // doomednum
S_SIGN52, // spawnstate
S_SIGN, // spawnstate
1000, // spawnhealth
S_PLAY_SIGN, // seestate
sfx_lvpass, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
MT_SPARK, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_EGGMANSIGN, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
32*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
MF_NOCLIP|MF_SCENERY|MF_BOUNCE|MF_RUNSPAWNFUNC, // flags
S_SIGNBOARD // raisestate
},
{ // MT_SPIKEBALL

View File

@ -63,6 +63,7 @@ void A_FishJump(); // Fish Jump
void A_ThrownRing(); // Sparkle trail for red ring
void A_SetSolidSteam();
void A_UnsetSolidSteam();
void A_SignSpin();
void A_SignPlayer();
void A_OverlayThink();
void A_JetChase();
@ -2058,59 +2059,13 @@ typedef enum state
S_BUBBLES4,
// Level End Sign
S_SIGN1,
S_SIGN2,
S_SIGN3,
S_SIGN4,
S_SIGN5,
S_SIGN6,
S_SIGN7,
S_SIGN8,
S_SIGN9,
S_SIGN10,
S_SIGN11,
S_SIGN12,
S_SIGN13,
S_SIGN14,
S_SIGN15,
S_SIGN16,
S_SIGN17,
S_SIGN18,
S_SIGN19,
S_SIGN20,
S_SIGN21,
S_SIGN22,
S_SIGN23,
S_SIGN24,
S_SIGN25,
S_SIGN26,
S_SIGN27,
S_SIGN28,
S_SIGN29,
S_SIGN30,
S_SIGN31,
S_SIGN32,
S_SIGN33,
S_SIGN34,
S_SIGN35,
S_SIGN36,
S_SIGN37,
S_SIGN38,
S_SIGN39,
S_SIGN40,
S_SIGN41,
S_SIGN42,
S_SIGN43,
S_SIGN44,
S_SIGN45,
S_SIGN46,
S_SIGN47,
S_SIGN48,
S_SIGN49,
S_SIGN50,
S_SIGN51,
S_SIGN52, // Eggman
S_SIGN53,
S_SIGN,
S_SIGNSPIN,
S_SIGNSPINLOOP,
S_SIGNROULETTE,
S_SIGNPLAYER,
S_SIGNBOARD,
S_EGGMANSIGN,
// Spike Ball
S_SPIKEBALL1,

View File

@ -129,6 +129,7 @@ void A_FishJump(mobj_t *actor);
void A_ThrownRing(mobj_t *actor);
void A_SetSolidSteam(mobj_t *actor);
void A_UnsetSolidSteam(mobj_t *actor);
void A_SignSpin(mobj_t *actor);
void A_SignPlayer(mobj_t *actor);
void A_OverlayThink(mobj_t *actor);
void A_JetChase(mobj_t *actor);
@ -5006,59 +5007,176 @@ void A_UnsetSolidSteam(mobj_t *actor)
actor->flags |= MF_NOCLIP;
}
// Function: A_SignSpin
//
// Description: Spins a signpost until it hits the ground and reaches its mapthing's angle.
//
// var1 = degrees to rotate object
// var2 = state to set object to once spinning stops
//
void A_SignSpin(mobj_t *actor)
{
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SignSpin", actor))
return;
#endif
INT32 locvar1 = var1;
INT32 locvar2 = var2;
INT16 i;
angle_t rotateangle = FixedAngle(locvar1 << FRACBITS);
if (P_IsObjectOnGround(actor) && P_MobjFlip(actor) * actor->momz <= 0)
{
if (actor->spawnpoint)
{
angle_t mapangle = FixedAngle(actor->spawnpoint->angle << FRACBITS);
angle_t diff = mapangle - actor->angle;
if (diff < rotateangle)
{
actor->angle = mapangle;
P_SetMobjState(actor, locvar2);
return;
}
}
else // no mapthing? just finish in your current angle
{
P_SetMobjState(actor, locvar2);
return;
}
}
actor->angle += rotateangle;
if (leveltime & 1 || actor->tracer == NULL) return;
for (i = -1; i < 2; i += 2)
{
P_SpawnMobjFromMobj(actor,
P_ReturnThrustX(actor, actor->tracer->angle, i * actor->radius),
P_ReturnThrustY(actor, actor->tracer->angle, i * actor->radius),
(actor->eflags & MFE_VERTICALFLIP) ? 0 : actor->height,
actor->info->painchance);
}
}
// Function: A_SignPlayer
//
// Description: Changes the state of a level end sign to reflect the player that hit it.
// Also used to display Eggman or the skin roulette whilst spinning.
//
// var1 = unused
// var1 = number of skin to display (e.g. 2 = Knuckles; special cases: -1 = target's skin, -2 = skin roulette, -3 = Eggman)
// var2 = unused
//
void A_SignPlayer(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
skin_t *skin = NULL;
mobj_t *ov;
skin_t *skin;
UINT8 facecolor, signcolor;
UINT32 signframe = states[actor->info->raisestate].frame;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SignPlayer", actor))
return;
#endif
if (!actor->target)
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins)
return;
if (!actor->target->player)
return;
skin = &skins[actor->target->player->skin];
if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
// if no face overlay, spawn one
if (actor->tracer->tracer == NULL || P_MobjWasRemoved(actor->tracer->tracer))
{
actor->color = skin->prefoppositecolor;
/*
If you're here from the comment above Color_Opposite,
the following line is the one which is dependent on the
array being symmetrical. It gets the opposite of the
opposite of your desired colour just so it can get the
brightness frame for the End Sign. It's not a great
design choice, but it's constant time array access and
the idea that the colours should be OPPOSITES is kind
of in the name. If you have a better idea, feel free
to let me know. ~toast 2016/07/20
*/
actor->frame += (15 - Color_Opposite[Color_Opposite[skin->prefoppositecolor - 1][0] - 1][1]);
}
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
{
actor->color = Color_Opposite[actor->target->player->skincolor - 1][0];
actor->frame += (15 - Color_Opposite[actor->target->player->skincolor - 1][1]);
}
if (skin->sprites[SPR2_SIGN].numframes)
{
// spawn an overlay of the player's face.
ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY);
P_SetTarget(&ov->target, actor);
ov->color = actor->target->player->skincolor;
P_SetTarget(&ov->target, actor->tracer);
P_SetTarget(&actor->tracer->tracer, ov);
}
else
ov = actor->tracer->tracer;
if (locvar1 == -1) // set to target's skin
{
if (!actor->target)
return;
if (!actor->target->player)
return;
skin = &skins[actor->target->player->skin];
facecolor = actor->target->player->skincolor;
if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
{
signcolor = skin->prefoppositecolor;
/*
If you're here from the comment above Color_Opposite,
the following line is the one which is dependent on the
array being symmetrical. It gets the opposite of the
opposite of your desired colour just so it can get the
brightness frame for the End Sign. It's not a great
design choice, but it's constant time array access and
the idea that the colours should be OPPOSITES is kind
of in the name. If you have a better idea, feel free
to let me know. ~toast 2016/07/20
*/
signframe += (15 - Color_Opposite[Color_Opposite[skin->prefoppositecolor - 1][0] - 1][1]);
}
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
{
signcolor = Color_Opposite[actor->target->player->skincolor - 1][0];
signframe += (15 - Color_Opposite[actor->target->player->skincolor - 1][1]);
}
}
else if (locvar1 != -3) // set to a defined skin
{
// I turned this function into a fucking mess. I'm so sorry. -Lach
if (locvar1 == -2) // next skin
{
if (ov->skin == NULL) // start at Sonic
skin = &skins[0];
else
{
UINT8 skinnum = (skin_t*)ov->skin-skins + 1;
player_t *player = actor->target ? actor->target->player : NULL;
while (skinnum < numskins && (player ? !R_SkinUsable(player-players, skinnum) : skins[skinnum].availability > 0))
skinnum++;
if (skinnum < numskins)
skin = &skins[skinnum];
// leave skin NULL if we go past the skin count, this will display Eggman
}
}
else // specific skin
{
skin = &skins[locvar1];
}
if (skin != NULL) // if not Eggman, get the appropriate colors
{
facecolor = skin->prefcolor;
if (skin->prefoppositecolor)
{
signcolor = skin->prefoppositecolor;
}
else
{
signcolor = Color_Opposite[facecolor - 1][0];
}
signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
}
}
if (skin != NULL && skin->sprites[SPR2_SIGN].numframes) // player face
{
ov->color = facecolor;
ov->skin = skin;
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN
actor->tracer->color = signcolor;
actor->tracer->frame = signframe;
}
else // Eggman face
{
ov->color = SKINCOLOR_NONE;
ov->skin = NULL;
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
actor->tracer->color = signcolor = SKINCOLOR_CARBON;
actor->tracer->frame = signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
}
}
@ -5106,7 +5224,7 @@ void A_OverlayThink(mobj_t *actor)
actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
else
actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
actor->angle = actor->target->angle;
actor->angle = actor->target->angle + actor->movedir;
actor->eflags = actor->target->eflags;
actor->momx = actor->target->momx;

View File

@ -6914,7 +6914,7 @@ void P_RunOverlays(void)
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = mo->target->scale;
mo->angle = mo->target->angle;
mo->angle = mo->target->angle + mo->movedir;
if (!(mo->state->frame & FF_ANIMATE))
zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
@ -10441,6 +10441,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->extravalue2 = 0;
mobj->fuse = 100;
break;
case MT_SIGN:
P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_OVERLAY));
P_SetTarget(&mobj->tracer->target, mobj);
P_SetMobjState(mobj->tracer, S_SIGNBOARD);
mobj->tracer->movedir = ANGLE_90;
default:
break;
}

View File

@ -4058,7 +4058,8 @@ void P_SetupSignExit(player_t *player)
continue;
P_SetTarget(&thing->target, player->mo);
P_SetMobjState(thing, S_SIGN1);
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
P_SetMobjState(thing, S_SIGNSPIN);
if (thing->info->seesound)
S_StartSound(thing, thing->info->seesound);
@ -4083,7 +4084,8 @@ void P_SetupSignExit(player_t *player)
continue;
P_SetTarget(&thing->target, player->mo);
P_SetMobjState(thing, S_SIGN1);
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
P_SetMobjState(thing, S_SIGNSPIN);
if (thing->info->seesound)
S_StartSound(thing, thing->info->seesound);