UltimateZoneBuilder/Source/Core/GZBuilder/GZGeneral.cs

390 lines
No EOL
17 KiB
C#
Executable file

#region ================== Namespaces
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.ZDoom;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
#endregion
namespace CodeImp.DoomBuilder.GZBuilder
{
//mxd. should get rid of this class one day...
public static class GZGeneral
{
#region ================== Properties
//gzdoom light types
public class LightDefNum : Attribute
{
public int[] DoomEdNums { get; private set; }
public LightDefNum(params int[] doomEdNums)
{
DoomEdNums = doomEdNums;
}
}
public class LightDefClass : Attribute
{
public string[] Classes { get; private set; }
public LightDefClass(params string[] clses)
{
Classes = clses;
}
}
public class LightDefModifier : Attribute
{
public LightModifier[] Modifiers { get; private set; }
public LightDefModifier(params LightModifier[] mods)
{
Modifiers = mods;
}
}
public class LightDefRenderStyle : Attribute
{
public LightRenderStyle RenderStyle { get; private set; }
public LightDefRenderStyle(LightRenderStyle rs)
{
RenderStyle = rs;
}
}
public enum LightDef
{
[LightDefRenderStyle(LightRenderStyle.NORMAL)]
[LightDefNum(9800, 9801, 9802, 9803, 9804)]
[LightDefClass("pointlight", "pointlightpulse", "pointlightflicker", "sectorpointlight", "pointlightflickerrandom")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
POINT_NORMAL,
[LightDefRenderStyle(LightRenderStyle.ADDITIVE)]
[LightDefNum(9810, 9811, 9812, 9813, 9814)]
[LightDefClass("pointlightadditive", "pointlightpulseadditive", "pointlightflickeradditive", "sectorpointlightadditive", "pointlightflickerrandomadditive")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
POINT_ADDITIVE,
[LightDefRenderStyle(LightRenderStyle.SUBTRACTIVE)]
[LightDefNum(9820, 9821, 9822, 9823, 9824)]
[LightDefClass("pointlightsubtractive", "pointlightpulsesubtractive", "pointlightflickersubtractive", "sectorpointlightsubtractive", "pointlightflickerrandomsubtractive")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
POINT_SUBTRACTIVE,
[LightDefRenderStyle(LightRenderStyle.ATTENUATED)]
[LightDefNum(9830, 9831, 9832, 9833, 9834)]
[LightDefClass("pointlightattenuated", "pointlightpulseattenuated", "pointlightflickerattenuated", "sectorpointlightattenuated", "pointlightflickerrandomattenuated")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
POINT_ATTENUATED,
[LightDefRenderStyle(LightRenderStyle.NORMAL)]
[LightDefNum(9840, 9841, 9842, 9843, 8944)]
[LightDefClass("spotlight", "spotlightpulse", "spotlightflicker", "sectorspotlight", "spotlightflickerrandom")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
SPOT_NORMAL,
[LightDefRenderStyle(LightRenderStyle.ADDITIVE)]
[LightDefNum(9850, 9851, 9852, 9853, 8954)]
[LightDefClass("spotlightadditive", "spotlightpulseadditive", "spotlightflickeradditive", "sectorspotlightadditive", "spotlightflickerrandomadditive")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
SPOT_ADDITIVE,
[LightDefRenderStyle(LightRenderStyle.SUBTRACTIVE)]
[LightDefNum(9860, 9861, 9862, 9863, 8964)]
[LightDefClass("spotlightsubtractive", "spotlightpulsesubtractive", "spotlightflickersubtractive", "sectorspotlightsubtractive", "spotlightflickerrandomsubtractive")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
SPOT_SUBTRACTIVE,
[LightDefRenderStyle(LightRenderStyle.ATTENUATED)]
[LightDefNum(9870, 9871, 9872, 9873, 8974)]
[LightDefClass("spotlightattenuated", "spotlightpulseattenuated", "spotlightflickerattenuated", "sectorspotlightattenuated", "spotlightflickerrandomattenuated")]
[LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)]
SPOT_ATTENUATED,
[LightDefRenderStyle(LightRenderStyle.VAVOOM)]
[LightDefNum(1502)]
[LightDefClass("vavoomlightwhite")]
VAVOOM_GENERIC,
[LightDefRenderStyle(LightRenderStyle.VAVOOM)]
[LightDefNum(1503)]
[LightDefClass("vavoomlightcolor")]
VAVOOM_COLORED,
UNKNOWN
}
// divide these by 100 to get light color alpha
// this, sadly, has to duplicate the enum in GZGeneral because it's shader-specific
public enum LightRenderStyle
{
SUBTRACTIVE = 100,
NORMAL = 99,
ATTENUATED = 98,
VAVOOM = 50,
ADDITIVE = 25,
NONE = 0,
}
public enum LightModifier
{
NORMAL,
PULSE,
FLICKER,
SECTOR,
FLICKERRANDOM
}
public enum LightType
{
POINT,
SPOT,
VAVOOM
}
public static LightDefNum GetLightDefNum(LightDef d)
{
FieldInfo fi = typeof(LightDef).GetField(d.ToString());
LightDefNum[] attrs = (LightDefNum[])fi.GetCustomAttributes(typeof(LightDefNum), false);
if (attrs.Length != 0)
return attrs[0];
return null;
}
public static LightDefClass GetLightDefClass(LightDef d)
{
FieldInfo fi = typeof(LightDef).GetField(d.ToString());
LightDefClass[] attrs = (LightDefClass[])fi.GetCustomAttributes(typeof(LightDefClass), false);
if (attrs.Length != 0)
return attrs[0];
return null;
}
public static LightDefModifier GetLightDefModifier(LightDef d)
{
FieldInfo fi = typeof(LightDef).GetField(d.ToString());
LightDefModifier[] attrs = (LightDefModifier[])fi.GetCustomAttributes(typeof(LightDefModifier), false);
if (attrs.Length != 0)
return attrs[0];
return null;
}
public static LightDefRenderStyle GetLightDefRenderStyle(LightDef d)
{
FieldInfo fi = typeof(LightDef).GetField(d.ToString());
LightDefRenderStyle[] attrs = (LightDefRenderStyle[])fi.GetCustomAttributes(typeof(LightDefRenderStyle), false);
if (attrs.Length != 0)
return attrs[0];
return null;
}
public class LightData
{
public LightDef LightDef { get; private set; }
private LightDefNum LightDefNum;
private LightDefClass LightDefClass;
private LightDefModifier LightDefModifier;
private LightDefRenderStyle LightDefRenderStyle;
public string LightClass { get; private set; }
public int LightNum { get; private set; }
public LightModifier LightModifier { get; private set; }
public LightRenderStyle LightRenderStyle { get; private set; }
public bool LightAnimated { get; private set; }
public bool LightInternal { get; private set; }
public bool LightVavoom { get; private set; }
public LightType LightType { get; private set; }
private void UpdateLightType()
{
switch (LightDef)
{
default:
case LightDef.POINT_NORMAL:
case LightDef.POINT_ADDITIVE:
case LightDef.POINT_SUBTRACTIVE:
case LightDef.POINT_ATTENUATED:
LightType = LightType.POINT;
break;
case LightDef.SPOT_NORMAL:
case LightDef.SPOT_ADDITIVE:
case LightDef.SPOT_SUBTRACTIVE:
case LightDef.SPOT_ATTENUATED:
LightType = LightType.SPOT;
break;
case LightDef.VAVOOM_GENERIC:
case LightDef.VAVOOM_COLORED:
LightType = LightType.VAVOOM;
break;
}
}
public LightData(LightDef d, int num)
{
LightDef = d;
LightNum = num;
LightDefNum = GetLightDefNum(LightDef);
LightDefClass = GetLightDefClass(LightDef);
LightDefModifier = GetLightDefModifier(LightDef);
LightDefRenderStyle = GetLightDefRenderStyle(LightDef);
LightClass = LightDefClass.Classes[Array.IndexOf(LightDefNum.DoomEdNums, LightNum)];
if (LightDefModifier != null)
LightModifier = LightDefModifier.Modifiers[Array.IndexOf(LightDefNum.DoomEdNums, LightNum)];
else LightModifier = LightModifier.NORMAL;
if (LightDefRenderStyle != null)
LightRenderStyle = LightDefRenderStyle.RenderStyle;
else LightRenderStyle = LightRenderStyle.NONE;
LightAnimated = (LightModifier == LightModifier.PULSE || LightModifier == LightModifier.FLICKER || LightModifier == LightModifier.FLICKERRANDOM);
LightInternal = true;
UpdateLightType();
LightVavoom = (LightType == LightType.VAVOOM);
}
public LightData(LightDef d, string cls)
{
LightDef = d;
LightClass = cls;
LightDefNum = GetLightDefNum(LightDef);
LightDefClass = GetLightDefClass(LightDef);
LightDefModifier = GetLightDefModifier(LightDef);
LightDefRenderStyle = GetLightDefRenderStyle(LightDef);
LightNum = LightDefNum.DoomEdNums[Array.IndexOf(LightDefClass.Classes, cls)];
if (LightDefModifier != null)
LightModifier = LightDefModifier.Modifiers[Array.IndexOf(LightDefClass.Classes, cls)];
else LightModifier = LightModifier.NORMAL;
if (LightDefRenderStyle != null)
LightRenderStyle = LightDefRenderStyle.RenderStyle;
else LightRenderStyle = LightRenderStyle.NONE;
LightAnimated = (LightModifier == LightModifier.PULSE || LightModifier == LightModifier.FLICKER || LightModifier == LightModifier.FLICKERRANDOM);
LightInternal = true;
LightVavoom = (LightDef == LightDef.VAVOOM_GENERIC || LightDef == LightDef.VAVOOM_COLORED);
UpdateLightType();
LightVavoom = (LightType == LightType.VAVOOM);
}
public LightData(LightModifier mod = LightModifier.NORMAL, LightRenderStyle rs = LightRenderStyle.NONE)
{
LightDef = LightDef.UNKNOWN;
LightClass = null;
LightNum = -1;
LightModifier = mod;
LightRenderStyle = rs;
LightAnimated = (LightModifier == LightModifier.PULSE || LightModifier == LightModifier.FLICKER || LightModifier == LightModifier.FLICKERRANDOM);
LightInternal = false;
LightVavoom = false;
LightType = LightType.POINT; // always point in GLDEFS
}
public void SetRenderStyle(LightRenderStyle rs)
{
if (LightInternal)
return;
LightRenderStyle = rs;
}
}
static IEnumerable<LightDef> _gldbn_ldefs;
public static LightData GetLightDataByNum(int doomednum)
{
if (_gldbn_ldefs == null)
_gldbn_ldefs = Enum.GetValues(typeof(LightDef)).Cast<LightDef>();
foreach (LightDef ldef in _gldbn_ldefs)
{
//
FieldInfo fi = typeof(LightDef).GetField(ldef.ToString());
LightDefNum[] attrs = (LightDefNum[])fi.GetCustomAttributes(typeof(LightDefNum), false);
if (attrs.Length == 0) continue;
//
LightDefNum attr = attrs[0];
if (Array.IndexOf(attr.DoomEdNums, doomednum) != -1)
return new LightData(ldef, doomednum);
}
return null;
}
public static LightData GetLightDataByClass(string cls)
{
cls = cls.ToLowerInvariant();
if (_gldbn_ldefs == null)
_gldbn_ldefs = Enum.GetValues(typeof(LightDef)).Cast<LightDef>();
foreach (LightDef ldef in _gldbn_ldefs)
{
//
FieldInfo fi = typeof(LightDef).GetField(ldef.ToString());
LightDefClass[] attrs = (LightDefClass[])fi.GetCustomAttributes(typeof(LightDefClass), false);
if (attrs.Length == 0) continue;
//
LightDefClass attr = attrs[0];
if (Array.IndexOf(attr.Classes, cls) != -1)
return new LightData(ldef, cls);
}
return null;
}
//asc script action specials
private static readonly int[] acsSpecials = { 80, 81, 82, 83, 84, 85, 226 };
public static int[] ACS_SPECIALS { get { return acsSpecials; } }
// [ZZ] this is for proper inheritance of lights.
// technically this can be found by parsing gzdoom.pk3/mapinfo/common.txt, but I wouldn't do that without a good reason for now.
public static LightData GetGZLightTypeByClass(ActorStructure actor)
{
ActorStructure p = actor;
while (p != null)
{
// found dynamic light type. alter it by actor flags.
// +MISSILEMORE makes it additive.
// +MISSILEEVENMORE makes it subtractive.
// +INCOMBAT makes it attenuated.
LightData ld = GetLightDataByClass(p.ClassName);
if (ld != null)
{
if (ld.LightDef != LightDef.VAVOOM_GENERIC && ld.LightDef != LightDef.VAVOOM_COLORED) // not vavoom
{
int baseType = ld.LightNum % 10;
int dispType = ld.LightNum - baseType;
if (actor.GetFlagValue("MISSILEMORE", false) || actor.GetFlagValue("DYNAMICLIGHT.ADDITIVE", false))
dispType = 9810;
else if (actor.GetFlagValue("MISSILEEVENMORE", false) || actor.GetFlagValue("DYNAMICLIGHT.SUBTRACTIVE", false))
dispType = 9820;
else if (actor.GetFlagValue("INCOMBAT", false) || actor.GetFlagValue("DYNAMICLIGHT.ATTENUATE", false))
dispType = 9830;
if (!actor.GetFlagValue("DYNAMICLIGHT.SPOT", false) && dispType >= 9840)
dispType -= 40;
if (actor.GetFlagValue("DYNAMICLIGHT.SPOT", false) && dispType < 9840)
dispType += 40;
return GetLightDataByNum(dispType + baseType);
}
else return null;
}
p = p.BaseClass;
}
return null;
}
// this is here so that I can see all dirty patches by listing references to this method.
public static void AssertNotNull(object o, string whatisit)
{
if (o == null)
{
throw new NullReferenceException(whatisit + " is null");
}
}
#endregion
}
}