В общем то, известная проблема - в зависимости от настроек
\\creatures\m_stalker.ltx
CODE
;---FIRE DISPERSIONS--------------------------------------------------
disp_walk_stand = 8 ;6
disp_walk_crouch = 4 ;3
disp_run_stand = 14 ;12;8
disp_run_crouch = 6 ;4
disp_stand_stand = 4
disp_stand_crouch = 2
disp_stand_stand_zoom = 1.5 ;1
disp_stand_crouch_zoom = 1.25;1
боты либо совсем кривые, либо просто снайперы, и это очень мало зависит от типа оружия -
при стрельбе практически нет различий, стреляет ли NPC из навороченной винтовки, или же строчит из автомата.
Порывшись, нашёл корень проблем - при стрельбе ботами учитывается только базовое рассеивание оружия, помноженное на умножающий коэфициент патрона.
\\trunk\xr_3da\xrGame\ai\stalker\ai_stalker_fire.cpp
CODE
float CAI_Stalker::GetWeaponAccuracy () const
{
float base = PI/180.f;
//влияние ранга на меткость
base *= m_fRankDisperison;
if (!movement().path_completed()) {
if (movement().movement_type() == eMovementTypeWalk)
if (movement().body_state() == eBodyStateStand)
return (base*m_disp_walk_stand);
else
return (base*m_disp_walk_crouch);
else
if (movement().movement_type() == eMovementTypeRun)
if (movement().body_state() == eBodyStateStand)
return (base*m_disp_run_stand);
else
return (base*m_disp_run_crouch);
}
if (movement().body_state() == eBodyStateStand)
if (zoom_state())
return (base*m_disp_stand_stand);
else
return (base*m_disp_stand_stand_zoom);
else
if (zoom_state())
return (base*m_disp_stand_crouch);
else
return (base*m_disp_stand_crouch_zoom);
}
\\trunk\xr_3da\xrGame\WeaponDispersion.cpp
CODE
//текущая дисперсия (в радианах) оружия с учетом используемого патрона
float CWeapon::GetFireDispersion (float cartridge_k)
{
//учет базовой дисперсии, состояние оружия и влияение патрона
float fire_disp = fireDispersionBase*cartridge_k*GetConditionDispersionFactor();
//вычислить дисперсию, вносимую самим стрелком
const CInventoryOwner* pOwner = smart_cast<const CInventoryOwner*>(H_Parent());
VERIFY (pOwner);
float parent_disp = pOwner->GetWeaponAccuracy();
fire_disp += parent_disp;
return fire_disp;
}
При всём этом безобразии просто накрутить разброс автоматического оружия раз в пять - десять тоже не вариант,
игрок просто лишится возможности нормально попадать.
В других движках, например refractor 2.0a, используемом в battlefield 2142 есть возможность прописать рассеивание для
каждой отдельной единицы оружия для ботов отдельно
CODE
rem *** AutoSentryGun Machine Gun ***
weaponTemplate.create EU_SentryGunWeapon
weaponTemplate.indirect 0
weaponTemplate.minRange 0.0
weaponTemplate.maxRange 110.0
weaponTemplate.setStrength Infantry 20.0
weaponTemplate.setStrength LightArmour 0.5
weaponTemplate.setStrength HeavyArmour 0.0
weaponTemplate.setStrength NavalArmour 0.0
weaponTemplate.setStrength Helicopter 2.0
weaponTemplate.setStrength AirPlane 1.0
weaponTemplate.setSoundSphereRadius 120.0
weaponTemplate.allowedDeviation 1.0 <<------------------------ вот так например, и это будет работать
weaponTemplate.setFiresThroughTransparent 1
Как можно было бы реализовать подобное в сталкере ?
В оригинальном движке параметр GetWeaponAccuracy вызывается при стрельбе/ударе лапой/пуске ракеты -
при любом типе нанесения урона, и при этом проверяется конфиг, содержащий наименование класса существа.
Для актёра это - [actor] , для собаки - [m_dog_normal] , для бармена, например, это будет - [m_barman] .
Одновременно с этим вызывается fire_disp оружия, даже если оружие - собственная лапа(просто тогда базовая дисперсия равна нулю).
Собственно можно было бы добавить параметр вроде AI_allowedDeviation в конфиг оружия, а также возможность движку считывать этот параметр,
в случае же отсутствия этого параметра(или неприменимом/невалидном значении) - возвращается единица в виде значения с плавающей запятой(float).
Если проще - то если например AI_allowedDeviation = 0.45678 или AI_allowedDeviation = 2.34 - читаем, иначе ставим единичку.
Далее - смотрим, управляется ли объект игроком, или ИИ - и если управляется игроком, то тогда AI_allowedDeviation просто не используется.
{
Как вариант - в конфиге живого существа считывается параметр, например
CODE
;species of monster
species = actor
(способ не очень хорош для кооператива, либо если делается сборка с возможностью
управлять сразу несколькими персонажами, как в небезызвестной сборке со старой версией Припяти)
}
Если же объект контролируется ИИ, то используется дополнительная формула, например что-то вроде этого
CODE
if (parent().controller() == CAI_stalker) {
parent_disp *= AI_allowedDeviation;
}
fire_disp += parent_disp;