Merge branch 'new_level_refactor' into localization

This commit is contained in:
Christoph Oelckers 2019-02-09 12:22:15 +01:00
commit 88e227f1f3
59 changed files with 222 additions and 22367 deletions

View file

@ -33,7 +33,7 @@ build_script:
- md build
- cd build
- cmake -G "%GENERATOR%" -T "%TOOLSET%" -DPK3_QUIET_ZIPDIR=YES ..
- cmake --build . --config "%CONFIGURATION%" -- /verbosity:minimal
- cmake --build . --config "%CONFIGURATION%" -- -maxcpucount -verbosity:minimal
after_build:
- set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION%\

View file

@ -108,11 +108,11 @@ matrix:
- os: windows
env:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -A Win32"
- CMAKE_OPTIONS="-A Win32"
- os: windows
env:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -A x64"
- CMAKE_OPTIONS="-A x64"
before_install:
- if [ -n "$GCC_VERSION" ]; then export CC="gcc-${GCC_VERSION}" CXX="g++-${GCC_VERSION}"; fi
@ -132,8 +132,8 @@ script:
-DFORCE_INTERNAL_GME=YES \
-DPK3_QUIET_ZIPDIR=YES \
..
- if [[ $TRAVIS_OS_NAME == 'windows' ]]; then cmake --build . -- -m; fi
- if [[ $TRAVIS_OS_NAME != 'windows' ]]; then cmake --build . -- -j2; fi
- if [[ $TRAVIS_OS_NAME == 'windows' ]]; then cmake --build . --config Release -- -maxcpucount -verbosity:minimal; fi
- if [[ $TRAVIS_OS_NAME != 'windows' ]]; then cmake --build . -- --jobs=2 --keep-going; fi
notifications:
email: false

View file

@ -1,47 +0,0 @@
{
"configurations": [
{
"name": "x64-Release",
"generator": "Ninja",
"configurationType": "Release",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"variables": [
{
"name": "ZDOOM_GENERATE_ASM",
"value": "True",
"type": "BOOL"
},
{
"name": "ZDOOM_GENERATE_MAPFILE",
"value": "True",
"type": "BOOL"
},
{
"name": "ZDOOM_OUTPUT_OLDSTYLE",
"value": "True",
"type": "BOOL"
},
{
"name": "JPEG_INCLUDE_DIR",
"value": "c:\\Programming\\vcpkg\\packages\\libjpeg-turbo_x64-windows-static\\include\\",
"type": "PATH"
},
{
"name": "JPEG_LIBRARY_DEBUG",
"value": "c:\\Programming\\vcpkg\\packages\\libjpeg-turbo_x64-windows-static\\lib\\jpeg.lib",
"type": "FILEPATH"
},
{
"name": "JPEG_LIBRARY_RELEASE",
"value": "c:\\Programming\\vcpkg\\packages\\libjpeg-turbo_x64-windows-static\\lib\\jpeg.lib",
"type": "FILEPATH"
}
]
}
]
}

21073
externs.txt

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -1,43 +0,0 @@
#pragma once
#include "tarray.h"
#include "r_defs.h"
#include "p_trace.h"
// [ZZ] Destructible geometry related
struct FHealthGroup
{
TArray<sector_t*> sectors;
TArray<line_t*> lines;
int health;
int id;
};
// for P_DamageSector
enum
{
SECPART_Floor = 0,
SECPART_Ceiling = 1,
SECPART_3D = 2
};
void P_SetHealthGroupHealth(FHealthGroup* group, int health);
void P_SetHealthGroupHealth(FLevelLocals *Level, int group, int health);
void P_InitHealthGroups(FLevelLocals *Level);
FHealthGroup* P_GetHealthGroup(FLevelLocals *Level, int id);
FHealthGroup* P_GetHealthGroupOrNew(FLevelLocals *Level, int id, int startinghealth);
void P_DamageSector(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius, bool dogroups);
void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius, bool dogroups);
void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName damageType);
void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, int bombdistance, FName damagetype, int fulldamagedistance);
bool P_ProjectileHitLinedef(AActor* projectile, line_t* line);
bool P_ProjectileHitPlane(AActor* projectile, int part);
bool P_CheckLinedefVulnerable(line_t* line, int side, int part = -1);
bool P_CheckSectorVulnerable(sector_t* sector, int part);
void P_SerializeHealthGroups(FSerializer& arc);

View file

@ -1422,7 +1422,7 @@ public:
}
int ApplyDamageFactor(FName damagetype, int damage) const;
int GetModifiedDamage(FName damagetype, int damage, bool passive);
int GetModifiedDamage(FName damagetype, int damage, bool passive, AActor *inflictor, AActor *source, int flags = 0);
void DeleteAttachedLights();
bool isFrozen();

View file

@ -217,7 +217,7 @@ void EventManager::InitHandler(PClass* type)
RegisterHandler(handler);
}
void EventManager::InitStaticHandlers(bool map)
void EventManager::InitStaticHandlers(FLevelLocals *l, bool map)
{
// don't initialize map handlers if restoring from savegame.
if (savegamerestore)
@ -225,6 +225,7 @@ void EventManager::InitStaticHandlers(bool map)
// just make sure
Shutdown();
Level = l;
// initialize event handlers from gameinfo
for (const FString& typeName : gameinfo.EventHandlers)
@ -241,7 +242,7 @@ void EventManager::InitStaticHandlers(bool map)
return;
// initialize event handlers from mapinfo
for (const FString& typeName : level.info->EventHandlers)
for (const FString& typeName : Level->info->EventHandlers)
{
PClass* type = GetHandlerClass(typeName);
if (IsStaticType(type))
@ -257,6 +258,7 @@ void EventManager::Shutdown()
{
handler->Destroy();
}
FirstEventHandler = LastEventHandler = nullptr;
}
#define DEFINE_EVENT_LOOPER(name, play) void EventManager::name() \

View file

@ -249,7 +249,7 @@ struct EventManager
// check type
bool IsStaticType(PClass* type);
// init static handlers
void InitStaticHandlers(bool map);
void InitStaticHandlers(FLevelLocals *l, bool map);
// shutdown handlers
void Shutdown();

View file

@ -114,7 +114,7 @@ CCMD (countdecals)
while (iterator.Next())
count++;
Printf("%s: Counted %d impact decals\n", Level->MapName.GetChars(), count);
Printf("%s: Counted %d impact decals, level counter is at %d\n", Level->MapName.GetChars(), count, Level->ImpactDecalCount);
}
}

