Forum posts

Posted 10 months ago2024-01-17 17:31:14 UTC
in What Is half Life SDK? Post #348454
Hello. I think this is a great question. Half-Life SDK ("SDK" stands for Software Development Kit) is a tool available to all Steam users who wants to modding Half-Life. If you purchased Half-Life on Steam, and type "Half-Life SDK" in the search box, you will be able to download it and have access to almost all the content for modifying Half-Life. I say "almost everything" because the source code of the game is not contained there, which you can find here (at least the official one).
Post data: Valve said at the end of November last year that they will update the Half-Life SDK, but they haven't done it yet (at least, they haven't released it).
Posted 1 year ago2023-09-30 15:39:25 UTC
in Using AI to create textures Post #347895
Hey. Nice method. Thanks for sharing. :biggrin:
Posted 1 year ago2023-01-07 23:13:58 UTC
in Coding issue: Monster infighting! Post #347222
Hello all, and happy new year!

I want to make an NPC (who is an enemy of the player) attack another NPC who accidentally damaged him. For example, if a monster_zombie is hit by a lightning bolt launched by a monster_alien_slave, then the former starts fighting the latter (ignoring the player momentarily).

So far, I did this that gives me error:

In zombie.cpp:
int CZombie :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
    // Trying to accomplish, unsuccessfully, monster infighting
    if ( pevAttacker->flags & FL_MONSTER )
    {
        ALERT( at_console, "Monster infighting!\n" );
        m_hEnemy->pev = pevAttacker;
    }
(...)
}
Once the monster_zombie takes damage from, in this case, a monster_alien_slave that launched its beam, the console displays the following message:
"Host_Error: WriteDest_Parm: not a client". And the game ends.

Maybe what I did is wrong (most likely.) Does anyone know how to achieve the monster infighting in Half-Life (if possible)?
Also, I want that once the monster_zombie has killed the monster_alien_slave (or simply the latter has died for another reason), the former starts attacking the player again.

Thanks in advance.
Posted 2 years ago2022-02-25 11:22:47 UTC
in Problems when level changes [Coding] Post #346295
Thanks for finding another problem and giving a hint on how I could improve the item I created. :)

PS: I will no longer use the expression I used to refer to highly skilled programmers.
Posted 2 years ago2022-02-24 14:45:53 UTC
in Problems when level changes [Coding] Post #346292
Hello everyone. I need help with a programming question (please, Lords of Coding, help!).

I have created an item that when picked up gives you 200 health points (the item is called "item_megahealth").
After 6 seconds have passed, the player's health points begin to drop until they reach 100 health points.

This works correctly on the map where I pick up the item, but when I go to another map (that is, when I go through a "trigger_changelevel") the item no longer works (ie the player's health points don't keep going down to 100).

If I go back to the original map, the health points continue to go down to 100.

I show you the code that I implemented (you can use it if you want):
// NEW MEGAHEALTH
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "items.h"

extern int gmsgItemPickup;

class CMegaHealth : public CItem
{
    void Spawn( void );
    void Precache( void );
    BOOL MyTouch( CBasePlayer *pPlayer );
    void EXPORT HealthThink( void );
};

LINK_ENTITY_TO_CLASS( item_megahealth, CMegaHealth );

void CMegaHealth :: Spawn( void )
{
    Precache();
    SET_MODEL(ENT(pev), "models/tool_box.mdl");
    CItem::Spawn();
}

void CMegaHealth :: Precache( void )
{
    PRECACHE_MODEL("models/tool_box.mdl");
    PRECACHE_SOUND("items/megahealth.wav");
}

BOOL CMegaHealth::MyTouch( CBasePlayer *pPlayer )
{
    if ( pPlayer->pev->deadflag != DEAD_NO )
    {
        return FALSE;
    }
    if ( ( pPlayer->pev->weapons & (1<<WEAPON_SUIT) ) )
    {
        pPlayer->pev->health = 200;
        EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/megahealth.wav", 1, ATTN_NORM );
        MESSAGE_BEGIN( MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev );
            WRITE_STRING( STRING(pev->classname) );
        MESSAGE_END();
        pev->effects |= EF_NODRAW;
        SetTouch( NULL );
        SUB_UseTargets( pPlayer, USE_TOGGLE, 0 );
        SetThink( &CMegaHealth::HealthThink );
        pev->nextthink = gpGlobals->time + 6;
        return FALSE;
    }
    return TRUE;
}

void CMegaHealth::HealthThink( void )
{
    auto pPlayer = GetClassPtr( ( CBasePlayer* ) &g_engfuncs.pfnPEntityOfEntIndex( 1 )->v );
    if ( pPlayer->pev->health > pPlayer->pev->max_health )
    {
        pPlayer->pev->health--;
        pev->nextthink = gpGlobals->time + 1;
        return;
    }
}
I need that when I switch from one map to another, the health points continue to go down to 100. If anyone has a clue or whatever, I would really appreciate it.
Hi, abbadon! Thanks for the tip, I never used that brush-based entity (trigger_counter), I always used the point-based entity I think you were referring to (game_counter). I will try the entity you suggest! Thank you for your time in responding. :hecu:
Hey UrbaNebula! Thanks!! :hecu:
A call to the Lords of Coding: :^_^:

