Ejemplo n.º 1
0
        };                                                                                         // Warp, Soft, Exit, Life, Life 2

        private void WriteItemSpellData(MagicSpell Spell, Item item)
        {
            // Set the spell an item casts
            var output = Spell.Data.ToHex().Remove(2);
            var offset = WeaponOffset + 0x8 * Math.Min((byte)item - WeaponStart, ArmourStart - WeaponStart) + 0x4 * Math.Max(0, (byte)item - ArmourStart) + MagicBitOffset;

            Put(offset, Blob.FromHex(output));

            // if the item is the Defense, overwrite the last character in the name, otherwise, keep the icon there.
            output = Spell.Name.ToHex().Remove(12) + (item == Item.Defense ? "FF" : "");
            offset = GearTextOffset + ((byte)item > (byte)Item.Ribbon ? 1 : 0) + GearTextSize * ((byte)item - WeaponStart);
            Put(offset, Blob.FromHex(output));
        }
Ejemplo n.º 2
0
        private void WriteItemSpellData(MagicSpell Spell, Item item)
        {
            // Set the spell an item casts
            var offset = WeaponOffset + 0x8 * Math.Min((byte)item - WeaponStart, ArmorStart - WeaponStart) + 0x4 * Math.Max(0, (byte)item - ArmorStart) + MagicBitOffset;

            Data[offset] = (byte)(Spell.Index + 1);

            if (ItemsText[(int)item].Contains("@"))
            {
                ItemsText[(int)item] = ItemsText[(int)item].Remove(0, 6).Insert(0, Spell.Name.PadRight(6));
            }
            else
            {
                ItemsText[(int)item] = Spell.Name.PadRight(7);
            }
        }
Ejemplo n.º 3
0
        private void WriteItemSpellData(MagicSpell Spell, Item item)
        {
            // Set the spell an item casts
            var offset = WeaponOffset + 0x8 * Math.Min((byte)item - WeaponStart, ArmorStart - WeaponStart) + 0x4 * Math.Max(0, (byte)item - ArmorStart) + MagicBitOffset;

            Data[offset] = (byte)(Spell.Index + 1);

            // Setup the text of the item's name to include the spell name.
            offset = GearTextOffset + ((byte)item > (byte)Item.Ribbon ? 1 : 0) + GearTextSize * ((byte)item - WeaponStart);
            if (Get(offset, 1)[0] > 200)
            {
                offset++;                 // If the first byte is in the icon range, bump the pointer to overwrite after it.
            }
            else if (Get(offset + 6, 1)[0] <= 200)
            {
                Data[offset + 6] = 0xFF;                 // Erase final non-icon characters from name.
            }

            Debug.Assert(Spell.Name.Length == 6);
            Put(offset, Spell.Name);
        }
Ejemplo n.º 4
0
        private void WriteItemSpellData(MagicSpell Spell, Item item)
        {
            // Set the spell an item casts
            var offset = WeaponOffset + 0x8 * Math.Min((byte)item - WeaponStart, ArmorStart - WeaponStart) + 0x4 * Math.Max(0, (byte)item - ArmorStart) + MagicBitOffset;

            Data[offset] = (byte)(Spell.Index + 1);

            // Setup the text of the item's name to include the spell name.
            offset = GearTextOffset + ((byte)item > (byte)Item.Ribbon ? 1 : 0) + GearTextSize * ((byte)item - WeaponStart);
            if (Get(offset, 1)[0] > 200)
            {
                offset++;                 // If the first byte is in the icon range, bump the pointer to overwrite after it.
            }
            else if (Get(offset + 6, 1)[0] <= 200)
            {
                Data[offset + 6] = 0xFF;                 // Erase final non-icon characters from name.
            }

            // Fix up the name of the spell so it works as part of an item name.
            var fixedSpellName = FF1Text.TextToBytes(FF1Text.BytesToText(Spell.Name).PadRight(6), false, FF1Text.Delimiter.Empty);

            Debug.Assert(fixedSpellName.Length == 6);
            Put(offset, fixedSpellName);
        }
