Fixed, game configurations: Boom game configurations used incorrect "thingflagscompare" block.

Fixed, Thing edit form: implemented overcomplicated required flags check (which should work as expected this time. probably.).
This commit is contained in:
MaxED 2014-11-03 13:02:59 +00:00
parent 06163d4611
commit f986f5c98d
9 changed files with 242 additions and 110 deletions

View file

@ -97,7 +97,7 @@ mapformat_doom
// How to compare thing flags (for the stuck things error checker)
thingflagscompare
{
include("Doom_misc.cfg", "thingflagscompare");
include("Boom_misc.cfg", "thingflagscompare");
}
// Things flags masks

View file

@ -35,25 +35,30 @@ thingflagstranslation
// How thing flags should be compared (for the stuck thing error check)
thingflagscompare
{
skills {
1;
2;
4;
}
skills {
1;
2;
4;
}
gamemodes {
16 {
invert = true;
}
gamemodes {
16 {
//invert = true;
ignoredgroup = "skills";
ingnorethisgroupwhenunset = true;
}
32 {
invert = true;
}
32 {
invert = true;
requiredflag = "16";
}
64 {
invert = true;
}
}
64 {
invert = true;
requiredflag = "16";
requiredgroup = "skills";
}
}
}

View file

@ -57,6 +57,8 @@ thingflagscompare
gamemodes {
16 {
comparemethod = "equal";
ignoredgroup = "skills";
ingnorethisgroupwhenunset = true;
}
}
}

View file

@ -59,9 +59,15 @@ thingflagscompare
}
gamemodes {
256;
512;
1024;
256 {
requiredgroup = "skills";
}
512 {
requiredgroup = "skills";
}
1024 {
ignoredgroup = "skills";
}
}
}

View file

@ -48,9 +48,15 @@ thingflagscompare
}
gamemodes {
single;
dm;
coop;
single {
requiredgroup = "skills";
}
coop {
requiredgroup = "skills";
}
dm {
ignoredgroup = "skills";
}
}
classes {

View file

@ -733,6 +733,34 @@ namespace CodeImp.DoomBuilder.Config
}
}
//mxd. Integrity check
foreach (KeyValuePair<string, Dictionary<string, ThingFlagsCompare>> group in thingflagscompare)
{
foreach (KeyValuePair<string, ThingFlagsCompare> flaggrp in group.Value)
{
// Required group is missing?
if (!string.IsNullOrEmpty(flaggrp.Value.RequiredGroup) && !thingflagscompare.ContainsKey(flaggrp.Value.RequiredGroup))
{
General.ErrorLogger.Add(ErrorType.Warning, "thingflagscompare group '" + flaggrp.Value.RequiredGroup + "', required by flag '" + flaggrp.Key + "' does not exist!");
flaggrp.Value.RequiredGroup = string.Empty;
}
// Ignored group is missing?
if(!string.IsNullOrEmpty(flaggrp.Value.IgnoredGroup) && !thingflagscompare.ContainsKey(flaggrp.Value.IgnoredGroup))
{
General.ErrorLogger.Add(ErrorType.Warning, "thingflagscompare group '" + flaggrp.Value.IgnoredGroup + "', ignored by flag '" + flaggrp.Key + "' does not exist!");
flaggrp.Value.IgnoredGroup = string.Empty;
}
// Required flag is missing?
if(!string.IsNullOrEmpty(flaggrp.Value.RequiredFlag) && !group.Value.ContainsKey(flaggrp.Value.RequiredFlag))
{
General.ErrorLogger.Add(ErrorType.Warning, "thingflagscompare flag '" + flaggrp.Value.RequiredFlag + "', required by flag '" + flaggrp.Key + "' does not exist!");
flaggrp.Value.RequiredFlag = string.Empty;
}
}
}
// Sort the translation flags, because they must be compared highest first!
thingflagstranslation.Sort();
}

View file

