화요일, 10월 24, 2006

일기 (2006.10.24)

Today was bright and clear. Same as me. yup, i've saw 'Samurai 7' tv series up to end episode. A like story as 'Rurouni Kenshin' just my case and very impressed as team works, feel proud and ^^ a little bit a funny. Would you like watch the 'Samurai 7' ? :)

hmm, .mdl motion control, ^^ I hit it made. but, not yet perfectly. I've found problem how can i control frame rate as .mdl ported to .b3d with animate mesh. The point is distance. yeah, its a nothing, funny huh ? Catch a key frame approximately 21 times in RUN animated 35 frame. So i calculated player postion Z value as distance per frame rate. Full distance value is 260.0(only RUN) and 21 up to 25 frame rate so, 12.3 per 1 frame. Look so not perfectly but not bad. I'll try continue... :)

토요일, 10월 21, 2006

일기 (2006.10.21)

ok, today was not a bad time. I've saw japanese animation called 'Samurai 7' tv series episode 13 up to 18(9)?. A fight katana with new weapon gun at that age. really cool. and Kyuzo... i like his style. Check it out below quote.


http://www.animovies.com/Product/Group.asp?GID=1068
A small village is being persecuted by robbers who return every harvest to seize the village''''s crops. Faced with starvation, the villagers send out a mission to find and recruit some samurai to defend them. With no pay to offer except rice, and knowing full well that only down-on-their-luck samurai would even consider accepting such an deal, the villagers can only hope that their saviours will appear before the rice is ready for harvest.

목요일, 10월 19, 2006

Purpose: Teamplay 시 player 가 처음 서버에 접속했을 때 이상하게 spawn 되는걸 fix

-= Teamplay 시 player 가 처음 서버에 접속했을 때 이상하게 spawn 되는걸 fix =-

Purpose: Teamplay 시 player 가 처음 서버에 접속했을 때 이상하게 spawn 되는걸 fix
Author: godmode2k (godmode2k@hotmail.com | MSN IM)
Date: September. 04. 2005
Destination:
Source:


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

(*)Special thanks to:



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 포함)"
7. "기존 M16에서 CS(카스)의 M4A1 weapon 만들기"
8. "AK47 weapon 만들기"
9. "Teamplay 시 player 가 처음 서버에 접속했을 때 이상하게 spawn 되는걸 fix"

주소는: 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
7. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=99
8. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=100
9. n/a

[ 추가사항 ]


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

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

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

*** 이 tutorial 은 6. "Counter-Strike 처럼 Team System 만들기(수정된 Radio Command Menu 포함)" 가 추가되었다는
사실하에 작성된 글입니다. (반드시 추가한 후에 작성하시기 바랍니다.)


--------------------------------------------------------------
파일명: mp files/player.cpp
작업위치:
edict_t *EntSelectTeamSpawnPoint( CBaseEntity *pPlayer )
{
CBaseEntity *pSpot;
edict_t *player;

player = pPlayer->edict();
CBasePlayer *cbPlayer = (CBasePlayer *)pPlayer; // Get a CBasePlayer
...
ReturnSpot:
if( FNullEnt( pSpot ) )
{
ALERT( at_error, "PutClientServer: no spawn points on level" );
return INDEXENT(0);
}

g_pLastSpawn = pSpot;

바로 아래 부분에 작성( 이 부분에 작성 )

return pSpot->edict();
}

--------------------------------------------------------------
// 018killer: Player Spawn at First time Teamplay [
// Purpose: Teamplay 시 player 가 처음 서버에 접속했을 때 이상하게 spawn 되는걸 fix
// player.cpp: CBasePlayer :: Spawn() 에서의 g_pGameRules->PlayerSpawn( cbPlayer ); 코드를 주석 처리하고
// player.cpp: edict_t *EntSelectTeamSpawnPoint( CBaseEntity *pPlayer ) {} 안의 ReturnSpot: 에 넣어주자

g_pGameRules->PlayerSpawn( cbPlayer );

// 018killer: Player Spawn at First time Teamplay ]
==============================================================



--------------------------------------------------------------
파일명: mp files/player.cpp
작업위치:
void CBasePlayer::Spawn( void )
{
pev->classname = MAKE_STRING("player");
pev->health = 100;
pev->armorvalue = 0;
pev->takedamage = DAMAGE_AIM;
...
m_flNextChatTime = gpGlobals->time;
g_pGameRules->PlayerSpawn( this );
}

에서 g_pGameRules->PlayerSpawn( this ); 를 아래와 같이 주석처리
--------------------------------------------------------------
// 018killer: Player Spawn at First time Teamplay [
// Purpose: Teamplay 시 player 가 처음 서버에 접속했을 때 이상하게 spawn 되는걸 fix
// player.cpp: CBasePlayer :: Spawn() 에서의 g_pGameRules->PlayerSpawn( cbPlayer ); 코드를 주석 처리하고
// player.cpp: edict_t *EntSelectTeamSpawnPoint( CBaseEntity *pPlayer ) {} 안의 ReturnSpot: 에 넣어주자

// g_pGameRules->PlayerSpawn( this );

// 018killer: Player Spawn at First time Teamplay ]
==============================================================



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

Purpose: AK47 weapon 만들기

-= CS(카스)의 AK47 weapon 만들기 =-

Purpose: AK47 weapon 만들기
Author: godmode2k (godmode2k@hotmail.com | MSN IM)
Date: October. 12. 2004
Destination: 모드나라 (http://mod.zoa.to)
Source:
http://www.planethalflife.com/hlprogramming/tutorial.asp?i=233


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

(*)Special thanks to:
- Adrien Shepard (adrien_shepard@hotmail.com)


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 포함)"
7. "기존 M16에서 CS(카스)의 M4A1 weapon 만들기"

주소는: 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
7. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=99

[ 추가사항 ]
* 원본 ak47.cpp 파일만으로는 동작하지 않습니다.
* 따라서 기존 M4A1의 코드와 흐름을 같이 했으며, 원본 ak47.cpp 자체 코드의 수정이 있었습니다.
*
*


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

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

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


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

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



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

#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 ak47_e
{
AK47_IDLE1,
AK47_RELOAD,
AK47_DRAW,
AK47_SHOOT1,
AK47_SHOOT2,
AK47_SHOOT3
};


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


// This is where you can change the animations,
// so if you have a model with diff anmations and you want to use it,
// you would also need to define the new animations in some of the classes like
// reload, idle, primary attack etc.

LINK_ENTITY_TO_CLASS( weapon_ak47, CAK47 );


//=========================================================
//=========================================================
void CAK47::Spawn( )
{
pev->classname = MAKE_STRING("weapon_ak47"); // hack to allow for old names
Precache( );
SET_MODEL(ENT(pev), "models/w_ak47.mdl");
m_iId = WEAPON_AK47;

m_iDefaultAmmo = AK47_DEFAULT_GIVE;

FallInit();// get ready to fall down.
}


void CAK47::Precache( void )
{
PRECACHE_MODEL("models/v_ak47.mdl");
PRECACHE_MODEL("models/w_ak47.mdl");
PRECACHE_MODEL("models/p_ak47.mdl");

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

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

PRECACHE_MODEL("models/player/sas/sas.mdl");

// Counter-Strike에 있는 AK47 sound files [
PRECACHE_SOUND ("weapons/ak47_clipout.wav");
PRECACHE_SOUND ("weapons/ak47_clipin.wav");

PRECACHE_SOUND ("weapons/ak47_boltpull.wav");

PRECACHE_SOUND ("weapons/ak47-1.wav");
PRECACHE_SOUND ("weapons/ak47-2.wav");
// Counter-Strike에 있는 AK47 sound files ]

m_usAK47 = PRECACHE_EVENT( 1, "events/ak47.sc" );
m_usAK472 = PRECACHE_EVENT( 1, "events/ak472.sc" );
}


int CAK47::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "357";
// p->pszAmmo1 = "9mm";
p->iMaxAmmo1 = _357_MAX_CARRY;
// p->iMaxAmmo1 = _9MM_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = AK47_MAX_CLIP;
p->iSlot = 1;
p->iPosition = 4;
p->iFlags = 0;
p->iId = m_iId = WEAPON_AK47;
p->iWeight = AK47_WEIGHT;

return 1;
}


int CAK47::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 CAK47::Deploy( )
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/ak47_deploy.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/ak47_boltpull.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));

// AK47 총기를 다시 draw
// 대부분 'q'를 누를 때 AK47이 다시 그려지는 모습을 보게됨
return DefaultDeploy( "models/v_ak47.mdl", "models/p_ak47.mdl", AK47_DRAW, "mp5" ); // "mp5" -> "ak47"로 해도 무관
}


void CAK47::PrimaryAttack()
{
// don''t fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound( );
m_flNextPrimaryAttack = 0.15;
return;
}

// I have it set to where the ak can fire underwater right above just remove parts
// where I commented it out from "//PlayEmptySound( );" to "//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;

// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

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

// #ifdef CLIENT_DLL
// if ( !bIsMultiplayer() )
// #else
// if ( !g_pGameRules->IsMultiplayer() )
// #endif
// {
// optimized multiplayer. Widened to make it easier to hit a moving player
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_AK47, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
// }
// else
// {
// single player spread
// vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_357, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
// }

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

PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usAK47, 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)
// HEV suit - indicate out of ammo condition
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 CAK47::SecondaryAttack( void )
{
return;
}


void CAK47::Reload( void )
{
if ( m_pPlayer->ammo_357 <= 0 )
// if ( m_pPlayer->ammo_9mm <= 0 )
return;

DefaultReload( AK47_MAX_CLIP, AK47_RELOAD, 2.3 );
//DefaultReload( AK47_MAX_CLIP, AK47_RELOAD, 2.75 );

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


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

m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );

// if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
// return;

int iAnim;
// switch ( RANDOM_LONG( 0, 1 ) )
// {
// default:
// case 1:
iAnim = AK47_IDLE1;
// break;
// }

SendWeaponAnim( iAnim );

// m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); // how long till we do this again.
}


class CAK47AmmoClip : 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_AK47CLIP_GIVE, "357", _357_MAX_CARRY) != -1);
if (bResult)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
}
return bResult;
}
};


LINK_ENTITY_TO_CLASS( ammo_ak47clip, CAK47AmmoClip );

// 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: ak47

#define WEAPON_AK47 17 // 무기에 대한 번호: 이것은 매우 중요함! 무기가 추가되는 대로 거기에 맞춰 번호를 sequence 대로 맞춰야 함
#define AK47_WEIGHT 20 // 무기중 우선권
#define AK47_MAX_CARRY 250 // 최대총알수
#define AK47_MAX_CLIP 30 // 한탄창 최대총알수
#define AK47_DEFAULT_GIVE 250 // 디폴트로 주어지는 총알수
#define AMMO_AK47CLIP_GIVE 30 // 주운탄창 총알수

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



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

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

class CAK47 : 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_usAK47;
unsigned short m_usAK472;
};

// 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: ak47

// 하프라이프에 ak47 화기와 탄약을 precache 합니다.
UTIL_PrecacheOtherWeapon( "weapon_ak47" );
UTIL_PrecacheOther( "ammo_ak47clip" );

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



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

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

BULLET_PLAYER_AK47, // ak47

// 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: ak47

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

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



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

// hornet
gSkillData.plrDmgHornet = 10;

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

// ak47
gSkillData.plrDmgAK47 = 20; // 맞았을 때 damage

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



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

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

float plrDmgAK47;

// 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: ak47

case BULLET_PLAYER_AK47:

// 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: ak47

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

// 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: ak47

void EV_FireAK47( struct event_args_s *args );
void EV_FireAK472( 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: ak47

gEngfuncs.pfnHookEvent( "events/ak47.sc", EV_FireAK47 );
gEngfuncs.pfnHookEvent( "events/ak472.sc", EV_FireAK472 );

// 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: ak47

CAK47 g_AK47;

// 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: ak47

HUD_PrepEntity( &g_AK47 , &player );

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



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

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

case WEAPON_AK47:
pWeapon = &g_AK47;
break;

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



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

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

//======================
// AK47 START
//======================
enum ak47_e
{
AK47_IDLE1,
AK47_RELOAD,
AK47_DRAW,
AK47_SHOOT1,
AK47_SHOOT2,
AK47_SHOOT3,
};

// Normal Fire
void EV_FireAK47( 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( AK47_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 #1 sound
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-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_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
}

// Secondary
void EV_FireAK472( 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( AK47_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 #2 sound
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-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_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
}
//======================
// AK47 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: ak47

void EV_FireAK47( struct event_args_s *args );
void EV_FireAK472( 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: ak47

case BULLET_PLAYER_AK47:

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



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

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

case BULLET_PLAYER_AK47:

// 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: ak47

case BULLET_PLAYER_AK47:
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: ak47

BULLET_PLAYER_AK47,

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



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

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



--------------------------------------------------------------
파일명: p_ak47.mdl, v_ak47.mdl, w_ak47.mdl
작업위치:
Steam/SteamApps/내 계정/half-life/My_MOD/models

--------------------------------------------------------------
모드의 models 디렉토리에 ak47 관련 modeling file 들을 넣어 줍니다.
ak47 관련 model 파일들은 Counter-Strike 안에 있는 AK47 model 들을 사용하시면 됩니다.
==============================================================



--------------------------------------------------------------
파일명: ak47-1.wav, ak47-2.wav, ak47_boltpull.wav, ak47_clipin.wav, ak47_clipout.wav
작업위치:
Steam/SteamApps/내 계정/half-life/My_MOD/sound/weapons

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



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

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


------------------------
파일명: weapon_ak47.txt
------------------------
10
weapon 320 320hud1 160 80 80 20
weapon_s 320 320hud1 160 100 80 20
ammo 320 640hud7 72 72 24 24
crosshair 320 crosshairs 24 0 24 24
autoaim 320 crosshairs 0 72 24 24
weapon 640 640hud10 0 0 170 45
weapon_s 640 640hud11 0 0 170 45
ammo 640 640hud7 72 72 24 24
crosshair 640 crosshairs 24 0 24 24
autoaim 640 crosshairs 0 72 24 24



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

Purpose: AK46 weapon 만들기

-= CS(카스)의 AK47 weapon 만들기 =-

Purpose: AK46 weapon 만들기
Author: godmode2k (godmode2k@hotmail.com | MSN IM)
Date: October. 12. 2004
Destination: 모드나라 (http://mod.zoa.to)
Source:
http://www.planethalflife.com/hlprogramming/tutorial.asp?i=233


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

(*)Special thanks to:
- Adrien Shepard (adrien_shepard@hotmail.com)


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 포함)"
7. "기존 M16에서 CS(카스)의 M4A1 weapon 만들기"

주소는: 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
7. http://cocowest.javasarang.net/mod/bbs/view.php?&bbs_id=hlsdk&page=&doc_num=99

[ 추가사항 ]
* 원본 ak47.cpp 파일만으로는 동작하지 않습니다.
* 따라서 기존 M4A1의 코드와 흐름을 같이 했으며, 원본 ak47.cpp 자체 코드의 수정이 있었습니다.
*
*


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

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

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


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

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



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

#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 ak47_e
{
AK47_IDLE1,
AK47_RELOAD,
AK47_DRAW,
AK47_SHOOT1,
AK47_SHOOT2,
AK47_SHOOT3
};


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


// This is where you can change the animations,
// so if you have a model with diff anmations and you want to use it,
// you would also need to define the new animations in some of the classes like
// reload, idle, primary attack etc.

LINK_ENTITY_TO_CLASS( weapon_ak47, CAK47 );


//=========================================================
//=========================================================
void CAK47::Spawn( )
{
pev->classname = MAKE_STRING("weapon_ak47"); // hack to allow for old names
Precache( );
SET_MODEL(ENT(pev), "models/w_ak47.mdl");
m_iId = WEAPON_AK47;

m_iDefaultAmmo = AK47_DEFAULT_GIVE;

FallInit();// get ready to fall down.
}


void CAK47::Precache( void )
{
PRECACHE_MODEL("models/v_ak47.mdl");
PRECACHE_MODEL("models/w_ak47.mdl");
PRECACHE_MODEL("models/p_ak47.mdl");

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

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

PRECACHE_MODEL("models/player/sas/sas.mdl");

// Counter-Strike에 있는 AK47 sound files [
PRECACHE_SOUND ("weapons/ak47_clipout.wav");
PRECACHE_SOUND ("weapons/ak47_clipin.wav");

PRECACHE_SOUND ("weapons/ak47_boltpull.wav");

PRECACHE_SOUND ("weapons/ak47-1.wav");
PRECACHE_SOUND ("weapons/ak47-2.wav");
// Counter-Strike에 있는 AK47 sound files ]

m_usAK47 = PRECACHE_EVENT( 1, "events/ak47.sc" );
m_usAK472 = PRECACHE_EVENT( 1, "events/ak472.sc" );
}


int CAK47::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "357";
// p->pszAmmo1 = "9mm";
p->iMaxAmmo1 = _357_MAX_CARRY;
// p->iMaxAmmo1 = _9MM_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = AK47_MAX_CLIP;
p->iSlot = 1;
p->iPosition = 4;
p->iFlags = 0;
p->iId = m_iId = WEAPON_AK47;
p->iWeight = AK47_WEIGHT;

return 1;
}


int CAK47::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 CAK47::Deploy( )
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/ak47_deploy.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/ak47_boltpull.wav", 1, ATTN_NORM, 0, 94 + RANDOM_LONG(0,0xf));

// AK47 총기를 다시 draw
// 대부분 'q'를 누를 때 AK47이 다시 그려지는 모습을 보게됨
return DefaultDeploy( "models/v_ak47.mdl", "models/p_ak47.mdl", AK47_DRAW, "mp5" ); // "mp5" -> "ak47"로 해도 무관
}


void CAK47::PrimaryAttack()
{
// don''t fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound( );
m_flNextPrimaryAttack = 0.15;
return;
}

// I have it set to where the ak can fire underwater right above just remove parts
// where I commented it out from "//PlayEmptySound( );" to "//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;

// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

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

// #ifdef CLIENT_DLL
// if ( !bIsMultiplayer() )
// #else
// if ( !g_pGameRules->IsMultiplayer() )
// #endif
// {
// optimized multiplayer. Widened to make it easier to hit a moving player
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_AK47, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
// }
// else
// {
// single player spread
// vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_357, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
// }

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

PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usAK47, 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)
// HEV suit - indicate out of ammo condition
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 CAK47::SecondaryAttack( void )
{
return;
}


void CAK47::Reload( void )
{
if ( m_pPlayer->ammo_357 <= 0 )
// if ( m_pPlayer->ammo_9mm <= 0 )
return;

DefaultReload( AK47_MAX_CLIP, AK47_RELOAD, 2.3 );
//DefaultReload( AK47_MAX_CLIP, AK47_RELOAD, 2.75 );

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


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

m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );

// if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
// return;

int iAnim;
// switch ( RANDOM_LONG( 0, 1 ) )
// {
// default:
// case 1:
iAnim = AK47_IDLE1;
// break;
// }

SendWeaponAnim( iAnim );

// m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); // how long till we do this again.
}


class CAK47AmmoClip : 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_AK47CLIP_GIVE, "357", _357_MAX_CARRY) != -1);
if (bResult)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
}
return bResult;
}
};


LINK_ENTITY_TO_CLASS( ammo_ak47clip, CAK47AmmoClip );

// 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: ak47

#define WEAPON_AK47 17 // 무기에 대한 번호: 이것은 매우 중요함! 무기가 추가되는 대로 거기에 맞춰 번호를 sequence 대로 맞춰야 함
#define AK47_WEIGHT 20 // 무기중 우선권
#define AK47_MAX_CARRY 250 // 최대총알수
#define AK47_MAX_CLIP 30 // 한탄창 최대총알수
#define AK47_DEFAULT_GIVE 250 // 디폴트로 주어지는 총알수
#define AMMO_AK47CLIP_GIVE 30 // 주운탄창 총알수

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



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

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

class CAK47 : 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_usAK47;
unsigned short m_usAK472;
};

// 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: ak47

// 하프라이프에 ak47 화기와 탄약을 precache 합니다.
UTIL_PrecacheOtherWeapon( "weapon_ak47" );
UTIL_PrecacheOther( "ammo_ak47clip" );

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



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

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

BULLET_PLAYER_AK47, // ak47

// 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: ak47

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

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



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

// hornet
gSkillData.plrDmgHornet = 10;

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

// ak47
gSkillData.plrDmgAK47 = 20; // 맞았을 때 damage

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



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

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

float plrDmgAK47;

// 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: ak47

case BULLET_PLAYER_AK47:

// 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: ak47

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

// 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: ak47

void EV_FireAK47( struct event_args_s *args );
void EV_FireAK472( 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: ak47

gEngfuncs.pfnHookEvent( "events/ak47.sc", EV_FireAK47 );
gEngfuncs.pfnHookEvent( "events/ak472.sc", EV_FireAK472 );

// 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: ak47

CAK47 g_AK47;

// 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: ak47

HUD_PrepEntity( &g_AK47 , &player );

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



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

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

case WEAPON_AK47:
pWeapon = &g_AK47;
break;

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



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

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

//======================
// AK47 START
//======================
enum ak47_e
{
AK47_IDLE1,
AK47_RELOAD,
AK47_DRAW,
AK47_SHOOT1,
AK47_SHOOT2,
AK47_SHOOT3,
};

// Normal Fire
void EV_FireAK47( 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( AK47_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 #1 sound
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-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_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
}

// Secondary
void EV_FireAK472( 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( AK47_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 #2 sound
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/ak47-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_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_AK47, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
}
}
//======================
// AK47 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: ak47

void EV_FireAK47( struct event_args_s *args );
void EV_FireAK472( 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: ak47

case BULLET_PLAYER_AK47:

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



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

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

case BULLET_PLAYER_AK47:

// 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: ak47

case BULLET_PLAYER_AK47:
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: ak47

BULLET_PLAYER_AK47,

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



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

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



--------------------------------------------------------------
파일명: p_ak47.mdl, v_ak47.mdl, w_ak47.mdl
작업위치:
Steam/SteamApps/내 계정/half-life/My_MOD/models

--------------------------------------------------------------
모드의 models 디렉토리에 ak47 관련 modeling file 들을 넣어 줍니다.
ak47 관련 model 파일들은 Counter-Strike 안에 있는 AK47 model 들을 사용하시면 됩니다.
==============================================================



--------------------------------------------------------------
파일명: ak47-1.wav, ak47-2.wav, ak47_boltpull.wav, ak47_clipin.wav, ak47_clipout.wav
작업위치:
Steam/SteamApps/내 계정/half-life/My_MOD/sound/weapons

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



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

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


------------------------
파일명: weapon_ak47.txt
------------------------
10
weapon 320 320hud1 160 80 80 20
weapon_s 320 320hud1 160 100 80 20
ammo 320 640hud7 72 72 24 24
crosshair 320 crosshairs 24 0 24 24
autoaim 320 crosshairs 0 72 24 24
weapon 640 640hud10 0 0 170 45
weapon_s 640 640hud11 0 0 170 45
ammo 640 640hud7 72 72 24 24
crosshair 640 crosshairs 24 0 24 24
autoaim 640 crosshairs 0 72 24 24



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

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 으로 메일을 보내주시기 바랍니다.