-= 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 으로 메일을 보내주시기 바랍니다.
목요일, 10월 19, 2006
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: 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: 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 으로 메일을 보내주시기 바랍니다.
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 으로 메일을 보내주시기 바랍니다.
피드 구독하기:
글 (Atom)