목요일, 10월 19, 2006

Purpose: 기존 M16에서 M4A1 weapon 만들기

-= 기존 M16에서 CS(카스)의 M4A1 weapon 만들기 =-

Purpose: 기존 M16에서 M4A1 weapon 만들기
Author: godmode2k (godmode2k@hotmail.com | MSN IM)
Date: October. 12. 2004
Destination: 모드나라 (http://mod.zoa.to)
Source:
http://cocowest.javasarang.net/wiki/wiki.php/M16_%BC%D2%C0%BD%B1%E2%BB%E7%BF%EB
MP5.cpp in HL1 SDK


SDK: HL1 SDK 2.3
Code: Multyplayer Source
Tested: Steam based

(*)Special thanks to:
- cocowest님
- MP5.cpp in HL1 SDK


Description:
지난번 제가 작성한 tutorials:
0. "자신이 만든 MOD를 STEAM 으로 돌려보기 입니다."
1. 외국 Tutorial 번역 "Creating a New VGUI Menu - Part 1"
2. "게임내에서 wave 파일을 재생하자!"
3. "Radio Command Menu 만들기(CS 처럼)"
4. "MOD 게임 바탕화면 Logo 바꾸기"
5. "HLDS로 나의 MOD Server 구성하기"
6. "Counter-Strike 처럼 Team System 만들기(수정된 Radio Command Menu 포함)"

주소는: 0. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=39
1. http://cocowest.javasarang.net/mod/vgui_p1/VGUIMenuPart1.htm
2. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=49
3. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=51
4. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=53
5. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=59
6. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=74

[ 추가사항 ]
* 기존에 cocowest 님께서 올려 놓으신 "M16 만들기" 코드를 좀 수정했습니다.
* 수정한 결과 Counter-Strike의 M4A1과 거의 흡사하게 동작을 합니다.
* sound, model, aim, time delay 등의 코드들이 수정 되었습니다.

* 현재 "M16 만들기" 코드 외에 다른 비슷한 방법이 있습니다만,
* SDK내의 무기 관련 코드를 모두 살펴본 결과, M16에서 작성된 코드 방식이 정석인것 같아서 그대로 유지를 했습니다.
* 하지만 몇몇 추가해줘야 하는 사항이 있지만 추가해 주지 않아도 동작을 하기에 그 부분의 코드는 제외했습니다.


[ 주의 ]
code를 추가해 줄 때,

// 018killer: ... [
// 018killer: ... ]

사이 부분의 code를 추가해 주시면 됩니다


*** 분량이 조금 많습니다. 커피나 시원한 음료수 하나 놓고 시작하시기 바랍니다.
*** 중간에 키보드를 던지는 ,,, ㅎㅎ; 그런일이 발생하지 않았으면 하는 바람입니다.

그럼, 준비가 되셨다면 시작해 볼까요?



--------------------------------------------------------------
파일명: mp files/m16.cpp , cl_dll files/m16.cpp
작업위치: top
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

/***
*
* m16.cpp
*
****/

#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "soundent.h"
#include "gamerules.h"
#include "shake.h"


enum m16_e // v_* 모델의 sequence정의와 같은 순서로 열거
{
M16_IDLE,
M16_SHOOT1,
M16_SHOOT2,
M16_SHOOT3,
M16_RELOAD,
M16_DRAW,
M16_ADD_SILENCER,
M16_IDLE_UNSIL,
M16_SHOOT1_UNSIL,
M16_SHOOT2_UNSIL,
M16_SHOOT3_UNSIL,
M16_RELOAD_UNSIL,
M16_DRAW_UNSIL,
M16_DETACH_SILENCER,
};

//
// enum m16_e 부분의 코드는 v_*.mdl 파일의 sequence 정의입니다. 확인하는 부분은
// v_*.mdl 파일을 MilkShape 3D 로 decomplie 하면 v_*.qc 라는 파일이 나옵니다.
// 그 파일을 열면 제일 아래 부분에 sequence 정의 부분이 나옵니다.
// 그 부분을 순서대로 enumeration 하시면 됩니다.
//

LINK_ENTITY_TO_CLASS( weapon_m16, CM16 );


//=========================================================

void CM16::Spawn( )
{
pev->classname = MAKE_STRING("weapon_m16");
Precache( );
SET_MODEL(ENT(pev), "models/w_m16.mdl");
m_iId = WEAPON_M16;

m_iDefaultAmmo = M16_DEFAULT_GIVE;

FallInit();
}


void CM16::Precache( void )
{
PRECACHE_MODEL("models/v_m16.mdl");
PRECACHE_MODEL("models/w_m16.mdl");
PRECACHE_MODEL("models/p_m16.mdl");

m_iShell = PRECACHE_MODEL ("models/shell.mdl");

PRECACHE_MODEL("models/w_9mmARclip.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");

// Counter-Strike에 있는 M4A1 sound files [
PRECACHE_SOUND ("weapons/m4a1_silencer_on.wav");
PRECACHE_SOUND ("weapons/m4a1_silencer_off.wav");

PRECACHE_SOUND ("weapons/m4a1_clipout.wav");
PRECACHE_SOUND ("weapons/m4a1_clipin.wav");

PRECACHE_SOUND ("weapons/m4a1_deploy.wav");
PRECACHE_SOUND ("weapons/m4a1_boltpull.wav");

PRECACHE_SOUND ("weapons/m4a1_unsil-1");
PRECACHE_SOUND ("weapons/m4a1-1.wav");
// Counter-Strike에 있는 M4A1 sound files ]

m_usM16 = PRECACHE_EVENT( 1, "events/m16.sc" );
m_usM162 = PRECACHE_EVENT( 1, "events/m162.sc" );
}

int CM16::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "9mm";
p->iMaxAmmo1 = _9MM_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = M16_MAX_CLIP;
p->iSlot = 2;
p->iPosition = 5;
p->iFlags = 0;
p->iId = m_iId = WEAPON_M16;
p->iWeight = M16_WEIGHT;

return 1;
}

