Ru/Authoring a weapon entity: Difference between revisions

From Valve Developer Community
< Ru
Jump to navigation Jump to search
mNo edit summary
No edit summary
Line 24: Line 24:
== Точки входа ==
== Точки входа ==


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.
: Вызывается перед началом движения игрока. В [[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 40: Line 40:
:* <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 <= [[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>.
[[Hitscan|Пули]] выстреливаются при соответствии , где <code>[[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>[[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>[[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|Не [[Lag compensation|компенсируйте лаги]] или [[Prediction|прогнозируйте]] этот вызов - ''делай'' прогнозируемую анимацию отсутствия патронов и перезарядки для [[viewmodel]].}}


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


* [[Projectiles]] (for projectile design issues)
* [[Projectiles|Снаряды]] (для проблем с дизайном модели снарядов)
* [[Authoring a Model Entity]] (for creating [[QPhysics]] entities)
* [[Authoring a Model Entity|Создание энтити-модели]] (для создания [[QPhysics]] энтити)
* <code>[[CPhysicsProp]]</code> (for creating [[VPhysics]] entities)
* <code>[[CPhysicsProp]]</code> (для создания [[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.
Здесь предполагается , что вы используете [[:Category: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 95: Line 95:
}
}


// 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 101: Line 101:
}
}


// 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.
Код сверху позволяет создать новую [[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>[[UTIL_ParticleTracer]]</code>.


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


{{todo|<code>CBaseEntity::DoImpactEffect()</code>}}
{{todo|<code>CBaseEntity::DoImpactEffect()</code>}}
Line 123: Line 123:
{{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]].
Смотрите [[AK47 weapon|ДОбавление нового оружия в ваш мод]].


[[Category:Weapons programming]]
[[Category:Weapons programming]]

Revision as of 10:40, 9 January 2023

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

Template:Todo:ru

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

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

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

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

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

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

Точки входа

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

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

Стрельба

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

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

Пули

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

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

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

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

Снаряды

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

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

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

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

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

Эффекты

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

Следы от пуль

Следы должны быть отправлены 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);
}

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

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

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

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

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

Networking

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

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

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