Revert "Revert "Merge branch 'metalfixes' into 'toast_cleanup'""

This reverts commit c04b560e92.
This commit is contained in:
toaster 2019-07-03 00:58:02 +01:00
parent c04b560e92
commit 4ad1703ae3
13 changed files with 351 additions and 135 deletions

View File

@ -5125,7 +5125,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_METALSONIC_BADBOUNCE",
"S_METALSONIC_SHOOT",
"S_METALSONIC_PAIN",
"S_METALSONIC_DEATH",
"S_METALSONIC_DEATH1",
"S_METALSONIC_DEATH2",
"S_METALSONIC_DEATH3",
"S_METALSONIC_DEATH4",
"S_METALSONIC_FLEE1",
"S_METALSONIC_FLEE2",
"S_METALSONIC_FLEE3",

View File

@ -5662,7 +5662,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (vis->mobj->type == MT_CYBRAKDEMON)
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
else if (vis->mobj->type == MT_METALSONIC_BATTLE)
vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE);

View File

@ -1363,7 +1363,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
INT32 skinnum = TC_DEFAULT;
if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (spr->mobj->type == MT_CYBRAKDEMON)
if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized)
skinnum = TC_ALLWHITE;
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
skinnum = TC_METALSONIC;

View File

@ -1747,20 +1747,23 @@ state_t states[NUMSTATES] =
{SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4
{SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT
{SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
{SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
{SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
{SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
{SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
{SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER
{SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE
{SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE
{SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
{SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
{SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH
{SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
{SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2
{SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3
{SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4
{SPR_METL, 13, 8, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
{SPR_METL, 13, 8, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
{SPR_METL, 13, 0, {A_Repeat}, 11, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
{SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4
{SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
{SPR_METL, 11, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2
{SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3
{SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2
@ -6259,13 +6262,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_METALSONIC_DASH, // seestate
sfx_s3k54, // seesound
0, // reactiontime
sfx_trpowr, // attacksound
sfx_bechrg, // attacksound
S_METALSONIC_PAIN, // painstate
S_METALSONIC_VECTOR,// painchance
sfx_dmpain, // painsound
S_METALSONIC_BADBOUNCE, // meleestate
S_METALSONIC_SHOOT, // missilestate
S_METALSONIC_DEATH, // deathstate
S_METALSONIC_DEATH1,// deathstate
S_METALSONIC_FLEE1, // xdeathstate
sfx_s3k6e, // deathsound
MT_ENERGYBALL, // speed
@ -6297,7 +6300,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
0, // speed
32*FRACUNIT, // radius
64*FRACUNIT, // height
52*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
@ -9140,7 +9143,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_ENERGYBALL1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_s3k54, // seesound
sfx_bexpld, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate

View File

@ -1888,7 +1888,10 @@ typedef enum state
S_METALSONIC_BADBOUNCE,
S_METALSONIC_SHOOT,
S_METALSONIC_PAIN,
S_METALSONIC_DEATH,
S_METALSONIC_DEATH1,
S_METALSONIC_DEATH2,
S_METALSONIC_DEATH3,
S_METALSONIC_DEATH4,
S_METALSONIC_FLEE1,
S_METALSONIC_FLEE2,
S_METALSONIC_FLEE3,

View File

@ -1235,8 +1235,8 @@ static int lib_pHomingAttack(lua_State *L)
INLEVEL
if (!source || !enemy)
return LUA_ErrInvalid(L, "mobj_t");
P_HomingAttack(source, enemy);
return 0;
lua_pushboolean(L, P_HomingAttack(source, enemy));
return 1;
}
static int lib_pSuperReady(lua_State *L)

View File

@ -176,7 +176,7 @@ void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move);
mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet);
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
boolean P_SuperReady(player_t *player);
void P_DoJump(player_t *player, boolean soundandstate);
#if 0

View File

@ -725,6 +725,27 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
// vectorise metal - done in a special case as at this point neither has the right flags for touching
if (thing->type == MT_METALSONIC_BATTLE
&& (tmthing->flags & MF_MISSILE)
&& tmthing->target != thing
&& thing->state == &states[thing->info->spawnstate])
{
blockdist = thing->radius + tmthing->radius;
if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
return true; // didn't hit it
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
thing->flags2 |= MF2_CLASSICPUSH;
return true;
}
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING)))
return true;

View File

@ -5395,7 +5395,8 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (mobj->info->activesound)\
S_StartSound(mobj, mobj->info->activesound);\
if (mobj->info->painchance)\
P_SetMobjState(mobj, mobj->info->painchance)
P_SetMobjState(mobj, mobj->info->painchance);\
mobj->flags2 &= ~MF2_INVERTAIMABLE;\
// Metal Sonic battle boss
// You CAN put multiple Metal Sonics in a single map
@ -5485,25 +5486,16 @@ static void P_Boss9Thinker(mobj_t *mobj)
// AI goes here.
{
angle_t angle;
if (mobj->threshold)
if (mobj->threshold || mobj->movecount)
mobj->momz = (mobj->watertop-mobj->z)/16; // Float to your desired position FASTER
else
mobj->momz = (mobj->watertop-mobj->z)/40; // Float to your desired position
if (mobj->movecount == 2) {
if (mobj->movecount == 2)
{
mobj_t *spawner;
fixed_t dist = 0;
angle = 0x06000000*leveltime;
// Alter your energy bubble's size/position
if (mobj->health > 3) {
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
P_SetScale(mobj->tracer, mobj->tracer->destscale);
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
mobj->tracer->momx = mobj->momx;
mobj->tracer->momy = mobj->momy;
mobj->tracer->momz = mobj->momz;
}
angle = 0x06000000*leveltime; // wtf?
// Face your target
P_BossTargetPlayer(mobj, true);
@ -5514,27 +5506,150 @@ static void P_Boss9Thinker(mobj_t *mobj)
else
mobj->angle -= InvAngle(angle)/8;
// Alter your energy bubble's size/position
if (mobj->health > 3)
{
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
P_SetScale(mobj->tracer, mobj->tracer->destscale);
}
else
mobj->tracer->frame &= ~FF_TRANSMASK; // this causes a flicker but honestly i like it this way
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
mobj->tracer->momx = mobj->momx;
mobj->tracer->momy = mobj->momy;
mobj->tracer->momz = mobj->momz;
// Firin' mah lazors - INDICATOR
if (mobj->fuse > TICRATE/2)
{
tic_t shoottime, worktime, calctime;
shoottime = (TICRATE/((mobj->extravalue1 == 3) ? 8 : 4));
shoottime += (shoottime>>1);
worktime = shoottime*(mobj->threshold/2);
calctime = mobj->fuse-(TICRATE/2);
if (calctime <= worktime && (calctime % shoottime == 0))
{
mobj_t *missile;
missile = P_SpawnMissile(mobj, mobj->target, MT_MSGATHER);
S_StopSound(missile);
if (mobj->extravalue1 >= 2)
P_SetScale(missile, FRACUNIT>>1);
missile->destscale = missile->scale>>1;
missile->fuse = TICRATE/2;
missile->scalespeed = abs(missile->destscale - missile->scale)/missile->fuse;
missile->z -= missile->height/2;
missile->momx *= -1;
missile->momy *= -1;
missile->momz *= -1;
if (mobj->extravalue1 == 2)
{
UINT8 i;
mobj_t *spread;
for (i = 0; i < 5; i++)
{
if (i == 2)
continue;
spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type);
spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2);
P_InstaThrust(spread,spread->angle,-spread->info->speed);
spread->momz = missile->momz;
P_SetScale(spread, missile->scale);
spread->destscale = missile->destscale;
spread->scalespeed = missile->scalespeed;
spread->fuse = missile->fuse;
P_UnsetThingPosition(spread);
spread->x -= spread->fuse*spread->momx;
spread->y -= spread->fuse*spread->momy;
spread->z -= spread->fuse*spread->momz;
P_SetThingPosition(spread);
}
P_InstaThrust(missile,missile->angle,-missile->info->speed);
}
else if (mobj->extravalue1 >= 3)
{
UINT8 i;
mobj_t *spread;
mobj->target->z -= (4*missile->height);
for (i = 0; i < 5; i++)
{
if (i != 2)
{
spread = P_SpawnMissile(mobj, mobj->target, missile->type);
P_SetScale(spread, missile->scale);
spread->destscale = missile->destscale;
spread->fuse = missile->fuse;
spread->z -= spread->height/2;
spread->momx *= -1;
spread->momy *= -1;
spread->momz *= -1;
P_UnsetThingPosition(spread);
spread->x -= spread->fuse*spread->momx;
spread->y -= spread->fuse*spread->momy;
spread->z -= spread->fuse*spread->momz;
P_SetThingPosition(spread);
}
mobj->target->z += missile->height*2;
}
mobj->target->z -= (6*missile->height);
}
P_UnsetThingPosition(missile);
missile->x -= missile->fuse*missile->momx;
missile->y -= missile->fuse*missile->momy;
missile->z -= missile->fuse*missile->momz;
P_SetThingPosition(missile);
S_StartSound(mobj, sfx_s3kb3);
}
}
// up...
mobj->z += mobj->height/2;
// Spawn energy particles
for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) {
for (spawner = mobj->hnext; spawner; spawner = spawner->hnext)
{
dist = P_AproxDistance(spawner->x - mobj->x, spawner->y - mobj->y);
if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1)
break;
}
if (spawner) {
if (spawner)
{
mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER);
if (mobj->health > mobj->info->damage)
missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/5);
if (dist == 0)
missile->fuse = 0;
else
missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy));
if (missile->fuse > mobj->fuse)
P_RemoveMobj(missile);
if (mobj->health > mobj->info->damage)
{
P_SetScale(missile, FRACUNIT/2);
missile->color = SKINCOLOR_GOLD; // sonic cd electric power
}
else
{
P_SetScale(missile, FRACUNIT/4);
missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power
}
missile->destscale = missile->scale*2;
missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse;
missile->colorized = true;
}
// ...then down. easier than changing the missile's momz after-the-fact
mobj->z -= mobj->height/2;
}
// Pre-threshold reactiontime stuff for attack phases
if (mobj->reactiontime && mobj->movecount == 3) {
if (mobj->reactiontime && mobj->movecount == 3)
{
mobj->reactiontime--;
if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase
@ -5555,13 +5670,15 @@ static void P_Boss9Thinker(mobj_t *mobj)
}
// threshold is used for attacks/maneuvers.
if (mobj->threshold) {
if (mobj->threshold && mobj->movecount != 2) {
fixed_t speed = 20*FRACUNIT + FixedMul(40*FRACUNIT, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, mobj->info->spawnhealth<<FRACBITS));
int tries = 0;
UINT8 tries = 0;
// Firin' mah lazors
if (mobj->movecount == 3 && mobj->movedir == 1) {
if (!(mobj->threshold&1)) {
if (mobj->movecount == 3 && mobj->movedir == 1)
{
if (!(mobj->threshold & 1))
{
mobj_t *missile;
if (mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound);
@ -5573,18 +5690,20 @@ static void P_Boss9Thinker(mobj_t *mobj)
A_FaceTarget(mobj);
missile = P_SpawnMissile(mobj, mobj->target, mobj->info->speed);
if (mobj->extravalue1 == 2 || mobj->extravalue1 == 3) {
if (mobj->extravalue1 >= 2)
{
missile->destscale = FRACUNIT>>1;
P_SetScale(missile, missile->destscale);
}
missile->fuse = 3*TICRATE;
missile->z -= missile->height/2;
if (mobj->extravalue1 == 2) {
int i;
if (mobj->extravalue1 == 2)
{
UINT8 i;
mobj_t *spread;
missile->flags |= MF_MISSILE;
for (i = 0; i < 5; i++) {
for (i = 0; i < 5; i++)
{
if (i == 2)
continue;
spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type);
@ -5593,11 +5712,32 @@ static void P_Boss9Thinker(mobj_t *mobj)
spread->momz = missile->momz;
spread->destscale = FRACUNIT>>1;
P_SetScale(spread, spread->destscale);
spread->fuse = 3*TICRATE;
spread->fuse = missile->fuse;
}
missile->flags &= ~MF_MISSILE;
P_InstaThrust(missile,missile->angle,missile->info->speed);
}
} else {
else if (mobj->extravalue1 >= 3)
{
UINT8 i;
mobj_t *spread;
mobj->target->z -= (2*missile->height);
for (i = 0; i < 5; i++)
{
if (i != 2)
{
spread = P_SpawnMissile(mobj, mobj->target, missile->type);
spread->destscale = FRACUNIT>>1;
P_SetScale(spread, spread->destscale);
spread->fuse = missile->fuse;
spread->z -= spread->height/2;
}
mobj->target->z += missile->height;
}
mobj->target->z -= (3*missile->height);
}
}
else
{
P_SetMobjState(mobj, mobj->state->nextstate);
if (mobj->extravalue1 == 3)
mobj->reactiontime = TICRATE/8;
@ -5611,7 +5751,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
P_SpawnGhostMobj(mobj);
// Pinball attack!
if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) {
if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2))
{
if ((statenum_t)(mobj->state-states) != mobj->info->seestate)
P_SetMobjState(mobj, mobj->info->seestate);
if (mobj->movedir == 0) // mobj health == 1
@ -5620,7 +5761,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
P_InstaThrust(mobj, mobj->angle, 22*FRACUNIT);
else // mobj health == 2
P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT);
if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce
if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true))
{ // Hit a wall? Find a direction to bounce
mobj->threshold--;
P_SetMobjState(mobj, mobj->state->nextstate);
if (!mobj->threshold) { // failed bounce!
@ -5633,11 +5775,15 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->movecount = 0;
P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION);
P_SetMobjState(mobj, mobj->info->meleestate);
} else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce.
}
else if (!(mobj->threshold%4))
{ // We've decided to lock onto the player this bounce.
S_StartSound(mobj, sfx_s3k5a);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time
} else { // No homing, just use P_BounceMove
}
else
{ // No homing, just use P_BounceMove
S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct...
P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy);
@ -5651,7 +5797,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
// Vector form dodge!
mobj->angle += mobj->movedir;
P_InstaThrust(mobj, mobj->angle, -speed);
while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) {
while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16)
{
S_StartSound(mobj, sfx_mspogo);
P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
@ -5708,7 +5855,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (mobj->flags2 & MF2_FRET)
return;
if (mobj->state == &states[mobj->info->raisestate])
if (mobj->movecount == 1 || mobj->movecount == 2)
{ // Charging energy
if (mobj->momx != 0 || mobj->momy != 0) { // Apply the air breaks
if (abs(mobj->momx)+abs(mobj->momy) < FRACUNIT)
@ -5716,11 +5863,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
else
P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -6*FRACUNIT/8);
}
return;
if (mobj->state == states+mobj->info->raisestate)
return;
}
if (mobj->fuse == 0)
{
mobj->flags2 &= ~MF2_INVERTAIMABLE;
// It's time to attack! What are we gonna do?!
switch(mobj->movecount)
{
@ -5728,6 +5877,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
default:
// Fly up and prepare for an attack!
// We have to charge up first, so let's go up into the air
S_StartSound(mobj, sfx_beflap);
P_SetMobjState(mobj, mobj->info->raisestate);
if (mobj->floorz >= mobj->target->floorz)
mobj->watertop = mobj->floorz + 256*FRACUNIT;
@ -5735,33 +5885,69 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->watertop = mobj->target->floorz + 256*FRACUNIT;
break;
case 1: {
case 1:
// Okay, we're up? Good, time to gather energy...
if (mobj->health > mobj->info->damage)
{ // No more bubble if we're broken (pinch phase)
mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
P_SetTarget(&mobj->tracer, shield);
P_SetTarget(&shield->target, mobj);
// Attack 2: Energy shot!
switch (mobj->health)
{
case 8: // shoot once
default:
mobj->extravalue1 = 0;
mobj->threshold = 2;
break;
case 7: // spread shot (vertical)
mobj->extravalue1 = 4;
mobj->threshold = 2;
break;
case 6: // three shots
mobj->extravalue1 = 1;
mobj->threshold = 3*2;
break;
case 5: // spread shot (horizontal)
mobj->extravalue1 = 2;
mobj->threshold = 2;
break;
case 4: // machine gun
mobj->extravalue1 = 3;
mobj->threshold = 5*2;
break;
}
}
else
P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
{
mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
P_SetTarget(&mobj->tracer, shield);
P_SetTarget(&shield->target, mobj);
shield->height -= 20*FRACUNIT; // different offset...
shield->color = SKINCOLOR_MAGENTA;
shield->colorized = true;
P_SetMobjState(shield, S_FIRS1);
//P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2...
}
mobj->fuse = 4*TICRATE;
mobj->flags |= MF_PAIN;
if (mobj->info->attacksound)
S_StartSound(mobj, mobj->info->attacksound);
A_FaceTarget(mobj);
break;
}
case 2:
// We're all charged and ready now! Unleash the fury!!
if (mobj->health > mobj->info->damage)
S_StopSound(mobj);
mobj_t *removemobj = mobj->tracer;
P_SetTarget(&mobj->tracer, mobj->hnext);
P_RemoveMobj(removemobj);
if (mobj->health <= mobj->info->damage)
{
mobj_t *removemobj = mobj->tracer;
P_SetTarget(&mobj->tracer, mobj->hnext);
P_RemoveMobj(removemobj);
}
if (mobj->health <= mobj->info->damage) {
mobj_t *whoosh;
// Attack 1: Pinball dash!
if (mobj->health == 1)
mobj->movedir = 0;
@ -5776,32 +5962,23 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->threshold = 24; // bounce 24 times
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
} else {
whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct
whoosh->frame = FF_FULLBRIGHT;
whoosh->sprite = SPR_ARMA;
whoosh->destscale = whoosh->scale<<1;
whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale);
whoosh->height = 38*whoosh->scale;
whoosh->fuse = 10;
whoosh->color = SKINCOLOR_MAGENTA;
whoosh->colorized = true;
whoosh->flags |= MF_NOCLIPHEIGHT;
}
else
{
// Attack 2: Energy shot!
mobj->movedir = 1;
if (mobj->health >= 8)
mobj->extravalue1 = 0;
else if (mobj->health >= 5)
mobj->extravalue1 = 2;
else if (mobj->health >= 4)
mobj->extravalue1 = 1;
else
mobj->extravalue1 = 3;
switch(mobj->extravalue1) {
case 0: // shoot once
case 2: // spread-shot
default:
mobj->threshold = 2;
break;
case 1: // shoot 3 times
mobj->threshold = 3*2;
break;
case 3: // shoot like a goddamn machinegun
mobj->threshold = 8*2;
break;
}
// looking for the number of things to fire? that's done in case 1 now
}
break;
@ -5835,21 +6012,26 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->angle -= InvAngle(angle)/8;
//A_FaceTarget(mobj);
// Check if we're being attacked
if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj))
goto nodanger;
if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius)
goto nodanger;
if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius)
goto nodanger;
if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius)
goto nodanger;
if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius)
goto nodanger;
if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z)
goto nodanger;
if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height)
goto nodanger;
if (mobj->flags2 & MF2_CLASSICPUSH)
mobj->flags2 &= ~MF2_CLASSICPUSH; // a missile caught us in PIT_CheckThing!
else
{
// Check if we're being attacked
if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj))
goto nodanger;
if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius)
goto nodanger;
if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius)
goto nodanger;
if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius)
goto nodanger;
if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius)
goto nodanger;
if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z)
goto nodanger;
if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height)
goto nodanger;
}
// An incoming attack is detected! What should we do?!
// Go into vector form!
@ -5857,13 +6039,17 @@ static void P_Boss9Thinker(mobj_t *mobj)
return;
nodanger:
mobj->flags2 |= MF2_INVERTAIMABLE;
// Move normally: Approach the player using normal thrust and simulated friction.
dist = P_AproxDistance(mobj->x-mobj->target->x, mobj->y-mobj->target->y);
P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -3*FRACUNIT/8);
if (dist < 64*FRACUNIT)
if (dist < 64*FRACUNIT && !(mobj->target->player && mobj->target->player->homing))
P_Thrust(mobj, mobj->angle, -4*FRACUNIT);
else if (dist > 180*FRACUNIT)
P_Thrust(mobj, mobj->angle, FRACUNIT);
else
P_Thrust(mobj, mobj->angle + ANGLE_90, FINECOSINE((((angle_t)(leveltime*ANG1))>>ANGLETOFINESHIFT) & FINEMASK)>>1);
mobj->momz += P_AproxDistance(mobj->momx, mobj->momy)/12; // Move up higher the faster you're going.
}
}

