diff --git a/src/dehacked.c b/src/dehacked.c index 2661fc2fd..61ecc5f6b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5910,16 +5910,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FOUR2", "S_FIVE2", - "S_LOCKON", + "S_LOCKON1", + "S_LOCKON2", // Tag Sign "S_TTAG", // Got Flag Sign - "S_GOTREDFLAG1", - "S_GOTREDFLAG2", - "S_GOTBLUEFLAG1", - "S_GOTBLUEFLAG2", + "S_GOTFLAG", + "S_GOTREDFLAG", + "S_GOTBLUEFLAG", "S_CORK", @@ -6714,8 +6714,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_GOTEMERALD", // Chaos Emerald (intangible) "MT_LOCKON", // Target "MT_TAG", // Tag Sign - "MT_GOTREDFLAG", // Got Flag sign - "MT_GOTBLUEFLAG", // Got Flag sign + "MT_GOTFLAG", // Got Flag sign // Ambient Sounds "MT_AWATERA", // Ambient Water Sound 1 diff --git a/src/info.c b/src/info.c index 491e7cdb0..2d1694a05 100644 --- a/src/info.c +++ b/src/info.c @@ -2530,15 +2530,15 @@ state_t states[NUMSTATES] = {SPR_DRWN, 10, 40, {NULL}, 0, 0, S_NULL}, // S_FOUR2 {SPR_DRWN, 11, 40, {NULL}, 0, 0, S_NULL}, // S_FIVE2 - {SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON + {SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1 + {SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2 {SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG // CTF Sign - {SPR_GFLG, 0, 1, {NULL}, 0, 0, S_GOTREDFLAG2}, // S_GOTREDFLAG1 - {SPR_GFLG, 1, 1, {NULL}, 0, 0, S_NULL}, // S_GOTREDFLAG2 - {SPR_GFLG, 0, 1, {NULL}, 0, 0, S_GOTBLUEFLAG2}, // S_GOTBLUEFLAG1 - {SPR_GFLG, 2, 1, {NULL}, 0, 0, S_NULL}, // S_GOTBLUEFLAG2 + {SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG + {SPR_GFLG, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTREDFLAG + {SPR_GFLG, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTBLUEFLAG {SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK @@ -12068,7 +12068,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_LOCKON -1, // doomednum - S_LOCKON, // spawnstate + S_LOCKON1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -12089,7 +12089,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, @@ -12120,36 +12120,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_GOTREDFLAG + { // MT_GOTFLAG -1, // doomednum - S_GOTREDFLAG1, // 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_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 8, // speed - 64*FRACUNIT, // radius - 32*FRACUNIT, // height - 111, // display offset - 16, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_GOTBLUEFLAG2 - -1, // doomednum - S_GOTBLUEFLAG1, // spawnstate + S_GOTFLAG, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -12457,7 +12430,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_CORK, // spawnstate 1000, // spawnhealth S_NULL, // seestate - sfx_itemup, // seesound + sfx_corkp, // seesound 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -12467,7 +12440,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_SMOKE1, // deathstate S_NULL, // xdeathstate - sfx_itemup, // deathsound + sfx_corkh, // deathsound 60*FRACUNIT, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height diff --git a/src/info.h b/src/info.h index 4501357b7..4b21e98ec 100644 --- a/src/info.h +++ b/src/info.h @@ -2720,16 +2720,16 @@ typedef enum state S_FOUR2, S_FIVE2, - S_LOCKON, + S_LOCKON1, + S_LOCKON2, // Tag Sign S_TTAG, // Got Flag Sign - S_GOTREDFLAG1, - S_GOTREDFLAG2, - S_GOTBLUEFLAG1, - S_GOTBLUEFLAG2, + S_GOTFLAG, + S_GOTREDFLAG, + S_GOTBLUEFLAG, S_CORK, @@ -3543,8 +3543,7 @@ typedef enum mobj_type MT_GOTEMERALD, // Chaos Emerald (intangible) MT_LOCKON, // Target MT_TAG, // Tag Sign - MT_GOTREDFLAG, // Got Flag sign - MT_GOTBLUEFLAG, // Got Flag sign + MT_GOTFLAG, // Got Flag sign // Ambient Sounds MT_AWATERA, // Ambient Water Sound 1 diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 53fa9bc55..ef8e025b8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -449,6 +449,28 @@ static int lib_pIsValidSprite2(lua_State *L) return 1; } +// P_SpawnLockOn doesn't exist either, but we want to expose making a local mobj without encouraging hacks. + +static int lib_pSpawnLockOn(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *lockon = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + statenum_t state = luaL_checkinteger(L, 3); + NOHUD + INLEVEL + if (!lockon) + return LUA_ErrInvalid(L, "mobj_t"); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + visual->target = lockon; + P_SetMobjStateNF(visual, state); + } + return 0; +} + static int lib_pSpawnMissile(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2328,6 +2350,7 @@ static luaL_Reg lib[] = { {"P_SpawnMobj",lib_pSpawnMobj}, {"P_RemoveMobj",lib_pRemoveMobj}, {"P_IsValidSprite2", lib_pIsValidSprite2}, + {"P_SpawnLockOn", lib_pSpawnLockOn}, {"P_SpawnMissile",lib_pSpawnMissile}, {"P_SpawnXYZMissile",lib_pSpawnXYZMissile}, {"P_SpawnPointMissile",lib_pSpawnPointMissile}, diff --git a/src/p_floor.c b/src/p_floor.c index 071ebcb86..d16c8b9ff 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1778,8 +1778,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_GOTEMERALD: case MT_LOCKON: case MT_TAG: - case MT_GOTREDFLAG: - case MT_GOTBLUEFLAG: + case MT_GOTFLAG: case MT_HOOP: case MT_HOOPCOLLIDE: case MT_NIGHTSCORE: diff --git a/src/p_inter.c b/src/p_inter.c index 36e800bf0..f5255a2f7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1348,6 +1348,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE); P_SetPlayerMobjState(toucher, S_PLAY_FALL); } + player->homing = 0; // Play a bounce sound? S_StartSound(toucher, special->info->painsound); @@ -1408,6 +1409,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE); P_SetPlayerMobjState(toucher, S_PLAY_FALL); } + player->homing = 0; // Play a bounce sound? S_StartSound(toucher, special->info->painsound); diff --git a/src/p_mobj.c b/src/p_mobj.c index a235af5b3..2fde531d1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6868,7 +6868,7 @@ void P_MobjThinker(mobj_t *mobj) return; if (/*(mobj->target) -- the following is implicit by P_AddShield && (mobj->target->player) - && */ (mobj->target->player->homing)) + && */ (mobj->target->player->homing) && (mobj->target->player->pflags & PF_SHIELDABILITY)) { P_SetMobjState(mobj, mobj->info->painstate); mobj->tics++; @@ -7012,13 +7012,15 @@ void P_MobjThinker(mobj_t *mobj) mobj->x = mobj->target->x; mobj->y = mobj->target->y; + mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); + mobj->destscale = mobj->target->destscale; P_SetScale(mobj, mobj->target->scale); - if (!(mobj->target->eflags & MFE_VERTICALFLIP)) - mobj->z = mobj->target->z + mobj->target->height + FixedMul(16*FRACUNIT, mobj->target->scale); + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); else - mobj->z = mobj->target->z - FixedMul(16*FRACUNIT, mobj->target->scale) - mobj->height; + mobj->z = mobj->target->z - FixedMul((16 + abs((leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; break; case MT_DROWNNUMBERS: if (!mobj->target) diff --git a/src/p_user.c b/src/p_user.c index 80906e1a4..f60edf79d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2349,12 +2349,17 @@ static void P_DoPlayerHeadSigns(player_t *player) // has it (but not on your own screen if you have the flag). if (splitscreen || player != &players[consoleplayer]) { - if (!(player->mo->eflags & MFE_VERTICALFLIP)) - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, ((player->gotflag & GF_REDFLAG) ? MT_GOTREDFLAG : MT_GOTBLUEFLAG)); + mobj_t *sign = P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, + player->mo->z+player->mo->momz, MT_GOTFLAG); + if (player->mo->eflags & MFE_VERTICALFLIP) + { + sign->z += player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTFLAG].height-FixedMul(16*FRACUNIT, player->mo->scale); + sign->eflags |= MFE_VERTICALFLIP; + } else - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTREDFLAG].height-FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, ((player->gotflag & GF_REDFLAG) ? MT_GOTREDFLAG : MT_GOTBLUEFLAG))->eflags |= MFE_VERTICALFLIP; // yes, MT_GOTREDFLAG's height is used for both of them. Doesn't really matter - they should both always be the same height. + sign->z += P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale); + if (leveltime & 1) + P_SetMobjStateNF(sign, (player->gotflag & GF_REDFLAG) ? S_GOTREDFLAG : S_GOTBLUEFLAG); } } } @@ -3843,8 +3848,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) { if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. { - mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); - visual->eflags |= (lockon->eflags & MFE_VERTICALFLIP); + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker visual->target = lockon; } } @@ -4102,9 +4106,20 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) // static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { + mobj_t *lockon = NULL; + if (player->pflags & PF_JUMPSTASIS) return; + if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || (player->charability2 == CA2_MULTIABILITY)) && (lockon = P_LookForEnemies(player, true, false)) && !((leveltime & 1) && (lockon->flags & (MF_ENEMY|MF_BOSS)) && player->powers[pw_shield] == SH_ATTRACT)) + { + if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + visual->target = lockon; + } + } + if (cmd->buttons & BT_USE && !(player->pflags & PF_JUMPDOWN) && !player->exiting && !P_PlayerInPain(player)) { if (player->mo->tracer && player->powers[pw_carry] == CR_MACESPIN) @@ -4255,9 +4270,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_SpawnThokMobj(player); - if (player->charability == CA_HOMINGTHOK && !player->homing) + if (player->charability == CA_HOMINGTHOK) { - mobj_t *lockon = P_LookForEnemies(player, true, false); if (lockon) { P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); @@ -7161,6 +7175,19 @@ static void P_MovePlayer(player_t *player) if (player->pflags & PF_JUMPED && !player->exiting && player->mo->health) { + mobj_t *lockon = NULL; + if (!player->powers[pw_super] && player->powers[pw_shield] == SH_ATTRACT && !(player->pflags & PF_THOKKED)) + { + if ((lockon = P_LookForEnemies(player, false, false)) && !(!(leveltime & 1) && player->charability == CA_HOMINGTHOK)) + { + if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + visual->target = lockon; + P_SetMobjStateNF(visual, visual->info->spawnstate+1); + } + } + } if (cmd->buttons & BT_USE) // Spin button effects { if (player->powers[pw_super]) // Super can't use shield actives, only passives @@ -7214,20 +7241,16 @@ static void P_MovePlayer(player_t *player) case SH_ATTRACT: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->homing = 2; + if (lockon) { - mobj_t *lockon = P_LookForEnemies(player, false, false); - if (lockon) - { - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); - player->pflags &= ~PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_s3k40); - player->homing = 3*TICRATE; - } - else - S_StartSound(player->mo, sfx_s3ka6); + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); + player->pflags &= ~PF_NOJUMPDAMAGE; + S_StartSound(player->mo, sfx_s3k40); + player->homing = 3*TICRATE; } + else + S_StartSound(player->mo, sfx_s3ka6); break; // Elemental/Bubblewrap shield activation case SH_ELEMENTAL: @@ -7886,7 +7909,8 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) mo = (mobj_t *)think; if (!(mo->flags & targetmask - || mo->type == MT_FAKEMOBILE)) // hehehehe + || mo->type == MT_FAKEMOBILE // hehehehe + || mo->type == MT_EGGSHIELD)) continue; // not a valid target if (mo->health <= 0) // dead @@ -7974,7 +7998,7 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target } // change slope - zdist = (P_MobjFlip(source) ? (enemy->z + enemy->height) - (source->z + source->height) : (enemy->z - source->z)); + zdist = ((P_MobjFlip(source) == -1) ? (enemy->z + enemy->height) - (source->z + source->height) : (enemy->z - source->z)); dist = P_AproxDistance(P_AproxDistance(enemy->x - source->x, enemy->y - source->y), zdist); if (dist < 1) diff --git a/src/sounds.c b/src/sounds.c index b2758923d..395015296 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -189,6 +189,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"mswarp", false, 60, 16, -1, NULL, 0, -1, -1, LUMPERROR}, {"mspogo", false, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"corkp", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 42eeee31f..0442ebb05 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -252,6 +252,8 @@ typedef enum sfx_mswarp, sfx_mspogo, sfx_boingf, + sfx_corkp, + sfx_corkh, // Menu, interface sfx_chchng,