View file

@ -573,7 +573,7 @@ static bool unloading;
EXTERN_CVAR(Bool, sv_singleplayerrespawn)
void FLevelLocals::ChangeLevel(const char *levelname, int position, int flags, int nextSkill)
void FLevelLocals::ChangeLevel(const char *levelname, int position, int inflags, int nextSkill)
{
if (!isPrimaryLevel()) return; // only the primary level may exit.
@ -630,7 +630,7 @@ void FLevelLocals::ChangeLevel(const char *levelname, int position, int flags, i
if (nextSkill != -1)
NextSkill = nextSkill;
if (flags & CHANGELEVEL_NOINTERMISSION)
if (inflags & CHANGELEVEL_NOINTERMISSION)
{
flags |= LEVEL_NOINTERMISSION;
}
@ -647,15 +647,15 @@ void FLevelLocals::ChangeLevel(const char *levelname, int position, int flags, i
{
if (nextinfo->flags2 & LEVEL2_RESETINVENTORY)
{
flags |= CHANGELEVEL_RESETINVENTORY;
inflags |= CHANGELEVEL_RESETINVENTORY;
}
if (nextinfo->flags2 & LEVEL2_RESETHEALTH)
{
flags |= CHANGELEVEL_RESETHEALTH;
inflags |= CHANGELEVEL_RESETHEALTH;
}
}
}
changeflags = flags;
changeflags = inflags;
BotInfo.End(); //Added by MC:

View file

@ -618,7 +618,7 @@ public:
bool FromSnapshot; // The current map was restored from a snapshot
bool HasHeightSecs; // true if some Transfer_Heights effects are present in the map. If this is false, some checks in the renderer can be shortcut.
bool HasDynamicLights; // Another render optimization for maps with no lights at all.
uint8_t frozenstate;
int frozenstate;
double teamdamage;

View file

@ -76,6 +76,7 @@ void DDecalFader::Tick ()
}
else if (Level->maptime >= TimeToEndDecay)
{
TheDecal->Expired(); // for impact decal bookkeeping.
TheDecal->Destroy (); // remove the decal
Destroy (); // remove myself
return;

View file

@ -666,6 +666,8 @@ DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, double ix, double
void DImpactDecal::CheckMax ()
{
static int SpawnCounter;
if (++Level->ImpactDecalCount >= cl_maxdecals)
{
DThinker *thinker = Level->FirstThinker (STAT_AUTODECAL);
@ -683,6 +685,17 @@ void DImpactDecal::CheckMax ()
//
//----------------------------------------------------------------------------
void DImpactDecal::Expired()
{
Level->ImpactDecalCount--;
}
//----------------------------------------------------------------------------
//
//
//
//----------------------------------------------------------------------------
DImpactDecal *DImpactDecal::StaticCreate (FLevelLocals *Level, const char *name, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color)
{
if (cl_maxdecals > 0)

View file

@ -26,6 +26,7 @@ public:
void Serialize(FSerializer &arc);
void OnDestroy() override;
virtual void Expired() {} // For thinkers that can remove their decal. For impact decal bookkeeping.
FTextureID StickToWall(side_t *wall, double x, double y, F3DFloor * ffloor);
double GetRealZ (const side_t *wall) const;
void SetShade (uint32_t rgb);
@ -71,6 +72,7 @@ public:
static DImpactDecal *StaticCreate(FLevelLocals *Level, const FDecalTemplate *tpl, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color = 0);
void BeginPlay ();
void Expired() override;
protected:
DBaseDecal *CloneSelf(const FDecalTemplate *tpl, double x, double y, double z, side_t *wall, F3DFloor * ffloor) const;

View file

@ -62,13 +62,12 @@
Only one selector of each type can be used.
*/
AActor *COPY_AAPTR(AActor *origin, int selector)
AActor *COPY_AAPTREX(FLevelLocals *Level, AActor *origin, int selector)
{
if (selector == AAPTR_DEFAULT) return origin;
FTranslatedLineTarget t;
auto Level = origin->Level;
auto AAPTR_RESOLVE_PLAYERNUM = [=](int playernum) -> AActor*
{
return (Level->PlayerInGame(playernum) ? Level->Players[playernum]->mo : nullptr);
@ -119,6 +118,11 @@ AActor *COPY_AAPTR(AActor *origin, int selector)
return origin;
}
AActor *COPY_AAPTR(AActor *origin, int selector)
{
if (origin == nullptr) return nullptr;
return COPY_AAPTREX(origin->Level, origin, selector);
}
// [FDARI] Exported logic for guarding against loops in Target (for missiles) and Master (for all) chains.
// It is called from multiple locations.

View file

@ -64,8 +64,9 @@ enum AAPTR
Only one selector of each type can be used.
*/
struct FLevelLocals;
AActor *COPY_AAPTR(AActor *origin, int selector);
AActor *COPY_AAPTREX(FLevelLocals *Level, AActor *origin, int selector);
enum PTROP
{
PTROP_UNSAFETARGET = 1,

View file

@ -692,6 +692,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
double lowestfloor[2] = {
linedef->frontsector->floorplane.ZatPoint(x, y),
linedef->backsector->floorplane.ZatPoint(x, y) };
bool lowestfloorset[2] = { false, false };
FTextureID highestfloorpic;
int highestfloorterrain = -1;
FTextureID lowestceilingpic;
@ -741,7 +742,11 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
highestfloorplanes[j] = rover->top.plane;
}
}
if(ff_top > lowestfloor[j] && ff_top <= thing->Z() + thing->MaxStepHeight) lowestfloor[j] = ff_top;
if (ff_top > lowestfloor[j] && ff_top <= thing->Z() + thing->MaxStepHeight)
{
lowestfloor[j] = ff_top;
lowestfloorset[j] = true;
}
}
}
@ -771,8 +776,14 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
open.topsec = lowestceilingsec;
open.topffloor = lowestceilingffloor;
}
open.lowfloor = MIN(lowestfloor[0], lowestfloor[1]);
// Don't overwrite still valid info from portals here.
if ((open.lowfloorthroughportal & 1) && lowestfloorset[0]) open.lowfloorthroughportal &= ~1;
if ((open.lowfloorthroughportal & 2) && lowestfloorset[1]) open.lowfloorthroughportal &= ~2;
double low1 = (open.lowfloorthroughportal & 1) ? open.lowfloor : lowestfloor[0];
double low2 = (open.lowfloorthroughportal & 2) ? open.lowfloor : lowestfloor[1];
open.lowfloor = MIN(low1, low2);
}
}
}