View File

@ -4803,10 +4803,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
player->mo->momx /= 2;
player->mo->momy /= 2;
}
else if (player->charability == CA_HOMINGTHOK)
if (player->charability == CA_HOMINGTHOK)
{
player->mo->momx /= 3;
player->mo->momy /= 3;
player->mo->momx /= 2;
player->mo->momy /= 2;
}
if (player->charability == CA_HOMINGTHOK)
@ -7923,7 +7923,7 @@ static void P_MovePlayer(player_t *player)
if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously
&& (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super
{
// Force shield activation
// Force stop
if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
{
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
@ -7939,17 +7939,17 @@ static void P_MovePlayer(player_t *player)
if (P_SuperReady(player))
P_DoSuperTransformation(player, false);
break;
// Whirlwind/Thundercoin shield activation
// Whirlwind jump/Thunder jump
case SH_WHIRLWIND:
case SH_THUNDERCOIN:
P_DoJumpShield(player);
break;
// Armageddon shield activation
// Armageddon pow
case SH_ARMAGEDDON:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
P_BlackOw(player);
break;
// Attract shield activation
// Attraction blast
case SH_ATTRACT:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
player->homing = 2;
@ -7965,7 +7965,7 @@ static void P_MovePlayer(player_t *player)
else
S_StartSound(player->mo, sfx_s3ka6);
break;
// Elemental/Bubblewrap shield activation
// Elemental stomp/Bubble bounce
case SH_ELEMENTAL:
case SH_BUBBLEWRAP:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
@ -7979,7 +7979,7 @@ static void P_MovePlayer(player_t *player)
? sfx_s3k43
: sfx_s3k44);
break;
// Flame shield activation
// Flame burst
case SH_FLAMEAURA:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale));
@ -8000,8 +8000,7 @@ static void P_MovePlayer(player_t *player)
{
if (player->homing && player->mo->tracer)
{
P_HomingAttack(player->mo, player->mo->tracer);
if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET))
if (!P_HomingAttack(player->mo, player->mo->tracer))
{
P_SetObjectMomZ(player->mo, 6*FRACUNIT, false);
if (player->mo->eflags & MFE_UNDERWATER)
@ -8020,10 +8019,9 @@ static void P_MovePlayer(player_t *player)
if (player->homing && player->mo->tracer)
{
P_SpawnThokMobj(player);
P_HomingAttack(player->mo, player->mo->tracer);
// But if you don't, then stop homing.
if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET))
if (!P_HomingAttack(player->mo, player->mo->tracer))
{
if (player->mo->eflags & MFE_UNDERWATER)
P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false);
@ -8621,7 +8619,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
continue; // not a valid target
if (mo->health <= 0) // dead
@ -8633,9 +8631,6 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
if (mo->flags2 & MF2_FRET)
continue;
if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus)
continue;
if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING))
continue;
@ -8689,17 +8684,23 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
return closestmo;
}
void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
{
fixed_t zdist;
fixed_t dist;
fixed_t ns = 0;
if (!enemy)
return;
return false;
if (!(enemy->health))
return;
if (!enemy->health)
return false;
if (enemy->flags2 & MF2_FRET)
return false;
if (!(enemy->flags & (MF_SHOOTABLE|MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
return false;
// change angle
source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y);
@ -8742,6 +8743,8 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns);
source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns);
source->momz = FixedMul(FixedDiv(zdist, dist), ns);
return true;
}
// Search for emeralds

View File

@ -528,12 +528,9 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
|| color == SKINCOLOR_NONE)
{
if (skinnum == TC_ALLWHITE)
memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8**));
memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8));
else if (skinnum == TC_BLINK && color != SKINCOLOR_NONE)
{
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
dest_colormap[i] = Color_Index[color-1][3];
}
memset(dest_colormap, Color_Index[color-1][3], NUM_PALETTE_ENTRIES * sizeof(UINT8));
else
{
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)

View File

@ -723,7 +723,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
{
// translate certain pixels to white
colfunc = transcolfunc;
if (vis->mobj->type == MT_CYBRAKDEMON)
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
else if (vis->mobj->type == MT_METALSONIC_BATTLE)
dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE);

View File

@ -137,7 +137,7 @@ sfxinfo_t S_sfx[NUMSFX] =
// Game objects, etc
{"appear", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Appearing platform"},
{"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon explosion"},
{"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon pow"},
{"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing!
{"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing!
{"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"},
@ -304,7 +304,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"},
{"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble Shield"},
{"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction blast"},
{"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning Shield"},
{"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder Shield"},
{"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"},
{"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"},
{"s3k44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble bounce"},