Beispiel #1
0
 private void setDeathDrain(QbItemArray ar, NotesMarker[] markers)
 {
     if (ar.Items.Count != 0 && ar.Items[0].QbItemType == QbItemType.ArrayStruct)
     {
         foreach (QbItemBase qib in ar.Items[0].Items)
         {
             QbItemStruct hdr = qib as QbItemStruct;
             if (qib != null && hdr.ItemCount == 2 && hdr.Items[0].QbItemType == QbItemType.StructItemInteger && hdr.Items[1].QbItemType == QbItemType.StructItemQbKey)
             {
                 if (((QbItemQbKey)hdr.Items[1]).Values[0] == QbKey.Create("boss_battle_begin_deathlick"))
                     ((QbItemInteger)hdr.Items[0]).Values[0] = Math.Max((uint)this.Length - 11000, (uint)0); //10000 can be read from DeathLick in guitar_battle.qb
             }
         }
     }
 }
Beispiel #2
0
        private void setMarkers(int[] frets, QbItemArray arr, QbFile text, NotesMarker[] markers)
        {
            int minNote = this.Notes.MinNoteOffsetSynced + _startPaddingMs + _fretPadding;
            QbItemStruct s;
            QbItemInteger i;
            QbItemQbKey q;
            QbKey qbKey;
            QbItemString txt;

            for (int c = text.Items.Count - 1; c > 0; c--)
                text.RemoveItem(text.Items[c]);

            if (arr.Items[0] is QbItemFloats)
            {
                QbItemStructArray newArr = new QbItemStructArray(arr.Root);
                newArr.Create(QbItemType.ArrayStruct);
                arr.AddItem(newArr);
                arr.RemoveItem(arr.Items[0]);
            }

            QbItemStructArray sa = (QbItemStructArray)arr.Items[0];
            sa.Items.Clear();

            NotesMarker marker;

            List<NotesMarker> mrk = new List<NotesMarker>(markers);

            if (mrk.Count > 0 && mrk[0].Offset > minNote)  //some charts don't have sections at the start so you can't practice the start notes :-(
            {
                if (mrk[0].Offset > minNote + 5000) // if > 5secs then add new
                    mrk.Insert(0, new NotesMarker("Start", minNote));
                else //else move first marker back to start
                    mrk[0].Offset = minNote;
            }

            for (int c = 0; c < mrk.Count; c++)
            {
                marker = mrk[c];
                if (c < mrk.Count - 1 && mrk[c + 1].Offset < minNote)
                    continue; //don't add sections at the start that would have no notes (crashes song??)

                qbKey = QbKey.Create(string.Format("{0}_markers_text_{1}", this.SongQb.Id, QbKey.Create(marker.Title).Crc.ToString("x").ToLower()));

                txt = new QbItemString(text);
                txt.Create(QbItemType.SectionString);
                txt.ItemQbKey = qbKey;
                txt.Strings = new string[] { marker.Title };
                text.AddItem(txt);

                s = new QbItemStruct(arr.Root);
                s.Create(QbItemType.StructHeader);
                sa.AddItem(s);

                i = new QbItemInteger(arr.Root);
                i.Create(QbItemType.StructItemInteger);
                i.ItemQbKey = QbKey.Create("time");
                i.Values = new uint[] { findNearestFret((uint)marker.Offset, frets) };
                s.AddItem(i);

                q = new QbItemQbKey(arr.Root);
                q.Create(QbItemType.StructItemQbKeyString);
                q.ItemQbKey = QbKey.Create("marker");
                q.Values = new QbKey[] { qbKey };
                s.AddItem(q);
            }
            text.AlignPointers();
            arr.Root.AlignPointers();
        }
