Ru/Authoring a weapon entity: Difference between revisions

From Valve Developer Community
< Ru
Jump to navigation Jump to search
No edit summary
m (Multipage removal)
 
(9 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{otherlang2
{{LanguageBar}}
|ru=Authoring_a_weapon_entity:ru
 
}}
 
{{Todo:ru|Данная статья переведена не полностью.}}
{{Translating|suf=:ru}}
{{note|suf=:ru|Есть неточности перевода , помеченные (?)}}
{{toc-right}}
{{toc-right}}


Как не удивительно Source имеет надёжные оружейные системы. Эта статья описывает шаги необходимые для создания [[hitscan|пулевых]] и снарядных оружий и как правильно настроить их для использования в мультиплеере.
Как не удивительно Source имеет надёжные оружейные системы. Эта статья описывает шаги необходимые для создания {{L|hitscan|пулевых}} и снарядных оружий и как правильно настроить их для использования в мультиплеере.


== Общие сведения ==
== Общие сведения ==


; Большинство свойств оружия может быть сконфигурировано с помощью [[Weapon script|оружейных скриптов]]
; Большинство свойств оружия может быть сконфигурировано с помощью {{L|Weapon script|оружейных скриптов}}
: Если всё что тебе требуется - это выстреливать пули с постоянной скоростью, тебе необходимы какие-никакие навыки в программировании.
: Если всё что тебе требуется - это выстреливать пули с постоянной скоростью, тебе необходимы какие-никакие навыки в программировании.
; Оружейный огонь может быть [[Prediction|прогнозирован]] игроком и [[Lag compensation|запозданием]] сервера
; Оружейный огонь может быть {{L|Prediction|прогнозирован}} игроком и {{L|Lag compensation|запозданием}} сервера
: Обычно это выглядит как снаряды в виде ракет, гранат, и других снарядов материализующихся из воздуха на компьютерах наблюдателей.
: Обычно это выглядит как снаряды в виде ракет, гранат, и других снарядов материализующихся из воздуха на компьютерах наблюдателей.
; [[viewmodel|Моделька от первого лица]] - это отдельная сущность
; {{L|viewmodel|Моделька от первого лица}} - это отдельная сущность
: Она создается игроком и делится между всеми видами оружия.
: Она создается игроком и делится между всеми видами оружия.
; В SDK есть широкий выбор оружия для изучения
; В SDK есть широкий выбор оружия для изучения
Line 20: Line 21:
== Оружейные скрипты ==
== Оружейные скрипты ==


От [[weapon script|оружейных скриптов]] зависит много свойств оружия , включая её [[model|модель]], амуницию , звуки , размер обоймы , и имя в пользовательском интерфейсе. Использование, расширение и шифрование оружейных скриптов описано в [[Weapon script|их статье]].
От {{L|weapon script|оружейных скриптов}} зависит много свойств оружия , включая её {{L|model|модель}}, амуницию , звуки , размер обоймы , и имя в пользовательском интерфейсе. Использование, расширение и шифрование оружейных скриптов описано в {{L|Weapon script|их статье}}.


Скрипт оружия будет автоматически загружен для любого оружия с [[LINK_ENTITY_TO_CLASS()|назначенным именем класса]]. Для более лёгкого [[precache|кэширования]] ресурсов, определяемых скриптами вызовите <code>PRECACHE_WEAPON_REGISTER(имя)</code> и никаких кавычек вокруг имени класса.
Скрипт оружия будет автоматически загружен для любого оружия с {{L|LINK_ENTITY_TO_CLASS()|назначенным именем класса}}. Для более лёгкого {{L|precache|кэширования}} ресурсов, определяемых скриптами вызовите <code>PRECACHE_WEAPON_REGISTER(имя)</code> и никаких кавычек вокруг имени класса.


== Точки входа ==
== Точки входа ==


There are four functions on a weapon which are called each frame by the owning player entity:
У оружия есть четыре функции, которые вызываются каждый кадр объектом которым владеет игрок:


