Пример #1
0
 public static T PerformBasicOperation <T>(PARAM.Cell c, string op, double opparam) where T : struct, IFormattable
 {
     try
     {
         dynamic val = c.Value;
         dynamic opp = opparam;
         if (op.Equals("="))
         {
             return((T)(opp));
         }
         else if (op.Equals("+"))
         {
             return((T)(val + opp));
         }
         else if (op.Equals("-"))
         {
             return((T)(val - opp));
         }
         else if (op.Equals("*"))
         {
             return((T)(val * opp));
         }
         else if (op.Equals("/"))
         {
             return((T)(val / opp));
         }
     }
     catch
     {
         // Operation error
     }
     return(default(T));
 }
Пример #2
0
        public static List <PARAM.Row> GetMatchingParamRowsByPropVal(PARAM param, string rowfield, string rowvalexp, bool lenient, bool failureAllOrNone)
        {
            List <PARAM.Row> rlist = new List <PARAM.Row>();

            try
            {
                Regex rx = lenient ? new Regex(rowvalexp.ToLower()) : new Regex($@"^{rowvalexp}$");
                foreach (PARAM.Row row in param.Rows)
                {
                    PARAM.Cell c = row[rowfield.Replace(@"\s", " ")];
                    if (c == null)
                    {
                        continue;
                    }
                    string term = c.Value.ToString();
                    if (c != null && rx.Match(term).Success)
                    {
                        rlist.Add(row);
                    }
                }
                return(rlist);
            }
            catch
            {
                return(failureAllOrNone ? param.Rows : rlist);
            }
        }
Пример #3
0
 private void dgvCells_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
 {
     PARAM.Cell cell = (PARAM.Cell)dgvCells.Rows[e.RowIndex].DataBoundItem;
     if (e.ColumnIndex == 1)
     {
         if (cell.Type == CellType.x8)
         {
             e.Value = $"0x{e.Value:X2}";
         }
         if (cell.Type == CellType.x16)
         {
             e.Value = $"0x{e.Value:X4}";
         }
         if (cell.Type == CellType.x32)
         {
             e.Value = $"0x{e.Value:X8}";
         }
     }
 }
Пример #4
0
 private void dgvCells_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
 {
     PARAM.Cell cell = (PARAM.Cell)dgvCells.Rows[e.RowIndex].DataBoundItem;
     if (e.ColumnIndex == 1)
     {
         var type = cell.Def.DisplayType;
         if (type == DefType.u8)
         {
             e.Value = $"0x{e.Value:X2}";
         }
         if (type == DefType.u16)
         {
             e.Value = $"0x{e.Value:X4}";
         }
         if (type == DefType.u32)
         {
             e.Value = $"0x{e.Value:X8}";
         }
     }
 }
Пример #5
0
        public static List <PARAM.Row> GetMatchingParamRowsByPropRef(PARAM param, string rowfield, string namerx, bool lenient, bool failureAllOrNone)
        {
            List <PARAM.Row> rlist = new List <PARAM.Row>();

            try
            {
                Regex rownamerx = lenient ? new Regex(namerx.ToLower()) : new Regex($@"^{namerx}$");
                foreach (PARAM.Row row in param.Rows)
                {
                    PARAM.Cell c = row[rowfield.Replace(@"\s", " ")];
                    if (c == null)
                    {
                        continue;
                    }
                    int val = (int)c.Value;
                    foreach (string rt in FieldMetaData.Get(c.Def).RefTypes)
                    {
                        if (!ParamBank.Params.ContainsKey(rt))
                        {
                            continue;
                        }
                        PARAM.Row r = ParamBank.Params[rt][val];
                        if (r == null)
                        {
                            continue;
                        }
                        string nameToMatch = r.Name == null ? "" : r.Name;
                        if (r != null && rownamerx.Match(lenient ? nameToMatch.ToLower() : nameToMatch).Success)
                        {
                            rlist.Add(row);
                            break;
                        }
                    }
                }
                return(rlist);
            }
            catch
            {
                return(failureAllOrNone ? param.Rows : rlist);
            }
        }