View file

@ -36,6 +36,7 @@ struct FCheckPosition
TMap<AActor*, bool> LastRipped;
bool DoRipping;
bool portalstep;
bool dropoffisportal;
int portalgroup;
int PushTime;

View file

@ -195,7 +195,7 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
HandleAspect = true;
Top = y;
HoldTics = (int)(holdTime * TICRATE);
Tics = 0;
Tics = -1; // -1 to compensate for one additional Tick the message will receive.
TextColor = textColor;
State = 0;
SourceText = copystring (text);

View file

@ -201,7 +201,7 @@ enum ELevelFlags : unsigned int
LEVEL2_LAXACTIVATIONMAPINFO = 0x00000008, // LEVEL_LAXMONSTERACTIVATION is not a default.
LEVEL2_MISSILESACTIVATEIMPACT=0x00000010, // Missiles are the activators of SPAC_IMPACT events, not their shooters
LEVEL2_FROZEN = 0x00000020, // Game is frozen by a TimeFreezer
// = 0x00000020, // unused
LEVEL2_KEEPFULLINVENTORY = 0x00000040, // doesn't reduce the amount of inventory items to 1

View file

@ -395,7 +395,7 @@ void PClassActor::StaticInit()
InitBotStuff();
// reinit GLOBAL static stuff from gameinfo, once classes are loaded.
staticEventManager.InitStaticHandlers(false);
staticEventManager.InitStaticHandlers(primaryLevel, false);
}
//==========================================================================

View file

@ -1034,7 +1034,7 @@ void MapLoader::SpawnLights(sector_t *sector)
// [RH] Hexen-like phased lighting
case LightSequenceStart:
Level->CreateThinker<DPhased>(sector);
Level->CreateThinker<DPhased>(sector)->Propagate();
break;
case dLight_Flicker:

View file

@ -3247,7 +3247,7 @@ const char *FBehavior::LookupString (uint32_t index, bool forprint) const
token.Substitute(" ", "");
token.Truncate(5);
FStringf label("TXT_ACS_%s_%d_%.5s", Level->MapName.GetChars(), index, token);
FStringf label("TXT_ACS_%s_%d_%.5s", Level->MapName.GetChars(), index, token.GetChars());
auto p = GStrings[label];
if (p) return p;
}
@ -5352,7 +5352,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args)
AActor *ptr = Level->SingleActorFromTID(args[1], activator);
if (argCount > 2)
{
ptr = COPY_AAPTR(ptr, args[2]);
ptr = COPY_AAPTREX(Level, ptr, args[2]);
}
if (ptr == activator) ptr = NULL;
ASSIGN_AAPTR(activator, args[0], ptr, (argCount > 3) ? args[3] : 0);
@ -6326,7 +6326,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
actor = Level->SingleActorFromTID(tid1, activator);
AActor * actor2 = tid2 == tid1 ? actor : Level->SingleActorFromTID(tid2, activator);
return COPY_AAPTR(actor, args[0]) == COPY_AAPTR(actor2, args[1]);
return COPY_AAPTREX(Level, actor, args[0]) == COPY_AAPTREX(Level, actor2, args[1]);
}
break;
@ -6504,7 +6504,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
int count = argCount >= 4 ? args[3] : 1;
int flags = argCount >= 5 ? args[4] : 0;
int ptr = argCount >= 6 ? args[5] : AAPTR_DEFAULT;
return P_Thing_CheckProximity(actor, classname, distance, count, flags, ptr);
return P_Thing_CheckProximity(Level, actor, classname, distance, count, flags, ptr);
}
case ACSF_CheckActorState:
@ -6528,8 +6528,8 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
case ACSF_DamageActor: // [arookas] wrapper around P_DamageMobj
{
// (target, ptr_select1, inflictor, ptr_select2, amount, damagetype)
AActor* target = COPY_AAPTR(Level->SingleActorFromTID(args[0], activator), args[1]);
AActor* inflictor = COPY_AAPTR(Level->SingleActorFromTID(args[2], activator), args[3]);
AActor* target = COPY_AAPTREX(Level, Level->SingleActorFromTID(args[0], activator), args[1]);
AActor* inflictor = COPY_AAPTREX(Level, Level->SingleActorFromTID(args[2], activator), args[3]);
FName damagetype(Level->Behaviors.LookupString(args[5]));
return P_DamageMobj(target, inflictor, inflictor, args[4], damagetype);
}

View file

