예제 #1
0
    public void create_particle(string aType, Vector3 position, Vector3 speed, QuTimer aTimer, float aScale, bool aUseRandomRotation)
    {
        var cache = mCachedParticles[aType];

        if (!cache.has_particle())
        {
            Texture2D tex = null;
            if (aType == "gold")
            {
                tex = ManagerManager.Manager.mNewRef.partGold;
            }
            if (aType == "silver")
            {
                tex = ManagerManager.Manager.mNewRef.partSilver2;
            }
            var newPart = new FlatElementImage(tex, new Vector2(60, 60), 100);
            foreach (Renderer f in newPart.PrimaryGameObject.GetComponentsInChildren <Renderer>())
            {
                f.gameObject.layer = ManagerManager.Manager.mBackgroundManager.mBackgroundLayer;
            }
            cache.return_particle(newPart);
        }
        var emitter = aType == "gold" ? mEmitter2 : mEmitter;
        var part    = emitter.add_particle(cache.take_particle(), position, speed, 1f, aType);

        part.element.HardFlatRotation = Random.Range(0f, 360f);
        part.element.HardScale        = aScale * Vector3.one;
        part.timer = new QuTimer(aTimer.getCurrent(), aTimer.getTarget());
    }
 public GenericAnimation(float aTime, float aForce, System.Action <float, float, FlatElementBase> aChange, System.Func <float, float> aFunction)
 {
     mTime     = new QuTimer(0, aTime);
     mForce    = aForce;
     mChange   = aChange;
     mFunction = aFunction;
 }
 //note, these will hard kill any events so if that event has vital code, it may not be called
 public void remove_event(QuTimer aKey)
 {
     if (aKey != null)
     {
         mEvents.Remove(aKey);
     }
 }
예제 #4
0
 public void skip_cutscene()
 {
     if (mLastCutsceneCompleteCb != null && mLastCutsceneChain != null)
     {
         TED.remove_event(mLastCutsceneChain);
         mLastCutsceneCompleteCb();
         mLastCutsceneChain      = null;
         mLastCutsceneCompleteCb = null;
     }
 }
