Selectively Changing Barney's Damage Values - What's Wrong Here? Created 3 years ago2021-01-14 22:40:19 UTC by hermanJnr. hermanJnr.

Created 3 years ago2021-01-14 22:40:19 UTC by hermanJnr. hermanJnr.

Posted 3 years ago2021-01-14 22:40:19 UTC Post #345227
TLDR: Trying to get two Barney variants with two ammo variants. Ammo variant works, but I can't get the second Barney to use it.

Hey guys, just had a C++ question for the code wizards on here! It's a bit of a long one explaining my issue, but I thought I'd list everything I've tried to make the problem more obvious :)

I'm rather helpless with programming myself but I've been attempting to create a custom variant of Barney that allows for him to use a more powerful bullet in his Glock. At the same time, I want to preserve the "normal" Barney who just uses his 9mm.

The steps I've done are as follows -
  • Added a new type of ammunition called MONSTER_BULLET_BARNSPECIAL. This works fine, and is the equivalent of the player's magnum 357 in damage. No issues here - if I just simply replace it instead of Barney's 9mm ammo (MONSTER_BULLET_9MM) in the .cpp, he tears stuff up.
  • Added a new Barney monster type called "Watson". It's based off CBarney in the .cpp. I did this as per the tutorial on this site (for adding the Hazmat/Cleansuit scientist in addition to normal Scientists as a separate "monster_cleansuitscientist"). This also works fine, and I can add Watson as a separate NPC in my HL levels now (after adding it to .FGD obviously).
All good so far!
  • I then tried to replace the default "BarneyFirePistol" settings with my own unique ones for the Watson variant, to give two different attacks, one for each Barney.
Unfortunately, this doesn't want to work. As far as I know, specifying void BarneyFirePistol (void); should allow the code to use the next entry of BarneyFirePistol in lieu of the original one?

This is what happens for the "Spawn" settings in the tutorial, and I was also able to use the same technique to make select HECU grunts friendly to the player in another edit.

The code I've got is as follows:
//
//Watson Unique Damage Settings
//

class CWatson : public CBarney
{
public:
    void BarneyFirePistol(void);
};

LINK_ENTITY_TO_CLASS (monster_watson, CWatson);

void CWatson::BarneyFirePistol(void)
{
    Vector vecShootOrigin;

    UTIL_MakeVectors(pev->angles);
    vecShootOrigin = pev->origin + Vector(0, 0, 55);
    Vector vecShootDir = ShootAtEnemy(vecShootOrigin);

    Vector angDir = UTIL_VecToAngles(vecShootDir);
    SetBlending(0, angDir.x);
    pev->effects = EF_MUZZLEFLASH;

    FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_BARNSPECIAL);

    int pitchShift = RANDOM_LONG(0, -20);

    // Only shift about half the time
    if (pitchShift > -10)
        pitchShift = -20;
    else
        pitchShift -= -15;
    EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "barney/ba_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift);

    CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 384, 0.3);

    // UNDONE: Reload?
    m_cAmmoLoaded--;// take away a bullet!
}
For some reason it seems the problem is that the code is defaulting to using the default "BarneyFirePistol". I've even tried renaming the new attack entry "WatsonFirePistol" or something along those lines, but it makes no difference.

Am I just being code illiterate? I think the edits I've made would make most coders cry to be fair haha.

Anyone who can offer help will of course be getting a note in the credits if and when I finish this mod ;)
Thank you everyone.
Posted 3 years ago2021-01-14 23:05:18 UTC Post #345229
To make this work as intended, CBarney::BarneyFirePistol must be a virtual function. So in barney.cpp, change the following line:
void BarneyFirePistol( void );
to:
virtual void BarneyFirePistol( void );
Without that, the code in CBarney will always call CBarney::BarneyFirePistol, instead of <type-of-current-object>::BarneyFirePistol.
Posted 3 years ago2021-01-15 10:06:39 UTC Post #345233
Captain, you are an absolute legend as ever ;) Thank you mate.
This fixed the problem immediately.

Not gonna lie, this had me scratching my head for 2 hours last night so I really appreciate the help. Have tons to learn when it comes to this stuff haha :)
Posted 3 years ago2021-01-15 13:23:42 UTC Post #345234
You might wanna also do this, for convenience:
class CWatson : public CBarney
{
public:
    void BarneyFirePistol() override;
};
The override part lets the programmer be 100% sure that it's overriding something. It will cause errors if the method you're overriding isn't virtual, which wouldn't happen otherwise.
class MyClass
{
public:
    void MyMethod();
};

class MySecondClass
{
public:
    void MyMethod() override; // ERROR because MyClass::MyMethod isn't virtual
};
It's useful in situations like these, and in general to keep track of what overrides what.
Admer456 Admer456If it ain't broken, don't fox it!
Posted 3 years ago2021-01-16 11:15:40 UTC Post #345236
Thank you Admer, I will add that too. Got to get into good habits after all!
You must be logged in to post a response.