【Mount&Blade】城市物价的研究

一:城市物价的实质

1:城市物价是怎么设定的?
其实城市有不同的几个,物品有不同,那么不同的城市里的不同物品,同一个城市的不同物品,不同城市的同一个物品,如何区分价格呢?如果直接把货物id作为slot,那么一个item.py里面货物id可能是500以上,也不方便管理。于是设计师就想出了和外交挑衅关系一样的复合slot的方法,首先,在PARTY SLOT里面设定一个专用于价格的基准slot:

slot_town_trade_good_prices_begin

然后货物id比如是388,假如以后自己在第一个货物前面添加一个其他物品比如宝剑,那么该货物的id变成389了,不方便管理,但是如果我们以货物的顺序编号作为货物本身的代替,那么不管日后如何添加(只要不添加在货物的范围里),货物的顺序编号始终不变,也就是货物id减去
trade_goods_begin,然后复合slot就是slot_town_trade_good_prices_begin加上货物顺序编号,然后存入城市的party。这就是物价的实质。

2:在游戏里买一个物品,会发现整个城市里这个物品的价格会提高一下,再买一个又会再高一下。然后卖物品也是同理,这是什么原因?
原来系统硬核里面,有两个script,game_event_buy_item和game_event_sell_item,会在市场窗口里买一个就自动执行一次script,而且不光如此,也可以通过

(call_script, "script_game_event_buy_item", "itm_cattle_meat", 0),

来自行增加一个买卖,尤其是第二个参数如果不是0,那么就物价增加更多一点。全骑砍里只限于向农村买牛。

3:另外还有两个命令

"script_center_get_production", ————获取该party下某物品的产值
"script_center_get_consumption",————获取该party下某物品的消耗值
(set_item_probability_in_merchandise,":cur_goods",":cur_probability"),————设置该物品的充裕度(100分为基准)。

4:关于计算一个Party的某个物品的总需求量,概念如下:
a)总需求量是由该货物的“一般需求量”和其作为原材料投入再生产的“再生产需求量”相加,然后考虑繁荣度因子最后确定组成的。
b)一般需求量只有区分城镇和村庄,城堡是没有需求的,而且城市里也分沙漠地带和非沙漠地带的需求也是不同的。游戏一开始会在script开头地方,对于各个不同的货物定义一些诸如slot_item_desert_demand,slot_item_rural_demand以及slot_item_urban_demand,以此来分别定义这个货物假如在不同的城市或村庄环境下的“一般需求量”。
c)再生产需求量必须要了解一下城市或者村庄的生产量是怎么回事,广义的说,程序应该可以通过把货物的id作为slot来记录party的生产量,
但是游戏里却重新定义了一大堆针对各个不同货物的生产量,比如一个城市的蜂蜜产量,那么先用一个程序

(item_set_slot, "itm_honey", slot_item_production_slot, slot_center_apiaries),

意思是,蜂蜜在城市产量的slot存入蜂蜜的slot_item_production_slot这个slot里,可能是constant打乱的缘故吧,游戏里要调取party的蜂蜜产量,要么记得slot的情况下,直接(party_get_slot, ":base_production", ":center_no", slot_center_apiaries),来获得蜂蜜产量,要么就如下的方式获得。

(item_get_slot, ":蜂蜜城市产量slot", ":蜂蜜", slot_item_production_slot),
(party_get_slot, ":该城市的蜂蜜产量", "$g_encountered_party", ":蜂蜜城市产量slot"),

总之一句话,就是通过许多slot_center_xx来获取该货物在城市的默认产量。回归正题,那么有一些物品比如工具,麦芽酒、油等等,他们是需要原材料比如铁、谷物或者橄榄来制造的,骑砍很严谨,并不是自动造出这些所以既然城市每个时间段会出产一些加工品,那么就一定村庄另一些货物作为原材料,那么也就多了一份消耗,具体可以在"center_get_consumption",这个script里面看。