예제 #5
0
    public void set_for_GRAVE(List <PerformanceStats> aStats)
    {
        //timing vars
        float gIntroText      = 4.5f;
        float gPreScoreCount  = 0.03f;
        float gScoreCount     = 0.2f;
        float gPostScoreCount = 0.07f;
        float gRestart        = 29;

        //disable the depth warning
        mManager.mZigManager.ForceShow = 2;

        //add the gravestone to the scene
        add_character(CharacterIndex.sGrave, true, false);

        //remove the grave
        if (aStats.Last().Character.Age == 999)
        {
            aStats.RemoveAt(aStats.Count - 1);
        }

        //add in fetus in case we skipped it in debug mode
        if (aStats.First().Character.Age != 0)
        {
            aStats.Insert(0, new PerformanceStats(new CharacterIndex(0, 0)));
        }

        //fake it for testing...

        /* TODO DELETE move this into ModeNormalPlay on force kill
         * mCharacters.Last().destroy(); //remove the grave
         * mElement.Remove(mCharacters.Last());
         * mCharacters.RemoveAt(mCharacters.Count -1);
         * Random.seed = 123;
         * for(int i = 0; i < 8; i++)
         * {
         *      if(aStats.Last().Character.Age < (new CharacterIndex(i,0)).Age)
         *      {
         *              PerformanceStats stat = new PerformanceStats(new CharacterIndex(i,Random.Range(0,4)));
         *              stat.update_score(0,Random.value);
         *              stat.update_score(1,Random.value);
         *              stat.Stats = mManager.mGameManager.CharacterHelper.Characters[stat.Character];
         *              aStats.Add(stat);
         *
         *              add_character(stat.Character,false);
         *      }
         * }
         * add_character(CharacterIndex.sGrave,false); //add the grave back in
         */


        //this is all a hack to get the score to show up right...
        float           scoreIncrementor = 0;
        FlatElementText finalScoreText   = new FlatElementText(mManager.mNewRef.serifFont, 70, "0", 21);

        finalScoreText.HardColor = (GameConstants.UiGraveText);
        FlatElementText finalAgeText   = new FlatElementText(mManager.mNewRef.serifFont, 50, "0", 21);
        float           ageIncrementer = 0;

        finalAgeText.HardColor = (GameConstants.UiGraveText);
        //perfectPercent.Text = ((int)(100*aStats.Sum(e=>e.Stats.Perfect+1)/(float)(aStats.Count*3))).ToString() + "%";
        //TODO why this no work??
        finalAgeText.Text = "0";        //aStats.Last().Character.Age.ToString();

        //hack to put things into bg camera
        foreach (Renderer f in finalScoreText.PrimaryGameObject.GetComponentsInChildren <Renderer>())
        {
            f.gameObject.layer = 4;
        }
        foreach (Renderer f in finalAgeText.PrimaryGameObject.GetComponentsInChildren <Renderer>())
        {
            f.gameObject.layer = 4;
        }
        //foreach (Renderer f in perfectEngraving.PrimaryGameObject.GetComponentsInChildren<Renderer>()) f.gameObject.layer = 4;

        Vector3 graveCenter = mCharacters[mCharacters.Count - 1].HardPosition + new Vector3(0, 50, 0);

        finalScoreText.HardPosition = graveCenter + new Vector3(30, -180, 0);
        finalAgeText.HardPosition   = graveCenter + new Vector3(25, 0, 0);
        mElement.Add(finalScoreText);
        //mElement.Add(perfectEngraving);
        mElement.Add(finalAgeText);

        graveCleanup.Add(finalScoreText);
        graveCleanup.Add(finalAgeText);


        TimedEventDistributor.TimedEventChain chain = TED.empty_chain();

        chain = chain.then_one_shot(
            delegate {
            set_sun();
        }
            , 0);
        chain = chain.then(
            low_skippable_text_bubble_event(GameStrings.GetString("SM1"), gIntroText), 3);

        /*.then( //wait a little bit to let the fading finish
         *      low_skippable_text_bubble_event("HERE IS YOUR LIFE STORY",gIntroText)
         *  );*/

        for (int i = 1; i < aStats.Count; i++)
        {
            PerformanceStats ps = aStats[i];


            chain = chain.then_one_shot(
                delegate() {
                if (ps.Character != CharacterIndex.sOneHundred)
                {
                    show_score(ps.Character, (int)ps.AdjustedScore, gPreScoreCount + gScoreCount + gPostScoreCount + 1.5f);
                }
            }
                , gPreScoreCount).then(
                delegate(float aTime)
            {
                if (aTime < gScoreCount)
                {
                    float displayScore  = scoreIncrementor + (aTime / gScoreCount) * ps.AdjustedScore;
                    float displayAge    = ageIncrementer + (aTime / gScoreCount) * (ps.Character.Age - ageIncrementer);
                    finalScoreText.Text = "" + (int)displayScore;
                    finalAgeText.Text   = "" + (int)displayAge;
                }
                if (aTime > gScoreCount + gPostScoreCount)
                {
                    scoreIncrementor   += ps.AdjustedScore;
                    ageIncrementer      = ps.Character.Age;
                    finalScoreText.Text = "" + (int)scoreIncrementor;
                    finalAgeText.Text   = "" + (int)ageIncrementer;
                    return(true);
                }
                return(false);
            },
                0);
        }

        chain = chain.wait(2.5f);

        //CONNECTIONS
        for (int i = 1; i < aStats.Count; i++)
        {
            PerformanceStats ps = aStats[i];



            float gFirstConnectionText = 5f;
            float gConnectionText      = 5f;
            float gPreParticle         = 2f;


            //TODO grave connections
            CharIndexContainerString connections;

            //TODO
            bool wasHard = ps.Stats.Difficulty > 1;
            if (wasHard)
            {
                connections = mManager.mCharacterBundleManager.get_character_stat(ps.Character).CharacterInfo.HardConnections;
            }
            else
            {
                connections = mManager.mCharacterBundleManager.get_character_stat(ps.Character).CharacterInfo.EasyConnections;
            }


            //for each connection, check if it is relevent to the currently looping character
            for (int j = 1; j < aStats.Count; j++)
            {
                var targetCharacter  = aStats[j].Character;                             //charcter we are connecting to
                var targetConnection = connections[targetCharacter];                    //message
                if (targetConnection != null && targetConnection != "")
                {
                    int accumChange = 0;                     //accum change is targetCharacters effect on the current character
                    accumChange = aStats[j].CutsceneChangeSet.accumulative_changes()[ps.Character];

                    if ((wasHard && accumChange > 0) ||                   //if was hard and effect was positive (i.e. hard)
                        (!wasHard && accumChange < 0))                    //if was easy and effect was negative (i.e. easy)
                    {
                        string []       conText = targetConnection.Replace("<S>", "@").Split('@');
                        PopupTextObject npo     = null;
                        chain = chain.then(
                            delegate(float aTime)
                        {
                            if (npo == null)
                            {
                                npo = add_timed_text_bubble(conText[0], gFirstConnectionText + gConnectionText, -0.6f, 1);
                                set_popup_color_for_cutscene_particles(npo, wasHard);
                                create_shine_over_character(targetCharacter, !wasHard, gFirstConnectionText + gConnectionText);
                                TED.add_one_shot_event(
                                    delegate() {
                                    create_shine_over_character(ps.Character, !wasHard, gFirstConnectionText + gConnectionText - 0.3f);
                                }
                                    , 0.3f);
                            }
                            if (npo.IsDestroyed || aTime > gPreParticle)
                            {
                                return(true);
                            }
                            return(false);
                        }
                            , 0);

                        System.Func <FlatElementBase, float, bool> jiggleDelegate =
                            delegate(FlatElementBase aBase, float aTime2)
                        {
                            aBase.mLocalRotation = Quaternion.AngleAxis(Mathf.Sin(aTime2 * Mathf.PI * 2 * 8) * 10f, Vector3.forward);
                            if (aTime2 >= (gFirstConnectionText - gPreParticle) / 4f)
                            {
                                aBase.mLocalRotation = Quaternion.identity;
                                return(true);
                            }
                            return(false);
                        };

                        chain = chain.then_one_shot(
                            delegate()
                        {
                            if (npo != null)
                            {
                                mCharacters[char_to_list_index(targetCharacter)].Events.add_event(jiggleDelegate, 0);
                                ManagerManager.Manager.mMusicManager.play_sound_effect("graveShine");
                            }
                            //create the shine
                        }
                            ).then_one_shot(
                            delegate()
                        {
                            if (npo != null && !npo.IsDestroyed)                                    //if we used softskip, npo could be destroyed at this point
                            {
                                npo.Text = conText.Last();
                                mCharacters[char_to_list_index(ps.Character)].Events.add_event(jiggleDelegate, 0);
                                ManagerManager.Manager.mMusicManager.play_sound_effect("graveShine");
                            }
                        },
                            gFirstConnectionText - gPreParticle).then(
                            delegate(float aTime){
                            if (npo.IsDestroyed || aTime > gConnectionText)
                            {
                                npo = null;
                                return(true);
                            }
                            return(false);
                        }
                            );
                    }
                }
            }
        }

        string deathSentence = "";

        if (aStats[aStats.Count - 1].DeathTime != -1)
        {
            deathSentence += GameStrings.GetString("SM2");
        }
        else
        {
            deathSentence += GameStrings.GetString("SM3");
        }
        if (!aStats [aStats.Count - 1].Character.IsDescriptionAdjective)
        {
            if ("aeiouAEIOU".IndexOf(aStats[aStats.Count - 1].Character.Description[0]) >= 0)
            {
                deathSentence += GameStrings.GetString("SM4");
            }
            else
            {
                deathSentence += GameStrings.GetString("SM5");
            }
        }
        deathSentence += aStats[aStats.Count - 1].Character.Description;

        chain = chain.then(
            low_skippable_text_bubble_event(deathSentence, gIntroText)
            , 1);


        foreach (CharacterIndex e in CharacterIndex.sAllCharacters)
        {
            UnlockRequirements.UnlockData unlockData;
            if (mManager.mMetaManager.UnlockManager.unlockedThisGame.TryGetValue(new UnlockRequirements.FakeCharIndex(e), out unlockData))
            {
                if (unlockData != null)
                {
                    ManagerManager.Log("announcing unlock " + e.StringIdentifier);
                    CharacterIndex ce = new CharacterIndex(e);
                    chain = chain.then_one_shot(
                        delegate(){
                        mUnlockAnnouncer.announce_unlock(ce, unlockData);
                    }
                        , 0).then(
                        delegate(float aTime){
                        return(!mUnlockAnnouncer.IsAnnouncing);
                    }
                        , 0);
                }
            }
        }

        //so we don't announce unlock again when we restart
        mManager.mMetaManager.UnlockManager.unlockedThisGame.Clear();



        if (GameConstants.showReward && aStats[aStats.Count - 1].Character.LevelIndex >= 7)
        {
            FlatElementImage rewardImage = null;
            FlatElementImage rewardFrame = null;
            mModeNormalPlay.mGiftManager.set_background_for_render();
            chain = chain.then_one_shot(
                delegate()  {
                var frameImg = mManager.mCharacterBundleManager.get_image("GIFT_frame");
                rewardFrame  = new FlatElementImage(frameImg.Image, frameImg.Data.Size, 24);
                rewardImage  = new FlatElementImage(mModeNormalPlay.mGiftManager.render_gift(0), new Vector2(2001, 1128), 23);

                //TODO play sound effect
                rewardImage.HardPosition = mFlatCamera.get_point(0, 3);
                rewardFrame.HardPosition = rewardImage.HardPosition;
                rewardImage.SoftPosition = mFlatCamera.get_point(Vector3.zero) + new Vector3(0, 150, 0);
                rewardFrame.SoftPosition = rewardImage.SoftPosition + new Vector3(0, 70, 0);
                mElement.Add(rewardImage);
                mElement.Add(rewardFrame);
                graveCleanup.Add(rewardImage);
                graveCleanup.Add(rewardFrame);

                var subChain = TED.empty_chain().wait(4);
                if (mModeNormalPlay.mGiftManager.gift_count() > 0)
                {
                    for (int i = 1; i < 100; i++)
                    {
                        int localIndex = i % mModeNormalPlay.mGiftManager.gift_count();
                        subChain       = subChain.then_one_shot(
                            delegate(){
                            //TODO sound effect
                            mModeNormalPlay.mGiftManager.render_gift(localIndex);
                        }
                            , 1f);
                    }
                }
            }
                , 2);
            //chain = chain.wait(6);
            //chain = chain.then(skippable_text_bubble_event("YOU ARE THE PERFECT WOMAN!",5,-0.8f,2),0);
        }



        //variables for credits animation..
        float lastTime = 0;

        FlatElementImage[] logos = null;
        //PopupTextObject gameOver = null;
        List <FlatElementText> creditsText = new List <FlatElementText>();
        float scrollSpeed = 820;

        mGraveCompleteCb = delegate()
        {
            Vector3 barYPosition = mFlatCamera.get_point(Vector3.zero) + new Vector3(0, -700, 0);
            TED.add_one_shot_event(
                delegate()
            {
                mManager.mMusicManager.fade_in_extra_music("creditsMusic");
                mManager.mMusicManager.fade_out();
                var imgData         = mManager.mCharacterBundleManager.get_image("BAR");
                var barImg          = new FlatElementImage(imgData.Image, imgData.Data.Size, 24);
                barImg.HardPosition = barYPosition + new Vector3(0, -1000, 0);
                barImg.SoftPosition = barYPosition;
                mElement.Add(barImg);
                graveCleanup.Add(barImg);
            }
                , 0).then_one_shot(
                delegate()
            {
                float lastXPosition = mFlatCamera.get_point(Vector3.zero).x - mFlatCamera.Width / 2 - 100;
                int counter         = 0;
                foreach (string e in GameConstants.credits)
                {
                    string val = e;
                    if (System.Text.RegularExpressions.Regex.IsMatch(e, @"^\d+$"))
                    {
                        val = GameStrings.GetString("GCcredits" + e);
                    }

                    var text          = new FlatElementText(mManager.mNewRef.genericFont, 70, val, 25);
                    float textWidth   = text.BoundingBox.width;
                    text.HardColor    = new Color(1, 1, 1, 1);
                    text.HardPosition = new Vector3(lastXPosition - textWidth / 2f, barYPosition.y, 0);
                    lastXPosition    += -textWidth - 75;
                    creditsText.Add(text);
                    mElement.Add(text);
                    graveCleanup.Add(text);
                    counter++;
                }

                if (GameConstants.SHOW_LOGOS)
                {
                    logos               = new FlatElementImage[3];
                    lastXPosition      += -200;
                    string[] imageNames = new string[] { "LOGO_FA", "LOGO_AI", "LOGO_GL" };
                    for (int i = 0; i < imageNames.Length; i++)
                    {
                        var imgData      = mManager.mCharacterBundleManager.get_image(imageNames[i]);
                        var img          = new FlatElementImage(imgData.Image, imgData.Data.Size, 25);
                        float imgWidth   = img.BoundingBox.width;
                        img.HardPosition = new Vector3(lastXPosition - imgWidth / 2, barYPosition.y, 0);
                        lastXPosition   += -img.BoundingBox.width / 2f - 500;
                        logos[i]         = img;
                        mElement.Add(img);
                        graveCleanup.Add(img);
                    }
                }
            }
                , 1).then_one_shot(
                delegate()
            {
                /* this will fade everything out super slowly
                 * List<FlatElementBase> graveItems = new List<FlatElementBase>(){finalScoreText,perfectPercent};
                 * foreach(FlatElementBase e in
                 *  mCharacters.Cast<FlatElementBase>()
                 *  .Concat(mDiffLabels.Cast<FlatElementBase>())
                 *  .Concat(mScoreLabels.Cast<FlatElementBase>())
                 *  .Concat(mScoreTexts.Cast<FlatElementBase>())
                 *  .Concat(graveItems.Cast<FlatElementBase>()))
                 * {
                 *  e.ColorInterpolationLimit = 0.05f;
                 *  e.SoftColor = GameConstants.UiWhiteTransparent;
                 * }*/
            }
                , 0).then(
                delegate(float aTime)
            {
                //scroll contents down
                Vector3 scroll = new Vector3(scrollSpeed * (aTime - lastTime), 0, 0);
                foreach (FlatElementText e in creditsText)
                {
                    e.SoftPosition = e.SoftPosition + scroll;
                }

                if (logos != null)
                {
                    foreach (FlatElementImage e in logos)
                    {
                        e.SoftPosition = e.SoftPosition + scroll;
                    }
                }

                lastTime = aTime;
                if (Input.GetKeyDown(KeyCode.Alpha0))
                {
                    return(true);
                }

                if (aTime > gRestart)
                {
                    return(true);
                }
                return(false);
            }
                , 0).then_one_shot(
                delegate(){
                mManager.mMusicManager.fade_out_extra_music();
                mManager.restart_game();
            }
                , 0);
            mGraveCompleteChain = TED.LastEventKeyAdded;
        };

        chain = chain.then_one_shot(
            delegate()
        {
            mGraveCompleteCb();
            mGraveCompleteCb = null;
            mGraveChain      = null;
        }
            , 1);

        mGraveChain = TED.LastEventKeyAdded;
    }
