diff --git a/doomsday/plugins/common/src/p_saveg.c b/doomsday/plugins/common/src/p_saveg.c index 8c0a9ff329..bf12f282e5 100644 --- a/doomsday/plugins/common/src/p_saveg.c +++ b/doomsday/plugins/common/src/p_saveg.c @@ -82,6 +82,7 @@ #include "p_door.h" #include "p_floor.h" #include "p_plat.h" +#include "hu_msg.h" // MACROS ------------------------------------------------------------------ @@ -1404,6 +1405,8 @@ static void SV_ReadPlayer(player_t *p) #if __JHEXEN__ # define MOBJ_SAVEVERSION 6 +#elif __JHEREITC__ +# define MOBJ_SAVEVERSION 8 #else # define MOBJ_SAVEVERSION 7 #endif @@ -1438,6 +1441,9 @@ static void SV_WriteMobj(mobj_t *original) // 6: Added damage // 7: Added generator in jHeretic // 7: Added flags3 + // + // JHERETIC + // 8: Added special3 SV_WriteByte(MOBJ_SAVEVERSION); #if !__JHEXEN__ @@ -1566,6 +1572,7 @@ static void SV_WriteMobj(mobj_t *original) # ifdef __JHERETIC__ SV_WriteLong(mo->special1); SV_WriteLong(mo->special2); + SV_WriteLong(mo->special3); # endif SV_WriteByte(mo->translucency); @@ -1838,6 +1845,31 @@ static int SV_ReadMobj(thinker_t *th) #endif mo->health = SV_ReadLong(); +#if __JHERETIC__ + if(ver < 8) + { + // Fix a bunch of kludges in the original Heretic. + switch(mo->type) + { + case MT_MACEFX1: + case MT_MACEFX2: + case MT_MACEFX3: + case MT_HORNRODFX2: + case MT_HEADFX3: + case MT_WHIRLWIND: + case MT_TELEGLITTER: + case MT_TELEGLITTER2: + mo->special3 = mo->health; + if(mo->type == MT_HORNRODFX2 && mo->special3 > 16) + mo->special3 = 16; + mo->health = mobjInfo[mo->type].spawnHealth; + break; + + default: + break; + } + } +#endif // Movement direction, movement generation (zig-zagging). mo->moveDir = SV_ReadLong(); // 0-7 @@ -1923,6 +1955,8 @@ static int SV_ReadMobj(thinker_t *th) #elif __JHERETIC__ mo->special1 = SV_ReadLong(); mo->special2 = SV_ReadLong(); + if(ver >= 8) + mo->special3 = SV_ReadLong(); #endif #if __JHEXEN__ @@ -1959,6 +1993,7 @@ static int SV_ReadMobj(thinker_t *th) // Restore! (unmangle) RestoreMobj(mo, ver); + return false; } diff --git a/doomsday/plugins/jheretic/defs/objects.ded b/doomsday/plugins/jheretic/defs/objects.ded index 6f15a53565..e705eb7adf 100644 --- a/doomsday/plugins/jheretic/defs/objects.ded +++ b/doomsday/plugins/jheretic/defs/objects.ded @@ -1956,7 +1956,7 @@ Thing { Death sound = "ramphit"; Active sound = "None"; Reaction time = 8; - Spawn health = 140; + Spawn health = 1000; Speed = 22; Radius = 12; Height = 8; diff --git a/doomsday/plugins/jheretic/include/p_mobj.h b/doomsday/plugins/jheretic/include/p_mobj.h index 51007582eb..5a2b30d7cc 100644 --- a/doomsday/plugins/jheretic/include/p_mobj.h +++ b/doomsday/plugins/jheretic/include/p_mobj.h @@ -195,6 +195,7 @@ typedef struct mobj_s { int flags3; int special1; // Special info int special2; // Special info + int special3; // Special info int health; int moveDir; // 0-7 int moveCount; // when 0, select a new dir diff --git a/doomsday/plugins/jheretic/src/p_enemy.c b/doomsday/plugins/jheretic/src/p_enemy.c index 9c69b517d7..1dc528a0b8 100644 --- a/doomsday/plugins/jheretic/src/p_enemy.c +++ b/doomsday/plugins/jheretic/src/p_enemy.c @@ -1652,7 +1652,7 @@ void C_DECL A_HeadAttack(mobj_t *actor) fire->mom[MY] = baseFire->mom[MY]; fire->mom[MZ] = baseFire->mom[MZ]; fire->damage = 0; - fire->health = (i + 1) * 2; + fire->special3 = (i + 1) * 2; P_CheckMissileSpawn(fire); } @@ -1668,7 +1668,7 @@ void C_DECL A_HeadAttack(mobj_t *actor) mo->tracer = target; mo->special1 = 60; mo->special2 = 50; // Timer for active sound. - mo->health = 20 * TICSPERSEC; // Duration. + mo->special3 = 20 * TICSPERSEC; // Duration. S_StartSound(SFX_HEDAT3, actor); } @@ -1677,8 +1677,8 @@ void C_DECL A_HeadAttack(mobj_t *actor) void C_DECL A_WhirlwindSeek(mobj_t *actor) { - actor->health -= 3; - if(actor->health < 0) + actor->special3 -= 3; + if(actor->special3 < 0) { actor->mom[MX] = actor->mom[MY] = actor->mom[MZ] = 0; P_MobjChangeState(actor, mobjInfo[actor->type].deathState); @@ -1723,10 +1723,10 @@ void C_DECL A_HeadIceImpact(mobj_t *ice) void C_DECL A_HeadFireGrow(mobj_t *fire) { - fire->health--; + fire->special3--; fire->pos[VZ] += 9; - if(fire->health == 0) + if(fire->special3 == 0) { fire->damage = fire->info->damage; P_MobjChangeState(fire, S_HEADFX3_4); @@ -1862,12 +1862,12 @@ void C_DECL A_Scream(mobj_t *actor) } } -void P_DropItem(mobj_t *source, mobjtype_t type, int special, int chance) +mobj_t* P_DropItem(mobjtype_t type, mobj_t* source, int special, int chance) { - mobj_t *mo; + mobj_t* mo; if(P_Random() > chance) - return; + return NULL; mo = P_SpawnMobj3f(type, source->pos[VX], source->pos[VY], source->pos[VZ] + source->height / 2, source->angle); @@ -1877,6 +1877,8 @@ void P_DropItem(mobj_t *source, mobjtype_t type, int special, int chance) mo->flags |= MF_DROPPED; mo->health = special; + + return mo; } void C_DECL A_NoBlocking(mobj_t *actor) @@ -1890,39 +1892,39 @@ void C_DECL A_NoBlocking(mobj_t *actor) case MT_MUMMYLEADER: case MT_MUMMYGHOST: case MT_MUMMYLEADERGHOST: - P_DropItem(actor, MT_AMGWNDWIMPY, 3, 84); + P_DropItem(MT_AMGWNDWIMPY, actor, 3, 84); break; case MT_KNIGHT: case MT_KNIGHTGHOST: - P_DropItem(actor, MT_AMCBOWWIMPY, 5, 84); + P_DropItem(MT_AMCBOWWIMPY, actor, 5, 84); break; case MT_WIZARD: - P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84); - P_DropItem(actor, MT_ARTITOMEOFPOWER, 0, 4); + P_DropItem(MT_AMBLSRWIMPY, actor, 10, 84); + P_DropItem(MT_ARTITOMEOFPOWER, actor, 0, 4); break; case MT_HEAD: - P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84); - P_DropItem(actor, MT_ARTIEGG, 0, 51); + P_DropItem(MT_AMBLSRWIMPY, actor, 10, 84); + P_DropItem(MT_ARTIEGG, actor, 0, 51); break; case MT_BEAST: - P_DropItem(actor, MT_AMCBOWWIMPY, 10, 84); + P_DropItem(MT_AMCBOWWIMPY, actor, 10, 84); break; case MT_CLINK: - P_DropItem(actor, MT_AMSKRDWIMPY, 20, 84); + P_DropItem(MT_AMSKRDWIMPY, actor, 20, 84); break; case MT_SNAKE: - P_DropItem(actor, MT_AMPHRDWIMPY, 5, 84); + P_DropItem(MT_AMPHRDWIMPY, actor, 5, 84); break; case MT_MINOTAUR: - P_DropItem(actor, MT_ARTISUPERHEAL, 0, 51); - P_DropItem(actor, MT_AMPHRDWIMPY, 10, 84); + P_DropItem(MT_ARTISUPERHEAL, actor, 0, 51); + P_DropItem(MT_AMPHRDWIMPY, actor, 10, 84); break; default: @@ -1930,9 +1932,9 @@ void C_DECL A_NoBlocking(mobj_t *actor) } } -void C_DECL A_Explode(mobj_t *actor) +void C_DECL A_Explode(mobj_t* actor) { - int damage; + int damage; damage = 128; switch(actor->type) @@ -2156,6 +2158,7 @@ void C_DECL A_SpawnTeleGlitter(mobj_t *actor) P_Random() << 24); mo->mom[MZ] = 1.0f / 4; + mo->special3 = 1000; } void C_DECL A_SpawnTeleGlitter2(mobj_t *actor) @@ -2169,11 +2172,12 @@ void C_DECL A_SpawnTeleGlitter2(mobj_t *actor) P_Random() << 24); mo->mom[MZ] = 1.0f / 4; + mo->special3 = 1000; } void C_DECL A_AccTeleGlitter(mobj_t *actor) { - if(++actor->health > 35) + if(++actor->special3 > 35) actor->mom[MZ] += actor->mom[MZ] / 2; } diff --git a/doomsday/plugins/jheretic/src/p_mobj.c b/doomsday/plugins/jheretic/src/p_mobj.c index a4ab6a0473..994d1016a0 100644 --- a/doomsday/plugins/jheretic/src/p_mobj.c +++ b/doomsday/plugins/jheretic/src/p_mobj.c @@ -1053,7 +1053,7 @@ void P_MobjThinker(mobj_t *mobj) /** * Spawns a mobj of "type" at the specified position. */ -mobj_t *P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, +mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle) { mobj_t *mo; @@ -1092,6 +1092,10 @@ mobj_t *P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, // Must link before setting state (ID assigned for the mo). P_MobjSetState(mo, info->spawnState); + if(mo->type == MT_MACEFX1 || mo->type == MT_MACEFX2 || + mo->type == MT_MACEFX3) + mo->special3 = 1000; + // Set subsector and/or block links. P_MobjSetPosition(mo); diff --git a/doomsday/plugins/jheretic/src/p_oldsvg.c b/doomsday/plugins/jheretic/src/p_oldsvg.c index 6328715b02..e7f9ed04c8 100644 --- a/doomsday/plugins/jheretic/src/p_oldsvg.c +++ b/doomsday/plugins/jheretic/src/p_oldsvg.c @@ -302,6 +302,26 @@ static void SV_v13_ReadMobj(void) mo->special1 = SV_v13_ReadLong(); mo->special2 = SV_v13_ReadLong(); mo->health = SV_v13_ReadLong(); + + // Fix a bunch of kludges in the original Heretic. + switch(mo->type) + { + case MT_MACEFX1: + case MT_MACEFX2: + case MT_MACEFX3: + case MT_HORNRODFX2: + case MT_HEADFX3: + case MT_WHIRLWIND: + case MT_TELEGLITTER: + case MT_TELEGLITTER2: + mo->special3 = mo->health; + mo->health = mobjInfo[mo->type].spawnHealth; + break; + + default: + break; + } + mo->moveDir = SV_v13_ReadLong(); mo->moveCount = SV_v13_ReadLong(); SV_v13_ReadLong(); // target diff --git a/doomsday/plugins/jheretic/src/p_pspr.c b/doomsday/plugins/jheretic/src/p_pspr.c index d3a02f0211..46fc941e3a 100644 --- a/doomsday/plugins/jheretic/src/p_pspr.c +++ b/doomsday/plugins/jheretic/src/p_pspr.c @@ -1336,10 +1336,10 @@ void C_DECL A_MaceBallImpact(mobj_t *ball) return; } - if(ball->health != MAGIC_JUNK && ball->pos[VZ] <= ball->floorZ && + if(ball->special3 != MAGIC_JUNK && ball->pos[VZ] <= ball->floorZ && ball->mom[MZ] != 0) { // Bounce. - ball->health = MAGIC_JUNK; + ball->special3 = MAGIC_JUNK; ball->mom[MZ] = FIX2FLT(FLT2FIX(ball->mom[MZ] * 192) >> 8); ball->flags2 &= ~MF2_FLOORBOUNCE; P_MobjChangeState(ball, ball->info->spawnState); @@ -1578,11 +1578,16 @@ void C_DECL A_FireSkullRodPL1(player_t *player, pspdef_t *psp) */ void C_DECL A_FireSkullRodPL2(player_t *player, pspdef_t *psp) { + mobj_t* mo; + P_ShotAmmo(player); if(IS_CLIENT) return; - P_SpawnMissile(MT_HORNRODFX2, player->plr->mo, NULL); + mo = P_SpawnMissile(MT_HORNRODFX2, player->plr->mo, NULL); + if(mo) + mo->special3 = 140; + // Use MissileMobj instead of the return value from // P_SpawnMissile because we need to give info to the mobj // even if it exploded immediately. @@ -1625,19 +1630,19 @@ void C_DECL A_AddPlayerRain(mobj_t *actor) if(player->rain1 && player->rain2) { // Terminate an active rain. - if(player->rain1->health < player->rain2->health) + if(player->rain1->special3 < player->rain2->special3) { - if(player->rain1->health > 16) + if(player->rain1->special3 > 16) { - player->rain1->health = 16; + player->rain1->special3 = 16; } player->rain1 = NULL; } else { - if(player->rain2->health > 16) + if(player->rain2->special3 > 16) { - player->rain2->health = 16; + player->rain2->special3 = 16; } player->rain2 = NULL; } @@ -1661,7 +1666,7 @@ void C_DECL A_SkullRodStorm(mobj_t *actor) int playerNum; player_t *player; - if(actor->health-- == 0) + if(actor->special3-- == 0) { P_MobjChangeState(actor, S_NULL); playerNum = (IS_NETGAME ? actor->special2 : 0);