Уровень сложности: Новичок
Время: Не более 5 - 10 минут, если в первый раз.
Оригинал: от Detler Дополнил пару примочек, плюс файлы исходников.
Так-с приступим. Вот основной код.
В weapon_parse.h дописываем в класс:
Code
class FileWeaponInfo_t
{
public:
FileWeaponInfo_t();
//ironsight
Vector m_expOffset; //Это нужно дописать
QAngle m_expOriOffset; //Это нужно дописать
...
Далее, открываем файл weapon_parse.cpp, там по поиску (ctrl+f) ищем строку void FileWeaponInfo_t::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
И после неё, точнее после открытия скобок "{", пишем код:
Code
// this just saves off the data in the script file for later use
KeyValues *pEt = pKeyValuesData->FindKey("ExpOffset");
if (pEt)
{
m_expOffset.x = pEt->GetFloat("x", 0.0f);
m_expOffset.y = pEt->GetFloat("y", 0.0f);
m_expOffset.z = pEt->GetFloat("z", 0.0f);
m_expOriOffset.x = pEt->GetFloat("xori", 0.0f);
m_expOriOffset.y = pEt->GetFloat("yori", 0.0f);
m_expOriOffset.z = pEt->GetFloat("zori", 0.0f);
}
else
{
m_expOffset = vec3_origin;
m_expOriOffset.Init();
}
Так-с... Теперь открываем файлец baseviewmodel_shared.cpp и меняем начало на:
Code
#include "cbase.h"
#include "baseviewmodel_shared.h"
#if defined( CLIENT_DLL )
#include "iprediction.h"
#include "prediction.h"
// cin: 070105 - ironsight mode changes
#include "convar.h"
#include "c_baseplayer.h"
#include "c_basecombatweapon.h"
#else
#include "vguiscreen.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
А чуть ниже меняем на это до комментариев со словами "// Purpose: ":
Code
#define VIEWMODEL_ANIMATION_PARITY_BITS 3
#define SCREEN_OVERLAY_MATERIAL "vgui/screens/vgui_overlay"
#if defined( CLIENT_DLL )
void ExpWpnTestOffset(ConVar *pConVar, char *pszString);
ConVar cl_exp_test_wpn_offset("cl_exp_test_wpn_offset", "0", 0, "Tests weapon offsets",
(FnChangeCallback)ExpWpnTestOffset);
ConVar cl_exp_test_wpn_offset_x("cl_exp_test_wpn_offset_x", "0");
ConVar cl_exp_test_wpn_offset_y("cl_exp_test_wpn_offset_y", "0");
ConVar cl_exp_test_wpn_offset_z("cl_exp_test_wpn_offset_z", "0");
ConVar cl_exp_test_wpn_ori_offset_x("cl_exp_test_wpn_ori_offset_x", "0");
ConVar cl_exp_test_wpn_ori_offset_y("cl_exp_test_wpn_ori_offset_y", "0");
ConVar cl_exp_test_wpn_ori_offset_z("cl_exp_test_wpn_ori_offset_z", "0");
// cin: 070105 - applies existing weapon offsets when
// entering test mode (this will not be called upon
// weapon change, so beware)
// this mode should only be used for calibrating the
// ironsighted mode offests for a particular weapon
void ExpWpnTestOffset(ConVar *pConVar, char *pszString)
{
CBasePlayer *pPlayer = UTIL_PlayerByIndex(engine->GetLocalPlayer());
if (pPlayer)
{
CBaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
if (pWeapon)
{
cl_exp_test_wpn_offset_x.SetValue(pWeapon->GetWpnData().m_expOffset.x);
cl_exp_test_wpn_offset_y.SetValue(pWeapon->GetWpnData().m_expOffset.y);
cl_exp_test_wpn_offset_z.SetValue(pWeapon->GetWpnData().m_expOffset.z);
cl_exp_test_wpn_ori_offset_x.SetValue(pWeapon->GetWpnData().m_expOriOffset.x);
cl_exp_test_wpn_ori_offset_y.SetValue(pWeapon->GetWpnData().m_expOriOffset.y);
cl_exp_test_wpn_ori_offset_z.SetValue(pWeapon->GetWpnData().m_expOriOffset.z);
}
}
}
// last time ironsighted mode was toggled
float gIronsightedTime(0.0f);
// i bound this to a key for testing(i.e. bind [ ironsight_toggle)
CON_COMMAND(ironsight_toggle, "toggles ironsight mode for the current weapon")
{
if (gpGlobals->curtime - gIronsightedTime < 0.5f)
return;
CBasePlayer *pPlayer = UTIL_PlayerByIndex(engine->GetLocalPlayer());
if (pPlayer)
{
C_BaseViewModel *pVm = pPlayer->GetViewModel();
if (pVm)
{
//pPlayer->m_Local.m_iHideHUD |= HIDEHUD_CROSSHAIR;)
pVm->m_bExpSighted ^= true;
gIronsightedTime = gpGlobals->curtime;
}
}
}
void CalcExpWpnOffsets(CBasePlayer *owner, Vector &pos, QAngle ∠)
{
Vector forward, right, up, offset;
// this is a simple test mode to help determine the proper values
// to place in the weapon script
if (cl_exp_test_wpn_offset.GetBool())
{
ang.x += cl_exp_test_wpn_ori_offset_x.GetFloat();
ang.y += cl_exp_test_wpn_ori_offset_y.GetFloat();
ang.z += cl_exp_test_wpn_ori_offset_z.GetFloat();
offset.Init(cl_exp_test_wpn_offset_x.GetFloat(),
cl_exp_test_wpn_offset_y.GetFloat(),
cl_exp_test_wpn_offset_z.GetFloat());
}
else
{
CBaseCombatWeapon *pWeapon = owner->GetActiveWeapon();
if (pWeapon)
{
ang += pWeapon->GetWpnData().m_expOriOffset;
offset = pWeapon->GetWpnData().m_expOffset;
}
}
// get eye direction angles
AngleVectors(ang, &forward, &right, &up);
// apply the offsets
pos += forward * offset.x;
pos += right * offset.y;
pos += up * offset.z;
}
#endif
Далее находим строку ViewModel::Spawn и меняем на:
Code
void CBaseViewModel::Spawn( void )
{
Precache( );
SetSize( Vector( -8, -4, -2), Vector(8, 4, 2) );
SetSolid( SOLID_NONE );
#ifdef CLIENT_DLL
// cin: 070105 - ironsighted mode changes
m_bExpSighted = false;
m_expFactor = 0.0f;
#endif
}
Теперь снова ищем строку void CBaseViewModel::CalcViewModelView и заменяем всю функцию на:
Code
void CBaseViewModel::CalcViewModelView( CBasePlayer *owner, const Vector& eyePosition, const QAngle& eyeAngles )
{
// UNDONE: Calc this on the server? Disabled for now as it seems unnecessary to have this info on the server
#if defined( CLIENT_DLL )
QAngle vmangoriginal = eyeAngles;
QAngle vmangles = eyeAngles;
Vector vmorigin = eyePosition;
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
//Allow weapon lagging
if ( pWeapon != NULL )
{
#if defined( CLIENT_DLL )
if ( !prediction->InPrediction() )
#endif
{
pWeapon->AddViewmodelBob( this, vmorigin, vmangles );
CalcViewModelLag( vmorigin, vmangles, vmangoriginal );
}
}
#if defined( CLIENT_DLL )
if ( !prediction->InPrediction() )
{
// Let the viewmodel shake at about 10% of the amplitude of the player's view
vieweffects->ApplyShake( vmorigin, vmangles, 0.1 );
}
#endif
// cin: 070105 - ironsighted mode changes
// get the wpn offsets
CalcExpWpnOffsets(owner, vmorigin, vmangles);
// get delta time for 1 sec interpolation and interpolate to/from positional offset
float delta(gpGlobals->curtime - gIronsightedTime);
m_expFactor = (m_bExpSighted) ?
(delta > 1.0f) ? 1.0f : delta :
(delta > 1.0f) ? 0.0f : 1.0f - delta;
Vector difPos(vmorigin - eyePosition);
vmorigin = eyePosition + (difPos * m_expFactor);
SetLocalOrigin(vmorigin);
SetLocalAngles(vmangles);
#endif
}
Так, почти сделали, теперь лезем в baseviewmodel_shared.h и меняем всё объявление класса:
Code
class CBaseViewModel : public CBaseAnimating
{
DECLARE_CLASS( CBaseViewModel, CBaseAnimating );
public:
bool m_bExpSighted; //ADDED
float m_expFactor; //ADDED
DECLARE_NETWORKCLASS();
DECLARE_PREDICTABLE();
#if !defined( CLIENT_DLL )
DECLARE_DATADESC();
#endif
Теперь компилируем проект и идём в папку scripts, там прописываем в середину фалов, после задачи патронов, перед звуками скрипты.
Для weapon_pistol.txt:
Code
ExpOffset
{
"x" "-13"
"y" "-5.5"
"z" "4.2"
}
Для weapon_shotgun.txt:
Code
ExpOffset
{
"x" "-9.00"
"y" "-9.00"
"z" "4.20"
}
Для weapon_ar2.txt:
Code
ExpOffset
{
"x" "-5.00"
"y" "-5.80"
"z" "2.30"
}
Для weapon_smg1.txt:
Code
ExpOffset
{
"x" "-8.00"
"y" "-6.45"
"z" "2.53"
}
И наконец для weapon_357.txt:
Code
ExpOffset
{
"x" "-8.00"
"y" "-5.63"
"z" "2.70"
}
Но и это ещё не всё! Теперь мы должны задать клавишу, команду для прицеливания!
В той же папке scripts открываем файл kb_akt.lst и прописываем туда новую строку:
Code
"ironsight_toggle" "#IronSight"
Получится что-то вроде этого:
Code
"blank" "=========================="
"blank" "#Valve_Combat_Title"
"blank" "=========================="
"+attack" "#Valve_Primar y_Attack"
"+attack2" "#Valve_Secondary_Attack"
"ironsight_toggle" "IronSight"
"+reload" "#Valve_Reload_Weapon"
"+use" "#Valve_Use_Items"
"impulse 100" "#Valve_Flashlight"
"+zoom" "#Valve_Suit_Zoom"
"impulse 50" "#Valve_Commander_Mode"
"slot1" "#Valve_Weapon_Category_1"
"slot2" "#Valve_Weapon_Category_2"
"slot3" "#Valve_Weapon_Category_3"
"slot4" "#Valve_Weapon_Category_4"
"slot5" "#Valve_Weapon_Category_5"
"slot6" "#Valve_Weapon_C ategory_6"
"invnext" "#Valve_Next_Weapon"
"invprev" "#Valve_Previous_Weapon"
"lastinv" "#Valve_Last_Weapon_Used"
Всё! Теперь можите смело запускать игру! И, да, не забудьте в настройках указать клавишу. Всё, удачных вам опытов.
P.S. Для тех, у кого не получилось, могут не отчаиваться, я выложил исходники всех файлов. =) Нужно только прописать строку в kv_akt.lst
Исходники тут