@ -485,7 +485,7 @@ DEFINE_ACTION_FUNCTION(AActor, CountProximity)
}
else
{
ret->SetInt(P_Thing_CheckProximity(self, classname, distance, 0, flags, ptr, true));
ret->SetInt(P_Thing_CheckProximity(self->Level, self, classname, distance, 0, flags, ptr, true));
}
return 1;
}
@ -4520,7 +4520,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckProximity)
PARAM_INT(flags);
PARAM_INT(ptr);
ACTION_RETURN_BOOL(!!P_Thing_CheckProximity(self, classname, distance, count, flags, ptr));
ACTION_RETURN_BOOL(!!P_Thing_CheckProximity(self->Level, self, classname, distance, count, flags, ptr));
}
/*===========================================================================

View file

@ -351,7 +351,7 @@ static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, const char *nam
if (name)
{
FStringf label("$TXT_DLG_%s_d%d_%s", name, int(pos), TokenFromString(speech.Dialogue));
FStringf label("$TXT_DLG_%s_d%d_%s", name, int(pos), TokenFromString(speech.Dialogue).GetChars());
node->Dialogue = label;
}
else
@ -435,7 +435,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, const char *nam
// Convert the rest of the data to our own internal format.
if (name)
{
FStringf label("$TXT_DLG_%s_d%d_%s", name, pos, TokenFromString(speech.Dialogue));
FStringf label("$TXT_DLG_%s_d%d_%s", name, pos, TokenFromString(speech.Dialogue).GetChars());
node->Dialogue = label;
}
else
@ -545,7 +545,7 @@ static void ParseReplies (const char *name, int pos, FStrifeDialogueReply **repl
if (name)
{
FStringf label("$TXT_RPLY%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Reply));
FStringf label("$TXT_RPLY%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Reply).GetChars());
reply->Reply = label;
}
else
@ -569,7 +569,7 @@ static void ParseReplies (const char *name, int pos, FStrifeDialogueReply **repl
{
if (name)
{
FStringf label("$TXT_RYES%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Yes));
FStringf label("$TXT_RYES%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Yes).GetChars());
reply->QuickYes = label;
}
else
@ -581,7 +581,7 @@ static void ParseReplies (const char *name, int pos, FStrifeDialogueReply **repl
{
if (name && strncmp(rsp->No, "NO. ", 4)) // All 'no' nodes starting with 'NO.' won't ever be shown and they all contain broken text.
{
FStringf label("$TXT_RNO%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->No));
FStringf label("$TXT_RNO%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->No).GetChars());
reply->QuickNo = label;
}
else

View file

@ -1150,13 +1150,13 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
// Handle active damage modifiers (e.g. PowerDamage)
if (damage > 0 && !(flags & DMG_NO_ENHANCE))
{
damage = source->GetModifiedDamage(mod, damage, false);
damage = source->GetModifiedDamage(mod, damage, false, inflictor, source, flags);
}
}
// Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
if (damage > 0 && !(flags & DMG_NO_PROTECT))
{
damage = target->GetModifiedDamage(mod, damage, true);
damage = target->GetModifiedDamage(mod, damage, true, inflictor, source, flags);
}
if (damage > 0 && !(flags & DMG_NO_FACTOR))
{
@ -1747,7 +1747,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain
// Take half damage in trainer mode
damage = int(damage * G_SkillProperty(SKILLP_DamageFactor) * sv_damagefactorplayer);
// Handle passive damage modifiers (e.g. PowerProtection)
damage = target->GetModifiedDamage(player->poisontype, damage, true);
damage = target->GetModifiedDamage(player->poisontype, damage, true, nullptr, source);
// Modify with damage factors
damage = target->ApplyDamageFactor(player->poisontype, damage);

View file

@ -148,7 +148,8 @@ PClassActor *P_GetSpawnableType(int spawnnum);
void InitSpawnablesFromMapinfo();
int P_Thing_CheckInputNum(player_t *p, int inputnum);
int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch);
int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting = false);
struct FLevelLocals;
int P_Thing_CheckProximity(FLevelLocals *Level, AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting = false);
enum
{

View file

@ -280,6 +280,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags)
tmf.ceilingz = NextHighestCeilingAt(sec, tmf.pos.X, tmf.pos.Y, tmf.pos.Z, tmf.pos.Z + tmf.thing->Height, flags, &tmf.ceilingsector, &ffc);
tmf.floorz = tmf.dropoffz = NextLowestFloorAt(sec, tmf.pos.X, tmf.pos.Y, tmf.pos.Z, flags, tmf.thing->MaxStepHeight, &tmf.floorsector, &fff);
tmf.dropoffisportal = tmf.floorsector != sec;
if (fff)
{
@ -1018,7 +1019,12 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
if (open.lowfloor < tm.dropoffz)
{
tm.dropoffz = open.lowfloor;
// Do not alter the dropoff if the previous portal layer got it solely from its own data.
if (!(cres.portalflags & FFCF_NOCEILING) || tm.dropoffisportal)
{
tm.dropoffz = open.lowfloor;
tm.dropoffisportal = open.lowfloorthroughportal;
}
}
}
}
@ -1680,6 +1686,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo
else
{
tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint(pos);
tm.dropoffisportal = false;
tm.floorpic = newsec->GetTexture(sector_t::floor);
tm.ceilingz = newsec->ceilingplane.ZatPoint(pos);
tm.ceilingpic = newsec->GetTexture(sector_t::ceiling);
@ -1704,6 +1711,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo
if (ff_top > tm.floorz && fabs(delta1) < fabs(delta2))
{
tm.floorz = tm.dropoffz = ff_top;
tm.dropoffisportal = false;
tm.floorpic = *rover->top.texture;
tm.floorterrain = rover->model->GetTerrain(rover->top.isceiling);
}

View file

@ -177,12 +177,17 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co
bool usefront;
// Store portal state to avoid registering false dropoffs.
open.lowfloorthroughportal = 0;
if (ff == LINEOPEN_MIN) open.lowfloorthroughportal |= 1;
if (bf == LINEOPEN_MIN) open.lowfloorthroughportal |= 2;
// [RH] fudge a bit for actors that are moving across lines
// bordering a slope/non-slope that meet on the floor. Note
// that imprecisions in the plane equation mean there is a
// good chance that even if a slope and non-slope look like
// they line up, they won't be perfectly aligned.
if (ff == -FLT_MIN || bf == -FLT_MIN || ref == NULL || fabs (ff-bf) > 1./256)
if (ff == LINEOPEN_MIN || bf == LINEOPEN_MIN || ref == NULL || fabs (ff-bf) > 1./256)
{
usefront = (ff > bf);
}
@ -196,6 +201,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co
usefront = !P_PointOnLineSide (*ref, linedef);
}
open.lowfloorthroughportal = false;
if (usefront)
{
open.bottom = ff;

View file

@ -111,6 +111,7 @@ struct FLineOpening
int floorterrain;
bool touchmidtex;
bool abovemidtex;
uint8_t lowfloorthroughportal;
F3DFloor *topffloor;
F3DFloor *bottomffloor;
};

View file

@ -4977,7 +4977,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag
mobj = Spawn (this, p->cls, spawn, NO_REPLACE);
if (flags & LEVEL_USEPLAYERSTARTZ)
if (this->flags & LEVEL_USEPLAYERSTARTZ)
{
if (spawn.Z == ONFLOORZ)
mobj->AddZ(mthing->pos.Z);
@ -7217,15 +7217,15 @@ void AActor::ClearCounters()
}
}
int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive)
int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive, AActor *inflictor, AActor *source, int flags)
{
auto inv = Inventory;
while (inv != nullptr)
{
IFVIRTUALPTRNAME(inv, NAME_Inventory, ModifyDamage)
{
VMValue params[5] = { (DObject*)inv, damage, int(damagetype), &damage, passive };
VMCall(func, params, 5, nullptr, 0);
VMValue params[8] = { (DObject*)inv, damage, int(damagetype), &damage, passive, inflictor, source, flags };
VMCall(func, params, 8, nullptr, 0);
}
inv = inv->Inventory;
}

View file

@ -964,7 +964,6 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
("spotstate", SpotState)
("fragglethinker", FraggleScriptThinker)
("acsthinker", ACSThinker)
("impactdecalcount", ImpactDecalCount)
("scrolls", Scrolls)
("automap", automap)
("interpolator", interpolator)
@ -1015,7 +1014,7 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
if (arc.isReading())
{
for (auto &sec : sectors)
{
{
P_Recalculate3DFloors(&sec);
}
for (int i = 0; i < MAXPLAYERS; ++i)
@ -1029,6 +1028,10 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
RecreateAllAttachedLights();
InitPortalGroups(this);
auto it = GetThinkerIterator<DImpactDecal>(NAME_None, STAT_AUTODECAL);
ImpactDecalCount = 0;
while (it.Next()) ImpactDecalCount++;
automap->UpdateShowAllLines();
}

View file

@ -423,7 +423,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame)
// [ZZ] init per-map static handlers. we need to call this before everything is set up because otherwise scripts don't receive PlayerEntered event
// (which happens at god-knows-what stage in this function, but definitely not the last part, because otherwise it'd work to put E_InitStaticHandlers before the player spawning)
Level->localEventManager->InitStaticHandlers(true);
Level->localEventManager->InitStaticHandlers(Level, true);
// generate a checksum for the level, to be included and checked with savegames.
map->GetChecksum(Level->md5);

View file

@ -567,9 +567,9 @@ int P_Thing_CheckInputNum(player_t *p, int inputnum)
}
return renum;
}
int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting)
int P_Thing_CheckProximity(FLevelLocals *Level, AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting)
{
AActor *ref = COPY_AAPTR(self, ptr);
AActor *ref = COPY_AAPTREX(Level, self, ptr);
// We need these to check out.
if (!ref || !classname || distance <= 0)

View file

@ -858,29 +858,41 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor
if (DEarthquake::StaticGetQuakeIntensities(viewpoint.TicFrac, viewpoint.camera, jiggers) > 0)
{
double quakefactor = r_quakeintensity;
DAngle an;
DVector3 pos; pos.Zero();
if (jiggers.RollIntensity != 0 || jiggers.RollWave != 0)
{
viewpoint.Angles.Roll += QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave);
}
if (jiggers.RelIntensity.X != 0 || jiggers.RelOffset.X != 0)
{
an = viewpoint.camera->Angles.Yaw;
double power = QuakePower(quakefactor, jiggers.RelIntensity.X, jiggers.RelOffset.X);
viewpoint.Pos += an.ToVector(power);
pos.X += QuakePower(quakefactor, jiggers.RelIntensity.X, jiggers.RelOffset.X);
}
if (jiggers.RelIntensity.Y != 0 || jiggers.RelOffset.Y != 0)
{
an = viewpoint.camera->Angles.Yaw + 90;
double power = QuakePower(quakefactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y);
viewpoint.Pos += an.ToVector(power);
pos.Y += QuakePower(quakefactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y);
}
// FIXME: Relative Z is not relative
if (jiggers.RelIntensity.Z != 0 || jiggers.RelOffset.Z != 0)
{
viewpoint.Pos.Z += QuakePower(quakefactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z);
pos.Z += QuakePower(quakefactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z);
}
// [MC] Tremendous thanks to Marisa Kirisame for helping me with this.
// Use a rotation matrix to make the view relative.
if (!pos.isZero())
{
DAngle yaw = viewpoint.camera->Angles.Yaw;
DAngle pitch = viewpoint.camera->Angles.Pitch;
DAngle roll = viewpoint.camera->Angles.Roll;
DVector3 relx, rely, relz;
DMatrix3x3 rot =
DMatrix3x3(DVector3(0., 0., 1.), yaw.Cos(), yaw.Sin()) *
DMatrix3x3(DVector3(0., 1., 0.), pitch.Cos(), pitch.Sin()) *
DMatrix3x3(DVector3(1., 0., 0.), roll.Cos(), roll.Sin());
relx = DVector3(1., 0., 0.)*rot;
rely = DVector3(0., 1., 0.)*rot;
relz = DVector3(0., 0., 1.)*rot;
viewpoint.Pos += relx * pos.X + rely * pos.Y + relz * pos.Z;
}
if (jiggers.Intensity.X != 0 || jiggers.Offset.X != 0)
{
viewpoint.Pos.X += QuakePower(quakefactor, jiggers.Intensity.X, jiggers.Offset.X);

View file

@ -95,7 +95,7 @@ namespace swrenderer
/////////////////////////////////////////////////////////////////////////
// Changes how rapidly things get dark with distance
void LightVisibility::SetVisibility(RenderViewport *viewport, double vis)
void LightVisibility::SetVisibility(RenderViewport *viewport, double vis, bool nolightfade)
{
vis = R_ClampVisibility(vis);
@ -140,7 +140,7 @@ namespace swrenderer
TiltVisibility = float(vis * viewport->viewwindow.FocalTangent * (16.f * 320.f) / viewwidth);
NoLightFade = !!(viewport->Level()->flags3 & LEVEL3_NOLIGHTFADE);
NoLightFade = nolightfade;
}
fixed_t LightVisibility::LightLevelToShadeImpl(RenderViewport *viewport, int lightlevel, bool foggy)

View file

@ -77,7 +77,7 @@ namespace swrenderer
class LightVisibility
{
public:
void SetVisibility(RenderViewport *viewport, double visibility);
void SetVisibility(RenderViewport *viewport, double visibility, bool nolightfade);
double GetVisibility() const { return CurrentVisibility; }
// The vis value to pass into the GETPALOOKUP or LIGHTSCALE macros

View file

@ -118,6 +118,7 @@ namespace swrenderer
double savedvisibility = Thread->Light->GetVisibility();
AActor *savedcamera = Thread->Viewport->viewpoint.camera;
sector_t *savedsector = Thread->Viewport->viewpoint.sector;
auto Level = Thread->Viewport->Level();
for (VisiblePlane *pl = planes->PopFirstPortalPlane(); pl != nullptr; pl = planes->PopFirstPortalPlane())
{
@ -137,7 +138,7 @@ namespace swrenderer
// Don't let gun flashes brighten the sky box
AActor *sky = port->mSkybox;
Thread->Viewport->viewpoint.extralight = 0;
Thread->Light->SetVisibility(Thread->Viewport.get(), sky->args[0] * 0.25f);
Thread->Light->SetVisibility(Thread->Viewport.get(), sky->args[0] * 0.25f, !!(Level->flags3 & LEVEL3_NOLIGHTFADE));
Thread->Viewport->viewpoint.Pos = sky->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac);
Thread->Viewport->viewpoint.Angles.Yaw = savedangles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * Thread->Viewport->viewpoint.TicFrac);
@ -150,7 +151,7 @@ namespace swrenderer
case PORTS_PORTAL:
case PORTS_LINKEDPORTAL:
Thread->Viewport->viewpoint.extralight = pl->extralight;
Thread->Light->SetVisibility(Thread->Viewport.get(), pl->visibility);
Thread->Light->SetVisibility(Thread->Viewport.get(), pl->visibility, !!(Level->flags3 & LEVEL3_NOLIGHTFADE));
Thread->Viewport->viewpoint.Pos.X = pl->viewpos.X + port->mDisplacement.X;
Thread->Viewport->viewpoint.Pos.Y = pl->viewpos.Y + port->mDisplacement.Y;
Thread->Viewport->viewpoint.Pos.Z = pl->viewpos.Z;
@ -167,8 +168,6 @@ namespace swrenderer
continue;
}
auto Level = Thread->Viewport->Level();
SetInSkyBox(port);
if (port->mPartner > 0) SetInSkyBox(&Level->sectorPortals[port->mPartner]);
Thread->Viewport->viewpoint.camera = nullptr;
@ -256,7 +255,7 @@ namespace swrenderer
Thread->Viewport->viewpoint.camera = savedcamera;
Thread->Viewport->viewpoint.sector = savedsector;
Thread->Viewport->viewpoint.Pos = savedpos;
Thread->Light->SetVisibility(Thread->Viewport.get(), savedvisibility);
Thread->Light->SetVisibility(Thread->Viewport.get(), savedvisibility, !!(Level->flags3 & LEVEL3_NOLIGHTFADE));
Thread->Viewport->viewpoint.extralight = savedextralight;
Thread->Viewport->viewpoint.Angles = savedangles;
Thread->Viewport->viewpoint.SetViewAngle(Thread->Viewport->viewwindow);

View file

@ -102,7 +102,7 @@ namespace swrenderer
int height = SCREENHEIGHT;
float trueratio;
ActiveRatio(width, height, &trueratio);
viewport->SetViewport(MainThread(), width, height, trueratio);
viewport->SetViewport(player->camera->Level, MainThread(), width, height, trueratio);
r_modelscene = r_models && Models.Size() > 0;
if (r_modelscene)
@ -379,7 +379,7 @@ namespace swrenderer
viewwindowx = x;
viewwindowy = y;
viewactive = true;
viewport->SetViewport(MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio);
viewport->SetViewport(actor->Level, MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio);
if (r_modelscene)
PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget);

View file

@ -95,7 +95,7 @@ namespace swrenderer
return Mat4f::Frustum(-width, width, -height + offset, height + offset, near, far, Handedness::Right, ClipZRange::NegativePositiveW);
}
void RenderViewport::SetViewport(RenderThread *thread, int fullWidth, int fullHeight, float trueratio)
void RenderViewport::SetViewport(FLevelLocals *Level, RenderThread *thread, int fullWidth, int fullHeight, float trueratio)
{
int virtheight, virtwidth, virtwidth2, virtheight2;
@ -135,7 +135,7 @@ namespace swrenderer
virtwidth = virtwidth * AspectMultiplier(viewwindow.WidescreenRatio) / 48;
}
double ypixelstretch = (Level()->info) ? Level()->info->pixelstretch : 1.2;
double ypixelstretch = (Level->info) ? Level->info->pixelstretch : 1.2;
BaseYaspectMul = 320.0 * virtheight2 / (r_Yaspect * virtwidth2);
YaspectMul = 320.0 * virtheight / (r_Yaspect * virtwidth) * ypixelstretch / 1.2;
@ -150,7 +150,7 @@ namespace swrenderer
InitTextureMapping();
// Reset r_*Visibility vars
thread->Light->SetVisibility(this, r_visibility);
thread->Light->SetVisibility(this, r_visibility, !!(Level->flags3 & LEVEL3_NOLIGHTFADE));
SetupBuffer();
}

View file

@ -20,7 +20,7 @@ namespace swrenderer
RenderViewport();
~RenderViewport();
void SetViewport(RenderThread *thread, int width, int height, float trueratio);
void SetViewport(FLevelLocals *Level, RenderThread *thread, int width, int height, float trueratio);
void SetupFreelook();
void SetupPolyViewport(RenderThread *thread);

View file

@ -2106,7 +2106,7 @@ public:
: FxExpression(EFX_Nop, p)
{
isresolved = true;
ValueType = TypeError;
ValueType = TypeVoid;
}
ExpEmit Emit(VMFunctionBuilder *build)
{

View file

@ -2797,9 +2797,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, isFrozen, isFrozen)
void setFrozen(FLevelLocals *self, int on)
{
self->frozenstate = (self->frozenstate & ~1) | !!on;
// For compatibility. The engine itself never checks this.
if (on) self->flags2 |= LEVEL2_FROZEN;
else self->flags2 &= ~LEVEL2_FROZEN;
}
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, setFrozen, setFrozen)
@ -2889,6 +2886,9 @@ DEFINE_FIELD(FLevelLocals, outsidefogdensity)
DEFINE_FIELD(FLevelLocals, skyfog)
DEFINE_FIELD(FLevelLocals, pixelstretch)
DEFINE_FIELD(FLevelLocals, deathsequence)
DEFINE_FIELD_BIT(FLevelLocals, frozenstate, frozen, 1) // still needed for backwards compatibility.
DEFINE_FIELD_NAMED(FLevelLocals, i_compatflags, compatflags)
DEFINE_FIELD_NAMED(FLevelLocals, i_compatflags2, compatflags2)
DEFINE_FIELD_BIT(FLevelLocals, flags, noinventorybar, LEVEL_NOINVENTORYBAR)
DEFINE_FIELD_BIT(FLevelLocals, flags, monsterstelefrag, LEVEL_MONSTERSTELEFRAG)
@ -2901,7 +2901,6 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, checkswitchrange, LEVEL2_CHECKSWITCHRANGE
DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND)
DEFINE_FIELD_BIT(FLevelLocals, flags2, allowrespawn, LEVEL2_ALLOWRESPAWN)
DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS)
DEFINE_FIELD_BIT(FLevelLocals, flags2, frozen, LEVEL2_FROZEN)
DEFINE_FIELD_BIT(FLevelLocals, flags2, infinite_flight, LEVEL2_INFINITE_FLIGHT)
DEFINE_FIELD_BIT(FLevelLocals, flags2, no_dlg_freeze, LEVEL2_CONV_SINGLE_UNFREEZE)
DEFINE_FIELD_BIT(FLevelLocals, flags2, keepfullinventory, LEVEL2_KEEPFULLINVENTORY)

View file

@ -799,9 +799,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearCounters, ClearCounters)
return 0;
}
static int GetModifiedDamage(AActor *self, int type, int damage, bool passive)
static int GetModifiedDamage(AActor *self, int type, int damage, bool passive, AActor *inflictor, AActor *source, int flags)
{
return self->GetModifiedDamage(ENamedName(type), damage, passive);
return self->GetModifiedDamage(ENamedName(type), damage, passive, inflictor, source, flags);
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetModifiedDamage, GetModifiedDamage)
@ -810,7 +810,10 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetModifiedDamage, GetModifiedDamage)
PARAM_NAME(type);
PARAM_INT(damage);
PARAM_BOOL(passive);
ACTION_RETURN_INT(self->GetModifiedDamage(type, damage, passive));
PARAM_OBJECT(inflictor, AActor);
PARAM_OBJECT(source, AActor);
PARAM_INT(flags);
ACTION_RETURN_INT(self->GetModifiedDamage(type, damage, passive, inflictor, source, flags));
}
static int ApplyDamageFactor(AActor *self, int type, int damage)
@ -1666,34 +1669,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, isFrozen, isFrozen)
}
//=====================================================================================
//
// compat flags. These two are the only ones that get checked in script code
// so anything more complex isn't really needed.
//
//=====================================================================================
static int compat_limitpain_(AActor *self)
{
return self->Level->i_compatflags & COMPATF_LIMITPAIN;
}
static int compat_mushroom_(AActor *self)
{
return self->Level->i_compatflags & COMPATF_MUSHROOM;
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, compat_limitpain, compat_limitpain_)
{
PARAM_SELF_PROLOGUE(AActor);
ACTION_RETURN_INT(compat_limitpain_(self));
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, compat_mushroom, compat_mushroom_)
{
PARAM_SELF_PROLOGUE(AActor);
ACTION_RETURN_INT(compat_mushroom_(self));
}
//===========================================================================
//
// PlayerPawn functions

View file

@ -271,7 +271,7 @@ bool DInterBackground::LoadBackground(bool isenterpic)
texture.SetInvalid();
level_info_t * li = FindLevelInfo(wbs->current);
if (li != nullptr) exitpic = li->EnterPic;
if (li != nullptr) exitpic = li->ExitPic;
lumpname = exitpic;
if (isenterpic)

View file

@ -651,7 +651,7 @@ class Actor : Thinker native
native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget);
native Actor RoughMonsterSearch(int distance, bool onlyseekable = false, bool frontonly = false);
native int ApplyDamageFactor(Name damagetype, int damage);
native int GetModifiedDamage(Name damagetype, int damage, bool passive);
native int GetModifiedDamage(Name damagetype, int damage, bool passive, Actor inflictor = null, Actor source = null, int flags = 0);
native bool CheckBossDeath();
void A_Light(int extralight) { if (player) player.extralight = clamp(extralight, -20, 20); }

View file

@ -630,7 +630,7 @@ extend class Actor
Actor mo;
double spawnz = 0;
if (!compat_notossdrops)
if (!(Level.compatflags & COMPATF_NOTOSSDROPS))
{
int style = sv_dropstyle;
if (style == 0)
@ -651,7 +651,7 @@ extend class Actor
{
mo.bDropped = true;
mo.bNoGravity = false; // [RH] Make sure it is affected by gravity
if (!compat_notossdrops)
if (!(Level.compatflags & COMPATF_NOTOSSDROPS))
{
mo.TossItem ();
}

View file

@ -691,6 +691,8 @@ struct LevelLocals native
native readonly int skyfog;
native readonly float pixelstretch;
native name deathsequence;
native readonly int compatflags;
native readonly int compatflags2;
// level_info_t *info cannot be done yet.
native String GetUDMFString(int type, int index, Name key);

View file

@ -1295,3 +1295,47 @@ enum EChangeLevelFlags
CHANGELEVEL_PRERAISEWEAPON = 64,
};
// [RH] Compatibility flags.
enum ECompatFlags
{
COMPATF_SHORTTEX = 1 << 0, // Use Doom's shortest texture around behavior?
COMPATF_STAIRINDEX = 1 << 1, // Don't fix loop index for stair building?
COMPATF_LIMITPAIN = 1 << 2, // Pain elemental is limited to 20 lost souls?
COMPATF_SILENTPICKUP = 1 << 3, // Pickups are only heard locally?
COMPATF_NO_PASSMOBJ = 1 << 4, // Pretend every actor is infinitely tall?
COMPATF_MAGICSILENCE = 1 << 5, // Limit actors to one sound at a time?
COMPATF_WALLRUN = 1 << 6, // Enable buggier wall clipping so players can wallrun?
COMPATF_NOTOSSDROPS = 1 << 7, // Spawn dropped items directly on the floor?
COMPATF_USEBLOCKING = 1 << 8, // Any special line can block a use line
COMPATF_NODOORLIGHT = 1 << 9, // Don't do the BOOM local door light effect
COMPATF_RAVENSCROLL = 1 << 10, // Raven's scrollers use their original carrying speed
COMPATF_SOUNDTARGET = 1 << 11, // Use sector based sound target code.
COMPATF_DEHHEALTH = 1 << 12, // Limit deh.MaxHealth to the health bonus (as in Doom2.exe)
COMPATF_TRACE = 1 << 13, // Trace ignores lines with the same sector on both sides
COMPATF_DROPOFF = 1 << 14, // Monsters cannot move when hanging over a dropoff
COMPATF_BOOMSCROLL = 1 << 15, // Scrolling sectors are additive like in Boom
COMPATF_INVISIBILITY = 1 << 16, // Monsters can see semi-invisible players
COMPATF_SILENT_INSTANT_FLOORS = 1<<17, // Instantly moving floors are not silent
COMPATF_SECTORSOUNDS = 1 << 18, // Sector sounds use original method for sound origin.
COMPATF_MISSILECLIP = 1 << 19, // Use original Doom heights for clipping against projectiles
COMPATF_CROSSDROPOFF = 1 << 20, // monsters can't be pushed over dropoffs
COMPATF_ANYBOSSDEATH = 1 << 21, // [GZ] Any monster which calls BOSSDEATH counts for level specials
COMPATF_MINOTAUR = 1 << 22, // Minotaur's floor flame is exploded immediately when feet are clipped
COMPATF_MUSHROOM = 1 << 23, // Force original velocity calculations for A_Mushroom in Dehacked mods.
COMPATF_MBFMONSTERMOVE = 1 << 24, // Monsters are affected by friction and pushers/pullers.
COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs.
COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines.
COMPATF_SPRITESORT = 1 << 27, // Invert sprite sorting order for sprites of equal distance
COMPATF_HITSCAN = 1 << 28, // Hitscans use original blockmap anf hit check code.
COMPATF_LIGHT = 1 << 29, // Find neighboring light level like Doom
COMPATF_POLYOBJ = 1 << 30, // Draw polyobjects the old fashioned way
COMPATF_MASKEDMIDTEX = 1 << 31, // Ignore compositing when drawing masked midtextures
COMPATF2_BADANGLES = 1 << 0, // It is impossible to face directly NSEW.
COMPATF2_FLOORMOVE = 1 << 1, // Use the same floor motion behavior as Doom.
COMPATF2_SOUNDCUTOFF = 1 << 2, // Cut off sounds when an actor vanishes instead of making it owner-less
COMPATF2_POINTONLINE = 1 << 3, // Use original but buggy P_PointOnLineSide() and P_PointOnDivlineSideCompat()
COMPATF2_MULTIEXIT = 1 << 4, // Level exit can be triggered multiple times (required by Daedalus's travel tubes, thanks to a faulty script)
COMPATF2_TELEPORT = 1 << 5, // Don't let indirect teleports trigger sector actions
COMPATF2_PUSHWINDOW = 1 << 6, // Disable the window check in CheckForPushSpecial()
};

View file

@ -105,8 +105,6 @@ extend class Actor
{
const FATSPREAD = 90./8;
private native bool compat_mushroom();
void A_FatRaise()
{
A_FaceTarget();
@ -196,7 +194,7 @@ extend class Actor
aimtarget.Height = Height;
bool shootmode = ((flags & MSF_Classic) || // Flag explicitly set, or no flags and compat options
(flags == 0 && CurState.bDehacked && compat_mushroom()));
(flags == 0 && CurState.bDehacked && (Level.compatflags & COMPATF_MUSHROOM)));
for (i = -numspawns; i <= numspawns; i += 8)
{

View file

@ -62,8 +62,6 @@ class PainElemental : Actor
extend class Actor
{
private native bool compat_limitpain();
//
// A_PainShootSkull
// Spawn a lost soul and launch it at the target
@ -88,7 +86,7 @@ extend class Actor
}
// [RH] make this optional
if (limit < 0 && compat_limitpain())
if (limit < 0 && (Level.compatflags & COMPATF_LIMITPAIN))
limit = 21;
if (limit > 0)

View file

@ -1002,7 +1002,7 @@ class Inventory : Actor
//
//===========================================================================
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive, Actor inflictor = null, Actor source = null, int flags = 0) {}
virtual bool Use (bool pickup) { return false; }

View file

@ -1655,7 +1655,7 @@ class PowerDamage : Powerup
//
//===========================================================================
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive)
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags)
{
if (!passive && damage > 0)
{
@ -1749,7 +1749,7 @@ class PowerProtection : Powerup
//
//===========================================================================
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive)
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags)
{
if (passive && damage > 0)
{

View file

@ -217,7 +217,7 @@ class StateProvider : Inventory
// Temporarily adjusts the pitch
double saved_player_pitch = self.Pitch;
self.Pitch += pitch;
let misl = SpawnPlayerMissile (missiletype, shootangle, ofs.X, ofs.Y, spawnheight, t, NULL, false, (flags & FPF_NOAUTOAIM) != 0);
let misl = SpawnPlayerMissile (missiletype, shootangle, ofs.X, ofs.Y, spawnheight, t, false, (flags & FPF_NOAUTOAIM) != 0);
self.Pitch = saved_player_pitch;
// automatic handling of seeker missiles

View file

@ -373,6 +373,7 @@ class LevelCompatibility native play
SetWallTexture(1027, Line.back, Side.top, "SP_HOT1");
// Replace tag for eastern secret at level start to not
// cause any action to the two-Baron trap
ClearSectorTags(127);
AddSectorTag(127, 100);
SetLineSpecial(382, Door_Open, 100, 16);
SetLineSpecial(388, Door_Open, 100, 16);
@ -997,7 +998,7 @@ class LevelCompatibility native play
SetLineSectorRef(328, Line.front, 74);
SetLineSectorRef(329, Line.front, 74);
AddSectorTag(74, 4);
SetLineSpecial(357, Transfer_Heights, 6);
SetLineSpecial(357, Transfer_Heights, 4, 6);
break;
}
@ -1220,6 +1221,15 @@ class LevelCompatibility native play
// Fix the soulsphere in a secret area (sector 324)
// so that it doesn't end up in an unreachable position.
SetThingXY(516, -934, 48);
break;
}
case '11EA5B8357DEB70A8F00900117831191': // kdizd_12.pk3 z1m3
{
// Fix incorrectly tagged underwater sector which causes render glitches.
ClearSectorTags(7857);
AddSectorTag(7857, 82);
break;
}
}
}

View file

@ -347,7 +347,7 @@ class Minotaur : Actor
}
else
{
if (Floorclip > 0 && compat_minotaur)
if (Floorclip > 0 && (Level.compatflags & COMPAT_MINOTAUR))
{
// only play the sound.
A_PlaySound ("minotaur/fx2hit", CHAN_WEAPON);

View file

@ -1930,7 +1930,7 @@ class PlayerPawn : Actor
override int GetMaxHealth(bool withupgrades) const
{
int ret = MaxHealth > 0? MaxHealth : (compat_dehhealth? 100 : deh.MaxHealth);
int ret = MaxHealth > 0? MaxHealth : ((Level.compatflags & COMPATF_DEHHEALTH)? 100 : deh.MaxHealth);
if (withupgrades) ret += stamina + BonusHealth;
return ret;
}