5:关于一个城镇或村庄货物的生产的基本概念
a)城市或村庄生产的货物是怎么刷出来的,
在trigger里执行一个script——————refresh_center_inventories,那么在这里面就会针对每个城市,每个货物,获得一下他们的产值,然后
给杂货商人刷出来,让你在菜单里能买到。那么是怎么刷给商人的呢?
先设定某一货物的具体充裕度,循环设定所有物品的充裕度。

(set_item_probability_in_merchandise, ":cur_goods", ":cur_production"), 

然后清一清商人物品栏,

(troop_clear_inventory, ":cur_merchant"),

然后执行这个命令:如下,他会硬核根据物品充裕度来添加商品的

      (troop_add_merchandise, ":cur_merchant", itp_type_goods, ":number_of_items_in_town"),

然后确保商人有20个空格子,

      (troop_ensure_inventory_space, ":cur_merchant", 20),

整理一下商人的物品

      (troop_sort_inventory, ":cur_merchant"),

这就解释了为什么有时候香料spicy那么难刷。因为充裕度低啊。
b)party的产值是怎么计算的你进入script_center_get_production就可以发现某个party的某个货物的最终产值,是由基本产值经过价格影响后形成的最终产值,首先是通过slot诸如slot_center_apiaries等获取的“基本产值”还有一个是因为产量会受到价格的影响,里面有个script就是

script_good_price_affects_good_production,

把基本产值去里面滚一圈回来的产值是最终产值。(这里要说一下,获得某物品的消耗script里,由于再生产的消耗是基于“基本产值”而非“最终产值”)

二、电脑满地图的npc会不会在城市里做生意,是怎么个模式。
我们都知道,每隔一段时间,会根据具体情况(比如国家战略或者玩家建议等原因)定义一下大地图上party的行动ai,通过“script_party_set_ai_state,”这个scipt。你打开这个script,你会发现,假如这个party的首领(就是第一个部队槽位)是英雄而不是路人甲。那么,他会执行一个叫(call_script, "script_troop_does_business_in_center", ":commander", ":party_is_in_town"),的命令也就是模拟英雄在城市里收税,如果call_script, "script_troop_does_business_in_center的目标是村庄,那么就是招募兵种。也可以这么理解,就是游戏里,任何party英雄补充兵源是通过两种方式结合的
1:无中生有,就是被打败以后,再次刷出来,那么这时候是通过template reinforcement abc来补充的,就涉及到template
2:已经有了party,active了,那么就是通过这个does business来实现补充兵源的。就是去村庄,根据slot_faction_tier_1_troop里定义的兵种,然后随机升级升一下来实现的。所以,英雄的部队是不会在城市里做生意的。那么如果非英雄部队呢?比如商人
这里我们要明确一个概念,明白如下几个问题:
问题1:为什么一个faction灭亡后,商队全体消失?
在simpley_trigger里面有一个Merchants thinking,里,可以看到

(store_faction_of_party, ":merchant_faction", ":party_no"),
         (faction_get_slot, ":num_towns", ":merchant_faction", slot_faction_num_towns),
         (try_begin),
           (le, ":num_towns", 0),
           (remove_party, ":party_no"),
         (else_try),

这就意味着一旦faction一个城池也不剩,那么这个faction的商队就移除了。

问题2:商人如何选择要走到哪个城市?
通过这个script:

script_cf_select_most_profitable_town_at_peace_with_faction_in_trade_route。

