diff --git a/.gitignore b/.gitignore index f2dce5f96..849ed7b2a 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ /lzma/x64/ /zlib/x64/ /build_vc2013_64bit +/build_vc2015 diff --git a/src/d_player.h b/src/d_player.h index e27bf1087..2ac2ad0d5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -427,6 +427,7 @@ public: short fixedcolormap; // can be set to REDCOLORMAP, etc. short fixedlightlevel; pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) + TObjPtr pspinterp[NUMPSPRITES]; // view sprite interpolations int morphTics; // player is a chicken/pig if > 0 const PClass *MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed int MorphStyle; // which effects to apply for this player instance when morphed diff --git a/src/g_doomedmap.cpp b/src/g_doomedmap.cpp index 45224329d..08d5aa2e2 100644 --- a/src/g_doomedmap.cpp +++ b/src/g_doomedmap.cpp @@ -135,7 +135,7 @@ CCMD (dumpmapthings) } else { - Printf("%6d none", infos[i]->Key); + Printf("%6d none\n", infos[i]->Key); } } diff --git a/src/g_game.cpp b/src/g_game.cpp index 8101ca23d..f77949687 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1726,6 +1726,15 @@ void G_DoPlayerPop(int playernum) players[playernum].mo = NULL; players[playernum].camera = NULL; } + // Now's the ideal time to remove his psprite interpolations. + for (int ii = 0; ii < NUMPSPRITES; ii++) + { + if (players[playernum].psprites[ii].interpolation != NULL) + { + players[playernum].psprites[ii].StopInterpolation(); + players[playernum].pspinterp[ii] = NULL; + } + } // [RH] Let the scripts know the player left FBehavior::StaticStartTypedScripts(SCRIPT_Disconnect, NULL, true, playernum); } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 54f9fa658..b85ae28e1 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1417,7 +1417,7 @@ FBehavior *FBehavior::StaticLoadModule (int lumpnum, FileReader *fr, int len) else { delete behavior; - Printf(TEXTCOLOR_RED "%s: invalid ACS module", Wads.GetLumpFullName(lumpnum)); + Printf(TEXTCOLOR_RED "%s: invalid ACS module\n", Wads.GetLumpFullName(lumpnum)); return NULL; } } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index a0b1ddbc1..603535b7c 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -184,7 +184,6 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf const char *message; const char *messagename; char gendermessage[1024]; - bool friendly; int gender; // No obituaries for non-players, voodoo dolls or when not wanted @@ -197,8 +196,6 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf if (inflictor && inflictor->player && inflictor->player->mo != inflictor) MeansOfDeath = NAME_None; - friendly = (self->player != attacker->player && self->IsTeammate(attacker)); - mod = MeansOfDeath; message = NULL; messagename = NULL; @@ -266,7 +263,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf if (message == NULL && attacker != NULL && attacker->player != NULL) { - if (friendly) + if (self->player != attacker->player && self->IsTeammate(attacker)) { self = attacker; gender = self->player->userinfo.GetGender(); diff --git a/src/p_local.h b/src/p_local.h index a2fa00c71..a8aaaeb0d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -153,7 +153,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PCl AActor *P_SpawnPlayerMissile (AActor* source, const PClass *type); AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle); AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const PClass *type, angle_t angle, - AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false); + AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false, bool noautoaim = false); void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 267e71bb9..901372eef 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5923,7 +5923,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle) AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const PClass *type, angle_t angle, AActor **pLineTarget, AActor **pMissileActor, - bool nofreeaim) + bool nofreeaim, bool noautoaim) { static const int angdiff[3] = { -1<<26, 1<<26, 0 }; angle_t an = angle; @@ -5936,7 +5936,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, { return NULL; } - if (source->player && source->player->ReadyWeapon && (source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM)) + if (source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM) || noautoaim)) { // Keep exactly the same angle and pitch as the player's own aim an = angle; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 63f3bc648..d2bf8cc87 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1104,11 +1104,32 @@ void P_MovePsprites (player_t *player) P_CheckWeaponZoom (player); } } + + psp = &player->psprites[0]; + for (i = 0; i < NUMPSPRITES; i++, psp++) + { + if (psp->state == NULL) + { + if (psp->interpolation != NULL) + { + player->pspinterp[i] = NULL; + psp->StopInterpolation(); + } + } + else if (psp->interpolation == NULL) + { + player->pspinterp[i] = psp->SetInterpolation(player - players, i); + } + } } FArchive &operator<< (FArchive &arc, pspdef_t &def) { arc << def.state << def.tics << def.sx << def.sy << def.sprite << def.frame; + + if (SaveVersion >= 4525) + arc << def.interpolation; + return arc; } diff --git a/src/p_pspr.h b/src/p_pspr.h index ca9b45ee8..62c2a6fe4 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -26,6 +26,7 @@ // Basic data types. // Needs fixed point, and BAM angles. #include "tables.h" +#include "r_data/r_interpolate.h" #include "thingdef/thingdef.h" #define WEAPONBOTTOM 128*FRACUNIT @@ -71,6 +72,11 @@ struct pspdef_t int sprite; int frame; bool processPending; // true: waiting for periodic processing on this tick + + TObjPtr interpolation; + DInterpolation *SetInterpolation(int player, int position); + void UpdateInterpolation(int player); + void StopInterpolation(); }; class FArchive; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 3203c84bc..210c05ac0 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -297,6 +297,11 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) { dst->mo->player = dst; } + // Fix the psprite interpolation pointers too. + for (int i = 0; i < NUMPSPRITES; i++) + { + dst->psprites[i].UpdateInterpolation(dst - players); + } // These 2 variables may not be overwritten. dst->attackdown = attackdown; dst->usedown = usedown; diff --git a/src/p_user.cpp b/src/p_user.cpp index 0617e5d6a..ced6732a3 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -316,6 +316,7 @@ player_t::player_t() memset (&cmd, 0, sizeof(cmd)); memset (frags, 0, sizeof(frags)); memset (psprites, 0, sizeof(psprites)); + memset (pspinterp, 0, sizeof(pspinterp)); } player_t &player_t::operator=(const player_t &p) @@ -371,6 +372,7 @@ player_t &player_t::operator=(const player_t &p) fixedcolormap = p.fixedcolormap; fixedlightlevel = p.fixedlightlevel; memcpy(psprites, &p.psprites, sizeof(psprites)); + memcpy(pspinterp, &p.pspinterp, sizeof(pspinterp)); morphTics = p.morphTics; MorphedPlayerClass = p.MorphedPlayerClass; MorphStyle = p.MorphStyle; @@ -435,6 +437,10 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep) if (*&ConversationNPC == old) ConversationNPC = replacement, changed++; if (*&ConversationPC == old) ConversationPC = replacement, changed++; if (*&MUSINFOactor == old) MUSINFOactor = replacement, changed++; + + for (int i = 0; i < NUMPSPRITES; i++) + if (*&pspinterp[i] == old) pspinterp[i] = static_cast(rep), changed++; + return changed; } @@ -454,6 +460,11 @@ size_t player_t::PropagateMark() { GC::Mark(PendingWeapon); } + for (int i = 0; i < NUMPSPRITES; i++) + { + GC::Mark(pspinterp[i]); + } + return sizeof(*this); } @@ -1562,12 +1573,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop) if (player != NULL) { player->mo = mo; - if (player->camera == self) - { - player->camera = mo; - } player->damagecount = 32; } + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].camera == self) + { + players[i].camera = mo; + } + } } //---------------------------------------------------------------------------- @@ -3049,7 +3063,11 @@ void player_t::Serialize (FArchive &arc) for (i = 0; i < MAXPLAYERS; i++) arc << frags[i]; for (i = 0; i < NUMPSPRITES; i++) + { arc << psprites[i]; + if (SaveVersion >= 4525) + arc << pspinterp[i]; + } arc << CurrentPlayerClass; diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp index 29f54c39b..527ecbadc 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -151,6 +151,35 @@ public: }; +//========================================================================== +// +// +// +//========================================================================== + +class DPSpriteInterpolation : public DInterpolation +{ + DECLARE_CLASS(DPSpriteInterpolation, DInterpolation) + + pspdef_t *psp; + int player, position; + fixed_t oldx, oldy; + fixed_t bakx, baky; + fixed_t ofsx, ofsy; + fixed_t nfsx, nfsy; + +public: + + DPSpriteInterpolation() {} + DPSpriteInterpolation(pspdef_t *psp, int player, int position); + void UpdatePointer(int player); + void Destroy(); + void UpdateInterpolation(); + void Restore(); + void Interpolate(fixed_t smoothratio); + void Serialize(FArchive &arc); +}; + //========================================================================== // // @@ -162,6 +191,7 @@ IMPLEMENT_CLASS(DSectorPlaneInterpolation) IMPLEMENT_CLASS(DSectorScrollInterpolation) IMPLEMENT_CLASS(DWallScrollInterpolation) IMPLEMENT_CLASS(DPolyobjInterpolation) +IMPLEMENT_CLASS(DPSpriteInterpolation) //========================================================================== // @@ -628,7 +658,6 @@ void DSectorScrollInterpolation::Serialize(FArchive &arc) arc << sector << ceiling << oldx << oldy; } - //========================================================================== // // @@ -824,6 +853,113 @@ void DPolyobjInterpolation::Serialize(FArchive &arc) if (arc.IsLoading()) bakverts.Resize(oldverts.Size()); } +//========================================================================== +// +// +// +//========================================================================== + +//========================================================================== +// +// +// +//========================================================================== + +DPSpriteInterpolation::DPSpriteInterpolation(pspdef_t *_psp, int _player, int _position) +: psp(_psp), player(_player), position(_position), + ofsx(0), ofsy(0), nfsx(0), nfsy(0) +{ + UpdateInterpolation (); + interpolator.AddInterpolation(this); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPSpriteInterpolation::UpdatePointer(int _player) +{ + player = _player; + psp = &players[player].psprites[position]; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPSpriteInterpolation::Destroy() +{ + psp->interpolation = NULL; + Super::Destroy(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPSpriteInterpolation::UpdateInterpolation() +{ + if ( position == ps_weapon ) + P_BobWeapon( &players[player], psp, &ofsx, &ofsy ); + + oldx = psp->sx + ofsx; + oldy = psp->sy + ofsy; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPSpriteInterpolation::Restore() +{ + psp->sx = bakx - nfsx; + psp->sy = baky - nfsy; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPSpriteInterpolation::Interpolate(fixed_t smoothratio) +{ + if ( position == ps_weapon ) + P_BobWeapon( &players[player], psp, &nfsx, &nfsy ); + + bakx = psp->sx + nfsx; + baky = psp->sy + nfsy; + + psp->sx = oldx + FixedMul(bakx - oldx, smoothratio) - nfsx; + psp->sy = oldy + FixedMul(baky - oldy, smoothratio) - nfsy; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPSpriteInterpolation::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + arc << player << position << oldx << oldy << ofsx << ofsy; + UpdatePointer(player); +} + +//========================================================================== +// +// +// +//========================================================================== //========================================================================== // @@ -944,6 +1080,62 @@ void FPolyObj::StopInterpolation() } } +//========================================================================== +// +// +// +//========================================================================== + +DInterpolation *pspdef_t::SetInterpolation(int player, int position) +{ + if (interpolation == NULL) + { + interpolation = new DPSpriteInterpolation(this, player, position); + } + interpolation->AddRef(); + GC::WriteBarrier(interpolation); + return interpolation; +} + +//========================================================================== +// +// +// +//========================================================================== + +void pspdef_t::UpdateInterpolation(int player) +{ + if (interpolation != NULL) + { + barrier_cast(interpolation)->UpdatePointer(player); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void pspdef_t::StopInterpolation() +{ + if (interpolation != NULL) + { + interpolation->DelRef(); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +//========================================================================== +// +// +// +//========================================================================== ADD_STAT (interpolations) { @@ -951,5 +1143,3 @@ ADD_STAT (interpolations) out.Format ("%d interpolations", interpolator.CountInterpolations ()); return out; } - - diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 54b816ebb..dab68867b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1320,6 +1320,7 @@ enum FP_Flags { FPF_AIMATANGLE = 1, FPF_TRANSFERTRANSLATION = 2, + FPF_NOAUTOAIM = 4, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) { @@ -1358,7 +1359,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) // Temporarily adjusts the pitch fixed_t SavedPlayerPitch = self->pitch; self->pitch -= pitch; - AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget); + AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget, NULL, false, (Flags & FPF_NOAUTOAIM) != 0); self->pitch = SavedPlayerPitch; // automatic handling of seeker missiles @@ -5071,7 +5072,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem) // A_SetSpeed // //========================================================================== - DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed) { ACTION_PARAM_START(2); @@ -5089,6 +5089,28 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed) ref->Speed = speed; } +//========================================================================== +// +// A_SetFloatSpeed +// +//========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatSpeed) +{ + ACTION_PARAM_START(2); + ACTION_PARAM_FIXED(speed, 0); + ACTION_PARAM_INT(ptr, 1); + + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + + ref->FloatSpeed = speed; +} + //=========================================================================== // // Common A_Damage handler @@ -5823,3 +5845,4 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMax) ACTION_PARAM_INT(max, 0); self->RipLevelMax = max; } + diff --git a/src/version.h b/src/version.h index f33f0999a..0cb89765d 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4524 +#define SAVEVER 4525 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index f231348d3..5877192ce 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -304,6 +304,7 @@ ACTOR Actor native //: Thinker action native A_SetDamageType(name damagetype); action native A_DropItem(class item, int dropamount = -1, int chance = 256); action native A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT); + action native A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT); action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); action native A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 04ed6f1fc..b5a8b8cd4 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -188,6 +188,7 @@ const int CPF_STEALARMOR = 32; // Flags for A_CustomMissile const int FPF_AIMATANGLE = 1; const int FPF_TRANSFERTRANSLATION = 2; +const int FPF_NOAUTOAIM = 4; // Flags for A_Teleport enum diff --git a/wadsrc/static/actors/doom/keen.txt b/wadsrc/static/actors/doom/keen.txt index 2c07e5b32..93d43764f 100644 --- a/wadsrc/static/actors/doom/keen.txt +++ b/wadsrc/static/actors/doom/keen.txt @@ -28,7 +28,7 @@ ACTOR CommanderKeen KEEN AB 6 KEEN C 6 A_Scream KEEN DEFGH 6 - KEEN I 6 A_NoBlocking + KEEN I 6 KEEN J 6 KEEN K 6 A_KeenDie KEEN L -1 diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index 541dd37ac..13ae00936 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -10,7 +10,7 @@ ACTOR Inventory native action native A_JumpIfNoAmmo(state label); action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus"); action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0); - action native A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, bool aimatangle = false, float pitch = 0); + action native A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0); action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270); action native A_Light(int extralight); action native A_Light0(); diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index f8303c352..77d30aacd 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -397,6 +397,11 @@ A53AE580A4AF2B5D0B0893F86914781E // TNT: Evilution map31 setthingflags 470 2016 } +D0139194F7817BF06F3988DFC47DB38D // Whispers of Satan map29 +{ + nopassover +} + 712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect { setsectortag 545 32000