; <code>ItemPreFrame()</code>
; <code>ItemPreFrame()</code>
: Called before the player has moved. In [[Episode Two]], decides whether now is a good time to display a HUD hint on weapon usage.
: Вызывается перед началом движения игрока. В {{L|Episode Two}}, решает , подходящее ли сейчас время чтобы отобразить подсказку по использованию оружия в HUD.
; <code>ItemHolsterFrame()</code>
; <code>ItemHolsterFrame()</code>
: Called before the player has moved, if the weapon is not active. Does nothing by default.
: Вызывается перед началом движения игрока, если игрок ничего не делает. В основном ничего не делает.
; <code>ItemBusyFrame()</code>
; <code>ItemBusyFrame()</code>
: Called after the player has moved, if the player cannot fire. Does nothing by default.
: Вызывается перед началом движения игрока, если игрок не стреляет. В основном ничего не делает.
; <code>ItemPostFrame()</code>
; <code>ItemPostFrame()</code>
: Called after the player has moved. The most important function, as it leads to one of the following:
: Вызывается после движения игрока. Это самая важная функция , ведь она ведёт к следующим:
:* <code>PrimaryAttack()</code>
:* <code>PrimaryAttack()</code>
:* <code>SecondaryAttack()</code>
:* <code>SecondaryAttack()</code>
Line 42: Line 43:
:* <code>WeaponIdle()</code>
:* <code>WeaponIdle()</code>


== Shooting ==
== Стрельба ==


A gun will typically shoot when the +attack key is active and <code>(m_flNextPrimaryAttack <= [[gpGlobals]]->curtime)</code>. For secondary fire, +attack2 and <code>m_flNext''Secondary''Attack</code> are checked instead.
Оружие обычно стреляет если кнопка отвечающая за +attack активна и <code>(m_flNextPrimaryAttack <= {{L|gpGlobals}}->curtime)</code>. Для дополнительного режима стрельбы, +attack2 и <code>m_flNext''Secondary''Attack</code> проверяются вместо предыдущей функции (?).


{{todo|How do NPCs attack?}}
{{todo|Как заставить NPC атаковать?}}


=== Bullets ===
=== Пули ===


[[Hitscan]] bullets are fired by passing a <code>[[FireBulletsInfo_t]]</code> object to <code>GetOwner()->FireBullets()</code>.
{{L|Hitscan|Пули}} выстреливаются при соответствии , где <code>{{L|FireBulletsInfo_t}}</code> противоречит <code>GetOwner()->FireBullets()</code>.


If all you want is a primary fire attack that spits out a constant stream of bullets (no matter whether they are 2 or 0.2 seconds apart) <code>CBaseCombatWeapon</code> is already up to the job and you only need write two functions:
Если всё что вам нужно это основная атака , которая выстреливает постоянный поток пуль (Не важно отделяют их 2 или 0.2 секунды) <code>CBaseCombatWeapon</code> уже выполняет нужную работу и вам надо только написать две функции:


; <code>float GetFireRate()</code>
; <code>float GetFireRate()</code>
: Seconds between each bullet.
: Время в секундах между каждым выстрелом.
; <code>const Vector& GetBulletSpread()</code>
; <code>const Vector& GetBulletSpread()</code>
: Cone within which bullets will be randomly spread. Use the <code>VECTOR_CONE_*</code> #defines to avoid doing the maths yourself.
: Конус , внутри которого пули будут иметь случайный разброс. Для него используйте <code>VECTOR_CONE_*</code> #определяет, как избежать самостоятельной работы с математикой.