问题3:商人是如何思考的?
首先如果商人所在faction还有城池,那么商队不灭的情况下,如果商队在城市里(也就是说商队在大地图上是不会思考的,逃离劫匪这个属于硬核,并且愿意支付离开城市的关税并且该城市没有被围攻那么他会先判断一下全地图哪个城市获利最大,获得目标城市(有时候会无法判断最佳获利城市,那么就维持-1,也就是再等8秒进行第二次思考),并且确保目标城市不等于他现在所在城市的时候,才会执行如下命令:

(party_set_ai_behavior, ":party_no", ai_bhvr_travel_to_party),
(party_set_ai_object, ":party_no", ":target_center"),
(party_set_flags, ":party_no", pf_default_behavior, 0),
(party_set_slot, ":party_no", slot_party_ai_state, spai_trading_with_town),
(party_set_slot, ":party_no", slot_party_ai_object, ":target_center"),

然后不出意外,移动到了目标城市,这时候,他又开始思考,假如slot_party_ai_state为spai_trading_with_town,那么就开始
执行script————script_do_merchant_town_trade,再引导到script_do_party_center_trade里面,开始做生意,这个script会模拟价格变动
以及城市繁荣度。(记住是模拟,其实商队本身自己是没有物品的,只是战后通过script_party_calculate_loot来模拟一些战利品,并且加载
到trp_temp_troop里。
同理,农民也会和所在城市做生意,Village farmers thinking,也在simple_trigger里。

问题4:商队是怎么被刷出来的,
在trigger里,每隔一秒钟,会有10%的概率执行

(call_script, "script_create_kingdom_party_if_below_limit", ":cur_kingdom",spt_kingdom_caravan),
就是根据上限,刷party
,然后进入这个script,发现
首先,统计一下这个faction的商队有多少个了已经
(call_script, "script_count_parties_of_faction_and_party_type", ":faction_no", ":party_type"),
其次,根据faction的规模获得商队上限。
(assign, ":party_count_limit", 5),
然后根据已有队伍数小于上限的标准,刷
(call_script,"script_cf_create_kingdom_party", ":faction_no", ":party_type"),

然后继续跟踪,进去看,
原来是
先设定(assign, ":party_template", "pt_kingdom_caravan_party"),
接下来设定刷出来的地点

(call_script,"script_cf_select_random_town_with_faction", ":faction_no", -1),
(set_spawn_radius, 0),
  最后设定一些party参数,比如家乡,上一个贸易城市,
(party_set_slot, ":result", slot_party_ai_state, spai_undefined),

再增加一下部队模板

(faction_get_slot, ":reinforcements_b", ":reinforcement_faction", slot_faction_reinforcements_b),
(try_end),
(party_add_template, ":result", ":reinforcements_b"),

最最后,要强调一下【【【【【【【商队刷出来以后,这个party其实是没有实际货物的!,因为只有troop才会有inventory,至于城镇里的马匹商人,那是一个实实在在的troop,和镇长一样,所以他们可以通过troop_add_merchandise来刷新货物,但是商队不行那么商队是怎么实现的呢,还记得骑砍买卖的game硬核吗?是通过获得某个party的复合slot来定义价格的,所以这个script里最后面还会定义一下所有的货物在这个商队环境下的价格,用的是(party_set_slot, ":result",":cur_goods_price_slot", average_price_factor), 也就是定价1000】】】】】

三、如何判断一个party是否在城池里

(party_get_attached_to, ":attached_to_party", ":party_no"),
(is_between, ":attached_to_party", centers_begin, centers_end),

通过这个来表示一个队伍是否在城池里。如果仅限于城镇,那么也可以

(party_is_in_any_town, ":party_no"),

配合

(party_get_cur_town, ":cur_center", ":party_no"),

来实现。
如果一个英雄party在城市里,但是他的新战略是(party_detach, ":party_no"),意味着他要离开这个attach的城市,那么别忘了加(party_detach, ":party_no"),来强制 让部队离开城市。

四、一个faction会刷英雄和刷商人以及刷农民都是不一样的机制

create_kingdom_hero_party
create_kingdom_party_if_below_limit
cf_create_kingdom_party
create_village_farmer_party

五、一个对于party右单击的小发现:对一个party进行右键点击

game_context_menu_get_buttons

六、一个部队ai的研究
a)ai有许多命令,顺序是先设定战略,再设定行动

(call_script, "script_party_set_ai_state", ":party_no", spai_holding_center, ":center_no"),

参数分别是部队名,战略名,战略目标,这样战略就设定好了,
然后会在party_set_ai_state里面,设定具体的行动

(party_set_ai_behavior, ":party_no", ai_bhvr_escort_party),
(party_set_ai_object, ":party_no", ":new_ai_object"),
(party_set_flags, ":party_no", pf_default_behavior, 0),

【party有许多flag,比如让一个party看得见,

(party_set_flags, reg0, pf_always_visible, 1),

或者

(party_set_flags, ":party_no", pf_default_behavior, 0),

0表示这个party在执行过程中会改变行为,如果1,表示强制执行目前的动作,但是要加入(party_set_slot, ":party_no", slot_party_commander_party, -1),来取消party的的上级单位】

b)此外,如果动作时(party_set_ai_behavior, ":party_no", ai_bhvr_travel_to_point),
那么,目标就多一个这个:(party_set_ai_target_position, ":party_no", pos2),比如围城,那么战略目标是“城池”但是围城的方式是通过移动到目标“城池”附近的一个点来表现的,这个要注意收集了,比如洗劫村庄,就是多一个target_position。还有比如动作ai_bhvr_in_town还有ai_bhvr_avoid_party,这种都是硬核决定的。注意收集。
于此同时,部队的ai的具体动作和战略目标的获得:

