* Add native support for multi-hit badiks to MF_ENEMY.

* MF2_FRET application and removal.
   * Flashing when flag present.
   * Bounce player back on successful damaging.
   * Add their spawnhealth to the chain.
* Reduce code duplication in P_TouchSpecialThing.
* Play with Crawla Commander a little bit as a test of its power.
This commit is contained in:
toasterbabe 2018-05-02 23:48:50 +01:00
parent 856edd50df
commit 6d1ba20a1d
5 changed files with 626 additions and 679 deletions

View file

@ -3760,7 +3760,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_CCOMMAND3, // seestate S_CCOMMAND3, // seestate
sfx_None, // seesound sfx_None, // seesound
2*TICRATE, // reactiontime 2*TICRATE, // reactiontime
sfx_None, // attacksound sfx_s3k60, // attacksound
S_CCOMMAND3, // painstate S_CCOMMAND3, // painstate
200, // painchance 200, // painchance
sfx_dmpain, // painsound sfx_dmpain, // painsound
@ -3775,7 +3775,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_s3k5d, // activesound
MF_SLIDEME|MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE, // flags MF_SLIDEME|MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View file

@ -5005,11 +5005,6 @@ void A_CrawlaCommanderThink(mobj_t *actor)
else else
thefloor = actor->floorz; thefloor = actor->floorz;
if (actor->fuse & 1)
actor->flags2 |= MF2_DONTDRAW;
else
actor->flags2 &= ~MF2_DONTDRAW;
if (actor->reactiontime > 0) if (actor->reactiontime > 0)
actor->reactiontime--; actor->reactiontime--;
@ -5043,14 +5038,13 @@ void A_CrawlaCommanderThink(mobj_t *actor)
dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y);
if (actor->target->player && actor->health > 1) if (actor->target->player)
{ {
if (dist < FixedMul(128*FRACUNIT, actor->scale) if (dist < FixedMul(64<<(FRACBITS+(actor->health == 1 ? 0 : 1)), actor->scale)
&& ((actor->target->player->pflags & PF_JUMPED) || (actor->target->player->pflags & PF_SPINNING))) && ((actor->target->player->pflags & PF_JUMPED) || (actor->target->player->pflags & PF_SPINNING)))
{ {
// Auugh! He's trying to kill you! Strafe! STRAAAAFFEEE!! // Auugh! She's trying to kill you! Strafe! STRAAAAFFEEE!!
if (actor->target->momx || actor->target->momy) P_InstaThrust(actor, actor->angle - ANGLE_180, FixedMul(20*FRACUNIT, actor->scale));
P_InstaThrust(actor, actor->angle - ANGLE_180, FixedMul(20*FRACUNIT, actor->scale));
return; return;
} }
} }
@ -5076,7 +5070,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
actor->angle -= (P_RandomByte()<<10); actor->angle -= (P_RandomByte()<<10);
if (actor->health > 1) if (actor->health > 1)
P_InstaThrust(actor, actor->angle, FixedMul(10*FRACUNIT, actor->scale)); P_Thrust(actor, actor->angle, 2*actor->scale);
} }
else if (!actor->reactiontime) else if (!actor->reactiontime)
{ {
@ -5085,8 +5079,9 @@ void A_CrawlaCommanderThink(mobj_t *actor)
if (dist < FixedMul(512*FRACUNIT, actor->scale)) if (dist < FixedMul(512*FRACUNIT, actor->scale))
{ {
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
P_InstaThrust(actor, actor->angle, FixedMul(60*FRACUNIT, actor->scale)); P_InstaThrust(actor, actor->angle, FixedMul(30*FRACUNIT, actor->scale));
actor->threshold = 1; actor->threshold = 1;
S_StartSound(actor, actor->info->attacksound);
} }
} }
actor->reactiontime = 2*TICRATE + P_RandomByte()/2; actor->reactiontime = 2*TICRATE + P_RandomByte()/2;
@ -5103,6 +5098,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
actor->momz = FixedMul(locvar2, actor->scale); actor->momz = FixedMul(locvar2, actor->scale);
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
P_InstaThrust(actor, actor->angle, FixedMul(locvar2/8, actor->scale)); P_InstaThrust(actor, actor->angle, FixedMul(locvar2/8, actor->scale));
S_StartSound(actor, actor->info->activesound);
// pogo on player // pogo on player
} }
else else

View file