int CM16::AddToPlayer( CBasePlayer *pPlayer )
{
if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
{
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
WRITE_BYTE( m_iId );
MESSAGE_END();
return TRUE;
}
return FALSE;
}

BOOL CM16::Deploy( )
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/m4a1_deploy.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/m4a1_boltpull.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));

// M4A1 총기를 다시 draw
// 대부분 'q'를 누를 때 M4A1이 다시 그려지는 모습을 보게됨
return DefaultDeploy( "models/v_m16.mdl", "models/p_m16.mdl", M16_DRAW, "m16" );

}


void CM16::PrimaryAttack()
{
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound( );
m_flNextPrimaryAttack = 0.15;
return;
}

if (m_iClip <= 0)
{
PlayEmptySound();
m_flNextPrimaryAttack = 0.15;
return;
}

m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;

m_iClip--;


m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;

m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
Vector vecDir;

if(!m_bSilenced) // 만약 소음기 비장착상태이면
// 화력 향상
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_4DEGREES, 8192, BULLET_PLAYER_M16, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
else // 소음기 장착상태이면
// 정확도 향상
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_2DEGREES, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );

int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif

if(!m_bSilenced) // 만약 소음기 비장착상태이면
{
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usM16, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );
}
else // 소음기 장착상태이면
{
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usM162, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );
}

if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);

m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;

if ( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() )
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;

m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}

void CM16::SecondaryAttack( void )
{
int iAnim;

if(!m_bSilenced) // 만약 소음기 비장착상태이면
{
m_bSilenced = TRUE; // 소음기 장착상태로 변경
iAnim = M16_ADD_SILENCER; // 소음기 장착 애니메이션
}
else // 만약 소음기 장착상태면
{
m_bSilenced = FALSE; // 소음기 비장착상태로 변경
iAnim = M16_DETACH_SILENCER; // 소음기 제거 애니메이션
}

//EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/glauncher.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));

// 소음기, 비소음기 delay의 값을 Counter-Strike의 M4A1은 +2로 해주는것이 sound와 잘 맞는다.
// {
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2; // 소음기 비소음기 전환 딜레이
// }

SendWeaponAnim( iAnim, 1 );

pev->nextthink = UTIL_WeaponTimeBase() + 3.0;
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 3.0;

// 소음기 장착 여부에 따라서 sound 출력
if( m_bSilenced )
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/m4a1_silencer_on.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));
else
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/m4a1_silencer_off.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));
}

