From d8ebbcfc08ced02e3fa7a9cd35d90c596b336198 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 11:55:08 +0100 Subject: [PATCH 1/9] - fixed: When loading a savegame the player class in the userinfo needs to be updated. - fixed: Class pointers should not be added to the list of garbage collected pointers. - fixed several warnings in the event code. --- src/dobjtype.cpp | 11 +++++++++++ src/dobjtype.h | 1 + src/g_level.cpp | 2 +- src/m_cheat.cpp | 2 +- src/p_interaction.cpp | 2 +- src/p_mobj.cpp | 3 +-- src/p_saveg.cpp | 3 +++ src/win32/i_main.cpp | 2 +- 8 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 5d4ec59c9..211c73e82 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1529,6 +1529,17 @@ bool PClassPointer::isCompatible(PType *type) return (other != nullptr && other->ClassRestriction->IsDescendantOf(ClassRestriction)); } +//========================================================================== +// +// PClassPointer :: SetPointer +// +//========================================================================== + +void PClassPointer::SetPointer(void *base, unsigned offset, TArray *special) const +{ + // Class pointers do not get added to FlatPointers because they are released from the GC. +} + //========================================================================== // // PClassPointer :: IsMatch diff --git a/src/dobjtype.h b/src/dobjtype.h index cc0a17da8..0151e6c11 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -401,6 +401,7 @@ public: bool isCompatible(PType *type); + void SetPointer(void *base, unsigned offset, TArray *special = NULL) const override; virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; }; diff --git a/src/g_level.cpp b/src/g_level.cpp index c34a80bb7..0842f3ec8 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1365,7 +1365,7 @@ void G_FinishTravel () for (int i = 0; i < pawnsnum; i++) { // [ZZ] fire the enter hook. - E_PlayerEntered(pawns[i]->player - players, true); + E_PlayerEntered(int(pawns[i]->player - players), true); // FBehavior::StaticStartTypedScripts(SCRIPT_Return, pawns[i], true); } diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index d11fb9574..c78ab5dde 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -350,7 +350,7 @@ void cht_DoCheat (player_t *player, int cheat) // player is now alive. // fire E_PlayerRespawned and start the ACS SCRIPT_Respawn. - E_PlayerRespawned(player - players); + E_PlayerRespawned(int(player - players)); // FBehavior::StaticStartTypedScripts(SCRIPT_Respawn, player->mo, true); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 24b37a56a..28df6e761 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -611,7 +611,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) ClientObituary (this, inflictor, source, dmgflags); // [ZZ] fire player death hook - E_PlayerDied(player - players); + E_PlayerDied(int(player - players)); // Death script execution, care of Skull Tag FBehavior::StaticStartTypedScripts (SCRIPT_Death, this, true); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 81fab5733..5bf611800 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -143,7 +143,6 @@ IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(LastHeard) IMPLEMENT_POINTER(master) IMPLEMENT_POINTER(Poisoner) - IMPLEMENT_POINTER(DamageFunc) IMPLEMENT_POINTER(alternative) IMPLEMENT_POINTERS_END @@ -5513,7 +5512,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) { // [ZZ] fire non-hub ENTER event // level.time is a hack to make sure that we don't call it on dummy player initialization during hub return. - if (!level.time) E_PlayerEntered(p - players, false); + if (!level.time) E_PlayerEntered(int(p - players), false); FBehavior::StaticStartTypedScripts (SCRIPT_Enter, p->mo, true); } else if (state == PST_REBORN) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 8f465e081..a3208598d 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -832,7 +832,10 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name) else { dst->userinfo.TransferFrom(uibackup); + // The player class must come from the save, so that the menu reflects the currently playing one. + dst->userinfo.PlayerClassChanged(src->mo->GetClass()->DisplayName); } + // Validate the skin dst->userinfo.SkinNumChanged(R_FindSkin(skins[dst->userinfo.GetSkin()].name, dst->CurrentPlayerClass)); diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 14c4791c6..29aa2e8d7 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1337,7 +1337,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); // Use this to break at a specific allocation number. - //_crtBreakAlloc = 53039; + _crtBreakAlloc = 165966; #endif DoMain (hInstance); From c8db1f151e656ab4adfa04dd48c60a81b0174f45 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 12:16:24 +0100 Subject: [PATCH 2/9] - fixed: All FNames inside actor classes need to be FNameNoInit or their constructor will overwrite them after copying the defaults. --- src/d_player.h | 12 ++++++------ src/p_user.cpp | 2 -- src/win32/i_main.cpp | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 65f401f2d..7fa0d45b2 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -155,12 +155,12 @@ public: double ViewBob; // Former class properties that were moved into the object to get rid of the meta class. - FName SoundClass; // Sound class - FName Face; // Doom status bar face (when used) - FName Portrait; - FName Slot[10]; - FName InvulMode; - FName HealingRadiusType; + FNameNoInit SoundClass; // Sound class + FNameNoInit Face; // Doom status bar face (when used) + FNameNoInit Portrait; + FNameNoInit Slot[10]; + FNameNoInit InvulMode; + FNameNoInit HealingRadiusType; double HexenArmor[5]; BYTE ColorRangeStart; // Skin color range BYTE ColorRangeEnd; diff --git a/src/p_user.cpp b/src/p_user.cpp index 6e7d7c8ec..eea26cc4b 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1232,8 +1232,6 @@ const char *APlayerPawn::GetSoundClass() const return skins[player->userinfo.GetSkin()].name; } - // [GRB] - auto pclass = GetClass(); return SoundClass != NAME_None? SoundClass.GetChars() : "player"; } diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 29aa2e8d7..14c4791c6 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1337,7 +1337,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); // Use this to break at a specific allocation number. - _crtBreakAlloc = 165966; + //_crtBreakAlloc = 53039; #endif DoMain (hInstance); From d8b8767ee9e907beb6d1223f0243a8bf187c8bd9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 12:27:50 +0100 Subject: [PATCH 3/9] - disabled render events pending further discussion and evaluation. --- src/d_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 04fd24d76..c7a001dfe 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -779,7 +779,7 @@ void D_Display () viewwindowx + viewwidth, viewwindowy + viewheight); // [ZZ] execute event hook that we just started the frame - E_RenderFrame(); + //E_RenderFrame(); // Renderer->RenderView(&players[consoleplayer]); @@ -900,7 +900,7 @@ void D_Display () NetUpdate (); // send out any new accumulation // normal update // draw ZScript UI stuff - E_RenderOverlay(); + //E_RenderOverlay(); C_DrawConsole (hw2d); // draw console M_Drawer (); // menu is drawn even on top of everything FStat::PrintStat (); From 67f6f28b55318954d373a6235e8c8b486aca67ed Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 13:14:59 +0100 Subject: [PATCH 4/9] - fixed: When finding the highest floor plane on a given side of a linedef, the necessary tests may not depend on the actual highest floor, which may originate from the other side of the line and cause valid planes that are between the currently set plane and the actual highest floor to be skipped. --- src/menu/menu.cpp | 2 +- src/p_3dfloors.cpp | 42 ++++++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 9d8e5f4f3..676057321 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -1283,7 +1283,7 @@ DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int ce DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings) { - auto c = PClass::FindClass("OptionMenuItemControl"); + auto c = PClass::FindClass("OptionMenuItemControlBase"); auto p = c->CreateNew(); VMValue params[] = { p, FString(label), cmd.GetIndex(), bindings }; auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index fa7b66d65..b699fadbd 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -773,7 +773,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li int highestfloorterrain = -1; FTextureID lowestceilingpic; sector_t *lowestceilingsec = NULL, *highestfloorsec = NULL; - secplane_t *highestfloorplanes[2] = { NULL, NULL }; + secplane_t *highestfloorplanes[2] = { &open.frontfloorplane, &open.backfloorplane }; highestfloorpic.SetInvalid(); lowestceilingpic.SetInvalid(); @@ -800,13 +800,19 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li lowestceilingsec = j == 0 ? linedef->frontsector : linedef->backsector; } - if(ff_top > highestfloor && delta1 <= delta2 && (!restrict || thing->Z() >= ff_top)) + if(delta1 <= delta2 && (!restrict || thing->Z() >= ff_top)) { - highestfloor = ff_top; - highestfloorpic = *rover->top.texture; - highestfloorterrain = rover->model->GetTerrain(rover->top.isceiling); - highestfloorsec = j == 0 ? linedef->frontsector : linedef->backsector; - highestfloorplanes[j] = rover->top.plane; + if (ff_top > highestfloor) + { + highestfloor = ff_top; + highestfloorpic = *rover->top.texture; + highestfloorterrain = rover->model->GetTerrain(rover->top.isceiling); + highestfloorsec = j == 0 ? linedef->frontsector : linedef->backsector; + } + if (ff_top > highestfloorplanes[j]->ZatPoint(x, y)) + { + highestfloorplanes[j] = rover->top.plane; + } } if(ff_top > lowestfloor[j] && ff_top <= thing->Z() + thing->MaxStepHeight) lowestfloor[j] = ff_top; } @@ -818,18 +824,18 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li open.floorpic = highestfloorpic; open.floorterrain = highestfloorterrain; open.bottomsec = highestfloorsec; - if (highestfloorplanes[0]) - { - open.frontfloorplane = *highestfloorplanes[0]; - if (open.frontfloorplane.fC() < 0) open.frontfloorplane.FlipVert(); - } - if (highestfloorplanes[1]) - { - open.backfloorplane = *highestfloorplanes[1]; - if (open.backfloorplane.fC() < 0) open.backfloorplane.FlipVert(); - } } - + if (highestfloorplanes[0] != &open.frontfloorplane) + { + open.frontfloorplane = *highestfloorplanes[0]; + if (open.frontfloorplane.fC() < 0) open.frontfloorplane.FlipVert(); + } + if (highestfloorplanes[1] != &open.backfloorplane) + { + open.backfloorplane = *highestfloorplanes[1]; + if (open.backfloorplane.fC() < 0) open.backfloorplane.FlipVert(); + } + if(lowestceiling < open.top) { open.top = lowestceiling; From 46d12635cef78009e60ac452783023516cab5c5e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 13:17:20 +0100 Subject: [PATCH 5/9] - fixed warning --- src/p_udmf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index a13c24e63..fc71160ae 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1854,7 +1854,7 @@ public: intptr_t v1i = intptr_t(ParsedLines[i].v1); intptr_t v2i = intptr_t(ParsedLines[i].v2); - if (v1i >= level.vertexes.Size() || v2i >= level.vertexes.Size() || v1i < 0 || v2i < 0) + if ((unsigned)v1i >= level.vertexes.Size() || (unsigned)v2i >= level.vertexes.Size()) { I_Error ("Line %d has invalid vertices: %zd and/or %zd.\nThe map only contains %u vertices.", i+skipped, v1i, v2i, level.vertexes.Size()); } From bd86abede35f91bace6733c465f40084ebc9a070 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 15 Feb 2017 10:09:18 -0500 Subject: [PATCH 6/9] - fixed Skulltag rune bugs. 1) When used in a hub, returning to a previous level in the hub deactivated the runes if they were a permanent powerup. 2) When picking up two different runes with the same effect, one rune wearing off removed the effect completely. 3) This entire system was done through an extremely hacky CheatFlags implementation. This was a gross hack, and it was no wonder it didn't always work properly. --- src/g_inventory/a_weapons.cpp | 4 ++-- src/namedef.h | 2 ++ src/p_lnspec.cpp | 6 ++++-- src/p_pspr.cpp | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index af180a4ea..fa9f63afa 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -230,7 +230,7 @@ bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo, int am int enough, enoughmask; int lAmmoUse1; - if ((dmflags & DF_INFINITE_AMMO) || (Owner->player->cheats & CF_INFINITEAMMO)) + if ((dmflags & DF_INFINITE_AMMO) || (Owner->FindInventory (PClass::FindActor(NAME_PowerInfiniteAmmo), true) != nullptr)) { return true; } @@ -311,7 +311,7 @@ DEFINE_ACTION_FUNCTION(AWeapon, CheckAmmo) bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough, int ammouse) { - if (!((dmflags & DF_INFINITE_AMMO) || (Owner->player->cheats & CF_INFINITEAMMO))) + if (!((dmflags & DF_INFINITE_AMMO) || (Owner->FindInventory (PClass::FindActor(NAME_PowerInfiniteAmmo), true) != nullptr))) { if (checkEnough && !CheckAmmo (altFire ? AltFire : PrimaryFire, false, false, ammouse)) { diff --git a/src/namedef.h b/src/namedef.h index a010fbb8a..ebd9f3e8e 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -203,6 +203,8 @@ xx(CallTryPickup) xx(QuestItem25) xx(QuestItem28) xx(QuestItem29) +xx(PowerDoubleFiringSpeed) +xx(PowerInfiniteAmmo) xx(AcolyteBlue) xx(SpectralLightningV1) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 5375085dd..e71cf2f79 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2841,7 +2841,7 @@ FUNC(LS_SetPlayerProperty) // Add or remove a power if (arg2 >= PROP_INVULNERABILITY && arg2 <= PROP_SPEED) { - static ENamedName powers[11] = + static ENamedName powers[13] = { NAME_PowerInvulnerable, NAME_PowerStrength, @@ -2853,7 +2853,9 @@ FUNC(LS_SetPlayerProperty) NAME_PowerFlight, NAME_None, NAME_None, - NAME_PowerSpeed + NAME_PowerSpeed, + NAME_PowerInfiniteAmmo, + NAME_PowerDoubleFiringSpeed }; int power = arg2 - PROP_INVULNERABILITY; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index bf6c79a82..8b8e93f6a 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1381,7 +1381,7 @@ void DPSprite::Tick() Tics--; // [BC] Apply double firing speed. - if ((Flags & PSPF_POWDOUBLE) && Tics && (Owner->cheats & CF_DOUBLEFIRINGSPEED)) + if ((Flags & PSPF_POWDOUBLE) && Tics && (Owner->mo->FindInventory (PClass::FindActor(NAME_PowerDoubleFiringSpeed), true))) Tics--; if (!Tics) From b3d7980b909acab178c337ae536329b82c9f9f8e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 21:19:35 +0100 Subject: [PATCH 7/9] - fixed: PowerProtection clamped its damage minimum to 1, but should do it to 0. --- src/menu/menu.cpp | 1 + wadsrc/static/zscript/inventory/powerups.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 676057321..a8dac6b54 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -270,6 +270,7 @@ bool DMenu::CallMenuEvent(int mkey, bool fromcontroller) void DMenu::Close () { + if (DMenu::CurrentMenu == nullptr) return; // double closing can happen in the save menu. assert(DMenu::CurrentMenu == this); DMenu::CurrentMenu = mParentMenu; Destroy(); diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index d355a5e14..828113ac8 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -1767,7 +1767,7 @@ class PowerProtection : Powerup { if (passive && damage > 0) { - newdamage = max(1, ApplyDamageFactors(GetClass(), damageType, damage, damage / 4)); + newdamage = max(0, ApplyDamageFactors(GetClass(), damageType, damage, damage / 4)); if (Owner != null && newdamage < damage) Owner.A_PlaySound(ActiveSound, CHAN_AUTO, 1.0, false, ATTN_NONE); } } From 4df2a221a8e41267d5576c49b05ba98cd7e058b9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 22:49:13 +0100 Subject: [PATCH 8/9] - fixed: The special called by the InterpolationSpecial actor must have no activator. This required splitting A_CallSpecial into a direct wrapper around P_ExecuteSpecial and implementing itself as a script function calling ExecuteSpecial so that this special case can use a version of the function that can be used without an activator. --- src/p_actionfunctions.cpp | 20 ---------------- src/p_lnspec.cpp | 24 +++++++++++++++++++ wadsrc/static/zscript/actor.txt | 6 ++++- wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/shared/movingcamera.txt | 2 +- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 40629bfcb..15e82a56c 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1410,26 +1410,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_RadiusDamageSelf) return 0; } -//========================================================================== -// -// Execute a line special / script -// -//========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_CallSpecial) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (special); - PARAM_INT_DEF (arg1); - PARAM_INT_DEF (arg2); - PARAM_INT_DEF (arg3); - PARAM_INT_DEF (arg4); - PARAM_INT_DEF (arg5); - - bool res = !!P_ExecuteSpecial(special, NULL, self, false, arg1, arg2, arg3, arg4, arg5); - - ACTION_RETURN_BOOL(res); -} - //========================================================================== // // The ultimate code pointer: Fully customizable missiles! diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index e71cf2f79..6f44cedcd 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -3717,3 +3717,27 @@ int P_ExecuteSpecial(int num, } return 0; } + +//========================================================================== +// +// Execute a line special / script +// +//========================================================================== +DEFINE_ACTION_FUNCTION(FLevelLocals, ExecuteSpecial) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_INT(special); + PARAM_OBJECT(activator, AActor); + PARAM_POINTER(linedef, line_t); + PARAM_BOOL(lineside); + PARAM_INT_DEF(arg1); + PARAM_INT_DEF(arg2); + PARAM_INT_DEF(arg3); + PARAM_INT_DEF(arg4); + PARAM_INT_DEF(arg5); + + bool res = !!P_ExecuteSpecial(special, linedef, activator, lineside, arg1, arg2, arg3, arg4, arg5); + + ACTION_RETURN_BOOL(res); +} + diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5e2454ed2..0666fce8b 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -737,7 +737,11 @@ class Actor : Thinker native native void A_VileChase(); native void A_BossDeath(); native void A_Detonate(); - native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0); + bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0) + { + return Level.ExecuteSpecial(special, self, null, false, arg1, arg2, arg3, arg4, arg5); + } + native void A_ActiveSound(); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index bffee91f0..7b872f472 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -469,6 +469,7 @@ struct LevelLocals native native String GetUDMFString(int type, int index, Name key); native int GetUDMFInt(int type, int index, Name key); native double GetUDMFFloat(int type, int index, Name key); + native bool ExecuteSpecial(int special, Actor activator, line linedef, bool lineside, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0); } diff --git a/wadsrc/static/zscript/shared/movingcamera.txt b/wadsrc/static/zscript/shared/movingcamera.txt index 15fdd0836..c6af13b42 100644 --- a/wadsrc/static/zscript/shared/movingcamera.txt +++ b/wadsrc/static/zscript/shared/movingcamera.txt @@ -311,7 +311,7 @@ class PathFollower : Actor while ( (spec = InterpolationSpecial(iterator.Next ())) ) { - A_CallSpecial(spec.special, spec.args[0], spec.args[1], spec.args[2], spec.args[3], spec.args[4]); + Level.ExecuteSpecial(spec.special, null, null, false, spec.args[0], spec.args[1], spec.args[2], spec.args[3], spec.args[4]); } } From 304e9894966e78902af1f9d084034c2c873de4a7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Feb 2017 23:06:24 +0100 Subject: [PATCH 9/9] - allow splashing on non-swimmable, non-solid 3D floors if they are marked liquid and have a splash assigned. --- src/p_trace.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 3597535e5..818372e74 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -41,6 +41,7 @@ #include "r_defs.h" #include "p_spec.h" #include "g_levellocals.h" +#include "p_terrain.h" //========================================================================== // @@ -135,6 +136,13 @@ static void GetPortalTransition(DVector3 &pos, sector_t *&sec) } } +static bool isLiquid(F3DFloor *ff) +{ + if (ff->flags & FF_SWIMMABLE) return true; + auto terrain = ff->model->GetTerrain(ff->flags & FF_INVERTPLANES ? sector_t::floor : sector_t::ceiling); + return Terrains[terrain].IsLiquid && Terrains[terrain].Splash != -1; +} + //========================================================================== // // Trace entry point @@ -300,9 +308,9 @@ void FTraceInfo::Setup3DFloors() if (!(rover->flags&FF_EXISTS)) continue; - if (rover->flags&FF_SWIMMABLE && Results->Crossed3DWater == NULL) + if (Results->Crossed3DWater == NULL) { - if (Check3DFloorPlane(rover, false)) + if (Check3DFloorPlane(rover, false) && isLiquid(rover)) { // only consider if the plane is above the actual floor. if (rover->top.plane->ZatPoint(Results->HitPos) > bf) @@ -767,7 +775,7 @@ bool FTraceInfo::TraceTraverse (int ptflags) { for (auto rover : CurSector->e->XFloor.ffloors) { - if ((rover->flags & FF_EXISTS) && (rover->flags&FF_SWIMMABLE)) + if ((rover->flags & FF_EXISTS) && isLiquid(rover)) { if (Check3DFloorPlane(rover, false)) {