注册 | 登录

游侠NETSHOW论坛





查看: 4668|回复: 10
打印 上一主题 下一主题

[外网分享] 从程序角度分析酿造公式 [复制链接]

帖子
397
精华
0
积分
219
金钱
1766
荣誉
2
人气
4
评议
0
跳转到指定楼层
楼主
发表于 2010-1-28 16:47:36 |只看该作者 |倒序浏览
先把结论放前面给懒人看
1. 决定酿造成果价格的因素有:你自己的脸(极为细微的影响),酿造技能等级,水果种类,水果品质,放进去的水果类型,酿造挑战奖励,机器是否改造了“提升品位”,酿造手法的选择。其中,其决定作用的是“放进去的水果类型”
2. 公式为
水果总基础价值*脸因素*酿造技能等级系数*是否升级了提升品位*配方评价系数*水果平均品质系数*是否完成了踩40水果挑战*酿造手法系数
3. 放进去的水果,数量和类型确定了,得到的结果就确定了,与放进去的顺序无关
4. 配方评价与水果的品质无关,你可以用“可怕”品质的水果拿到“太神奇了”评价


OK,懒人可以走了~~

下面我们来看代码。在www.carls-sims-3-guide.com上,Fatmice同志对游戏脚本进行了跟踪和解包,截取了酿造的程序段发布给我们分享。我会在关键的语句上加上我的注释和疑问,有理解不到位的地方请大家指正。

----------------------------------------------我是名为代码的分割线!-----------------------------------------------------