Пример #6
0
        public static List <PARAM.Row> GetMatchingParamRowsByPropVal(PARAM param, string rowfield, string rowvalexp, bool lenient, bool failureAllOrNone)
        {
            List <PARAM.Row> rlist = new List <PARAM.Row>();

            try
            {
                Regex rx = new Regex(rowvalexp);
                foreach (PARAM.Row row in param.Rows)
                {
                    PARAM.Cell c    = row[rowfield];
                    string     term = lenient ? $@".*{c.Value.ToString()}.*" : c.Value.ToString();
                    if (c != null && rx.Match(term).Success)
                    {
                        rlist.Add(row);
                    }
                }
                return(rlist);
            }
            catch
            {
                return(failureAllOrNone ? param.Rows : rlist);
            }
        }
        private SortedDictionary <int, List <EntityId> > FindItemLots(GameData game)
        {
            PARAM itemLots = game.Param("ItemLotParam");
            PARAM npcs     = game.Param("NpcParam");

            SortedDictionary <int, List <EntityId> > usedItemLots = new SortedDictionary <int, List <EntityId> >();

            // TODO: Merge in Sekiro map scraper, which is a fair bit more sophisticated.
            Dictionary <EntityId, EntityId>    objects      = new Dictionary <EntityId, EntityId>();
            Dictionary <int, List <EntityId> > usedNpcs     = new Dictionary <int, List <EntityId> >();
            Dictionary <int, List <EntityId> > usedEntities = new Dictionary <int, List <EntityId> >();

            foreach (KeyValuePair <string, MSB3> entry in game.Maps)
            {
                string location = game.Locations[entry.Key];
                foreach (MSB3.Part.Object part in entry.Value.Parts.Objects)
                {
                    EntityId id = new EntityId(location, part.Name, part.EventEntityID);
                    objects[id] = id;
                    if (part.EventEntityID > 0)
                    {
                        AddMulti(usedEntities, part.EventEntityID, id);
                    }
                }
                foreach (MSB3.Part.Enemy enemy in entry.Value.Parts.Enemies)
                {
                    EntityId id = new EntityId(location, enemy.Name, enemy.EventEntityID, enemy.NPCParamID, enemy.CharaInitID);
                    objects[id] = id;
                    if (enemy.NPCParamID > 0)
                    {
                        AddMulti(usedNpcs, enemy.NPCParamID, id);
                    }
                    if (enemy.EventEntityID > 0)
                    {
                        AddMulti(usedEntities, enemy.EventEntityID, id);
                    }
                }
            }
            foreach (KeyValuePair <string, MSB3> entry in game.Maps)
            {
                string location = game.Locations[entry.Key];
                foreach (MSB3.Event.Treasure treasure in entry.Value.Events.Treasures)
                {
                    if (treasure.PartName2 != null)
                    {
                        EntityId id = new EntityId(location, treasure.PartName2);
                        if (!objects.ContainsKey(id))
                        {
                            if (logUnused)
                            {
                                Console.WriteLine($"Missing entity for treasure {treasure.Name} with entity {treasure.PartName2} and lot {treasure.ItemLot1}");
                            }
                            continue;
                        }
                        AddMulti(usedItemLots, treasure.ItemLot1, objects[id]);
                    }
                }
            }
            foreach (PARAM.Row row in npcs.Rows)
            {
                int        npcID = (int)row.ID;
                PARAM.Cell cell  = row["ItemLotId1"];
                if (cell == null || (int)cell.Value == -1)
                {
                    continue;
                }
                int itemLot = (int)cell.Value;
                if (itemLots[itemLot] == null)
                {
                    if (logUnused)
                    {
                        Console.WriteLine($"Invalid NPC lot item for {npcID} with lot {itemLot}");
                    }
                    continue;
                }
                if (!usedNpcs.ContainsKey(npcID))
                {
                    if (logUnused)
                    {
                        Console.WriteLine($"Unused NPC: {npcID}");
                    }
                    continue;
                }
                AddMulti(usedItemLots, itemLot, usedNpcs[npcID]);
            }
            foreach (KeyValuePair <int, int> entry in entityItemLots)
            {
                int        entityId = entry.Key;
                List <int> itemLot  = new List <int> {
                    entry.Value
                };
                if (additionalEntityItemLots.ContainsKey(entityId))
                {
                    itemLot.AddRange(additionalEntityItemLots[entityId]);
                }
                if (!usedEntities.ContainsKey(entityId))
                {
                    Warn($"Missing NPC {entityId} with item lot {String.Join(", ", itemLot)}");
                    continue;
                }
                List <EntityId> id = usedEntities[entityId];
                foreach (int lot in itemLot)
                {
                    if (logUnused && (int)itemLots[lot]["getItemFlagId"].Value == -1 && id[0].GetModelID() != 2150)
                    {
                        Warn($"Eventless entity drop, not crystal lizard, for {String.Join(", ", id)} item lot {lot}");
                    }
                    AddMulti(usedItemLots, lot, id);
                }
            }
            foreach (int itemLot in Enumerable.Concat(talkLots, crowLots))
            {
                if ((int)itemLots[itemLot]["getItemFlagId"].Value == -1)
                {
                    Warn($"No event id attached to talk event {itemLot}");
                }
                AddMulti(usedItemLots, itemLot, new EntityId("", "from talk"));
            }
            if (logUnused)
            {
                int lastLot = 0;
                foreach (PARAM.Row lot in itemLots.Rows)
                {
                    int itemLot = (int)lot.ID;
                    if (itemLot == lastLot + 1)
                    {
                        // Don't require groups of item lots to be connected, only the base lot
                        lastLot = itemLot;
                        continue;
                    }
                    if (!usedItemLots.ContainsKey(itemLot))
                    {
                        Console.WriteLine($"Unconnected item lot {itemLot}: {game.LotName(itemLot)}");
                    }
                    lastLot = itemLot;
                }
            }
            return(usedItemLots);
        }