@ -17,6 +17,8 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
@ -39,6 +41,10 @@ namespace CodeImp.DoomBuilder.Config
#region ================== Variables
private readonly string flag;
private string requiredgroup; //mxd. This flag only works if at least one flag is set in the "requiredgroup"
private string ignoredgroup; //mxd. If this flag is set, flags from ignoredgroup can be... well... ignored!
private string requiredflag; //mxd. This flag only works if requiredflag is set.
private readonly bool ingnorethisgroupwhenunset; //mxd
private readonly CompareMethod comparemethod;
private readonly bool invert;
private readonly string group;
@ -49,6 +55,9 @@ namespace CodeImp.DoomBuilder.Config
public string Flag { get { return flag; } }
public string Group { get { return group; } }
public string RequiredGroup { get { return requiredgroup; } internal set { requiredgroup = value; } } //mxd
public string IgnoredGroup { get { return ignoredgroup; } internal set { ignoredgroup = value; } } //mxd
public string RequiredFlag { get { return requiredflag; } internal set { requiredflag = value; } } //mxd
#endregion
@ -77,6 +86,10 @@ namespace CodeImp.DoomBuilder.Config
}
invert = cfg.ReadSetting(cfgpath + ".invert", false);
requiredgroup = cfg.ReadSetting(cfgpath + ".requiredgroup", string.Empty); //mxd
ignoredgroup = cfg.ReadSetting(cfgpath + ".ignoredgroup", string.Empty); //mxd
requiredflag = cfg.ReadSetting(cfgpath + ".requiredflag", string.Empty); //mxd
ingnorethisgroupwhenunset = cfg.ReadSetting(cfgpath + ".ingnorethisgroupwhenunset", false); //mxd
// We have no destructor
GC.SuppressFinalize(this);
@ -97,25 +110,155 @@ namespace CodeImp.DoomBuilder.Config
bool t2flag;
// Check if the flags exist
if(!t1.Flags.ContainsKey(flag) || !t2.Flags.ContainsKey(flag)) {
//mxd. If a map is in UDMF format - check Fields
if(!General.Map.UDMF || !t1.Fields.ContainsKey(flag) || !t2.Fields.ContainsKey(flag))
return 0;
if (!t1.Flags.ContainsKey(flag) || !t2.Flags.ContainsKey(flag)) return 0;
// tag flag inversion into account
t1flag = invert ? !(bool)t1.Fields[flag].Value : (bool)t1.Fields[flag].Value;
t2flag = invert ? !(bool)t2.Fields[flag].Value : (bool)t2.Fields[flag].Value;
} else {
// tag flag inversion into account
t1flag = invert ? !t1.Flags[flag] : t1.Flags[flag];
t2flag = invert ? !t2.Flags[flag] : t2.Flags[flag];
//mxd. We should ignore the flag if requiredgroup doesn't have any flags set
if(!string.IsNullOrEmpty(requiredgroup))
{
bool t1hasrequiredflags = false;
bool t2hasrequiredflags = false;
foreach(string key in General.Map.Config.ThingFlagsCompare[requiredgroup].Keys)
{
if(t1.Flags.ContainsKey(key) && (General.Map.Config.ThingFlagsCompare[requiredgroup][key].invert ? !t1.Flags[key] : t1.Flags[key]))
t1hasrequiredflags = true;
if(t2.Flags.ContainsKey(key) && (General.Map.Config.ThingFlagsCompare[requiredgroup][key].invert ? !t2.Flags[key] : t2.Flags[key]))
t2hasrequiredflags = true;
}
// Can't compare...
if (!t1hasrequiredflags || !t2hasrequiredflags) return 0;
}
//mxd. We should ignore the flag if requiredflag is not set
if (string.IsNullOrEmpty(requiredflag))
{
bool inverted = General.Map.Config.ThingFlagsCompare[group].ContainsKey(requiredflag) && General.Map.Config.ThingFlagsCompare[group][requiredflag].invert;
bool t1hasrequiredflag = inverted ? !t1.Flags[requiredflag] : t1.Flags[requiredflag];
bool t2hasrequiredflag = inverted ? !t2.Flags[requiredflag] : t2.Flags[requiredflag];
// Can't compare...
if(!t1hasrequiredflag || !t2hasrequiredflag) return 0;
}
//mxd. We should also ignore the flag if it's in ingoredgroup
foreach(KeyValuePair<string, Dictionary<string, ThingFlagsCompare>> pair in General.Map.Config.ThingFlagsCompare)
{
foreach(KeyValuePair<string, ThingFlagsCompare> flaggrp in pair.Value)
{
if (!string.IsNullOrEmpty(flaggrp.Value.ignoredgroup) && group == flaggrp.Value.ignoredgroup)
{
bool t1ignoreflagset = flaggrp.Value.invert ? !t1.Flags[flaggrp.Key] : t1.Flags[flaggrp.Key];
bool t2ignoreflagset = flaggrp.Value.invert ? !t2.Flags[flaggrp.Key] : t2.Flags[flaggrp.Key];
// Can't compare...
if(!t1ignoreflagset || !t2ignoreflagset) return 0;
}
}
}
// Take flag inversion into account
t1flag = invert ? !t1.Flags[flag] : t1.Flags[flag];
t2flag = invert ? !t2.Flags[flag] : t2.Flags[flag];
if (comparemethod == CompareMethod.And && (t1flag && t2flag)) return 1;
if (comparemethod == CompareMethod.Equal && (t1flag == t2flag)) return 1;
return 0;
}
//mxd
public static string CheckThingEditFormFlags(List<CheckBox> checkboxes)
{
Dictionary<string, bool> flags = new Dictionary<string, bool>(checkboxes.Count);
Dictionary<string, Dictionary<string, bool>> flagspergroup = new Dictionary<string, Dictionary<string, bool>>(General.Map.Config.ThingFlagsCompare.Count);
Dictionary<string, bool> requiredgroups = new Dictionary<string, bool>();
Dictionary<string, bool> ignoredgroups = new Dictionary<string, bool>();
// Gather flags
foreach (CheckBox cb in checkboxes)
{
flags.Add(cb.Tag.ToString(), cb.CheckState == CheckState.Checked);
}
// Gather flags per group
foreach (KeyValuePair<string, Dictionary<string, ThingFlagsCompare>> group in General.Map.Config.ThingFlagsCompare)
{
flagspergroup.Add(group.Key, new Dictionary<string, bool>());
foreach (KeyValuePair<string, ThingFlagsCompare> flaggrp in group.Value)
{
bool flagset = IsFlagSet(flags, flaggrp.Key, flaggrp.Value.invert) && (string.IsNullOrEmpty(flaggrp.Value.requiredflag) || IsFlagSet(flags, flaggrp.Value.requiredflag, group.Value[flaggrp.Value.requiredflag].invert));
if(flagset)
{
flagspergroup[group.Key].Add(flaggrp.Key, true);
if(!string.IsNullOrEmpty(flaggrp.Value.requiredgroup) && !requiredgroups.ContainsKey(flaggrp.Value.requiredgroup))
requiredgroups.Add(flaggrp.Value.requiredgroup, false);
}
else if(flaggrp.Value.ingnorethisgroupwhenunset)
{
ignoredgroups.Add(group.Key, false);
}
}
}
// Check dependancies
foreach (KeyValuePair<string, Dictionary<string, bool>> group in flagspergroup)
{
foreach(KeyValuePair<string, bool> flaggrp in group.Value)
{
if(!flaggrp.Value) continue;
string ignoredgrp = General.Map.Config.ThingFlagsCompare[group.Key][flaggrp.Key].ignoredgroup;
if (!string.IsNullOrEmpty(ignoredgrp) && !requiredgroups.ContainsKey(ignoredgrp))
{
ignoredgroups.Add(ignoredgrp, false);
}
}
}
// Get rid of ignoredgroups
foreach (KeyValuePair<string, bool> group in ignoredgroups)
{
flagspergroup.Remove(group.Key);
}
// Return message
string result = string.Empty;
foreach (KeyValuePair<string, Dictionary<string, bool>> group in flagspergroup)
{
if (group.Value.Count == 0)
{
switch(group.Key)
{
case "skills":
result += "Thing is not used in any skill level.";
break;
case "gamemodes":
result += "Thing is not used in any game mode.";
break;
case "classes":
result += "Thing is not used by any class.";
break;
default:
result += "At least one '" + group.Key + "' flag should be set.";
break;
}
}
}
return result;
}
//mxd
private static bool IsFlagSet(Dictionary<string, bool> flags, string flag, bool invert)
{
bool result = flags.ContainsKey(flag) && flags[flag];
return (invert ? !result : result);
}
#endregion
}
}

