Подопытный: func_recharge
Всегда хотелось, чтобы зарядник в хл был управляемым. А то стоит он себе и ждёт, пока его разрядят. А хочется, чтобы он ещё включался/выключался нажатим кнопки/событием в игре. Вот я и зделал специальную функицию для контроля зарядника. Она состоит из усовершенствования самого зарядника (необязательно, но полезно) и дополнительной энтити.
Часть 1. Модифицируем зарядник. Файл: h_battery.cpp Класс: CRecharge Цель: модификация
Находим блок подключения заголовочных модулей (#include) и после него (строка 29) вписываем два дефайна:
#define SF_RECHARGE_SPEC 1 #define SF_RECHARGE_SKILL 2
это два дополнительных флага для нашего зарядника. Первый значит, что зарядник будет использовать особое значение заряда, а не стандартное. Второй значит, что значения будет взято из переменной в skill.cfg (нужно, чтобы был установлен первый флаг). Теперь надо наши флаги привязать к заряднику, чтобы от них что-то зависило. Это зделаем в процедуре CRecharge::Spawn. Находим вот эту строку:
m_iJuice = gSkillData.suitchargerCapacity;
заменяем её на такой код:
if (pev->spawnflags & SF_RECHARGE_SKILL) { pev->armorvalue = (int)GetSkillCvar( (char *)STRING(pev->message) ); }
if (pev->spawnflags & SF_RECHARGE_SPEC) { m_iJuice = max( pev->armorvalue, 0); } else m_iJuice = gSkillData.suitchargerCapacity;
это мы заставили наши флаги работать. То есть, когда установлен первый флаг, то значению энергии присваивается значение с параметра armorvalue (но не меньше ноля), в противном случае устанавливается стандартное значение. Когда установлен второй - параметру armorvalue присваивается skill-значение, имя переменной берём с параметра message. Далее найдём такую строку (она следующая после этого блока ):
pev->frame = 0;
Заменяем на это:
if ( m_iJuice > 0 ) { pev->frame = 0; } else pev->frame = 1;
это мы ставим условие, что если стартовое значение энергии - нулевое, то зарядник выглядит разряженным. Теперь мы имеем усовершенствованный зарядник, но чтобы его использовать надо прописать новые флаги и настройки в fgd-файл. Откройте его, найдите SolidClass func_recharge, допишите в него слелующие настройки:
code:
spawnflags(Flags) =
[
1 : "Spec. Juice" : 0
2 : "Skill Juice" : 0
]
armorvalue(integer) : "Juice (if spec)" : 0
message(string) : "Juice (if skill)"
По первому сабжу - всё.
Часть 2. Энтитя контроля. Файл: h_battery.cpp Класс: CRechargeControl Цель: создание
Спускайтесь в самый низ файла, сейчас будем мноооого писать. Для начала обьявим дефайны:
#define SF_RECHARGE_CONTROL_ONCE 1 #define SF_RECHARGE_CONTROL_AWARD 2 #define SF_RECHARGE_CONTROL_SKILL 4 #define SF_RECHARGE_CONTROL_NSND 8
это четыре спаунфлага: первый - для одноразового срабатывания энтити; второй - для того, чтобы значение не просто устанавливалось, а прибавлялось/отнималось; третий - для использования значения из skill.cfg; четвёртый - для того, чтобы от речарджера не производились звуки при включении/выключении. Далее пишем наш класс:
class CRechargeControl : public CPointEntity { public: void Spawn( void ); void Precache( void ); void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); private: int m_iPrevJuice; };
переменная m_iPrevJuice нужна, чтобы энтитя "думала" производить звук или нет. Далее привязываем класс к энтити:
LINK_ENTITY_TO_CLASS( trigger_recharge_control, CRechargeControl );
Тут я назвал энтитю как trigger_recharge_control, но Вы можете обозвать её и по другому :) Далее идёт процедура кеширования:
void CRechargeControl::Precache( void ) { PRECACHE_SOUND("items/suitchargeno1.wav"); PRECACHE_SOUND("items/suitchargeok1.wav"); }
это мы кешируем два звучка, которые будут исходить от зарядника при включении/выключении. Далее процедура создания:
void CRechargeControl::Spawn(void) { Precache(); pev->solid = SOLID_NOT; pev->movetype = MOVETYPE_NONE; if (pev->spawnflags & SF_RECHARGE_CONTROL_SKILL) { pev->armorvalue = (int)GetSkillCvar( (char *)STRING(pev->message) ); } }
я думаю, тут всё понятно :) Теперь самая главная процедура вызова:
void CRechargeControl::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { CRecharge *pRecharge = NULL; pRecharge = (CRecharge *)UTIL_FindEntityByTargetname( NULL, STRING(pev->target) ); if (pRecharge) { m_iPrevJuice = pRecharge->m_iJuice; if (pev->spawnflags & SF_RECHARGE_CONTROL_AWARD) { pRecharge->m_iJuice += (int)pev->armorvalue; } else pRecharge->m_iJuice = (int)pev->armorvalue; if (pRecharge->m_iJuice > 0) { pRecharge->pev->frame = 0; } else pRecharge->pev->frame = 1; if (!(pev->spawnflags & SF_RECHARGE_CONTROL_NSND)) { if ( (m_iPrevJuice <= 0) && (pRecharge->m_iJuice > 0) ) { EMIT_SOUND_DYN( ENT(pRecharge->pev), CHAN_STATIC, "items/suitchargeok1.wav", 1, ATTN_NORM, 0, 150 ); } if ( (m_iPrevJuice > 0) && (pRecharge->m_iJuice <= 0) ) { EMIT_SOUND_DYN( ENT(pRecharge->pev), CHAN_STATIC, "items/suitchargeno1.wav", 1, ATTN_NORM, 0, 150 ); } } } if (pev->spawnflags & SF_RECHARGE_CONTROL_ONCE) { UTIL_Remove( this ); } }
если Вы программируете для хл, то Вы всё поймёте без обьяснений :) Вот наша энтитя готова, теперь добавим её в fgd-файл. Вот её описание:
code:
@PointClass base(Targetname,Target) = trigger_recharge_control : "Recharger control entity"
[
spawnflags(flags) =
[
1: "Remove on fire" : 0
2: "Award/Deduct" : 0
4: "Skill value" : 0
8: "No Sound" : 0
]
armorvalue(integer) : "Juice" : 100
message(string) : "Juice (skill)"
]
О, и не забудьте к func_recharge добавить base Targetname, чтобы в чарджера появилось Имя, по которому мы будем на него наводить наш контроллер. Всё, готово, добавляйте и наслаждайтесь :)
Источник: http://www.hlfx.ru/forum/showthread.php?s=08077d3c0f5c95eb3c499ca8c7341ced&threadid=605 |