예제 #6
0
    public void reset_sunset()
    {
        //reset sunset background
        ShowBackground = true;
        set_sun(0, true);

        //remove characters
        while (mCharacters.Count > 0)
        {
            remove_last_character();
        }

        clear_TED_and_fade_out_bubbles();

        //remove grave scores
        //note, this MUST be called after clear_TED_and_fade_out_bubbles or it's a double cleanup
        foreach (var e in mScoreLabels)
        {
            e.destroy();
            mElement.Remove(e);
        }
        foreach (var e in mScoreTexts)
        {
            e.destroy();
            mElement.Remove(e);
        }
        mScoreLabels.Clear();
        mScoreTexts.Clear();


        //remove shines
        //note, this MUST be called after clear_TED_and_fade_out_bubbles or it's a double cleanup
        foreach (var e in mShineCleanup)
        {
            e.destroy();
            mElement.Remove(e);
        }
        mShineCleanup.Clear();


        //clear out grave events
        //make sure to call clear_TED_and_fade_out_bubbles() first
        if (mGraveChain != null)
        {
            //TED.remove_event(mGraveChain); //should alreday be rmeoved
            mGraveChain = null;
        }
        if (mGraveCompleteChain != null)
        {
            //TED.remove_event(mGraveCompleteChain); //should already be removed
            mGraveCompleteChain = null;
        }
        mGraveCompleteCb = null;



        //cleanup credits
        foreach (var e in graveCleanup)
        {
            var elt = e;
            elt.destroy();
            mElement.Remove(elt);

            //fade out version, but this is no good when rapidly resetting. Not that that's something that happens outside of debug mode

            /*TED.add_one_shot_event(
             *  delegate()
             *  {
             *      elt.SoftColor = new Color(0.5f, 0.5f, 0.5f, 0);
             *  }
             * ).then_one_shot(
             *  delegate()
             *  {
             *      elt.destroy();
             *      mElement.Remove(elt);
             *  }
             * , 2);*/
        }
        graveCleanup.Clear();
    }