I want to create an entity that can count the number of monsters that died on a map (monsters that the player has killed or that have been killed by the environment/another NPC). Its name would be env_counter.

It is not necessary to distinguish which monsters died (monster_headcrab, monster_alien_slave, monster_osprey, etc.). This entity must also be able to count the deaths of monsters that have been generated by the monstermaker entity.

It is, so far, the most ambitious plan that I have proposed in terms of Half-Life programming. :P

I was wondering if you can give me a hand in guiding me on how to create such an entity.

I want it to be an entity that shows a text on the screen indicating the number of dead monsters (as can be achieved achieved by env_message entity). :)
Posted 3 years ago2021-07-05 18:22:37 UTC
in Need help with weapon coding Post #345733
First of all, this code was implemented in the official Half-Life SDK released by Valve.
As a final comment, please excuse me if my code contains unnecessary or redundant lines (I'm not really an expert). I hope someone takes the initiative to even make a wiki page with this humble contribution. :D

First, I added the following lines of code in weapons.h:
// NEW MINIGUN
class CMinigun : public CBasePlayerWeapon
{
public:
    void Spawn( void );
    void Precache( void );
    int iItemSlot( void ) { return 3; }
    int GetItemInfo(ItemInfo *p);
    int AddToPlayer(CBasePlayer *pPlayer);
    BOOL Deploy( void );
    void PrimaryAttack( void );
    void MinigunFire( void );
    void Reload( void );
    void WeaponIdle( void );
    void Holster( int skiplocal = 0 );
    int m_iShell;

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

private:
    unsigned short m_usSpinUpMinigun;
    unsigned short m_usFireMinigun;
};
Then, I created an element called minigun.cpp in hldll. All the code it contains is as follows:
// NEW MINIGUN
#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"

enum minigun_e {
    MINIGUN_IDLE1 = 0,
    MINIGUN_IDLE2,
    MINIGUN_SPINUP,
    MINIGUN_SPINDOWN,
    MINIGUN_FIRE,
    MINIGUN_FIRE_EMPTY,
    MINIGUN_RELOAD,
    MINIGUN_DRAW,
    MINIGUN_HOLSTER
};

LINK_ENTITY_TO_CLASS( weapon_minigun, CMinigun );

void CMinigun::Spawn()
{
    pev->classname = MAKE_STRING("weapon_minigun");
    Precache();
    m_iId = WEAPON_MINIGUN;
    SET_MODEL(ENT(pev), "models/w_minigun.mdl");
    m_iDefaultAmmo = MINIGUN_DEFAULT_GIVE;
    FallInit();
}

void CMinigun::Precache( void )
{
    PRECACHE_MODEL("models/v_minigun.mdl");
    PRECACHE_MODEL("models/w_minigun.mdl");
    PRECACHE_MODEL("models/p_minigun.mdl");
    PRECACHE_SOUND("weapons/minigun_fire.wav");
    PRECACHE_SOUND("weapons/minigun_spinup.wav");
    PRECACHE_SOUND("weapons/minigun_spindown.wav");
    m_usSpinUpMinigun = PRECACHE_EVENT( 1, "events/minigun1.sc" );
    m_usFireMinigun = PRECACHE_EVENT( 1, "events/minigun2.sc" );
    m_iShell = PRECACHE_MODEL("models/shell.mdl");
    PRECACHE_SOUND("weapons/357_cock1.wav");
}

int CMinigun::GetItemInfo(ItemInfo *p)
{
    p->pszName = STRING(pev->classname);
    p->pszAmmo1 = "chaingun";
    p->iMaxAmmo1 = MINIGUN_MAX_CARRY;
    p->pszAmmo2 = NULL;
    p->iMaxAmmo2 = -1;
    p->iMaxClip = MINIGUN_MAX_CLIP;
    p->iSlot = 2;
    p->iPosition = 4;
    p->iFlags = 0;
    p->iId = m_iId = WEAPON_MINIGUN;
    p->iWeight = MINIGUN_WEIGHT;
    return 1;
}

int CMinigun::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 CMinigun::Deploy()
{
    return DefaultDeploy( "models/v_minigun.mdl", "models/p_minigun.mdl", MINIGUN_DRAW, "mp5" );
}

void CMinigun::Holster( int skiplocal /* = 0 */ )
{
    m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
    SendWeaponAnim( MINIGUN_HOLSTER );
    m_fInAttack = 0;
}

void CMinigun::PrimaryAttack( void )
{
    if ( m_iClip <= 0 )
    {
        PlayEmptySound();
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
        return;
    }
    if ( m_fInAttack == 0 )
    {
        PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usSpinUpMinigun, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
        m_flTimeWeaponIdle = m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.6;
        SendWeaponAnim( MINIGUN_SPINUP );
        EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/minigun_spinup.wav", 1, ATTN_NORM);
        m_fInAttack = 1;
        return;
    }
    else if ( m_fInAttack == 1 )
    {
        MinigunFire();
        return;
    }
}

void CMinigun::MinigunFire()
{
    m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
    SendWeaponAnim( MINIGUN_FIRE );
    m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
    m_iClip--;
    UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
    Vector vecShellVelocity = m_pPlayer->pev->velocity + gpGlobals->v_right * RANDOM_FLOAT(50,70) + 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 * 32 + gpGlobals->v_right * 6 , vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL );
    m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
    m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH;
    EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/minigun_fire.wav", 1, ATTN_NORM);
    Vector vecSrc = m_pPlayer->GetGunPosition();
    Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
    Vector vecDir;
#ifdef CLIENT_DLL
    if ( !bIsMultiplayer() )
#else
    if ( !g_pGameRules->IsMultiplayer() )
#endif
    {
        vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MINIGUN, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
    }
    else
    {
        vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MINIGUN, 0, 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_usFireMinigun, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );
    m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;
}