(get_party_ai_current_behavior, ":ai_bhvr", ":cur_party"),
(get_party_ai_current_object, ":ai_object", ":cur_party"),
(party_get_ai_target_position, pos2, "$qst_capture_conspirators_party_1"),
(party_get_battle_opponent, ":battle_opponent", ":ai_object"),

这里要强调一下,战略的设定诸如spai_holding_center这种的,其实这只是个slot,只是个数字,没有具体意义。用来在party_set_ai_state的script里面更形象化的区分具体该set那个具体动作。而ai_bhvr_avoid_party这种的,就是在header里面定义过的具体的值了,所以spai这种的没有获得的命令,也就是说,战略只是一个过渡决定具体哪个动作的。一个party究竟ai如何还是要看他的具体动作,并不是战略,战略spai只是一过性的过渡专用。是set,而具体动作则是状态。两者不要混淆。

七、工厂的买卖修正
在presentation的budget里找到#Enterprise
工厂和工头对话后的流程是这样的
1:有个这样的slot,

(party_set_slot, "$g_encountered_party", slot_center_player_enterprise_production_order, 0),

当值为0表示全部卖掉,当值为1表示留给自己。
2:于是每隔7天,会在trigger里播放一个presentation,"prsnt_budget_report",工厂的卖出都是在这里面进行的。
3:你在这个"prsnt_budget_report"里看,

(party_get_slot, ":enterprise_output", ":center_no", slot_center_player_enterprise),
 (gt, ":enterprise_output", 1),
 (neg|party_slot_ge, ":center_no", slot_center_player_enterprise_days_until_complete, 1),

意思是,城市的工厂已经开了,并且设施建造时间已经到了。当slot_center_player_enterprise这个slot为0表示工厂关掉了。
4:然后将会模拟一下工厂的运营

(call_script, "script_process_player_enterprise", ":enterprise_output", ":center_no"),

记住,

"script_process_player_enterprise"

这个script在你向工头询问财务报表以及向镇长询问开场收益预判的时候也会用到,因此【【【【【如果你想修正,最好避开这两个,而是新开一个script,这样一来,就不会使得你问问收益预估就发生资金变动】】】】】】】】

5,产品在工厂里生产出来的单价=出产产品的slot基准价 乘以 该城市的价格影响因素,然后再除以1000

a)
(item_get_slot, ":base_price", ":item_type", slot_item_base_price),
获得基准价
b)

(store_sub, ":cur_good_price_slot", ":item_type", trade_goods_begin),
(val_add, ":cur_good_price_slot", slot_town_trade_good_prices_begin),
(party_get_slot, ":cur_price_modifier", ":center", ":cur_good_price_slot"),