private void NectarFinishTask()
{
    List<Ingredient> fruitsUsed = base.Inventory.FindAll<Ingredient>(false);
    foreach (GameObject obj2 in fruitsUsed)
    {
        base.Inventory.SetNotInUse(obj2);
    }
    if (((fruitsUsed != null) && (fruitsUsed.Count > 0)) && (this.mLastSimToMake != null))
    {
        float num = 0f; //定义了num为水果总原始价值,置初值为0
        float num2 = (((float) RandomGen.NextDouble()) * (kMaxGlobalValueVariance - kMinGlobalValueVariance)) + kMinGlobalValueVariance;
        //你的脸在这里起作用,这里生成了一个随机数,使其加权于两个全局变量的运算值,这两个全局变量的意义不明
        int skillLevel = this.mLastSimToMake.SkillManager.GetSkillLevel(SkillNames.Nectar);
        float num4 = ((kLevel10Multiplier - kLevel0Multiplier) * (((float) skillLevel) / 10f)) + kLevel0Multiplier;
        //定义num4为酿造技能等级加权值
        fruitsUsed.Sort(); //这里对放进容器的水果进行了排序,排序条件不明,不过可以在游戏里试出来
        string str = "";
        bool flag = true; //这个flag的作用是标记是否放置的全是同一种水果
        Ingredient ingredient = fruitsUsed[0];
        string key = "";
        Dictionary<string, int> ingredients = new Dictionary<string, int>();
        if (ingredient != null)
        {
            key = ingredient.Data.Key;
        }
        float num5 = 0f; //定义水果品质综合权值num5的初值为0
        foreach (Ingredient ingredient2 in fruitsUsed)
        {
            if (flag && !key.Equals(ingredient2.Data.Key))
            {
                flag = false; //如果有不同种类的水果,则置为false
            }
            str = str + ingredient2.Data.Key; //把每个水果的key值串起来
            if (!ingredients.ContainsKey(ingredient2.Data.Key))
            {
                ingredients.Add(ingredient2.Data.Key, 1);
            }
            else
            {
                Dictionary<string, int> dictionary2;
                string str9;
                (dictionary2 = ingredients)[str9 = ingredient2.Data.Key] = dictionary2[str9] + 1;
            }
            num += ingredient2.Data.NectarValue; //把水果的基础价值累加
            num5 += (float) ingredient2.GetQuality(); //把水果的品质权值累加
            base.Inventory.TryToRemove(ingredient2);
        }
        num5 /= (float) fruitsUsed.Count; //获取平均品质权值

       uint hash = ResourceUtils.HashString32(str);
       //这里就是配方评价系数的产生根源了,他把串起来的水果key值字符串放到哈希算法里求出了一个哈希值,这样就使得各个不同组合获得了完全不同的结果
        float num7 = 1f; //定义num7为配方评价系数,置初值为1
        if (!flag)
        {
            num7 = CalculateHashMultiplier(hash);
           //如果使用了不同种类的水果,则用刚才获得的哈希值为种子,计算配方评价系数
        }
        float makeStyleValueModifier = this.GetMakeStyleValueModifier(this.mLastUsedMakeStyle);
       //获取操作手法加权值,通过大家测试的结果可以大致认为浓缩为1.20~1.30,批量为0.70~0.75
        int makeStyleBottleModifier = this.GetMakeStyleBottleModifier(this.mLastUsedMakeStyle);
        
float baseValue = ((((((num * num2) * num4) * this.mFlavorMultiplier) * num7) * kQualityLevelMultiplier[((int) num5) - 1]) * this.mMultiplierFromFeet) * makeStyleValueModifier;
        //这里计算了单瓶价格各个参数的定义参见上面的注释。this.mMultiplierFromFeet这个是踩40次水果的挑战奖励, this.mFlavorMultipli是机器是否升级了提升品位,其值是1.15
        int numBottles = (kNumBottlesPerBatch + this.mBottleDifference) + makeStyleBottleModifier;
       //这个地方算瓶数,瓶数是单独计算的,其本身是不影响单瓶的价值的,但影响瓶数的操作选择影响了基础价格加权值
        NectarSkill skill = this.mLastSimToMake.SkillManager.GetSkill<NectarSkill>(SkillNames.Nectar);
        if ((skill != null) && skill.IsNectarMaster())
        {
            numBottles += NectarSkill.kExtraBottlesNectarMaster; //挑战200瓶,奖励额外的一瓶
        }

       //下面是自动命名等一系列粗活,就不在主贴列出了,详见1楼

------------------------------------------------我是更多结论的分割线-------------------------------------------------

那么我们可以看到实际上那个预测结果的功能就是调用了HASH那一段,所以“还有更好的组合”并不意味着你把6+4调整成7+3会真的有好结果,只是告诉你这个算出来的HASH值落在了一个高不成低不就的窗口区间而已...之所以预言失败是因为这个HASH值并没有真正的投入到CalculateHashMultiplier()函数里去计算,所以总是有误差

另外num2这个看脸的参数,实测影响在0.02+-之间,其实可以忽略...

[ 本帖最后由 diaalphisto 于 2010-1-28 16:58 编辑 ]
已有 2 人评分金钱 人气 收起 理由
ql5069 + 1 高手
游游猪头肉 + 15 對代碼分析的很透徹……

总评分: 金钱 + 15  人气 + 1   查看全部评分

使用道具 举报

帖子
397
精华
0
积分
219
金钱
1766
荣誉
2
人气
4
评议
0
沙发
发表于 2010-1-28 16:49:20 |只看该作者

后半部分代码

List<IngredientNameCount> list2 = new List<IngredientNameCount>();
        foreach (string str3 in ingredients.Keys)
        {
            list2.Add(new IngredientNameCount(str3, ((float) ingredients[str3]) / ((float) fruitsUsed.Count)));
        }
        list2.Sort();
        string str4 = "";
        string str5 = "";
        if (list2.Count > 0)
        {
            str4 = IngredientData.NameToDataMap[list2[0].IngredientName].Name;
        }
        if (list2.Count > 1)
        {
            str5 = IngredientData.NameToDataMap[list2[1].IngredientName].Name;
        }
        List<NectarSkill.NectarBottleInfo> mTopNectarsMade = new List<NectarSkill.NectarBottleInfo>();
        if (skill != null)
        {
            mTopNectarsMade = skill.mTopNectarsMade;
        }
        string mBottleName = "";
        if (string.IsNullOrEmpty(str5))
        {
            mBottleName = Localization.LocalizeString("Gameplay/Objects/CookingObjects/NectarBottle:NectarNameOneFruit", new object[] { str4 });
        }
        else
        {
            mBottleName = Localization.LocalizeString("Gameplay/Objects/CookingObjects/NectarBottle:NectarName", new object[] { str4, str5 });
            if (mBottleName.Length > 40)
            {
                mBottleName = Localization.LocalizeString("Gameplay/Objects/CookingObjects/NectarBottle:NectarNameOneFruit", new object[] { str4 });
            }
        }
        foreach (NectarSkill.NectarBottleInfo info in mTopNectarsMade)
        {
            if (info.mFruitHash == hash)
            {
                mBottleName = info.mBottleName;
            }
        }
        string entryKey = "Gameplay/Objects/HobbiesSkills/NectarMaker:";
        if (flag)
        {
            entryKey = entryKey + "NameBottleDialogJustOneFruit";
        }
        else if (num7 < kPoorComboThreshold)
        {
            entryKey = entryKey + "NameBottleDialogTerribly";
        }
        else if (num7 < kWellComboThreshold)
        {
            entryKey = entryKey + "NameBottleDialogPoor";
        }
        else if (num7 < kGreatComboThreshold)
        {
            entryKey = entryKey + "NameBottleDialogWell";
        }
        else if (num7 < kAmazingComboThreshold)
        {
            entryKey = entryKey + "NameBottleDialogGreat";
        }
        else
        {
            entryKey = entryKey + "NameBottleDialogAmazing";
        }
        string name = StringInputDialog.Show(Localization.LocalizeString("Gameplay/Objects/HobbiesSkills/NectarMaker:NameBottleDialog", new object[0]), Localization.LocalizeString(entryKey, new object[0]), mBottleName, 40, 5);
        bool flag2 = false;
        if (skill != null)
        {
            skill.MadeXBottles(numBottles);
            skill.UsedFruits(fruitsUsed);
            skill.NectarTypeMade(new NectarSkill.NectarBottleInfo(hash, name, ingredients, (int) baseValue));
            flag2 = skill.ReachedMaxLevel();
        }
        int dateNum = ((int) SimClock.ConvertFromTicks(GameStates.TimeInHomeworld.Ticks, TimeUnit.Weeks)) + 1;
        for (int i = 0; i < numBottles; i++)
        {
            NectarBottle item = GlobalFunctions.CreateObjectOutOfWorld("NectarBottle", null, new NectarBottleObjectInitParams(hash, name, list2, "Gameplay/Objects/HobbiesSkills/NectarMaker:Weeks", dateNum, baseValue, baseValue, this.mLastSimToMake, flag2)) as NectarBottle;
            this.mBottles.Add(item);
            EventTracker.SendEvent(EventTypeId.kMadeNectar, this.mLastSimToMake.CreatedSim, item);
        }
        if (this.mBottles.Count > 0)
        {
            this.mCurrentStateMachine.SetActor("nectarBottle", this.mBottles[0]);
        }
        this.mCurrentStateMachine.RequestState("nectarMaker", "Exit");
        this.mCurrentStateMachine.Dispose();
        this.mCurrentStateMachine = null;
        this.mMultiplierFromFeet = 1f;
        this.mLastUsedMakeStyle = MakeNectarStyle.Basic;
        this.mLastSimToMake = null;
        this.CurrentState = NectarMakerState.FruitAddable;
    }
}

