From 74fc45d7b7f20f40e78ada6f3016366714edcab4 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 16 Jul 2016 15:39:57 +0300 Subject: [PATCH 01/13] Fixed instant boss brain spawning There was a possibility of division by zero which led to nonsensical spawn time http://forum.zdoom.org/viewtopic.php?t=52760 --- src/g_doom/a_bossbrain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 51ee77ff8..5d10e0138 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -147,7 +147,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) { spit->special2 = 0; } - else if (fabs(spit->Vel.X) > fabs(spit->Vel.Y)) + else if (fabs(spit->Vel.Y) > fabs(spit->Vel.X)) { spit->special2 = int((targ->Y() - self->Y()) / spit->Vel.Y); } From 58fb993402258d6f604b50d676444d9b37191dbe Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 16 Jul 2016 16:48:36 +0300 Subject: [PATCH 02/13] Added ability to select ammo image and text display order in alternative HUD Controlled via hud_ammo_order CVAR: * 0 (default): image and text * any other value: text and image --- src/g_shared/shared_hud.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 4bfe85271..46cf61d54 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -81,6 +81,7 @@ CVAR (Int , hud_showtime, 0, CVAR_ARCHIVE); // Show time on HUD CVAR (Int , hud_timecolor, CR_GOLD,CVAR_ARCHIVE); // Color of in-game time on HUD CVAR (Int , hud_showlag, 0, CVAR_ARCHIVE); // Show input latency (maketic - gametic difference) +CVAR (Int, hud_ammo_order, 0, CVAR_ARCHIVE); // ammo image and text order CVAR (Int, hud_ammo_red, 25, CVAR_ARCHIVE) // ammo percent less than which status is red CVAR (Int, hud_ammo_yellow, 50, CVAR_ARCHIVE) // ammo percent less is yellow more green CVAR (Int, hud_health_red, 25, CVAR_ARCHIVE) // health amount less than which status is red @@ -586,9 +587,21 @@ static int DrawAmmo(player_t *CPlayer, int x, int y) // ok, we got all ammo types. Now draw the list back to front (bottom to top) int def_width = ConFont->StringWidth("000/000"); - x-=def_width; int yadd = ConFont->GetHeight(); + int xtext = x - def_width; + int ximage = x; + + if (hud_ammo_order > 0) + { + xtext -= 24; + ximage -= 20; + } + else + { + ximage -= def_width + 20; + } + for(i=orderedammos.Size()-1;i>=0;i--) { @@ -613,8 +626,8 @@ static int DrawAmmo(player_t *CPlayer, int x, int y) ammo < ( (maxammo * hud_ammo_red) / 100) ? CR_RED : ammo < ( (maxammo * hud_ammo_yellow) / 100) ? CR_GOLD : CR_GREEN ); - DrawHudText(ConFont, fontcolor, buf, x-tex_width, y+yadd, trans); - DrawImageToBox(TexMan[icon], x-20, y, 16, 8, trans); + DrawHudText(ConFont, fontcolor, buf, xtext-tex_width, y+yadd, trans); + DrawImageToBox(TexMan[icon], ximage, y, 16, 8, trans); y-=10; } return y; From da9f4cc1dd63201ddf29ec86610fd02be981f4c8 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 16 Jul 2016 16:50:37 +0300 Subject: [PATCH 03/13] Added 'ammo display order' item to options menu --- wadsrc/static/language.enu | 3 +++ wadsrc/static/menudef.txt | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index d27374ed2..cef67aca9 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1835,6 +1835,7 @@ ALTHUDMNU_SHOWAMMO = "Show ammo for"; ALTHUDMNU_SHOWTIME = "Show time"; ALTHUDMNU_TIMECOLOR = "Time color"; ALTHUDMNU_SHOWLAG = "Show network latency"; +ALTHUDMNU_AMMOORDER = "Ammo display order"; ALTHUDMNU_AMMORED = "Red ammo display below %"; ALTHUDMNU_AMMOYELLOW = "Yellow ammo display below %"; ALTHUDMNU_HEALTHRED = "Red health display below"; @@ -2210,6 +2211,8 @@ OPTVAL_SYSTEMSECONDS = "System, seconds"; OPTVAL_SYSTEM = "System"; OPTVAL_NETGAMESONLY = "Netgames only"; OPTVAL_ALWAYS = "Always"; +OPTVAL_AMMOIMAGETEXT = "Image and Text"; +OPTVAL_AMMOTEXTIMAGE = "Text and Image"; OPTVAL_SCRIPTSONLY = "Scripts Only"; OPTVAL_NEVER = "Never"; OPTVAL_ALL = "All"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index bb854f378..2a59c4103 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -821,6 +821,12 @@ OptionValue "AltHUDLag" 2, "$OPTVAL_ALWAYS" } +OptionValue "AltHUDAmmoOrder" +{ + 0, "$OPTVAL_AMMOIMAGETEXT" + 1, "$OPTVAL_AMMOTEXTIMAGE" +} + OptionMenu "AltHUDOptions" { Title "$ALTHUDMNU_TITLE" @@ -837,6 +843,7 @@ OptionMenu "AltHUDOptions" Option "$ALTHUDMNU_SHOWTIME", "hud_showtime", "AltHUDTime" Option "$ALTHUDMNU_TIMECOLOR", "hud_timecolor", "TextColors" Option "$ALTHUDMNU_SHOWLAG", "hud_showlag", "AltHUDLag" + Option "$ALTHUDMNU_AMMOORDER", "hud_ammo_order", "AltHUDAmmoOrder" Slider "$ALTHUDMNU_AMMORED", "hud_ammo_red", 0, 100, 1, 0 Slider "$ALTHUDMNU_AMMOYELLOW", "hud_ammo_yellow", 0, 100, 1, 0 Slider "$ALTHUDMNU_HEALTHRED", "hud_health_red", 0, 100, 1, 0 From ee72760f3a01eecd23d87779e007d960bb4eb57b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 16 Jul 2016 15:32:19 +0300 Subject: [PATCH 04/13] libc++ is now used by the linker too (when applicable) --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 67b7dbb17..5fe947ef8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -518,6 +518,7 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) # C++11 support using SDKs 10.7 and 10.8. if ( APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" ) set( CMAKE_CXX_FLAGS "-stdlib=libc++ ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-stdlib=libc++ ${CMAKE_EXE_LINKER_FLAGS}" ) endif () # Remove extra warnings when using the official DirectX headers. From 3c7e1e0528d8716816980c9624d791168782a2c6 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Mon, 30 May 2016 15:16:05 -0500 Subject: [PATCH 05/13] - Added the tracer actor spawning for A_FireBullets and A_CustomBulletAttack. The projectiles spawning conditions rely upon the puff successfully spawning. # Conflicts: # wadsrc/static/actors/actor.txt --- src/thingdef/thingdef_codeptr.cpp | 60 ++++++++++++++++++++--- wadsrc/static/actors/actor.txt | 2 +- wadsrc/static/actors/shared/inventory.txt | 2 +- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 1b1c7b2cf..61506a1c8 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1635,6 +1635,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) PARAM_FLOAT_OPT (range) { range = 0; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (ptr) { ptr = AAPTR_TARGET; } + PARAM_CLASS_OPT (missile, AActor) { missile = nullptr; } + PARAM_FLOAT_OPT (Spawnheight) { Spawnheight = 32; } + PARAM_FLOAT_OPT (Spawnofs_xy) { Spawnofs_xy = 0; } AActor *ref = COPY_AAPTR(self, ptr); @@ -1662,6 +1665,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) { DAngle angle = bangle; DAngle slope = bslope; + DAngle tempangle = (pr_cwbullet.Random2() / 255.); + DAngle tempslope = (pr_cwbullet.Random2() / 255.); if (flags & CBAF_EXPLICITANGLE) { @@ -1670,8 +1675,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) } else { - angle += spread_xy * (pr_cwbullet.Random2() / 255.); - slope += spread_z * (pr_cwbullet.Random2() / 255.); + angle += spread_xy * tempangle; + slope += spread_z * tempslope; } int damage = damageperbullet; @@ -1679,7 +1684,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) if (!(flags & CBAF_NORANDOM)) damage *= ((pr_cabullet()%3)+1); - P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); + AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); + + if (puff && missile) + { + double x = Spawnofs_xy * angle.Cos(); + double y = Spawnofs_xy * angle.Sin(); + AActor *proj = P_SpawnMissileXYZ(self->Vec3Offset(x, y, self->GetBobOffset() + Spawnheight), self, puff, missile, false); + if (proj) + { + double missilespeed; + A_Face(proj, puff, 0., 0.); + missilespeed = fabs(proj->Angles.Pitch.Cos() * proj->Speed); + proj->Vel.Z = proj->Angles.Pitch.Sin() * proj->Speed; + proj->VelFromAngle(missilespeed); + } + } } } return 0; @@ -1810,6 +1830,28 @@ enum FB_Flags FBF_NORANDOMPUFFZ = 32, }; +static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, DAngle angle, double Spawnheight, double Spawnofs_xy) +{ + if (self && missile && puff) + { + double x = Spawnofs_xy * angle.Cos(); + double y = Spawnofs_xy * angle.Sin(); + DAngle ang = self->Angles.Yaw - 90; + DVector2 ofs = ang.ToVector(Spawnofs_xy); + //AActor *proj = P_SpawnMissileXYZ(self->Vec3Offset(x, y, z + self->GetBobOffset()), self, puff, missile, false); + + AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true); + if (proj) + { + double missilespeed; + A_Face(proj, puff, 0., 0.); + missilespeed = fabs(proj->Angles.Pitch.Cos() * proj->Speed); + proj->Vel.Z = proj->Angles.Pitch.Sin() * proj->Speed; + proj->VelFromAngle(missilespeed); + } + } +} + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) { PARAM_ACTION_PROLOGUE; @@ -1817,9 +1859,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) PARAM_ANGLE (spread_z); PARAM_INT (numbullets); PARAM_INT (damageperbullet); - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; } + PARAM_CLASS_OPT (pufftype, AActor) { pufftype = nullptr; } PARAM_INT_OPT (flags) { flags = FBF_USEAMMO; } PARAM_FLOAT_OPT (range) { range = 0; } + PARAM_CLASS_OPT (missile, AActor) { missile = nullptr; } + PARAM_FLOAT_OPT (Spawnheight) { Spawnheight = 0; } + PARAM_FLOAT_OPT (Spawnofs_xy) { Spawnofs_xy = 0; } if (!self->player) return 0; @@ -1858,7 +1903,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if (!(flags & FBF_NORANDOM)) damage *= ((pr_cwbullet()%3)+1); - P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags); + AActor *puff = P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags); + FireBulletMissile(self, missile, puff, bangle, Spawnheight, Spawnofs_xy); + } else { @@ -1885,7 +1932,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if (!(flags & FBF_NORANDOM)) damage *= ((pr_cwbullet()%3)+1); - P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); + AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); + FireBulletMissile(self, missile, puff, angle, Spawnheight, Spawnofs_xy); } } return 0; diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index cb6ff4d93..8c35df21b 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -189,7 +189,7 @@ ACTOR Actor native //: Thinker native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); native state A_Jump(int chance = 256, state label, ...); native void A_CustomMissile(class missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET); - native void A_CustomBulletAttack(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET); + native void A_CustomBulletAttack(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ 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, int limit = 0); native state A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT); native state A_JumpIfCloser(float distance, state label, bool noz = false); diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index a49dfd14c..43a33f93a 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -9,7 +9,7 @@ ACTOR Inventory native action native state 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", sound MeleeSound = "", sound MissSound = ""); - action native A_FireBullets(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0); + action native A_FireBullets(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); action native A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, float spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0); action native A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ 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, int limit = 0); action native A_Light(int extralight); From 791852a6bdfb14119cbefc7968ddd3cddd7317e9 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Mon, 30 May 2016 15:29:23 -0500 Subject: [PATCH 06/13] Cleaned up. --- src/thingdef/thingdef_codeptr.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 61506a1c8..784bb3518 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1665,8 +1665,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) { DAngle angle = bangle; DAngle slope = bslope; - DAngle tempangle = (pr_cwbullet.Random2() / 255.); - DAngle tempslope = (pr_cwbullet.Random2() / 255.); if (flags & CBAF_EXPLICITANGLE) { @@ -1675,8 +1673,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) } else { - angle += spread_xy * tempangle; - slope += spread_z * tempslope; + angle += spread_xy * (pr_cwbullet.Random2() / 255.); + slope += spread_z * (pr_cwbullet.Random2() / 255.); } int damage = damageperbullet; @@ -1838,7 +1836,6 @@ static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, double y = Spawnofs_xy * angle.Sin(); DAngle ang = self->Angles.Yaw - 90; DVector2 ofs = ang.ToVector(Spawnofs_xy); - //AActor *proj = P_SpawnMissileXYZ(self->Vec3Offset(x, y, z + self->GetBobOffset()), self, puff, missile, false); AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true); if (proj) From cc8e7f8de6a34d1ee671d2d989504df6d42ab20c Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Mon, 30 May 2016 15:31:19 -0500 Subject: [PATCH 07/13] Cleaning finished. --- src/thingdef/thingdef_codeptr.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 784bb3518..ce1f4f4c5 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1832,8 +1832,6 @@ static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, { if (self && missile && puff) { - double x = Spawnofs_xy * angle.Cos(); - double y = Spawnofs_xy * angle.Sin(); DAngle ang = self->Angles.Yaw - 90; DVector2 ofs = ang.ToVector(Spawnofs_xy); From 4750dfd8b6c261901d561521ba6733fada886298 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Mon, 30 May 2016 18:08:43 -0500 Subject: [PATCH 08/13] Added ability to set the puffs directly as the spawned projectile's target, master, and/or tracer. --- src/thingdef/thingdef_codeptr.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index ce1f4f4c5..f3118c3dd 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1622,6 +1622,9 @@ enum CBA_Flags CBAF_EXPLICITANGLE = 4, CBAF_NOPITCH = 8, CBAF_NORANDOMPUFFZ = 16, + CBAF_PUFFTARGET = 32, + CBAF_PUFFMASTER = 64, + CBAF_PUFFTRACER = 128, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) @@ -1691,6 +1694,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) AActor *proj = P_SpawnMissileXYZ(self->Vec3Offset(x, y, self->GetBobOffset() + Spawnheight), self, puff, missile, false); if (proj) { + if (flags & CBAF_PUFFTARGET) proj->target = puff; + if (flags & CBAF_PUFFMASTER) proj->master = puff; + if (flags & CBAF_PUFFTRACER) proj->tracer = puff; double missilespeed; A_Face(proj, puff, 0., 0.); missilespeed = fabs(proj->Angles.Pitch.Cos() * proj->Speed); @@ -1826,9 +1832,12 @@ enum FB_Flags FBF_NOPITCH = 8, FBF_NOFLASH = 16, FBF_NORANDOMPUFFZ = 32, + FBF_PUFFTARGET = 64, + FBF_PUFFMASTER = 128, + FBF_PUFFTRACER = 256, }; -static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, DAngle angle, double Spawnheight, double Spawnofs_xy) +static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, DAngle angle, double Spawnheight, double Spawnofs_xy, int flags) { if (self && missile && puff) { @@ -1838,6 +1847,9 @@ static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true); if (proj) { + if (flags & FBF_PUFFTARGET) proj->target = puff; + if (flags & FBF_PUFFMASTER) proj->master = puff; + if (flags & FBF_PUFFTRACER) proj->tracer = puff; double missilespeed; A_Face(proj, puff, 0., 0.); missilespeed = fabs(proj->Angles.Pitch.Cos() * proj->Speed); @@ -1899,7 +1911,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) damage *= ((pr_cwbullet()%3)+1); AActor *puff = P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags); - FireBulletMissile(self, missile, puff, bangle, Spawnheight, Spawnofs_xy); + FireBulletMissile(self, missile, puff, bangle, Spawnheight, Spawnofs_xy, flags); } else @@ -1928,7 +1940,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) damage *= ((pr_cwbullet()%3)+1); AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); - FireBulletMissile(self, missile, puff, angle, Spawnheight, Spawnofs_xy); + FireBulletMissile(self, missile, puff, angle, Spawnheight, Spawnofs_xy, flags); } } return 0; From 10fabc3ab7feb06c3435ad8bd0837ef9171331e1 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sun, 19 Jun 2016 10:59:00 -0500 Subject: [PATCH 09/13] Cleaned up code. Puffs no longer need ALWAYSPUFF. - A_CustomBulletAttack and A_FireBullets will perform a second P_LineAttack to get a puff which only returns to the previous function after a tracer. --- src/p_local.h | 3 +- src/p_map.cpp | 51 ++++++++++++++-------- src/thingdef/thingdef_codeptr.cpp | 70 ++++++++++++++++++++++--------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index ac6b264d9..42b4da7e7 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -325,7 +325,8 @@ enum // P_LineAttack flags { LAF_ISMELEEATTACK = 1, LAF_NORANDOMPUFFZ = 2, - LAF_NOIMPACTDECAL = 4 + LAF_NOIMPACTDECAL = 4, + LAF_NOINTERACT = 8, }; AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL); diff --git a/src/p_map.cpp b/src/p_map.cpp index 2fe41b17b..d63bf18b6 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4096,6 +4096,7 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage) { + bool nointeract = !!(flags && LAF_NOINTERACT); DVector3 direction; double shootz; FTraceResults trace; @@ -4185,26 +4186,32 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } int tflags; - if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) tflags = TRACE_NoSky; + if (nointeract || (puffDefaults && puffDefaults->flags6 & MF6_NOTRIGGER)) tflags = TRACE_NoSky; else tflags = TRACE_NoSky | TRACE_Impact; if (!Trace(t1->PosAtZ(shootz), t1->Sector, direction, distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN, t1, trace, tflags, CheckForActor, &TData)) { // hit nothing - if (puffDefaults == NULL) - { - } - else if (puffDefaults->ActiveSound) + if (!nointeract && puffDefaults && puffDefaults->ActiveSound) { // Play miss sound S_Sound(t1, CHAN_WEAPON, puffDefaults->ActiveSound, 1, ATTN_NORM); } - if (puffDefaults != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF) + + // [MC] LAF_NOINTERACT guarantees puff spawning and returns it directly to the calling function. + // No damage caused, no sounds played, no blood splatters. + + if (nointeract || (puffDefaults && puffDefaults->flags3 & MF3_ALWAYSPUFF)) { // Spawn the puff anyway puff = P_SpawnPuff(t1, pufftype, trace.HitPos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget, 2, puffFlags); + + if (nointeract) + { + return puff; + } } else { - return NULL; + return nullptr; } } else @@ -4212,12 +4219,17 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (trace.HitType != TRACE_HitActor) { // position a bit closer for puffs - if (trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky)) + if (nointeract || trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky)) { DVector2 pos = P_GetOffsetPosition(trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4); puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - 90, 0, puffFlags); puff->radius = 1/65536.; + + if (nointeract) + { + return puff; + } } // [RH] Spawn a decal @@ -4255,14 +4267,6 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } else { - bool bloodsplatter = (t1->flags5 & MF5_BLOODSPLATTER) || - (t1->player != NULL && t1->player->ReadyWeapon != NULL && - (t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD)); - - bool axeBlood = (t1->player != NULL && - t1->player->ReadyWeapon != NULL && - (t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD)); - // Hit a thing, so it could be either a puff or blood DVector3 bleedpos = trace.HitPos; // position a bit closer for puffs/blood if using compatibility mode. @@ -4275,7 +4279,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } // Spawn bullet puffs or blood spots, depending on target type. - if ((puffDefaults != NULL && puffDefaults->flags3 & MF3_PUFFONACTORS) || + if (nointeract || (puffDefaults && puffDefaults->flags3 & MF3_PUFFONACTORS) || (trace.Actor->flags & MF_NOBLOOD) || (trace.Actor->flags2 & (MF2_INVULNERABLE | MF2_DORMANT))) { @@ -4284,6 +4288,11 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, // We must pass the unreplaced puff type here puff = P_SpawnPuff(t1, pufftype, bleedpos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - 90, 2, puffFlags | PF_HITTHING, trace.Actor); + + if (nointeract) + { + return puff; + } } // Allow puffs to inflict poison damage, so that hitscans can poison, too. @@ -4320,6 +4329,14 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } if (!(puffDefaults != NULL && puffDefaults->flags3&MF3_BLOODLESSIMPACT)) { + bool bloodsplatter = (t1->flags5 & MF5_BLOODSPLATTER) || + (t1->player != nullptr && t1->player->ReadyWeapon != nullptr && + (t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD)); + + bool axeBlood = (t1->player != nullptr && + t1->player->ReadyWeapon != nullptr && + (t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD)); + if (!bloodsplatter && !axeBlood && !(trace.Actor->flags & MF_NOBLOOD) && !(trace.Actor->flags2 & (MF2_INVULNERABLE | MF2_DORMANT))) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index f3118c3dd..10d0d4498 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1666,6 +1666,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); for (i = 0; i < numbullets; i++) { + bool temp = false; DAngle angle = bangle; DAngle slope = bslope; @@ -1686,6 +1687,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) damage *= ((pr_cabullet()%3)+1); AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); + if (!puff) + { + temp = true; + puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + } if (puff && missile) { @@ -1694,14 +1700,20 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) AActor *proj = P_SpawnMissileXYZ(self->Vec3Offset(x, y, self->GetBobOffset() + Spawnheight), self, puff, missile, false); if (proj) { - if (flags & CBAF_PUFFTARGET) proj->target = puff; - if (flags & CBAF_PUFFMASTER) proj->master = puff; - if (flags & CBAF_PUFFTRACER) proj->tracer = puff; - double missilespeed; - A_Face(proj, puff, 0., 0.); - missilespeed = fabs(proj->Angles.Pitch.Cos() * proj->Speed); - proj->Vel.Z = proj->Angles.Pitch.Sin() * proj->Speed; - proj->VelFromAngle(missilespeed); + // FAF_BOTTOM = 1 + // Aim for the base of the puff as that's where blood puffs will spawn... roughly. + + A_Face(proj, puff, 0., 0., 0., 0., 1); + proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed); + + if (temp) + puff->Destroy(); + else + { + if (flags & CBAF_PUFFTARGET) proj->target = puff; + if (flags & CBAF_PUFFMASTER) proj->master = puff; + if (flags & CBAF_PUFFTRACER) proj->tracer = puff; + } } } } @@ -1837,7 +1849,7 @@ enum FB_Flags FBF_PUFFTRACER = 256, }; -static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, DAngle angle, double Spawnheight, double Spawnofs_xy, int flags) +static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, DAngle angle, double Spawnheight, double Spawnofs_xy, int flags, bool temp) { if (self && missile && puff) { @@ -1847,14 +1859,20 @@ static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true); if (proj) { - if (flags & FBF_PUFFTARGET) proj->target = puff; - if (flags & FBF_PUFFMASTER) proj->master = puff; - if (flags & FBF_PUFFTRACER) proj->tracer = puff; - double missilespeed; - A_Face(proj, puff, 0., 0.); - missilespeed = fabs(proj->Angles.Pitch.Cos() * proj->Speed); - proj->Vel.Z = proj->Angles.Pitch.Sin() * proj->Speed; - proj->VelFromAngle(missilespeed); + // FAF_BOTTOM = 1 + // Aim for the base of the puff as that's where blood puffs will spawn... roughly. + + A_Face(proj, puff, 0., 0., 0., 0., 1); + proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed); + + if (temp) + puff->Destroy(); + else + { + if (flags & FBF_PUFFTARGET) proj->target = puff; + if (flags & FBF_PUFFMASTER) proj->master = puff; + if (flags & FBF_PUFFTRACER) proj->tracer = puff; + } } } } @@ -1910,8 +1928,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if (!(flags & FBF_NORANDOM)) damage *= ((pr_cwbullet()%3)+1); + bool temp = false; AActor *puff = P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags); - FireBulletMissile(self, missile, puff, bangle, Spawnheight, Spawnofs_xy, flags); + + if (!puff) + { + temp = true; + puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + } + FireBulletMissile(self, missile, puff, bangle, Spawnheight, Spawnofs_xy, flags, temp); } else @@ -1939,8 +1964,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if (!(flags & FBF_NORANDOM)) damage *= ((pr_cwbullet()%3)+1); + bool temp = false; AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); - FireBulletMissile(self, missile, puff, angle, Spawnheight, Spawnofs_xy, flags); + + if (!puff) + { + temp = true; + puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + } + FireBulletMissile(self, missile, puff, angle, Spawnheight, Spawnofs_xy, flags, temp); } } return 0; From 02064437c5481bfe9766acfd87aa670b82870310 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Wed, 22 Jun 2016 19:34:14 -0500 Subject: [PATCH 10/13] Fixed wrong angle/slopes being used and one too many &s for NOINTERACT. --- src/p_map.cpp | 2 +- src/thingdef/thingdef_codeptr.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index d63bf18b6..1684ee534 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4096,7 +4096,7 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage) { - bool nointeract = !!(flags && LAF_NOINTERACT); + bool nointeract = !!(flags & LAF_NOINTERACT); DVector3 direction; double shootz; FTraceResults trace; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 10d0d4498..7f9a6edfe 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1690,7 +1690,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) if (!puff) { temp = true; - puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); } if (puff && missile) @@ -1970,7 +1970,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if (!puff) { temp = true; - puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); } FireBulletMissile(self, missile, puff, angle, Spawnheight, Spawnofs_xy, flags, temp); } From 376c9b030650c460dcc5df1ab5576df0759a9485 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Wed, 13 Jul 2016 09:48:24 -0500 Subject: [PATCH 11/13] - Optimized handling of puffs in the event they're null. - Only spawn the puff as needed again if the projectile actually spawns. --- src/thingdef/thingdef_codeptr.cpp | 103 ++++++++++++++++++------------ 1 file changed, 62 insertions(+), 41 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 7f9a6edfe..734ef2ef7 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1666,7 +1666,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); for (i = 0; i < numbullets; i++) { - bool temp = false; DAngle angle = bangle; DAngle slope = bslope; @@ -1687,32 +1686,39 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) damage *= ((pr_cabullet()%3)+1); AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); - if (!puff) - { - temp = true; - puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); - } - - if (puff && missile) + if (missile != nullptr && pufftype != nullptr) { double x = Spawnofs_xy * angle.Cos(); double y = Spawnofs_xy * angle.Sin(); - AActor *proj = P_SpawnMissileXYZ(self->Vec3Offset(x, y, self->GetBobOffset() + Spawnheight), self, puff, missile, false); + + DVector3 pos = self->Pos(); + self->SetXYZ(self->Vec3Offset(x, y, 0.)); + AActor *proj = P_SpawnMissileAngleZSpeed(self, self->Z() + self->GetBobOffset() + Spawnheight, missile, self->Angles.Yaw, 0, GetDefaultByType(missile)->Speed, self, false); + self->SetXYZ(pos); + if (proj) { - // FAF_BOTTOM = 1 - // Aim for the base of the puff as that's where blood puffs will spawn... roughly. - - A_Face(proj, puff, 0., 0., 0., 0., 1); - proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed); - - if (temp) - puff->Destroy(); - else + bool temp = (puff == nullptr); + if (!puff) { - if (flags & CBAF_PUFFTARGET) proj->target = puff; - if (flags & CBAF_PUFFMASTER) proj->master = puff; - if (flags & CBAF_PUFFTRACER) proj->tracer = puff; + puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + } + if (puff) + { + // FAF_BOTTOM = 1 + // Aim for the base of the puff as that's where blood puffs will spawn... roughly. + + A_Face(proj, puff, 0., 0., 0., 0., 1); + proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed); + + if (temp) + puff->Destroy(); + else + { + if (flags & CBAF_PUFFTARGET) proj->target = puff; + if (flags & CBAF_PUFFMASTER) proj->master = puff; + if (flags & CBAF_PUFFTRACER) proj->tracer = puff; + } } } } @@ -1849,14 +1855,10 @@ enum FB_Flags FBF_PUFFTRACER = 256, }; -static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, DAngle angle, double Spawnheight, double Spawnofs_xy, int flags, bool temp) +static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp) { - if (self && missile && puff) + if (proj && puff) { - DAngle ang = self->Angles.Yaw - 90; - DVector2 ofs = ang.ToVector(Spawnofs_xy); - - AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true); if (proj) { // FAF_BOTTOM = 1 @@ -1865,9 +1867,7 @@ static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, A_Face(proj, puff, 0., 0., 0., 0., 1); proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed); - if (temp) - puff->Destroy(); - else + if (!temp) { if (flags & FBF_PUFFTARGET) proj->target = puff; if (flags & FBF_PUFFMASTER) proj->master = puff; @@ -1875,6 +1875,10 @@ static void FireBulletMissile(AActor *self, PClassActor *missile, AActor *puff, } } } + if (puff && temp) + { + puff->Destroy(); + } } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) @@ -1928,16 +1932,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if (!(flags & FBF_NORANDOM)) damage *= ((pr_cwbullet()%3)+1); - bool temp = false; AActor *puff = P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags); - if (!puff) + if (missile != nullptr) { - temp = true; - puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + bool temp = false; + DAngle ang = self->Angles.Yaw - 90; + DVector2 ofs = ang.ToVector(Spawnofs_xy); + AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, bangle, nullptr, nullptr, false, true); + if (proj) + { + if (!puff) + { + temp = true; + puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + } + AimBulletMissile(proj, puff, flags, temp); + } } - FireBulletMissile(self, missile, puff, bangle, Spawnheight, Spawnofs_xy, flags, temp); - } else { @@ -1964,15 +1976,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if (!(flags & FBF_NORANDOM)) damage *= ((pr_cwbullet()%3)+1); - bool temp = false; AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags); - if (!puff) + if (missile != nullptr) { - temp = true; - puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + bool temp = false; + DAngle ang = self->Angles.Yaw - 90; + DVector2 ofs = ang.ToVector(Spawnofs_xy); + AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true); + if (proj) + { + if (!puff) + { + temp = true; + puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); + } + AimBulletMissile(proj, puff, flags, temp); + } } - FireBulletMissile(self, missile, puff, angle, Spawnheight, Spawnofs_xy, flags, temp); } } return 0; From 7544adfc912e899400b2a250be33cd8247cfc534 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Wed, 13 Jul 2016 10:15:10 -0500 Subject: [PATCH 12/13] Combined the target/master/tracer checking into AimBulletMissile. --- src/thingdef/thingdef_codeptr.cpp | 38 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 734ef2ef7..63ba6ec30 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1627,6 +1627,8 @@ enum CBA_Flags CBAF_PUFFTRACER = 128, }; +static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, bool cba); + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) { PARAM_SELF_PROLOGUE(AActor); @@ -1705,20 +1707,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) } if (puff) { - // FAF_BOTTOM = 1 - // Aim for the base of the puff as that's where blood puffs will spawn... roughly. - - A_Face(proj, puff, 0., 0., 0., 0., 1); - proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed); - - if (temp) - puff->Destroy(); - else - { - if (flags & CBAF_PUFFTARGET) proj->target = puff; - if (flags & CBAF_PUFFMASTER) proj->master = puff; - if (flags & CBAF_PUFFTRACER) proj->tracer = puff; - } + AimBulletMissile(proj, puff, flags, temp, true); } } } @@ -1855,7 +1844,7 @@ enum FB_Flags FBF_PUFFTRACER = 256, }; -static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp) +static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, bool cba) { if (proj && puff) { @@ -1869,9 +1858,18 @@ static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp) if (!temp) { - if (flags & FBF_PUFFTARGET) proj->target = puff; - if (flags & FBF_PUFFMASTER) proj->master = puff; - if (flags & FBF_PUFFTRACER) proj->tracer = puff; + if (cba) + { + if (flags & CBAF_PUFFTARGET) proj->target = puff; + if (flags & CBAF_PUFFMASTER) proj->master = puff; + if (flags & CBAF_PUFFTRACER) proj->tracer = puff; + } + else + { + if (flags & FBF_PUFFTARGET) proj->target = puff; + if (flags & FBF_PUFFMASTER) proj->master = puff; + if (flags & FBF_PUFFTRACER) proj->tracer = puff; + } } } } @@ -1947,7 +1945,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) temp = true; puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); } - AimBulletMissile(proj, puff, flags, temp); + AimBulletMissile(proj, puff, flags, temp, false); } } } @@ -1991,7 +1989,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) temp = true; puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT); } - AimBulletMissile(proj, puff, flags, temp); + AimBulletMissile(proj, puff, flags, temp, false); } } } From c150116f79aa04479f0cec0e697c546567af7a54 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 16 Jul 2016 19:55:00 +0200 Subject: [PATCH 13/13] - fixed: When changing weapons due to starting or ending a Tome of Power effect, the PSprite's caller needs to be changed. In this case the PSprite animation won't be changed, only the ReadyWeapon. But in order to work, the PSprite's caller needs to change as well so that the next weapon check does not fail. --- src/g_shared/a_artifacts.cpp | 17 ++++++++++++++++- src/g_shared/a_weapons.cpp | 13 ++++++++++++- src/p_pspr.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 07071daa6..b5ac970ca 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1127,12 +1127,27 @@ void APowerWeaponLevel2::InitEffect () assert (sister->SisterWeapon == weapon); - Owner->player->ReadyWeapon = sister; if (weapon->GetReadyState() != sister->GetReadyState()) { + Owner->player->ReadyWeapon = sister; P_SetPsprite(Owner->player, PSP_WEAPON, sister->GetReadyState()); } + else + { + DPSprite *psp = Owner->player->FindPSprite(PSP_WEAPON); + if (psp != nullptr && psp->GetCaller() == Owner->player->ReadyWeapon) + { + // If the weapon changes but the state does not, we have to manually change the PSprite's caller here. + psp->SetCaller(sister); + Owner->player->ReadyWeapon = sister; + } + else + { + // Something went wrong. Initiate a regular weapon change. + Owner->player->PendingWeapon = sister; + } + } } //=========================================================================== diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index e7ebfc77b..575914fe8 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -642,7 +642,18 @@ void AWeapon::EndPowerup () } else { - Owner->player->ReadyWeapon = SisterWeapon; + DPSprite *psp = Owner->player->FindPSprite(PSP_WEAPON); + if (psp != nullptr && psp->GetCaller() == Owner->player->ReadyWeapon) + { + // If the weapon changes but the state does not, we have to manually change the PSprite's caller here. + psp->SetCaller(SisterWeapon); + Owner->player->ReadyWeapon = SisterWeapon; + } + else + { + // Something went wrong. Initiate a regular weapon change. + Owner->player->PendingWeapon = SisterWeapon; + } } } } diff --git a/src/p_pspr.h b/src/p_pspr.h index a7cf49f8c..41d258df8 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -76,6 +76,7 @@ public: FState* GetState() const { return State; } DPSprite* GetNext() { return Next; } AActor* GetCaller() { return Caller; } + void SetCaller(AActor *newcaller) { Caller = newcaller; } double x, y; double oldx, oldy;