获得价格影响因素:cur_price_modifier
c)相乘再除以1000,

(store_mul, ":final_price_for_single_produced_good", ":base_price", ":cur_price_modifier"),
(val_div, ":final_price_for_single_produced_good", 1000),

d)如果想获得总的毛收益,那么还要单价乘以产量

(item_get_slot, ":number_of_outputs_produced", ":item_type", slot_item_output_per_run),
(store_mul, ":final_price_for_total_produced_goods", ":number_of_outputs_produced", ":final_price_for_single_produced_good"),

那么总毛收益就是final_price_for_total_produced_goods的值

e)如果想获得净收益,那么还要总毛收益-工人劳力成本-第一原材料成本-第二原材料成本
那么第一原材料成本,也是单价乘以投入需求量,但是1.174在这个环节就开始有个概念需要明确:就是为什么劳动力成本,第一原料成本和第二原料成本他们的需求量为什么和slot_item_output_per_run的这个值无关?从presentation的(item_get_slot, ":price_of_labor", ":item_type", slot_item_overhead_per_run),开始。首先是劳动力成本,这里只是获取item_type这个物品的slot_item_overhead_per_run这个slot来定义劳动力成本,也许一开始就设定好了产量slot_item_output_per_run,也就是规定在item_type的这个产量下,劳动力成本就直接设置的总值,不需要再乘以产量(但是如果日后想加一个提高产量倍数,可以在这里面增加),那么两个原材料也是一样通过获得(item_get_slot, ":number_of_inputs_required", ":item_type", slot_item_input_number),【【记住,这个slot_item_input_number获得的原料需求量是第一原料和第二原料共用的,也就是生产一个产品,他们第一原料需求量和第二原料需求量是一样的。不再分开定义】】】换言之,slot_item_output_per_run这个定义的不是单个产品所需消耗的原材料的量,而是骑砍这一类产品(已经提前确定了产值),一轮生产所需要的原材料的量,因此不必再乘以产值。【【【【这里要明确,骑砍游戏里,针对原材料,都是先假定全部从市场里拿货,然后假如你在工厂里有先放置原料,那么再从差价里抵扣,从presentation里就可以看到是这么个原理】】】】再来看第二原料的消耗,这里他偷了个懒,没有先写第二原料的单价,然后乘以总需求量,而是直接写了第二原料总需求量final_price_for_secondary_input(而且一开始也没有定义),这样不好需要修正,但是第二原材料会先判断一下产品到底需不需要这个原料(item_slot_ge, ":item_type", slot_item_secondary_raw_material, 1),,这样很好,但是第一原料却没有这样判断也需要修正!!!
第三,原材料的总成本,他只是考虑了原料的单价直接乘以原料的需求量,却没有考虑当你从市场里买走一个原料,那么当你买第二个的时候,这个原料的单价已经上涨了,【【【【这更需要修正!!!!但是记住,不可以在预估里面,只可以在real里面,但是如果你直接模拟了物价变动,那么,就在presentation里面的两个#If the transaction is for real, and not just a budget check都要取消,因为1.174原版在presentation里面模拟过物价变动,但是不准确】】】】

f)工厂默认是一生产出来就全部卖向市场,然后统计到net_profit里去,但是如果你选择保留在仓库,即
slot_center_player_enterprise_production_order等于1,那么他就会计算一下工厂工头有多少个物品栏空格,
然后计算出可以留多少个在工厂内部,然后依据留下的数量,从net_profit里扣除。是这样的一个流程。涉及到两个变量:

":outputs_added_to_warehouse", ":outputs_added_to_market"),

同理可知,原材料到底是从市场里进货还是从工厂里直接拿,涉及到4个变量

":inputs_taken_from_market"
":2ary_inputs_taken_from_market"

这两个应该是相等的。

":inputs_taken_from_warehouse"
":2ary_inputs_taken_from_warehouse"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354