View file

@ -633,47 +633,17 @@ namespace CodeImp.DoomBuilder.Windows
{
if(preventchanges) return;
foreach(KeyValuePair<string, Dictionary<string, ThingFlagsCompare>> group in General.Map.Config.ThingFlagsCompare)
string warn = ThingFlagsCompare.CheckThingEditFormFlags(flags.Checkboxes);
if(!string.IsNullOrEmpty(warn))
{
if(group.Value.Count < 2) continue;
bool haveflags = false;
foreach(CheckBox cb in flags.Checkboxes)
{
if (group.Value.ContainsKey(cb.Tag.ToString()) && cb.CheckState != CheckState.Unchecked)
{
haveflags = true;
break;
}
}
if (!haveflags)
{
switch(group.Key)
{
case "skills":
tooltip.SetToolTip(missingflags, "Thing is not used in any skill level.");
break;
case "gamemodes":
tooltip.SetToolTip(missingflags, "Thing is not used in any game mode.");
break;
case "classes":
tooltip.SetToolTip(missingflags, "Thing is not used by any class.");
break;
default:
tooltip.SetToolTip(missingflags, "At least one '" + group.Key + "' flag should be set.");
break;
}
missingflags.Visible = true;
settingsgroup.ForeColor = Color.DarkRed;
return;
}
//got missing flags
tooltip.SetToolTip(missingflags, warn);
missingflags.Visible = true;
settingsgroup.ForeColor = Color.DarkRed;
return;
}
//everything is OK
missingflags.Visible = false;
settingsgroup.ForeColor = SystemColors.ControlText;
}