Skip on to the [[#Networking|networking]] section if this fits your bill; [[#Effects|effects]] will be handled for you. Otherwise see  <code>[[FireBulletsInfo_t]]</code> for details on setting up your own hitscan attack.
Переходим к секции с [[#Networking|нетворкингом]] если это соответствует вашим требованиям; [[#Effects|Эффекты]] будут сделаны за вас. Иначе смотрите <code>{{L|FireBulletsInfo_t}}</code> за подробностями , чтобы настроить вашу собственную hitscan атаку.


=== Projectiles ===
=== Снаряды ===


Rockets, grenades, and other projectiles are entities in their own right which exist independently of the weapon they came from. The weapon should spawn them with <code>[[Create()]]</code>:
Ракеты, гранаты, и другие снаряды это самостоятельные энтити которые существуют независимо (почти) от оружия из которого они вылетели. Оружие должно создать их с помощью <code>{{L|Create()}}</code>:


<source lang=cpp>CBaseEntity::Create( "my_projectile", GetOwner()->Weapon_ShootPosition(), GetOwner()->EyeAngles(), GetOwnerEntity() );</source>
<source lang=cpp>CBaseEntity::Create( "my_projectile", GetOwner()->Weapon_ShootPosition(), GetOwner()->EyeAngles(), GetOwnerEntity() );</source>


Note that the owner is the player who own the weapon (<code>GetOwnerEntity()</code>), not the weapon itself.
Обратите внимание , что их владелец тот же , что и владеет оружием (<code>GetOwnerEntity()</code>), а само не оружие как таковое.


{{tip|Don't [[Lag compensation|lag compensate]] or [[Prediction|predict]] this call - but ''do'' predict [[viewmodel]] animation, ammo depletion and reloading.}}
{{tip|Не {{L|Lag compensation|компенсируйте лаги}} или {{L|Prediction|прогнозируйте}} этот вызов - ''делай'' прогнозируемую анимацию отсутствия патронов и перезарядки для {{L|viewmodel}}.}}


Further reading:
Читайте следующее:


* [[Projectiles]] (for projectile design issues)
* {{L|Projectiles|Снаряды}} (для проблем с дизайном модели снарядов)
* [[Authoring a Model Entity]] (for creating [[QPhysics]] entities)
* {{L|Authoring a Model Entity|Создание энтити-модели}} (для создания {{L|QPhysics}} энтити)
* <code>[[CPhysicsProp]]</code> (for creating [[VPhysics]] entities)
* <code>{{L|CPhysicsProp}}</code> (для создания {{L|VPhysics}} энтити)


=== Effects ===
=== Эффекты ===


This section assumes you are using the new [[:Category:Particle System|particle system]], which is driven by artists. The old, hard-coded particle tech was never documented.
Здесь предполагается , что вы используете {{LCategory|Particle System|систему партиклов}}, которая создаётся художниками. Старая технология  "закодирования партиклов намертво" никогда не документировалась.


==== Tracers ====
==== Следы от пуль ====


Tracers should be dispatched from <code>CBaseEntity::MakeTracer()</code>. <code>CBasePlayer</code> is set up to emit the old hard-coded tracer effects; if you want to make changes it's best to implement particles. Doing so is easy:
Следы должны быть отправлены <code>CBaseEntity::MakeTracer()</code>. <code>CBasePlayer</code> который настроен на излучение "намертво закодированных" эффектов; если вы хотите внести изменения, лучше всего осуществить партиклы(?). Это делается несложно:


<source lang=cpp>
<source lang=cpp>
// ALL IN SHARED CODE
// ВСЁ В ОБЩЕМ КОДЕ


// always emit tracers; let the particle system determine volume
// всегда излучать следы; пусть система партиклов сама определяет объём
// (if you don't mind editing CBasePlayer, just change m_iTracerFreq there)
// (если вы не собираетесь редактировать CBasePlayer, просто измените m_iTracerFreq )
void CMyPlayer::FireBullets( const FireBulletsInfo_t &info )
void CMyPlayer::FireBullets( const FireBulletsInfo_t &info )
{
{
Line 97: Line 98:
}
}


// pass through to weapon, if desired
// перейдите к оружию, если есть необходимость
void CMyPlayer::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType )
void CMyPlayer::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType )
{
{
Line 103: Line 104:
}
}


// emit weapon-specific tracer
// излучает эффект этого оружия
void CMyWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType )
void CMyWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType )
{
{
// 1 is attachment #1, which should be the muzzle
// 1 это аттачмент #1, который является дулом
UTIL_ParticleTracer("my_tracer",vecTracerSrc,tr.endpos,entindex(),1);
UTIL_ParticleTracer("my_tracer",vecTracerSrc,tr.endpos,entindex(),1);
}
}
</source>
</source>


The code above will create a new [[particle system]] for each bullet fired, which is suitable for one-shot effects. If your weapon shoots rapidly consider instead dispatching an effect which spawns a stream of particles when the player starts firing and using <code>StopParticleEffects(this)</code> to terminate it when they finish. Test <code>(CBasePlayer::m_nButtons & IN_ATTACK)</code> to achieve this.
Код сверху позволяет создать новую {{L|particle system|систему частиц}} , которая подходит для эффектов одиночной стрельбы для каждой пули . Если ваше оружие стреляет быстро рассмотрите вместо этого возможность создания эффекта который создаёт поток партиклов когда игрок начинает стрелять , и используйте <code>StopParticleEffects(this)</code> чтобы завершить работу эффекта, когда он закончит стрелять. Попробуйте <code>(CBasePlayer::m_nButtons & IN_ATTACK)</code> чтобы достичь данного эффекта.


{{note|If your weapon has other particle effects you'll need stop the tracers with <code>ParticleProp()->StopEmission(CNewParticleEffect* pEffect)</code> instead, which is client-side.}}
{{note|Если ваше оружие имеет другие партикл-эффекты вам понадобиться остановить след <code>ParticleProp()->StopEmission(CNewParticleEffect* pEffect)</code> вместо того , который находится на стороне игрока.}}


See also <code>[[UTIL_ParticleTracer]]</code>.
Смотрите также <code>{{L|UTIL_ParticleTracer}}</code>.


==== Impacts ====
==== Эффект попадания ====


{{todo|<code>CBaseEntity::DoImpactEffect()</code>}}
{{todo|<code>CBaseEntity::DoImpactEffect()</code>}}
Line 125: Line 126:
{{todo|Shared code, prediction, predicted viewmodels, compensation...}}
{{todo|Shared code, prediction, predicted viewmodels, compensation...}}


== Sample weapon ==
== Оружие-пример ==


See [[AK47 weapon|Adding a new weapon to your mod]].
Смотрите {{L|AK47 weapon|Добавление нового оружия в ваш мод}}.


[[Category:Weapons programming]]
{{ACategory|Weapons programming}}

Latest revision as of 04:49, 12 July 2024

English (en)Русский (ru)Translate (Translate)


Info content.png
This page is being translated.
You can help by finishing the translation.
If this page cannot be translated for some reason, or is left untranslated for an extended period of time after this notice is posted, the page should be requested to be deleted.
Also, please make sure the article complies with the alternate languages guide.(en)
Note.pngПримечание:Есть неточности перевода , помеченные (?)

Как не удивительно Source имеет надёжные оружейные системы. Эта статья описывает шаги необходимые для создания пулевых(en) и снарядных оружий и как правильно настроить их для использования в мультиплеере.

Общие сведения

Большинство свойств оружия может быть сконфигурировано с помощью оружейных скриптов(en)
Если всё что тебе требуется - это выстреливать пули с постоянной скоростью, тебе необходимы какие-никакие навыки в программировании.
Оружейный огонь может быть прогнозирован(en) игроком и запозданием(en) сервера
Обычно это выглядит как снаряды в виде ракет, гранат, и других снарядов материализующихся из воздуха на компьютерах наблюдателей.
Моделька от первого лица(en) - это отдельная сущность
Она создается игроком и делится между всеми видами оружия.
В SDK есть широкий выбор оружия для изучения
Valve предоставляет исходный код как однопользовательских, так и многопользовательских игр.

Оружейные скрипты

От оружейных скриптов(en) зависит много свойств оружия , включая её модель(en), амуницию , звуки , размер обоймы , и имя в пользовательском интерфейсе. Использование, расширение и шифрование оружейных скриптов описано в их статье(en).

Скрипт оружия будет автоматически загружен для любого оружия с назначенным именем класса(en). Для более лёгкого кэширования(en) ресурсов, определяемых скриптами вызовите PRECACHE_WEAPON_REGISTER(имя) и никаких кавычек вокруг имени класса.

Точки входа

У оружия есть четыре функции, которые вызываются каждый кадр объектом которым владеет игрок:

ItemPreFrame()
Вызывается перед началом движения игрока. В Episode Two(en), решает , подходящее ли сейчас время чтобы отобразить подсказку по использованию оружия в HUD.
ItemHolsterFrame()
Вызывается перед началом движения игрока, если игрок ничего не делает. В основном ничего не делает.
ItemBusyFrame()
Вызывается перед началом движения игрока, если игрок не стреляет. В основном ничего не делает.
ItemPostFrame()
Вызывается после движения игрока. Это самая важная функция , ведь она ведёт к следующим:
  • PrimaryAttack()
  • SecondaryAttack()
  • HandleFireOnEmpty()
  • Reload()
  • WeaponIdle()

Стрельба

Оружие обычно стреляет если кнопка отвечающая за +attack активна и (m_flNextPrimaryAttack <= gpGlobals(en)->curtime). Для дополнительного режима стрельбы, +attack2 и m_flNextSecondaryAttack проверяются вместо предыдущей функции (?).

Нужно сделать: Как заставить NPC атаковать?

Пули

Пули(en) выстреливаются при соответствии , где FireBulletsInfo_t(en) противоречит GetOwner()->FireBullets().

Если всё что вам нужно это основная атака , которая выстреливает постоянный поток пуль (Не важно отделяют их 2 или 0.2 секунды) CBaseCombatWeapon уже выполняет нужную работу и вам надо только написать две функции:

float GetFireRate()
Время в секундах между каждым выстрелом.
const Vector& GetBulletSpread()
Конус , внутри которого пули будут иметь случайный разброс. Для него используйте VECTOR_CONE_* #определяет, как избежать самостоятельной работы с математикой.

Переходим к секции с нетворкингом если это соответствует вашим требованиям; Эффекты будут сделаны за вас. Иначе смотрите FireBulletsInfo_t(en) за подробностями , чтобы настроить вашу собственную hitscan атаку.

Снаряды

Ракеты, гранаты, и другие снаряды это самостоятельные энтити которые существуют независимо (почти) от оружия из которого они вылетели. Оружие должно создать их с помощью Create()(en):

CBaseEntity::Create( "my_projectile", GetOwner()->Weapon_ShootPosition(), GetOwner()->EyeAngles(), GetOwnerEntity() );

Обратите внимание , что их владелец тот же , что и владеет оружием (GetOwnerEntity()), а само не оружие как таковое.

Tip.pngСовет:Не компенсируйте лаги(en) или прогнозируйте(en) этот вызов - делай прогнозируемую анимацию отсутствия патронов и перезарядки для viewmodel(en).

Читайте следующее:

Эффекты

Здесь предполагается , что вы используете систему партиклов(en), которая создаётся художниками. Старая технология "закодирования партиклов намертво" никогда не документировалась.

Следы от пуль

Следы должны быть отправлены CBaseEntity::MakeTracer(). CBasePlayer который настроен на излучение "намертво закодированных" эффектов; если вы хотите внести изменения, лучше всего осуществить партиклы(?). Это делается несложно:

// ВСЁ В ОБЩЕМ КОДЕ

// всегда излучать следы; пусть система партиклов сама определяет объём
// (если вы не собираетесь редактировать CBasePlayer, просто измените m_iTracerFreq )
void CMyPlayer::FireBullets( const FireBulletsInfo_t &info )
{
	FireBulletsInfo_t new_info(info);
	new_info.m_iTracerFreq = 1;
	BaseClass::FireBullets(new_info);
}

// перейдите к оружию, если есть необходимость
void CMyPlayer::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType )
{
	GetActiveWeapon()->MakeTracer(vecTracerSrc,tr,iTracerType);
}

// излучает эффект этого оружия
void CMyWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType )
{
	// 1 это аттачмент #1, который является дулом
	UTIL_ParticleTracer("my_tracer",vecTracerSrc,tr.endpos,entindex(),1);
}

Код сверху позволяет создать новую систему частиц(en) , которая подходит для эффектов одиночной стрельбы для каждой пули . Если ваше оружие стреляет быстро рассмотрите вместо этого возможность создания эффекта который создаёт поток партиклов когда игрок начинает стрелять , и используйте StopParticleEffects(this) чтобы завершить работу эффекта, когда он закончит стрелять. Попробуйте (CBasePlayer::m_nButtons & IN_ATTACK) чтобы достичь данного эффекта.

Note.pngПримечание:Если ваше оружие имеет другие партикл-эффекты вам понадобиться остановить след ParticleProp()->StopEmission(CNewParticleEffect* pEffect) вместо того , который находится на стороне игрока.

Смотрите также UTIL_ParticleTracer(en).

Эффект попадания

Нужно сделать: CBaseEntity::DoImpactEffect()

Networking

Нужно сделать: Shared code, prediction, predicted viewmodels, compensation...

Оружие-пример

Смотрите Добавление нового оружия в ваш мод(en).