void CMinigun::WeaponIdle( void )
{
    if ( m_flTimeWeaponIdle >= 0.6 )
    {
        if ( m_fInAttack == 1 )
        {
            m_flTimeWeaponIdle = m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.4;
            SendWeaponAnim( MINIGUN_SPINDOWN );
            EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/minigun_spindown.wav", 1, ATTN_NORM);
            m_fInAttack = 0;
            return;
        }
    }
    ResetEmptySound();
    if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
        return;
    int iAnim;
    switch ( RANDOM_LONG( 0, 1 ) )
    {
    case 0:
        iAnim = MINIGUN_IDLE1;
        break;
    default:
    case 1:
        iAnim = MINIGUN_IDLE2;
        break;
    }
    SendWeaponAnim( iAnim );
    m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}

void CMinigun::Reload( void )
{
    if ( m_pPlayer->ammo_9mm <= 0 )
         return;
    DefaultReload( MINIGUN_MAX_CLIP, MINIGUN_RELOAD, 1.5 );
}
Everything previously written would have been useless if I had not written the following in ev_hldm.cpp (hl_cdll):
// NEW MINIGUN
//======================
// MINIGUN START
//======================
enum minigun_e {
    MINIGUN_IDLE1 = 0,
    MINIGUN_IDLE2,
    MINIGUN_SPINUP,
    MINIGUN_SPINDOWN,
    MINIGUN_FIRE,
    MINIGUN_FIRE_EMPTY,
    MINIGUN_RELOAD,
    MINIGUN_DRAW,
    MINIGUN_HOLSTER
};

void EV_SpinUpMinigun( event_args_t *args )
{
    int idx;
    vec3_t origin;
    vec3_t angles;
    vec3_t velocity;

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

    gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/minigun_spinup.wav", 1, ATTN_NORM, 0, PITCH_NORM);

    if ( EV_IsLocal( idx ) )
    {
        gEngfuncs.pEventAPI->EV_WeaponAnimation( MINIGUN_SPINUP, 1 );
    }
}

void EV_FireMinigun( event_args_t *args )
{
    int idx;
    vec3_t origin;
    vec3_t angles;
    vec3_t velocity;
    int empty;

    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 );

    empty = args->bparam1;
    AngleVectors( angles, forward, right, up );

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

    if ( EV_IsLocal( idx ) )
    {
        EV_MuzzleFlash();
        gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? MINIGUN_FIRE_EMPTY : MINIGUN_FIRE, 2 );
        V_PunchAxis( -2, 0 );
    }

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

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

    gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/minigun_fire.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );

    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_MINIGUN, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
    }
    else
    {
        EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MINIGUN, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
    }
}

//======================
// MINIGUN END
//======================
For the other details that I did not comment on here, I suggest reviewing this article written by Penguinboy about weapons programming, I relied entirely on that article to make my new weapon. :hecu:
Posted 3 years ago2021-07-03 23:41:50 UTC
in Need help with weapon coding Post #345727
Forget it, I've already figured it out, haha. I was supposed to create an event for the barrel spinning. And I did it and now it works perfectly!
Posted 3 years ago2021-07-03 22:07:33 UTC
in Need help with weapon coding Post #345726
Hey, Solokiller! I took a look at the code you told me. And, well, based on that code I made my own to create a minigun:
void CMinigun::PrimaryAttack( void )
{
    if ( m_iClip <= 0 )
    {
        PlayEmptySound();
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
        return;
    }
    if ( m_fInAttack == 0 )
    {
        m_flTimeWeaponIdle = m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.6;
        SendWeaponAnim( MINIGUN_SPINUP );
        EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/minigun_spinup.wav", 1, ATTN_NORM);
        m_fInAttack = 1;
        return;
    }
    else if ( m_fInAttack == 1 )
    {
        MinigunFire();
        return;
    }
}

void CMinigun::MinigunFire()
{
    m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
    SendWeaponAnim( MINIGUN_FIRE );
    m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
    m_iClip--;
    UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
    Vector vecShellVelocity = m_pPlayer->pev->velocity + gpGlobals->v_right * RANDOM_FLOAT(50,70) + 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 * 32 + gpGlobals->v_right * 6 , vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL );
    m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
    m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH;
    EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/minigun_fire.wav", 1, ATTN_NORM);
    Vector vecSrc = m_pPlayer->GetGunPosition();
    Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
    Vector vecDir;