View file

@ -335,10 +335,11 @@ namespace CodeImp.DoomBuilder.Windows
preventchanges = false;
//mxd. Trigger angle/pitch/roll update manually...
//mxd. Trigger updates manually...
angle_WhenTextChanged(angle, EventArgs.Empty);
pitch_WhenTextChanged(pitch, EventArgs.Empty);
roll_WhenTextChanged(roll, EventArgs.Empty);
flags_OnValueChanged(flags, EventArgs.Empty);
updateScriptControls(); //mxd
@ -862,46 +863,17 @@ namespace CodeImp.DoomBuilder.Windows
{
if(preventchanges) return;
foreach(KeyValuePair<string, Dictionary<string, ThingFlagsCompare>> group in General.Map.Config.ThingFlagsCompare)
string warn = ThingFlagsCompare.CheckThingEditFormFlags(flags.Checkboxes);
if(!string.IsNullOrEmpty(warn))
{
if(group.Value.Count < 2) continue;
bool haveflags = false;
foreach(CheckBox cb in flags.Checkboxes)
{
if(group.Value.ContainsKey(cb.Tag.ToString()) && cb.CheckState != CheckState.Unchecked) {
haveflags = true;
break;
}
}
if(!haveflags)
{
switch(group.Key)
{
case "skills":
tooltip.SetToolTip(missingflags, "Thing is not used in any skill level.");
break;
case "gamemodes":
tooltip.SetToolTip(missingflags, "Thing is not used in any game mode.");
break;
case "classes":
tooltip.SetToolTip(missingflags, "Thing is not used by any class.");
break;
default:
tooltip.SetToolTip(missingflags, "At least one '" + group.Key + "' flag should be set.");
break;
}
missingflags.Visible = true;
settingsgroup.ForeColor = Color.DarkRed;
return;
}
//got missing flags
tooltip.SetToolTip(missingflags, warn);
missingflags.Visible = true;
settingsgroup.ForeColor = Color.DarkRed;
return;
}
//everything is OK
missingflags.Visible = false;
settingsgroup.ForeColor = SystemColors.ControlText;
}