Пример #8
0
 public static MassEditResult PerformSingleMassEdit(string csvString, ActionManager actionManager, string param, string field, bool useSpace)
 {
     try
     {
         PARAM p = ParamBank.Params[param];
         if (p == null)
         {
             return(new MassEditResult(MassEditResultType.PARSEERROR, "No Param selected"));
         }
         string[]            csvLines    = csvString.Split('\n');
         int                 changeCount = 0;
         List <EditorAction> actions     = new List <EditorAction>();
         foreach (string csvLine in csvLines)
         {
             if (csvLine.Trim().Equals(""))
             {
                 continue;
             }
             string[] csvs = csvLine.Split(useSpace ? ' ' : ',', 2, StringSplitOptions.RemoveEmptyEntries);
             if (csvs.Length != 2)
             {
                 return(new MassEditResult(MassEditResultType.PARSEERROR, "CSV has wrong number of values"));
             }
             int       id    = int.Parse(csvs[0]);
             string    value = csvs[1];
             PARAM.Row row   = p[id];
             if (row == null)
             {
                 return(new MassEditResult(MassEditResultType.OPERATIONERROR, $@"Could not locate row {id}"));
             }
             if (field.Equals("Name"))
             {
                 if (row.Name == null || !row.Name.Equals(value))
                 {
                     actions.Add(new PropertiesChangedAction(row.GetType().GetProperty("Name"), -1, row, value));
                 }
             }
             else
             {
                 PARAM.Cell cell = row[field];
                 if (cell == null)
                 {
                     return(new MassEditResult(MassEditResultType.OPERATIONERROR, $@"Could not locate field {field}"));
                 }
                 // Array types are unhandled
                 if (cell.Value.GetType().IsArray)
                 {
                     continue;
                 }
                 object newval = PerformOperation(cell, "=", value);
                 if (newval == null)
                 {
                     return(new MassEditResult(MassEditResultType.OPERATIONERROR, $@"Could not assign {value} to field {cell.Def.InternalName}"));
                 }
                 if (!cell.Value.Equals(newval))
                 {
                     actions.Add(new PropertiesChangedAction(cell.GetType().GetProperty("Value"), -1, cell, newval));
                 }
             }
         }
         changeCount = actions.Count;
         if (changeCount != 0)
         {
             actionManager.ExecuteAction(new CompoundAction(actions));
         }
         return(new MassEditResult(MassEditResultType.SUCCESS, $@"{changeCount} rows affected"));
     }
     catch
     {
         return(new MassEditResult(MassEditResultType.PARSEERROR, "Unable to parse CSV into correct data types"));
     }
 }
