diff --git a/Build/Compilers/ZDoom/zdefs.acs b/Build/Compilers/ZDoom/zdefs.acs index 3a32219d..f3825364 100644 --- a/Build/Compilers/ZDoom/zdefs.acs +++ b/Build/Compilers/ZDoom/zdefs.acs @@ -691,6 +691,9 @@ #define CHAN_VOICE 2 #define CHAN_ITEM 3 #define CHAN_BODY 4 +#define CHAN_5 5 +#define CHAN_6 6 +#define CHAN_7 7 // Modifier flags for PlaySound @@ -1042,3 +1045,10 @@ #define ML_BLOCKUSE 0x02000000 #define ML_BLOCKSIGHT 0x04000000 #define ML_BLOCKHITSCAN 0x08000000 + +#define QF_RELATIVE 1 +#define QF_SCALEDOWN 1 << 1 +#define QF_SCALEUP 1 << 2 +#define QF_MAX 1 << 3 +#define QF_FULLINTENSITY 1 << 4 +#define QF_WAVE 1 << 5 diff --git a/Build/Compilers/ZDoom/zspecial.acs b/Build/Compilers/ZDoom/zspecial.acs index 169d58ac..abea6e1a 100644 --- a/Build/Compilers/ZDoom/zspecial.acs +++ b/Build/Compilers/ZDoom/zspecial.acs @@ -334,7 +334,8 @@ special -88:SetActorRoll(2), -89:ChangeActorRoll(2,3), -90:GetActorRoll(1), - + -91:QuakeEx(8,12), + // Zandronum's -100:ResetMap(0), -101:PlayerIsSpectator(1), diff --git a/Build/Scripting/ZDoom_ACS.cfg b/Build/Scripting/ZDoom_ACS.cfg index e36d2cab..5eb1aa34 100644 --- a/Build/Scripting/ZDoom_ACS.cfg +++ b/Build/Scripting/ZDoom_ACS.cfg @@ -318,6 +318,7 @@ keywords PolyWait = "void PolyWait(int polyid)"; Print = "void Print(type:expression)\nPrint will print something to the screen.\nPrint will only display for the activator of the script\nFor printing to all players, use PrintBold."; PrintBold = "void PrintBold(type:expression)\nThis is exactly the same as Print, except all players will see the printed text\non the screen instead of just the activator of the script."; + QuakeEx = "void QuakeEx(int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, str sound[, int flags = 0[, float mulwavex = 1.0[, float mulwavey = 1.0[, float mulwavez = 1.0]]]])"; Radius_Quake = "Radius_Quake(intensity, duration, damrad, tremrad, tid)"; Radius_Quake2 = "void Radius_Quake2(int tid, int intensity, int duration, int damrad, int tremrad, str sound)"; Random = "int Random(int min, int max)"; @@ -869,6 +870,12 @@ constants PTROP_NOSAFEGUARDS; PTROP_UNSAFEMASTER; PTROP_UNSAFETARGET; + QF_RELATIVE; + QF_SCALEDOWN; + QF_SCALEUP; + QF_MAX; + QF_FULLINTENSITY; + QF_WAVE; SCROLL; SCROLL_AND_CARRY; SDF_ABSANGLE; diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg index 738513f4..3b5a939b 100644 --- a/Build/Scripting/ZDoom_DECORATE.cfg +++ b/Build/Scripting/ZDoom_DECORATE.cfg @@ -20,7 +20,7 @@ keywords { #Include = "#Include"; //Monster AI - A_AlertMonsters = "A_AlertMonsters[(float maxrange = 0[, int flags = 0])]"; + A_AlertMonsters = "A_AlertMonsters[(float maxrange = 0.0[, int flags = 0])]"; A_Burst = "A_Burst(str type)"; A_CentaurDefend = "A_CentaurDefend"; A_Chase = "A_Chase[(str meleestate = \"Melee\"[, str rangedstate = \"Missile\"[, int flags = 0]])]"; @@ -34,8 +34,8 @@ keywords A_DamageTarget = "A_DamageTarget(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage."; A_DamageTracer = "A_DamageTracer(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage."; A_Die = "A_Die[(str damagetype)]"; - A_FaceTarget = "A_FaceTarget[(float angle = 0[, float pitch = 0])]\nA_FaceTarget(float max_turn, float max_pitch, float ang_offset, float pitch_offset, int flags)"; - A_FaceMaster = "A_FaceMaster[(float angle = 0[, float pitch = 0])]\nA_FaceMaster(float max_turn, float max_pitch, float ang_offset, float pitch_offset, int flags)"; + A_FaceTarget = "A_FaceTarget[(float angle = 0.0[, float pitch = 0.0])]\nA_FaceTarget(float max_turn, float max_pitch, float ang_offset, float pitch_offset, int flags)"; + A_FaceMaster = "A_FaceMaster[(float angle = 0.0[, float pitch = 0.0])]\nA_FaceMaster(float max_turn, float max_pitch, float ang_offset, float pitch_offset, int flags)"; A_FastChase = "A_FastChase"; A_KillChildren = "A_KillChildren[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\[, str species = \"None\]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage."; A_KillMaster = "A_KillMaster[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage."; @@ -59,12 +59,12 @@ keywords A_Srcr2Decide = "A_Srcr2Decide"; A_SwapTeleFog = "A_SwapTeleFog"; A_TurretLook = "A_TurretLook"; - A_Teleport = "A_Teleport[(str teleportstate = \"Teleport\"[, str targettype = \"BossSpot\"[, str fogtype = \"TeleportFog\"[, int flags = 0[, float mindist = 0[, float maxdist = 0]]]]])]"; + A_Teleport = "A_Teleport[(str teleportstate = \"Teleport\"[, str targettype = \"BossSpot\"[, str fogtype = \"TeleportFog\"[, int flags = 0[, float mindist = 0.0[, float maxdist = 0.0]]]]])]"; A_VileChase = "A_VileChase"; A_Wander = "A_Wander"; //Generic monster attacks - A_CustomMissile = "A_CustomMissile(str missiletype[, float spawnheight = 0[, int spawnofs_horiz = 0[, int angle = 0[, int aimflags = 0[, int pitch = 0[, int target = AAPTR_TARGET]]]]]])"; - A_CustomBulletAttack = "A_CustomBulletAttack(float horz_spread, float vert_spread, int numbullets, int damageperbullet[, str pufftype = \"BulletPuff\"[, float range = 0[, int flags = 0[, int target = AAPTR_TARGET]]]])"; + A_CustomMissile = "A_CustomMissile(str missiletype[, float spawnheight = 0.0[, int spawnofs_horiz = 0[, int angle = 0[, int aimflags = 0[, int pitch = 0[, int target = AAPTR_TARGET]]]]]])"; + A_CustomBulletAttack = "A_CustomBulletAttack(float horz_spread, float vert_spread, int numbullets, int damageperbullet[, str pufftype = \"BulletPuff\"[, float range = 0.0[, int flags = 0[, int target = AAPTR_TARGET]]]])"; A_CustomRailgun = "A_CustomRailgun(int damage[, int offset[, color ringcolor[, color corecolor[, int flags[, bool aim[, float maxdiff[, str pufftype[, float spread_xy[, float spread_z[, fixed range[, int duration[, float sparsity[, float driftspeed[, str spawnclass[, float spawnofs_z]]]]]]]]]]]]]]])"; A_CustomMeleeAttack = "A_CustomMeleeAttack(int damage[, str meleesound[, str misssound[, str damagetype[, bool bleed]]]])"; A_CustomComboAttack = "A_CustomComboAttack(str missiletype, float spawnheight, int damage, str meleesound[, str damagetype = \"Melee\"[, bool bleed = true]])"; @@ -83,7 +83,7 @@ keywords A_FreezeDeathChunks = "A_FreezeDeathChunks"; A_IceGuyDie = "A_IceGuyDie"; //Sound functions - A_PlaySound = "A_PlaySound(str soundname[, int slot[, float volume = 1.0[, bool looping = false[, float attenuation]]]])"; + A_PlaySound = "A_PlaySound(str soundname[, int slot = CHAN_BODY[, float volume = 1.0[, bool looping = false[, float attenuation = ATTN_NORM]]]])"; A_PlayWeaponSound = "A_PlayWeaponSound(str soundname)"; A_ActiveSound = "A_ActiveSound"; A_LoopActiveSound = "A_LoopActiveSound"; @@ -114,17 +114,17 @@ keywords A_PlayerSkinCheck = "A_PlayerSkinCheck(str state)"; A_SkullPop = "A_SkullPop[(str type = \"BloodySkull\")]"; A_Quake = "A_Quake(int intensity, int duration, int damageradius, int tremorradius[, str sound = \"world/quake\"])"; - A_QuakeEx = "A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad[, str sound = \"world/quake\"[, int flags = 0[, float mulwavex = 1[, float mulwavey = 1[, float mulwavez = 1]]]]])"; + A_QuakeEx = "A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad[, str sound = \"world/quake\"[, int flags = 0[, float mulwavex = 1.0[, float mulwavey = 1.0[, float mulwavez = 1.0]]]]])"; //Spawn functions A_TossGib = "A_TossGib"; A_SpawnDebris = "A_SpawnDebris(str type[, bool translation = false[, float horizontal_vel = 1.0[, float vertical_vel = 1.0]]])"; A_SpawnItem = "A_SpawnItem(str type, int distance, float zpos, bool useammo, bool translation)"; - A_SpawnItemEx = "A_SpawnItemEx(str type[, float xoffset = 0[, float yoffset = 0[, float zoffset = 0[, float xvelocity = 0[, float yvelocity = 0[, float zvelocity = 0[, float angle = 0[, int flags = 0[, int skipchance = 0[, int tid = 0]]]]]]]]]])"; + A_SpawnItemEx = "A_SpawnItemEx(str type[, float xoffset = 0.0[, float yoffset = 0.0[, float zoffset = 0.0[, float xvelocity = 0.0[, float yvelocity = 0.0[, float zvelocity = 0.0[, float angle = 0.0[, int flags = 0[, int skipchance = 0[, int tid = 0]]]]]]]]]])"; //State jumps A_CheckCeiling = "A_CheckCeiling(int offset OR str state)"; A_CheckFloor = "A_CheckFloor(int offset OR str state)"; A_CheckFlag = "A_CheckFlag(str flagname, state label[, int check_pointer = AAPTR_DEFAULT])"; - A_CheckLOF = "A_CheckLOF(state jump[, int flags = 0[, float range = 0[, float minrange = 0[, float angle = 0[, float pitch = 0[, float offsetheight = 0[, float offsetwidth = 0[, int ptr_target = AAPTR_DEFAULT]]]]]]]])"; + A_CheckLOF = "A_CheckLOF(state jump[, int flags = 0[, float range = 0.0[, float minrange = 0.0[, float angle = 0.0[, float pitch = 0.0[, float offsetheight = 0.0[, float offsetwidth = 0.0[, int ptr_target = AAPTR_DEFAULT]]]]]]]])"; A_CheckRange = "A_CheckRange(float distance, int offset OR str state)"; A_CheckSight = "A_CheckSight(int offset OR str state)"; A_CheckSightOrRange = "A_CheckSightOrRange(float distance, int offset OR str state)"; @@ -135,10 +135,10 @@ keywords A_JumpIfHealthLower = "A_JumpIfHealthLower(int health, int offset OR str state[, int pointer = AAPTR_DEFAULT])"; A_JumpIfInventory = "A_JumpIfInventory(str inventorytype, int amount, int offset OR str state[, int owner = AAPTR_DEFAULT])"; A_JumpIfInTargetInventory = "A_JumpIfInTargetInventory(str item, int count, int offset OR str state[, int forward])"; - A_JumpIfInTargetLOS = "A_JumpIfInTargetLOS(int offset OR str state[, float fov = 0[, int flags = 0[, float dist_max = 0[, float dist_close = 0]]]])\nflags: JLOSF flags."; + A_JumpIfInTargetLOS = "A_JumpIfInTargetLOS(int offset OR str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags."; A_JumpIfMasterCloser = "A_JumpIfMasterCloser(int distance, int offset OR str state)"; A_JumpIfNoAmmo = "A_JumpIfNoAmmo(int offset OR str state)"; - A_JumpIfTargetInLOS = "A_JumpIfTargetInLOS(int offset OR str state[, float fov = 0[, int flags = 0[, float dist_max = 0[, float dist_close = 0]]]])\nflags: JLOSF flags."; + A_JumpIfTargetInLOS = "A_JumpIfTargetInLOS(int offset OR str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags."; A_JumpIfTargetInsideMeleeRange = "A_JumpIfTargetInsideMeleeRange(int offset OR str state)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is within melee range of the caller."; A_JumpIfTargetOutsideMeleeRange = "A_JumpIfTargetOutsideMeleeRange(int offset OR str state)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is beyond melee range of the caller."; A_JumpIfTracerCloser = "A_JumpIfTracerCloser(int distance, int offset OR str state)"; @@ -146,7 +146,7 @@ keywords A_ActiveAndUnblock = "A_ActiveAndUnblock"; A_CallSpecial = "A_CallSpecial(int special[, int arg1[, int arg2[, int arg3[, int arg4[, int arg5]]]]])"; A_ChangeFlag = "A_ChangeFlag(str flagname, bool value)"; - A_ChangeVelocity = "A_ChangeVelocity[(float x = 0[, float y = 0[, float z = 0[, int flags = 0[, int pointer = AAPTR_DEFAULT]]]])]\nflags: CVF flags."; + A_ChangeVelocity = "A_ChangeVelocity[(float x = 0.0[, float y = 0.0[, float z = 0.0[, int flags = 0[, int pointer = AAPTR_DEFAULT]]]])]\nflags: CVF flags."; A_ClearShadow = "A_ClearShadow"; A_CopyFriendliness = "A_CopyFriendliness[(int copyfrom = AAPTR_MASTER)]"; A_DeQueueCorpse = "A_DeQueueCorpse"; @@ -200,8 +200,8 @@ keywords A_SeekerMissile = "A_SeekerMissile(angle threshold, angle maxturnangle[, int flags = 0[, int chance = 50[, int distance = 10]]])\nflags: SMF flags."; A_Tracer = "A_Tracer"; A_Tracer2 = "A_Tracer2"; - A_FaceTracer = "A_FaceTracer[(float angle = 0[, float pitch = 0])]\nA_FaceTracer(float max_turn, float max_pitch, float ang_offset, float pitch_offset, int flags)"; - A_Fire = "A_Fire[(float height = 0)]"; + A_FaceTracer = "A_FaceTracer[(float angle = 0.0[, float pitch = 0.0])]\nA_FaceTracer(float max_turn, float max_pitch, float ang_offset, float pitch_offset, int flags)"; + A_Fire = "A_Fire[(float height = 0.0)]"; A_Weave = "A_Weave(int horzspeed, int vertspeed, float horzdist, float vertdist)"; A_Warp = "A_Warp(int ptr_destination, float x-offset, float y-offset, float z-offset, float angle, int flags, str success_state)\nflags: WARPF flags."; A_Countdown = "A_Countdown"; @@ -240,11 +240,11 @@ keywords A_SetCrosshair = "A_SetCrosshair(int number)"; //Weapon attack functions A_Punch = "A_Punch"; - A_Saw = "A_Saw[(str fullsound = \"weapons/sawfull\"[, str hitsound = \"weapons/sawhit\"[, int damage = 0[, str pufftype = \"BulletPuff\"[, int flags = 0[, float range = 65.0[, float spread_xy = 2.8125[, float spread_z = 0[, float lifesteal = 0[, int lifestealmax = 0[, str armorbonustype = \"ArmorBonus\"]]]]]]]]]])]"; - A_CustomPunch = "A_CustomPunch(int damage[, bool norandom = false[, int flags = 0[, str pufftype = \"BulletPuff\"[, float range = 64.0[, float lifesteal = 0[, int lifestealmax = 0[, str armorbonustype = \"ArmorBonus\"]]]]]]])"; - A_FireBullets = "A_FireBullets(int spread_horz, int spread_vert, int numbullets, int damage[, str pufftype = \"\"[, int flags = FBF_USEAMMO[, float range = 0]]])"; + A_Saw = "A_Saw[(str fullsound = \"weapons/sawfull\"[, str hitsound = \"weapons/sawhit\"[, int damage = 0[, str pufftype = \"BulletPuff\"[, int flags = 0[, float range = 65.0[, float spread_xy = 2.8125[, float spread_z = 0.0[, float lifesteal = 0.0[, int lifestealmax = 0[, str armorbonustype = \"ArmorBonus\"]]]]]]]]]])]"; + A_CustomPunch = "A_CustomPunch(int damage[, bool norandom = false[, int flags = 0[, str pufftype = \"BulletPuff\"[, float range = 64.0[, float lifesteal = 0.0[, int lifestealmax = 0[, str armorbonustype = \"ArmorBonus\"]]]]]]])"; + A_FireBullets = "A_FireBullets(int spread_horz, int spread_vert, int numbullets, int damage[, str pufftype = \"\"[, int flags = FBF_USEAMMO[, float range = 0.0]]])"; A_FireCustomMissile = "A_FireCustomMissile(str missiletype[, int angle = 0[, bool useammo = false[, int spawnofs_horz = 0[, int spawnheight = 0[, bool aim = false OR int flags = 0[, angle pitch = 0]]]]]])"; - A_RailAttack = "A_RailAttack(int damage[, int spawnofs_horz[, bool useammo[, color ringcolor[, color corecolor[, int flags[, int maxdiff[, str pufftype[, float spread_xy = 0[, float spread_z = 0[, fixed range = 8192[, int duration = 35[, float sparsity = 1.0[, float driftspeed = 1.0[, str spawnclass[, float spawnofs_z = 0]]]]]]]]]]]]]]])"; + A_RailAttack = "A_RailAttack(int damage[, int spawnofs_horz[, bool useammo[, color ringcolor[, color corecolor[, int flags[, int maxdiff[, str pufftype[, float spread_xy = 0[, float spread_z = 0.0[, fixed range = 8192[, int duration = 35[, float sparsity = 1.0[, float driftspeed = 1.0[, str spawnclass[, float spawnofs_z = 0.0]]]]]]]]]]]]]]])"; A_FireAssaultGun = "A_FireAssaultGun"; A_FireBFG = "A_FireBFG"; A_FireOldBFG = "A_FireOldBFG"; @@ -276,7 +276,7 @@ keywords A_SkullAttack = "A_SkullAttack[(int speed = 20)]"; A_BspiAttack = "A_BspiAttack"; A_CyberAttack = "A_CyberAttack"; - A_PainAttack = "A_PainAttack[(str spawntype = \"LostSoul\"[, float angle = 0[, int flags = 0[, int limit = 21]]])]"; + A_PainAttack = "A_PainAttack[(str spawntype = \"LostSoul\"[, float angle = 0.0[, int flags = 0[, int limit = 21]]])]"; A_DualPainAttack = "A_DualPainAttack[(str spawntype = \"LostSoul\")]"; A_PainDie = "A_PainDie[(str spawntype = \"LostSoul\")]"; A_SkelFist = "A_SkelFist"; @@ -303,11 +303,11 @@ keywords A_SkelWhoosh = "A_SkelWhoosh"; A_StartFire = "A_StartFire"; A_FireCrackle = "A_FireCrackle"; - A_BFGSpray = "A_BFGSpray[(str flashtype = \"BFGExtra\"[, int numrays = 40[, int damage = 15[, float angle = 90[, float distance = 1024[, float vrange = 32[, int explicit_damage = 0]]]]]])]"; + A_BFGSpray = "A_BFGSpray[(str flashtype = \"BFGExtra\"[, int numrays = 40[, int damage = 15[, float angle = 90.0[, float distance = 1024.0[, float vrange = 32.0[, int explicit_damage = 0]]]]]])]"; A_BarrelDestroy = "A_BarrelDestroy"; //Miscellaneous functions not listed in the "Action functions" wiki article A_Bang4Cloud = "A_Bang4Cloud"; - A_Blast = "A_Blast[(int flags = 0[, int strength = 255[, int radius = 255[, float speed = 20[, str blasteffect = \"BlastEffect\"[, sound blastsound = \"BlastRadius\"]]]]])]"; + A_Blast = "A_Blast[(int flags = 0[, int strength = 255[, int radius = 255[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, sound blastsound = \"BlastRadius\"]]]]])]"; A_DropWeaponPieces = "A_DropWeaponPieces(str actorclass1, str actorclass2, str actorclass3)"; A_Feathers = "A_Feathers"; A_GauntletAttack = "A_GauntletAttack(int power)"; diff --git a/Source/Core/Map/Sidedef.cs b/Source/Core/Map/Sidedef.cs index ea91178b..405bf96f 100644 --- a/Source/Core/Map/Sidedef.cs +++ b/Source/Core/Map/Sidedef.cs @@ -365,7 +365,8 @@ namespace CodeImp.DoomBuilder.Map if(!LowRequired()) { - if(!changed) { //mxd + if(!changed) //mxd + { BeforePropsChange(); changed = true; } @@ -398,6 +399,44 @@ namespace CodeImp.DoomBuilder.Map // Doublesided? if(Other != null) { + //mxd. Check sloped ceilings... + if(General.Map.UDMF && this.sector != Other.Sector) + { + float thisstartz = this.sector.CeilHeight; + float thisendz = this.sector.CeilHeight; + float otherstartz = Other.sector.CeilHeight; + float otherendz = Other.sector.CeilHeight; + + // Check if this side is affected by UDMF slope (it overrides vertex heights, riiiiiight?..) TODO: check this! + if(this.sector.CeilSlope.GetLengthSq() > 0) + { + Plane ceil = new Plane(this.sector.CeilSlope, this.sector.CeilSlopeOffset); + thisstartz = ceil.GetZ(this.Line.Start.Position); + thisendz = ceil.GetZ(this.Line.End.Position); + } + else if(this.sector.Sidedefs.Count == 3) // Check vertex heights on this side + { + if(!float.IsNaN(this.Line.Start.ZCeiling)) thisstartz = this.Line.Start.ZCeiling; + if(!float.IsNaN(this.Line.End.ZCeiling)) thisendz = this.Line.End.ZCeiling; + } + + // Check if other side is affected by UDMF slope (it overrides vertex heights, riiiiiight?..) TODO: check this! + if(Other.sector.CeilSlope.GetLengthSq() > 0) + { + Plane ceil = new Plane(Other.sector.CeilSlope, Other.sector.CeilSlopeOffset); + otherstartz = ceil.GetZ(this.Line.Start.Position); + otherendz = ceil.GetZ(this.Line.End.Position); + } + else if(Other.sector.Sidedefs.Count == 3) // Check other line's vertex heights + { + if(!float.IsNaN(this.Line.Start.ZCeiling)) otherstartz = this.Line.Start.ZCeiling; + if(!float.IsNaN(this.Line.End.ZCeiling)) otherendz = this.Line.End.ZCeiling; + } + + // Texture is required when our start or end vertex is higher than on the other side. + if(thisstartz > otherstartz || thisendz > otherendz) return true; + } + // Texture is required when ceiling of other side is lower return (Other.sector.CeilHeight < this.sector.CeilHeight); } @@ -422,6 +461,44 @@ namespace CodeImp.DoomBuilder.Map // Doublesided? if(Other != null) { + //mxd. Check sloped floors... + if(General.Map.UDMF && this.sector != Other.Sector) + { + float thisstartz = this.sector.FloorHeight; + float thisendz = this.sector.FloorHeight; + float otherstartz = Other.sector.FloorHeight; + float otherendz = Other.sector.FloorHeight; + + // Check if this side is affected by UDMF slope (it overrides vertex heights, riiiiiight?..) TODO: check this! + if(this.sector.FloorSlope.GetLengthSq() > 0) + { + Plane floor = new Plane(this.sector.FloorSlope, this.sector.FloorSlopeOffset); + thisstartz = floor.GetZ(this.Line.Start.Position); + thisendz = floor.GetZ(this.Line.End.Position); + } + else if(this.sector.Sidedefs.Count == 3) // Check vertex heights on this side + { + if(!float.IsNaN(this.Line.Start.ZFloor)) thisstartz = this.Line.Start.ZFloor; + if(!float.IsNaN(this.Line.End.ZFloor)) thisendz = this.Line.End.ZFloor; + } + + // Check if other side is affected by UDMF slope (it overrides vertex heights, riiiiiight?..) TODO: check this! + if(Other.sector.FloorSlope.GetLengthSq() > 0) + { + Plane floor = new Plane(Other.sector.FloorSlope, Other.sector.FloorSlopeOffset); + otherstartz = floor.GetZ(this.Line.Start.Position); + otherendz = floor.GetZ(this.Line.End.Position); + } + else if(Other.sector.Sidedefs.Count == 3) // Check other line's vertex heights + { + if(!float.IsNaN(this.Line.Start.ZFloor)) otherstartz = this.Line.Start.ZFloor; + if(!float.IsNaN(this.Line.End.ZFloor)) otherendz = this.Line.End.ZFloor; + } + + // Texture is required when our start or end vertex is lower than on the other side. + if(thisstartz < otherstartz || thisendz < otherendz) return true; + } + // Texture is required when floor of other side is higher return (Other.sector.FloorHeight > this.sector.FloorHeight); }