void CM16::Reload( void )
{
if ( m_pPlayer->ammo_9mm <= 0 ) // 만약 총알이 없다면
return;

if(!m_bSilenced) // 만약 소음기 비장착상태이면
{
DefaultReload( M16_MAX_CLIP, M16_RELOAD_UNSIL, 2.75 ); // 비장착 재장전 애니메이션
}
else // 만약 소음기 장착상태이면
{
DefaultReload( M16_MAX_CLIP, M16_RELOAD, 2.75 ); // 장착 재장전 애니메이션
}

EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/m4a1_clipout.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/m4a1_clipin.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));
}

void CM16::WeaponIdle( void )
{
ResetEmptySound( );

m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );

int iAnim;

if(!m_bSilenced) // If the gun isnt silenced
{
iAnim = M16_IDLE_UNSIL;
}
else // If it is silenced
{
iAnim = M16_IDLE;
}

SendWeaponAnim( iAnim );
}

class CM16AmmoClip : public CBasePlayerAmmo
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_9mmARclip.mdl");
CBasePlayerAmmo::Spawn( );
}

void Precache( void )
{
PRECACHE_MODEL ("models/w_9mmARclip.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
}

BOOL AddAmmo( CBaseEntity *pOther )
{
int bResult = (pOther->GiveAmmo( AMMO_M16CLIP_GIVE, "9mm", _9MM_MAX_CARRY) != -1);
if (bResult)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
}
return bResult;
}
};
LINK_ENTITY_TO_CLASS( ammo_m16clip, CM16AmmoClip );

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/weapons.h
작업위치:
// The amount of ammo given to a player by an ammo item.
#define AMMO_URANIUMBOX_GIVE 20
...
#define AMMO_CROSSBOWCLIP_GIVE CROSSBOW_MAX_CLIP
#define AMMO_RPGCLIP_GIVE RPG_MAX_CLIP
#define AMMO_URANIUMBOX_GIVE 20
#define AMMO_SNARKBOX_GIVE 5

바로 아래 부분
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

#define WEAPON_M16 16 // 무기에 대한 번호: 이것은 매우 중요함! 무기가 추가되는 대로 거기에 맞춰 번호를 sequence 대로 맞춰야 함
#define M16_WEIGHT 20 // 무기중 우선권
#define M16_MAX_CARRY 250 // 최대총알수
#define M16_MAX_CLIP 30 // 한탄창 최대총알수
#define M16_DEFAULT_GIVE 250 // 디폴트로 주어지는 총알수
#define AMMO_M16CLIP_GIVE 30 // 주운탄창 총알수

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/weapons.h
작업위치:
class CPython : public CBasePlayerWeapon
{
public:
...
private:
unsigned short m_usFirePython;
};

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

class CM16 : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 3; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer( CBasePlayer *pPlayer );

void PrimaryAttack( void );
void SecondaryAttack( void );
BOOL Deploy( void );
void Reload( void );
void WeaponIdle( void );
float m_flNextAnimTime;
int m_iShell;
bool m_bSilenced;

virtual BOOL UseDecrement( void )
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}

