From b39482d721ea2550aa753261f80da2ffe5336193 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 15 Sep 2019 04:51:45 -0400 Subject: [PATCH 01/17] Lua port of the capsule visual No item collision or gameplay at all yet --- src/dehacked.c | 10 +++ src/info.c | 61 +++++++++++++++++ src/info.h | 10 +++ src/p_inter.c | 28 ++++++++ src/p_mobj.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 290 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index be45f3f0f..edfade76b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -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 diff --git a/src/info.c b/src/info.c index 31f2f8348..ba58d2615 100644 --- a/src/info.c +++ b/src/info.c @@ -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<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; diff --git a/src/p_mobj.c b/src/p_mobj.c index 970829812..885ee21af 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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; } From cd65381abc4b7d5e486a7d52c203db16bb020347 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 15 Sep 2019 17:25:33 -0400 Subject: [PATCH 02/17] Add another file to handle Kart item collision functions, now items can damage anything with MF_SHOOTABLE Now this code won't make me pull out my hair. Could possibly be enhanced by using a function or define to handle the big copy-pasted tmthing/thing switch blocks in p_map, but for now I'm way happier. As a result, Battle capsules are now destructible. --- src/Makefile | 1 + src/info.c | 2 +- src/k_collide.c | 319 +++++++++++++++++++++++++++++++++ src/k_collide.h | 16 ++ src/p_inter.c | 3 +- src/p_map.c | 458 +++++++++--------------------------------------- src/p_mobj.c | 2 +- 7 files changed, 418 insertions(+), 383 deletions(-) create mode 100644 src/k_collide.c create mode 100644 src/k_collide.h diff --git a/src/Makefile b/src/Makefile index f4a77aedd..18e0ddde5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -489,6 +489,7 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/y_inter.o \ $(OBJDIR)/st_stuff.o \ $(OBJDIR)/k_kart.o \ + $(OBJDIR)/k_collide.o\ $(OBJDIR)/m_aatree.o \ $(OBJDIR)/m_anigif.o \ $(OBJDIR)/m_argv.o \ diff --git a/src/info.c b/src/info.c index ba58d2615..09a90f77e 100644 --- a/src/info.c +++ b/src/info.c @@ -20159,7 +20159,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_BATTLECAPSULE 2333, // doomednum S_INVISIBLE, // spawnstate - 1000, // spawnhealth + 1, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime diff --git a/src/k_collide.c b/src/k_collide.c new file mode 100644 index 000000000..7edbe3e87 --- /dev/null +++ b/src/k_collide.c @@ -0,0 +1,319 @@ +/// \file k_collide.c +/// \brief SRB2Kart item collision hooks + +#include "k_collide.h" +#include "doomtype.h" +#include "p_mobj.h" +#include "k_kart.h" +#include "p_local.h" +#include "s_sound.h" +#include "r_main.h" // R_PointToAngle2, R_PointToDist2 +#include "hu_stuff.h" // Sink snipe print +#include "doomdef.h" // Sink snipe print +#include "g_game.h" // Sink snipe print + +boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) +{ + boolean damageitem = false; + + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) + return true; + + if (t1->health <= 0 || t2->health <= 0) + return true; + + if ((t1->type == MT_ORBINAUT_SHIELD || t1->type == MT_JAWZ_SHIELD) && t1->lastlook + && (t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) && t2->lastlook + && (t1->target == t2->target)) // Don't hit each other if you have the same target + return true; + + if (t2->player) + { + if (t2->player->powers[pw_flashing] + && !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ || t1->type == MT_JAWZ_DUD)) + return true; + + if (t2->player->kartstuff[k_hyudorotimer]) + return true; // no interaction + + // Player Damage + P_DamageMobj(t2, t1, t1->target, 1); + K_KartBouncing(t2, t1, false, false); + S_StartSound(t2, sfx_s3k7b); + + damageitem = true; + } + else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD + || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD + || t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD + || t2->type == MT_BALLHOG) + { + // Other Item Damage + if (t2->eflags & MFE_VERTICALFLIP) + t2->z -= t2->height; + else + t2->z += t2->height; + + S_StartSound(t2, t2->info->deathsound); + P_KillMobj(t2, t1, t1); + + P_SetObjectMomZ(t2, 8*FRACUNIT, false); + P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT); + + P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH); + + damageitem = true; + } + else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE) + { + damageitem = true; + // Bomb death + P_KillMobj(t2, t1, t1); + } + else if (t2->flags & MF_SPRING && (t1->type != MT_ORBINAUT_SHIELD && t1->type != MT_JAWZ_SHIELD)) + { + // Let thrown items hit springs! + P_DoSpring(t2, t1); + } + else if (t2->flags & MF_SHOOTABLE) + { + // Shootable damage + P_DamageMobj(t2, t2, t1->target, 1); + damageitem = true; + } + + if (damageitem) + { + // This Item Damage + if (t1->eflags & MFE_VERTICALFLIP) + t1->z -= t1->height; + else + t1->z += t1->height; + + S_StartSound(t1, t1->info->deathsound); + P_KillMobj(t1, t2, t2); + + P_SetObjectMomZ(t1, 8*FRACUNIT, false); + P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT); + } + + return true; +} + +boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) +{ + boolean damageitem = false; + + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) + return true; + + if (t1->health <= 0 || t2->health <= 0) + return true; + + if (((t1->type == MT_BANANA_SHIELD) && (t2->type == MT_BANANA_SHIELD)) + && (t1->target == t2->target)) // Don't hit each other if you have the same target + return true; + + if (t1->type == MT_BALLHOG && t2->type == MT_BALLHOG) + return true; // Ballhogs don't collide with eachother + + if (t2->player) + { + if (t2->player->powers[pw_flashing]) + return true; + + // Banana snipe! + if (t1->type == MT_BANANA && t1->health > 1) + S_StartSound(t2, sfx_bsnipe); + + // Player Damage + K_SpinPlayer(t2->player, t1->target, 0, t1, (t1->type == MT_BANANA || t1->type == MT_BANANA_SHIELD)); + + damageitem = true; + } + else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD + || t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD + || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD || t2->type == MT_JAWZ_SHIELD + || t2->type == MT_BALLHOG) + { + // Other Item Damage + if (t2->eflags & MFE_VERTICALFLIP) + t2->z -= t2->height; + else + t2->z += t2->height; + + S_StartSound(t2, t2->info->deathsound); + P_KillMobj(t2, t1, t1); + + P_SetObjectMomZ(t2, 8*FRACUNIT, false); + P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT); + + P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH); + + damageitem = true; + } + else if (t2->flags & MF_SHOOTABLE) + { + // Shootable damage + P_DamageMobj(t2, t2, t1->target, 1); + damageitem = true; + } + + if (damageitem) + { + // This Item Damage + if (t1->eflags & MFE_VERTICALFLIP) + t1->z -= t1->height; + else + t1->z += t1->height; + + S_StartSound(t1, t1->info->deathsound); + P_KillMobj(t1, t2, t2); + + P_SetObjectMomZ(t1, 8*FRACUNIT, false); + P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT); + } + + return true; +} + +boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) +{ + // Push fakes out of other item boxes + if (t2->type == MT_RANDOMITEM || t2->type == MT_EGGMANITEM) + P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y), t2->radius/4); + + // Player collision is handled by TouchSpecial + return true; +} + +boolean K_MineCollide(mobj_t *t1, mobj_t *t2) +{ + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) + return true; + + if (t1->health <= 0 || t2->health <= 0) + return true; + + if (t2->player) + { + if (t2->player->powers[pw_flashing]) + return true; + + // Bomb punting + if ((t1->state >= &states[S_SSMINE1] && t1->state <= &states[S_SSMINE4]) + || (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_DEPLOY13])) + P_KillMobj(t1, t2, t2); + else + K_PuntMine(t1, t2); + } + else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD + || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) + { + // Bomb death + P_KillMobj(t1, t2, t2); + + // Other Item Damage + if (t2->eflags & MFE_VERTICALFLIP) + t2->z -= t2->height; + else + t2->z += t2->height; + + S_StartSound(t2, t2->info->deathsound); + P_KillMobj(t2, t1, t1); + + P_SetObjectMomZ(t2, 8*FRACUNIT, false); + P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT); + } + else if (t2->flags & MF_SHOOTABLE) + { + // Bomb death + P_KillMobj(t1, t2, t2); + // Shootable damage + P_DamageMobj(t2, t2, t1->target, 1); + } + + return true; +} + +boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2) +{ + if (t2->player) + { + if (t2->player->powers[pw_flashing]) + return true; + + if (t1->state == &states[S_MINEEXPLOSION1]) + K_ExplodePlayer(t2->player, t1->target, t1); + else + K_SpinPlayer(t2->player, t1->target, 0, t1, false); + } + else if (t2->flags & MF_SHOOTABLE) + { + // Shootable damage + P_DamageMobj(t2, t2, t1->target, 1); + } + + return true; +} + +boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2) +{ + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) + return true; + + if (t2->player) + { + if (t2->player->powers[pw_flashing]) + return true; + + S_StartSound(NULL, sfx_bsnipe); // let all players hear it. + HU_SetCEchoFlags(0); + HU_SetCEchoDuration(5); + HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[t2->player-players])); + I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[t2->player-players]); + P_DamageMobj(t2, t1, t1->target, 10000); + P_KillMobj(t1, t2, t2); + } + else if (t2->flags & MF_SHOOTABLE) + { + // Shootable damage + P_KillMobj(t2, t2, t1->target); + // This item damage + P_KillMobj(t1, t2, t2); + } + + return true; +} + +boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2) +{ + if (t2->player || t2->type == MT_FALLINGROCK) + K_KartBouncing(t2, t1, false, false); + return true; +} + +boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2) +{ + if (!(t2->flags & MF_SOLID || t2->flags & MF_SHOOTABLE || t2->flags & MF_BOUNCE)) + return true; + + if (!(t2->health)) + return true; + + if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD + || t2->type == MT_EGGMANITEM || t2->type == MT_EGGMANITEM_SHIELD + || t2->type == MT_SSMINE || t2->type == MT_SSMINE_SHIELD + || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) + return false; + + if (t1->health) + P_KillMobj(t1, t2, t2); + + /*if (t2->player && (t2->player->kartstuff[k_invincibilitytimer] > 0 + || t2->player->kartstuff[k_growshrinktimer] > 0)) + return true;*/ + + K_KartBouncing(t2, t1, false, true); + return false; +} diff --git a/src/k_collide.h b/src/k_collide.h new file mode 100644 index 000000000..86f643b3f --- /dev/null +++ b/src/k_collide.h @@ -0,0 +1,16 @@ +#ifndef __K_COLLIDE__ +#define __K_COLLIDE__ + +#include "doomtype.h" +#include "p_mobj.h" + +boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2); +boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2); +boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2); +boolean K_MineCollide(mobj_t *t1, mobj_t *t2); +boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2); +boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2); +boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2); +boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); + +#endif diff --git a/src/p_inter.c b/src/p_inter.c index 02e455476..576cd428d 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2546,7 +2546,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) cur->momz = 8 * target->scale * P_MobjFlip(target); cur->flags &= ~MF_NOGRAVITY; - cur->fuse = 24; + cur->tics = TICRATE; + cur->frame &= ~FF_ANIMATE; // Stop animating the propellers cur = cur->hnext; } diff --git a/src/p_map.c b/src/p_map.c index d99105005..78879759d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -25,6 +25,7 @@ #include "s_sound.h" #include "w_wad.h" #include "k_kart.h" // SRB2kart 011617 +#include "k_collide.h" #include "hu_stuff.h" // SRB2kart #include "i_system.h" // SRB2kart @@ -665,7 +666,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // SRB2kart 011617 - Colission[sic] code for kart items //{ - if (thing->type == MT_SMK_ICEBLOCK) + if (tmthing->type == MT_SMK_ICEBLOCK) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -673,31 +674,20 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (!(tmthing->flags & MF_SOLID || tmthing->flags & MF_SHOOTABLE || tmthing->flags & MF_BOUNCE)) - return true; + return K_SMKIceBlockCollide(tmthing, thing); + } + else if (thing->type == MT_SMK_ICEBLOCK) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath - if (!(tmthing->health)) - return true; - - if (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD - || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_EGGMANITEM_SHIELD - || tmthing->type == MT_SSMINE || tmthing->type == MT_SSMINE_SHIELD - || tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) - return false; - - if (thing->health) - P_KillMobj(thing, tmthing, tmthing); - - /*if (tmthing->player && (tmthing->player->kartstuff[k_invincibilitytimer] > 0 - || tmthing->player->kartstuff[k_growshrinktimer] > 0)) - return true;*/ - - K_KartBouncing(tmthing, thing, false, true); - return false; + return K_SMKIceBlockCollide(thing, tmthing); } - // Push fakes out of other items - if (tmthing->type == MT_EGGMANITEM && (thing->type == MT_RANDOMITEM || thing->type == MT_EGGMANITEM)) + if (tmthing->type == MT_EGGMANITEM) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -705,10 +695,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y), thing->radius/4); + K_EggItemCollide(tmthing, thing); return true; } - else if (thing->type == MT_EGGMANITEM && (tmthing->type == MT_RANDOMITEM || tmthing->type == MT_EGGMANITEM)) + else if (thing->type == MT_EGGMANITEM) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -716,7 +706,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y), tmthing->radius/4); + K_EggItemCollide(thing, tmthing); return true; } @@ -732,97 +722,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0))) - return true; - - if (tmthing->health <= 0 || thing->health <= 0) - return true; - - if ((tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) && tmthing->lastlook - && (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) && thing->lastlook - && (tmthing->target == thing->target)) // Don't hit each other if you have the same target - return true; - - if (thing->player && thing->player->powers[pw_flashing] - && !(tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD)) - return true; - - if (thing->player && thing->player->kartstuff[k_hyudorotimer]) - return true; // no interaction - - if (thing->type == MT_PLAYER) - { - // Player Damage - P_DamageMobj(thing, tmthing, tmthing->target, 1); - K_KartBouncing(thing, tmthing, false, false); - S_StartSound(thing, sfx_s3k7b); - - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD - || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD - || thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD - || thing->type == MT_BALLHOG) - { - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; - - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); - - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - - P_SpawnMobj(thing->x/2 + tmthing->x/2, thing->y/2 + tmthing->y/2, thing->z/2 + tmthing->z/2, MT_ITEMCLASH); - - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE) - { - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - - // Bomb death - P_KillMobj(thing, tmthing, tmthing); - } - else if (thing->flags & MF_SPRING && (tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD || tmthing->type == MT_ORBINAUT)) - P_DoSpring(thing, tmthing); - - return true; + return K_OrbinautJawzCollide(tmthing, thing); } - else if (tmthing->flags & MF_SPRING && (thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_ORBINAUT)) + else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD + || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -830,14 +733,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->health <= 0) - return true; - - P_DoSpring(tmthing, thing); - - return true; + return K_OrbinautJawzCollide(thing, tmthing); } - else if (tmthing->type == MT_SINK) + + if (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD || tmthing->type == MT_BALLHOG) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -845,26 +744,9 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0))) - return true; - - if (thing->player && thing->player->powers[pw_flashing]) - return true; - - if (thing->type == MT_PLAYER) - { - S_StartSound(NULL, sfx_bsnipe); //let all players hear it. - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players])); - I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[thing->player-players]); - P_DamageMobj(thing, tmthing, tmthing->target, 10000); - P_KillMobj(tmthing, thing, thing); - } - - return true; + return K_BananaBallhogCollide(tmthing, thing); } - else if (tmthing->type == MT_MINEEXPLOSION) + else if (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD || thing->type == MT_BALLHOG) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -872,24 +754,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (!(thing->type == MT_PLAYER)) - return true; - - if (thing->player && thing->player->powers[pw_flashing]) - return true; - - if (thing->type == MT_PLAYER && thing->player) - { - if (tmthing->state == &states[S_MINEEXPLOSION1]) - K_ExplodePlayer(thing->player, tmthing->target, tmthing); - else - K_SpinPlayer(thing->player, tmthing->target, 0, tmthing, false); - } - - return true; // This doesn't collide with anything, but we want it to effect the player anyway. + return K_BananaBallhogCollide(thing, tmthing); } - else if (tmthing->type == MT_BANANA_SHIELD || tmthing->type == MT_BANANA - || tmthing->type == MT_BALLHOG) + + if (tmthing->type == MT_SSMINE || tmthing->type == MT_SSMINE_SHIELD) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -897,78 +765,9 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0))) - return true; - - if (tmthing->health <= 0 || thing->health <= 0) - return true; - - if (((tmthing->type == MT_BANANA_SHIELD) && (thing->type == MT_BANANA_SHIELD)) - && (tmthing->target == thing->target)) // Don't hit each other if you have the same target - return true; - - if (tmthing->type == MT_BALLHOG && thing->type == MT_BALLHOG) - return true; // Ballhogs don't collide with eachother - - if (thing->player && thing->player->powers[pw_flashing]) - return true; - - if (thing->type == MT_PLAYER) - { - // Banana snipe! - if (tmthing->type == MT_BANANA && tmthing->health > 1) - S_StartSound(thing, sfx_bsnipe); - - // Player Damage - K_SpinPlayer(thing->player, tmthing->target, 0, tmthing, (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD)); - - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD - || thing->type == MT_ORBINAUT || thing->type == MT_ORBINAUT_SHIELD - || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_JAWZ_SHIELD - || thing->type == MT_BALLHOG) - { - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; - - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); - - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - - P_SpawnMobj(thing->x/2 + tmthing->x/2, thing->y/2 + tmthing->y/2, thing->z/2 + tmthing->z/2, MT_ITEMCLASH); - - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - } - - return true; + return K_MineCollide(tmthing, thing); } - else if (tmthing->type == MT_SSMINE_SHIELD || tmthing->type == MT_SSMINE) + else if (thing->type == MT_SSMINE || thing->type == MT_SSMINE_SHIELD) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -976,52 +775,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0))) - return true; - - if (tmthing->health <= 0 || thing->health <= 0) - return true; - - if (thing->player && thing->player->powers[pw_flashing]) - return true; - - if (thing->type == MT_PLAYER) - { - // Bomb punting - if ((tmthing->state >= &states[S_SSMINE1] && tmthing->state <= &states[S_SSMINE4]) - || (tmthing->state >= &states[S_SSMINE_DEPLOY8] && tmthing->state <= &states[S_SSMINE_DEPLOY13])) - P_KillMobj(tmthing, thing, thing); - else - K_PuntMine(tmthing, thing); - } - else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD - || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) - { - P_KillMobj(tmthing, thing, thing); - - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; - - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); - - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - } - - return true; + return K_MineCollide(thing, tmthing); } - else if (tmthing->type == MT_PLAYER && - (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_ORBINAUT - || thing->type == MT_JAWZ_SHIELD || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD - || thing->type == MT_BANANA_SHIELD || thing->type == MT_BANANA - || thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE - || thing->type == MT_MINEEXPLOSION - || thing->type == MT_SINK || thing->type == MT_BALLHOG - )) + + if (tmthing->type == MT_MINEEXPLOSION) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -1029,122 +786,63 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (tmthing->player && tmthing->player->powers[pw_flashing] - && !(thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD)) - return true; + return K_MineExplosionCollide(tmthing, thing); + } + else if (thing->type == MT_MINEEXPLOSION) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath - if (tmthing->player && tmthing->player->kartstuff[k_hyudorotimer]) // I thought about doing this for just the objects below but figured it should apply to everything. - return true; // no interaction + return K_MineExplosionCollide(thing, tmthing); + } - if (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD - || thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) - { - if ((thing->target == tmthing) && (thing->threshold > 0)) - return true; + if (tmthing->type == MT_SINK) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath - if (tmthing->health <= 0 || thing->health <= 0) - return true; + return K_KitchenSinkCollide(tmthing, thing); + } + else if (thing->type == MT_SINK) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath - // Player Damage - P_DamageMobj(tmthing, thing, thing->target, 1); - K_KartBouncing(tmthing, thing, false, false); - S_StartSound(tmthing, sfx_s3k7b); + return K_KitchenSinkCollide(thing, tmthing); + } - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; + if (tmthing->type == MT_FALLINGROCK) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); + return K_FallingRockCollide(tmthing, thing); + } + else if (thing->type == MT_FALLINGROCK) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_BANANA_SHIELD || thing->type == MT_BANANA - || thing->type == MT_BALLHOG) - { - if ((thing->target == tmthing) && (thing->threshold > 0)) - return true; - - if (tmthing->health <= 0 || thing->health <= 0) - return true; - - // Banana snipe! - if (thing->type == MT_BANANA && thing->health > 1) - S_StartSound(tmthing, sfx_bsnipe); - - // Player Damage - K_SpinPlayer(tmthing->player, thing->target, 0, thing, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD)); - - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; - - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); - - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE) - { - if ((thing->target == tmthing) && (thing->threshold > 0)) - return true; - - if (tmthing->health <= 0 || thing->health <= 0) - return true; - - // Bomb punting - if ((thing->state >= &states[S_SSMINE1] && thing->state <= &states[S_SSMINE4]) - || (thing->state >= &states[S_SSMINE_DEPLOY8] && thing->state <= &states[S_SSMINE_DEPLOY13])) - P_KillMobj(thing, tmthing, tmthing); - else - K_PuntMine(thing, tmthing); - } - else if (thing->type == MT_MINEEXPLOSION && tmthing->player) - { - // Player Damage - if (thing->state == &states[S_MINEEXPLOSION1]) - K_ExplodePlayer(tmthing->player, thing->target, thing); - else - K_SpinPlayer(tmthing->player, thing->target, 0, thing, false); - - return true; - } - else if (thing->type == MT_SINK) - { - if ((thing->target == tmthing) && (thing->threshold > 0)) - return true; - - S_StartSound(NULL, sfx_cgot); //let all players hear it. - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[tmthing->player-players])); - I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[tmthing->player-players]); - P_DamageMobj(tmthing, thing, thing->target, 10000); - P_KillMobj(thing, tmthing, tmthing); - } - - return true; + return K_FallingRockCollide(thing, tmthing); } //} - if ((thing->type == MT_FALLINGROCK && (tmthing->player || tmthing->type == MT_FALLINGROCK)) - || (tmthing->type == MT_FALLINGROCK && (thing->player || thing->type == MT_FALLINGROCK))) - { - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - K_KartBouncing(thing, tmthing, false, false); - } - if ((thing->type == MT_SPRINGSHELL || thing->type == MT_YELLOWSHELL) && thing->health > 0 && (tmthing->player || (tmthing->flags & MF_PUSHABLE)) && tmthing->health > 0) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 885ee21af..4def2c713 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6965,7 +6965,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags2 & MF2_OBJECTFLIP) mobj->eflags |= MFE_VERTICALFLIP; - if (mobj->fuse) + if (mobj->tics > 0) mobj->flags2 ^= MF2_DONTDRAW; break; //} From 2648e5d3def95e07884e7c29c4db28509b9cbb07 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 15 Sep 2019 17:33:49 -0400 Subject: [PATCH 03/17] Fix the inner capsule sides not moving outward --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 576cd428d..0b45d3878 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2535,7 +2535,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) while (cur && !P_MobjWasRemoved(cur)) { // Shoot every piece outward - if (cur->x != target->x && cur->y != target->y) + if (!(cur->x == target->x && cur->y == target->y)) { P_InstaThrust(cur, R_PointToAngle2(target->x, target->y, cur->x, cur->y), From 1ef09699d1b9c51328cde632f2b7d9027dc36fc9 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 15 Sep 2019 20:19:48 -0400 Subject: [PATCH 04/17] Functional gameplay - Capsules get spawned in the proper scenarios - Level ends when all capsules are busted - Time gets used on the leaderboard instead of score Also split a handful of Battle code into k_battle.c. Lots of other code could probably get moved here later --- src/Makefile | 1 + src/d_clisrv.c | 1 + src/d_netcmd.c | 1 + src/doomstat.h | 5 +- src/g_game.c | 6 + src/k_battle.c | 436 ++++++++++++++++++++++++++++++++++++++++++++++ src/k_battle.h | 13 ++ src/k_kart.c | 219 +---------------------- src/k_kart.h | 4 - src/lua_baselib.c | 1 + src/p_inter.c | 11 ++ src/p_mobj.c | 68 +------- src/p_saveg.c | 4 + src/p_setup.c | 74 +++----- src/p_spec.c | 3 + src/p_tick.c | 1 + src/sounds.h | 2 + src/y_inter.c | 6 +- 18 files changed, 515 insertions(+), 341 deletions(-) create mode 100644 src/k_battle.c create mode 100644 src/k_battle.h diff --git a/src/Makefile b/src/Makefile index 18e0ddde5..d8c6fca11 100644 --- a/src/Makefile +++ b/src/Makefile @@ -490,6 +490,7 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/st_stuff.o \ $(OBJDIR)/k_kart.o \ $(OBJDIR)/k_collide.o\ + $(OBJDIR)/k_battle.o \ $(OBJDIR)/m_aatree.o \ $(OBJDIR)/m_anigif.o \ $(OBJDIR)/m_argv.o \ diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4d61194c4..33a1dfe61 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -47,6 +47,7 @@ #include "lua_script.h" #include "lua_hook.h" #include "k_kart.h" +#include "k_battle.h" #ifdef CLIENT_LOADINGSCREEN // cl loading screen diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 11c4547de..073b3fa3f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -47,6 +47,7 @@ #include "m_cond.h" #include "m_anigif.h" #include "k_kart.h" // SRB2kart +#include "k_battle.h" #include "y_inter.h" #ifdef NETGAME_DEVMODE diff --git a/src/doomstat.h b/src/doomstat.h index 1f855da27..716b3fe85 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -353,7 +353,10 @@ extern UINT16 emeralds; #define EMERALD7 64 #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) -extern INT32 nummaprings, nummapboxes, numgotboxes; //keep track of spawned rings/coins/battle mode items +extern INT32 nummaprings; // keep track of spawned rings/coins +extern INT32 nummapboxes, numgotboxes; // keep track of spawned battle mode items +extern UINT8 maptargets, numtargets; // Keep track of spawend Battle Mode targets +extern boolean targetsspawned; // have targets been spawned already? /** Time attack information, currently a very small structure. */ diff --git a/src/g_game.c b/src/g_game.c index e406e29d1..50aa7b904 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -48,6 +48,7 @@ #include "m_cond.h" // condition sets #include "md5.h" // demo checksums #include "k_kart.h" // SRB2kart +#include "k_battle.h" gameaction_t gameaction; gamestate_t gamestate = GS_NULL; @@ -188,6 +189,11 @@ INT32 nummaprings = 0; INT32 nummapboxes = 0; INT32 numgotboxes = 0; +// Break the Capsules counters for Battle Mode! +UINT8 maptargets = 0; // targets in map +UINT8 numtargets = 0; // targets busted +boolean targetsspawned = false; // have targets been spawned already? + // Elminates unnecessary searching. boolean CheckForBustableBlocks; boolean CheckForBouncySector; diff --git a/src/k_battle.c b/src/k_battle.c new file mode 100644 index 000000000..dafabf670 --- /dev/null +++ b/src/k_battle.c @@ -0,0 +1,436 @@ +/// \file k_battle.c +/// \brief SRB2Kart Battle Mode specific code + +#include "k_battle.h" +#include "k_kart.h" +#include "doomtype.h" +#include "doomdata.h" +#include "g_game.h" +#include "p_mobj.h" +#include "p_local.h" +#include "p_setup.h" +#include "p_slopes.h" // P_GetZAt +#include "r_main.h" +#include "r_defs.h" // MAXFFLOORS +#include "info.h" + +boolean K_IsPlayerWanted(player_t *player) +{ + UINT8 i; + if (!(G_BattleGametype())) + return false; + for (i = 0; i < 4; i++) + { + if (battlewanted[i] == -1) + break; + if (player == &players[battlewanted[i]]) + return true; + } + return false; +} + +void K_CalculateBattleWanted(void) +{ + UINT8 numingame = 0, numplaying = 0, numwanted = 0; + SINT8 bestbumperplayer = -1, bestbumper = -1; + SINT8 camppos[MAXPLAYERS]; // who is the biggest camper + UINT8 ties = 0, nextcamppos = 0; + boolean setbumper = false; + UINT8 i, j; + + if (!G_BattleGametype()) + { + for (i = 0; i < 4; i++) + battlewanted[i] = -1; + return; + } + + wantedcalcdelay = wantedfrequency; + + for (i = 0; i < MAXPLAYERS; i++) + camppos[i] = -1; // initialize + + for (i = 0; i < MAXPLAYERS; i++) + { + UINT8 position = 1; + + if (!playeringame[i] || players[i].spectator) // Not playing + continue; + + if (players[i].exiting) // We're done, don't calculate. + return; + + numplaying++; + + if (players[i].kartstuff[k_bumper] <= 0) // Not alive, so don't do anything else + continue; + + numingame++; + + if (bestbumper == -1 || players[i].kartstuff[k_bumper] > bestbumper) + { + bestbumper = players[i].kartstuff[k_bumper]; + bestbumperplayer = i; + } + else if (players[i].kartstuff[k_bumper] == bestbumper) + bestbumperplayer = -1; // Tie, no one has best bumper. + + for (j = 0; j < MAXPLAYERS; j++) + { + if (!playeringame[j] || players[j].spectator) + continue; + if (players[j].kartstuff[k_bumper] <= 0) + continue; + if (j == i) + continue; + if (players[j].kartstuff[k_wanted] == players[i].kartstuff[k_wanted] && players[j].marescore > players[i].marescore) + position++; + else if (players[j].kartstuff[k_wanted] > players[i].kartstuff[k_wanted]) + position++; + } + + position--; // Make zero based + + while (camppos[position] != -1) // Port priority! + position++; + + camppos[position] = i; + } + + if (numplaying <= 2 || (numingame <= 2 && bestbumper == 1)) // In 1v1s then there's no need for WANTED. In bigger netgames, don't show anyone as WANTED when they're equally matched. + numwanted = 0; + else + numwanted = min(4, 1 + ((numingame-2) / 4)); + + for (i = 0; i < 4; i++) + { + if (i+1 > numwanted) // Not enough players for this slot to be wanted! + battlewanted[i] = -1; + else if (bestbumperplayer != -1 && !setbumper) // If there's a player who has an untied bumper lead over everyone else, they are the first to be wanted. + { + battlewanted[i] = bestbumperplayer; + setbumper = true; // Don't set twice + } + else + { + // Don't accidentally set the same player, if the bestbumperplayer is also a huge camper. + while (bestbumperplayer != -1 && camppos[nextcamppos] != -1 + && bestbumperplayer == camppos[nextcamppos]) + nextcamppos++; + + // Do not add *any* more people if there's too many times that are tied with others. + // This could theoretically happen very easily if people don't hit each other for a while after the start of a match. + // (I will be sincerely impressed if more than 2 people tie after people start hitting each other though) + + if (camppos[nextcamppos] == -1 // Out of entries + || ties >= (numwanted-i)) // Already counted ties + { + battlewanted[i] = -1; + continue; + } + + if (ties < (numwanted-i)) + { + ties = 0; // Reset + for (j = 0; j < 2; j++) + { + if (camppos[nextcamppos+(j+1)] == -1) // Nothing beyond, cancel + break; + if (players[camppos[nextcamppos]].kartstuff[k_wanted] == players[camppos[nextcamppos+(j+1)]].kartstuff[k_wanted]) + ties++; + } + } + + if (ties < (numwanted-i)) // Is it still low enough after counting? + { + battlewanted[i] = camppos[nextcamppos]; + nextcamppos++; + } + else + battlewanted[i] = -1; + } + } +} + +void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount) +{ + statenum_t st; + mobj_t *pt; + + if (!source || !source->mo) + return; + + if (amount == 1) + st = S_BATTLEPOINT1A; + else if (amount == 2) + st = S_BATTLEPOINT2A; + else if (amount == 3) + st = S_BATTLEPOINT3A; + else + return; // NO STATE! + + pt = P_SpawnMobj(source->mo->x, source->mo->y, source->mo->z, MT_BATTLEPOINT); + P_SetTarget(&pt->target, source->mo); + P_SetMobjState(pt, st); + if (victim && victim->skincolor) + pt->color = victim->skincolor; + else + pt->color = source->skincolor; +} + +void K_CheckBumpers(void) +{ + UINT8 i; + UINT8 numingame = 0; + SINT8 winnernum = -1; + INT32 winnerscoreadd = 0; + + if (!multiplayer) + return; + + if (!G_BattleGametype()) + return; + + if (gameaction == ga_completed) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) // not even in-game + continue; + + if (players[i].exiting) // we're already exiting! stop! + return; + + numingame++; + winnerscoreadd += players[i].marescore; + + if (players[i].kartstuff[k_bumper] <= 0) // if you don't have any bumpers, you're probably not a winner + continue; + else if (winnernum > -1) // TWO winners? that's dumb :V + return; + + winnernum = i; + winnerscoreadd -= players[i].marescore; + } + + if (numingame <= 1) + { + K_SpawnBattleCapsules(); + return; + } + + if (winnernum > -1 && playeringame[winnernum]) + { + players[winnernum].marescore += winnerscoreadd; + CONS_Printf(M_GetText("%s recieved %d point%s for winning!\n"), player_names[winnernum], winnerscoreadd, (winnerscoreadd == 1 ? "" : "s")); + } + + for (i = 0; i < MAXPLAYERS; i++) // This can't go in the earlier loop because winning adds points + K_KartUpdatePosition(&players[i]); + + for (i = 0; i < MAXPLAYERS; i++) // and it can't be merged with this loop because it needs to be all updated before exiting... multi-loops suck... + P_DoPlayerExit(&players[i]); +} + +void K_SpawnBattleCapsules(void) +{ + mapthing_t *mt; + UINT8 n = 0; + size_t i; + + if (targetsspawned) + return; + + if (!G_BattleGametype()) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator) + n++; + if (players[i].exiting) + return; + if (n > 1) + break; + } + + if (n > 1) + return; + + mt = mapthings; + for (i = 0; i < nummapthings; i++, mt++) + { + if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum) + { + sector_t *mtsector, *sec; + fixed_t x, y, z; + fixed_t floorheights[MAXFFLOORS+1]; + UINT8 numfloors = 1; + mobj_t *mobj = NULL; + boolean fly = true; + + mt->mobj = NULL; + + mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; + mt->z = (INT16)( +#ifdef ESLOPE + mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : +#endif + mtsector->floorheight)>>FRACBITS; + + x = mt->x << FRACBITS; + y = mt->y << FRACBITS; + + sec = R_PointInSubsector(x, y)->sector; + + if (mt->options & MTF_OBJECTFLIP) + { + z = ( +#ifdef ESLOPE + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : +#endif + sec->ceilingheight) - mobjinfo[MT_BATTLECAPSULE].height; + + floorheights[0] = z; + + if (mt->options >> ZSHIFT) + z -= ((mt->options >> ZSHIFT) << FRACBITS); + } + else + { + z = +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight; + + floorheights[0] = z; + + if (mt->options >> ZSHIFT) + z += ((mt->options >> ZSHIFT) << FRACBITS); + } + + + if (sec->ffloors) + { + ffloor_t *rover; + for (rover = sec->ffloors; rover; rover = rover->next) + { + if ((rover->flags & FF_EXISTS) && (rover->flags & FF_BLOCKOTHERS)) + { + if (mt->options & MTF_OBJECTFLIP) + { + floorheights[numfloors] = ( +#ifdef ESLOPE + *rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : +#endif + *rover->bottomheight) - mobjinfo[MT_BATTLECAPSULE].height; + } + else + { + floorheights[numfloors] = ( +#ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : +#endif + *rover->topheight); + } + + numfloors++; + } + } + } + + mt->z = (INT16)(z>>FRACBITS); + + mobj = P_SpawnMobj(x, y, z, MT_BATTLECAPSULE); + mobj->spawnpoint = mt; + + if (mt->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + for (i = 0; i < numfloors; i++) + { + if (z == floorheights[i]) + { + fly = false; + break; + } + } + + // Flying capsules + if (fly) + { + mobj->flags |= MF_NOGRAVITY; + mobj->extravalue1 = 1; // Set extravalue1 for later reference + } + + // Moved from P_SpawnMobj due to order of operations mumbo jumbo + { + mobj_t *cur, *prev = mobj; + + // 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; + } + } + + mobj->angle = FixedAngle(mt->angle * FRACUNIT); + mt->mobj = mobj; + } + } + + targetsspawned = true; +} diff --git a/src/k_battle.h b/src/k_battle.h new file mode 100644 index 000000000..04c413d68 --- /dev/null +++ b/src/k_battle.h @@ -0,0 +1,13 @@ +#ifndef __K_BATTLE__ +#define __K_BATTLE__ + +#include "doomtype.h" +#include "d_player.h" + +boolean K_IsPlayerWanted(player_t *player); +void K_CalculateBattleWanted(void); +void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); +void K_CheckBumpers(void); +void K_SpawnBattleCapsules(void); + +#endif diff --git a/src/k_kart.c b/src/k_kart.c index c56c7c982..f9926d570 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4,6 +4,8 @@ /// \brief SRB2kart general. /// All of the SRB2kart-unique stuff. +#include "k_kart.h" +#include "k_battle.h" #include "doomdef.h" #include "hu_stuff.h" #include "g_game.h" @@ -18,7 +20,6 @@ #include "z_zone.h" #include "m_misc.h" #include "m_cond.h" -#include "k_kart.h" #include "f_finale.h" #include "lua_hud.h" // For Lua hud checks #include "lua_hook.h" // For MobjDamage and ShouldDamage @@ -621,21 +622,6 @@ boolean K_IsPlayerLosing(player_t *player) return (player->kartstuff[k_position] > winningpos); } -boolean K_IsPlayerWanted(player_t *player) -{ - UINT8 i; - if (!(G_BattleGametype())) - return false; - for (i = 0; i < 4; i++) - { - if (battlewanted[i] == -1) - break; - if (player == &players[battlewanted[i]]) - return true; - } - return false; -} - fixed_t K_GetKartGameSpeedScalar(SINT8 value) { // Easy = 81.25% @@ -2374,32 +2360,6 @@ void K_DoInstashield(player_t *player) P_SetTarget(&layerb->target, player->mo); } -void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount) -{ - statenum_t st; - mobj_t *pt; - - if (!source || !source->mo) - return; - - if (amount == 1) - st = S_BATTLEPOINT1A; - else if (amount == 2) - st = S_BATTLEPOINT2A; - else if (amount == 3) - st = S_BATTLEPOINT3A; - else - return; // NO STATE! - - pt = P_SpawnMobj(source->mo->x, source->mo->y, source->mo->z, MT_BATTLEPOINT); - P_SetTarget(&pt->target, source->mo); - P_SetMobjState(pt, st); - if (victim && victim->skincolor) - pt->color = victim->skincolor; - else - pt->color = source->skincolor; -} - void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem) { UINT8 scoremultiply = 1; @@ -6639,181 +6599,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } -void K_CalculateBattleWanted(void) -{ - UINT8 numingame = 0, numplaying = 0, numwanted = 0; - SINT8 bestbumperplayer = -1, bestbumper = -1; - SINT8 camppos[MAXPLAYERS]; // who is the biggest camper - UINT8 ties = 0, nextcamppos = 0; - boolean setbumper = false; - UINT8 i, j; - - if (!G_BattleGametype()) - { - for (i = 0; i < 4; i++) - battlewanted[i] = -1; - return; - } - - wantedcalcdelay = wantedfrequency; - - for (i = 0; i < MAXPLAYERS; i++) - camppos[i] = -1; // initialize - - for (i = 0; i < MAXPLAYERS; i++) - { - UINT8 position = 1; - - if (!playeringame[i] || players[i].spectator) // Not playing - continue; - - if (players[i].exiting) // We're done, don't calculate. - return; - - numplaying++; - - if (players[i].kartstuff[k_bumper] <= 0) // Not alive, so don't do anything else - continue; - - numingame++; - - if (bestbumper == -1 || players[i].kartstuff[k_bumper] > bestbumper) - { - bestbumper = players[i].kartstuff[k_bumper]; - bestbumperplayer = i; - } - else if (players[i].kartstuff[k_bumper] == bestbumper) - bestbumperplayer = -1; // Tie, no one has best bumper. - - for (j = 0; j < MAXPLAYERS; j++) - { - if (!playeringame[j] || players[j].spectator) - continue; - if (players[j].kartstuff[k_bumper] <= 0) - continue; - if (j == i) - continue; - if (players[j].kartstuff[k_wanted] == players[i].kartstuff[k_wanted] && players[j].marescore > players[i].marescore) - position++; - else if (players[j].kartstuff[k_wanted] > players[i].kartstuff[k_wanted]) - position++; - } - - position--; // Make zero based - - while (camppos[position] != -1) // Port priority! - position++; - - camppos[position] = i; - } - - if (numplaying <= 2 || (numingame <= 2 && bestbumper == 1)) // In 1v1s then there's no need for WANTED. In bigger netgames, don't show anyone as WANTED when they're equally matched. - numwanted = 0; - else - numwanted = min(4, 1 + ((numingame-2) / 4)); - - for (i = 0; i < 4; i++) - { - if (i+1 > numwanted) // Not enough players for this slot to be wanted! - battlewanted[i] = -1; - else if (bestbumperplayer != -1 && !setbumper) // If there's a player who has an untied bumper lead over everyone else, they are the first to be wanted. - { - battlewanted[i] = bestbumperplayer; - setbumper = true; // Don't set twice - } - else - { - // Don't accidentally set the same player, if the bestbumperplayer is also a huge camper. - while (bestbumperplayer != -1 && camppos[nextcamppos] != -1 - && bestbumperplayer == camppos[nextcamppos]) - nextcamppos++; - - // Do not add *any* more people if there's too many times that are tied with others. - // This could theoretically happen very easily if people don't hit each other for a while after the start of a match. - // (I will be sincerely impressed if more than 2 people tie after people start hitting each other though) - - if (camppos[nextcamppos] == -1 // Out of entries - || ties >= (numwanted-i)) // Already counted ties - { - battlewanted[i] = -1; - continue; - } - - if (ties < (numwanted-i)) - { - ties = 0; // Reset - for (j = 0; j < 2; j++) - { - if (camppos[nextcamppos+(j+1)] == -1) // Nothing beyond, cancel - break; - if (players[camppos[nextcamppos]].kartstuff[k_wanted] == players[camppos[nextcamppos+(j+1)]].kartstuff[k_wanted]) - ties++; - } - } - - if (ties < (numwanted-i)) // Is it still low enough after counting? - { - battlewanted[i] = camppos[nextcamppos]; - nextcamppos++; - } - else - battlewanted[i] = -1; - } - } -} - -void K_CheckBumpers(void) -{ - UINT8 i; - UINT8 numingame = 0; - SINT8 winnernum = -1; - INT32 winnerscoreadd = 0; - - if (!multiplayer) - return; - - if (!G_BattleGametype()) - return; - - if (gameaction == ga_completed) - return; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) // not even in-game - continue; - - if (players[i].exiting) // we're already exiting! stop! - return; - - numingame++; - winnerscoreadd += players[i].marescore; - - if (players[i].kartstuff[k_bumper] <= 0) // if you don't have any bumpers, you're probably not a winner - continue; - else if (winnernum > -1) // TWO winners? that's dumb :V - return; - - winnernum = i; - winnerscoreadd -= players[i].marescore; - } - - if (numingame <= 1) - return; - - if (winnernum > -1 && playeringame[winnernum]) - { - players[winnernum].marescore += winnerscoreadd; - CONS_Printf(M_GetText("%s recieved %d point%s for winning!\n"), player_names[winnernum], winnerscoreadd, (winnerscoreadd == 1 ? "" : "s")); - } - - for (i = 0; i < MAXPLAYERS; i++) // This can't go in the earlier loop because winning adds points - K_KartUpdatePosition(&players[i]); - - for (i = 0; i < MAXPLAYERS; i++) // and it can't be merged with this loop because it needs to be all updated before exiting... multi-loops suck... - P_DoPlayerExit(&players[i]); -} - void K_CheckSpectateStatus(void) { UINT8 respawnlist[MAXPLAYERS]; diff --git a/src/k_kart.h b/src/k_kart.h index b91e8c8a1..7c09e92de 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -21,7 +21,6 @@ UINT8 K_GetKartColorByName(const char *name); void K_RegisterKartStuff(void); boolean K_IsPlayerLosing(player_t *player); -boolean K_IsPlayerWanted(player_t *player); fixed_t K_GetKartGameSpeedScalar(SINT8 value); void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); void K_KartPainEnergyFling(player_t *player); @@ -33,7 +32,6 @@ void K_KartPlayerHUDUpdate(player_t *player); void K_KartPlayerThink(player_t *player, ticcmd_t *cmd); void K_KartPlayerAfterThink(player_t *player); void K_DoInstashield(player_t *player); -void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem); void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor); void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor); @@ -66,8 +64,6 @@ fixed_t K_GetKartAccel(player_t *player); UINT16 K_GetKartFlashing(player_t *player); fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove); void K_MoveKartPlayer(player_t *player, boolean onground); -void K_CalculateBattleWanted(void); -void K_CheckBumpers(void); void K_CheckSpectateStatus(void); // sound stuff for lua diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 38af4d2e9..f468f3b88 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -26,6 +26,7 @@ #include "hu_stuff.h" // HU_AddChatText #include "console.h" #include "k_kart.h" // SRB2Kart +#include "k_battle.h" #include "d_netcmd.h" // IsPlayerAdmin #include "lua_script.h" diff --git a/src/p_inter.c b/src/p_inter.c index 0b45d3878..240b7062f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -27,6 +27,7 @@ #include "m_misc.h" #include "v_video.h" // video flags for CEchos #include "k_kart.h" // SRB2kart +#include "k_battle.h" // CTF player names #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" @@ -2528,7 +2529,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) { mobj_t *cur; + numtargets++; target->fuse = 16; + target->flags |= MF_NOCLIP|MF_NOCLIPTHING; cur = target->hnext; @@ -2551,6 +2554,14 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) cur = cur->hnext; } + + // All targets busted! + if (numtargets >= maptargets) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + P_DoPlayerExit(&players[i]); + } } break; diff --git a/src/p_mobj.c b/src/p_mobj.c index 4def2c713..d70c71e0f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -36,6 +36,7 @@ #endif #include "k_kart.h" +#include "k_battle.h" // protos. //static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}}; @@ -10210,73 +10211,6 @@ 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; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 7d2e9a307..a79f90559 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3277,6 +3277,8 @@ static void P_NetArchiveMisc(void) // SRB2kart WRITEINT32(save_p, numgotboxes); + WRITEUINT8(save_p, numtargets); + WRITEUINT8(save_p, targetsspawned); WRITEUINT8(save_p, gamespeed); WRITEUINT8(save_p, franticitems); @@ -3386,6 +3388,8 @@ static inline boolean P_NetUnArchiveMisc(void) // SRB2kart numgotboxes = READINT32(save_p); + numtargets = READUINT8(save_p); + targetsspawned = (boolean)READUINT8(save_p); gamespeed = READUINT8(save_p); franticitems = (boolean)READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index d1ef91705..81bbcdd68 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -84,6 +84,7 @@ // SRB2Kart #include "k_kart.h" +#include "k_battle.h" // K_SpawnBattleCapsules // // Map MD5, calculated on level load. @@ -1021,6 +1022,12 @@ static void P_LoadThings(void) if (mt->type == mobjinfo[MT_RANDOMITEM].doomednum) nummapboxes++; + if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum) + { + maptargets++; + continue; // These should not be spawned *yet* + } + mt->mobj = NULL; P_SpawnMapThing(mt); } @@ -1077,14 +1084,19 @@ static void P_LoadThings(void) for (i = 0; i < nummapthings; i++, mt++) { if (mt->type == 300 || mt->type == 308 || mt->type == 309 - || mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) - || mt->type == 1705 || mt->type == 1713 || mt->type == 1800) + || mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) + || mt->type == 1705 || mt->type == 1713 || mt->type == 1800) { + sector_t *mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; + mt->mobj = NULL; - // Z for objects Tails 05-26-2002 - mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) - ->sector->floorheight>>FRACBITS); + // Z for objects + mt->z = (INT16)( +#ifdef ESLOPE + mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : +#endif + mtsector->floorheight)>>FRACBITS; P_SpawnHoopsAndRings (mt); } @@ -2291,15 +2303,13 @@ static void P_LevelInitStuff(void) memset(localaiming, 0, sizeof(localaiming)); - // map object scale - mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale; - // special stage tokens, emeralds, and ring total tokenbits = 0; runemeraldmanager = false; nummaprings = 0; - nummapboxes = 0; - numgotboxes = 0; + nummapboxes = numgotboxes = 0; + maptargets = numtargets = 0; + targetsspawned = false; // emerald hunt hunt1 = hunt2 = hunt3 = NULL; @@ -3140,44 +3150,7 @@ boolean P_SetupLevel(boolean skipprecip) /*else if (modeattacking == ATTACKING_NIGHTS && !demo.playback) P_LoadNightsGhosts();*/ - if (G_TagGametype()) - { - INT32 realnumplayers = 0; - INT32 playersactive[MAXPLAYERS]; - - //I just realized how problematic this code can be. - //D_NumPlayers() will not always cover the scope of the netgame. - //What if one player is node 0 and the other node 31? - //The solution? Make a temp array of all players that are currently playing and pick from them. - //Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended? - //Also, you'd never have to loop through all 32 players slots to find anything ever again. - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator) - { - playersactive[realnumplayers] = i; //stores the player's node in the array. - realnumplayers++; - } - } - - if (realnumplayers) //this should also fix the dedicated crash bug. You only pick a player if one exists to be picked. - { - i = P_RandomKey(realnumplayers); - players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts. - - // Taken and modified from G_DoReborn() - // Remove the player so he can respawn elsewhere. - // first dissasociate the corpse - if (players[playersactive[i]].mo) - P_RemoveMobj(players[playersactive[i]].mo); - - G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location. - } - else - CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n")); - - } - else if (G_RaceGametype() && server) + if (G_RaceGametype() && server) CV_StealthSetValue(&cv_numlaps, ((netgame || multiplayer) && cv_basenumlaps.value && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) @@ -3304,6 +3277,8 @@ boolean P_SetupLevel(boolean skipprecip) if (!(netgame || multiplayer) && !majormods) mapvisited[gamemap-1] |= MV_VISITED; + G_AddMapToBuffer(gamemap-1); + levelloading = false; P_RunCachedActions(); @@ -3341,7 +3316,8 @@ boolean P_SetupLevel(boolean skipprecip) #endif } - G_AddMapToBuffer(gamemap-1); + // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match + K_SpawnBattleCapsules(); return true; } diff --git a/src/p_spec.c b/src/p_spec.c index ec5de3224..1479d54b8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5668,6 +5668,9 @@ static void P_RunLevelLoadExecutors(void) */ void P_InitSpecials(void) { + // Set the map object scale + mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale; + // Set the default gravity. Custom gravity overrides this setting. gravity = (FRACUNIT*8)/10; diff --git a/src/p_tick.c b/src/p_tick.c index 2502c7213..297bf31e6 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -23,6 +23,7 @@ #include "lua_script.h" #include "lua_hook.h" #include "k_kart.h" +#include "k_battle.h" // Object place #include "m_cheat.h" diff --git a/src/sounds.h b/src/sounds.h index bb46ea9d8..a05c7babd 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -14,6 +14,8 @@ #ifndef __SOUNDS__ #define __SOUNDS__ +#include "doomdef.h" + // Customisable sounds for Skins typedef enum { diff --git a/src/y_inter.c b/src/y_inter.c index c270f04ab..855aae6a2 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -433,7 +433,7 @@ void Y_IntermissionDrawer(void) if (data.match.rankingsmode) timeheader = "RANK"; else - timeheader = (intertype == int_race ? "TIME" : "SCORE"); + timeheader = ((intertype == int_race || (intertype == int_match && targetsspawned)) ? "TIME" : "SCORE"); // draw the level name V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.match.levelstring); @@ -519,7 +519,7 @@ void Y_IntermissionDrawer(void) V_DrawRightAlignedThinString(x+152+gutter, y-1, (data.match.numplayers > NUMFORNEWCOLUMN ? V_6WIDTHSPACE : 0), "NO CONTEST."); else { - if (intertype == int_race) + if (intertype == int_race || (intertype == int_match && targetsspawned)) { snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(data.match.val[i], true), G_TicsToSeconds(data.match.val[i]), G_TicsToCentiseconds(data.match.val[i])); @@ -840,7 +840,7 @@ void Y_StartIntermission(void) case int_match: { // Calculate who won - Y_CalculateMatchData(0, Y_CompareBattle); + Y_CalculateMatchData(0, targetsspawned ? Y_CompareRace : Y_CompareBattle); if (cv_inttime.value > 0) S_ChangeMusicInternal("racent", true); // loop it break; From 88578f0534d053adadaeffce42bccf5b83339d95 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 15 Sep 2019 23:36:55 -0400 Subject: [PATCH 05/17] Moving capsules --- src/k_battle.c | 88 +++++++++++++++++++++++++---- src/p_mobj.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 223 insertions(+), 14 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index dafabf670..abf1d4540 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -233,6 +233,67 @@ void K_CheckBumpers(void) P_DoPlayerExit(&players[i]); } +static void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj) +{ + UINT8 sequence = mt->extrainfo-1; + fixed_t speed = (FRACUNIT >> 3) * mt->angle; + boolean backandforth = (mt->options & MTF_AMBUSH); + boolean reverse = (mt->options & MTF_OBJECTSPECIAL); + mobj_t *mo2; + mobj_t *target = NULL; + thinker_t *th; + + // Find the inital target + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (reverse) // Use the highest waypoint number as first + { + if (mo2->health != 0) + { + if (target == NULL) + target = mo2; + else if (mo2->health > target->health) + target = mo2; + } + } + else // Use the lowest waypoint number as first + { + if (mo2->health == 0) + target = mo2; + } + } + } + + if (!target) + { + CONS_Alert(CONS_WARNING, "No target waypoint found for moving capsule (seq: #%d)\n", sequence); + return; + } + + P_SetTarget(&mobj->target, target); + mobj->lastlook = sequence; + mobj->movecount = target->health; + mobj->movefactor = speed; + + if (backandforth) + mobj->cusval = 1; + + if (reverse) + mobj->cvmem = -1; + else + mobj->cvmem = 1; +} + void K_SpawnBattleCapsules(void) { mapthing_t *mt; @@ -269,6 +330,7 @@ void K_SpawnBattleCapsules(void) UINT8 numfloors = 1; mobj_t *mobj = NULL; boolean fly = true; + UINT8 j; mt->mobj = NULL; @@ -352,9 +414,9 @@ void K_SpawnBattleCapsules(void) mobj->flags2 |= MF2_OBJECTFLIP; } - for (i = 0; i < numfloors; i++) + for (j = 0; j < numfloors; j++) { - if (z == floorheights[i]) + if (z == floorheights[j]) { fly = false; break; @@ -368,6 +430,10 @@ void K_SpawnBattleCapsules(void) mobj->extravalue1 = 1; // Set extravalue1 for later reference } + // Moving capsules! + if (mt->extrainfo && mt->angle) + K_SetupMovingCapsule(mt, mobj); + // Moved from P_SpawnMobj due to order of operations mumbo jumbo { mobj_t *cur, *prev = mobj; @@ -392,16 +458,17 @@ void K_SpawnBattleCapsules(void) prev = cur; // Supports on the bottom - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) { cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - cur->extravalue1 = i; + cur->extravalue1 = j; - // TODO: use karma bomb wheels on grounded, moving capsules - if (mobj->extravalue1) + if (mobj->extravalue1) // Flying capsule, moving or not P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORTFLY); + else if (mobj->target && !P_MobjWasRemoved(mobj->target)) // Grounded, moving capsule + P_SetMobjState(cur, S_KARMAWHEEL); else - P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT); + P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT); // Grounded, stationary capsule P_SetTarget(&cur->target, mobj); P_SetTarget(&cur->hprev, prev); @@ -410,12 +477,12 @@ void K_SpawnBattleCapsules(void) } // Side paneling - for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) { cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - cur->extravalue1 = i; + cur->extravalue1 = j; - if (i & 1) + if (j & 1) P_SetMobjState(cur, S_BATTLECAPSULE_SIDE2); else P_SetMobjState(cur, S_BATTLECAPSULE_SIDE1); @@ -427,7 +494,6 @@ void K_SpawnBattleCapsules(void) } } - mobj->angle = FixedAngle(mt->angle * FRACUNIT); mt->mobj = mobj; } } diff --git a/src/p_mobj.c b/src/p_mobj.c index d70c71e0f..4bab95137 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9130,7 +9130,147 @@ void P_MobjThinker(mobj_t *mobj) mobj->momz = sine/2; } - // TODO: insert moving capsule code here + // Moving capsules + if (mobj->target && !P_MobjWasRemoved(mobj->target)) + { + fixed_t speed = mobj->movefactor; + UINT8 sequence = mobj->lastlook; + UINT8 num = mobj->movecount; + boolean backandforth = mobj->cusval; + SINT8 direction = mobj->cvmem; + mobj_t *next = NULL; + thinker_t *th; + fixed_t dist, momx, momy, momz; + + dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); + if (mobj->extravalue1) + dist = P_AproxDistance(dist, mobj->target->z - mobj->z); + if (dist < 1) + dist = 1; + + if (speed <= dist) + { + momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); + momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); + if (mobj->extravalue1) + momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); + + mobj->momx = momx; + mobj->momy = momy; + if (mobj->extravalue1) + mobj->momz = momz; + } + else + { + mobj_t *mo2; + + speed -= dist; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + mobj->z = mobj->target->z; + P_SetThingPosition(mobj); + + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + + // Onto the next waypoint! + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (mo2->health == num + direction) + { + next = mo2; + break; + } + } + } + + // Are we at the end of the waypoint chain? + // If so, search again for the first/previous waypoint (depending on settings) + if (next == NULL) + { + if (backandforth) + { + mobj->cvmem = -mobj->cvmem; + direction = mobj->cvmem; + } + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (backandforth) + { + if (mo2->health == num + direction) + { + next = mo2; + break; + } + } + else + { + if (direction < 0) + { + if (next == NULL || mo2->health > next->health) + next = mo2; + } + else + { + if (next == NULL || mo2->health < next->health) + next = mo2; + } + } + } + } + } + + if (next && !P_MobjWasRemoved(next)) + { + P_SetTarget(&mobj->target, next); + mobj->movecount = next->health; + + dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); + if (mobj->extravalue1) + dist = P_AproxDistance(dist, mobj->target->z - mobj->z); + if (dist < 1) + dist = 1; + + momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); + momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); + if (mobj->extravalue1) + momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); + + mobj->momx = momx; + mobj->momy = momy; + if (mobj->extravalue1) + mobj->momz = momz; + } + else + { + CONS_Alert(CONS_WARNING, "Moving capsule could not find next waypoint! (seq: %d)\n", sequence); + P_SetTarget(&mobj->target, NULL); + } + } + } if (flip == -1) bottom = mobj->z + mobj->height; @@ -9159,7 +9299,9 @@ void P_MobjThinker(mobj_t *mobj) 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) + else if (state == S_BATTLECAPSULE_SUPPORT + || state == S_BATTLECAPSULE_SUPPORTFLY + || state == S_KARMAWHEEL) { fixed_t offx = mobj->radius; fixed_t offy = mobj->radius; @@ -9173,7 +9315,8 @@ void P_MobjThinker(mobj_t *mobj) newx += offx; newy += offy; } - else if (state == S_BATTLECAPSULE_SIDE1 || state == S_BATTLECAPSULE_SIDE2) + else if (state == S_BATTLECAPSULE_SIDE1 + || state == S_BATTLECAPSULE_SIDE2) { fixed_t offset = 48 * mobj->scale; angle_t angle = (ANGLE_45 * cur->extravalue1); From b174f1526064cc39bbe48255e57b22b9973ffa35 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 15 Sep 2019 23:40:50 -0400 Subject: [PATCH 06/17] Waiting for the roulette gives you Orbinaut x3 instead of just one Should reduce the amount of waiting, and make banana vs orbis more of a decision --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index f9926d570..9c6a1a3ed 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1155,8 +1155,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) } else { - if (modeattacking || cv_orbinaut.value) // Waited patiently? You get an orbinaut! - K_KartGetItemResult(player, KITEM_ORBINAUT); + if (modeattacking || cv_tripleorbinaut.value) // Waited patiently? You get Orbinaut x3! + K_KartGetItemResult(player, KRITEM_TRIPLEORBINAUT); else // Default to sad if nothing's enabled... K_KartGetItemResult(player, KITEM_SAD); player->karthud[khud_itemblinkmode] = 0; From e84c618da8ffeaa84332db0c02f7d2b50bd8c013 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 24 Sep 2019 07:17:05 -0400 Subject: [PATCH 07/17] Rudimentary Record Attack support --- src/d_clisrv.c | 6 +- src/dehacked.c | 8 +-- src/doomstat.h | 2 +- src/g_game.c | 187 +++++++++++++++++++++++-------------------------- src/m_cond.c | 3 +- src/m_cond.h | 4 +- src/m_menu.c | 186 ++++++++++++++++++++---------------------------- src/p_setup.c | 19 ++--- src/st_stuff.c | 2 +- src/y_inter.c | 71 ++++++++++--------- 10 files changed, 226 insertions(+), 262 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 33a1dfe61..a88f06f13 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3683,7 +3683,11 @@ void SV_StartSinglePlayerServer(void) server = true; netgame = false; multiplayer = false; - gametype = GT_RACE; //srb2kart + + if (modeattacking == ATTACKING_CAPSULES) + gametype = GT_MATCH; //srb2kart + else + gametype = GT_RACE; //srb2kart // no more tic the game with this settings! SV_StopServer(); diff --git a/src/dehacked.c b/src/dehacked.c index edfade76b..ed1700b18 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2473,10 +2473,10 @@ static void readunlockable(MYFILE *f, INT32 num) unlockables[num].type = SECRET_PANDORA; else if (fastcmp(word2, "CREDITS")) unlockables[num].type = SECRET_CREDITS; - else if (fastcmp(word2, "RECORDATTACK")) - unlockables[num].type = SECRET_RECORDATTACK; - else if (fastcmp(word2, "NIGHTSMODE")) - unlockables[num].type = SECRET_NIGHTSMODE; + else if (fastcmp(word2, "TIMEATTACK")) + unlockables[num].type = SECRET_TIMEATTACK; + else if (fastcmp(word2, "BREAKTHECAPSULES")) + unlockables[num].type = SECRET_BREAKTHECAPSULES; else if (fastcmp(word2, "HEADER")) unlockables[num].type = SECRET_HEADER; else if (fastcmp(word2, "LEVELSELECT")) diff --git a/src/doomstat.h b/src/doomstat.h index 716b3fe85..4ba7cc665 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -64,7 +64,7 @@ extern boolean metalrecording; #define ATTACKING_NONE 0 #define ATTACKING_RECORD 1 -//#define ATTACKING_NIGHTS 2 +#define ATTACKING_CAPSULES 2 extern UINT8 modeattacking; // menu demo things diff --git a/src/g_game.c b/src/g_game.c index 50aa7b904..ba9382c37 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2866,9 +2866,13 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) return; } + // -- Record Attack -- + if (modeattacking) + spawnpoint = playerstarts[0]; + // -- CTF -- // Order: CTF->DM->Coop - if (gametype == GT_CTF && players[playernum].ctfteam) + else if (gametype == GT_CTF && players[playernum].ctfteam) { if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start @@ -4745,8 +4749,8 @@ char *G_BuildMapTitle(INT32 mapnum) #define DEMOHEADER "\xF0" "KartReplay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! -#define DF_RECORDATTACK 0x02 // This demo is from record attack and contains its final completion time! -#define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares! +#define DF_TIMEATTACK 0x02 // This demo is from Time Attack and contains its final completion time & best lap! +#define DF_BREAKTHECAPSULES 0x04 // This demo is from Break the Capsules and contains its final completion time! #define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? #define DF_ATTACKSHIFT 1 #define DF_ENCORE 0x40 @@ -4790,7 +4794,6 @@ static ticcmd_t oldcmd[MAXPLAYERS]; // Not used for Metal Sonic #define GZT_SPRITE 0x10 // Animation frame #define GZT_EXTRA 0x20 -#define GZT_NIGHTS 0x40 // NiGHTS Mode stuff! // GZT_EXTRA flags #define EZT_THOK 0x01 // Spawned a thok object @@ -5294,13 +5297,6 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) if (!(demoflags & DF_GHOST)) return; // No ghost data to write. - if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer) - { - // We're talking about the NiGHTS thing, not the normal platforming thing! - ziptic |= GZT_NIGHTS; - ghost = ghost->tracer; - } - ziptic_p = demo_p++; // the ziptic, written at the end of this function #define MAXMOM (0x7FFF<<8) @@ -5517,12 +5513,6 @@ void G_ConsGhostTic(INT32 playernum) demo_p++; if (ziptic & GZT_SPRITE) demo_p++; - if(ziptic & GZT_NIGHTS) { - if (!testmo || !testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer) - nightsfail = true; - else - testmo = testmo->tracer; - } if (ziptic & GZT_EXTRA) { // But wait, there's more! @@ -6373,20 +6363,19 @@ void G_BeginRecording(void) switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - WRITEUINT32(demo_p,UINT32_MAX); // lap - break; - /*case ATTACKING_NIGHTS: // 2 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - WRITEUINT32(demo_p,0); // score - break;*/ - default: // 3 - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + WRITEUINT32(demo_p,UINT32_MAX); // lap + break; + case ATTACKING_CAPSULES: // 2 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + break; + default: // 3 + break; } WRITEUINT32(demo_p,P_GetInitSeed()); @@ -6524,18 +6513,18 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap) { if (!demo.recording || !demotime_p) return; - if (demoflags & DF_RECORDATTACK) + if (demoflags & DF_TIMEATTACK) { WRITEUINT32(demotime_p, ptime); WRITEUINT32(demotime_p, plap); demotime_p = NULL; } - /*else if (demoflags & DF_NIGHTSATTACK) + else if (demoflags & DF_BREAKTHECAPSULES) { WRITEUINT32(demotime_p, ptime); - WRITEUINT32(demotime_p, pscore); + (void)plap; demotime_p = NULL; - }*/ + } } static void G_LoadDemoExtraFiles(UINT8 **pp) @@ -6711,6 +6700,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) UINT8 c; UINT16 s ATTRUNUSED; UINT8 aflags = 0; + boolean uselaps = false; // load the new file FIL_DefaultExtension(newname, ".lmp"); @@ -6737,20 +6727,17 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p++; // gametype G_SkipDemoExtraFiles(&p); - aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK); + aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES); I_Assert(aflags); - if (flags & DF_RECORDATTACK) - { - newtime = READUINT32(p); + + if (flags & DF_TIMEATTACK) + uselaps = true; // get around uninitalized error + + newtime = READUINT32(p); + if (uselaps) newlap = READUINT32(p); - } - /*else if (flags & DF_NIGHTSATTACK) - { - newtime = READUINT32(p); - newscore = READUINT32(p); - }*/ - else // appease compiler - return 0; + else + newlap = UINT32_MAX; Z_Free(buffer); @@ -6809,28 +6796,32 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) Z_Free(buffer); return UINT8_MAX; } - if (flags & DF_RECORDATTACK) - { - oldtime = READUINT32(p); + + oldtime = READUINT32(p); + if (uselaps) oldlap = READUINT32(p); - } - /*else if (flags & DF_NIGHTSATTACK) - { - oldtime = READUINT32(p); - oldscore = READUINT32(p); - }*/ - else // appease compiler - return UINT8_MAX; + else + oldlap = 0; Z_Free(buffer); c = 0; - if (newtime < oldtime - || (newtime == oldtime && (newlap < oldlap))) - c |= 1; // Better time - if (newlap < oldlap - || (newlap == oldlap && newtime < oldtime)) - c |= 1<<1; // Better lap time + + if (uselaps) + { + if (newtime < oldtime + || (newtime == oldtime && (newlap < oldlap))) + c |= 1; // Better time + if (newlap < oldlap + || (newlap == oldlap && newtime < oldtime)) + c |= 1<<1; // Better lap time + } + else + { + if (newtime < oldtime) + c |= 1; // Better time + } + return c; } @@ -7246,19 +7237,18 @@ void G_DoPlayDemo(char *defdemoname) switch (modeattacking) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - hu_demotime = READUINT32(demo_p); - hu_demolap = READUINT32(demo_p); - break; - /*case ATTACKING_NIGHTS: // 2 - hu_demotime = READUINT32(demo_p); - hu_demoscore = READUINT32(demo_p); - break;*/ - default: // 3 - modeattacking = ATTACKING_NONE; - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + hu_demotime = READUINT32(demo_p); + hu_demolap = READUINT32(demo_p); + break; + case ATTACKING_CAPSULES: // 2 + hu_demotime = READUINT32(demo_p); + break; + default: // 3 + modeattacking = ATTACKING_NONE; + break; } // Random seed @@ -7651,18 +7641,19 @@ void G_AddGhost(char *defdemoname) if (ghostversion != 0x0001) #endif G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. + switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - p += 8; // demo time, lap - break; - /*case ATTACKING_NIGHTS: // 2 - p += 8; // demo time left, score - break;*/ - default: // 3 - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + p += 8; // demo time, lap + break; + case ATTACKING_CAPSULES: // 2 + p += 4; // demo time + break; + default: // 3 + break; } p += 4; // random seed @@ -7901,16 +7892,16 @@ void G_UpdateStaffGhostName(lumpnum_t l) switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - p += 8; // demo time, lap - break; - /*case ATTACKING_NIGHTS: // 2 - p += 8; // demo time left, score - break;*/ - default: // 3 - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + p += 8; // demo time, lap + break; + case ATTACKING_CAPSULES: // 2 + p += 4; // demo time + break; + default: // 3 + break; } p += 4; // random seed @@ -8256,7 +8247,7 @@ void G_SaveDemo(void) free(demobuffer); demo.recording = false; - if (modeattacking != ATTACKING_RECORD) + if (!modeattacking) { if (demo.savemode == DSM_SAVED) CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); diff --git a/src/m_cond.c b/src/m_cond.c index b777e7d22..2195b42e4 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -171,7 +171,8 @@ unlockable_t unlockables[MAXUNLOCKABLES] = /* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, false, false, 0}, /* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, false, false, 0}, - /* 07 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0}, + /* 07 */ {"Time Attack", "", -1, -1, SECRET_TIMEATTACK, 0, true, true, 0}, + /* 08 */ {"Break the Capsules", "", -1, -1, SECRET_BREAKTHECAPSULES, 0, true, true, 0}, }; // Default number of emblems and extra emblems diff --git a/src/m_cond.h b/src/m_cond.h index 07e4480d1..37edcada9 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -117,8 +117,8 @@ typedef struct #define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar #define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints #define SECRET_PANDORA -3 // Enables Pandora's Box -#define SECRET_RECORDATTACK -2 // Enables Record Attack on the main menu -#define SECRET_NIGHTSMODE -1 // Enables NiGHTS Mode on the main menu +#define SECRET_TIMEATTACK -2 // Enables Time Attack on the main menu +#define SECRET_BREAKTHECAPSULES -1 // Enables Break the Capsules on the main menu #define SECRET_HEADER 0 // Does nothing on its own, just serves as a header for the menu #define SECRET_LEVELSELECT 1 // Selectable level select #define SECRET_WARP 2 // Selectable warp diff --git a/src/m_menu.c b/src/m_menu.c index 166b115d6..ed7afd81d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -133,8 +133,8 @@ typedef enum { LLM_CREATESERVER, LLM_LEVELSELECT, - LLM_RECORDATTACK, - LLM_NIGHTSATTACK + LLM_TIMEATTACK, + LLM_BREAKTHECAPSULES } levellist_mode_t; levellist_mode_t levellistmode = LLM_CREATESERVER; @@ -200,9 +200,7 @@ static char *M_GetConditionString(condition_t cond); menu_t SR_MainDef, SR_UnlockChecklistDef; // Misc. Main Menu -#if 0 // Bring this back when we have actual single-player static void M_SinglePlayerMenu(INT32 choice); -#endif static void M_Options(INT32 choice); static void M_Manual(INT32 choice); static void M_SelectableClearMenus(INT32 choice); @@ -225,7 +223,7 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef, MISC_ChangeSpectateDef; //static void M_LoadGame(INT32 choice); static void M_TimeAttack(INT32 choice); static boolean M_QuitTimeAttackMenu(void); -//static void M_NightsAttack(INT32 choice); +static void M_BreakTheCapsules(INT32 choice); static void M_Statistics(INT32 choice); static void M_HandleStaffReplay(INT32 choice); static void M_ReplayTimeAttack(INT32 choice); @@ -473,8 +471,7 @@ static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDEN|CV_CALL, dummystaf static menuitem_t MainMenu[] = { {IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_MainDef, 76}, - //{IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84}, - {IT_CALL |IT_STRING, NULL, "Time Attack", M_TimeAttack, 84}, + {IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84}, {IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 92}, {IT_CALL |IT_STRING, NULL, "Options", M_Options, 100}, {IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108}, @@ -790,18 +787,16 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { - //{IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, - {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 100}, - //{IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108}, - {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 108}, + //{IT_CALL | IT_STRING, NULL, "Grand Prix", M_LoadGame, 92}, + {IT_SECRET, NULL, "Time Attack", M_TimeAttack, 100}, + {IT_SECRET, NULL, "Break the Capsules", M_BreakTheCapsules, 108}, }; enum { - //sploadgame, - sprecordattack, - //spnightsmode, - spstatistics + //spgrandprix, + sptimeattack, + spbreakthecapsules }; // Single Player Load Game @@ -1860,52 +1855,6 @@ static menu_t SP_GhostDef = NULL }; -/*static menu_t SP_NightsAttackDef = -{ - "M_NIGHTS", - sizeof (SP_NightsAttackMenu)/sizeof (menuitem_t), - &MainDef, // Doesn't matter. - SP_NightsAttackMenu, - M_DrawNightsAttackMenu, - 32, 40, - 0, - NULL -}; -static menu_t SP_NightsReplayDef = -{ - "M_NIGHTS", - sizeof(SP_NightsReplayMenu)/sizeof(menuitem_t), - &SP_NightsAttackDef, - SP_NightsReplayMenu, - M_DrawNightsAttackMenu, - 32, 120, - 0, - NULL -}; -static menu_t SP_NightsGuestReplayDef = -{ - "M_NIGHTS", - sizeof(SP_NightsGuestReplayMenu)/sizeof(menuitem_t), - &SP_NightsAttackDef, - SP_NightsGuestReplayMenu, - M_DrawNightsAttackMenu, - 32, 120, - 0, - NULL -}; -static menu_t SP_NightsGhostDef = -{ - "M_NIGHTS", - sizeof(SP_NightsGhostMenu)/sizeof(menuitem_t), - &SP_NightsAttackDef, - SP_NightsGhostMenu, - M_DrawNightsAttackMenu, - 32, 120, - 0, - NULL -};*/ - - /*menu_t SP_PlayerDef = { "M_PICKP", @@ -2144,7 +2093,7 @@ static void Nextmap_OnChange(void) CV_StealthSetValue(&cv_dummystaff, 0); - active = false; + active = 0; SP_TimeAttackMenu[taguest].status = IT_DISABLED; SP_TimeAttackMenu[tareplay].status = IT_DISABLED; //SP_TimeAttackMenu[taghost].status = IT_DISABLED; @@ -2165,11 +2114,15 @@ static void Nextmap_OnChange(void) SP_GuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL; active |= 3; } - if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_chooseskin.string))) { - SP_ReplayMenu[1].status = IT_WHITESTRING|IT_CALL; - SP_GuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL; - active |= 3; + + if (levellistmode != LLM_BREAKTHECAPSULES) { + if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_chooseskin.string))) { + SP_ReplayMenu[1].status = IT_WHITESTRING|IT_CALL; + SP_GuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL; + active |= 3; + } } + if (FIL_FileExists(va("%s-%s-last.lmp", gpath, cv_chooseskin.string))) { SP_ReplayMenu[2].status = IT_WHITESTRING|IT_CALL; SP_GuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL; @@ -4232,11 +4185,13 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) return false; // not unlocked return true;*/ - case LLM_RECORDATTACK: + case LLM_TIMEATTACK: + case LLM_BREAKTHECAPSULES: /*if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) return false;*/ - if (!(mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) + if ((levellistmode == LLM_TIMEATTACK && !(mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) + || (levellistmode == LLM_BREAKTHECAPSULES && !(mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH))) return false; if (M_MapLocked(mapnum+1)) @@ -4255,20 +4210,6 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) return false;*/ return true; - /*case LLM_NIGHTSATTACK: - if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true;*/ default: return false; } @@ -6594,18 +6535,16 @@ static void M_Credits(INT32 choice) // SINGLE PLAYER MENU // ================== -#if 0 // Bring this back when we have actual single-player static void M_SinglePlayerMenu(INT32 choice) { (void)choice; - SP_MainMenu[sprecordattack].status = - (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; - /*SP_MainMenu[spnightsmode].status = - (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;*/ + SP_MainMenu[sptimeattack].status = + (M_SecretUnlocked(SECRET_TIMEATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; + SP_MainMenu[spbreakthecapsules].status = + (M_SecretUnlocked(SECRET_BREAKTHECAPSULES)) ? IT_CALL|IT_STRING : IT_SECRET; M_SetupNextMenu(&SP_MainDef); } -#endif /*static void M_LoadGameLevelSelect(INT32 choice) { @@ -7586,8 +7525,11 @@ void M_DrawTimeAttackMenu(void) V_DrawFill((BASEVIDWIDTH - dupadjust)>>1, 78, dupadjust, 36, 159); - V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:"); - K_drawKartTimestamp(lap, 19, 86, 0, 2); + if (levellistmode != LLM_BREAKTHECAPSULES) + { + V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:"); + K_drawKartTimestamp(lap, 19, 86, 0, 2); + } V_DrawRightAlignedString(292, 80, highlightflags, "BEST TIME:"); K_drawKartTimestamp(time, 162, 86, cv_nextmap.value, 1); @@ -7676,11 +7618,43 @@ static void M_TimeAttack(INT32 choice) memset(skins_cons_t, 0, sizeof (skins_cons_t)); - levellistmode = LLM_RECORDATTACK; // Don't be dependent on cv_newgametype + levellistmode = LLM_TIMEATTACK; // Don't be dependent on cv_newgametype if (M_CountLevelsToShowInList() == 0) { - M_StartMessage(M_GetText("No record-attackable levels found.\n"),NULL,MM_NOTHING); + M_StartMessage(M_GetText("No levels found for Time Attack.\n"),NULL,MM_NOTHING); + return; + } + + M_PatchSkinNameTable(); + + M_PrepareLevelSelect(); + M_SetupNextMenu(&SP_TimeAttackDef); + + G_SetGamestate(GS_TIMEATTACK); + + if (cv_nextmap.value) + Nextmap_OnChange(); + else + CV_AddValue(&cv_nextmap, 1); + + itemOn = tastart; // "Start" is selected. + + S_ChangeMusicInternal("racent", true); +} + +// Same as above, but sets a different levellistmode. Should probably be merged... +static void M_BreakTheCapsules(INT32 choice) +{ + (void)choice; + + memset(skins_cons_t, 0, sizeof (skins_cons_t)); + + levellistmode = LLM_BREAKTHECAPSULES; // Don't be dependent on cv_newgametype + + if (M_CountLevelsToShowInList() == 0) + { + M_StartMessage(M_GetText("No levels found for Break the Capsules.\n"),NULL,MM_NOTHING); return; } @@ -7814,13 +7788,13 @@ static boolean M_QuitTimeAttackMenu(void) }*/ // Going to Nights Attack menu... -/*static void M_NightsAttack(INT32 choice) +/*static void M_BreakTheCapsules(INT32 choice) { (void)choice; memset(skins_cons_t, 0, sizeof (skins_cons_t)); - levellistmode = LLM_NIGHTSATTACK; // Don't be dependent on cv_newgametype + levellistmode = LLM_BREAKTHECAPSULES; // Don't be dependent on cv_newgametype if (M_CountLevelsToShowInList() == 0) { @@ -7848,7 +7822,7 @@ static boolean M_QuitTimeAttackMenu(void) (void)choice; emeralds = 0; M_ClearMenus(true); - modeattacking = ATTACKING_NIGHTS; + modeattacking = ATTACKING_CAPSULES; I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); @@ -7872,7 +7846,7 @@ static void M_ChooseTimeAttack(INT32 choice) (void)choice; emeralds = 0; M_ClearMenus(true); - modeattacking = ATTACKING_RECORD; + modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD); I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); @@ -7922,7 +7896,7 @@ static void M_HandleStaffReplay(INT32 choice) if (l == LUMPERROR) break; M_ClearMenus(true); - modeattacking = ATTACKING_RECORD; + modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD); demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed G_DoPlayDemo(va("%sS%02u",G_BuildMapName(cv_nextmap.value),cv_dummystaff.value)); break; @@ -7943,7 +7917,7 @@ static void M_ReplayTimeAttack(INT32 choice) { const char *which; M_ClearMenus(true); - modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows + modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD); // set modeattacking before G_DoPlayDemo so the map loader knows demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed if (currentMenu == &SP_ReplayDef) @@ -8090,10 +8064,8 @@ static void M_ModeAttackRetry(INT32 choice) { (void)choice; G_CheckDemoStatus(); // Cancel recording - if (modeattacking == ATTACKING_RECORD) + if (modeattacking) M_ChooseTimeAttack(0); - /*else if (modeattacking == ATTACKING_NIGHTS) - M_ChooseNightsAttack(0);*/ } static void M_ModeAttackEndGame(INT32 choice) @@ -8105,16 +8077,10 @@ static void M_ModeAttackEndGame(INT32 choice) Command_ExitGame_f(); M_StartControlPanel(); - switch(modeattacking) - { - default: - case ATTACKING_RECORD: + + if (modeattacking) currentMenu = &SP_TimeAttackDef; - break; - /*case ATTACKING_NIGHTS: - currentMenu = &SP_NightsAttackDef; - break;*/ - } + itemOn = currentMenu->lastOn; G_SetGamestate(GS_TIMEATTACK); modeattacking = ATTACKING_NONE; diff --git a/src/p_setup.c b/src/p_setup.c index 81bbcdd68..9c65ab9bb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2630,15 +2630,18 @@ static void P_LoadRecordGhosts(void) } // Best Lap ghost - if (cv_ghost_bestlap.value) + if (modeattacking != ATTACKING_CAPSULES) { - for (i = 0; i < numskins; ++i) + if (cv_ghost_bestlap.value) { - if (cv_ghost_bestlap.value == 1 && players[consoleplayer].skin != i) - continue; + for (i = 0; i < numskins; ++i) + { + if (cv_ghost_bestlap.value == 1 && players[consoleplayer].skin != i) + continue; - if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-lap-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, skins[i].name))) + G_AddGhost(va("%s-%s-lap-best.lmp", gpath, skins[i].name)); + } } } @@ -3145,10 +3148,8 @@ boolean P_SetupLevel(boolean skipprecip) } } - if (modeattacking == ATTACKING_RECORD && !demo.playback) + if (modeattacking && !demo.playback) P_LoadRecordGhosts(); - /*else if (modeattacking == ATTACKING_NIGHTS && !demo.playback) - P_LoadNightsGhosts();*/ if (G_RaceGametype() && server) CV_StealthSetValue(&cv_numlaps, diff --git a/src/st_stuff.c b/src/st_stuff.c index e59846aed..fb7bd2aa5 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1272,7 +1272,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused. #endif ) { - if (modeattacking == ATTACKING_NIGHTS) + if (modeattacking == ATTACKING_CAPSULES) { INT32 maretime = max(stplyr->realtime - stplyr->marebegunat, 0); fixed_t cornerx = vid.width, cornery = vid.height-SCZ(20); diff --git a/src/y_inter.c b/src/y_inter.c index 855aae6a2..aac984316 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -720,8 +720,13 @@ static void Y_UpdateRecordReplays(void) if ((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) mainrecords[gamemap-1]->time = players[consoleplayer].realtime; - if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap)) - mainrecords[gamemap-1]->lap = bestlap; + if (modeattacking != ATTACKING_CAPSULES) + { + if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap)) + mainrecords[gamemap-1]->lap = bestlap; + } + else + mainrecords[gamemap-1]->lap = 0; // Save demo! bestdemo[255] = '\0'; @@ -752,13 +757,16 @@ static void Y_UpdateRecordReplays(void) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string); - if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)) - { // Better lap time, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD LAP!"), M_GetText("Saved replay as"), bestdemo); + if (modeattacking != ATTACKING_CAPSULES) + { + snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string); + if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)) + { // Better lap time, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD LAP!"), M_GetText("Saved replay as"), bestdemo); + } } //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); @@ -800,12 +808,20 @@ void Y_StartIntermission(void) { timer = 0; - /* // srb2kart: time attack tally is UGLY rn - if (modeattacking) - intertype = int_timeattack; - else - */ - intertype = int_race; + if (!majormods && !multiplayer && !demo.playback) // move this once we have a proper time attack screen + { + // Update visitation flags + mapvisited[gamemap-1] |= MV_BEATEN; + if (ALL7EMERALDS(emeralds)) + mapvisited[gamemap-1] |= MV_ALLEMERALDS; + /*if (ultimatemode) + mapvisited[gamemap-1] |= MV_ULTIMATE; + if (data.coop.gotperfbonus) + mapvisited[gamemap-1] |= MV_PERFECT;*/ + + if (modeattacking) + Y_UpdateRecordReplays(); + } } else { @@ -820,13 +836,13 @@ void Y_StartIntermission(void) if (!timer) timer = 1; } - - if (gametype == GT_MATCH) - intertype = int_match; - else //if (gametype == GT_RACE) - intertype = int_race; } + if (gametype == GT_MATCH) + intertype = int_match; + else //if (gametype == GT_RACE) + intertype = int_race; + // We couldn't display the intermission even if we wanted to. // But we still need to give the players their score bonuses, dummy. //if (dedicated) return; @@ -847,21 +863,6 @@ void Y_StartIntermission(void) } case int_race: // (time-only race) { - if (!majormods && !multiplayer && !demo.playback) // remove this once we have a proper time attack screen - { - // Update visitation flags - mapvisited[gamemap-1] |= MV_BEATEN; - if (ALL7EMERALDS(emeralds)) - mapvisited[gamemap-1] |= MV_ALLEMERALDS; - /*if (ultimatemode) - mapvisited[gamemap-1] |= MV_ULTIMATE; - if (data.coop.gotperfbonus) - mapvisited[gamemap-1] |= MV_PERFECT;*/ - - if (modeattacking == ATTACKING_RECORD) - Y_UpdateRecordReplays(); - } - // Calculate who won Y_CalculateMatchData(0, Y_CompareRace); break; From 9cb834b0044e64b5ee11b54733584362fedc923b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 24 Sep 2019 11:24:01 -0400 Subject: [PATCH 08/17] Capsule counter, map change when spawning capsules mid-game --- src/doomstat.h | 2 -- src/g_game.c | 7 +--- src/k_battle.c | 14 ++++++-- src/k_battle.h | 3 ++ src/k_kart.c | 89 +++++++++++++++++++++++++++++++++++++------------- src/p_saveg.c | 6 ++-- src/p_setup.c | 2 +- src/y_inter.c | 7 ++-- 8 files changed, 91 insertions(+), 39 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 4ba7cc665..3a71975c9 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -355,8 +355,6 @@ extern UINT16 emeralds; extern INT32 nummaprings; // keep track of spawned rings/coins extern INT32 nummapboxes, numgotboxes; // keep track of spawned battle mode items -extern UINT8 maptargets, numtargets; // Keep track of spawend Battle Mode targets -extern boolean targetsspawned; // have targets been spawned already? /** Time attack information, currently a very small structure. */ diff --git a/src/g_game.c b/src/g_game.c index ba9382c37..a3be67bb7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -189,11 +189,6 @@ INT32 nummaprings = 0; INT32 nummapboxes = 0; INT32 numgotboxes = 0; -// Break the Capsules counters for Battle Mode! -UINT8 maptargets = 0; // targets in map -UINT8 numtargets = 0; // targets busted -boolean targetsspawned = false; // have targets been spawned already? - // Elminates unnecessary searching. boolean CheckForBustableBlocks; boolean CheckForBouncySector; @@ -2867,7 +2862,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) } // -- Record Attack -- - if (modeattacking) + if (modeattacking || battlecapsules) spawnpoint = playerstarts[0]; // -- CTF -- diff --git a/src/k_battle.c b/src/k_battle.c index abf1d4540..085b63e52 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -14,6 +14,13 @@ #include "r_defs.h" // MAXFFLOORS #include "info.h" +// Capsules mode enabled for this map? +boolean battlecapsules = false; + +// Capsule counters +UINT8 maptargets = 0; // Capsules in map +UINT8 numtargets = 0; // Capsules busted + boolean K_IsPlayerWanted(player_t *player) { UINT8 i; @@ -216,7 +223,8 @@ void K_CheckBumpers(void) if (numingame <= 1) { - K_SpawnBattleCapsules(); + if (!battlecapsules) + D_MapChange(gamemap, gametype, encoremode, true, 0, false, false); return; } @@ -300,7 +308,7 @@ void K_SpawnBattleCapsules(void) UINT8 n = 0; size_t i; - if (targetsspawned) + if (battlecapsules) return; if (!G_BattleGametype()) @@ -498,5 +506,5 @@ void K_SpawnBattleCapsules(void) } } - targetsspawned = true; + battlecapsules = true; } diff --git a/src/k_battle.h b/src/k_battle.h index 04c413d68..2a3f7c1c2 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -4,6 +4,9 @@ #include "doomtype.h" #include "d_player.h" +extern boolean battlecapsules; +extern UINT8 maptargets, numtargets; + boolean K_IsPlayerWanted(player_t *player); void K_CalculateBattleWanted(void); void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); diff --git a/src/k_kart.c b/src/k_kart.c index 8e9d89299..1aaf6769a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6715,6 +6715,8 @@ static patch_t *kp_lapstickernarrow; static patch_t *kp_splitlapflag; static patch_t *kp_bumpersticker; static patch_t *kp_bumperstickerwide; +static patch_t *kp_capsulesticker; +static patch_t *kp_capsulestickerwide; static patch_t *kp_karmasticker; static patch_t *kp_splitkarmabomb; static patch_t *kp_timeoutsticker; @@ -6743,6 +6745,7 @@ static patch_t *kp_speedometerlabel[4]; static patch_t *kp_rankbumper; static patch_t *kp_tinybumper[2]; static patch_t *kp_ranknobumpers; +static patch_t *kp_rankcapsule; static patch_t *kp_battlewin; static patch_t *kp_battlecool; @@ -6811,6 +6814,8 @@ void K_LoadKartHUDGraphics(void) kp_splitlapflag = W_CachePatchName("K_SPTLAP", PU_HUDGFX); kp_bumpersticker = W_CachePatchName("K_STBALN", PU_HUDGFX); kp_bumperstickerwide = W_CachePatchName("K_STBALW", PU_HUDGFX); + kp_capsulesticker = W_CachePatchName("K_STCAPN", PU_HUDGFX); + kp_capsulestickerwide = W_CachePatchName("K_STCAPW", PU_HUDGFX); kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX); kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX); kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX); @@ -6935,6 +6940,7 @@ void K_LoadKartHUDGraphics(void) kp_tinybumper[0] = W_CachePatchName("K_BLNA", PU_HUDGFX); kp_tinybumper[1] = W_CachePatchName("K_BLNB", PU_HUDGFX); kp_ranknobumpers = W_CachePatchName("K_NOBLNS", PU_HUDGFX); + kp_rankcapsule = W_CachePatchName("K_CAPICO", PU_HUDGFX); // Battle graphics kp_battlewin = W_CachePatchName("K_BWIN", PU_HUDGFX); @@ -8418,52 +8424,91 @@ static void K_drawKartBumpersOrKarma(void) V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|splitflags, frameslash); - if (stplyr->kartstuff[k_bumper] <= 0) + if (battlecapsules) { - V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap); - V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_comebackpoints]) % 10]); - V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[2]); - } - else - { - V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap); + V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankcapsule, NULL); - if (stplyr->kartstuff[k_bumper] > 9 || cv_kartbumpers.value > 9) + if (numtargets > 9 || maptargets > 9) { UINT8 ln[2]; - ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10); - ln[1] = (abs(stplyr->kartstuff[k_bumper]) % 10); + ln[0] = ((numtargets / 10) % 10); + ln[1] = (numtargets % 10); V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); - ln[0] = ((abs(cv_kartbumpers.value) / 10) % 10); - ln[1] = (abs(cv_kartbumpers.value) % 10); + ln[0] = ((maptargets / 10) % 10); + ln[1] = (maptargets % 10); V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); } else { - V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]); - V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_kartbumpers.value) % 10]); + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[numtargets % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[maptargets % 10]); + } + } + else + { + if (stplyr->kartstuff[k_bumper] <= 0) + { + V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap); + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_comebackpoints]) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[2]); + } + else + { + V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap); + + if (stplyr->kartstuff[k_bumper] > 9 || cv_kartbumpers.value > 9) + { + UINT8 ln[2]; + ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10); + ln[1] = (abs(stplyr->kartstuff[k_bumper]) % 10); + + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + + ln[0] = ((abs(cv_kartbumpers.value) / 10) % 10); + ln[1] = (abs(cv_kartbumpers.value) % 10); + + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + } + else + { + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_kartbumpers.value) % 10]); + } } } } else { - if (stplyr->kartstuff[k_bumper] <= 0) + if (battlecapsules) { - V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_karmasticker, colormap); - V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/2", stplyr->kartstuff[k_comebackpoints])); + if (numtargets > 9 && maptargets > 9) + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_capsulestickerwide, NULL); + else + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_capsulesticker, NULL); + V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", numtargets, maptargets)); } else { - if (stplyr->kartstuff[k_bumper] > 9 && cv_kartbumpers.value > 9) - V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap); + if (stplyr->kartstuff[k_bumper] <= 0) + { + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_karmasticker, colormap); + V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/2", stplyr->kartstuff[k_comebackpoints])); + } else - V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap); - V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); + { + if (stplyr->kartstuff[k_bumper] > 9 && cv_kartbumpers.value > 9) + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap); + else + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap); + V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); + } } } } diff --git a/src/p_saveg.c b/src/p_saveg.c index a79f90559..baf4f9ee0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -34,6 +34,8 @@ #include "p_slopes.h" #endif +#include "k_battle.h" + savedata_t savedata; UINT8 *save_p; @@ -3278,7 +3280,7 @@ static void P_NetArchiveMisc(void) // SRB2kart WRITEINT32(save_p, numgotboxes); WRITEUINT8(save_p, numtargets); - WRITEUINT8(save_p, targetsspawned); + WRITEUINT8(save_p, battlecapsules); WRITEUINT8(save_p, gamespeed); WRITEUINT8(save_p, franticitems); @@ -3389,7 +3391,7 @@ static inline boolean P_NetUnArchiveMisc(void) // SRB2kart numgotboxes = READINT32(save_p); numtargets = READUINT8(save_p); - targetsspawned = (boolean)READUINT8(save_p); + battlecapsules = (boolean)READUINT8(save_p); gamespeed = READUINT8(save_p); franticitems = (boolean)READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 9c65ab9bb..09cd8cf6d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2309,7 +2309,7 @@ static void P_LevelInitStuff(void) nummaprings = 0; nummapboxes = numgotboxes = 0; maptargets = numtargets = 0; - targetsspawned = false; + battlecapsules = false; // emerald hunt hunt1 = hunt2 = hunt3 = NULL; diff --git a/src/y_inter.c b/src/y_inter.c index aac984316..8a90e20b2 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -39,6 +39,7 @@ #include "m_random.h" // M_RandomKey #include "g_input.h" // PLAYER1INPUTDOWN #include "k_kart.h" // colortranslations +#include "k_battle.h" #include "console.h" // cons_menuhighlight #include "lua_hook.h" // IntermissionThinker hook @@ -433,7 +434,7 @@ void Y_IntermissionDrawer(void) if (data.match.rankingsmode) timeheader = "RANK"; else - timeheader = ((intertype == int_race || (intertype == int_match && targetsspawned)) ? "TIME" : "SCORE"); + timeheader = ((intertype == int_race || (intertype == int_match && battlecapsules)) ? "TIME" : "SCORE"); // draw the level name V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.match.levelstring); @@ -519,7 +520,7 @@ void Y_IntermissionDrawer(void) V_DrawRightAlignedThinString(x+152+gutter, y-1, (data.match.numplayers > NUMFORNEWCOLUMN ? V_6WIDTHSPACE : 0), "NO CONTEST."); else { - if (intertype == int_race || (intertype == int_match && targetsspawned)) + if (intertype == int_race || (intertype == int_match && battlecapsules)) { snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(data.match.val[i], true), G_TicsToSeconds(data.match.val[i]), G_TicsToCentiseconds(data.match.val[i])); @@ -856,7 +857,7 @@ void Y_StartIntermission(void) case int_match: { // Calculate who won - Y_CalculateMatchData(0, targetsspawned ? Y_CompareRace : Y_CompareBattle); + Y_CalculateMatchData(0, battlecapsules ? Y_CompareRace : Y_CompareBattle); if (cv_inttime.value > 0) S_ChangeMusicInternal("racent", true); // loop it break; From dbb6f9ca116611ce925bb024f6a87293221dc5d7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 27 Sep 2019 04:20:09 -0400 Subject: [PATCH 09/17] use MF2_AMBUSH for backandforth --- src/k_battle.c | 12 ++++++++---- src/p_mobj.c | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index 085b63e52..913202637 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -293,13 +293,17 @@ static void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj) mobj->movecount = target->health; mobj->movefactor = speed; - if (backandforth) - mobj->cusval = 1; + if (backandforth) { + mobj->flags2 |= MF2_AMBUSH; + } else { + mobj->flags2 &= ~MF2_AMBUSH; + } - if (reverse) + if (reverse) { mobj->cvmem = -1; - else + } else { mobj->cvmem = 1; + } } void K_SpawnBattleCapsules(void) diff --git a/src/p_mobj.c b/src/p_mobj.c index 3f02c16e0..d994a017f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9377,7 +9377,7 @@ void P_MobjThinker(mobj_t *mobj) fixed_t speed = mobj->movefactor; UINT8 sequence = mobj->lastlook; UINT8 num = mobj->movecount; - boolean backandforth = mobj->cusval; + boolean backandforth = (mobj->flags2 & MF2_AMBUSH); SINT8 direction = mobj->cvmem; mobj_t *next = NULL; thinker_t *th; From 48ff9ddf85dea5b87f3e25a6d88ee02ecadcc7fd Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 1 Mar 2020 15:58:00 -0500 Subject: [PATCH 10/17] Move overtime stuff to k_battle.c --- src/g_game.c | 3 - src/k_battle.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++ src/k_battle.h | 4 + src/p_local.h | 1 - src/p_mobj.c | 210 ------------------------------------------------ src/p_tick.c | 10 ++- 6 files changed, 224 insertions(+), 218 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 62dbc7684..966e71715 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -263,9 +263,6 @@ INT16 votelevels[5][2]; // Levels that were rolled by the host SINT8 votes[MAXPLAYERS]; // Each player's vote SINT8 pickedvote; // What vote the host rolls -// Battle overtime system -struct battleovertime battleovertime; - // Server-sided, synched variables SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points tic_t wantedcalcdelay; // Time before it recalculates WANTED diff --git a/src/k_battle.c b/src/k_battle.c index 913202637..bd44ff8fa 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -13,6 +13,9 @@ #include "r_main.h" #include "r_defs.h" // MAXFFLOORS #include "info.h" +#include "s_sound.h" +#include "m_random.h" +#include "r_sky.h" // skyflatnum // Capsules mode enabled for this map? boolean battlecapsules = false; @@ -241,6 +244,217 @@ void K_CheckBumpers(void) P_DoPlayerExit(&players[i]); } +#define MAXPLANESPERSECTOR (MAXFFLOORS+1)*2 + +static void K_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjtype_t type, boolean ceiling) +{ + UINT8 i; + fixed_t flatz[MAXPLANESPERSECTOR]; + boolean flip[MAXPLANESPERSECTOR]; + UINT8 numflats = 0; + mobj_t *mo; + subsector_t *ss = R_IsPointInSubsector(x, y); + sector_t *sec; + + if (!ss) + return; + sec = ss->sector; + + // convoluted stuff JUST to get all of the planes we need to draw orbs on :V + + for (i = 0; i < MAXPLANESPERSECTOR; i++) + flip[i] = false; + + if (sec->floorpic != skyflatnum) + { +#ifdef ESLOPE + flatz[numflats] = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight); +#else + flatz[numflats] = (sec->floorheight); +#endif + numflats++; + } + if (sec->ceilingpic != skyflatnum && ceiling) + { +#ifdef ESLOPE + flatz[numflats] = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale); +#else + flatz[numflats] = (sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale); +#endif + flip[numflats] = true; + numflats++; + } + + if (sec->ffloors) + { + ffloor_t *rover; + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER)) + continue; + if (*rover->toppic != skyflatnum) + { +#ifdef ESLOPE + flatz[numflats] = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight); +#else + flatz[numflats] = (*rover->topheight); +#endif + numflats++; + } + if (*rover->bottompic != skyflatnum && ceiling) + { +#ifdef ESLOPE + flatz[numflats] = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight) - FixedMul(mobjinfo[type].height, scale); +#else + flatz[numflats] = (*rover->bottomheight) - FixedMul(mobjinfo[type].height, scale); +#endif + flip[numflats] = true; + numflats++; + } + } + } + + if (numflats <= 0) // no flats + return; + + for (i = 0; i < numflats; i++) + { + mo = P_SpawnMobj(x, y, flatz[i], type); + + // Lastly, if this can see the skybox mobj, then... we just wasted our time :V + if (skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0])) + { + const fixed_t sbz = skyboxmo[0]->z; + fixed_t checkz = sec->floorheight; + + while (checkz < sec->ceilingheight) + { + P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, checkz); + if (P_CheckSight(skyboxmo[0], mo)) + { + P_RemoveMobj(mo); + break; + } + else + checkz += 32*mapobjectscale; + } + + P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, sbz); + + if (P_MobjWasRemoved(mo)) + continue; + } + + P_SetScale(mo, scale); + + if (flip[i]) + { + mo->flags2 |= MF2_OBJECTFLIP; + mo->eflags |= MFE_VERTICALFLIP; + } + + switch(type) + { + case MT_OVERTIMEFOG: + mo->destscale = 8*mo->scale; + mo->momz = P_RandomRange(1,8)*mo->scale; + break; + case MT_OVERTIMEORB: + //mo->destscale = mo->scale/4; + mo->frame += ((leveltime/4) % 8); + /*if (battleovertime.enabled < 10*TICRATE) + mo->flags2 |= MF2_SHADOW;*/ + mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90; + mo->z += P_RandomRange(0,48) * mo->scale; + break; + default: + break; + } + } +} + +#undef MAXPLANESPERSECTOR + +void K_RunBattleOvertime(void) +{ + UINT16 i, j; + + if (battleovertime.enabled < 10*TICRATE) + { + battleovertime.enabled++; + if (battleovertime.enabled == TICRATE) + S_StartSound(NULL, sfx_bhurry); + if (battleovertime.enabled == 10*TICRATE) + S_StartSound(NULL, sfx_kc40); + } + else + { + if (battleovertime.radius > battleovertime.minradius) + battleovertime.radius -= mapobjectscale; + else + battleovertime.radius = battleovertime.minradius; + } + + if (leveltime & 1) + { + UINT8 transparency = tr_trans50; + + if (!splitscreen && players[displayplayers[0]].mo) + { + INT32 dist = P_AproxDistance(battleovertime.x-players[displayplayers[0]].mo->x, battleovertime.y-players[displayplayers[0]].mo->y); + transparency = max(0, NUMTRANSMAPS - ((256 + (dist>>FRACBITS)) / 256)); + } + + if (transparency < NUMTRANSMAPS) + { + mobj_t *beam = P_SpawnMobj(battleovertime.x, battleovertime.y, battleovertime.z + (mobjinfo[MT_RANDOMITEM].height/2), MT_OVERTIMEBEAM); + P_SetScale(beam, beam->scale*2); + if (transparency > 0) + beam->frame |= transparency<>FRACBITS / 2));*/ + + for (i = 0; i < 16; i++) + { + j = 0; + while (j < 32) // max attempts + { + fixed_t x = battleovertime.x + ((P_RandomRange(-64,64) * 128)<extrainfo-1; diff --git a/src/k_battle.h b/src/k_battle.h index 2a3f7c1c2..8f9bbf202 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -4,6 +4,9 @@ #include "doomtype.h" #include "d_player.h" +// Battle overtime system +struct battleovertime battleovertime; + extern boolean battlecapsules; extern UINT8 maptargets, numtargets; @@ -11,6 +14,7 @@ boolean K_IsPlayerWanted(player_t *player); void K_CalculateBattleWanted(void); void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); void K_CheckBumpers(void); +void K_RunBattleOvertime(void); void K_SpawnBattleCapsules(void); #endif diff --git a/src/p_local.h b/src/p_local.h index 33f0026da..97a6586c4 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -230,7 +230,6 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state); void P_RunOverlays(void); fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player); void P_RunShadows(void); -void P_RunBattleOvertime(void); void P_MobjThinker(mobj_t *mobj); boolean P_RailThinker(mobj_t *mobj); void P_PushableThinker(mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index 7dc425704..22432c47a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6482,216 +6482,6 @@ static void P_RemoveShadow(mobj_t *thing) } } -// SAL'S KART BATTLE MODE OVERTIME HANDLER -#define MAXPLANESPERSECTOR (MAXFFLOORS+1)*2 -static void P_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjtype_t type, boolean ceiling) -{ - UINT8 i; - fixed_t flatz[MAXPLANESPERSECTOR]; - boolean flip[MAXPLANESPERSECTOR]; - UINT8 numflats = 0; - mobj_t *mo; - subsector_t *ss = R_IsPointInSubsector(x, y); - sector_t *sec; - - if (!ss) - return; - sec = ss->sector; - - // convoluted stuff JUST to get all of the planes we need to draw orbs on :V - - for (i = 0; i < MAXPLANESPERSECTOR; i++) - flip[i] = false; - - if (sec->floorpic != skyflatnum) - { -#ifdef ESLOPE - flatz[numflats] = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight); -#else - flatz[numflats] = (sec->floorheight); -#endif - numflats++; - } - if (sec->ceilingpic != skyflatnum && ceiling) - { -#ifdef ESLOPE - flatz[numflats] = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale); -#else - flatz[numflats] = (sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale); -#endif - flip[numflats] = true; - numflats++; - } - - if (sec->ffloors) - { - ffloor_t *rover; - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER)) - continue; - if (*rover->toppic != skyflatnum) - { -#ifdef ESLOPE - flatz[numflats] = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight); -#else - flatz[numflats] = (*rover->topheight); -#endif - numflats++; - } - if (*rover->bottompic != skyflatnum && ceiling) - { -#ifdef ESLOPE - flatz[numflats] = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight) - FixedMul(mobjinfo[type].height, scale); -#else - flatz[numflats] = (*rover->bottomheight) - FixedMul(mobjinfo[type].height, scale); -#endif - flip[numflats] = true; - numflats++; - } - } - } - - if (numflats <= 0) // no flats - return; - - for (i = 0; i < numflats; i++) - { - mo = P_SpawnMobj(x, y, flatz[i], type); - - // Lastly, if this can see the skybox mobj, then... we just wasted our time :V - if (skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0])) - { - const fixed_t sbz = skyboxmo[0]->z; - fixed_t checkz = sec->floorheight; - - while (checkz < sec->ceilingheight) - { - P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, checkz); - if (P_CheckSight(skyboxmo[0], mo)) - { - P_RemoveMobj(mo); - break; - } - else - checkz += 32*mapobjectscale; - } - - P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, sbz); - - if (P_MobjWasRemoved(mo)) - continue; - } - - P_SetScale(mo, scale); - - if (flip[i]) - { - mo->flags2 |= MF2_OBJECTFLIP; - mo->eflags |= MFE_VERTICALFLIP; - } - - switch(type) - { - case MT_OVERTIMEFOG: - mo->destscale = 8*mo->scale; - mo->momz = P_RandomRange(1,8)*mo->scale; - break; - case MT_OVERTIMEORB: - //mo->destscale = mo->scale/4; - mo->frame += ((leveltime/4) % 8); - /*if (battleovertime.enabled < 10*TICRATE) - mo->flags2 |= MF2_SHADOW;*/ - mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90; - mo->z += P_RandomRange(0,48) * mo->scale; - break; - default: - break; - } - } -} -#undef MAXPLANESPERSECTOR - -void P_RunBattleOvertime(void) -{ - UINT16 i, j; - - if (battleovertime.enabled < 10*TICRATE) - { - battleovertime.enabled++; - if (battleovertime.enabled == TICRATE) - S_StartSound(NULL, sfx_bhurry); - if (battleovertime.enabled == 10*TICRATE) - S_StartSound(NULL, sfx_kc40); - } - else - { - if (battleovertime.radius > battleovertime.minradius) - battleovertime.radius -= mapobjectscale; - else - battleovertime.radius = battleovertime.minradius; - } - - if (leveltime & 1) - { - UINT8 transparency = tr_trans50; - - if (!splitscreen && players[displayplayers[0]].mo) - { - INT32 dist = P_AproxDistance(battleovertime.x-players[displayplayers[0]].mo->x, battleovertime.y-players[displayplayers[0]].mo->y); - transparency = max(0, NUMTRANSMAPS - ((256 + (dist>>FRACBITS)) / 256)); - } - - if (transparency < NUMTRANSMAPS) - { - mobj_t *beam = P_SpawnMobj(battleovertime.x, battleovertime.y, battleovertime.z + (mobjinfo[MT_RANDOMITEM].height/2), MT_OVERTIMEBEAM); - P_SetScale(beam, beam->scale*2); - if (transparency > 0) - beam->frame |= transparency<>FRACBITS / 2));*/ - - for (i = 0; i < 16; i++) - { - j = 0; - while (j < 32) // max attempts - { - fixed_t x = battleovertime.x + ((P_RandomRange(-64,64) * 128)< Date: Sun, 1 Mar 2020 16:03:31 -0500 Subject: [PATCH 11/17] This was in the wrong place --- src/doomstat.h | 9 --------- src/k_battle.c | 3 +++ src/k_battle.h | 8 ++++++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 017abd566..06e0825aa 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -487,15 +487,6 @@ extern INT16 votelevels[5][2]; extern SINT8 votes[MAXPLAYERS]; extern SINT8 pickedvote; -/** Battle overtime information - */ -extern struct battleovertime -{ - UINT16 enabled; ///< Has this been initalized yet? - fixed_t radius, minradius; ///< Radius of kill field - fixed_t x, y, z; ///< Position to center on -} battleovertime; - extern tic_t hidetime; extern UINT32 timesBeaten; // # of times the game has been beaten. diff --git a/src/k_battle.c b/src/k_battle.c index bd44ff8fa..5f5073a2b 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -17,6 +17,9 @@ #include "m_random.h" #include "r_sky.h" // skyflatnum +// Battle overtime info +struct battleovertime battleovertime; + // Capsules mode enabled for this map? boolean battlecapsules = false; diff --git a/src/k_battle.h b/src/k_battle.h index 8f9bbf202..902347d68 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -4,8 +4,12 @@ #include "doomtype.h" #include "d_player.h" -// Battle overtime system -struct battleovertime battleovertime; +extern struct battleovertime +{ + UINT16 enabled; ///< Has this been initalized yet? + fixed_t radius, minradius; ///< Radius of kill field + fixed_t x, y, z; ///< Position to center on +} battleovertime; extern boolean battlecapsules; extern UINT8 maptargets, numtargets; From 601ab839f04b203f912aa252b2ec0ea8b47120b2 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 22 Mar 2020 14:55:47 -0400 Subject: [PATCH 12/17] Set bumpers to 1 in Break the Capsules --- src/g_game.c | 2 +- src/k_battle.c | 8 ++++++++ src/k_battle.h | 1 + src/k_kart.c | 18 +++++++++++------- src/p_mobj.c | 2 +- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 4074491dc..679f45974 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2633,7 +2633,7 @@ void G_PlayerReborn(INT32 player) itemtype = 0; itemamount = 0; growshrinktimer = 0; - bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0); + bumper = (G_BattleGametype() ? K_StartingBumperCount() : 0); rings = (G_BattleGametype() ? 0 : 5); comebackpoints = 0; wanted = 0; diff --git a/src/k_battle.c b/src/k_battle.c index 5f5073a2b..b188e3921 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -27,6 +27,14 @@ boolean battlecapsules = false; UINT8 maptargets = 0; // Capsules in map UINT8 numtargets = 0; // Capsules busted +INT32 K_StartingBumperCount(void) +{ + if (modeattacking) + return 1; // Break the Capsules + + return cv_kartbumpers.value; +} + boolean K_IsPlayerWanted(player_t *player) { UINT8 i; diff --git a/src/k_battle.h b/src/k_battle.h index 902347d68..bbada65f3 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -14,6 +14,7 @@ extern struct battleovertime extern boolean battlecapsules; extern UINT8 maptargets, numtargets; +INT32 K_StartingBumperCount(void); boolean K_IsPlayerWanted(player_t *player); void K_CalculateBattleWanted(void); void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); diff --git a/src/k_kart.c b/src/k_kart.c index bdd984805..ee2b6f0d4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3036,7 +3036,7 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force) if (!force) { - if (victim->kartstuff[k_bumper] <= 0) // || player->kartstuff[k_bumper] >= cv_kartbumpers.value+2 + if (victim->kartstuff[k_bumper] <= 0) // || player->kartstuff[k_bumper] >= K_StartingBumperCount()+2 return; if (player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0) @@ -9520,9 +9520,10 @@ static void K_drawKartBumpersOrKarma(void) } else { + INT32 maxbumper = K_StartingBumperCount(); V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap); - if (stplyr->kartstuff[k_bumper] > 9 || cv_kartbumpers.value > 9) + if (stplyr->kartstuff[k_bumper] > 9 || maxbumper > 9) { UINT8 ln[2]; ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10); @@ -9531,8 +9532,8 @@ static void K_drawKartBumpersOrKarma(void) V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); - ln[0] = ((abs(cv_kartbumpers.value) / 10) % 10); - ln[1] = (abs(cv_kartbumpers.value) % 10); + ln[0] = ((abs(maxbumper) / 10) % 10); + ln[1] = (abs(maxbumper) % 10); V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); @@ -9540,7 +9541,7 @@ static void K_drawKartBumpersOrKarma(void) else { V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]); - V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_kartbumpers.value) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(maxbumper) % 10]); } } } @@ -9564,11 +9565,14 @@ static void K_drawKartBumpersOrKarma(void) } else { - if (stplyr->kartstuff[k_bumper] > 9 && cv_kartbumpers.value > 9) + INT32 maxbumper = K_StartingBumperCount(); + + if (stplyr->kartstuff[k_bumper] > 9 && maxbumper > 9) V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap); else V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap); - V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); + + V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], maxbumper)); } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index b768f10d8..137e056b1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11323,7 +11323,7 @@ void P_SpawnPlayer(INT32 playernum) || (p->jointime <= 1 && pcount <= 1)) { if (leveltime < 1 || (p->jointime <= 1 && pcount <= 1)) // Start of the map? - p->kartstuff[k_bumper] = cv_kartbumpers.value; // Reset those bumpers! + p->kartstuff[k_bumper] = K_StartingBumperCount(); // Reset those bumpers! if (p->kartstuff[k_bumper]) { From b18df427dd9f3597c5d67806a9d39ac87d0b1880 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 22 Mar 2020 16:07:25 -0400 Subject: [PATCH 13/17] Break the Capsules ends when you lose bumpers --- src/k_battle.c | 53 +++++++++++++++++++++++++++++++++++++------------- src/k_kart.c | 15 ++++++++++---- src/p_mobj.c | 5 ++++- src/p_user.c | 11 ++++++----- src/y_inter.c | 18 +++++++++++++---- 5 files changed, 74 insertions(+), 28 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index b188e3921..f57ba5ec9 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -205,9 +205,7 @@ void K_CheckBumpers(void) UINT8 numingame = 0; SINT8 winnernum = -1; INT32 winnerscoreadd = 0; - - if (!multiplayer) - return; + boolean nobumpers = false; if (!G_BattleGametype()) return; @@ -227,8 +225,11 @@ void K_CheckBumpers(void) winnerscoreadd += players[i].marescore; if (players[i].kartstuff[k_bumper] <= 0) // if you don't have any bumpers, you're probably not a winner + { + nobumpers = true; continue; - else if (winnernum > -1) // TWO winners? that's dumb :V + } + else if (winnernum != -1) // TWO winners? that's dumb :V return; winnernum = i; @@ -238,7 +239,23 @@ void K_CheckBumpers(void) if (numingame <= 1) { if (!battlecapsules) + { + // Reset map to turn on battle capsules D_MapChange(gamemap, gametype, encoremode, true, 0, false, false); + } + else + { + if (nobumpers) + { + for (i = 0; i < MAXPLAYERS; i++) + { + players[i].pflags |= PF_TIMEOVER; + //players[i].lives = 0; + P_DoPlayerExit(&players[i]); + } + } + } + return; } @@ -534,7 +551,6 @@ static void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj) void K_SpawnBattleCapsules(void) { mapthing_t *mt; - UINT8 n = 0; size_t i; if (battlecapsules) @@ -543,18 +559,27 @@ void K_SpawnBattleCapsules(void) if (!G_BattleGametype()) return; - for (i = 0; i < MAXPLAYERS; i++) + if (modeattacking == ATTACKING_CAPSULES) { - if (playeringame[i] && !players[i].spectator) - n++; - if (players[i].exiting) - return; - if (n > 1) - break; + ; } + else + { + UINT8 n = 0; - if (n > 1) - return; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator) + n++; + if (players[i].exiting) + return; + if (n > 1) + break; + } + + if (n > 1) + return; + } mt = mapthings; for (i = 0; i < nummapthings; i++, mt++) diff --git a/src/k_kart.c b/src/k_kart.c index ee2b6f0d4..9da1244f0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -605,6 +605,9 @@ boolean K_IsPlayerLosing(player_t *player) INT32 winningpos = 1; UINT8 i, pcount = 0; + if (battlecapsules && player->kartstuff[k_bumper] <= 0) + return true; // DNF in break the capsules + if (player->kartstuff[k_position] == 1) return false; @@ -10131,10 +10134,14 @@ static void K_drawBattleFullscreen(void) V_DrawFadeScreen(0xFF00, 16); if (stplyr->exiting < 6*TICRATE && !stplyr->spectator) { - if (stplyr->kartstuff[k_position] == 1) - V_DrawFixedPatch(x<kartstuff[k_position] == 1) + p = kp_battlewin; + + V_DrawFixedPatch(x<y; dummy.z = thiscam->z; dummy.height = thiscam->height; - if (player->pflags & PF_TIMEOVER) + + if ((player->pflags & PF_TIMEOVER) && G_RaceGametype()) player->karthud[khud_timeovercam] = (2*TICRATE)+1; + if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. P_ResetCamera(player, thiscam); else P_SlideCameraMove(thiscam); + if (resetcalled) // Okay this means the camera is fully reset. return true; } diff --git a/src/p_user.c b/src/p_user.c index 666855f53..757354631 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1158,10 +1158,10 @@ boolean P_EndingMusic(player_t *player) sprintf(buffer, "k*fail"); // F-Zero death results theme else { - if (bestlocalpos == 1) - sprintf(buffer, "k*win"); - else if (K_IsPlayerLosing(bestlocalplayer)) + if (K_IsPlayerLosing(bestlocalplayer)) sprintf(buffer, "k*lose"); + else if (bestlocalpos == 1) + sprintf(buffer, "k*win"); else sprintf(buffer, "k*ok"); } @@ -6961,9 +6961,10 @@ static void P_DeathThink(player_t *player) if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already goto notrealplayer; - if (player->pflags & PF_TIMEOVER) + if ((player->pflags & PF_TIMEOVER) && G_RaceGametype()) { player->karthud[khud_timeovercam]++; + if (player->mo) { player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); @@ -7178,7 +7179,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall || (leveltime < introtime)); // Kart intro cam #endif - if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround + if ((player->pflags & PF_TIMEOVER) && G_RaceGametype()) // 1 for momentum keep, 2 for turnaround timeover = (player->karthud[khud_timeovercam] > 2*TICRATE ? 2 : 1); else timeover = 0; diff --git a/src/y_inter.c b/src/y_inter.c index 1f489fa2c..7adf601d7 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -796,16 +796,26 @@ static void Y_UpdateRecordReplays(void) if (!mainrecords[gamemap-1]) G_AllocMainRecordData(gamemap-1); - if ((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) - mainrecords[gamemap-1]->time = players[consoleplayer].realtime; + if (players[consoleplayer].pflags & PF_TIMEOVER) + { + players[consoleplayer].realtime = UINT32_MAX; + } - if (modeattacking != ATTACKING_CAPSULES) + if (((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) + && (players[consoleplayer].realtime < UINT32_MAX)) // DNF + { + mainrecords[gamemap-1]->time = players[consoleplayer].realtime; + } + + if (modeattacking == ATTACKING_RECORD) { if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap)) mainrecords[gamemap-1]->lap = bestlap; } else + { mainrecords[gamemap-1]->lap = 0; + } // Save demo! bestdemo[255] = '\0'; @@ -836,7 +846,7 @@ static void Y_UpdateRecordReplays(void) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); } - if (modeattacking != ATTACKING_CAPSULES) + if (modeattacking == ATTACKING_RECORD) { snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)) From 8d91ff1e1c79f8dbcd1d1b832f987d09083d2a76 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 22 Mar 2020 16:13:41 -0400 Subject: [PATCH 14/17] No time limit in capsules --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 3e182bccc..e83315a12 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1786,7 +1786,7 @@ void P_CheckTimeLimit(void) if (!(multiplayer || netgame)) return; - if (G_RaceGametype()) + if (G_RaceGametype() || battlecapsules) return; if (leveltime < (timelimitintics + starttime)) From 198b9770f7ee0301d5f41cc7cdf5f1b0c844d57f Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 22 Mar 2020 16:14:53 -0400 Subject: [PATCH 15/17] Apply to any break the capsules, instead of only time attack --- src/k_battle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index f57ba5ec9..0eef0127c 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -29,8 +29,8 @@ UINT8 numtargets = 0; // Capsules busted INT32 K_StartingBumperCount(void) { - if (modeattacking) - return 1; // Break the Capsules + if (battlecapsules) + return 1; // always 1 hit in Break the Capsules return cv_kartbumpers.value; } From 7f07fa9b2d533b81f3a7e6e5cced07a3f669fcb9 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 22 Mar 2020 16:23:56 -0400 Subject: [PATCH 16/17] Move item box counter stuff into k_battle --- src/doomstat.h | 1 - src/g_game.c | 4 ---- src/k_battle.c | 4 ++++ src/k_battle.h | 1 + 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 0b36fc753..855866483 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -372,7 +372,6 @@ extern UINT16 emeralds; #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) extern INT32 nummaprings; // keep track of spawned rings/coins -extern INT32 nummapboxes, numgotboxes; // keep track of spawned battle mode items /** Time attack information, currently a very small structure. */ diff --git a/src/g_game.c b/src/g_game.c index 679f45974..3018c33e8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -199,10 +199,6 @@ UINT32 bluescore, redscore; // CTF and Team Match team scores // ring count... for PERFECT! INT32 nummaprings = 0; -// box respawning in battle mode -INT32 nummapboxes = 0; -INT32 numgotboxes = 0; - // Elminates unnecessary searching. boolean CheckForBustableBlocks; boolean CheckForBouncySector; diff --git a/src/k_battle.c b/src/k_battle.c index 0eef0127c..6b3fb310a 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -23,6 +23,10 @@ struct battleovertime battleovertime; // Capsules mode enabled for this map? boolean battlecapsules = false; +// box respawning in battle mode +INT32 nummapboxes = 0; +INT32 numgotboxes = 0; + // Capsule counters UINT8 maptargets = 0; // Capsules in map UINT8 numtargets = 0; // Capsules busted diff --git a/src/k_battle.h b/src/k_battle.h index bbada65f3..b69938d39 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -12,6 +12,7 @@ extern struct battleovertime } battleovertime; extern boolean battlecapsules; +extern INT32 nummapboxes, numgotboxes; // keep track of spawned battle mode items extern UINT8 maptargets, numtargets; INT32 K_StartingBumperCount(void); From 53df47b4fe1d64fa086a5e9b79466c3616d0bf03 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 22 Mar 2020 20:29:58 -0400 Subject: [PATCH 17/17] toaster suggestions --- src/k_battle.c | 6 +----- src/y_inter.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index 6b3fb310a..fe727cee3 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -563,11 +563,7 @@ void K_SpawnBattleCapsules(void) if (!G_BattleGametype()) return; - if (modeattacking == ATTACKING_CAPSULES) - { - ; - } - else + if (modeattacking != ATTACKING_CAPSULES) { UINT8 n = 0; diff --git a/src/y_inter.c b/src/y_inter.c index 7adf601d7..7afdad678 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -169,7 +169,7 @@ static void Y_UnloadVoteData(void); // // SRB2Kart - Y_CalculateMatchData and ancillary functions // -static void Y_CompareRace(INT32 i) +static void Y_CompareTime(INT32 i) { UINT32 val = ((players[i].pflags & PF_TIMEOVER || players[i].realtime == UINT32_MAX) ? (UINT32_MAX-1) : players[i].realtime); @@ -181,7 +181,7 @@ static void Y_CompareRace(INT32 i) data.match.num[data.match.numplayers] = i; } -static void Y_CompareBattle(INT32 i) +static void Y_CompareScore(INT32 i) { UINT32 val = ((players[i].pflags & PF_TIMEOVER) ? (UINT32_MAX-1) : players[i].marescore); @@ -1103,9 +1103,18 @@ void Y_StartIntermission(void) case int_match: { // Calculate who won - Y_CalculateMatchData(0, battlecapsules ? Y_CompareRace : Y_CompareBattle); + if (battlecapsules) + { + Y_CalculateMatchData(0, Y_CompareTime); + } + else + { + Y_CalculateMatchData(0, Y_CompareScore); + } + if (cv_inttime.value > 0) S_ChangeMusicInternal("racent", true); // loop it + break; } case int_race: // (time-only race)