diff --git a/src/deh_tables.c b/src/deh_tables.c index 513a50c46..46e36120e 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -2437,6 +2437,12 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_DASHRING_VERTICAL_FLASH1", "S_DASHRING_VERTICAL_FLASH2", + // Adventure Air Booster + "S_ADVENTUREAIRBOOSTER", + "S_ADVENTUREAIRBOOSTER_EXHAUST1", + "S_ADVENTUREAIRBOOSTER_EXHAUST2", + "S_ADVENTUREAIRBOOSTER_PART", + // Sneaker Panels "S_SNEAKERPANEL", "S_SNEAKERPANEL_SMALL", @@ -2523,6 +2529,17 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_KANNA", "S_OGAMI", + // Dimension Disaster + "S_DVDTRUMPET", + "S_DVDSHINE1", + "S_DVDSHINE2", + "S_DVDSHINE3", + "S_DVDSHINE4", + "S_DVDSHINE5", + "S_DVDSPARK1", + "S_DVDSPARK2", + "S_DVDSPARK3", + "S_SUNBEAMPALM_STEM", "S_SUNBEAMPALM_LEAF", @@ -3639,6 +3656,11 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_DASHRING", "MT_RAINBOWDASHRING", + // Adventure Air Booster + "MT_ADVENTUREAIRBOOSTER", + "MT_ADVENTUREAIRBOOSTER_HITBOX", + "MT_ADVENTUREAIRBOOSTER_PART", + // Sneaker Panels "MT_SNEAKERPANEL", "MT_SNEAKERPANELSPAWNER", @@ -3699,6 +3721,10 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_HANAGUMIHALL_STEAM", "MT_HANAGUMIHALL_NPC", + // Dimension Disaster + "MT_DVDTRUMPET", + "MT_DVDPARTICLE", + "MT_SUNBEAMPALM_STEM", "MT_SUNBEAMPALM_LEAF", diff --git a/src/info.c b/src/info.c index aa9d66bbc..8707a57f3 100644 --- a/src/info.c +++ b/src/info.c @@ -501,6 +501,9 @@ char sprnames[NUMSPRITES + 1][5] = // Dash Rings "RAIR", + // Adventure Air Booster + "ADVR", + // Sneaker Panels "BSTP", "BSTS", @@ -549,6 +552,10 @@ char sprnames[NUMSPRITES + 1][5] = "HGCF", "HGCG", + // Dimension Disaster + "DVDD", + "SPRC", + "TUST", "TULE", @@ -2929,6 +2936,12 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, TICRATE/3 - 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH2}, // S_DASHRING_VERTICAL_FLASH1 {SPR_RAIR, FF_ADD|3, 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH1}, // S_DASHRING_VERTICAL_FLASH2 + // Adventure Air Booster + {SPR_ADVR, 17|FF_FULLBRIGHT|FF_ADD, 1, {A_RollAngle}, 8, 0, S_ADVENTUREAIRBOOSTER}, // S_ADVENTUREAIRBOOSTER + {SPR_ADVR, 5|FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|FF_PAPERSPRITE, 10, {NULL}, 4, 2, S_NULL}, // S_ADVENTUREAIRBOOSTER_EXHAUST1 + {SPR_ADVR, 11|FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|FF_PAPERSPRITE, 10, {NULL}, 4, 2, S_NULL}, // S_ADVENTUREAIRBOOSTER_EXHAUST2 + {SPR_ADVR, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_ADVENTUREAIRBOOSTER_PART + // Sneaker Panels {SPR_BSTP, FF_ANIMATE|FF_GLOBALANIM|FF_FLOORSPRITE|FF_FULLBRIGHT, -1, {NULL}, 5, 2, S_SNEAKERPANEL}, // S_SNEAKERPANEL {SPR_BSTS, FF_ANIMATE|FF_GLOBALANIM|FF_FLOORSPRITE|FF_FULLBRIGHT, -1, {NULL}, 5, 2, S_SNEAKERPANEL_SMALL}, // S_SNEAKERPANEL_SMALL @@ -3019,6 +3032,17 @@ state_t states[NUMSTATES] = {SPR_HGCF, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KANNA {SPR_HGCG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_OGAMI + // Dimension Disaster + {SPR_DVDD, 1, -1, {NULL}, 0, 0, S_NULL}, // S_DVDTRUMPET + {SPR_SPRC, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_DVDSHINE2}, // S_DVDSHINE1 + {SPR_SPRC, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_DVDSHINE3}, // S_DVDSHINE2 + {SPR_SPRC, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_DVDSHINE4}, // S_DVDSHINE3 + {SPR_SPRC, 4|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_DVDSHINE5}, // S_DVDSHINE4 + {SPR_SPRC, 5|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_DVDSHINE1}, // S_DVDSHINE5 + {SPR_SPRC, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_DVDSPARK2}, // S_DVDSPARK1 + {SPR_SPRC, FF_TRANS20|FF_FULLBRIGHT|7, 3, {NULL}, 0, 0, S_DVDSPARK3}, // S_DVDSPARK2 + {SPR_SPRC, FF_TRANS40|FF_FULLBRIGHT|8, 3, {NULL}, 0, 0, S_NULL}, // S_DVDSPARK3 + {SPR_TUST, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SUNBEAMPALM_STEM {SPR_TULE, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SUNBEAMPALM_LEAF @@ -16834,6 +16858,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_ADVENTUREAIRBOOSTER + 3500, // doomednum + S_ADVENTUREAIRBOOSTER, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_spdpad, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 50*FRACUNIT, // radius + 2*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_supert, // activesound + MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_ADVENTUREAIRBOOSTER_HITBOX + -1, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 127*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPHEIGHT|MF_SPECIAL|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_ADVENTUREAIRBOOSTER_PART + -1, // doomednum + S_ADVENTUREAIRBOOSTER_PART, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 64*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SNEAKERPANEL 510, // doomednum S_SNEAKERPANEL, // spawnstate @@ -17779,6 +17884,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_DVDTRUMPET + 3181, // doomednum + S_DVDTRUMPET, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_DVDPARTICLE + -1, // doomednum + S_DVDSPARK1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 2*FRACUNIT, // speed + 8*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // dispoffset + 100, // mass + 62*FRACUNIT, // damage + sfx_None, // activesound + MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + { // MT_SUNBEAMPALM_STEM 2697, // doomednum S_SUNBEAMPALM_STEM, // spawnstate diff --git a/src/info.h b/src/info.h index 442581ac8..96f06786c 100644 --- a/src/info.h +++ b/src/info.h @@ -1040,6 +1040,9 @@ typedef enum sprite // Dash Rings SPR_RAIR, + // Adventure Air Booster + SPR_ADVR, + // Sneaker Panels SPR_BSTP, SPR_BSTS, @@ -1088,6 +1091,10 @@ typedef enum sprite SPR_HGCF, SPR_HGCG, + // Dimension Disaster + SPR_DVDD, + SPR_SPRC, + SPR_TUST, SPR_TULE, @@ -3430,6 +3437,12 @@ typedef enum state S_DASHRING_VERTICAL_FLASH1, S_DASHRING_VERTICAL_FLASH2, + // Adventure Air Booster + S_ADVENTUREAIRBOOSTER, + S_ADVENTUREAIRBOOSTER_EXHAUST1, + S_ADVENTUREAIRBOOSTER_EXHAUST2, + S_ADVENTUREAIRBOOSTER_PART, + // Sneaker Panels S_SNEAKERPANEL, S_SNEAKERPANEL_SMALL, @@ -3516,6 +3529,17 @@ typedef enum state S_KANNA, S_OGAMI, + // Dimension Disaster + S_DVDTRUMPET, + S_DVDSHINE1, + S_DVDSHINE2, + S_DVDSHINE3, + S_DVDSHINE4, + S_DVDSHINE5, + S_DVDSPARK1, + S_DVDSPARK2, + S_DVDSPARK3, + S_SUNBEAMPALM_STEM, S_SUNBEAMPALM_LEAF, @@ -4659,6 +4683,11 @@ typedef enum mobj_type MT_DASHRING, MT_RAINBOWDASHRING, + // Adventure Air Booster + MT_ADVENTUREAIRBOOSTER, + MT_ADVENTUREAIRBOOSTER_HITBOX, + MT_ADVENTUREAIRBOOSTER_PART, + // Sneaker Panels MT_SNEAKERPANEL, MT_SNEAKERPANELSPAWNER, @@ -4719,6 +4748,10 @@ typedef enum mobj_type MT_HANAGUMIHALL_STEAM, MT_HANAGUMIHALL_NPC, + // Dimension Disaster + MT_DVDTRUMPET, + MT_DVDPARTICLE, + MT_SUNBEAMPALM_STEM, MT_SUNBEAMPALM_LEAF, diff --git a/src/k_objects.h b/src/k_objects.h index ee1a24290..746bccb0b 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -208,6 +208,12 @@ void Obj_RainbowDashRingThink(mobj_t *mobj); void Obj_DashRingTouch(mobj_t *mobj, player_t *player); void Obj_DashRingPlayerThink(player_t *player); boolean Obj_DashRingPlayerHasNoGravity(player_t *player); +boolean Obj_DashRingIsUsableByPlayer(mobj_t *mobj, player_t *player); + +/* Adventure Dash Ring */ +void Obj_AdventureAirBoosterSetup(mobj_t *mobj, mapthing_t *mthing); +void Obj_AdventureAirBoosterHitboxTouch(mobj_t *hitbox, player_t *player); +void Obj_AdventureAirBoosterFuse(mobj_t *mobj); /* Sneaker Panels */ void Obj_SneakerPanelSpriteScale(mobj_t *mobj); diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 0dde3da9f..5ba9951d2 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -55,6 +55,7 @@ target_sources(SRB2SDL2 PRIVATE sealed-star.c talk-point.cpp powerup-spinner.cpp + adventure-air-booster.c ) add_subdirectory(versus) diff --git a/src/objects/adventure-air-booster.c b/src/objects/adventure-air-booster.c new file mode 100644 index 000000000..884a8431a --- /dev/null +++ b/src/objects/adventure-air-booster.c @@ -0,0 +1,218 @@ +#include "../p_local.h" +#include "../k_kart.h" +#include "../k_objects.h" +#include "../s_sound.h" +#include "../m_random.h" +#include "../r_main.h" + +// Hardcoder note: I renamed anything using "Adventure Dash Ring"/"ADR" to "Adventure Air Booster"/"AAB" for consistency with the HVR config +// Hardcoder note: AAB_DIST used to be 64, but it was halved everywhere it was used, so I just halved the base value instead of during calculations +// Hardcoder note: AAB_STRENGTH_ADD used to be 75 to be multiplied with AAB_STRENGTH/100 at runtime, I just baked that calculation into it instead + +#define AAB_DIST (32*FRACUNIT) // distance between the back and front of the booster +#define AAB_FRONTBACKSPACE (8*FRACUNIT) // distance between the 2 sides of the front & back part of the booster +#define AAB_RADIUS (225*FRACUNIT) // radius (width) of the booster (in pixels). Used to determine where to spawn the 2 arrows on the sides +#define AAB_STRENGTH (55*FRACUNIT) // default speed for the booster +static const fixed_t AAB_STRENGTH_ADD = (75*AAB_STRENGTH/100); // each time the booster is used, add AAB_STRENGTH_ADD speed to the next player +#define AAB_DASHRINGPUSHTICS (3*TICRATE/2) +#define AAB_SPRINGSTARSTICS (TICRATE/2) + +static const skincolornum_t AAB_COLORS[] = { + SKINCOLOR_YELLOW, + SKINCOLOR_GREEN, + SKINCOLOR_RED, + SKINCOLOR_BLUE, +}; +static const UINT8 AAB_NUM_COLORS = sizeof(AAB_COLORS) / sizeof(skincolornum_t); + +static void AdventureAirBoosterUpdateColor(mobj_t *mobj) +{ + mobj_t *part = mobj->hnext; + + mobj->color = AAB_COLORS[mobj->extravalue1]; + + while (!P_MobjWasRemoved(part)) + { + part->color = mobj->color; + part = part->hnext; + } +} + +void Obj_AdventureAirBoosterSetup(mobj_t *mobj, mapthing_t *mthing) +{ + mobj_t *prev = mobj; + mobj_t *part; + angle_t positionAngle = mobj->angle; + fixed_t oldHeight = mobj->height; + fixed_t baseScale = mobj->scale; + fixed_t xPos, yPos; + SINT8 i; + + // arg1: double scale (pre-dates UDMF) + if (mthing->thing_args[0]) + { + baseScale *= 2; + } + + // set scale and flip + P_SetScale(mobj, mobj->movefactor = mobj->old_scale = mobj->destscale = baseScale); + mobj->scalespeed = mobj->scale >> 2; + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + mobj->old_z = mobj->z -= (mobj->height - oldHeight); + } + +#define SpawnPart()\ +{\ + part = P_SpawnMobjFromMobj(mobj, xPos, yPos, 0, MT_ADVENTUREAIRBOOSTER_PART);\ + P_SetTarget(&part->target, mobj);\ + P_SetTarget(&prev->hnext, part);\ + P_SetTarget(&part->hprev, prev);\ + prev = part;\ +} + + // Spawn the back rings + for (i = 0; i < 2; i++) + { + xPos = -P_ReturnThrustX(NULL, positionAngle, (AAB_FRONTBACKSPACE * i) + AAB_DIST); + yPos = -P_ReturnThrustY(NULL, positionAngle, (AAB_FRONTBACKSPACE * i) + AAB_DIST); + // with this order of operations, the first part to spawn is the front, then the back. + SpawnPart(); + part->frame |= (1 - i); + part->old_angle = part->angle = mobj->angle + ANGLE_90; // put it sideways + } + + // Now the front ring + for (i = 0; i < 2; i++) + { + xPos = P_ReturnThrustX(NULL, positionAngle, -(AAB_FRONTBACKSPACE * i) + AAB_DIST); + yPos = P_ReturnThrustY(NULL, positionAngle, -(AAB_FRONTBACKSPACE * i) + AAB_DIST); + // with this order of operations, the first part to spawn is the front, then the back. + SpawnPart(); + part->frame |= (3 - i); + part->old_angle = part->angle = mobj->angle + ANGLE_90; // put it sideways + } + + // and now the 2 arrows + positionAngle = mobj->angle + ANGLE_90; // put the angle to the side! + for (i = -1; i < 2; i += 2) + { + xPos = P_ReturnThrustX(NULL, positionAngle, AAB_RADIUS * i) / 2; + yPos = P_ReturnThrustY(NULL, positionAngle, AAB_RADIUS * i) / 2; + // with this order of operations, the first arrow we spawn is the right one, then the left one. Angle them accordingly. + SpawnPart(); + part->frame |= 4; + part->old_angle = part->angle = mobj->angle - (ANGLE_45 * i); + } +#undef SpawnPart + + part = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_ADVENTUREAIRBOOSTER_HITBOX); + part->old_angle = part->angle = mobj->angle; + part->old_z = part->z -= P_MobjFlip(part) * (part->height >> 1); + P_SetTarget(&part->target, mobj); + P_SetTarget(&mobj->tracer, part); // Hardcoder note: Since the hitbox doesn't need to be colored, I decided not to tack it on the end of the hnext chain; tracer is more easily accessible to scripters + + mobj->extravalue1 = 1; // default to green + AdventureAirBoosterUpdateColor(mobj); +} + +void Obj_AdventureAirBoosterHitboxTouch(mobj_t *hitbox, player_t *player) +{ + mobj_t *mo = player->mo; + mobj_t *booster = hitbox->target; + mobj_t *part; + angle_t finalAngle = hitbox->angle; + angle_t playerAngle; + fixed_t finalSpeed, playerSpeed, xPos, yPos; + SINT8 i; + + if (P_MobjWasRemoved(booster) || !Obj_DashRingIsUsableByPlayer(booster, player)) + { + return; + } + + // reflect angles like springs + finalSpeed = FixedMul(AAB_STRENGTH + (booster->extravalue1 * AAB_STRENGTH_ADD), mapobjectscale); + playerSpeed = FixedHypot(mo->momx, mo->momy); + if (playerSpeed > 0) + { + playerAngle = R_PointToAngle2(0, 0, mo->momx, mo->momy); + } + else + { + playerAngle = mo->angle; + } + + finalAngle = K_ReflectAngle(playerAngle, finalAngle, playerSpeed, finalSpeed); + + mo->momz = 0; + P_InstaThrust(mo, finalAngle, finalSpeed); + + P_SetTarget(&mo->tracer, booster); + player->carry = CR_DASHRING; + player->dashRingPullTics = 0; + player->dashRingPushTics = AAB_DASHRINGPUSHTICS; + player->springstars = AAB_SPRINGSTARSTICS; + player->springcolor = booster->color; + player->turbine = 0; + player->flashing = 0; + player->fastfall = 0; + K_TumbleInterrupt(player); + + S_StartSound(mo, booster->info->seesound); + + // before we change the colour, spawn a buncha sparkles + for (i = 0; i < 12; i++) + { + part = P_SpawnMobjFromMobj( + hitbox, + FixedMul(AAB_RADIUS << 1, P_RandomFixed(PR_DECORATION)) - AAB_RADIUS, + FixedMul(AAB_RADIUS << 1, P_RandomFixed(PR_DECORATION)) - AAB_RADIUS, + FixedMul(AAB_RADIUS << 1, P_RandomFixed(PR_DECORATION)) - AAB_RADIUS, + MT_DVDPARTICLE + ); + part->color = booster->color; + P_SetMobjState(part, S_DVDSHINE1); + P_SetScale(part, part->old_scale = hitbox->scale * P_RandomRange(PR_DECORATION, 2, 4)); + part->tics = P_RandomRange(PR_DECORATION, 1, 8); + part->fuse = TICRATE >> 1; + part->destscale = 1; + part->scalespeed = part->scale / part->fuse; + P_InstaThrust(part, finalAngle, FixedMul(finalSpeed, P_RandomRange(PR_DECORATION, FRACUNIT*80/100, FRACUNIT*120/100))); + } + + // visuals + booster->fuse = TICRATE >> 1; + booster->destscale = 1; + + // spawn the 3 layers + for (i = -1; i < 2; i++) + { + xPos = P_ReturnThrustX(NULL, booster->angle + ANGLE_90, (AAB_RADIUS >> 1) * i) + P_ReturnThrustX(NULL, booster->angle, AAB_RADIUS); + yPos = P_ReturnThrustY(NULL, booster->angle + ANGLE_90, (AAB_RADIUS >> 1) * i) + P_ReturnThrustY(NULL, booster->angle, AAB_RADIUS); + + part = P_SpawnMobjFromMobj(hitbox, xPos, yPos, hitbox->info->height >> 1, MT_PARTICLE); + part->old_angle = part->angle = booster->angle; + part->color = booster->color; + P_SetMobjState(part, i == 0 ? S_ADVENTUREAIRBOOSTER_EXHAUST2 : S_ADVENTUREAIRBOOSTER_EXHAUST1); + } + + if (++booster->extravalue1 >= AAB_NUM_COLORS) + { + booster->extravalue1 = 0; + // we just went through a blue booster, play sparkle sfx + S_StartSound(mo, booster->info->activesound); + } + AdventureAirBoosterUpdateColor(booster); +} + +void Obj_AdventureAirBoosterFuse(mobj_t *mobj) +{ + mobj_t *ghost = P_SpawnGhostMobj(mobj); + mobj->destscale = mobj->movefactor; + ghost->destscale = mobj->movefactor * 8; + ghost->scalespeed = mobj->movefactor; + ghost->height = mobj->height; +} diff --git a/src/objects/dash-rings.c b/src/objects/dash-rings.c index 5d1c68501..77abc44d8 100644 --- a/src/objects/dash-rings.c +++ b/src/objects/dash-rings.c @@ -120,18 +120,27 @@ static boolean DashRingsAreTooClose(mobj_t *ring1, mobj_t *ring2) return false; } -void Obj_DashRingTouch(mobj_t *ring, player_t *player) +boolean Obj_DashRingIsUsableByPlayer(mobj_t *ring, player_t *player) { if (player->carry != CR_NONE) { if (player->carry != CR_DASHRING) // being carried by something else - return; + return false; if (player->dashRingPullTics > 0) // being pulled into a dash ring already - return; + return false; if (player->dashRingPushTics > 0 && !P_MobjWasRemoved(player->mo->tracer) && DashRingsAreTooClose(player->mo->tracer, ring)) // dash ring is too close to recently used dash ring - return; + return false; + } + return true; +} + +void Obj_DashRingTouch(mobj_t *ring, player_t *player) +{ + if (!Obj_DashRingIsUsableByPlayer(ring, player)) + { + return; } P_SetTarget(&player->mo->tracer, ring); diff --git a/src/p_inter.c b/src/p_inter.c index aa77ea26c..3fb9dd22a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -938,6 +938,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) Obj_DashRingTouch(special, player); return; + case MT_ADVENTUREAIRBOOSTER_HITBOX: + Obj_AdventureAirBoosterHitboxTouch(special, player); + return; + case MT_DLZ_ROCKET: Obj_DLZRocketSpecial(special, player); return; diff --git a/src/p_mobj.c b/src/p_mobj.c index 488193e3a..2d24166f4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10053,6 +10053,11 @@ static boolean P_FuseThink(mobj_t *mobj) P_RemoveMobj(mobj); return false; } + case MT_ADVENTUREAIRBOOSTER: + { + Obj_AdventureAirBoosterFuse(mobj); + break; + } case MT_SNEAKERPANELSPAWNER: { Obj_SneakerPanelSpawnerFuse(mobj); @@ -13810,6 +13815,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj) Obj_DashRingSetup(mobj, mthing); break; } + case MT_ADVENTUREAIRBOOSTER: + { + Obj_AdventureAirBoosterSetup(mobj, mthing); + break; + } case MT_SNEAKERPANEL: { Obj_SneakerPanelSetup(mobj, mthing);