private:
unsigned short m_usM16;
unsigned short m_usM162;
};

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/weapons.cpp
작업위치:
// called by worldspawn
void W_Precache(void)
{
...
// mp5
UTIL_PrecacheOtherWeapon( "weapon_9mmAR" );
UTIL_PrecacheOther( "ammo_9mmAR" );
UTIL_PrecacheOther( "ammo_ARgrenades" );

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

// 하프라이프에 m16 화기와 탄약을 precache 합니다.
UTIL_PrecacheOtherWeapon( "weapon_m16" );
UTIL_PrecacheOther( "ammo_m16clip" );

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/weapons.h
작업위치:
// bullet types
typedef enum
{
...
BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

BULLET_PLAYER_M16, // m16

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/combat.cpp
작업위치:
Vector CBaseEntity::FireBulletsPlayer ( ... )
{
...
...
case BULLET_PLAYER_357:
...
< 추가 할 곳 >
case BULLET_NONE: // FIX
...

에서 case BULLET_PLAYER_357: 와 case BULLET_NONE: // FIX 사이에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

case BULLET_PLAYER_M16: // 총알이 발사될 때 호출
pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgM16, vecDir, &tr, DMG_BULLET);
break;

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/multiplay_gamerules.cpp
작업위치:
void CHalfLifeMultiplay::RefreshSkillData( void )
{
...

// hornet
gSkillData.plrDmgHornet = 10;

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

// m16
gSkillData.plrDmgM16 = 20; // 맞았을 때 damage

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/skill.h
작업위치:
struct skilldata_t
{
...
// Player Weapons
float plrDmgCrowbar;
float plrDmg9MM;
...
float plrDmgSatchel;
float plrDmgTripmine;

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

float plrDmgM16;

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/weapons.cpp
작업위치:
void DecalGunshot( TraceResult *pTrace, int iBulletType )
{
...
switch( iBulletType )
{
case BULLET_PLAYER_9MM:
case BULLET_MONSTER_9MM:
...
case BULLET_PLAYER_357:

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

case BULLET_PLAYER_M16:

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: mp files/multiplay_gamerules.cpp
작업위치:
void CHalfLifeMultiplay :: PlayerSpawn( CBasePlayer *pPlayer )
{
...
if ( addDefault )
{
pPlayer->GiveNamedItem( "weapon_crowbar" );
pPlayer->GiveNamedItem( "weapon_9mmhandgun" );

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

pPlayer->GiveNamedItem( "weapon_m16" ); // 플레이어가 스폰될 때 m16이 주어집니다.

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/hl_events.cpp
작업위치:
extern "C"
{
// HLDM
void EV_FireGlock1( struct event_args_s *args );
...
void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args );

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

void EV_FireM16( struct event_args_s *args );
void EV_FireM162( struct event_args_s *args );

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/hl_events.cpp
작업위치:
void Game_HookEvents( void )
{
gEngfuncs.pfnHookEvent( "events/glock1.sc", EV_FireGlock1 );
...
gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

gEngfuncs.pfnHookEvent( "events/m16.sc", EV_FireM16 );
gEngfuncs.pfnHookEvent( "events/m162.sc", EV_FireM162 );

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/hl_weapons.cpp
작업위치: 전역변수
// HLDM Weapon placeholder entities.
CGlock g_Glock;
...
CTripmine g_Tripmine;
CSqueak g_Snark;

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

CM16 g_M16;

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/hl_weapons.cpp
작업위치:
void HUD_InitClientWeapons( void )
{
...
HUD_PrepEntity( &g_Tripmine , &player );
HUD_PrepEntity( &g_Snark , &player );

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

HUD_PrepEntity( &g_M16 , &player );

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/hl_weapons.cpp
작업위치:
void HUD_WeaponsPostThink( ... )
{
...
case WEAPON_MP5:
pWeapon = &g_Mp5;
break;

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

case WEAPON_M16:
pWeapon = &g_M16;
break;

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/ev_hldm.cpp
작업위치:
//======================
// SQUEAK END
//======================

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

//======================
// M16 START
//======================
enum m16_e
{
M16_IDLE,
M16_SHOOT1,
M16_SHOOT2,
M16_SHOOT3,
M16_RELOAD,
M16_DRAW,
M16_ADD_SILENCER,
M16_IDLE_UNSIL,
M16_SHOOT1_UNSIL,
M16_SHOOT2_UNSIL,
M16_SHOOT3_UNSIL,
M16_RELOAD_UNSIL,
M16_DRAW_UNSIL,
M16_DETACH_SILENCER,
};

// Normal Fire
void EV_FireM16( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;

vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
float flSpread = 0.01;

idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );

AngleVectors( angles, forward, right, up );

shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");

if ( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( M16_SHOOT1_UNSIL + gEngfuncs.pfnRandomLong(0,2), 2 );

V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -2, 2 ) );
}

EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );

EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );

// 소음기 비장착시 fire sound
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m4a1_unsil-1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m4a1_unsil-2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
}

EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );

if ( gEngfuncs.GetMaxClients() > 1 )
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_M16, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_M16, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
}

// Silenced
void EV_FireM162( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;

vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
float flSpread = 0.01;

idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );

AngleVectors( angles, forward, right, up );

shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");

if ( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( M16_SHOOT1 + gEngfuncs.pfnRandomLong(0,2), 2 );

V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -2, 2 ) );
}

EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );

EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );

// 소음기 장착시 fire sound
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m4a1-1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m4a1-1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
}

EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );

if ( gEngfuncs.GetMaxClients() > 1 )
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_M16, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_M16, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
}
//======================
// M16 END
//======================

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/ev_hldm.cpp
작업위치:
extern "C"
{

// HLDM
void EV_FireGlock1( struct event_args_s *args );
...
void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args );

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