使用道具 举报

帖子
569
精华
0
积分
285
金钱
736
荣誉
0
人气
0
评议
0
板凳
发表于 2010-1-28 16:52:53 |只看该作者
囧,资深分析啊,完全看不懂,插个楼溜走

使用道具 举报

帖子
397
精华
0
积分
219
金钱
1766
荣誉
2
人气
4
评议
0
地板
发表于 2010-1-28 17:04:01 |只看该作者
其实我想表达的意思是 看到HASH这个单词的时候我就决定放弃配方测试了 因为这个是完全没有规律可循的...
那边那个帖子就不再测试了,只收集Amazing配方好了。。。

使用道具 举报

帖子
3715
精华
0
积分
1858
金钱
5456
荣誉
0
人气
3
评议
0
5#
发表于 2010-1-28 17:11:04 |只看该作者
总算是有个权威结论了……感谢LZ,感谢砖家,叫兽……

使用道具 举报

帖子
397
精华
0
积分
219
金钱
1766
荣誉
2
人气
4
评议
0
6#
发表于 2010-1-28 18:55:15 |只看该作者
从公式我们可以看出 要拿到最高价值的配方 必须选用最贵的水果
所以应该重点关注生命果 火龙果 克伦烈奴这三个 这3个至少要占都9个水果位置 然后剩下的一个位置用来配一个某种水果 得到更漂亮的哈希值
另外,为了拿到全效果 至少要1个生命果 3个火龙果 所以 高价配方的实际组合是有限的,其中能拿到漂亮哈希值的Amazing配方也是容易排查的.

使用道具 举报

帖子
566
精华
0
积分
283
金钱
1865
荣誉
0
人气
0
评议
0
7#
发表于 2010-1-28 19:10:42 |只看该作者
天哪,我看见这些代码之类的我就要疯了······
我依赖着电脑程序,却讨厌编程
orztse.sinaapp.com→我的Blog

使用道具 举报

帖子
397
精华
0
积分
219
金钱
1766
荣誉
2
人气
4
评议
0
8#
发表于 2010-1-28 19:12:23 |只看该作者
你可以只看结论......

使用道具 举报

SIMS市民

帖子
1111
精华
0
积分
556
金钱
2840
荣誉
0
人气
0
评议
0
9#
发表于 2010-1-28 20:54:40 |只看该作者
谢谢楼主鞑湿,转嫁,交手.......

使用道具 举报

帖子
8
精华
0
积分
4
金钱
298
荣誉
0
人气
0
评议
0
10#
发表于 2012-7-29 23:24:22 |只看该作者
擦,楼主忽悠我们呐?值都没给出呢,还有代码也完全不正确吧?真正写起来根本不可能有那么复杂的,要发就发开发人员的源代码,这些我都能自己想个出来自己写了,连动态链接库的代码或者各值都没说出来,这跟没说没两样

使用道具 举报

帖子
8
精华
0
积分
4
金钱
298
荣誉
0
人气
0
评议
0
11#
发表于 2012-7-29 23:44:05 |只看该作者
楼主必定要解释下为什么9生命果+1石榴比其他很多配方都值钱呢

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

手机版|Archiver|游侠NETSHOW论坛 ( 苏ICP备2023007791号 )

GMT+8, 2025-10-26 18:37 , Processed in 0.360912 second(s), 13 queries , Gzip On, Memcache On.

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

分享到