Beispiel #3
0
        private int replaceNotesItems()
        {
            int notesLength = 0; //position of final notes item (last fret)
            QbKey song = this.SongQb.Id;
            string songName = song.Text;

            GameFile gf = _project.FileManager.File(_project.GameInfo.GetNotesFilename(song));

            if (gf == null)
                return notesLength; //return 0, this prevents exceptions in the ISO tool which doesn't replace notes

            string notesPak = gf.LocalName;

            PakFormat pf = new PakFormat(notesPak, "", "", _project.GameInfo.PakFormatType);
            PakEditor pak = new PakEditor(pf);
            QbFile qb = pak.ReadQbFile(_project.GameInfo.GetNotesQbFilename(song));

            //modify the mid file
            //clearAllQbItems(qb, this.Notes.GhItems,
            //    QbKey.Create(string.Format("{0}_TimeSig", songName)),
            //    QbKey.Create(string.Format("{0}_FretBars", songName)),
            //    QbKey.Create(string.Format("{0}_Markers", songName)));

            QbFile qbText;
            if (!_project.GameInfo.MidTextInQbPak)
                qbText = pak.ReadQbFile(_project.GameInfo.GetNotesTextQbFilename(song));
            else
            {
                qbText = _project.FileManager.QbPakEditor.ReadQbFile(_project.GameInfo.GetNotesTextQbFilename(song));
            }

            QbItemArray ar;

            int[] ints;
            int offset;

            //calculate ms to add to wav to ensure notes don't start before the given time (in seconds)
            if (this.Notes.MinNoteOffsetSynced < this.MinMsBeforeNotesStart)
                _startPaddingMs = this.MinMsBeforeNotesStart - this.Notes.MinNoteOffsetSynced;

            this.Length = this.Audio.AudioLength + _startPaddingMs;

            offset = this.Notes.BaseFile.NonNoteSyncOffset + _startPaddingMs;

            int[] frets = (int[])this.Notes.BaseFile.Frets.Clone(); //clone in case class is holding reference
            for (int i = 0; i < frets.Length; i++)
                frets[i] += offset;

            //this function sets _fretPadding, another padding value.  It adds padding to allow a properly spaced fret to be at position 0
            frets = adjustFrets(frets);
            notesLength = frets[frets.Length - 1];

            //set the track length to the notes length if it's longer
            if (this.Length < notesLength)
                this.Length = notesLength;
            else
                this.Length += _fretPadding;

            offset += _fretPadding;

            int[] timeSig = (int[])this.Notes.BaseFile.Parser.GetTimeSig().Clone(); //clone in case class is holding reference

            if (timeSig.Length == 0)
                timeSig = new int[] { 0, 4, 4 };

            for (int i = 0; i < timeSig.Length; i += 3)
                timeSig[i] = (int)findNearestFret((uint)(timeSig[i] + offset), frets);

            timeSig[0] = 0; //if the first item is not 0 the song won't load??.

            NotesMarker[] markers = (NotesMarker[])this.Notes.BaseFile.Parser.GetNotesMarkers().Clone(); //clone in case class is holding reference
            for (int i = 0; i < markers.Length; i += 3)
                markers[i] = new NotesMarker(markers[i].Title, markers[i].Offset + offset); //perform deep clone

            int oldSustainTrigger;
            int sustainTrigger;
            int nextNote;
            int[] faceOffP1Ints = new int[0];
            int[] faceOffP2Ints = new int[0];
            GhNotesItem faceOffItem = null;

            //we have a face off item for each mapping, GH3 only has one per song,  find the one with the hardest difficulty (They're always the same anyway)
            foreach (GhNotesItem ghi in this.Notes.GhItems)
            {
                if (ghi.IsMapped && ghi.MappedFileItem.FaceOffP1Count != 0 && ghi.MappedFileItem.FaceOffP2Count != 0)
                {
                    //non generated overrides generated
                    if (faceOffItem == null || faceOffItem.MappedFileItem.HasGeneratedFaceOff || (ghi.MappedFileItem.HasGeneratedFaceOff == faceOffItem.MappedFileItem.HasGeneratedFaceOff))
                    {
                        if (faceOffItem == null || ((int)faceOffItem.Difficulty < (int)ghi.Difficulty && ghi.Type == NotesType.Guitar)) //guitar is more reliable
                            faceOffItem = ghi;
                    }
                }
            }

            if (faceOffItem != null)
            {
                offset = faceOffItem.MappedFileItem.SyncOffset + _startPaddingMs + _fretPadding;

                faceOffP1Ints = (int[])faceOffItem.MappedFileItem.FaceOffP1.Clone();
                for (int i = 0; i < faceOffP1Ints.Length; i += 2)
                    faceOffP1Ints[i] += offset;

                faceOffP2Ints = (int[])faceOffItem.MappedFileItem.FaceOffP2.Clone();
                for (int i = 0; i < faceOffP2Ints.Length; i += 2)
                    faceOffP2Ints[i] += offset;
            }

            foreach (GhNotesItem ghi in this.Notes.GhItems)
            {
                if (ghi.IsMapped)
                {
                    oldSustainTrigger = ghi.MappedFileItem.SustainTrigger;
                    sustainTrigger = (int)((float)(frets[1] - frets[0]) / 2F);
                    ghi.MappedFileItem.SustainTrigger = sustainTrigger;

                    //Offset notes
                    offset = ghi.MappedFileItem.SyncOffset + _startPaddingMs + _fretPadding;

                    ints = (int[])ghi.MappedFileItem.Notes.Clone(); //don't modify original notes
                    int startFret = 0;
                    for (int i = 0; i < ints.Length; i += 3)
                    {
                        ints[i] += offset;
                        if (i + 3 < ints.Length)
                            nextNote = ints[i + 3] + offset;
                        else
                            nextNote = 0;

                        //loop to find fret length note is in to calculate if note is sustained
                        int fpos;
                        int fretLen = 0;
                        bool isSustained = false;
                        for (int c = startFret; c < frets.Length; c++)
                        {
                            if ((fpos = frets[c]) > ints[i] && c > 0) //careful fpos is assigned here
                            {
                                startFret = c; //next time start from here
                                fretLen = fpos - frets[c - 1];
                                isSustained = ints[i + 1] > ((fretLen / 192.0) * (double)(192 >> 2));  //(fretLen / 192.0 == bpmUnit
                                break;
                            }
                        }
                        //clip sustained notes to GH3 mode
                        if (isSustained)
                            ints[i + 1] = setSustain(ints[i], ints[i + 1], nextNote, oldSustainTrigger / 2, sustainTrigger / 2, this.Notes.Gh3SustainClipping);
                    }
                    int[] notes = ints;

                    //if this is a boss battle then remove notes that are not within the face off sections
                    if (this.IsBoss && faceOffItem != null)
                        ints = convertBossNotesToFaceOff(ints, ghi.Type == NotesType.Guitar ? faceOffP1Ints : faceOffP2Ints);
                    ints = adjustNotes(ints); //merge any notes that are really close together

                    //replace track notes
                    ar = (QbItemArray)qb.FindItem(ghi.SongNotesQbKey, false);
                    replaceQbItems(ar, ints, false);
                    setLength(ar, this.Length, 3, frets, false);

                    //Offset star power
                    ints = (int[])ghi.MappedFileItem.StarPower.Clone(); //don't modify original starpower
                    for (int i = 0; i < ints.Length; i += 3)
                        ints[i] += offset;
                    //if (faceOffItem != null)
                    //    alignBattleStarPowerToFaceOff(ints, ghi.Type == NotesType.Guitar ? faceOffP1Ints : faceOffP2Ints);
                    ints = adjustBattleStarPower(ints, notes);

                    //replace star power
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerQbKey, false);
                    replaceQbItems(ar, this.Notes.ForceNoStarPower ? new int[0] : ints, true); //optionally set to no star power
                    setLength(ar, this.Length, 3, frets, false);

                    int[] sp = ints;

                    //Offset star battle mode
                    ints = (int[])ghi.MappedFileItem.BattlePower.Clone();
                    for (int i = 0; i < ints.Length; i += 3)
                        ints[i] += offset;
                    //if (faceOffItem != null)
                    //    alignBattleStarPowerToFaceOff(ints, ghi.Type == NotesType.Guitar ? faceOffP1Ints : faceOffP2Ints);
                    ints = adjustBattleStarPower(ints, notes);

                    if (ints.Length == 0) //if no ints then use star power
                        ints = (int[])sp.Clone(); //just to ensure there's no issue with 2 references pointing at the same array

                    //replace star battle notes
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerBattleQbKey, false);
                    replaceQbItems(ar, ints, true);
                    setLength(ar, this.Length, 3, frets, false);

                }
                else
                {
                    ar = (QbItemArray)qb.FindItem(ghi.SongNotesQbKey, false);
                    clearQbItems(ar);
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerQbKey, false);
                    clearQbItems(ar);
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerBattleQbKey, false);
                    clearQbItems(ar);
                }
            }

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Easy.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Medium.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Hard.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Expert.ToString())), false);
            clearQbItems(ar);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Easy.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Medium.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Hard.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Expert.ToString())), false);
            clearQbItems(ar);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP1", songName)), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP2", songName)), false);
            clearQbItems(ar);

            //start with expert guitar and work down the difficulties to find a GHItem with Face off, copy in to BOss Battle also

            if (faceOffItem != null)
            {
                QbItemArray fo1 = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_FaceOffP1", songName)), false);
                QbItemArray fo2 = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_FaceOffP2", songName)), false);
                if (faceOffItem.IsMapped && faceOffItem.MappedFileItem != null && faceOffItem.MappedFileItem.FaceOffP1Count + faceOffItem.MappedFileItem.FaceOffP2Count != 0)
                {
                    faceOffP1Ints = adjustFaceOff(faceOffP1Ints);
                    replaceQbItems(fo1, faceOffP1Ints, true, 2);

                    //ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP1", songName)), false);
                    //replaceQbItems(ar, faceOffP1Ints, true, 2);

                    faceOffP2Ints = adjustFaceOff(faceOffP2Ints);
                    replaceQbItems(fo2, faceOffP2Ints, true, 2);

                    //ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP2", songName)), false);
                    //replaceQbItems(ar, faceOffP2Ints, true, 2);
                }
                else
                {
                    clearQbItems(fo1);
                    clearQbItems(fo2);
                }

            }

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_TimeSig", songName)), false);
            replaceQbItems(ar, timeSig, true);
            setLength(ar, this.Length, 3, frets, false);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_FretBars", songName)), false);
            replaceQbItems(ar, frets, false);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Markers", songName)), false);
            if (markers.Length != 0)
                setMarkers(frets, ar, qbText, markers);
            else
                calculateMarkers(frets, ar, qbText);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Scripts_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Anim_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Triggers_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Cameras_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Lightshow_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Crowd_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Drums_Notes", songName)), false);
            ////setLength(ar, this.Length, 3, frets, true);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Performance_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Scripts", songName)), false);
            if (this.SongQb.IsBoss) //set the death drain marker to the correct location
                setDeathDrain(ar, markers);
            else
                setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Anim", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Triggers", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Cameras", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Lightshow", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Crowd", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Drums", songName)), false);
            ////setLength(ar, this.Length, 3, frets, true);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Performance", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);

            qb.AlignPointers();
            qb.IsValid();
            qbText.AlignPointers();
            qbText.IsValid();

            long origPakLen = pak.FileLength;
            string tmpPak = string.Format("{0}_{1}", notesPak, Guid.NewGuid().ToString("N"));
            File.Copy(notesPak, tmpPak);

            if (_project.GameInfo.MidTextInQbPak)
            {
                //save markers to qbPak
                _project.FileManager.QbPakEditor.ReplaceFile(_project.GameInfo.GetNotesTextQbFilename(song), qbText);
            }
            else //save markers to mid pak
            {
                pak.ReplaceFile(_project.GameInfo.GetNotesTextQbFilename(song), qbText);
            }

            //replace notes to mid pak
            pak.ReplaceFile(_project.GameInfo.GetNotesQbFilename(song), qb);

            //pad notes pak with original file
            //add padding to ensure song works - This took over a month of testing to find!!
            //////////using (FileStream fs = new FileStream(notesPak, FileMode.Open, FileAccess.ReadWrite))
            //////////{

            //////////    using (FileStream fsI = new FileStream(tmpPak, FileMode.Open, FileAccess.Read))
            //////////    {
            //////////        fs.Seek(0, SeekOrigin.End);

            //////////        string tag = " -=> NANOOK <=-  PADDING BELOW  ";
            //////////        if (fs.Position + tag.Length < fsI.Length)
            //////////            fs.Write(Encoding.Default.GetBytes(tag), 0, tag.Length);

            //////////        if (fs.Position < fsI.Length)
            //////////        {
            //////////            fsI.Seek(fs.Position, SeekOrigin.Begin);
            //////////            copy(fsI, fs, fsI.Length - fsI.Position);
            //////////        }

            //////////    }
            //////////}

            FileHelper.Delete(tmpPak);

            return notesLength;
        }