本帖最后由 huagao 于 2025-10-18 17:11 编辑
Ini配置文件是骑砍初始化设置的文件,里面涵盖了很多mod的配置设置。而前段时间我研究维京源码的时候扫了一眼发现有一些维京独有的设置,拿破仑同理,正好中文站我一直没有找到关于ini的集成,那暂且将就自己的研究写一下大概。 首先说明一下,ini里大部分都是布尔类型,是某些功能的开关,剩下部分都是功能参数,浮点数和整型都有,还有很少一部分是字符串,就是些brf名字啊mod名字甚么的,这个看一原数据应该都知道就不再多说。 然后整理一下ini的大概框架,ini里的参数大概由:mod基础信息,大地图参数,部队/兵种参数,物品参数,战场参数,游戏功能参数,着色器图像参数,联机参数组成。接下来挨个写一下。 module_name = rgl日志返回的mod名 module_version = mod版本 compatible_module_version = 兼容的游戏版本(应该是和联机有关) compatible_multiplayer_version_no = 和上一条一起用,联机用的 compatible_savegame_module_version = 同上 compatible_with_warband = 原版遗留下来的开关,适配战团的? operation_set_version = 维京的东西,应该是和和(get_operation_set_version, ), 搭配使用(也有一说是强制使用新版本的API,但是我测试无效) works_with_version_max = 应该是原版骑砍的东西,战团改成了那几个compatible参数 works_with_version_min = 同上 num_hints = 加载界面的提示数量 load_resource = 调用brf的声明,可以调用战团根目录CommonRes中的brf,也可以用这个调用mod根目录resources的brf load_resource_nofast = 跟上面好像一样,看名字的意思是更慢? load_mod_resource = 调用brf的声明,只能用于mod根目录的resources load_module_resource = 跟上面一样,不是简写罢了。 scan_module_sounds = 是否调用mod根目录的sounds里的资源 scan_module_textures = 是否调用mod根目录的textures里的资源 use_case_insensitive_mesh_searches = 是否对调用资源区分大小写(例如Aaa和aaa声明的时候只声明一个,这个我用来做一些测试brf,没问题的用小写,还没尝试的就丢进大写,虽然不知道有什么意义。。) |
map_max_distance = 控制大地图的缩放极限 map_min_x = 确定世界地图的东部边界。地图可以继续越过这个边界,但各方将无法越过这个边界。 map_max_x = 确定世界地图的西部边界。地图可以继续越过这个边界,但各方将无法越过这个边界。 map_min_y = 确定世界地图的北部边界。地图可以继续越过这个边界,但各方将无法越过这个边界。 map_max_y = 确定世界地图的南部边界。地图可以继续越过这个边界,但各方将无法越过这个边界。 以上四个是大地图的区域划分,看命名应该就知道了,min为负,max为正 map_sea_direction = 海浪的方向? map_sea_wave_rotation = 战团ini注释说是可以看到破洞的地方?
map_sea_speed_x = map_sea_speed_y = 大地图上海洋的流动速度
map_min_elevation = map_max_elevation = 这俩应该是镜头缩放的控制
map_river_direction = map_river_speed_x = map_river_speed_y = 河流显示的流动速度和方向?我寻思战团那河流不流也没啥影响啊
map_tree_types = 大地图地形上tree的数量,模型在战团自带的map_treel里面,下面同理 map_desert_tree_types = 沙漠地形中沙漠树的数量 map_snow_tree_types = 雪地地形中雪树的数量 map_steppe_tree_types = 草原地形中草原树的数量
starting_day = 开始游戏的日期时间,用脚本game get date text也可以设置 starting_month = starting_year = time_multiplier = 大地图时间流逝速度,战团默认0.25,ctrl空格可以快进的那个
seeing_range = party在大地图上的视野半径范围 Show_party_ids_instead_of_names = 在大地图party会显示id而不是名称,应该是开发用的 auto_create_note_indices = 不会自动遍历所有的troops/factions/towns区检查它们是否有text注释 auto_compute_party_radius = 维京里面扒的,大地图上有大图标并移动镜头时,当大图标的边缘还没出镜头但是大图标的中心点已经出镜头的时候,大图标会瞬间不见,开启这个参数可以修正这个问题,这样就算大图标中心点出镜了,大图标还是可以看见剩下那一部分的。 disable_disband_on_terrain_type = 同样是维京找的,禁止在对应的地形上解散。应该是对应维京不准再海上遣散,不然茫茫大海也没地方去,说不过去。这个的用法应该不是布尔型的开关,对应的应该是header terrain types.py里面地形的id,这样就说的通了,维京里给的参数是0,就对的上我这个说法了 use_strict_pathfinding_for_ships = 还是维京的,船只在海上显示航路 |
attribute_points_per_level = 每次升级获得的属性点
skill_points_per_level = 每次升级获得的技能点
weapon_points_per_level = 每次升级获得的熟练度点
hero_xp_multiplier = hero型trp杀敌获得经验的倍数系数
regulars_xp_multiplier = 普通型trp(小兵)杀敌获得经验的倍数系数
level_boundary_multiplier = 升级所需的经验倍数
player_xp_multiplier = 玩家杀敌获得经验的倍数系数
skill_leadership_bonus = 统御技能每点增加人数上限
base_companion_limit = 没点统御的玩家队伍npc的数量
skill_prisoner_management_bonus = 俘虏管理技能每点增加俘虏人数上限
track_spotting_multiplier = 侦察技能每点的作用范围(从水浒那边玩家的探讨发现如果地图很大,party数量比较多的话,这个系数可能会影响到大地图掉帧。设置为0就不会有脚印生成了)
attribute_required_per_skill_level = 加技能需要的对应属性的增值(例如一点铁骨需要3点力量)
can_run_faster_with_skills = 敏捷和跑动对移速的影响,在T社的论坛找了大概的公式: 布尔型为1时:((敏捷+跑动*6+25)*30 / (负重+30)+90)/100,布尔型为0时:((敏捷* 0.7+跑动*3+25)*70 / (负重+70)+90)/100
hero_wounded_treshold = hero型trp最低进入战斗的血量
player_wounded_treshold = 玩家最低进入战斗的血量
|
display_wp_one_handed = display_wp_polearms = display_wp_throwing = display_wp_two_handed = display_wp_archery = display_wp_crossbows = display_wp_firearms = 以上都是屏蔽相关类型武器熟练度在角色主界面显示的开关,正如很多mod屏蔽了火器一样,实际上只是不显示,这个熟练度仍然存在的,而且杀敌的时候还是可以获取到对应的经验
meek_modifier_speed_bonus = timid_modifier_speed_bonus = 以上是给对应前缀的马匹设置速度加/减成的开关,这是维京那找的,不知道其他前缀有没有,还没尝试,有时间的可以帮忙尝试一下看看是不是所有马匹前缀都可以
use_crossbow_as_firearm = 因为战团当时给VC的支持,导致火器的伤害逻辑里面加了熟练度和力量的加成(适配VC的投石索),后来为了拿破仑那边的火器,又加了这个开关,以避免正常火器的伤害计算不合理 shorter_pistol_aiming = 和上条一样,vc针对手枪的这种特殊情况的排除 can_reload_while_moving = 移动装填开关,和上一条搭配使用 use_phased_reload = 被打断装填动作不需要重新开始,配合itcf_reload_musket或itcf_reload_pistol使用 |
maximum_number_of_notification_messages = 战场消息的数量 battle_size_min = 维京里的,战场规模 battle_size_max = far_plane_distance = 同样时维京的,场景内最远的渲染视野/地形边界,默认是1250cm mission_object_prune_time = 移除prop的时间,单位是秒,但是代码中途加进去的不适用这个,可以适用于射出去的箭矢或掉在地上或初始存在的东西之类的 use_advanced_formation = 这个是阵型,0就是战团的阵型指挥,1就是拿破仑的,启用的话应该需要调整ui.csv,添加新命令的文本
air_friction_arrow = 设置箭矢的阻力系数,战团默认0.002 air_friction_bullet = 设置子弹的阻力系数,战团默认0.002 crush_through_treshold = 需要多少伤害突破格挡,需要itp crush through的flag
shield_penetration_factor = shield_penetration_offset = 投射物伤害 > shield_penetration_offset + shield_penetration_factor * 盾牌防御,就可以穿盾
armor_soak_factor_against_cut = armor_soak_factor_against_pierce = armor_soak_factor_against_blunt = 上面这仨是决定护甲直接减免的伤害(砍伤/刺伤/钝伤)
armor_reduction_factor_against_cut = armor_reduction_factor_against_pierce = armor_reduction_factor_against_blunt = 上面这仨是决定护甲百分比减免的伤害(砍伤/刺伤/钝伤)
extra_penetration_factor_reduction = extra_penetration_factor_soak = 额外被护甲减免伤害的参数,给武器上itp_extra_penetration可以从上面这俩里面获取收益,设置为0就可以无视护甲,设置为1就是等于没设置。同样soak是直接减伤,reduction是百分比减伤
melee_damage_speed_power = missile_damage_speed_power = 上面这俩就是设置为2.0时,近战武器/投射物的伤害会和其速度速度的平方成正比,设置成1.0就是线性的了
couched_lance_damage_multiplier = 长枪的额外伤害 damage_interrupt_attack_threshold = 打出硬直的最低伤害(再低就不能打断近战攻击) damage_interrupt_attack_threshold_mp = 同上,联机用的 no_friendly_fire_for_bots = 联机里面ai不打友军 ai_decide_direction_according_to_damage = 开启后AI在决定使用哪种攻击时会考虑每个方向攻击的伤害 apply_all_ammo_damage_modifiers = 维京的东西,弹药会施加对应的砍伤/刺伤/钝伤 brace_rotation_limit = 拿破仑的东西,默认值是0.01,不能低于默认值,如果大于0.5就会失效。限制矛类武器的动画旋转效果的? fall_damage_multiplier = 掉落伤害的加成 horse_charge_damage_multiplier = 马撞人的伤害加成 lance_pike_effect_speed = 马匹会被长枪截停(停龙车)的最低速度 disable_attack_while_jumping = agent跳跃时是否可以攻击的开关,打开后跳跃也不会打断攻击动作 consider_weapon_length_for_weapon_quality 维京来的,AI会把武器的长度也考虑进使用哪个武器的的算法中,具体的算法丢在最后 |
dont_supress_initial_warnings = 不会往rgl日志文件中输出WARNING警告,比如那几个战团没有的音效和脚本还有界面 give_performance_warnings = 会给出各种奇怪的警告,包括但不限于模型,碰撞和代码 dont_load_regular_troop_inventories = 存档保存普通兵种(小兵)物品栏的开关(会影响存档时间和大小)
has_custom_battle = 关掉就没有主界面的自定义战斗了 has_multiplayer = 关掉就没有主界面的联机游戏了 has_single_player = 关掉就没有主界面单机游戏的新建和加载了 has_tutorial = 关掉就没有主界面的教程了 enable_quick_battles = 快速战斗是原版的功能吧,这也是个历史遗留物 (以上几个控制主界面功能的开关方式还有一种办法就是在game variables.txt里面找到对应overlay的pos参数,把它们移出界面外,这里面参数是按照屏幕长宽 1*0.75来的,无论你的屏幕是什么尺寸长宽比,也不管你的分辨率是多少。我在解侠里面就用了这种方法因为我当时沙比,想了个大脑洞结果补不出来。)
has_accessories_for_female = 选女号开局的话,捏脸界面有胡子UI的调整 limit_hair_colors = 头发的设置,应该是启用这个才会调用那几个hair_black/red之类的
Show_faction_color = party的颜色是否会用对应阵营的颜色 isable_force_leaving_conversations = 禁用TAB键强行跳出对话 show_troop_upgrades_button = 维京找的,部队界面显示升级button,接口是game_troop_upgrades_button_clicked show_quest_notes = 任务界面是否出现提示 can_adjust_camera_distance = 用小键盘加减缩放cam位置的开关 disable_zoom = 是否可以使用gk_zoom缩放cam位置的开关,用(is_zoom_disabled),可以检测 can_crouch = 是否可以蹲下的开关,开启这个的话还是需要手动添加包括ui等 can_objects_make_sound = 场景物可以播放sound的开关 can_use_scene_props_in_single_player = 单机游戏也可以和场景物互动的开关 disable_moveable_flag_optimization = 场景物不需要sokf_moveable就可以动,有一个冷知识,古早时代的1143版本一部分的闪退可以启用这个解决 disable_food_slot = 启用食物装备栏(古早骑砍的设定,再item的头文件中可以找到ek_food = 9,没啥用了已经,早期把马匹放进去会被鲨了吃肉) has_forced_particles = 用这个可以强制关闭粒子效果 horses_rear_with_attack = 马被毒打时会不会后退的开关 horses_try_running_away = 没人骑的马会不会瞎溜达的开关 |
supports_directx_7 = 是否支持DX7,现在应该没啥用了,没谁的不支持了吧
use_scene_unloading = use_texture_degration_cache = 以上两组分别针对场景和纹理贴图,系维京里面找到的。个人推测测试,布尔类型开关,开启的话,从场景出去或脱离贴图使用范围时就会从“内存池”里面去除该场景/纹理贴图,如再次使用会重新加载;关闭的话就直接是加载“内存池”里面的资源了。 加载频繁的话就费时间,但是节约资源。需要自己把握(经过老奥的测试,对加载资源等有改善,但是会针对资源文件单独生成缓存文件)
reduce_texture_loader_memory_usage = 多线程处理,可以缩短进游戏加载时间 add_set_neighbors_to_tangent_flag_to_shader = 只知道是个着色器参数 blood_multiplier = 维京的血液特效参数 disable_high_hdr = 故名思意,禁用高HDR效果 fix_gamma_on_dx7_operation_colors = 着色器参数,应该和那几个set_startup_xxx_light的操作函数有关系吧 screenshot_format = 按Ctrl和 Insert截图,赋值决定截图格式。0是jpg,1是png,2是bmp |
因为中文站的代码展示会吞掉缩进,所以这里直接丢
void mbTroop::equipItems(int dna, bool requireCivilian, bool prohibitFullhelm)
{
if (m_flags & tf_inactive)
return;
bool bowEquipped = false;
bool bowAmmoEquipped = false;
bool crossbowEquipped = false;
bool crossbowAmmoEquipped = false;
bool gunEquipped = false;
bool gunAmmoEquipped = false;
bool oneHanderEquipped = false;
bool shieldEquipped = false;
bool polearmEquipped = false;
bool swordEquipped = false;
unequipItems();
unsigned int requireFlags = 0;
unsigned int ignoreFlags = 0;
if (isHero() && requireCivilian)
requireFlags = itp_civilian;
if (isHero() && prohibitFullhelm)
ignoreFlags = itp_covers_head;
equipItemSlot(dna, ek_head_armor, requireFlags, ignoreFlags, -1, -1, -1, (m_flags & tf_guarantee_helmet) != 0);
equipItemSlot(dna, ek_body_armor, requireFlags, ignoreFlags, -1, -1, -1, (m_flags & tf_guarantee_armor) != 0);
equipItemSlot(dna, ek_leg_armor, requireFlags, ignoreFlags, -1, -1, -1, (m_flags & tf_guarantee_boots) != 0);
equipItemSlot(dna, ek_hand_armor, requireFlags, ignoreFlags, -1, -1, -1, (m_flags & tf_guarantee_gloves) != 0);
equipItemSlot(dna, ek_horse, 0, ignoreFlags, -1, -1, -1, (m_flags & tf_guarantee_horse) != 0);
for (int i = ek_weapon_0; i <= ek_weapon_3; ++i)
{
bool equipped = false;
if (i == ek_weapon_0)
{
bool guaranteeRanged = (m_flags & tf_guarantee_ranged) != 0;
equipped = equipItemSlot(dna, 0, 0, ignoreFlags, itp_type_pistol, itp_type_musket, -1, guaranteeRanged);
if (!equipped)
equipped = equipItemSlot(dna, 0, 0, ignoreFlags, itp_type_bow, itp_type_crossbow, itp_type_thrown, guaranteeRanged);
if (equipped)
{
switch (m_equipment.getItemKind()->getType())
{
case itp_type_bow:
bowEquipped = true;
break;
case itp_type_crossbow:
crossbowEquipped = true;
break;
case itp_type_thrown:
oneHanderEquipped = true;
break;
case itp_type_pistol:
case itp_type_musket:
gunEquipped = true;
break;
}
}
}
if (!equipped && bowEquipped && !bowAmmoEquipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_arrows, -1, -1, true);
if (equipped)
bowAmmoEquipped = true;
}
if (!equipped && crossbowEquipped && !crossbowAmmoEquipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_bolts, -1, -1, true);
if (equipped)
crossbowAmmoEquipped = true;
}
if (!equipped && gunEquipped && !gunAmmoEquipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_bullets, -1, -1, true);
if (equipped)
gunAmmoEquipped = true;
}
if (!equipped && oneHanderEquipped && !shieldEquipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_shield, -1, -1, (m_flags & tf_guarantee_shield) != 0);
if (equipped)
shieldEquipped = true;
}
if (!equipped && !polearmEquipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_polearm, -1, -1, (m_flags & tf_guarantee_polearm) != 0);
if (equipped)
{
polearmEquipped = true;
if (!(m_equipment.getItemKind()->m_properties & itp_two_handed))
oneHanderEquipped = true;
}
}
if (!equipped && !swordEquipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_one_handed, itp_type_two_handed, -1, true);
if (equipped)
{
swordEquipped = true;
if (!(m_equipment.getItemKind()->m_properties & itp_two_handed))
oneHanderEquipped = true;
}
if (!equipped && !polearmEquipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_polearm, -1, -1, true);
if (equipped)
{
polearmEquipped = true;
if (!(m_equipment.getItemKind()->m_properties & itp_two_handed))
oneHanderEquipped = true;
}
}
}
if (!equipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_thrown, -1, -1, false);
if (equipped)
oneHanderEquipped = true;
}
if (!equipped)
{
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_one_handed, itp_type_two_handed, -1, false);
if (equipped)
{
if (!(m_equipment.getItemKind()->m_properties & itp_two_handed))
oneHanderEquipped = true;
}
}
if (!equipped && bowEquipped)
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_arrows, -1, -1, false);
if (!equipped && crossbowEquipped)
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_bolts, -1, -1, false);
if (!equipped && gunEquipped)
equipped = equipItemSlot(dna, i, 0, ignoreFlags, itp_type_bullets, -1, -1, false);
if (isHero() && !equipped)
{
if (!equipItemSlot(dna, i, 0, ignoreFlags, itp_type_thrown, -1, -1, true))
{
if (equipItemSlot(dna, i, 0, ignoreFlags, itp_type_one_handed, itp_type_two_handed, itp_type_polearm, true))
{
if (!(m_equipment.getItemKind()->m_properties & itp_two_handed))
oneHanderEquipped = true;
}
}
}
}
}
bool mbTroop::equipItemSlot(int dna, int itemSlotNo, unsigned int requireFlags, unsigned int ignoreFlags, int requiredItemType1, int requiredItemType2, int requiredItemType3, bool guarantee)
{
int inventorySlotNo = findSuitableItem(dna, itemSlotNo, requireFlags, ignoreFlags, requiredItemType1, requiredItemType2, requiredItemType3, guarantee);
if (inventorySlotNo < 0)
return false;
unequipItem(itemSlotNo);
m_equipment[itemSlotNo] = m_inventory[inventorySlotNo];
m_inventory[inventorySlotNo].m_itemKindNo = -1;
return true;
}
int mbTroop::findSuitableItem(int dna, int itemSlotNo, unsigned int requireFlags, unsigned int ignoreFlags, int requiredItemType1, int requiredItemType2, int requiredItemType3, bool guarantee)
{
int numInventorySlots = getNumInventorySlots();
int numSuitableItems = 0;
for (int i = 0; i < numInventorySlots; ++i)
{
if (m_inventory.isValid() && isInventoryItemSuitable(i, itemSlotNo, requireFlags, ignoreFlags, requiredItemType1, requiredItemType2, requiredItemType3))
numSuitableItems++;
}
if (rglConfig::Battle::bRandomTroopEquipping)
{
if (numSuitableItems <= 0)
return -1;
if (!guarantee)
numSuitableItems++;
g_dnaRng.setValue(157 * dna + 7);
int randomIndex = g_dnaRng.getInt(numSuitableItems);
int index = 0;
for (int i = 0; i < numInventorySlots; ++i)
{
if (m_inventory.isValid() && isInventoryItemSuitable(i, itemSlotNo, requireFlags, ignoreFlags, requiredItemType1, requiredItemType2, requiredItemType3) && index++ == randomIndex)
return i;
}
return -1;
}
else
{
float bestValue = -1.0f;
float worstValue = 1000000000.0f;
int bestCase = -1;
int worstCase = -1;
if (numSuitableItems && !guarantee)
numSuitableItems += 3;
float threshold = numSuitableItems > 0 ? (1.7f / numSuitableItems) : 0.0f;
for (int i = 0; i < numInventorySlots; ++i)
{
if (m_inventory.m_itemKindNo >= 0 && isInventoryItemSuitable(i, itemSlotNo, requireFlags, ignoreFlags, requiredItemType1, requiredItemType2, requiredItemType3))
{
float value = (float)m_inventory.getItemKind()->m_value;
g_dnaRng.setValue(3 * m_inventory.m_itemKindNo + 157 * dna + 7);
if (isHero() || threshold > g_dnaRng.getFloat())
{
if (bestValue < value)
{
bestValue = value;
bestCase = i;
}
}
if (guarantee)
{
if (worstValue > value)
{
worstValue = value;
worstCase = i;
}
}
}
}
if (bestCase != -1)
return bestCase;
else
return worstCase;
}
}
bool mbTroop::isInventoryItemSuitable(int inventorySlotNo, int itemSlotNo, unsigned int requireFlags, unsigned int ignoreFlags, int requiredItemType1, int requiredItemType2, int requiredItemType3)
{
mbItemKind *itemKind = m_inventory[inventorySlotNo].getItemKind();
int type = itemKind->getType();
return canEquipItemInSlot(m_inventory[inventorySlotNo], itemSlotNo) && (itemKind->m_properties & requireFlags) == requireFlags && (itemKind->m_properties & ignoreFlags) == 0 && (requiredItemType1 == -1 || requiredItemType1 == type || requiredItemType2 == type || requiredItemType3 == type);
} |
|