#ifdef CLIENT_DLL
    if ( !bIsMultiplayer() )
#else
    if ( !g_pGameRules->IsMultiplayer() )
#endif
    {
        vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MINIGUN, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
    }
    else
    {
        vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MINIGUN, 0, 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_usFireMinigun, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );
    m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15;
}

void CMinigun::WeaponIdle( void )
{
    if ( m_flTimeWeaponIdle > 0.6 )
    {
        if ( m_fInAttack == 1 )
        {
            m_flTimeWeaponIdle = m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.4;
            SendWeaponAnim( MINIGUN_SPINDOWN );
            EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/minigun_spindown.wav", 1, ATTN_NORM);
            m_fInAttack = 0;
            return;
        }
    }
    ResetEmptySound();
    if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
        return;
    int iAnim;
    switch ( RANDOM_LONG( 0, 1 ) )
    {
    case 0:
        iAnim = MINIGUN_IDLE1;
        break;
    default:
    case 1:
        iAnim = MINIGUN_IDLE2;
        break;
    }
    SendWeaponAnim( iAnim );
    m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}
This code that I wrote does not work so well that let's say: there are times when the gun fires without spinning up the barrel.
I wanted to know if you guys could help me improve it. :D
Posted 3 years ago2021-06-27 21:17:58 UTC
in Need help with weapon coding Post #345708
Hello, guys. I wonder if you can help me with this: I want to create a chaingun (minigun) but I'm stuck on the part about making the barrel start spinning, then firing and when I stop firing, the barrel stop spinning. I have the following animations:
enum minigun_e {
    MINIGUN_IDLE1 = 0,
    MINIGUN_IDLE2,
    MINIGUN_SPINUP,
    MINIGUN_SPINDOWN,
    MINIGUN_FIRE,
    MINIGUN_FIRE_EMPTY,
    MINIGUN_RELOAD,
    MINIGUN_DRAW,
    MINIGUN_HOLSTER
};
In other words, I need to display the MINIGUN_SPINUP animation first, then the MINIGUN_FIRE animation (after a few seconds), and finally the MINIGUN_SPINDOWN animation when I stop pressing the right mouse button or I'm out of bullets.

I think that the key must be in the PrimaryAttack method. :hecu:

What follows is everything I have done thus far:
#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"

enum minigun_e {
    MINIGUN_IDLE1 = 0,
    MINIGUN_IDLE2,
    MINIGUN_SPINUP,
    MINIGUN_SPINDOWN,
    MINIGUN_FIRE,
    MINIGUN_FIRE_EMPTY,
    MINIGUN_RELOAD,
    MINIGUN_DRAW,
    MINIGUN_HOLSTER
};

LINK_ENTITY_TO_CLASS( weapon_minigun, CMinigun );

void CMinigun::Spawn()
{
    pev->classname = MAKE_STRING("weapon_minigun");
    Precache();
    m_iId = WEAPON_MINIGUN;
    SET_MODEL(ENT(pev), "models/w_minigun.mdl");
    m_iDefaultAmmo = MINIGUN_DEFAULT_GIVE;
    FallInit();
}

void CMinigun::Precache( void )
{
    PRECACHE_MODEL("models/v_minigun.mdl");
    PRECACHE_MODEL("models/w_minigun.mdl");
    PRECACHE_MODEL("models/p_minigun.mdl");
    PRECACHE_SOUND ("weapons/minigun_fire.wav");
    PRECACHE_SOUND ("weapons/minigun_spinup.wav");
    PRECACHE_SOUND ("weapons/minigun_spindown.wav");
    m_usFireMinigun = PRECACHE_EVENT( 1, "events/minigun.sc" );
    m_iShell = PRECACHE_MODEL("models/shell.mdl");
    PRECACHE_SOUND("weapons/357_cock1.wav");
}

int CMinigun::GetItemInfo(ItemInfo *p)
{
    p->pszName = STRING(pev->classname);
    p->pszAmmo1 = "9mm";
    p->iMaxAmmo1 = _9MM_MAX_CARRY;
    p->pszAmmo2 = NULL;
    p->iMaxAmmo2 = -1;
    p->iMaxClip = MINIGUN_MAX_CLIP;
    p->iSlot = 2;
    p->iPosition = 3;
    p->iFlags = 0;
    p->iId = m_iId = WEAPON_MINIGUN;
    p->iWeight = MINIGUN_WEIGHT;
    return 1;
}

