Lua port of the capsule visual

No item collision or gameplay at all yet
This commit is contained in:
TehRealSalt 2019-09-15 04:51:45 -04:00
parent f7f27199a6
commit b39482d721
5 changed files with 290 additions and 0 deletions

View file

@ -7199,6 +7199,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_DRAFTDUST4",
"S_DRAFTDUST5",
"S_BATTLECAPSULE_SIDE1",
"S_BATTLECAPSULE_SIDE2",
"S_BATTLECAPSULE_TOP",
"S_BATTLECAPSULE_BUTTON",
"S_BATTLECAPSULE_SUPPORT",
"S_BATTLECAPSULE_SUPPORTFLY",
#ifdef SEENAMES
"S_NAMECHECK",
#endif
@ -7988,6 +7995,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_RINGSPARKS",
"MT_DRAFTDUST",
"MT_BATTLECAPSULE",
"MT_BATTLECAPSULE_PIECE",
#ifdef SEENAMES
"MT_NAMECHECK",
#endif

View file

@ -3437,6 +3437,13 @@ state_t states[NUMSTATES] =
{SPR_DRAF, 3, 1, {NULL}, 0, 0, S_DRAFTDUST5}, // S_DRAFTDUST4
{SPR_DRAF, 4, 1, {NULL}, 0, 0, S_NULL}, // S_DRAFTDUST5
{SPR_CAPS, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SIDE1
{SPR_CAPS, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SIDE2
{SPR_CAPS, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_TOP
{SPR_CAPS, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_BUTTON
{SPR_CAPS, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SUPPORT
{SPR_CAPS, FF_ANIMATE|5, -1, {NULL}, 3, 1, S_NULL}, // S_BATTLECAPSULE_SUPPORTFLY
#ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif
@ -20149,6 +20156,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_BATTLECAPSULE
2333, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_INVISIBLE, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
28<<FRACBITS, // radius
112<<FRACBITS, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_BATTLECAPSULE_PIECE
-1, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // 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
8<<FRACBITS, // radius
8<<FRACBITS, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
// ============================================================================================================================//
#ifdef SEENAMES

View file

@ -4096,6 +4096,13 @@ typedef enum state
S_DRAFTDUST4,
S_DRAFTDUST5,
S_BATTLECAPSULE_SIDE1,
S_BATTLECAPSULE_SIDE2,
S_BATTLECAPSULE_TOP,
S_BATTLECAPSULE_BUTTON,
S_BATTLECAPSULE_SUPPORT,
S_BATTLECAPSULE_SUPPORTFLY,
#ifdef SEENAMES
S_NAMECHECK,
#endif
@ -4902,6 +4909,9 @@ typedef enum mobj_type
MT_RINGSPARKS,
MT_DRAFTDUST,
MT_BATTLECAPSULE,
MT_BATTLECAPSULE_PIECE,
#ifdef SEENAMES
MT_NAMECHECK,
#endif

View file

@ -2524,6 +2524,34 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
S_StartSound(target, sfx_s3k80);
}
break;
case MT_BATTLECAPSULE:
{
mobj_t *cur;
target->fuse = 16;
cur = target->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
// Shoot every piece outward
if (cur->x != target->x && cur->y != target->y)
{
P_InstaThrust(cur,
R_PointToAngle2(target->x, target->y, cur->x, cur->y),
R_PointToDist2(target->x, target->y, cur->x, cur->y) / 12
);
}
cur->momz = 8 * target->scale * P_MobjFlip(target);
cur->flags &= ~MF_NOGRAVITY;
cur->fuse = 24;
cur = cur->hnext;
}
}
break;
default:
break;

View file

@ -6956,6 +6956,18 @@ void P_MobjThinker(mobj_t *mobj)
P_SetMobjStateNF(smok, smok->info->painstate); // same function, diff sprite
}
break;
case MT_BATTLECAPSULE_PIECE:
if (mobj->extravalue2)
mobj->frame |= FF_VERTICALFLIP;
else
mobj->frame &= ~FF_VERTICALFLIP;
if (mobj->flags2 & MF2_OBJECTFLIP)
mobj->eflags |= MFE_VERTICALFLIP;
if (mobj->fuse)
mobj->flags2 ^= MF2_DONTDRAW;
break;
//}
case MT_WATERDROP:
P_SceneryCheckWater(mobj);
@ -7403,6 +7415,27 @@ void P_MobjThinker(mobj_t *mobj)
return;
}
break;
case MT_BATTLECAPSULE:
if (!(mobj->fuse & 1))
{
const SINT8 amt = 96;
mobj_t *dust;
UINT8 i;
for (i = 0; i < 2; i++)
{
fixed_t xoffset = P_RandomRange(-amt, amt) * mobj->scale;
fixed_t yoffset = P_RandomRange(-amt, amt) * mobj->scale;
fixed_t zoffset = P_RandomRange(-(amt >> 1), (amt >> 1)) * mobj->scale;
dust = P_SpawnMobj(mobj->x + xoffset, mobj->y + yoffset,
mobj->z + (mobj->height >> 1) + zoffset, MT_EXPLODE);
}
if (dust && !P_MobjWasRemoved(dust)) // Only do for 1 explosion
S_StartSound(dust, sfx_s3k3d);
}
break;
//}
default:
break;
@ -9076,6 +9109,87 @@ void P_MobjThinker(mobj_t *mobj)
trail->color = mobj->color;
}
break;
case MT_BATTLECAPSULE:
{
SINT8 realflip = P_MobjFlip(mobj);
SINT8 flip = realflip; // Flying capsules needs flipped sprites, but not flipped gravity
fixed_t bottom;
mobj_t *cur;
if (mobj->extravalue1)
{
const INT32 speed = 6*TICRATE; // longer is slower
const fixed_t pi = 22*FRACUNIT/7; // Inaccurate, but is close enough for our usage
fixed_t sine = FINESINE((((2*pi*speed) * leveltime) >> ANGLETOFINESHIFT) & FINEMASK) * flip;
// Flying capsules are flipped upside-down, like S3K
flip = -flip;
// ALL CAPSULE MOVEMENT NEEDS TO HAPPEN AFTER THIS & ADD TO MOMENTUM FOR BOBBING TO BE ACCURATE
mobj->momz = sine/2;
}
// TODO: insert moving capsule code here
if (flip == -1)
bottom = mobj->z + mobj->height;
else
bottom = mobj->z;
cur = mobj->hnext;
// Move each piece to the proper position
while (cur && !P_MobjWasRemoved(cur))
{
fixed_t newx = mobj->x;
fixed_t newy = mobj->y;
fixed_t newz = bottom;
statenum_t state = (statenum_t)(cur->state-states);
cur->scale = mobj->scale;
cur->destscale = mobj->destscale;
cur->scalespeed = mobj->scalespeed;
cur->extravalue2 = mobj->extravalue1;
cur->flags2 = (cur->flags2 & ~MF2_OBJECTFLIP)|(mobj->flags2 & MF2_OBJECTFLIP);
if (state == S_BATTLECAPSULE_TOP)
newz += (80 * mobj->scale * flip);
else if (state == S_BATTLECAPSULE_BUTTON)
newz += (108 * mobj->scale * flip);
else if (state == S_BATTLECAPSULE_SUPPORT || state == S_BATTLECAPSULE_SUPPORTFLY)
{
fixed_t offx = mobj->radius;
fixed_t offy = mobj->radius;
if (cur->extravalue1 & 1)
offx = -offx;
if (cur->extravalue1 > 1)
offy = -offy;
newx += offx;
newy += offy;
}
else if (state == S_BATTLECAPSULE_SIDE1 || state == S_BATTLECAPSULE_SIDE2)
{
fixed_t offset = 48 * mobj->scale;
angle_t angle = (ANGLE_45 * cur->extravalue1);
newx += FixedMul(offset, FINECOSINE(angle >> ANGLETOFINESHIFT));
newy += FixedMul(offset, FINESINE(angle >> ANGLETOFINESHIFT));
newz += (12 * mobj->scale * flip);
cur->angle = angle + ANGLE_90;
}
P_TeleportMove(cur, newx, newy, newz);
cur = cur->hnext;
}
}
break;
//}
case MT_TURRET:
P_MobjCheckWater(mobj);
@ -10096,6 +10210,73 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
}
}
break;
case MT_BATTLECAPSULE:
{
mobj_t *cur, *prev = mobj;
UINT8 i;
// Flying capsules
if (!(mobj->eflags & MFE_ONGROUND))
{
mobj->flags |= MF_NOGRAVITY;
mobj->extravalue1 = 1; // Set extravalue1 for later reference
}
// Init hnext list
// Spherical top
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
P_SetMobjState(cur, S_BATTLECAPSULE_TOP);
P_SetTarget(&cur->target, mobj);
P_SetTarget(&cur->hprev, prev);
P_SetTarget(&prev->hnext, cur);
prev = cur;
// Tippity-top decorational button
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
P_SetMobjState(cur, S_BATTLECAPSULE_BUTTON);
P_SetTarget(&cur->target, mobj);
P_SetTarget(&cur->hprev, prev);
P_SetTarget(&prev->hnext, cur);
prev = cur;
// Supports on the bottom
for (i = 0; i < 4; i++)
{
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
cur->extravalue1 = i;
// TODO: use karma bomb wheels on grounded, moving capsules
if (mobj->extravalue1)
P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORTFLY);
else
P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT);
P_SetTarget(&cur->target, mobj);
P_SetTarget(&cur->hprev, prev);
P_SetTarget(&prev->hnext, cur);
prev = cur;
}
// Side paneling
for (i = 0; i < 8; i++)
{
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
cur->extravalue1 = i;
if (i & 1)
P_SetMobjState(cur, S_BATTLECAPSULE_SIDE2);
else
P_SetMobjState(cur, S_BATTLECAPSULE_SIDE1);
P_SetTarget(&cur->target, mobj);
P_SetTarget(&cur->hprev, prev);
P_SetTarget(&prev->hnext, cur);
prev = cur;
}
}
break;
default:
break;
}