public static void GenerateSkills(PlayerExporter exporter, CodeGenerator output)
        {
            SkillGeneratorEnv env = (SkillGeneratorEnv)exporter.GenEnv;

            for (int i = 0; i < exporter.Skills.Count; ++i)
            {
                var skill         = exporter.Skills[i];
                var skillFuncName = "skill_" + i.ToString();
                if (skill is NormalSkill)
                {
                    var cskill = (NormalSkill)skill;
                    env.CurrentSkillKeyName = cskill.Key.GetKeyName();
                    env.CurrentActionName   = cskill.ActionID;

                    var functionContent = GenerateNormalSkillFunction(exporter, env, cskill.ActionID, false);
                    functionContent = new ILineObject[] {
                        new ControlBlock(ControlBlockType.If, "!(\"uu\" in this.u)", new ILineObject[] {
                            new SimpleLineObject("this.u.uu <- { uuu = this.u.weakref() };"),
                        }).Statement(),
                    }.Concat(functionContent);

                    var func = new FunctionBlock(skillFuncName, new string[0], functionContent);
                    output.WriteStatement(func.Statement());
                }
            }
        }
        private static IEnumerable <ILineObject> GenerateNormalSkillFunction(PlayerExporter exporter,
                                                                             SkillGeneratorEnv env, string id, bool stateLabelAsUpdate)
        {
            List <ILineObject> ret = new List <ILineObject>();

            var action = exporter.GetAction(id);
            var ae     = new Pat.ActionEffects(action);

            foreach (var b in action.Behaviors)
            {
                b.MakeEffects(ae);
            }

            exporter.SSERecorder.AddAction(ae, env.GetActionID(id), env);

            ret.AddRange(ae.InitEffects.Select(e => e.Generate(env)));

            var list2 = ae.UpdateEffects.Select(e => e.Generate(env));

            list2 = new ILineObject[] { GenerateNormalSkillUpdateSSEChecker() }.Concat(list2);
            if (stateLabelAsUpdate)
            {
                list2 = list2.Concat(new ILineObject[] { new SimpleLineObject("return true;") });
            }

            var         updateFunc = new FunctionBlock("", new string[0], list2).AsExpression();
            ILineObject setUpdate;

            if (stateLabelAsUpdate)
            {
                setUpdate = ThisExpr.Instance.MakeIndex("SetUpdateFunction").Call(updateFunc).Statement();
            }
            else
            {
                setUpdate = ThisExpr.Instance.MakeIndex("stateLabel").Assign(updateFunc).Statement();
            }
            ret.Add(setUpdate);

            var keys = ae.SegmentFinishEffects.Select(
                keyEffect => new FunctionBlock("", new string[0], keyEffect.Select(e => e.Generate(env))).AsExpression());
            var keyCount = action.Segments.Count - 1;

            if (ae.SegmentFinishEffects.Count < keyCount)
            {
                keyCount = ae.SegmentFinishEffects.Count;
            }
            var arrayObj = new ArrayExpr(keys.Take(keyCount).ToArray());
            var setKey   = ThisExpr.Instance.MakeIndex("keyAction").Assign(arrayObj).Statement();

            ret.Add(new SimpleLineObject("this.SetEndTakeCallbackFunction(this.KeyActionCheck);"));
            ret.Add(setKey);

            if (ae.SegmentFinishEffects.Count >= action.Segments.Count)
            {
                var effects       = ae.SegmentFinishEffects[action.Segments.Count - 1].Select(e => e.Generate(env));
                var funcEndMotion = new FunctionBlock("", new string[0], effects).AsExpression();
                var setEndMotion  = ThisExpr.Instance.MakeIndex("SetEndMotionCallbackFunction").Call(funcEndMotion).Statement();
                ret.Add(setEndMotion);
            }

            return(ret);
        }