В этом туторе написано как создать или воссоздать ледакол из беты Half-Life 2. Итак начнем! Для начала создайте в серверной части кода (src/dlls/hl2_dll/) файл под названием weapon_iceaxe.cpp, а потом weapon_iceaxe.h. В тот что с расширением .срр впишем следующий код: //========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Iceaxe - an old favorite // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "basehlcombatweapon.h" #include "player.h" #include "gamerules.h" #include "ammodef.h" #include "mathlib.h" #include "in_buttons.h" #include "soundent.h" #include "basebludgeonweapon.h" #include "vstdlib/random.h" #include "npcevent.h" #include "ai_basenpc.h" #include "weapon_iceaxe.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" ConVar sk_plr_dmg_iceaxe ( "sk_plr_dmg_iceaxe","10"); ConVar sk_npc_dmg_iceaxe ( "sk_npc_dmg_iceaxe","5"); //----------------------------------------------------------------------------- // CWeaponIceaxe //----------------------------------------------------------------------------- IMPLEMENT_SERVERCLASS_ST(CWeaponIceaxe, DT_WeaponIceaxe) END_SEND_TABLE() #ifndef HL2MP LINK_ENTITY_TO_CLASS( weapon_iceaxe, CWeaponIceaxe ); PRECACHE_WEAPON_REGISTER( weapon_iceaxe ); #endif acttable_t CWeaponIceaxe::m_acttable[] = { { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true }, { ACT_IDLE, ACT_IDLE_ANGRY_MELEE, false }, { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, false }, }; IMPLEMENT_ACTTABLE(CWeaponIceaxe); //----------------------------------------------------------------------------- // Constructor //----------------------------------------------------------------------------- CWeaponIceaxe::CWeaponIceaxe( void ) { } //----------------------------------------------------------------------------- // Purpose: Get the damage amount for the animation we're doing // Input : hitActivity - currently played activity // Output : Damage amount //----------------------------------------------------------------------------- float CWeaponIceaxe::GetDamageForActivity( Activity hitActivity ) { if ( ( GetOwner() != NULL ) && ( GetOwner()->IsPlayer() ) ) return sk_plr_dmg_iceaxe.GetFloat(); return sk_npc_dmg_iceaxe.GetFloat(); } //----------------------------------------------------------------------------- // Purpose: Add in a view kick for this weapon //----------------------------------------------------------------------------- void CWeaponIceaxe::AddViewKick( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return; QAngle punchAng; punchAng.x = random->RandomFloat( 2.0f, 4.0f ); punchAng.y = random->RandomFloat( -2.0f, -1.0f ); punchAng.z = 0.0f; pPlayer->ViewPunch( punchAng ); } //----------------------------------------------------------------------------- // Animation event handlers //----------------------------------------------------------------------------- void CWeaponIceaxe::HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { // Trace up or down based on where the enemy is... // But only if we're basically facing that direction Vector vecDirection; AngleVectors( GetAbsAngles(), &vecDirection ); Vector vecEnd; VectorMA( pOperator->Weapon_ShootPosition(), 50, vecDirection, vecEnd ); CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, Vector(-16,-16,-16), Vector(36,36,36), GetDamageForActivity( GetActivity() ), DMG_CLUB, 0.75 ); // did I hit someone? if ( pHurt ) { // play sound WeaponSound( MELEE_HIT ); // Fake a trace impact, so the effects work out like a player's crowbaw trace_t traceHit; UTIL_TraceLine( pOperator->Weapon_ShootPosition(), pHurt->GetAbsOrigin(), MASK_SHOT_HULL, pOperator, COLLISION_GROUP_NONE, &traceHit ); ImpactEffect( traceHit ); } else { WeaponSound( MELEE_MISS ); } } //----------------------------------------------------------------------------- // Animation event //----------------------------------------------------------------------------- void CWeaponIceaxe::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { switch( pEvent->event ) { case EVENT_WEAPON_MELEE_HIT: HandleAnimEventMeleeHit( pEvent, pOperator ); break; default: BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); break; } } ConVar sk_iceaxe_lead_time( "sk_iceaxe_lead_time", "0.7" ); int CWeaponIceaxe::WeaponMeleeAttack1Condition( float flDot, float flDist ) { // Attempt to lead the target (needed because citizens can't hit manhacks with the iceaxe!) CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); CBaseEntity *pEnemy = pNPC->GetEnemy(); if (!pEnemy) return COND_NONE; Vector vecVelocity; vecVelocity = pEnemy->GetSmoothedVelocity( ); // Project where the enemy will be in a little while float dt = sk_iceaxe_lead_time.GetFloat(); dt += random->RandomFloat( -0.3f, 0.2f ); if ( dt < 0.0f ) dt = 0.0f; Vector vecExtrapolatedPos; VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); Vector vecDelta; VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); if ( fabs( vecDelta.z ) > 70 ) { return COND_TOO_FAR_TO_ATTACK; } Vector vecForward = pNPC->BodyDirection2D( ); vecDelta.z = 0.0f; float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); if ((flDist > 64) && (flExtrapolatedDist > 64)) { return COND_TOO_FAR_TO_ATTACK; } float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) { return COND_NOT_FACING_ATTACK; } return COND_CAN_MELEE_ATTACK1; } А теперь в weapon_iceaxe.h впишем это: //========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef WEAPON_ICEAXE_H #define WEAPON_ICEAXE_H #include "basebludgeonweapon.h" #if defined( _WIN32 ) #pragma once #endif #define ICEAXE_RANGE 60 #define ICEAXE_REFIRE 0.25f //----------------------------------------------------------------------------- // CWeaponIceaxe //----------------------------------------------------------------------------- class CWeaponIceaxe : public CBaseHLBludgeonWeapon { public: DECLARE_CLASS( CWeaponIceaxe, CBaseHLBludgeonWeapon ); DECLARE_SERVERCLASS(); DECLARE_ACTTABLE(); CWeaponIceaxe(); float GetRange( void ) { return ICEAXE_RANGE; } float GetFireRate( void ) { return ICEAXE_REFIRE; } void AddViewKick( void ); float GetDamageForActivity( Activity hitActivity ); // Animation event virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); private: // Animation event handlers void HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); virtual int WeaponMeleeAttack1Condition( float flDot, float flDist ); }; #endif // WEAPON_ICEAXE_H Всё, с серверной частью все хорошо, теперь нам нужно вписать наш ледакол в клинет, так что направляемся сюда (src\cl_dll\hl2_hud\c_weapon__stubs_hl2.cpp) и где то после строчки: STUB_WEAPON_CLASS( weapon_crowbar, WeaponCrowbar, C_BaseHLBludgeonWeapon ); Впишем эту строчку: STUB_WEAPON_CLASS( weapon_iceaxe, WeaponIceaxe, C_BaseHLBludgeonWeapon ); Так, теперь надо кое что сделать для нашей второй медленной, но более сильной атаки Для этого зайдите сюда (src\dlls\basebludgeonweapon.cpp) и тут в самом низу файла поменяйте строку: nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER; на эту: nHitActivity = ACT_VM_MISSCENTER; Всё, можно компилить! Теперь зайдем в папку с модом, а потом в папку Scripts и там создадим файл weapon_iceaxe.txt и в него впишем следующие: // Iceaxe WeaponData { // Weapon data is loaded by both the Game and Client DLLs. "printname" "IceAxe" "viewmodel" "models/weapons/v_iceaxe.mdl" "playermodel" "models/weapons/w_iceaxe.mdl" "anim_prefix" "crowbar" "bucket" "0" "bucket_position" "1" "clip_size" "-1" "primary_ammo" "None" "secondary_ammo" "None" "weight" "0" "item_flags" "0" // Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds) SoundData { "single_shot" "Weapon_IceAxe.Single" "melee_hit" "Weapon_IceAxe.Melee_Hit" "melee_hit_world" "Weapon_IceAxe.Melee_HitWorld" } // Weapon Sprite data is loaded by the Client DLL. TextureData { "weapon" { "file" "sprites/w_icons1b" "x" "0" "y" "64" "width" "128" "height" "64" } "weapon_s" { "file" "sprites/w_icons1b" "x" "0" "y" "64" "width" "128" "height" "64" } "ammo" { "file" "sprites/640hud7" "x" "0" "y" "72" "width" "24" "height" "24" } "ammo2" { "file" "sprites/640hud7" "x" "48" "y" "72" "width" "24" "height" "24" } "crosshair" { "font" "Crosshairs" "character" "Q" } "autoaim" { "file" "sprites/crosshairs" "x" "0" "y" "48" "width" "24" "height" "24" } } } Теперь осталась финешная прямаю, надо дописать звуки к ледаколу. Для этого нам надо зайти сюда (scripts\game_sounds_weapons.txt) и тут после обозначей звуков ломика (crowbar) впишем наши: // weapon_iceaxe.txt "Weapon_IceAxe.Single" { "channel" "CHAN_WEAPON" "volume" "1.0" "soundlevel" "SNDLVL_105dB" "pitch" "95,100" "wave" "weapons/iceaxe/iceaxe_swing1.wav" } "Weapon_IceAxe.Melee_Hit" { "channel" "CHAN_WEAPON" "volume" "1.0" "soundlevel" "SNDLVL_105dB" "pitch" "98,102" "rndwave" { "wave" "impact/bullets/flesh/flesh1.wav" "wave" "impact/bullets/flesh/flesh2.wav" "wave" "impact/bullets/flesh/flesh3.wav" } } "Weapon_IceAxe.Melee_HitWorld" { "channel" "CHAN_WEAPON" "volume" "1.0" "soundlevel" "SNDLVL_105dB" "pitch" "98,102" "rndwave" { "wave" "weapons/crowbar/crowbar_impact1.wav" "wave" "weapons/crowbar/crowbar_impact2.wav" } } Сделали? Отлично, теперь нам надо сделать совсем чуть-чуть! Идём сюда (cfg\skill.cfg) и после этих строк: sk_plr_dmg_crowbar "10" sk_npc_dmg_crowbar "5" Впишем эти: sk_plr_dmg_iceaxe "10" sk_npc_dmg_iceaxe "5" Всё, заходим в игру и радуемя жизни! Модели к туториалу качать здесь или взять из Миссинг Инфо.
|