void EV_FireM16( struct event_args_s *args );
void EV_FireM162( struct event_args_s *args );

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/ev_hldm.cpp
작업위치:
void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType )
{
...
switch( iBulletType )
{
case BULLET_PLAYER_357:

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

case BULLET_PLAYER_M16:

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/ev_hldm.cpp
작업위치:
int EV_HLDM_CheckTracer( ... )
{
...
switch( iBulletType )
{
case BULLET_MONSTER_12MM:

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

case BULLET_PLAYER_M16:

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/hl/ev_hldm.cpp
작업위치:
void EV_HLDM_FireBullets( ... )
{
...
switch(iBulletType)
{
default:
case BULLET_PLAYER_9MM:
...
case BULLET_PLAYER_357:

EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );

break;

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

case BULLET_PLAYER_M16:
if ( !tracer )
{
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
}
break;

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: cl_dll files/ev_hldm.h
작업위치:
// bullet types
typedef enum
{
BULLET_NONE = 0,
...
BULLET_PLAYER_CROWBAR, // crowbar swipe

바로 아래 부분에 작성
--------------------------------------------------------------
// 018killer: AddWeapons [
// Purpose: m16

BULLET_PLAYER_M16,

// 018killer: AddWeapons ]
==============================================================



--------------------------------------------------------------
파일명: m16.sc, m162.sc
작업위치:
모드의 events 폴더
Steam/SteamApps/내 계정/half-life/My_MOD/events

--------------------------------------------------------------
모드의 events 폴더에 m16.sc , m162.sc 을 만듭니다.
(이름만 같게해서 내용없는 파일을 만든다.)
==============================================================



--------------------------------------------------------------
파일명: p_m16.mdl, v_m16.mdl, w_m16.mdl
작업위치:
Steam/SteamApps/내 계정/half-life/My_MOD/models

--------------------------------------------------------------
모드의 models 디렉토리에 m16 관련 modeling file 들을 넣어 줍니다.
m16 model은 아래의 url로 download 하시고,
아니면 Counter-Strike 안에 있는 M4A1 model 들을 사용하셔도 됩니다.

Download URL:
hl_m16_cs.zip
http://cocowest.javasarang.net/wiki/wiki.php/M16_%BC%D2%C0%BD%B1%E2%BB%E7%BF%EB?action=download&value=hl_m16_cs.zip
==============================================================



--------------------------------------------------------------
파일명: m4a1_silencer_on.wav, m4a1_silencer_off.wav, m4a1_clipout.wav, m4a1_clipin.wav, m4a1_deploy, m4a1_boltpull.wav, m4a1_unsil-1, m4a1-1.wav
작업위치:
Steam/SteamApps/내 계정/half-life/My_MOD/sound/weapons

--------------------------------------------------------------
모드의 sound/weapons 디렉토리에 m4a1 관련 sound file 들을 넣어 줍니다.
m4a1 관련 sound 파일들은 Counter-Strike 안에 있는 sound/weapons/M4A1 관련 .wav 파일 들을 사용하시면 됩니다.
==============================================================



--------------------------------------------------------------
파일명: weapon_m4a1.txt
작업위치:
Steam/SteamApps/내 계정/half-life/My_MOD/sprites

--------------------------------------------------------------
weapon_m4a1.txt 파일은 HUD에서 사용되는 AIM 입니다.
이 파일이 없으면 HUD상에 해당 무기의 AIM이 보이질 않습니다.
CS에서 사용되는 무기들은 counter-strike.gcf 파일안에 sprites 디렉토리에 있습니다.
==============================================================


------------------------
파일명: weapon_m4a1.txt
------------------------
10
weapon 320 320hud1 80 40 80 20
weapon_s 320 320hud1 80 60 80 20
ammo 320 640hud7 0 96 24 24
crosshair 320 crosshairs 24 0 24 24
autoaim 320 crosshairs 0 72 24 24
weapon 640 640hud2 0 45 170 45
weapon_s 640 640hud5 0 45 170 45
ammo 640 640hud7 0 96 24 24
crosshair 640 crosshairs 24 0 24 24
autoaim 640 crosshairs 0 72 24 24



이상입니다.
질문이나 fix 되어야 할 점이 있을시엔 godmode2k@hotmail.com 으로 메일을 보내주시기 바랍니다.

댓글 없음:

댓글 쓰기