@ -349,8 +349,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->spectator) if (player->spectator)
return; return;
// Ignore eggman in "ouchie" mode // Ignore multihits in "ouchie" mode
if (special->flags & MF_BOSS && special->flags2 & MF2_FRET) if (special->flags & (MF_ENEMY|MF_BOSS) && special->flags2 & MF2_FRET)
return; return;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
@ -363,14 +363,52 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
? (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2) ? (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2)
: 0); : 0);
if (special->flags & MF_BOSS) if ((special->flags & (MF_ENEMY|MF_BOSS)) && !(special->flags & MF_MISSILE))
{ {
////////////////////////////////////////////////////////
/////ENEMIES & BOSSES!!/////////////////////////////////
////////////////////////////////////////////////////////
if (special->type == MT_BLACKEGGMAN) if (special->type == MT_BLACKEGGMAN)
{ {
P_DamageMobj(toucher, special, special, 1, 0); // ouch P_DamageMobj(toucher, special, special, 1, 0); // ouch
return; return;
} }
if (special->type == MT_BIGMINE)
{
special->momx = toucher->momx/3;
special->momy = toucher->momy/3;
special->momz = toucher->momz/3;
toucher->momx /= -8;
toucher->momy /= -8;
toucher->momz /= -8;
special->flags &= ~MF_SPECIAL;
if (special->info->activesound)
S_StartSound(special, special->info->activesound);
P_SetTarget(&special->tracer, toucher);
player->homing = 0;
return;
}
if (special->type == MT_GSNAPPER && !elementalpierce
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z
&& P_DamageMobj(toucher, special, special, 1, DMG_SPIKE))
return; // Can only hit snapper from above
if (special->type == MT_SHARP
&& ((special->state == &states[special->info->xdeathstate]) || (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0)))
{
if (player->pflags & PF_BOUNCING)
{
toucher->momz = -toucher->momz;
P_DoAbilityBounce(player, false);
return;
}
else if (P_DamageMobj(toucher, special, special, 1, DMG_SPIKE))
return; // Cannot hit sharp from above or when red and angry
}
if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
|| (player->pflags & (PF_SPINNING|PF_GLIDING)) || (player->pflags & (PF_SPINNING|PF_GLIDING))
@ -388,15 +426,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
if (player->pflags & PF_BOUNCING) if (player->pflags & PF_BOUNCING)
P_DoAbilityBounce(player, false); P_DoAbilityBounce(player, false);
toucher->momx = -toucher->momx; if (special->info->spawnhealth > 1) // Multi-hit? Bounce back!
toucher->momy = -toucher->momy; {
toucher->momx = -toucher->momx;
toucher->momy = -toucher->momy;
}
P_DamageMobj(special, toucher, toucher, 1, 0); P_DamageMobj(special, toucher, toucher, 1, 0);
} }
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP)) else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) || (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP)))
&& player->charability == CA_FLY && player->charability == CA_FLY
&& (player->powers[pw_tailsfly] && (player->powers[pw_tailsfly]
|| toucher->state-states == S_PLAY_FLY_TIRED)) // Tails can shred stuff with his propeller. || toucher->state-states == S_PLAY_FLY_TIRED)) // Tails can shred stuff with her propeller.
{ {
toucher->momz = -toucher->momz/2; toucher->momz = -toucher->momz/2;
@ -407,81 +448,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
} }
else if ((special->flags & MF_ENEMY) && !(special->flags & MF_MISSILE))
{
////////////////////////////////////////////////////////
/////ENEMIES!!//////////////////////////////////////////
////////////////////////////////////////////////////////
if (special->type == MT_BIGMINE)
{
special->momx = toucher->momx/3;
special->momy = toucher->momy/3;
special->momz = toucher->momz/3;
toucher->momx /= -8;
toucher->momy /= -8;
toucher->momz /= -8;
special->flags &= ~MF_SPECIAL;
if (special->info->activesound)
S_StartSound(special, special->info->activesound);
P_SetTarget(&special->tracer, toucher);
player->homing = 0;
return;
}
else if (special->type == MT_GSNAPPER && !(((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce)
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z
&& !(player->powers[pw_shield] & SH_PROTECTSPIKE))
{
// Can only hit snapper from above
P_DamageMobj(toucher, special, special, 1, DMG_SPIKE);
}
else if (special->type == MT_SHARP
&& ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2))
&& !(player->powers[pw_shield] & SH_PROTECTSPIKE))
{
if (player->pflags & PF_BOUNCING)
{
toucher->momz = -toucher->momz;
P_DoAbilityBounce(player, false);
}
else // Cannot hit sharp from above or when red and angry
P_DamageMobj(toucher, special, special, 1, DMG_SPIKE);
}
else if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
|| (player->pflags & (PF_SPINNING|PF_GLIDING))
|| (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)
|| ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0))
|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
{
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
{
if (elementalpierce == 2)
P_DoBubbleBounce(player);
else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
toucher->momz = -toucher->momz;
}
if (player->pflags & PF_BOUNCING)
P_DoAbilityBounce(player, false);
P_DamageMobj(special, toucher, toucher, 1, 0);
}
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) // Flame is bad at logic - JTE
&& player->charability == CA_FLY
&& (player->powers[pw_tailsfly]
|| toucher->state-states == S_PLAY_FLY_TIRED)) // Tails can shred stuff with his propeller.
{
if (P_MobjFlip(toucher)*toucher->momz < 0)
toucher->momz = -toucher->momz/2;
P_DamageMobj(special, toucher, toucher, 1, 0);
}
else
P_DamageMobj(toucher, special, special, 1, 0);
return;
}
else if (special->flags & MF_FIRE) else if (special->flags & MF_FIRE)
{ {
P_DamageMobj(toucher, special, special, 1, DMG_FIRE); P_DamageMobj(toucher, special, special, 1, DMG_FIRE);
@ -2195,21 +2161,27 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
{ {
if (target->flags & MF_BOSS) if (target->flags & MF_BOSS)
score = 1000; score = 1000;
else if ((target->flags & MF_ENEMY) && !(target->flags & MF_MISSILE)) else if ((target->flags & MF_ENEMY) && !(target->flags & MF_MISSILE) && target->info->spawnhealth)
{ {
UINT8 locscoreadd = source->player->scoreadd + target->info->spawnhealth;
mobj_t *scoremobj; mobj_t *scoremobj;
UINT32 scorestate = mobjinfo[MT_SCORE].spawnstate; UINT32 scorestate = mobjinfo[MT_SCORE].spawnstate;
scoremobj = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2), MT_SCORE); scoremobj = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2), MT_SCORE);
// On ground? No chain starts. // More Sonic-like point system
if (!source->player->powers[pw_invulnerability] && P_IsObjectOnGround(source)) if (!mariomode) switch (locscoreadd)
{ {
source->player->scoreadd = 0; case 1: score = 100; break;
score = 100; case 2: score = 200; scorestate += 1; break;
case 3: score = 500; scorestate += 2; break;
case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14:
score = 1000; scorestate += 3; break;
default: score = 10000; scorestate += 4; break;
} }
// Mario Mode has Mario-like chain point values // Mario Mode has Mario-like chain point values
else if (mariomode) switch (++source->player->scoreadd) else switch (locscoreadd)
{ {
case 1: score = 100; break; case 1: score = 100; break;
case 2: score = 200; scorestate += 1; break; case 2: score = 200; scorestate += 1; break;
@ -2229,19 +2201,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
scorestate += 10; scorestate += 10;
break; break;
} }
// More Sonic-like point system
else switch (++source->player->scoreadd)
{
case 1: score = 100; break;
case 2: score = 200; scorestate += 1; break;
case 3: score = 500; scorestate += 2; break;
case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14:
score = 1000; scorestate += 3; break;
default: score = 10000; scorestate += 4; break;
}
P_SetMobjState(scoremobj, scorestate); P_SetMobjState(scoremobj, scorestate);
// On ground? No chain starts.
if (!source->player->powers[pw_invulnerability] && P_IsObjectOnGround(source))
source->player->scoreadd = locscoreadd;
} }
} }
@ -2385,6 +2350,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
P_SpawnMobjFromMobj(target, 0, 0, 0, MT_YELLOWSPRING); P_SpawnMobjFromMobj(target, 0, 0, 0, MT_YELLOWSPRING);
break; break;
case MT_CRAWLACOMMANDER:
target->momx = target->momy = target->momz = 0;
break;
case MT_EGGMOBILE3: case MT_EGGMOBILE3:
{ {
thinker_t *th; thinker_t *th;
@ -3131,36 +3100,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return false; return false;
} }
// Special case for Crawla Commander if (target->flags & (MF_ENEMY|MF_BOSS))
if (target->type == MT_CRAWLACOMMANDER)
{
if (!force && target->fuse) // Invincible
return false;
#ifdef HAVE_BLUA
if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target))
return true;
#endif
if (target->health > 1)
{
if (target->info->painsound)
S_StartSound(target, target->info->painsound);
target->fuse = TICRATE/2;
target->flags2 |= MF2_FRET;
}
else
{
target->flags |= MF_NOGRAVITY;
target->fuse = 0;
}
target->momx = target->momy = target->momz = 0;
P_InstaThrust(target, target->angle-ANGLE_180, FixedMul(5*FRACUNIT, target->scale));
}
else if (target->flags & MF_BOSS)
{ {
if (!force && target->flags2 & MF2_FRET) // Currently flashing from being hit if (!force && target->flags2 & MF2_FRET) // Currently flashing from being hit
return false; return false;
@ -3173,13 +3113,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (target->health > 1) if (target->health > 1)
target->flags2 |= MF2_FRET; target->flags2 |= MF2_FRET;
} }
#ifdef HAVE_BLUA
else if (target->flags & MF_ENEMY)
{
if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target))
return true;
}
#endif
player = target->player; player = target->player;
@ -3348,6 +3281,18 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
else else
switch (target->type) switch (target->type)
{ {
case MT_CRAWLACOMMANDER:
if (target->info->painsound)
S_StartSound(target, target->info->painsound);
target->fuse = TICRATE/2;
target->momz = 0;
P_InstaThrust(target, target->angle-ANGLE_180, FixedMul(5*FRACUNIT, target->scale));
P_SetMobjState(target, target->info->painstate);
break;
case MT_EGGMOBILE2: // egg slimer case MT_EGGMOBILE2: // egg slimer
if (target->health < target->info->damage) // in pinch phase if (target->health < target->info->damage) // in pinch phase
{ {

File diff suppressed because it is too large Load diff

View file

@ -717,7 +717,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap; dc_colormap = vis->colormap;
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
{ {
// translate certain pixels to white // translate certain pixels to white
colfunc = transcolfunc; colfunc = transcolfunc;