예제 #7
0
    public void set_for_CUTSCENE(System.Action cutsceneCompleteCb, NUPD.ChangeSet aChanges, bool aAstronautHack)
    {
        //first we remove all characters from cutscene text that are locked
        List <NUPD.ChangeSubSet> newChanges = new List <NUPD.ChangeSubSet>(aChanges.Changes);

        for (int i = 0; i < aChanges.Changes.Count; i++)
        {
            foreach (CharacterIndex f in CharacterIndex.sAllCharacters)
            {
                if (mManager.mMetaManager.UnlockManager.is_unlocked(f) != 1)
                {
                    newChanges[i].Changes[f] = 0;
                }
            }
        }
        //then we remove text that has no characters assosciated with it
        newChanges = newChanges.Where(e => !e.Changes.is_zero()).ToList();



        //used for skipping cutscene

        /*
         * TED.add_event(
         *      delegate(float aTime)
         *      {
         *              add_timed_text_bubble("CUTSCENE HERE",1);
         *              return true;
         *      },
         * 0).then_one_shot( //dummy
         *      delegate(){cutsceneCompleteCb();},END_CUTSCENE_DELAY_TIME);
         * return;*/

        float gStartCutsceneDelay    = 2.5f;
        float gPerformanceText       = 3.5f;
        float gCutsceneText          = 5f;
        float gCutsceneTextIncrement = .3f;
        float gPreParticle           = 1.5f;
        float gBubblePos             = 0.2f;

        //TODO put in actual random bubbless
        int lastBubbleIndex = Random.Range(0, 3);
        var cutsceneBubbles = new CharacterBundleManager.ImageSizePair[] {
            mManager.mCharacterBundleManager.get_image("CUTSCENE_BUBBLE-0"),
            mManager.mCharacterBundleManager.get_image("CUTSCENE_BUBBLE-1"),
            mManager.mCharacterBundleManager.get_image("CUTSCENE_BUBBLE-2")
        };


        mLastCutsceneCompleteCb = delegate() {
            cutsceneCompleteCb();
            mLastCutsceneCompleteCb = null;
            mLastCutsceneChain      = null;
        };

        //string[] perfectPhrase = {"awful","mediocre","good", "perfect"};
        //string[] performancePhrase = {"horribly","poorly","well", "excellently"};
        PopupTextObject introPo = null;

        TimedEventDistributor.TimedEventChain chain = TED.add_event(
            delegate(float aTime)
        {
            //string text = "";
            if (mModeNormalPlay.CurrentPerformanceStat.Character == CharacterIndex.sFetus)
            {
                //DELETE this has been moved to text files..
                //text = "Prepare to be Born";
            }
            else if (mModeNormalPlay.CurrentPerformanceStat.DeathTime == -1)                    //if we did not die this time
            {
                //TODO use color text here... In fact you should replace color text as yoru standard text object really...
                //text = aChanges.PerformanceDescription.Replace("<P>",perfectPhrase[mBBLastPerformanceGraph.Stats.Perfect]);

                /*string noCapsDescription = mBBLastPerformanceGraph.Character.Description.ToLower();
                 * if(mBBLastPerformanceGraph.Character.IsDescriptionAdjective)
                 *      text = "You lived your life " + noCapsDescription + " " + performancePhrase[(int)Mathf.Clamp(mBBLastPerformanceGraph.Score*4,0,3)] + ".";
                 * else
                 *      text = "You lived your life as a " + noCapsDescription + " " + performancePhrase[(int)Mathf.Clamp(mBBLastPerformanceGraph.Score*4,0,3)] + ".";*/

                //TODO this should be different for age 85 if astronaut
                if (aAstronautHack)
                {
                    introPo = add_timed_text_bubble(GameStrings.GetString("NIM1"), gPerformanceText);
                }
                else
                {
                    introPo = add_timed_text_bubble(aChanges.PerformanceDescription, gPerformanceText);
                }
            }
            return(true);
        },
            gStartCutsceneDelay).then(
            delegate(float aTime)
        {
            if (introPo != null && introPo.IsDestroyed)
            {
                return(true);
            }
            if (!(mModeNormalPlay.CurrentPerformanceStat.Character == CharacterIndex.sFetus))
            {
                if (aTime > gPerformanceText)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            return(true);
        },
            0);


        foreach (var e in newChanges)
        {
            //string changeMsg = Random.Range(0,3) == 0 ? PDStats.negative_sentences[(int)e][0] : PDStats.positive_sentences[(int)e][0];
            var             changes     = e;
            var             diffChanges = e.Changes;
            string          changeMsg   = e.Description;
            PopupTextObject po          = null;

            List <CharacterIndex> aChangedChars = new List <CharacterIndex>();
            List <int>            oldDiffs      = new List <int>();
            List <int>            aDiffs        = new List <int>();
            foreach (CharacterIndex cchar in CharacterIndex.sAllCharacters)
            {
                if (diffChanges[cchar] != 0)
                {
                    aChangedChars.Add(cchar);
                    int nDiff = Mathf.Clamp(mManager.mGameManager.get_character_difficulty(cchar) + diffChanges[cchar], 0, 3);
                    oldDiffs.Add(mManager.mGameManager.get_character_difficulty(cchar));
                    aDiffs.Add(nDiff);
                }
            }

            chain = chain.then(
                delegate(float aTime)
            {
                if (po == null)
                {
                    po = add_timed_text_bubble(
                        changeMsg, gCutsceneText + gCutsceneTextIncrement * aChangedChars.Count,
                        gBubblePos,
                        cutsceneBubbles[lastBubbleIndex]);
                    lastBubbleIndex = (lastBubbleIndex + 1) % 3;

                    //dumb stuff I need to make sure there was actually a change
                    foreach (CharacterIndex cchar in CharacterIndex.sAllCharacters)
                    {
                        if (diffChanges[cchar] != 0)
                        {
                            set_popup_color_for_cutscene_particles(po, changes.is_positive());
                            break;
                        }
                    }
                }
                if (po.IsDestroyed || aTime > gPreParticle)
                {
                    return(true);
                }
                return(false);
            }
                , 0).then(
                delegate(float aTime)
            {
                if (!po.IsDestroyed)
                {
                    mHeadPop.popup_character(aChangedChars.ToArray(), aDiffs.ToArray(), oldDiffs.ToArray(), !changes.is_positive());
                }
                return(true);
            }
                , 0).then(
                delegate(float aTime)
            {
                if (po.IsDestroyed || aTime > gCutsceneText + gCutsceneTextIncrement * aChangedChars.Count - gPreParticle)
                {
                    return(true);
                }
                return(false);
            }
                , 0);
        }

        chain = chain.then_one_shot(delegate(){ mLastCutsceneCompleteCb(); }, END_CUTSCENE_DELAY_TIME);

        //TODO this is a hack fix, need to fix it properly...
        //chain = chain.then_one_shot(delegate() { if(mLastCutsceneCompleteCb != null) mLastCutsceneCompleteCb(); }, END_CUTSCENE_DELAY_TIME);

        mLastCutsceneChain = TED.LastEventKeyAdded;
    }
 public void add_event_raw(System.Func <float, bool> aEvent, float aTime = 0)
 {
     LastEventKeyAdded = new QuTimer(0, aTime);
     mEvents.Add(LastEventKeyAdded, aEvent);
 }
 public void clear_events()
 {
     LastEventKeyAdded = null;
     mEvents.Clear();
 }