int CMinigun::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 CMinigun::Deploy()
{
    return DefaultDeploy( "models/v_minigun.mdl", "models/p_minigun.mdl", MINIGUN_DRAW, "mp5" );
}
Thanks for your time! :biggrin:
Oh, God. It worked! Thanks a lot, Solokiller!
Hello! I was wondering how to make UTIL_ScreenFade last longer than 16 seconds (by default, that is the maximum duration of this UTIL).
I mean, is it possible to edit the code of UTIL_ScreenFade so that the duration of the screen fade effect lasts longer than 16 seconds?
In my case, I want it to last 30 seconds, no more:
UTIL_ScreenFade( pPlayer, Vector(255,0,0), 1, 30, 128, FFADE_IN ); // float fadeHold only lasts 16 s
I have searched for a tutorial and didn't really find anything. :(
Thanks in advance.
Posted 3 years ago2021-06-06 00:27:12 UTC
in Coding issue: the monstermaker entity Post #345679
Hey, Solokiller. Many thanks! That was very helpful.
Posted 3 years ago2021-06-05 14:10:26 UTC
in Coding issue: the monstermaker entity Post #345677
Hey there! I'm back with a new programming issue: the monstermaker entity edit.

Basically I would like to include these effects from this article about Alien Teleport Effect (HL1) in the code of monstermaker.cpp.

That is, I plan to include the following entities in one:
2 env_sprite's
2 ambient_generic's
1 light
1 env_beam

I'll show you what I've done so far. I have successfully included two sprites!
//=========================================================
// MakeMonster - this is the code that drops the monster
//=========================================================
void CMonsterMaker::MakeMonster( void )
{

// (...) original code

if (FBitSet(pev->spawnflags, SF_MONSTERMAKER_NEW_EFFECTS)) // NEW
    {
        // first sprite
        CSprite *pSprite1 = CSprite::SpriteCreate( "sprites/fexplo1.spr", pev->origin, TRUE );
        pSprite1->SetTransparency( kRenderTransAdd, 77, 210, 130, 255, kRenderFxNoDissipation ); // rendermode, rendercolor (r, g, b), renderamt, renderfx
        pSprite1->SetScale( 1.0 );
        pSprite1->pev->framerate = 10.0;
        pSprite1->TurnOn(); // idk
        pSprite1->AnimateAndDie( 10 );
        // second sprite
        CSprite *pSprite2 = CSprite::SpriteCreate( "sprites/xflare1.spr", pev->origin, TRUE );
        pSprite2->SetTransparency( kRenderTransAdd, 184, 250, 214, 255, kRenderFxNoDissipation ); // rendermode, rendercolor (r, g, b), renderamt, renderfx
        pSprite2->SetScale( 1.0 );
        pSprite2->pev->framerate = 10.0;
        pSprite2->TurnOn(); // idk
        pSprite2->AnimateAndDie( 10 );
    }
}
So far, what I did was set a condition: If the SF_MONSTERMAKER_NEW_EFFECTS flag is on, every time a monster spawns it will produce the effect I want to create.

By the way, here is the flag's identification number:
// Monstermaker spawnflags
#define SF_MONSTERMAKER_START_ON 1 // start active ( if has targetname )
#define SF_MONSTERMAKER_CYCLIC 4 // drop one monster every time fired.
#define SF_MONSTERMAKER_MONSTERCLIP 8 // Children are blocked by monsterclip
#define SF_MONSTERMAKER_NEW_EFFECTS 16 // NEW
And the precached sprites:
void CMonsterMaker :: Precache( void )
{
    CBaseMonster::Precache();

    UTIL_PrecacheOther( STRING( m_iszMonsterClassname ) );
    PRECACHE_MODEL("sprites/fexplo1.spr"); // NEW
    PRECACHE_MODEL("sprites/xflare1.spr"); // NEW
}
But I don't know how to include an env_beam that has the following:
Brightness: 150
Beam color: 197 243 169
Life: .5
Width: 1.8
Noise: 35
Sprite model: "sprites/lgtning.spr"
Strike again time: -.5
Random strike
End sparks

Please, can you help me? :biggrin:
Posted 3 years ago2021-04-08 01:14:57 UTC
in Help me, Lords of coding!! Post #345518
Thanks, Captain P. I see that it's more complicated than what I thought :confused:
Posted 3 years ago2021-04-07 00:41:40 UTC
in Help me, Lords of coding!! Post #345516
Merci, Shepard62700FR! And of course, thanks to Dr. Orange and Bruce for their contributions too.
I think I did well what Shepard62700FR told me.
I mean, first I have removed BOOL m_fDamageDoubler from CBasePlayer class declaration (player.h). Right there I have written:
float m_flDoubleDamageBonusTime;

bool HasDoubleDamageBonus()
{
    return gpGlobals->time < m_flDoubleDamageBonusTime;
}
In CBasePlayer::Spawn (player.cpp) I have added:
m_flDoubleDamageBonusTime = gpGlobals->time + 15.0f;
And in TYPEDESCRIPTION (player.cpp) I have added too:
DEFINE_FIELD( CBasePlayer, m_flDoubleDamageBonusTime, FIELD_TIME ),
And finally the code of my item was like this (items.cpp):
class CDamageDoubler : public CItem
{
    void CDamageDoubler :: Spawn( void )
    {
        Precache();
        SET_MODEL(ENT(pev), "models/w_rad.mdl");
        CItem::Spawn();
    }

    void CDamageDoubler :: Precache( void )
    {
        PRECACHE_MODEL("models/w_rad.mdl");
        PRECACHE_SOUND("scientist/sci_pain3.wav"); // stahp sound
    }

