Update UCRP_UFOATTACKMETHOD into UCRP_TARGETATTACKMETHOD

Supports Prison Eggs and Gachabom now as well.
For the original behaviour, combine with the new UCRP_SMASHUFO.
This commit is contained in:
toaster 2023-10-17 21:03:20 +01:00
parent b91823540b
commit 01b97cb829
7 changed files with 124 additions and 58 deletions

View file

@ -396,8 +396,9 @@ typedef enum
UFOD_ORBINAUT = 1<<4, UFOD_ORBINAUT = 1<<4,
UFOD_JAWZ = 1<<5, UFOD_JAWZ = 1<<5,
UFOD_SPB = 1<<6, UFOD_SPB = 1<<6,
UFOD_GACHABOM = 1<<7,
// free up to and including 1<<31 // free up to and including 1<<31
} ufodamaging_t; } targetdamaging_t;
struct roundconditions_t struct roundconditions_t
{ {
@ -416,7 +417,7 @@ struct roundconditions_t
UINT8 hittrackhazard[((MAX_LAPS+1)/8) + 1]; UINT8 hittrackhazard[((MAX_LAPS+1)/8) + 1];
ufodamaging_t ufodamaging; targetdamaging_t targetdamaging;
mobjeflag_t wet_player; mobjeflag_t wet_player;

View file

@ -2896,7 +2896,8 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
else if ((offset=0) || fastcmp(params[0], "FINISHCOOL") else if ((offset=0) || fastcmp(params[0], "FINISHCOOL")
|| (++offset && fastcmp(params[0], "FINISHPERFECT")) || (++offset && fastcmp(params[0], "FINISHPERFECT"))
|| (++offset && fastcmp(params[0], "FINISHALLPRISONS")) || (++offset && fastcmp(params[0], "FINISHALLPRISONS"))
|| (++offset && fastcmp(params[0], "NOCONTEST"))) || (++offset && fastcmp(params[0], "NOCONTEST"))
|| (++offset && fastcmp(params[0], "SMASHUFO")))
{ {
//PARAMCHECK(1); //PARAMCHECK(1);
ty = UCRP_FINISHCOOL + offset; ty = UCRP_FINISHCOOL + offset;
@ -3007,19 +3008,26 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
} }
} }
} }
else if (fastcmp(params[0], "UFOATTACKMETHOD")) else if (fastcmp(params[0], "TARGETATTACKMETHOD"))
{ {
PARAMCHECK(1); PARAMCHECK(1);
ty = UCRP_UFOATTACKMETHOD; ty = UCRP_TARGETATTACKMETHOD;
// See ufodamaging_t // See targetdamaging_t
if ((offset=1) || fastcmp(params[1], "BOOST") if (fastcmp(params[1], "BOOST"))
|| (++offset && fastcmp(params[1], "WHIP")) re = UFOD_BOOST;
|| (++offset && fastcmp(params[1], "BANANA")) else if (fastcmp(params[1], "WHIP"))
|| (++offset && fastcmp(params[1], "ORBINAUT")) re = UFOD_WHIP;
|| (++offset && fastcmp(params[1], "JAWZ")) else if (fastcmp(params[1], "BANANA"))
|| (++offset && fastcmp(params[1], "SPB"))) re = UFOD_BANANA;
re = offset; else if (fastcmp(params[1], "ORBINAUT"))
re = UFOD_ORBINAUT;
else if (fastcmp(params[1], "JAWZ"))
re = UFOD_JAWZ;
else if (fastcmp(params[1], "SPB"))
re = UFOD_SPB;
else if (fastcmp(params[1], "GACHABOM"))
re = UFOD_GACHABOM;
else else
{ {
deh_warning("Unknown attack method %s for condition ID %d", params[1], id+1); deh_warning("Unknown attack method %s for condition ID %d", params[1], id+1);

View file

@ -1505,6 +1505,15 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
case UCRP_NOCONTEST: case UCRP_NOCONTEST:
return (player->pflags & PF_NOCONTEST); return (player->pflags & PF_NOCONTEST);
case UCRP_SMASHUFO:
return (
specialstageinfo.valid == true
&& (
P_MobjWasRemoved(specialstageinfo.ufo)
|| specialstageinfo.ufo->health <= 1
)
);
case UCRP_MAKERETIRE: case UCRP_MAKERETIRE:
{ {
// You can't "make" someone retire in coop. // You can't "make" someone retire in coop.
@ -1683,15 +1692,8 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
return (!(player->roundconditions.hittrackhazard[requiredlap] & requiredbit) != (cn->requirement == 1)); return (!(player->roundconditions.hittrackhazard[requiredlap] & requiredbit) != (cn->requirement == 1));
} }
case UCRP_UFOATTACKMETHOD: case UCRP_TARGETATTACKMETHOD:
return ( return (player->roundconditions.targetdamaging == (targetdamaging_t)cn->requirement);
specialstageinfo.valid == true
&& (
P_MobjWasRemoved(specialstageinfo.ufo)
|| specialstageinfo.ufo->health <= 1
)
&& player->roundconditions.ufodamaging == (ufodamaging_t)(1<<cn->requirement)
);
case UCRP_WETPLAYER: case UCRP_WETPLAYER:
return (((player->roundconditions.wet_player & cn->requirement) == 0) return (((player->roundconditions.wet_player & cn->requirement) == 0)
@ -2314,10 +2316,15 @@ static const char *M_GetConditionString(condition_t *cn)
case UCRP_FINISHPERFECT: case UCRP_FINISHPERFECT:
return "finish a perfect round"; return "finish a perfect round";
case UCRP_FINISHALLPRISONS: case UCRP_FINISHALLPRISONS:
return "break every prison"; return "break every Prison Egg";
case UCRP_NOCONTEST: case UCRP_NOCONTEST:
return "NO CONTEST"; return "NO CONTEST";
case UCRP_SMASHUFO:
if (!gamedata->everseenspecial)
return NULL;
return "smash the UFO Catcher";
case UCRP_MAKERETIRE: case UCRP_MAKERETIRE:
{ {
if (cn->requirement < 0 || !skins[cn->requirement].realname[0]) if (cn->requirement < 0 || !skins[cn->requirement].realname[0])
@ -2387,7 +2394,7 @@ static const char *M_GetConditionString(condition_t *cn)
return va("%s on lap %u", work, cn->extrainfo1); return va("%s on lap %u", work, cn->extrainfo1);
} }
case UCRP_UFOATTACKMETHOD: case UCRP_TARGETATTACKMETHOD:
{ {
if (!gamedata->everseenspecial) if (!gamedata->everseenspecial)
return NULL; return NULL;
@ -2396,24 +2403,28 @@ static const char *M_GetConditionString(condition_t *cn)
switch (cn->requirement) switch (cn->requirement)
{ {
case 1: // See targetdamaging_t
case UFOD_BOOST:
work = "boost power"; work = "boost power";
break; break;
case 2: case UFOD_WHIP:
work = "Insta-Whip"; work = "Insta-Whip";
break; break;
case 3: case UFOD_BANANA:
work = "Bananas"; work = "Bananas";
break; break;
case 4: case UFOD_ORBINAUT:
work = "Orbinauts"; work = "Orbinauts";
break; break;
case 5: case UFOD_JAWZ:
work = "Jawz"; work = "Jawz";
break; break;
case 6: case UFOD_SPB:
work = "Self Propelled Bombs"; work = "Self Propelled Bombs";
break; break;
case UFOD_GACHABOM:
work = "Gachabom";
break;
default: default:
break; break;
} }
@ -2421,7 +2432,7 @@ static const char *M_GetConditionString(condition_t *cn)
if (work == NULL) if (work == NULL)
return va("INVALID ATTACK CONDITION \"%d:%d\"", cn->type, cn->requirement); return va("INVALID ATTACK CONDITION \"%d:%d\"", cn->type, cn->requirement);
return va("smash the UFO Catcher using only %s", work); return va("using only %s", work);
} }
case UCRP_WETPLAYER: case UCRP_WETPLAYER:

View file

@ -97,6 +97,7 @@ typedef enum
UCRP_FINISHPERFECT, // Finish a perfect race UCRP_FINISHPERFECT, // Finish a perfect race
UCRP_FINISHALLPRISONS, // Break all prisons UCRP_FINISHALLPRISONS, // Break all prisons
UCRP_NOCONTEST, // No Contest UCRP_NOCONTEST, // No Contest
UCRP_SMASHUFO, // Smash the UFO Catcher
UCRP_MAKERETIRE, // Make another player of [skin] No Contest UCRP_MAKERETIRE, // Make another player of [skin] No Contest
@ -124,7 +125,7 @@ typedef enum
UCRP_TRACKHAZARD, // (Don't) get hit by a track hazard (maybe specific lap) UCRP_TRACKHAZARD, // (Don't) get hit by a track hazard (maybe specific lap)
UCRP_UFOATTACKMETHOD, // Defeat a UFO Catcher using only one method UCRP_TARGETATTACKMETHOD, // Break targets/UFO using only one method
UCRP_WETPLAYER, // Don't touch [strictness] [fluid] UCRP_WETPLAYER, // Don't touch [strictness] [fluid]
} conditiontype_t; } conditiontype_t;

View file

@ -764,7 +764,7 @@ static void UFOKillPieces(mobj_t *ufo)
static UINT8 GetUFODamage(mobj_t *inflictor, UINT8 damageType) static UINT8 GetUFODamage(mobj_t *inflictor, UINT8 damageType)
{ {
UINT8 ret = 0; UINT8 ret = 0;
ufodamaging_t ufodamaging = UFOD_GENERIC; targetdamaging_t targetdamaging = UFOD_GENERIC;
if (inflictor != NULL && P_MobjWasRemoved(inflictor) == false) if (inflictor != NULL && P_MobjWasRemoved(inflictor) == false)
{ {
@ -773,46 +773,52 @@ static UINT8 GetUFODamage(mobj_t *inflictor, UINT8 damageType)
// Shields deal chip damage. // Shields deal chip damage.
case MT_JAWZ_SHIELD: case MT_JAWZ_SHIELD:
{ {
ufodamaging = UFOD_JAWZ; targetdamaging = UFOD_JAWZ;
ret = 10; ret = 10;
break; break;
} }
case MT_ORBINAUT_SHIELD: case MT_ORBINAUT_SHIELD:
{ {
ufodamaging = UFOD_ORBINAUT; targetdamaging = UFOD_ORBINAUT;
ret = 10; ret = 10;
break; break;
} }
case MT_INSTAWHIP: case MT_INSTAWHIP:
{ {
ufodamaging = UFOD_WHIP; targetdamaging = UFOD_WHIP;
ret = 10; ret = 10;
break; break;
} }
case MT_JAWZ: case MT_JAWZ:
{ {
// Thrown Jawz deal a bit extra. // Thrown Jawz deal a bit extra.
ufodamaging = UFOD_JAWZ; targetdamaging = UFOD_JAWZ;
ret = 15; ret = 15;
break; break;
} }
case MT_ORBINAUT: case MT_ORBINAUT:
{ {
// Thrown orbinauts deal double damage. // Thrown orbinauts deal double damage.
ufodamaging = UFOD_ORBINAUT; targetdamaging = UFOD_ORBINAUT;
ret = 20; ret = 20;
break; break;
} }
case MT_GACHABOM:
{
// Thrown gachabom need to be tracked, but have no special damage value as of yet.
targetdamaging = UFOD_GACHABOM;
break;
}
case MT_SPB: case MT_SPB:
{ {
// SPB deals triple damage. // SPB deals triple damage.
ufodamaging |= UFOD_SPB; targetdamaging |= UFOD_SPB;
ret = 30; ret = 30;
break; break;
} }
case MT_BANANA: case MT_BANANA:
{ {
ufodamaging = UFOD_BANANA; targetdamaging = UFOD_BANANA;
// Banana snipes deal triple damage, // Banana snipes deal triple damage,
// laid down bananas deal regular damage. // laid down bananas deal regular damage.
@ -828,7 +834,7 @@ static UINT8 GetUFODamage(mobj_t *inflictor, UINT8 damageType)
case MT_PLAYER: case MT_PLAYER:
{ {
// Players deal damage relative to how many sneakers they used. // Players deal damage relative to how many sneakers they used.
ufodamaging = UFOD_BOOST; targetdamaging = UFOD_BOOST;
ret = 15 * max(1, inflictor->player->numsneakers); ret = 15 * max(1, inflictor->player->numsneakers);
break; break;
} }
@ -845,20 +851,9 @@ static UINT8 GetUFODamage(mobj_t *inflictor, UINT8 damageType)
} }
} }
{ P_TrackRoundConditionTargetDamage(targetdamaging);
// We have to iterate over all players, otherwise a player who gets exactly one hit in will trick the Challenges system.
UINT8 i;
for (i = 0; i <= splitscreen; i++)
{
if (!playeringame[g_localplayers[i]])
continue;
if (players[g_localplayers[i]].spectator)
continue;
players[i].roundconditions.ufodamaging |= ufodamaging;
}
}
if (ret) if (ret != 0)
return ret; return ret;
// Guess from damage type. // Guess from damage type.

View file

@ -977,10 +977,21 @@ void P_TouchCheatcheck(mobj_t *post, player_t *player, boolean snaptopost)
player->cheatchecknum = post->health; player->cheatchecknum = post->health;
} }
static void P_AddBrokenPrison(mobj_t *target, mobj_t *source) void P_TrackRoundConditionTargetDamage(targetdamaging_t targetdamaging)
{ {
(void)target; UINT8 i;
for (i = 0; i <= splitscreen; i++)
{
if (!playeringame[g_localplayers[i]])
continue;
if (players[g_localplayers[i]].spectator)
continue;
players[i].roundconditions.targetdamaging |= targetdamaging;
}
}
static void P_AddBrokenPrison(mobj_t *target, mobj_t *inflictor, mobj_t *source)
{
if (!battleprisons) if (!battleprisons)
return; return;
@ -1002,6 +1013,43 @@ static void P_AddBrokenPrison(mobj_t *target, mobj_t *source)
K_SpawnBattlePoints(source->player, NULL, 1); K_SpawnBattlePoints(source->player, NULL, 1);
} }
targetdamaging_t targetdamaging = UFOD_GENERIC;
if (P_MobjWasRemoved(inflictor) == true)
;
else switch (inflictor->type)
{
case MT_GACHABOM:
targetdamaging = UFOD_GACHABOM;
break;
case MT_ORBINAUT:
case MT_ORBINAUT_SHIELD:
targetdamaging = UFOD_ORBINAUT;
break;
case MT_BANANA:
targetdamaging = UFOD_BANANA;
break;
case MT_INSTAWHIP:
targetdamaging = UFOD_WHIP;
break;
// This is only accessible for MT_CDUFO's touch!
case MT_PLAYER:
targetdamaging = UFOD_BOOST;
break;
// The following can't be accessed in standard play...
// but the cost of tracking them here is trivial :D
case MT_JAWZ:
case MT_JAWZ_SHIELD:
targetdamaging = UFOD_JAWZ;
break;
case MT_SPB:
targetdamaging = UFOD_SPB;
break;
default:
break;
}
P_TrackRoundConditionTargetDamage(targetdamaging);
if (gamedata->prisoneggstothispickup) if (gamedata->prisoneggstothispickup)
{ {
gamedata->prisoneggstothispickup--; gamedata->prisoneggstothispickup--;
@ -2008,7 +2056,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
S_StartSound(target, sfx_mbs60); S_StartSound(target, sfx_mbs60);
P_AddBrokenPrison(target, source); P_AddBrokenPrison(target, inflictor, source);
} }
break; break;
@ -2018,7 +2066,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->momz = -(3*mapobjectscale)/2; target->momz = -(3*mapobjectscale)/2;
target->fuse = 2*TICRATE; target->fuse = 2*TICRATE;
P_AddBrokenPrison(target, source); P_AddBrokenPrison(target, inflictor, source);
break; break;
case MT_BATTLEBUMPER: case MT_BATTLEBUMPER:

View file

@ -546,6 +546,8 @@ void P_UpdateLastPickup(player_t *player, UINT8 type);
boolean P_CanPickupEmblem(player_t *player, INT32 emblemID); boolean P_CanPickupEmblem(player_t *player, INT32 emblemID);
boolean P_EmblemWasCollected(INT32 emblemID); boolean P_EmblemWasCollected(INT32 emblemID);
void P_TrackRoundConditionTargetDamage(targetdamaging_t targetdamaging);
// //
// P_SPEC // P_SPEC
// //