Tutorial: Add a new simple weapon (straightforward way) Last edited 1 year ago2022-09-29 09:54:21 UTC

You are viewing an older revision of this wiki page. The current revision may be more detailed and up-to-date. Click here to see the current revision of this page.
DISCLAIMER
This is not a proper way of adding new weapon because it does not use client side prediction and stuffs, but it is still reliable for single player mods. For more complete guide, refer Weapons Programming - Standard Weapons.
Are you programming for a single-player Half-Life mod and looking for an easy way to add new, normal hitscan, shooting weapons? You are at the right place. In this guide, we will look into a way to add AK-47 from CS 1.6 to Half-Life.

Before we start

This guide requires you to use:

Get the files

Get the models, sound and sprites from CS 1.6 and put in the respective folders in your mod folder. Assets to be taken:

Files to edit

As a bare minimum, these are the files needed to be edited to get a working weapon (minus client side prediction). They are: As a matter of fact, ak47.cpp needs to be manually created by right clicking dlls folder in hldll/Source Files, click Add, New Item, and type in ak47. This file needs to be updated to hl_cdll as well by finding its location (alongside other weapons, search for mp5.cpp for example). Right click on the folder, click Add and click Existing Items and find the ak47.cpp.

weapons.h

Scroll down and paste this code
enum ak47_e
{
    AK47_IDLE,
    AK47_RELOAD,
    AK47_DRAW,
    AK47_SHOOT1,
    AK47_SHOOT2,
    AK47_SHOOT3,
};

class CAK47 : public CBasePlayerWeapon
{
    void Spawn();
    void Precache();
    int iItemSlot() { return 2; }
    bool GetItemInfo(ItemInfo* p);
    void PrimaryAttack();
    void Reload();
    bool Deploy();
    void WeaponIdle();
    bool UseDecrement()
    {
#if defined(CLIENT_WEAPONS)
        return true;
#else
        return false;
#endif
    }

    int m_iShell;
};

ak47.cpp

Paste this code
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "player.h"
#include "soundent.h"
#include "gamerules.h"
#include "UserMessages.h"

LINK_ENTITY_TO_CLASS(weapon_ak47, CAK47);

void CAK47::Spawn()
{
    Precache();
    SET_MODEL(ENT(pev), "models/w_ak47.mdl");
    m_iId = WEAPON_AK47;
    m_iDefaultAmmo = 30;
    FallInit(); // get ready to fall down.
}

void CAK47::Precache()
{
    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_SOUND("weapons/ak47-1.wav");
}

bool CAK47::GetItemInfo(ItemInfo* p)
{
    p->pszName = STRING(pev->classname);
    p->pszAmmo1 = "762";
    p->iMaxAmmo1 = 90;
    p->pszAmmo2 = NULL;
    p->iMaxAmmo2 = NULL;
    p->iMaxClip = 30;
    p->iSlot = 2;
    p->iPosition = 3;
    p->iFlags = 0;
    p->iId = m_iId = WEAPON_AK47;
    p->iWeight = MP5_WEIGHT;

    return true;
}

bool CAK47::Deploy()
{
    return DefaultDeploy("models/v_ak47.mdl", "models/p_ak47.mdl", AK47_DRAW, "mp5");
}

void CAK47::PrimaryAttack()
{
    // don't fire underwater
    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_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 = m_pPlayer->FireBulletsPlayer(1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MP5,
        1, 30, m_pPlayer->pev, m_pPlayer->random_seed);

    SendWeaponAnim(AK47_SHOOT1 + RANDOM_LONG(0, 2));
    EMIT_SOUND(edict(), CHAN_AUTO, "weapons/ak47-1.wav", 1, ATTN_NORM);

    Vector vecShellVelocity = m_pPlayer->pev->velocity + gpGlobals->v_right * RANDOM_FLOAT(100, 200) +
        gpGlobals->v_up * RANDOM_FLOAT(100, 150) + gpGlobals->v_forward * 25;
    EjectBrass(pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_up * -12 + gpGlobals->v_forward * 20 +
        gpGlobals->v_right * -8, vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL);

    m_pPlayer->pev->punchangle.x -= 2;
    m_iClip--;
    m_flNextPrimaryAttack = 0.1;
    m_flTimeWeaponIdle = 0.85;
}

void CAK47::Reload()
{
    DefaultReload(30, AK47_RELOAD, 2.5);
}


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

    if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
        return;

    SendWeaponAnim(AK47_IDLE);
}

cdll_dll.h

Add WEAPON_AK47 in the same WeaponID enum.

hl_weapons.cpp

case WEAPON_SNARK:
        pWeapon = &g_Snark;
        break;
and paste
case WEAPON_AK47:
    pWeapon = &g_AK47;
    break;
below it.

weapons.cpp

Find UTIL_PrecacheOtherWeapon("weapon_hornetgun"); and paste UTIL_PrecacheOtherWeapon("weapon_ak47"); below it.

player.cpp (Optional)

This is to add ak47 to the impulse 101 cheat command. Find GiveNamedItem("weapon_hornetgun"); and paste GiveNamedItem("weapon_ak47"); below it.

Finale

Save and compile your codes. It should give you a working AK-47 under the Crossbow slot.

Edits

If you want to edit some of the attributes, you can do as below.

Enjoy!

You now have a working AK-47!

2 Comments

Commented 10 months ago2023-06-25 12:29:38 UTC Comment #105376
Works 100%. Thx. but my I ask you question, how can I use desert eagle sprites? I already have code for it but I can't bcz of sprites
Commented 9 months ago2023-07-16 04:08:33 UTC Comment #105403
@Draxler: What sprites? Do you mean the laser?

You must log in to post a comment. You can login or register a new account.