    BOOL CDamageDoubler :: MyTouch( CBasePlayer *pPlayer )
    {
        if ( ( pPlayer->pev->weapons & (1<<WEAPON_SUIT) ) ) // The player can take this item only if he is wearing the HEV suit
        {
            ALERT( at_console, "You have picked up the damage doubler\n" ); // Display a message on the console.
            EMIT_SOUND(ENT(pPlayer->pev), CHAN_ITEM, "scientist/sci_pain3.wav", 1, ATTN_NORM); // play the stahp sound
            pPlayer->HasDoubleDamageBonus(); // New line
            return TRUE;
        }
        return FALSE;
    }
};

LINK_ENTITY_TO_CLASS( item_damage_doubler, CDamageDoubler );
But I do not know exactly how to double the damage of both weapons that use FireBulletsPlayer and those that do not use this function. If you can give me a concrete example, it would be very helpful. :)
Posted 3 years ago2021-04-05 18:18:43 UTC
in Help me, Lords of coding!! Post #345510
Hello Dr. Orange! What you say sounds logical. But how would I make that effect last only 15 seconds? That question surpasses my rudimentary knowledge of programming in Half-Life :(
Posted 3 years ago2021-04-04 22:41:22 UTC
in Help me, Lords of coding!! Post #345507
Hello there. I'm back with a new issue.
I want to create an item that doubles all the damage done by the player, but I don't know how to achieve that.
As far as I know, there is nothing in the Half-Life source code that looks like the item I want to create, so that's why I'm asking for your help.

The concept is simple but at the same time complicated: Once you pick up the item, for 15 seconds all the damage you do with your weapons will be double. After 15 seconds, the item will be removed from your inventory, and the effect will end. Now you can pick up another item of these.

Oh, Lords of Coding, I invoke you!

I have only written the basic structure of my item, at the bottom of items.cpp:
// An item that doubles all the damage done.
class CDamageDoubler : public CItem
{
    void CDamageDoubler :: Spawn( void )
    {
        Precache();
        SET_MODEL(ENT(pev), "models/w_rad.mdl");
        CItem::Spawn();
    }

    void CDamageDoubler :: Precache( void )
    {
        PRECACHE_MODEL("models/w_rad.mdl");
        PRECACHE_SOUND("scientist/sci_pain3.wav"); // stahp sound
    }

    BOOL CDamageDoubler :: MyTouch( CBasePlayer *pPlayer )
    {
        if ( pPlayer->m_fDamageDoubler ) // If the player owns this item, then he cannot take another.
        {
            return FALSE;
        }

        if ( ( pPlayer->pev->weapons & (1<<WEAPON_SUIT) ) ) // The player can take this item only if he is wearing the HEV suit
        {
            ALERT( at_console, "You have picked up the damage doubler\n" ); // Display a message on the console.
            EMIT_SOUND(ENT(pPlayer->pev), CHAN_ITEM, "scientist/sci_pain3.wav", 1, ATTN_NORM); // play the stahp sound
            pPlayer->m_fDamageDoubler = TRUE;
            return TRUE;
        }
        return FALSE;
    }
};

LINK_ENTITY_TO_CLASS( item_damage_doubler, CDamageDoubler );
m_fDamageDoubler is declared somewhere in player.h:
BOOL m_fDamageDoubler; // For my item that doubles the damage done
Thanks in advance!!!
Posted 3 years ago2021-02-12 20:15:52 UTC
in Lords of Coding, I need help!!11!!one Post #345340
Oh, I feel stupid :lol: Thank you, Solokiller. It works! My problem is solved! You're one of those Lords of coding!
Valve, we got a lord of coding here!Valve, we got a lord of coding here!
Posted 3 years ago2021-02-12 15:34:11 UTC
in Lords of Coding, I need help!!11!!one Post #345338
Hello Solokiller. Thanks for answering. When I replace WRITE_SHORT( entindex() ); with WRITE_SHORT(entindex() + (attachmentIndex << 12)); it says identifier "attachmentIndex" is undefined. And it fails to compile. :cry:
Posted 3 years ago2021-02-12 02:01:32 UTC
in Lords of Coding, I need help!!11!!one Post #345334
Hello hermanJnr, thank for your response! I still can't find a solution for my problem :(
Posted 3 years ago2021-02-11 19:10:03 UTC
in Lords of Coding, I need help!!11!!one Post #345332
Hey, Lord of coding, I know your knowledge of Half-Life programming is vastly superior to mine. For dat reason, I ask for your help! :D

I want the beam that I have created (simulating the orange beam of the tau cannon) to come out from an $attachment that I defined from the QC file of my model, and not from the model's origin, as you can see in the image that I attach here:
This is the problem!This is the problem!
This is the bunch of code I wrote so far:
void CHEVScientistGauss :: HandleAnimEvent( MonsterEvent_t *pEvent )
(...)
case HEVGAUSS_AE_SHOOT_GAUSS:
{
    if (m_hEnemy != NULL)
    {
        TraceResult tr;
        Vector vecSrc, vecAngles;
        vecAngles = ShootAtEnemy( vecSrc );
        UTIL_TraceLine( vecSrc, vecSrc + vecAngles * 1024, dont_ignore_monsters, ENT( pev ), &tr);
        CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
        if (pEntity != NULL && pEntity->pev->takedamage)
        {
            ClearMultiDamage();
            pEntity->TraceAttack( pev, gSkillData.hevscientistGaussDmg, pev->velocity, &tr, DMG_SHOCK );
            ApplyMultiDamage( pev, pev );
        }
        MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
            WRITE_BYTE( TE_BEAMENTPOINT );
            WRITE_SHORT( entindex() );
            WRITE_COORD( tr.vecEndPos.x );
            WRITE_COORD( tr.vecEndPos.y );
            WRITE_COORD( tr.vecEndPos.z );
            WRITE_SHORT( m_iBeam );
            WRITE_BYTE( 0 );
            WRITE_BYTE( 0 );
            WRITE_BYTE( 1 );
            WRITE_BYTE( 10 );
            WRITE_BYTE( 0 );
            WRITE_BYTE( 255 );
            WRITE_BYTE( 128 );
            WRITE_BYTE( 0 );
            WRITE_BYTE( 128 );
            WRITE_BYTE( 0 );
        MESSAGE_END();
        EMIT_SOUND( ENT(pev), CHAN_WEAPON, "weapons/gauss2.wav", 1, ATTN_NORM );
    }
}
break;
Thanks guys for your time. :glad:
Posted 3 years ago2020-11-21 23:34:33 UTC
in Need help with Activities and NPC coding Post #344919
I just tested your method. It compiled correctly, but for some reason I don't know the NPC animations are bugged. The NPC stay freeze.
Anyway, I really appreciate your help, guys. But I think it would be better if I create the NPC with all weapons separately. :confused:
Posted 4 years ago2020-11-20 18:21:24 UTC
in Need help with Activities and NPC coding Post #344909
Hello Captain P, thanks for your correction. :D
I just deleted that part (iSequence = LookupActivity ( NewActivity );), but unfortunately my NPC still plays all the idle animations :(
I'm starting to think it's more complicated than I thought...
Posted 4 years ago2020-11-20 13:28:16 UTC
in Need help with Activities and NPC coding Post #344906
Yep, I just did what you said. And here's the bunch of code I wrote:
case ACT_IDLE:
if (FBitSet(pev->weapons, HEVSCI_GLOCK)) // 9mm handgun hevscientist
{
    if ( m_fStanding )
    {
        iSequence = LookupSequence( "ref_aim_onehanded" );
    }
    else
    {
        iSequence = LookupSequence( "crouch_aim_onehanded" );
    }
}
else if (FBitSet(pev->weapons, HEVSCI_PYTHON)) // .357 Magnum hevscientist
{
    if ( m_fStanding )
    {
        iSequence = LookupSequence( "ref_aim_python" );
    }
    else
    {
        iSequence = LookupSequence( "crouch_aim_python" );
    }
}
else if (FBitSet(pev->weapons, HEVSCI_SHOTGUN)) // Shotgun hevscientist
{
    if ( m_fStanding )
    {
        iSequence = LookupSequence( "ref_aim_shotgun" );
    }
    else
    {
        iSequence = LookupSequence( "crouch_aim_shotgun" );
    }
}
else if (FBitSet(pev->weapons, HEVSCI_MP5)) // MP5 hevscientist
{
    if ( m_fStanding )
    {
        iSequence = LookupSequence( "ref_aim_mp5" );
    }
    else
    {
        iSequence = LookupSequence( "crouch_aim_mp5" );
    }
}
else if (FBitSet(pev->weapons, HEVSCI_CROSSBOW)) // Crossbow hevscientist
{
    if ( m_fStanding )
    {
        iSequence = LookupSequence( "ref_aim_bow" );
    }
    else
    {
        iSequence = LookupSequence( "crouch_aim_bow" );
    }
}
else if (FBitSet(pev->weapons, HEVSCI_RPG)) // RPG hevscientist
{
    if ( m_fStanding )
    {
        iSequence = LookupSequence( "ref_aim_rpg" );
    }
    else
    {
        iSequence = LookupSequence( "crouch_aim_rpg" );
    }
}
else if (FBitSet(pev->weapons, HEVSCI_GAUSS)) // Gauss hevscientist
{
    if ( m_fStanding )
    {
        iSequence = LookupSequence( "ref_aim_gauss" );
    }
    else
    {
        iSequence = LookupSequence( "crouch_aim_gauss" );
    }
}
iSequence = LookupActivity ( NewActivity );
break;
And my NPC still plays all the idling sequences without select one specifically. But I guess this is the way! And it seem that something's still missing...
Posted 4 years ago2020-11-20 01:31:36 UTC
in Need help with Activities and NPC coding Post #344897
Hey Shepard. I tried that method from hgrunt.cpp, but my NPC still plays all idling animations :(
In the QC file, I assigned to every idling sequence (glock, magnum, shotgun, etc.) the ACT_IDLE tag. Is that right?
Posted 4 years ago2020-11-19 12:25:06 UTC
in Need help with Activities and NPC coding Post #344889
Hello people. Will you believe me if I tell you that I've been trying for months the following coding issue with no satisfactory results? Yes, it took me several months of headaches, and I'm getting sad :(
So for dat reason I'm appealing to TWHL, specifically to Half-Life's Lords of Coding. :D

I'm trying out a new NPC that consists in hevscientist with multiple faces and weapons to choose (yeah, like those ones saw in Sweet Half-Life).
I want to assign a specific idling animation to every weapon the model has. For example, if the model has a RPG, the idling animation will be those that hold up an RPG. If the model has a crowbar, the idling animation will be the one that carry a crowbar, and so on.

The challenge, I guess, is make the NPC choose a certain animation when it has a given weapon. Note that if all idling sequences has ACT_IDLE attached to them, the NPC plays all idling animations without distinction.

But I can't get what I'm looking for. Is there something I gotta do in the code?
Thanks in advance, and have a nice day :cool:
Thanks Shepard! :cool:
Hello everyone! I'm making a NPC that can shoot the following weapons: Glock, Python (357. Magnum), Shotgun, MP5, Crossbow, RPG, Gauss and Egon!
Hard work I've chosen. I wrote up the code for Glock, Python, Shotgun and MP5. They basically are a slightly modified copy of a hgrunt.cpp's bunch of code. I'll show up as an example my Python's method:

//=========================================================
// PythonShoot
//=========================================================
void CMyNewNPC :: PythonShoot ( void )
{
Vector vecShootOrigin = GetGunPosition();
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );

UTIL_MakeVectors ( pev->angles );

Vector vecShellVelocity = gpGlobals->v_right * RANDOM_FLOAT(40,90) + gpGlobals->v_up * RANDOM_FLOAT(75,200) + gpGlobals->v_forward * RANDOM_FLOAT(-40, 40);
EjectBrass ( vecShootOrigin - vecShootDir * -24, vecShellVelocity, pev->angles.y, m_iBrassShell, TE_BOUNCE_SHELL);
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_357 );

pev->effects |= EF_MUZZLEFLASH;

m_cAmmoLoaded--;

Vector angDir = UTIL_VecToAngles( vecShootDir );
SetBlending( 0, angDir.x );
}

I wonder if you have the bunch of code for RPG, Crossbow, Gauss and Egon shoots! Due to I couldn't find them out through the Half-Life SDK yet. Or at least if you know where I can find them, please tell me! I suspect they are a little bit more complicated than the others I made! (I think they use different sprites, more sounds and models, beams...).

Thanks in advance,
Alexis.
I just couldn't get it. :\
Hello guys. Well I'm sorry if I sound kinda annoying, but you helped me some time ago. I'm very thankful with you. Now, I'm wondering again if you can help me one more time.
I can't figure out how to get NPCs show up their health points and name in vanilla Half-Life, just like they do in Sven Co-op. I wonder if you guys know how to do it... I think I'm gonna have to edit cl_dll, but certainly Idk.
Thanks in advance,
Alexis.
Posted 4 years ago2020-05-30 00:35:23 UTC
in Need help with player.mdl Post #344325
Thank you guys for your responses. I tried what abbadon said and it worked (about changing model's origin on QC file).
You're the best!
Problem solved!Problem solved!
Posted 4 years ago2020-05-28 04:34:49 UTC
in Need help with player.mdl Post #344313
Hello guys. I need your help again: When I'm implementing player.mdl (through monster_generic entity) into my map, it gets its lower half of the body under the floor, as you can see in the picture below:
player.mdl getting its lower half of the body under the floorplayer.mdl getting its lower half of the body under the floor
If you know how to fix that issue, you'd have helped me a lot. Because I coudn't fix it yet!
Alexis.
Posted 4 years ago2020-05-23 07:11:07 UTC
in Security guards reloading their gun Post #344282
I did it and it worked successfully. Thank you!
Posted 4 years ago2020-05-22 01:49:05 UTC
in Security guards reloading their gun Post #344266
Hello folks. I wonder if you know how to get, through programming, security guards (monster_barney) reloading their gun after firing 17 shots. I'm now using Visual Studio 2019 and Solokiller's updated Half-Life SDK that works with VS2019. I think it's possible since barney.mdl contains an animation doing so. But I couldn't find the bunch of code that allow security guards reload their gun :cry: . So, I need your help again!
Thanks in advance,
Alexis.
Posted 4 years ago2020-05-21 18:04:42 UTC
in About adding randomness to HL Post #344261
Thank you guys for answering. Solokiller's method worked perfectly! I've tested myself.
This thread is solved.
I'm in debt to you!
Alexis.
Posted 4 years ago2020-05-20 19:04:20 UTC
in About adding randomness to HL Post #344252
Hey there. I'm seeking out the way to add randomness to HL for triggering events. I wanna do it through editing its source code (using Microsoft Visual Studio 2010 and official Valve's Half-Life 1 SDK from GitHub). But I coudn't figure out how to do it :cry: . So, I'm wondering if you guys know how to do it. I was thinking about creating a new entity, like trigger_random or so.

I would appreciate your help of course. Greetings from Argentina!
Alexis.