mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 12:31:54 +00:00
Talk Point visual (for dialogue)
- Spinning question mark surrounded by multi-colored orbs, representing the radius of the dialogue activator - Collect animation
This commit is contained in:
parent
1a916a7d16
commit
6df73670dd
6 changed files with 212 additions and 3 deletions
|
|
@ -3005,6 +3005,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
||||||
|
|
||||||
// MT_STARSTREAM
|
// MT_STARSTREAM
|
||||||
"S_STARSTREAM",
|
"S_STARSTREAM",
|
||||||
|
|
||||||
|
// MT_SCRIPT_THING
|
||||||
|
"S_TALKPOINT",
|
||||||
|
"S_TALKPOINT_ORB",
|
||||||
};
|
};
|
||||||
|
|
||||||
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
||||||
|
|
@ -3726,6 +3730,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
||||||
|
|
||||||
"MT_CHECKPOINT_END",
|
"MT_CHECKPOINT_END",
|
||||||
"MT_SCRIPT_THING",
|
"MT_SCRIPT_THING",
|
||||||
|
"MT_SCRIPT_THING_ORB",
|
||||||
|
|
||||||
"MT_RIDEROID",
|
"MT_RIDEROID",
|
||||||
"MT_RIDEROIDNODE",
|
"MT_RIDEROIDNODE",
|
||||||
|
|
|
||||||
36
src/info.c
36
src/info.c
|
|
@ -734,6 +734,9 @@ char sprnames[NUMSPRITES + 1][5] =
|
||||||
"SENC",
|
"SENC",
|
||||||
"SEAS",
|
"SEAS",
|
||||||
|
|
||||||
|
// Tutorial
|
||||||
|
"TLKP", // Talk Point
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
"VIEW",
|
"VIEW",
|
||||||
};
|
};
|
||||||
|
|
@ -3515,6 +3518,10 @@ state_t states[NUMSTATES] =
|
||||||
|
|
||||||
// MT_STARSTREAM
|
// MT_STARSTREAM
|
||||||
{SPR_SEAS, FF_ANIMATE|0, 30, {NULL}, 29, 1, S_NULL}, // S_STARSTREAM
|
{SPR_SEAS, FF_ANIMATE|0, 30, {NULL}, 29, 1, S_NULL}, // S_STARSTREAM
|
||||||
|
|
||||||
|
// MT_SCRIPT_THING
|
||||||
|
{SPR_TLKP, 0|FF_SEMIBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_TALKPOINT
|
||||||
|
{SPR_TLKP, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_TALKPOINT_ORB
|
||||||
};
|
};
|
||||||
|
|
||||||
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
|
|
@ -18517,7 +18524,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
|
|
||||||
{ // MT_SCRIPT_THING
|
{ // MT_SCRIPT_THING
|
||||||
4096, // doomednum
|
4096, // doomednum
|
||||||
S_INVISIBLE, // spawnstate
|
S_TALKPOINT, // spawnstate
|
||||||
|
1000, // spawnhealth
|
||||||
|
S_NULL, // seestate
|
||||||
|
sfx_None, // seesound
|
||||||
|
0, // reactiontime
|
||||||
|
sfx_None, // attacksound
|
||||||
|
S_NULL, // painstate
|
||||||
|
0, // painchance
|
||||||
|
sfx_None, // painsound
|
||||||
|
S_NULL, // meleestate
|
||||||
|
S_NULL, // missilestate
|
||||||
|
S_NULL, // deathstate
|
||||||
|
S_NULL, // xdeathstate
|
||||||
|
sfx_None, // deathsound
|
||||||
|
0, // speed
|
||||||
|
16*FRACUNIT, // radius
|
||||||
|
16*FRACUNIT, // height
|
||||||
|
0, // display offset
|
||||||
|
0, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
|
|
||||||
|
{ // MT_SCRIPT_THING_ORB
|
||||||
|
-1, // doomednum
|
||||||
|
S_TALKPOINT_ORB, // spawnstate
|
||||||
1000, // spawnhealth
|
1000, // spawnhealth
|
||||||
S_NULL, // seestate
|
S_NULL, // seestate
|
||||||
sfx_None, // seesound
|
sfx_None, // seesound
|
||||||
|
|
|
||||||
|
|
@ -1269,6 +1269,9 @@ typedef enum sprite
|
||||||
SPR_SENC, // Cabotron
|
SPR_SENC, // Cabotron
|
||||||
SPR_SEAS, // Starstream
|
SPR_SEAS, // Starstream
|
||||||
|
|
||||||
|
// Tutorial
|
||||||
|
SPR_TLKP, // Talk Point
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
SPR_VIEW,
|
SPR_VIEW,
|
||||||
|
|
||||||
|
|
@ -4002,6 +4005,10 @@ typedef enum state
|
||||||
// MT_STARSTREAM
|
// MT_STARSTREAM
|
||||||
S_STARSTREAM,
|
S_STARSTREAM,
|
||||||
|
|
||||||
|
// MT_SCRIPT_THING
|
||||||
|
S_TALKPOINT,
|
||||||
|
S_TALKPOINT_ORB,
|
||||||
|
|
||||||
S_FIRSTFREESLOT,
|
S_FIRSTFREESLOT,
|
||||||
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
||||||
NUMSTATES
|
NUMSTATES
|
||||||
|
|
@ -4742,6 +4749,7 @@ typedef enum mobj_type
|
||||||
|
|
||||||
MT_CHECKPOINT_END,
|
MT_CHECKPOINT_END,
|
||||||
MT_SCRIPT_THING,
|
MT_SCRIPT_THING,
|
||||||
|
MT_SCRIPT_THING_ORB,
|
||||||
|
|
||||||
MT_RIDEROID,
|
MT_RIDEROID,
|
||||||
MT_RIDEROIDNODE,
|
MT_RIDEROIDNODE,
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,9 @@ void Obj_SSCabotronMobjThink(mobj_t* mo);
|
||||||
void Obj_SSCabotronStarMobjThink(mobj_t* mo);
|
void Obj_SSCabotronStarMobjThink(mobj_t* mo);
|
||||||
|
|
||||||
/* Talk Point */
|
/* Talk Point */
|
||||||
|
void Obj_TalkPointInit(mobj_t* mo);
|
||||||
void Obj_TalkPointThink(mobj_t* mo);
|
void Obj_TalkPointThink(mobj_t* mo);
|
||||||
|
void Obj_TalkPointOrbThink(mobj_t* mo);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,45 @@
|
||||||
// See the 'LICENSE' file for more details.
|
// See the 'LICENSE' file for more details.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "objects.hpp"
|
#include "objects.hpp"
|
||||||
|
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
#include "../g_game.h"
|
#include "../g_game.h"
|
||||||
#include "../p_spec.h"
|
#include "../p_spec.h"
|
||||||
|
#include "../tables.h"
|
||||||
|
|
||||||
using namespace srb2::objects;
|
using namespace srb2::objects;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Vec2<Fixed> angle_vector(angle_t x)
|
||||||
|
{
|
||||||
|
return Vec2<Fixed> {FCOS(x), FSIN(x)};
|
||||||
|
}
|
||||||
|
|
||||||
struct TalkPoint : Mobj
|
struct TalkPoint : Mobj
|
||||||
{
|
{
|
||||||
|
static constexpr angle_t kSpinSpeed = ANGLE_11hh;
|
||||||
|
static constexpr tic_t kCollectDuration = 12;
|
||||||
|
|
||||||
void thing_args() = delete;
|
void thing_args() = delete;
|
||||||
Fixed radius() const { return mobj_t::thing_args[0] * FRACUNIT; }
|
Fixed radius() const { return mobj_t::thing_args[0] * FRACUNIT; }
|
||||||
bool oneshot() const { return !mobj_t::thing_args[1]; }
|
bool oneshot() const { return !mobj_t::thing_args[1]; }
|
||||||
bool disabled() const { return mobj_t::thing_args[2]; }
|
bool disabled() const { return mobj_t::thing_args[2]; }
|
||||||
|
|
||||||
|
void extravalue1() = delete;
|
||||||
|
tic_t collect() const { return mobj_t::extravalue1; }
|
||||||
|
void collect(tic_t n) { mobj_t::extravalue1 = n; }
|
||||||
|
|
||||||
|
// This value scales up as the radius gets larger
|
||||||
|
Fixed scaling() const { return std::min<Fixed>(FRACUNIT, Fixed {320 * mapobjectscale} / radius()); }
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
void think()
|
void think()
|
||||||
{
|
{
|
||||||
if (disabled())
|
if (disabled())
|
||||||
|
|
@ -33,6 +54,26 @@ struct TalkPoint : Mobj
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (collect() > 0)
|
||||||
|
{
|
||||||
|
collect(collect() - 1);
|
||||||
|
|
||||||
|
if (collect() == 0)
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect animation: stretch upward, spin faster, fade out
|
||||||
|
spriteyscale(kCollectDuration * FRACUNIT / collect());
|
||||||
|
angle += kCollectDuration * kSpinSpeed / collect();
|
||||||
|
renderflags = (renderflags & ~RF_TRANSMASK) |
|
||||||
|
((9 - (collect() * 9 / kCollectDuration)) << RF_TRANSSHIFT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
angle += kSpinSpeed;
|
||||||
|
|
||||||
for (UINT8 i = 0; i < MAXPLAYERS; i++)
|
for (UINT8 i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] == false || players[i].spectator == true)
|
if (playeringame[i] == false || players[i].spectator == true)
|
||||||
|
|
@ -53,8 +94,9 @@ struct TalkPoint : Mobj
|
||||||
|
|
||||||
if (oneshot())
|
if (oneshot())
|
||||||
{
|
{
|
||||||
remove();
|
// Collect animation: appear brighter during fade-out
|
||||||
return;
|
renderflags |= RF_FULLBRIGHT;
|
||||||
|
collect(kCollectDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -63,9 +105,115 @@ struct TalkPoint : Mobj
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Orb : Mobj
|
||||||
|
{
|
||||||
|
static constexpr std::array<skincolornum_t, 10> kColors = {
|
||||||
|
SKINCOLOR_NONE,
|
||||||
|
SKINCOLOR_JAWZ,
|
||||||
|
SKINCOLOR_AQUAMARINE,
|
||||||
|
SKINCOLOR_LIME,
|
||||||
|
SKINCOLOR_BANANA,
|
||||||
|
SKINCOLOR_CREAMSICLE,
|
||||||
|
SKINCOLOR_DAWN,
|
||||||
|
SKINCOLOR_TAFFY,
|
||||||
|
SKINCOLOR_VIOLET,
|
||||||
|
SKINCOLOR_RUST,
|
||||||
|
};
|
||||||
|
|
||||||
|
void target() = delete;
|
||||||
|
TalkPoint* origin() const { return Mobj::target<TalkPoint>(); }
|
||||||
|
void origin(TalkPoint* n) { Mobj::target(n); }
|
||||||
|
|
||||||
|
void extravalue1() = delete;
|
||||||
|
angle_t speed() const { return mobj_t::extravalue1; }
|
||||||
|
void speed(angle_t n) { mobj_t::extravalue1 = n; }
|
||||||
|
|
||||||
|
bool valid() const { return Mobj::valid(origin()) && origin()->valid(); }
|
||||||
|
|
||||||
|
static Orb* spawn(TalkPoint* origin, UINT8 index, angle_t angle)
|
||||||
|
{
|
||||||
|
Orb* orb = Mobj::spawn<Orb>({origin->pos2d() + radius_vector(origin, angle), origin->z}, MT_SCRIPT_THING_ORB);
|
||||||
|
orb->origin(origin);
|
||||||
|
|
||||||
|
orb->color = kColors[index % kColors.size()]; // cycle colors
|
||||||
|
orb->colorized = true;
|
||||||
|
|
||||||
|
orb->angle = angle;
|
||||||
|
orb->sprzoff(20 * mapobjectscale); // roughly eye level with the player
|
||||||
|
orb->speed(FixedAngle(Fixed {45*FRACUNIT/8} * origin->scaling())); // slower with larger radius
|
||||||
|
|
||||||
|
return orb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void think()
|
||||||
|
{
|
||||||
|
if (!valid())
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rotate
|
||||||
|
angle += speed();
|
||||||
|
move_origin({origin()->pos2d() + radius_vector(), origin()->z});
|
||||||
|
|
||||||
|
// bob
|
||||||
|
spriteyoffset(8 * FSIN(angle + (leveltime * speed())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static vec2 radius_vector(TalkPoint* origin, angle_t angle)
|
||||||
|
{
|
||||||
|
// Collect animation: orbs fly outward
|
||||||
|
return angle_vector(angle) * origin->radius() * origin->spriteyscale();
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 radius_vector() const { return radius_vector(origin(), angle); }
|
||||||
|
};
|
||||||
|
|
||||||
|
void TalkPoint::init()
|
||||||
|
{
|
||||||
|
if (scaling() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orbs get spaced further apart as the radius increases
|
||||||
|
fixed_t orb_rad = Fixed {88 * mapobjectscale} / scaling();
|
||||||
|
if (orb_rad == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn more orbs within a larger radius
|
||||||
|
INT32 count = (Fixed {M_TAU_FIXED} * radius()) / orb_rad;
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
angle_t step = ANGLE_MAX / count;
|
||||||
|
angle_t angle = 0;
|
||||||
|
for (INT32 i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
Orb::spawn(this, i, angle);
|
||||||
|
angle += step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace
|
}; // namespace
|
||||||
|
|
||||||
|
void Obj_TalkPointInit(mobj_t* mo)
|
||||||
|
{
|
||||||
|
static_cast<TalkPoint*>(mo)->init();
|
||||||
|
}
|
||||||
|
|
||||||
void Obj_TalkPointThink(mobj_t* mo)
|
void Obj_TalkPointThink(mobj_t* mo)
|
||||||
{
|
{
|
||||||
static_cast<TalkPoint*>(mo)->think();
|
static_cast<TalkPoint*>(mo)->think();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Obj_TalkPointOrbThink(mobj_t* mo)
|
||||||
|
{
|
||||||
|
static_cast<Orb*>(mo)->think();
|
||||||
|
}
|
||||||
|
|
|
||||||
12
src/p_mobj.c
12
src/p_mobj.c
|
|
@ -6460,6 +6460,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
||||||
case MT_SCRIPT_THING:
|
case MT_SCRIPT_THING:
|
||||||
Obj_TalkPointThink(mobj);
|
Obj_TalkPointThink(mobj);
|
||||||
return;
|
return;
|
||||||
|
case MT_SCRIPT_THING_ORB:
|
||||||
|
Obj_TalkPointOrbThink(mobj);
|
||||||
|
return;
|
||||||
case MT_SPIKEDTARGET:
|
case MT_SPIKEDTARGET:
|
||||||
{
|
{
|
||||||
if (P_MobjWasRemoved(mobj->target) || (mobj->target->health <= 0) || (mobj->target->z == mobj->target->floorz))
|
if (P_MobjWasRemoved(mobj->target) || (mobj->target->health <= 0) || (mobj->target->z == mobj->target->floorz))
|
||||||
|
|
@ -10565,6 +10568,10 @@ fixed_t P_GetMobjDefaultScale(mobj_t *mobj)
|
||||||
return 4*FRACUNIT;
|
return 4*FRACUNIT;
|
||||||
case MT_WALLSPIKE:
|
case MT_WALLSPIKE:
|
||||||
return 2*FRACUNIT;
|
return 2*FRACUNIT;
|
||||||
|
case MT_SCRIPT_THING:
|
||||||
|
return 4*FRACUNIT;
|
||||||
|
case MT_SCRIPT_THING_ORB:
|
||||||
|
return 2*FRACUNIT;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -13841,6 +13848,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
|
||||||
Obj_SSWindowMapThingSpawn(mobj, mthing);
|
Obj_SSWindowMapThingSpawn(mobj, mthing);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MT_SCRIPT_THING:
|
||||||
|
{
|
||||||
|
Obj_TalkPointInit(mobj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue