diff --git a/src/deh_tables.c b/src/deh_tables.c index 57ef8d885..66271a5f4 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5380,6 +5380,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_DROPTARGET", // Drop Target "MT_DROPTARGET_SHIELD", + "MT_DROPTARGET_MORPH", "MT_BALLHOG", // Ballhog "MT_BALLHOGBOOM", diff --git a/src/info.c b/src/info.c index 355816512..b536ec66d 100644 --- a/src/info.c +++ b/src/info.c @@ -23722,6 +23722,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_DROPTARGET_MORPH + -1, // doomednum + S_DROPTARGET, // spawnstate + 1, // 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 + 45*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_BALLHOG -1, // doomednum S_BALLHOG1, // spawnstate diff --git a/src/info.h b/src/info.h index 3a1921b3c..f7496fc14 100644 --- a/src/info.h +++ b/src/info.h @@ -6452,6 +6452,7 @@ typedef enum mobj_type MT_DROPTARGET, // Drop Target MT_DROPTARGET_SHIELD, + MT_DROPTARGET_MORPH, MT_BALLHOG, // Ballhog MT_BALLHOGBOOM, diff --git a/src/k_collide.c b/src/k_collide.c index 1256263a8..b930865c1 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -457,6 +457,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2) { mobj_t *draggeddroptarget = (t1->type == MT_DROPTARGET_SHIELD) ? t1->target : NULL; + UINT8 strength; if (((t1->target == t2) || (t1->target == t2->target)) && ((t1->threshold > 0 && t2->type == MT_PLAYER) || (t2->type != MT_PLAYER && t2->threshold > 0))) return true; @@ -467,9 +468,21 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2) if (t2->player && (t2->player->hyudorotimer || t2->player->justbumped)) return true; + if (t1->health > 3) // forward thrown + { + strength = 0; + } + else if (t1->reactiontime == 0 || draggeddroptarget) + { + strength = 80; + } + else + { + strength = 140; + } + // Intensify bumps if already spinning... - P_Thrust(t1, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y), - ((t1->reactiontime && !draggeddroptarget) ? 140 : 80) * t1->scale); + P_Thrust(t1, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y), strength * t1->scale); if (draggeddroptarget) { @@ -548,9 +561,22 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2) t1->flags |= MF_SHOOTABLE; // The following sets t1->target to t2, so draggeddroptarget keeps it persisting... P_DamageMobj(t1, t2, (t2->target ? t2->target : t2), 1, DMG_NORMAL); - t1->color = (t1->health > 1) - ? SKINCOLOR_GOLD - : SKINCOLOR_CRIMSON; + + switch (t1->health) + { + case 3: + t1->color = SKINCOLOR_LIME; + break; + + case 2: + t1->color = SKINCOLOR_GOLD; + break; + + case 1: + t1->color = SKINCOLOR_CRIMSON; + break; + } + t1->flags &= ~MF_SHOOTABLE; t1->spritexscale = 3*FRACUNIT; diff --git a/src/k_kart.c b/src/k_kart.c index 6d49e468c..cf63a39be 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5496,6 +5496,8 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, if (mapthing == MT_DROPTARGET && mo) { + mo->health++; + mo->color = SKINCOLOR_WHITE; mo->reactiontime = TICRATE/2; P_SetMobjState(mo, mo->info->painstate); } diff --git a/src/k_objects.h b/src/k_objects.h index 922764c94..1578d8177 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -101,6 +101,10 @@ void Obj_InitLoopCenter(mobj_t *center); void Obj_LinkLoopAnchor(mobj_t *anchor, mobj_t *center, UINT8 type); void Obj_LoopEndpointCollide(mobj_t *special, mobj_t *toucher); +/* Drop Target */ +void Obj_BeginDropTargetMorph(mobj_t *target, skincolornum_t color); +boolean Obj_DropTargetMorphThink(mobj_t *morph); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index ca8680205..ef74b299f 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -13,4 +13,5 @@ target_sources(SRB2SDL2 PRIVATE monitor.c item-spot.c loops.c + drop-target.c ) diff --git a/src/objects/drop-target.c b/src/objects/drop-target.c new file mode 100644 index 000000000..1f81289f4 --- /dev/null +++ b/src/objects/drop-target.c @@ -0,0 +1,64 @@ +#include "../doomdef.h" +#include "../info.h" +#include "../k_objects.h" +#include "../p_local.h" + +#define MORPH_TIME_FACTOR (3) + +#define morph_target(o) ((o)->target) +#define morph_time(o) ((o)->extravalue1) + +void +Obj_BeginDropTargetMorph +( mobj_t * target, + skincolornum_t color) +{ + mobj_t *x = P_SpawnMobjFromMobj(target, 0, 0, 0, + MT_DROPTARGET_MORPH); + + x->color = color; + x->colorized = true; + x->renderflags |= RF_FULLBRIGHT; + + P_SetTarget(&morph_target(x), target); + + morph_time(x) = tr_trans90 * MORPH_TIME_FACTOR; + + x->health = target->health; +} + +boolean +Obj_DropTargetMorphThink (mobj_t *x) +{ + mobj_t *target = morph_target(x); + + if (P_MobjWasRemoved(target)) + { + P_RemoveMobj(x); + return false; + } + + if (target->health != x->health) + { + P_RemoveMobj(x); + return false; + } + + morph_time(x)--; + + if (morph_time(x) <= 0) + { + target->health--; + target->color = x->color; + + P_RemoveMobj(x); + return false; + } + + x->renderflags = (x->renderflags & ~(RF_TRANSMASK)) + | ((morph_time(x) / MORPH_TIME_FACTOR) << RF_TRANSSHIFT); + + P_MoveOrigin(x, target->x, target->y, target->z); + + return true; +} diff --git a/src/p_mobj.c b/src/p_mobj.c index b910f4a3d..0e5e9fb02 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6619,6 +6619,12 @@ static void P_MobjSceneryThink(mobj_t *mobj) case MT_MONITOR_SHARD: Obj_MonitorShardThink(mobj); break; + case MT_DROPTARGET_MORPH: + if (Obj_DropTargetMorphThink(mobj) == false) + { + return; + } + break; case MT_VWREF: case MT_VWREB: { @@ -7417,6 +7423,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (!--mobj->reactiontime) { P_SetMobjState(mobj, mobj->info->spawnstate); + + // forward thrown + if (mobj->health == 4) + { + Obj_BeginDropTargetMorph(mobj, SKINCOLOR_LIME); + } } } else