Пример #9
0
        public static object PerformOperation(PARAM.Cell cell, string op, string opparam)
        {
            try
            {
                if (op.Equals("ref"))
                {
                    if (cell.Value.GetType() == typeof(int))
                    {
                        foreach (string reftype in FieldMetaData.Get(cell.Def).RefTypes)
                        {
                            PARAM p = ParamBank.Params[reftype];
                            if (p == null)
                            {
                                continue;
                            }
                            foreach (PARAM.Row r in p.Rows)
                            {
                                if (r.Name == null)
                                {
                                    continue;
                                }
                                if (r.Name.Equals(opparam))
                                {
                                    return((int)r.ID);
                                }
                            }
                        }
                    }
                }
                if (op.Equals("="))
                {
                    if (cell.Value.GetType() == typeof(bool))
                    {
                        return(bool.Parse(opparam));
                    }
                    else if (cell.Value.GetType() == typeof(string))
                    {
                        return(opparam);
                    }
                }

                if (cell.Value.GetType() == typeof(long))
                {
                    return(PerformBasicOperation <long>(cell, op, double.Parse(opparam)));
                }
                if (cell.Value.GetType() == typeof(ulong))
                {
                    return(PerformBasicOperation <ulong>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(int))
                {
                    return(PerformBasicOperation <int>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(uint))
                {
                    return(PerformBasicOperation <uint>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(short))
                {
                    return(PerformBasicOperation <short>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(ushort))
                {
                    return(PerformBasicOperation <ushort>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(sbyte))
                {
                    return(PerformBasicOperation <sbyte>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(byte))
                {
                    return(PerformBasicOperation <byte>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(float))
                {
                    return(PerformBasicOperation <float>(cell, op, double.Parse(opparam)));
                }
                else if (cell.Value.GetType() == typeof(double))
                {
                    return(PerformBasicOperation <double>(cell, op, double.Parse(opparam)));
                }
            }
            catch
            {
            }
            return(null);
        }
Пример #10
0
        private void PropEditorPropRow(object oldval, ref int id, string internalName, FieldMetaData cellMeta, Type propType, PropertyInfo proprow, PARAM.Cell nullableCell, PARAM.Row nullableRow)
        {
            List <string> RefTypes   = cellMeta == null ? null : cellMeta.RefTypes;
            string        VirtualRef = cellMeta == null ? null : cellMeta.VirtualRef;
            ParamEnum     Enum       = cellMeta == null ? null : cellMeta.EnumType;
            string        Wiki       = cellMeta == null ? null : cellMeta.Wiki;
            bool          IsBool     = cellMeta == null ? false : cellMeta.IsBool;
            object        newval     = null;

            ImGui.PushID(id);
            ImGui.AlignTextToFramePadding();
            PropertyRowName(ref internalName, cellMeta);
            PropertyRowNameContextMenu(internalName, cellMeta);
            if (Wiki != null)
            {
                if (UIHints.AddImGuiHintButton(internalName, ref Wiki))
                {
                    cellMeta.Wiki = Wiki;
                }
            }
            if (ParamEditorScreen.HideReferenceRowsPreference == false && RefTypes != null)
            {
                ImGui.TextColored(new Vector4(1.0f, 1.0f, 0.0f, 1.0f), @$ "  <{String.Join(',', RefTypes)}>");
            }
            if (ParamEditorScreen.HideEnumsPreference == false && Enum != null)
            {
                ImGui.TextColored(new Vector4(1.0f, 1.0f, 0.0f, 1.0f), @$ "  {Enum.name}");
            }
            //PropertyRowMetaDefContextMenu();
            ImGui.NextColumn();
            ImGui.SetNextItemWidth(-1);
            bool changed = false;

            bool matchDefault = nullableCell != null && nullableCell.Def.Default.Equals(oldval);

            if (matchDefault)
            {
                ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(0.75f, 0.75f, 0.75f, 1.0f));
            }
            else if ((ParamEditorScreen.HideReferenceRowsPreference == false && RefTypes != null) || (ParamEditorScreen.HideEnumsPreference == false && Enum != null) || VirtualRef != null)
            {
                ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1.0f, 0.5f, 1.0f, 1.0f));
            }

            changed = PropertyRow(propType, oldval, out newval, IsBool);
            bool committed = ImGui.IsItemDeactivatedAfterEdit();

            if ((ParamEditorScreen.HideReferenceRowsPreference == false && RefTypes != null) || (ParamEditorScreen.HideEnumsPreference == false && Enum != null) || VirtualRef != null || matchDefault)
            {
                ImGui.PopStyleColor();
            }
            PropertyRowValueContextMenu(internalName, VirtualRef, oldval);

            if (ParamEditorScreen.HideReferenceRowsPreference == false && RefTypes != null)
            {
                PropertyRowRefs(RefTypes, oldval);
            }
            if (ParamEditorScreen.HideEnumsPreference == false && Enum != null)
            {
                ImGui.TextColored(new Vector4(1.0f, 0.5f, 0.5f, 1.0f), Enum.values.GetValueOrDefault(oldval.ToString(), "Not Enumerated"));
            }
            if ((ParamEditorScreen.HideReferenceRowsPreference == false || ParamEditorScreen.HideEnumsPreference == false) && PropertyRowMetaValueContextMenu(oldval, ref newval, RefTypes, Enum))
            {
                changed   = true;
                committed = true;
            }

            UpdateProperty(proprow, nullableCell != null ? (object)nullableCell : nullableRow, newval, changed, committed);
            ImGui.NextColumn();
            ImGui.PopID();
            id++;
        }
Пример #11
0
 private void PropEditorPropCellRow(PARAM.Cell cell, ref int id)
 {
     PropEditorPropRow(cell.Value, ref id, cell.Def.InternalName, FieldMetaData.Get(cell.Def), cell.Value.GetType(), cell.GetType().GetProperty("Value"), cell, null);
 }
        private ItemLocs FindItemLocs(GameData game)
        {
            PARAM itemLots = game.Param("ItemLotParam");
            PARAM npcs     = game.Param("NpcParam");

            ItemLocs ret = new ItemLocs
            {
                usedItemLots     = new SortedDictionary <int, List <EntityId> >(),
                usedBaseShops    = new SortedDictionary <int, List <EntityId> >(),
                baseLotsToCreate = new Dictionary <int, int>(),
                // TODO: See if we can have a reasaonable processing step
                newEntityLots = new Dictionary <int, int>(),
            };

            Dictionary <EntityId, EntityId>    objects      = new Dictionary <EntityId, EntityId>();
            Dictionary <int, List <EntityId> > usedNpcs     = new Dictionary <int, List <EntityId> >();
            Dictionary <int, List <EntityId> > usedEntities = new Dictionary <int, List <EntityId> >();
            Dictionary <int, List <EntityId> > usedEsds     = new Dictionary <int, List <EntityId> >();

            // Map from item lot to ESD id, hackily extracted from ESD.
            Dictionary <int, HashSet <int> > talkItemLocations = new Dictionary <int, HashSet <int> >();
            // This is a bit intensive. Ideally just dump this somewhere else
            HashSet <int> debugEsd = new HashSet <int>();

            IEnumerable <ESD.Condition> GetCommands(List <ESD.Condition> condList) => Enumerable.Concat(condList, condList.SelectMany(cond => GetCommands(cond.Subconditions)));

            foreach (KeyValuePair <string, Dictionary <string, ESD> > entry in game.Talk)
            {
                string location = game.Locations.ContainsKey(entry.Key) ? game.Locations[entry.Key] : "";
                // 62210
                foreach (KeyValuePair <string, ESD> esdEntry in entry.Value)
                {
                    ESD esd   = esdEntry.Value;
                    int esdId = int.Parse(esdEntry.Key.Substring(1));
                    foreach ((int, int, ESD.State)stateDesc in esd.StateGroups.SelectMany(stateGroup => stateGroup.Value.Select(state => (stateGroup.Key, state.Key, state.Value))))
                    {
                        (int groupId, int id, ESD.State state) = stateDesc;
                        foreach (ESD.CommandCall cmd in new[] { state.EntryCommands, state.WhileCommands, state.ExitCommands, GetCommands(state.Conditions).SelectMany(c => c.PassCommands) }.SelectMany(c => c))
                        {
                            foreach (byte[] arg in cmd.Arguments)
                            {
                                if (arg.Length == 6 && arg[0] == 0x82 && arg[5] == 0xA1)
                                {
                                    int opt = BitConverter.ToInt32(arg, 1);
                                    if (opt >= 60000 && opt <= 69900 && itemLots[opt] != null)
                                    {
                                        AddMulti(talkItemLocations, opt, esdId);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            bool logEntities = false;

            foreach (KeyValuePair <string, MSBS> entry in game.Smaps)
            {
                string location = game.Locations[entry.Key];
                MSBS   msb      = entry.Value;
                Dictionary <string, int> partEsds = new Dictionary <string, int>();
                List <MSBS.Part.Enemy>   enemies  = msb.Parts.Enemies;
                // TODO: Update SoulsFormat and migrate to new names
                foreach (MSBS.Event.Talk ev in entry.Value.Events.Talks)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        string part  = ev.EnemyNames[i];
                        int    esdId = ev.TalkIDs[i];
                        if (esdId < 0 || part == null)
                        {
                            continue;
                        }
                        partEsds[part] = esdId;
                    }
                }
                foreach (MSBS.Entry obj in entry.Value.Parts.GetEntries())
                {
                    MSBS.Part part = obj as MSBS.Part;
                    if (part == null)
                    {
                        continue;
                    }
                    EntityId   id;
                    int        esdId    = 0;
                    List <int> groupIDs = part.EntityGroupIDs.Where(groupID => groupID > 0).ToList();
                    if (part is MSBS.Part.Enemy enemy)
                    {
                        esdId = partEsds.ContainsKey(enemy.Name) ? partEsds[enemy.Name] : -1;
                        id    = new EntityId(location, enemy.Name, enemy.EntityID, enemy.NPCParamID, enemy.CharaInitID, groupIDs);
                    }
                    else if (part is MSBS.Part.Object || logEntities)
                    {
                        id = new EntityId(location, part.Name, part.EntityID, GroupIds: groupIDs);
                    }
                    else
                    {
                        continue;
                    }
                    objects[id] = id;
                    if (id.EventEntityID > 0)
                    {
                        AddMulti(usedEntities, id.EventEntityID, id);
                    }
                    foreach (int groupID in groupIDs)
                    {
                        AddMulti(usedEntities, groupID, id);
                    }
                    if (id.NPCParamID > 0)
                    {
                        AddMulti(usedNpcs, id.NPCParamID, id);
                    }
                    if (esdId > 0)
                    {
                        if (debugEsd.Contains(esdId))
                        {
                            Console.WriteLine($"ESD {esdId} belongs to {game.EntityName(id, true)} in {location}, entity id {id.EventEntityID}");
                        }
                        AddMulti(usedEsds, esdId, id);
                    }
                }
            }
            if (logEntities)
            {
                foreach (KeyValuePair <int, List <EntityId> > entry in usedEntities.OrderBy(e => e.Key))
                {
                    Console.WriteLine($"{entry.Key}: {string.Join(", ", entry.Value.Select(e => $"{game.EntityName(e, true)} in {e.MapName}"))}");
                }
            }
            List <EntityId> unusedEsd = new List <EntityId> {
                new EntityId("", "Unknown Dialogue")
            };

            foreach (KeyValuePair <int, HashSet <int> > entry in talkItemLocations)
            {
                List <EntityId> talkIds;
                if (addUnused)
                {
                    talkIds = entry.Value.SelectMany(esd => usedEsds.ContainsKey(esd) ? usedEsds[esd] : unusedEsd).ToList();
                }
                else
                {
                    talkIds = entry.Value.Where(esd => usedEsds.ContainsKey(esd)).SelectMany(esd => usedEsds[esd]).ToList();
                    if (talkIds.Count == 0)
                    {
                        continue;
                    }
                }
                AddMulti(ret.usedItemLots, entry.Key, talkIds);
            }
            foreach (KeyValuePair <int, int> entry in shopEsds)
            {
                if (!usedEsds.ContainsKey(entry.Value) && !addUnused)
                {
                    continue;
                }
                AddMulti(ret.usedBaseShops, entry.Key, usedEsds.ContainsKey(entry.Value) ? usedEsds[entry.Value] : unusedEsd);
            }
            foreach (KeyValuePair <string, MSBS> entry in game.Smaps)
            {
                string location = game.Locations[entry.Key];
                foreach (MSBS.Event.Treasure treasure in entry.Value.Events.Treasures)
                {
                    if (treasure.TreasurePartName != null)
                    {
                        EntityId id = new EntityId(location, treasure.TreasurePartName);
                        if (!objects.ContainsKey(id))
                        {
                            if (logUnused)
                            {
                                Console.WriteLine($"Missing entity for treasure {treasure.Name} with entity {treasure.TreasurePartName} and lot {treasure.ItemLotID}");
                            }
                            continue;
                        }
                        AddMulti(ret.usedItemLots, treasure.ItemLotID, objects[id]);
                    }
                }
            }
            foreach (PARAM.Row row in npcs.Rows)
            {
                int        npcID = (int)row.ID;
                PARAM.Cell cell  = row["ItemLotId1"];
                if (cell == null || (int)cell.Value == -1)
                {
                    continue;
                }
                int itemLot = (int)cell.Value;
                if (itemLots[itemLot] == null)
                {
                    if (logUnused)
                    {
                        Console.WriteLine($"Invalid NPC lot item for {npcID} with lot {itemLot}");
                    }
                    continue;
                }
                if (!usedNpcs.ContainsKey(npcID))
                {
                    if (logUnused)
                    {
                        Console.WriteLine($"Unused NPC: {npcID}");
                    }
                    if (addUnused)
                    {
                        AddMulti(ret.usedItemLots, itemLot, new EntityId("", "Unused NPC"));
                    }
                    continue;
                }
                AddMulti(ret.usedItemLots, itemLot, usedNpcs[npcID]);
            }
            foreach (KeyValuePair <int, int> entry in entityItemLots)
            {
                int        entityId = entry.Key;
                List <int> itemLot  = new List <int> {
                    entry.Value
                };
                if (additionalEntityItemLots.ContainsKey(entityId))
                {
                    itemLot.AddRange(additionalEntityItemLots[entityId]);
                }
                List <EntityId> id;
                if (usedEntities.ContainsKey(entityId))
                {
                    id = usedEntities[entityId];
                }
                else
                {
                    Console.WriteLine($"XX Missing entity {entityId} with item lot {String.Join(", ", itemLot)}");
                    id = new List <EntityId> {
                        new EntityId("", "from entity")
                    };
                }

                foreach (int lot in itemLot)
                {
                    if (logUnused && (int)itemLots[lot]["getItemFlagId"].Value == -1 && id[0].GetModelID() != 2150)
                    {
                        Console.WriteLine($"Eventless entity drop, not crystal lizard, for {String.Join(", ", id)} item lot {lot}");
                    }
                    AddMulti(ret.usedItemLots, lot, id);
                }
            }
            Dictionary <int, int> syntheticLotBase = new Dictionary <int, int>();

            foreach (KeyValuePair <int, int> entry in treasureCarpDrops)
            {
                int             entityId = entry.Key;
                int             baseLot  = entry.Value;
                List <EntityId> id;
                if (usedEntities.ContainsKey(entityId))
                {
                    id = usedEntities[entityId];
                }
                else
                {
                    Console.WriteLine($"XX Missing entity {entityId} with item lot {baseLot}");
                    id = new List <EntityId> {
                        new EntityId("", "from entity")
                    };
                }
                if (syntheticLotBase.ContainsKey(baseLot))
                {
                    syntheticLotBase[baseLot] += 5;
                }
                else
                {
                    syntheticLotBase[baseLot] = baseLot;
                }
                int itemLot = syntheticLotBase[baseLot];
                ret.baseLotsToCreate[itemLot] = baseLot;
                // TODO: See if this info can be extracted anywhere else
                ret.newEntityLots[entityId] = itemLot;
                AddMulti(ret.usedItemLots, itemLot, id);
            }
            foreach (KeyValuePair <int, string> entry in scriptLots)
            {
                int itemLot = entry.Key;
                if ((int)itemLots[itemLot]["getItemFlagId"].Value == -1)
                {
                    // TODO: Make sure there are all classified...
                    // Console.WriteLine($"XX No event id attached to script event {itemLot}");
                }
                AddMulti(ret.usedItemLots, itemLot, new EntityId(entry.Value, "Scripted"));
            }
            foreach (int itemLot in talkLots)
            {
                if ((int)itemLots[itemLot]["getItemFlagId"].Value == -1)
                {
                    Console.WriteLine($"XX No event id attached to talk event {itemLot}");
                }
                AddMulti(ret.usedItemLots, itemLot, new EntityId("", "from talk"));
            }
            int  lastLot       = 0;
            bool lastConnected = false;

            foreach (PARAM.Row lot in itemLots.Rows)
            {
                int  itemLot   = (int)lot.ID;
                bool connected = (byte)lot["LotItemNum1"].Value == 1;
                if (itemLot == lastLot + 1)
                {
                    // Don't require groups of item lots to be connected, only the base lot
                }
                else if (connected && lastConnected && (itemLot - lastLot) % 10 == 0 && (itemLot - lastLot) <= 40)
                {
                    // This is also fine.... aaaa. Bell Demon drops.
                }
                else
                {
                    if (!ret.usedItemLots.ContainsKey(itemLot))
                    {
                        if (logUnused)
                        {
                            Console.WriteLine($"Unconnected item lot {itemLot}: {game.LotName(itemLot)}");
                        }
                        if (addUnused)
                        {
                            AddMulti(ret.usedItemLots, itemLot, new EntityId("", "unknown"));
                        }
                    }
                }
                lastLot       = itemLot;
                lastConnected = connected;
            }
            return(ret);
        }
Пример #13
0
        private static int WriteMemoryCell(PARAM.Cell cell, IntPtr CellDataPtr, ref int bitFieldPos, ref BitArray bits, SoulsMemoryHandler memoryHandler)
        {
            PARAMDEF.DefType displayType = cell.Def.DisplayType;
            // If this can be simplified, that would be ideal. Currently we have to reconcile DefType, a numerical size in bits, and the Type used for the bitField array
            if (cell.Def.BitSize != -1)
            {
                if (displayType == SoulsFormats.PARAMDEF.DefType.u8)
                {
                    if (bitFieldPos == 0)
                    {
                        bits = new BitArray(8);
                    }
                    bits.Set(bitFieldPos, Convert.ToBoolean(cell.Value));
                    bitFieldPos++;
                    if (bitFieldPos == 8)
                    {
                        byte valueRead = 0;
                        memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                        byte[] bitField = new byte[1];
                        bits.CopyTo(bitField, 0);
                        bitFieldPos = 0;
                        byte bitbuffer = bitField[0];
                        if (valueRead != bitbuffer)
                        {
                            memoryHandler.WriteProcessMemory(CellDataPtr, ref bitbuffer);
                        }
                        return(sizeof(byte));
                    }
                    return(0);
                }
                else if (displayType == SoulsFormats.PARAMDEF.DefType.u16)
                {
                    if (bitFieldPos == 0)
                    {
                        bits = new BitArray(16);
                    }
                    bits.Set(bitFieldPos, Convert.ToBoolean(cell.Value));
                    bitFieldPos++;
                    if (bitFieldPos == 16)
                    {
                        ushort valueRead = 0;
                        memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                        ushort[] bitField = new ushort[1];
                        bits.CopyTo(bitField, 0);
                        bitFieldPos = 0;
                        ushort bitbuffer = bitField[0];
                        if (valueRead != bitbuffer)
                        {
                            memoryHandler.WriteProcessMemory(CellDataPtr, ref bitbuffer);
                        }
                        return(sizeof(UInt16));
                    }
                    return(0);
                }
                else if (displayType == SoulsFormats.PARAMDEF.DefType.u32)
                {
                    if (bitFieldPos == 0)
                    {
                        bits = new BitArray(32);
                    }
                    bits.Set(bitFieldPos, Convert.ToBoolean(cell.Value));
                    bitFieldPos++;
                    if (bitFieldPos == 32)
                    {
                        uint valueRead = 0;
                        memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                        uint[] bitField = new uint[1];
                        bits.CopyTo(bitField, 0);
                        bitFieldPos = 0;
                        uint bitbuffer = bitField[0];
                        if (valueRead != bitbuffer)
                        {
                            memoryHandler.WriteProcessMemory(CellDataPtr, ref bitbuffer);
                        }
                        return(sizeof(UInt32));
                    }
                    return(0);
                }
            }
            if (displayType == SoulsFormats.PARAMDEF.DefType.f32)
            {
                float valueRead = 0f;
                memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                float value = Convert.ToSingle(cell.Value);
                if (valueRead != value)
                {
                    memoryHandler.WriteProcessMemory(CellDataPtr, ref value);
                }
                return(sizeof(float));
            }
            else if (displayType == SoulsFormats.PARAMDEF.DefType.s32)
            {
                int valueRead = 0;
                memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                int value = Convert.ToInt32(cell.Value);
                if (valueRead != value)
                {
                    memoryHandler.WriteProcessMemory(CellDataPtr, ref value);
                }
                return(sizeof(Int32));
            }
            else if (displayType == SoulsFormats.PARAMDEF.DefType.s16)
            {
                short valueRead = 0;
                memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                short value = Convert.ToInt16(cell.Value);
                if (valueRead != value)
                {
                    memoryHandler.WriteProcessMemory(CellDataPtr, ref value);
                }
                return(sizeof(Int16));
            }
            else if (displayType == SoulsFormats.PARAMDEF.DefType.s8)
            {
                sbyte valueRead = 0;
                memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                sbyte value = Convert.ToSByte(cell.Value);
                if (valueRead != value)
                {
                    memoryHandler.WriteProcessMemory(CellDataPtr, ref value);
                }
                return(sizeof(sbyte));
            }
            else if (displayType == SoulsFormats.PARAMDEF.DefType.u32)
            {
                uint valueRead = 0;
                memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                uint value = Convert.ToUInt32(cell.Value);
                if (valueRead != value)
                {
                    memoryHandler.WriteProcessMemory(CellDataPtr, ref value);
                }
                return(sizeof(UInt32));
            }
            else if (displayType == SoulsFormats.PARAMDEF.DefType.u16)
            {
                ushort valueRead = 0;
                memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                ushort value = Convert.ToUInt16(cell.Value);
                if (valueRead != value)
                {
                    memoryHandler.WriteProcessMemory(CellDataPtr, ref value);
                }
                return(sizeof(UInt16));
            }
            else if (displayType == SoulsFormats.PARAMDEF.DefType.u8)
            {
                byte valueRead = 0;
                memoryHandler.ReadProcessMemory(CellDataPtr, ref valueRead);

                byte value = Convert.ToByte(cell.Value);
                if (valueRead != value)
                {
                    memoryHandler.WriteProcessMemory(CellDataPtr, ref value);
                }
                return(sizeof(byte));
            }
            else if (displayType == SoulsFormats.PARAMDEF.DefType.dummy8 || displayType == SoulsFormats.PARAMDEF.DefType.fixstr || displayType == SoulsFormats.PARAMDEF.DefType.fixstrW)
            {
                return(cell.Def.ArrayLength);
            }
            else
            {
                throw new Exception("Unexpected Field Type");
            }
        }
Пример #14
0
 private void PropEditorPropCellRow(PARAM.Cell cell, PARAM.Cell vcell, ref int id, Regex propSearchRx)
 {
     PropEditorPropRow(cell.Value, vcell == null?null:vcell.Value, ref id, cell.Def.InternalName, FieldMetaData.Get(cell.Def), cell.Value.GetType(), cell.GetType().GetProperty("Value"), cell, null, propSearchRx);
 }