Ejemplo n.º 5
0
        public void ShuffleMagicLevels(MT19337 rng, bool keepPermissions, bool tieredShuffle, bool mixSpellbooks, bool noSpellcrafter)
        {
            var magicSpells = GetSpells();

            if (tieredShuffle && noSpellcrafter)
            {
                // if we are doing a tiered shuffle, swap the position of TMPR and SABR before further shuffling for balance purposes
                MagicSpell tmpTMPR = magicSpells[14];
                magicSpells[14] = magicSpells[54];
                magicSpells[54] = tmpTMPR;
            }

            // First we have to un-interleave white and black spells.
            var whiteSpells = magicSpells.Where((spell, i) => (i / 4) % 2 == 0).ToList();
            var blackSpells = magicSpells.Where((spell, i) => (i / 4) % 2 == 1).ToList();

            if (tieredShuffle)
            {
                // weigh spell probability of landing in a tier based on where it was in the original game
                var whiteSpellList      = new List <MagicSpell> [3];
                var blackSpellList      = new List <MagicSpell> [3];
                var whiteSpellFinalList = new List <MagicSpell> [3];
                var blackSpellFinalList = new List <MagicSpell> [3];
                int mergedSpellDoubler  = 1;
                whiteSpellList[0] = magicSpells.Where((spell, i) => (i / 4) % 2 == 0 && i < 24).ToList();
                whiteSpellList[1] = magicSpells.Where((spell, i) => (i / 4) % 2 == 0 && i < 48 && i >= 24).ToList();
                whiteSpellList[2] = magicSpells.Where((spell, i) => (i / 4) % 2 == 0 && i >= 48).ToList();
                blackSpellList[0] = magicSpells.Where((spell, i) => (i / 4) % 2 == 1 && i < 24).ToList();
                blackSpellList[1] = magicSpells.Where((spell, i) => (i / 4) % 2 == 1 && i < 48 && i >= 24).ToList();
                blackSpellList[2] = magicSpells.Where((spell, i) => (i / 4) % 2 == 1 && i >= 48).ToList();
                if (mixSpellbooks)
                {
                    whiteSpellList[0]  = whiteSpellList[0].Concat(blackSpellList[0]).ToList();
                    whiteSpellList[1]  = whiteSpellList[1].Concat(blackSpellList[1]).ToList();
                    whiteSpellList[2]  = whiteSpellList[2].Concat(blackSpellList[2]).ToList();
                    mergedSpellDoubler = 2;
                }
                whiteSpellFinalList[0] = new List <MagicSpell> {
                };
                whiteSpellFinalList[1] = new List <MagicSpell> {
                };
                whiteSpellFinalList[2] = new List <MagicSpell> {
                };
                blackSpellFinalList[0] = new List <MagicSpell> {
                };
                blackSpellFinalList[1] = new List <MagicSpell> {
                };
                blackSpellFinalList[2] = new List <MagicSpell> {
                };
                whiteSpells.Clear();
                blackSpells.Clear();
                foreach (MagicSpell spell in whiteSpellList[2])
                {
                    // 70% chance of tier 7-8, 25% chance of tier 4-6, 5% chance of tier 1-3
                    int diceRoll = rng.Between(0, 19);
                    if (diceRoll < 14)
                    {
                        whiteSpellFinalList[2].Add(spell);
                    }
                    else if (diceRoll < 19)
                    {
                        whiteSpellFinalList[1].Add(spell);
                    }
                    else
                    {
                        whiteSpellFinalList[0].Add(spell);
                    }
                }
                foreach (MagicSpell spell in whiteSpellList[1])
                {
                    // 60% chance of tier 4-6, 25% chance of tier 1-3, 15% chance of tier 7-8
                    // if a section of the final list is full, move to another section
                    int diceRoll = rng.Between(0, 19);
                    if (diceRoll < 12)
                    {
                        if (whiteSpellFinalList[1].Count >= 12 * mergedSpellDoubler)
                        {
                            if (whiteSpellFinalList[0].Count >= 12 * mergedSpellDoubler)
                            {
                                whiteSpellFinalList[2].Add(spell);
                            }
                            else
                            {
                                whiteSpellFinalList[0].Add(spell);
                            }
                        }
                        else
                        {
                            whiteSpellFinalList[1].Add(spell);
                        }
                    }
                    else if (diceRoll < 17)
                    {
                        if (whiteSpellFinalList[0].Count >= 12 * mergedSpellDoubler)
                        {
                            if (whiteSpellFinalList[1].Count >= 12 * mergedSpellDoubler)
                            {
                                whiteSpellFinalList[2].Add(spell);
                            }
                            else
                            {
                                whiteSpellFinalList[1].Add(spell);
                            }
                        }
                        else
                        {
                            whiteSpellFinalList[0].Add(spell);
                        }
                    }
                    else
                    {
                        if (whiteSpellFinalList[2].Count >= 8 * mergedSpellDoubler)
                        {
                            if (whiteSpellFinalList[1].Count >= 12 * mergedSpellDoubler)
                            {
                                whiteSpellFinalList[0].Add(spell);
                            }
                            else
                            {
                                whiteSpellFinalList[1].Add(spell);
                            }
                        }
                        else
                        {
                            whiteSpellFinalList[2].Add(spell);
                        }
                    }
                }
                foreach (MagicSpell spell in whiteSpellList[0])
                {
                    // fill the remaining tiers with the tier 1-3 base magic
                    if (whiteSpellFinalList[0].Count >= 12 * mergedSpellDoubler)
                    {
                        if (whiteSpellFinalList[1].Count >= 12 * mergedSpellDoubler)
                        {
                            whiteSpellFinalList[2].Add(spell);
                        }
                        else
                        {
                            whiteSpellFinalList[1].Add(spell);
                        }
                    }
                    else
                    {
                        whiteSpellFinalList[0].Add(spell);
                    }
                }
                // and repeat the process for black magic if we didn't mix spellbooks
                if (mixSpellbooks)
                {
                    // if we mixed spellbooks, split the white (merged) spellbook in halves to set the black spell list
                    blackSpellFinalList[0] = whiteSpellFinalList[0].Take(12).ToList();
                    whiteSpellFinalList[0] = whiteSpellFinalList[0].Except(blackSpellFinalList[0]).ToList();
                    blackSpellFinalList[1] = whiteSpellFinalList[1].Take(12).ToList();
                    whiteSpellFinalList[1] = whiteSpellFinalList[1].Except(blackSpellFinalList[1]).ToList();
                    blackSpellFinalList[2] = whiteSpellFinalList[2].Take(8).ToList();
                    whiteSpellFinalList[2] = whiteSpellFinalList[2].Except(blackSpellFinalList[2]).ToList();
                }
                else
                {
                    foreach (MagicSpell spell in blackSpellList[2])
                    {
                        // 70% chance of tier 7-8, 25% chance of tier 4-6, 5% chance of tier 1-3
                        int diceRoll = rng.Between(0, 19);
                        if (diceRoll < 14)
                        {
                            blackSpellFinalList[2].Add(spell);
                        }
                        else if (diceRoll < 19)
                        {
                            blackSpellFinalList[1].Add(spell);
                        }
                        else
                        {
                            blackSpellFinalList[0].Add(spell);
                        }
                    }
                    foreach (MagicSpell spell in blackSpellList[1])
                    {
                        // 60% chance of tier 4-6, 25% chance of tier 1-3, 15% chance of tier 7-8
                        // if a section of the final list is full, move to another section
                        int diceRoll = rng.Between(0, 19);
                        if (diceRoll < 12)
                        {
                            if (blackSpellFinalList[1].Count >= 12)
                            {
                                if (blackSpellFinalList[0].Count >= 12)
                                {
                                    blackSpellFinalList[2].Add(spell);
                                }
                                else
                                {
                                    blackSpellFinalList[0].Add(spell);
                                }
                            }
                            else
                            {
                                blackSpellFinalList[1].Add(spell);
                            }
                        }
                        else if (diceRoll < 17)
                        {
                            if (blackSpellFinalList[0].Count >= 12)
                            {
                                if (blackSpellFinalList[1].Count >= 12)
                                {
                                    blackSpellFinalList[2].Add(spell);
                                }
                                else
                                {
                                    blackSpellFinalList[1].Add(spell);
                                }
                            }
                            else
                            {
                                blackSpellFinalList[0].Add(spell);
                            }
                        }
                        else
                        {
                            if (blackSpellFinalList[2].Count >= 8)
                            {
                                if (blackSpellFinalList[1].Count >= 12)
                                {
                                    blackSpellFinalList[0].Add(spell);
                                }
                                else
                                {
                                    blackSpellFinalList[1].Add(spell);
                                }
                            }
                            else
                            {
                                blackSpellFinalList[2].Add(spell);
                            }
                        }
                    }
                    foreach (MagicSpell spell in blackSpellList[0])
                    {
                        // fill the remaining tiers with the tier 1-3 base magic
                        if (blackSpellFinalList[0].Count >= 12)
                        {
                            if (blackSpellFinalList[1].Count >= 12)
                            {
                                blackSpellFinalList[2].Add(spell);
                            }
                            else
                            {
                                blackSpellFinalList[1].Add(spell);
                            }
                        }
                        else
                        {
                            blackSpellFinalList[0].Add(spell);
                        }
                    }
                }
                // shuffle each of the final lists
                foreach (List <MagicSpell> spellList in whiteSpellFinalList)
                {
                    spellList.Shuffle(rng);
                }
                if (!mixSpellbooks)
                {
                    foreach (List <MagicSpell> spellList in blackSpellFinalList)
                    {
                        spellList.Shuffle(rng);
                    }
                }
                // and append each in turn to the whitespells / blackspells list
                whiteSpells = whiteSpells.Concat(whiteSpellFinalList[0]).ToList();
                whiteSpells = whiteSpells.Concat(whiteSpellFinalList[1]).ToList();
                whiteSpells = whiteSpells.Concat(whiteSpellFinalList[2]).ToList();
                blackSpells = blackSpells.Concat(blackSpellFinalList[0]).ToList();
                blackSpells = blackSpells.Concat(blackSpellFinalList[1]).ToList();
                blackSpells = blackSpells.Concat(blackSpellFinalList[2]).ToList();
            }
            else
            {
                if (mixSpellbooks)
                {
                    var mergedList = magicSpells.ToList();
                    mergedList.Shuffle(rng);
                    whiteSpells = mergedList.Where((spell, i) => (i / 4) % 2 == 0).ToList();
                    blackSpells = mergedList.Where((spell, i) => (i / 4) % 2 == 1).ToList();
                }
                else
                {
                    whiteSpells.Shuffle(rng);
                    blackSpells.Shuffle(rng);
                }
            }

            // Now we re-interleave the spells.
            var shuffledSpells = new List <MagicSpell>();

            for (int i = 0; i < MagicCount; i++)
            {
                var sourceIndex = 4 * (i / 8) + i % 4;
                if ((i / 4) % 2 == 0)
                {
                    shuffledSpells.Add(whiteSpells[sourceIndex]);
                }
                else
                {
                    shuffledSpells.Add(blackSpells[sourceIndex]);
                }
            }

            Put(MagicOffset, shuffledSpells.Select(spell => spell.Data).Aggregate((seed, next) => seed + next));
            Put(MagicNamesOffset, shuffledSpells.Select(spell => spell.Name).Aggregate((seed, next) => seed + next));
            Put(MagicTextPointersOffset, shuffledSpells.Select(spell => spell.TextPointer).ToArray());

            if (keepPermissions)
            {
                // Shuffle the permissions the same way the spells were shuffled.
                for (int c = 0; c < MagicPermissionsCount; c++)
                {
                    var oldPermissions = Get(MagicPermissionsOffset + c * MagicPermissionsSize, MagicPermissionsSize);

                    var newPermissions = new byte[MagicPermissionsSize];
                    for (int i = 0; i < 8; i++)
                    {
                        for (int j = 0; j < 8; j++)
                        {
                            var oldIndex      = shuffledSpells[8 * i + j].Index;
                            var oldPermission = (oldPermissions[oldIndex / 8] & (0x80 >> oldIndex % 8)) >> (7 - oldIndex % 8);
                            newPermissions[i] |= (byte)(oldPermission << (7 - j));
                        }
                    }

                    Put(MagicPermissionsOffset + c * MagicPermissionsSize, newPermissions);
                }
            }

            // Map old indices to new indices.
            var newIndices = new byte[MagicCount];

            for (byte i = 0; i < MagicCount; i++)
            {
                newIndices[shuffledSpells[i].Index] = i;
            }

            // Fix enemy spell pointers to point to where the spells are now.
            var scripts = Get(ScriptOffset, ScriptSize * ScriptCount).Chunk(ScriptSize);

            foreach (var script in scripts)
            {
                // Bytes 2-9 are magic spells.
                for (int i = 2; i < 10; i++)
                {
                    if (script[i] != 0xFF)
                    {
                        script[i] = newIndices[script[i]];
                    }
                }
            }
            Put(ScriptOffset, scripts.SelectMany(script => script.ToBytes()).ToArray());

            // Fix weapon and armor spell pointers to point to where the spells are now.
            var weapons = Get(WeaponOffset, WeaponSize * WeaponCount).Chunk(WeaponSize);

            foreach (var weapon in weapons)
            {
                if (weapon[3] != 0x00)
                {
                    weapon[3] = (byte)(newIndices[weapon[3] - 1] + 1);
                }
            }
            Put(WeaponOffset, weapons.SelectMany(weapon => weapon.ToBytes()).ToArray());

            var armors = Get(ArmorOffset, ArmorSize * ArmorCount).Chunk(ArmorSize);

            foreach (var armor in armors)
            {
                if (armor[3] != 0x00)
                {
                    armor[3] = (byte)(newIndices[armor[3] - 1] + 1);
                }
            }
            Put(ArmorOffset, armors.SelectMany(armor => armor.ToBytes()).ToArray());

            // Fix the crazy out of battle spell system.
            var outOfBattleSpellOffset = MagicOutOfBattleOffset;

            for (int i = 0; i < MagicOutOfBattleCount; i++)
            {
                var oldSpellIndex = Data[outOfBattleSpellOffset] - 0xB0;
                var newSpellIndex = newIndices[oldSpellIndex];

                Put(outOfBattleSpellOffset, new[] { (byte)(newSpellIndex + 0xB0) });

                outOfBattleSpellOffset += MagicOutOfBattleSize;
            }

            // Confused enemies are supposed to cast FIRE, so figure out where FIRE ended up.
            var newFireSpellIndex = shuffledSpells.FindIndex(spell => spell.Data == magicSpells[FireSpellIndex].Data);

            Put(ConfusedSpellIndexOffset, new[] { (byte)newFireSpellIndex });
        }